@real-router/react 0.12.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,10 +17,10 @@ npm install @real-router/react @real-router/core @real-router/browser-plugin
17
17
 
18
18
  ## Entry Points
19
19
 
20
- | Import Path | React Version | Includes |
21
- |-------------|---------------|----------|
22
- | `@real-router/react` | 19.2+ | Full API (hooks, `Link`, `RouteView` with `keepAlive`) |
23
- | `@real-router/react/legacy` | 18+ | All hooks and `Link`, no `RouteView` |
20
+ | Import Path | React Version | Includes |
21
+ | --------------------------- | ------------- | ------------------------------------------------------ |
22
+ | `@real-router/react` | 19.2+ | Full API (hooks, `Link`, `RouteView` with `keepAlive`) |
23
+ | `@real-router/react/legacy` | 18+ | All hooks and `Link`, no `RouteView` |
24
24
 
25
25
  Both share the same underlying code — `/legacy` excludes components that require React 19.2's `<Activity>` API.
26
26
 
@@ -33,9 +33,11 @@ import { RouterProvider, RouteView, Link } from "@real-router/react";
33
33
 
34
34
  const router = createRouter([
35
35
  { name: "home", path: "/" },
36
- { name: "users", path: "/users", children: [
37
- { name: "profile", path: "/:id" },
38
- ]},
36
+ {
37
+ name: "users",
38
+ path: "/users",
39
+ children: [{ name: "profile", path: "/:id" }],
40
+ },
39
41
  ]);
40
42
 
41
43
  router.usePlugin(browserPluginFactory());
@@ -49,9 +51,15 @@ function App() {
49
51
  <Link routeName="users">Users</Link>
50
52
  </nav>
51
53
  <RouteView nodeName="">
52
- <RouteView.Match routeName="home"><HomePage /></RouteView.Match>
53
- <RouteView.Match routeName="users"><UsersPage /></RouteView.Match>
54
- <RouteView.NotFound><NotFoundPage /></RouteView.NotFound>
54
+ <RouteView.Match routeName="home">
55
+ <HomePage />
56
+ </RouteView.Match>
57
+ <RouteView.Match routeName="users">
58
+ <UsersPage />
59
+ </RouteView.Match>
60
+ <RouteView.NotFound>
61
+ <NotFoundPage />
62
+ </RouteView.NotFound>
55
63
  </RouteView>
56
64
  </RouterProvider>
57
65
  );
@@ -60,14 +68,14 @@ function App() {
60
68
 
61
69
  ## Hooks
62
70
 
63
- | Hook | Returns | Re-renders |
64
- |------|---------|------------|
65
- | `useRouter()` | `Router` | Never |
66
- | `useNavigator()` | `Navigator` | Never (stable ref, safe to destructure) |
67
- | `useRoute()` | `{ router, route, previousRoute }` | Every navigation |
68
- | `useRouteNode(name)` | `{ router, route, previousRoute }` | Only when node activates/deactivates |
69
- | `useRouteUtils()` | `RouteUtils` | Never |
70
- | `useRouterTransition()` | `{ isTransitioning, toRoute, fromRoute }` | On transition start/end |
71
+ | Hook | Returns | Re-renders |
72
+ | ----------------------- | ----------------------------------------- | --------------------------------------- |
73
+ | `useRouter()` | `Router` | Never |
74
+ | `useNavigator()` | `Navigator` | Never (stable ref, safe to destructure) |
75
+ | `useRoute()` | `{ router, route, previousRoute }` | Every navigation |
76
+ | `useRouteNode(name)` | `{ router, route, previousRoute }` | Only when node activates/deactivates |
77
+ | `useRouteUtils()` | `RouteUtils` | Never |
78
+ | `useRouterTransition()` | `{ isTransitioning, toRoute, fromRoute }` | On transition start/end |
71
79
 
72
80
  ```tsx
73
81
  // useRouteNode — re-renders only when "users.*" changes
@@ -76,9 +84,12 @@ function UsersLayout() {
76
84
  if (!route) return null;
77
85
 
78
86
  switch (route.name) {
79
- case "users": return <UsersList />;
80
- case "users.profile": return <UserProfile id={route.params.id} />;
81
- default: return null;
87
+ case "users":
88
+ return <UsersList />;
89
+ case "users.profile":
90
+ return <UserProfile id={route.params.id} />;
91
+ default:
92
+ return null;
82
93
  }
83
94
  }
84
95
 
@@ -106,9 +117,9 @@ Navigation link with automatic active state detection. Re-renders only when its
106
117
  <Link
107
118
  routeName="users.profile"
108
119
  routeParams={{ id: "123" }}
109
- activeClassName="active" // default: "active"
110
- activeStrict={false} // default: false (ancestor match)
111
- ignoreQueryParams={true} // default: true
120
+ activeClassName="active" // default: "active"
121
+ activeStrict={false} // default: false (ancestor match)
122
+ ignoreQueryParams={true} // default: true
112
123
  routeOptions={{ replace: true }}
113
124
  >
114
125
  View Profile
@@ -133,6 +144,32 @@ Declarative route matching with optional `keepAlive` — preserves component sta
133
144
  </RouteView>
134
145
  ```
135
146
 
147
+ #### `RouteView.Match` props
148
+
149
+ | Prop | Type | Description |
150
+ | ----------- | ----------- | --------------------------------------------------------------------------- |
151
+ | `segment` | `string` | Route segment to match |
152
+ | `keepAlive` | `boolean` | Preserve state via React `<Activity>` (React 19.2+) |
153
+ | `fallback` | `ReactNode` | Shown while children suspend. Wraps children in `<Suspense>` when provided. |
154
+
155
+ #### Lazy loading with `fallback`
156
+
157
+ Pass `fallback` to code-split a route component. `RouteView.Match` wraps children in `<Suspense>` automatically:
158
+
159
+ ```tsx
160
+ import { lazy } from "react";
161
+
162
+ const LazyDashboard = lazy(() => import("./Dashboard"));
163
+
164
+ <RouteView nodeName="">
165
+ <RouteView.Match segment="dashboard" fallback={<Spinner />}>
166
+ <LazyDashboard />
167
+ </RouteView.Match>
168
+ </RouteView>;
169
+ ```
170
+
171
+ `fallback` and `keepAlive` work together — `<Activity>` wraps the whole match including the `<Suspense>` boundary.
172
+
136
173
  ## React 18 Migration
137
174
 
138
175
  One import path change — all hooks and `Link` work identically:
@@ -146,14 +183,26 @@ One import path change — all hooks and `Link` work identically:
146
183
 
147
184
  ## Migration from react-router5
148
185
 
149
- | API | react-router5 | @real-router/react |
150
- |-----|---------------|-------------------|
151
- | `RouterProvider`, `Link` | Yes | Yes |
152
- | `useRouter`, `useRoute`, `useRouteNode` | Yes | Yes |
153
- | `RouteView` with `keepAlive` | No | Yes (React 19.2+) |
154
- | `useNavigator`, `useRouteUtils`, `useRouterTransition` | No | Yes |
155
- | `withRouter`, `withRoute`, `routeNode` (HOCs) | Yes | No — use hooks |
156
- | `Router`, `Route`, `RouteNode` (render props) | Yes | No — use hooks |
186
+ | API | react-router5 | @real-router/react |
187
+ | ------------------------------------------------------ | ------------- | ------------------ |
188
+ | `RouterProvider`, `Link` | Yes | Yes |
189
+ | `useRouter`, `useRoute`, `useRouteNode` | Yes | Yes |
190
+ | `RouteView` with `keepAlive` | No | Yes (React 19.2+) |
191
+ | `useNavigator`, `useRouteUtils`, `useRouterTransition` | No | Yes |
192
+ | `withRouter`, `withRoute`, `routeNode` (HOCs) | Yes | No — use hooks |
193
+ | `Router`, `Route`, `RouteNode` (render props) | Yes | No — use hooks |
194
+
195
+ ## Accessibility
196
+
197
+ Enable screen reader announcements for route changes:
198
+
199
+ ```tsx
200
+ <RouterProvider router={router} announceNavigation>
201
+ {/* Your app */}
202
+ </RouterProvider>
203
+ ```
204
+
205
+ When enabled, a visually hidden `aria-live` region announces each navigation. Focus moves to the first `<h1>` on the new page. See [Accessibility guide](https://github.com/greydragon888/real-router/wiki/Accessibility) for details.
157
206
 
158
207
  ## Documentation
159
208
 
@@ -164,12 +213,12 @@ Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
164
213
 
165
214
  ## Related Packages
166
215
 
167
- | Package | Description |
168
- |---------|-------------|
169
- | [@real-router/core](https://www.npmjs.com/package/@real-router/core) | Core router (required dependency) |
170
- | [@real-router/browser-plugin](https://www.npmjs.com/package/@real-router/browser-plugin) | Browser History API integration |
171
- | [@real-router/sources](https://www.npmjs.com/package/@real-router/sources) | Subscription layer (used internally) |
172
- | [@real-router/route-utils](https://www.npmjs.com/package/@real-router/route-utils) | Route tree queries (`useRouteUtils`) |
216
+ | Package | Description |
217
+ | ---------------------------------------------------------------------------------------- | ------------------------------------ |
218
+ | [@real-router/core](https://www.npmjs.com/package/@real-router/core) | Core router (required dependency) |
219
+ | [@real-router/browser-plugin](https://www.npmjs.com/package/@real-router/browser-plugin) | Browser History API integration |
220
+ | [@real-router/sources](https://www.npmjs.com/package/@real-router/sources) | Subscription layer (used internally) |
221
+ | [@real-router/route-utils](https://www.npmjs.com/package/@real-router/route-utils) | Route tree queries (`useRouteUtils`) |
173
222
 
174
223
  ## Contributing
175
224
 
@@ -17,6 +17,8 @@ interface MatchProps {
17
17
  readonly exact?: boolean;
18
18
  /** Preserve component state when deactivated (React Activity). Defaults to false. */
19
19
  readonly keepAlive?: boolean;
20
+ /** Fallback content to show while children are suspended. */
21
+ readonly fallback?: ReactNode;
20
22
  /** Content to render when matched. */
21
23
  readonly children: ReactNode;
22
24
  }
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- var e=require("react"),t=require("@real-router/core"),r=require("@real-router/route-utils"),o=require("react/jsx-runtime"),n=require("@real-router/sources"),u=require("@real-router/core/api");function s(e){return null}function i(e){return null}function a(e,t,o){return o?e===t:r.startsWithSegment(e,t)}function c(t,r){for(const o of e.Children.toArray(t))e.isValidElement(o)&&(o.type===s||o.type===i?r.push(o):c(o.props.children,r))}function l(t,r,n,u){return n?o.jsx(e.Activity,{mode:u,children:t},r):o.jsx(e.Fragment,{children:t},r)}s.displayName="RouteView.Match",i.displayName="RouteView.NotFound";var d=e.createContext(null),p=e.createContext(null),m=e.createContext(null),h=()=>{const t=e.useContext(p);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function g(r){const o=h(),u=e.useMemo(()=>n.createRouteNodeSource(o,r),[o,r]),{route:s,previousRoute:i}=e.useSyncExternalStore(u.subscribe,u.getSnapshot,u.getSnapshot),a=e.useMemo(()=>t.getNavigator(o),[o]);return e.useMemo(()=>({navigator:a,route:s,previousRoute:i}),[a,s,i])}function v({nodeName:r,children:n}){const{route:u}=g(r),s=e.useRef(new Set);if(!u)return null;const d=[];c(n,d);const{rendered:p}=function(r,n,u,s){let c=null,d=!1;const p=[];for(const e of r){if(e.type===i){c=e.props.children;continue}const{segment:t,exact:r=!1,keepAlive:o=!1}=e.props,m=u?`${u}.${t}`:t;!d&&a(n,m,r)?(d=!0,s.add(m),p.push(l(e.props.children,m,o,"visible"))):o&&s.has(m)&&p.push(l(e.props.children,m,o,"hidden"))}return d||n!==t.UNKNOWN_ROUTE||null===c||p.push(o.jsx(e.Fragment,{children:c},"__route-view-not-found__")),{rendered:p,activeMatchFound:d}}(d,u.name,r,s.current);return p.length>0?o.jsx(o.Fragment,{children:p}):null}v.displayName="RouteView";var f=Object.assign(v,{Match:s,NotFound:i}),N=Object.freeze({}),S=Object.freeze({});function x(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}var y=e.memo(({routeName:t,routeParams:r=N,routeOptions:u=S,className:s,activeClassName:i="active",activeStrict:a=!1,ignoreQueryParams:c=!0,onClick:l,target:d,children:p,...m})=>{const g=h(),v=x(r),f=x(u),y=function(t,r,o=!1,u=!0){const s=h(),i=x(r),a=e.useMemo(()=>n.createActiveRouteSource(s,t,i,{strict:o,ignoreQueryParams:u}),[s,t,i,o,u]);return e.useSyncExternalStore(a.subscribe,a.getSnapshot,a.getSnapshot)}(t,v,a,c),R=e.useMemo(()=>"function"==typeof g.buildUrl?g.buildUrl(t,v):g.buildPath(t,v),[g,t,v]),b=e.useCallback(e=>{l&&(l(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==d&&(e.preventDefault(),g.navigate(t,v,f).catch(()=>{}))},[l,d,g,t,v,f]),w=e.useMemo(()=>y&&i?s?`${s} ${i}`.trim():i:s??void 0,[y,s,i]);return o.jsx("a",{...m,href:R,className:w,onClick:b,children:p})},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)});y.displayName="Link",exports.Link=y,exports.RouteView=f,exports.RouterProvider=({router:r,children:u})=>{const s=e.useMemo(()=>t.getNavigator(r),[r]),i=e.useMemo(()=>n.createRouteSource(r),[r]),{route:a,previousRoute:c}=e.useSyncExternalStore(i.subscribe,i.getSnapshot,i.getSnapshot),l=e.useMemo(()=>({navigator:s,route:a,previousRoute:c}),[s,a,c]);return o.jsx(p,{value:r,children:o.jsx(m,{value:s,children:o.jsx(d,{value:l,children:u})})})},exports.useNavigator=()=>{const t=e.useContext(m);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.useContext(d);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=g,exports.useRouteUtils=()=>{const e=h();return r.getRouteUtils(u.getPluginApi(e).getTree())},exports.useRouter=h,exports.useRouterTransition=function(){const t=h(),r=e.useMemo(()=>n.createTransitionSource(t),[t]);return e.useSyncExternalStore(r.subscribe,r.getSnapshot,r.getSnapshot)};//# sourceMappingURL=index.js.map
1
+ var e=require("react"),t=require("@real-router/core"),r=require("@real-router/route-utils"),o=require("react/jsx-runtime"),n=require("@real-router/sources"),u=require("dom-utils"),s=require("@real-router/core/api");function i(e){return null}function a(e){return null}function c(e,t,o){return o?e===t:r.startsWithSegment(e,t)}function l(t,r){for(const o of e.Children.toArray(t))e.isValidElement(o)&&(o.type===i||o.type===a?r.push(o):l(o.props.children,r))}function d(t,r,n,u,s){const i=void 0===s?t:o.jsx(e.Suspense,{fallback:s,children:t});return n?o.jsx(e.Activity,{mode:u,children:i},r):o.jsx(e.Fragment,{children:i},r)}i.displayName="RouteView.Match",a.displayName="RouteView.NotFound";var p=e.createContext(null),m=e.createContext(null),h=e.createContext(null),v=()=>{const t=e.useContext(m);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function g(r){const o=v(),u=e.useMemo(()=>n.createRouteNodeSource(o,r),[o,r]),{route:s,previousRoute:i}=e.useSyncExternalStore(u.subscribe,u.getSnapshot,u.getSnapshot),a=e.useMemo(()=>t.getNavigator(o),[o]);return e.useMemo(()=>({navigator:a,route:s,previousRoute:i}),[a,s,i])}function f({nodeName:r,children:n}){const{route:u}=g(r),s=e.useRef(new Set);if(!u)return null;const i=[];l(n,i);const{rendered:p}=function(r,n,u,s){let i=null,l=!1;const p=[];for(const e of r){if(e.type===a){i=e.props.children;continue}const{segment:t,exact:r=!1,keepAlive:o=!1,fallback:m}=e.props,h=u?`${u}.${t}`:t;!l&&c(n,h,r)?(l=!0,s.add(h),p.push(d(e.props.children,h,o,"visible",m))):o&&s.has(h)&&p.push(d(e.props.children,h,o,"hidden",m))}return l||n!==t.UNKNOWN_ROUTE||null===i||p.push(o.jsx(e.Fragment,{children:i},"__route-view-not-found__")),{rendered:p,activeMatchFound:l}}(i,u.name,r,s.current);return p.length>0?o.jsx(o.Fragment,{children:p}):null}f.displayName="RouteView";var N=Object.assign(f,{Match:i,NotFound:a}),S=Object.freeze({}),x=Object.freeze({});function R(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}var y=e.memo(({routeName:t,routeParams:r=S,routeOptions:s=x,className:i,activeClassName:a="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:d,target:p,children:m,...h})=>{const g=v(),f=R(r),N=R(s),y=function(t,r,o=!1,u=!0){const s=v(),i=R(r),a=e.useMemo(()=>n.createActiveRouteSource(s,t,i,{strict:o,ignoreQueryParams:u}),[s,t,i,o,u]);return e.useSyncExternalStore(a.subscribe,a.getSnapshot,a.getSnapshot)}(t,f,c,l),b=e.useMemo(()=>u.buildHref(g,t,f),[g,t,f]),C=e.useCallback(e=>{d&&(d(e),e.defaultPrevented)||u.shouldNavigate(e.nativeEvent)&&"_blank"!==p&&(e.preventDefault(),g.navigate(t,f,N).catch(()=>{}))},[d,p,g,t,f,N]),w=e.useMemo(()=>u.buildActiveClassName(y,a,i),[y,a,i]);return o.jsx("a",{...h,href:b,className:w,onClick:C,children:m})},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)});y.displayName="Link",exports.Link=y,exports.RouteView=N,exports.RouterProvider=({router:r,children:s,announceNavigation:i})=>{e.useEffect(()=>{if(!i)return;const e=u.createRouteAnnouncer(r);return()=>{e.destroy()}},[i,r]);const a=e.useMemo(()=>t.getNavigator(r),[r]),c=e.useMemo(()=>n.createRouteSource(r),[r]),{route:l,previousRoute:d}=e.useSyncExternalStore(c.subscribe,c.getSnapshot,c.getSnapshot),v=e.useMemo(()=>({navigator:a,route:l,previousRoute:d}),[a,l,d]);return o.jsx(m,{value:r,children:o.jsx(h,{value:a,children:o.jsx(p,{value:v,children:s})})})},exports.useNavigator=()=>{const t=e.useContext(h);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.useContext(p);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=g,exports.useRouteUtils=()=>{const e=v();return r.getRouteUtils(s.getPluginApi(e).getTree())},exports.useRouter=v,exports.useRouterTransition=function(){const t=v(),r=e.useMemo(()=>n.createTransitionSource(t),[t]);return e.useSyncExternalStore(r.subscribe,r.getSnapshot,r.getSnapshot)};//# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/modern/RouteView/components.tsx","../../src/components/modern/RouteView/helpers.tsx","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/components/modern/RouteView/RouteView.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["startsWithSegment","Children","isValidElement","jsx","Activity","Fragment","UNKNOWN_ROUTE","createContext","useContext","useMemo","createRouteNodeSource","useSyncExternalStore","getNavigator","useRef","createActiveRouteSource","memo","useCallback","getRouteUtils","getPluginApi","createTransitionSource","createRouteSource"],"mappings":"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","file":"index.js","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","// 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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\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/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/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","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\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/components/modern/RouteView/components.tsx","../../src/components/modern/RouteView/helpers.tsx","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/components/modern/RouteView/RouteView.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["startsWithSegment","Children","isValidElement","jsx","Suspense","Activity","Fragment","UNKNOWN_ROUTE","createContext","useContext","useMemo","createRouteNodeSource","useSyncExternalStore","getNavigator","useRef","createActiveRouteSource","memo","buildHref","useCallback","shouldNavigate","buildActiveClassName","getRouteUtils","getPluginApi","createTransitionSource","useEffect","createRouteAnnouncer","createRouteSource"],"mappings":";;;AAEO,SAAS,MAAM,MAAA,EAA0B;AAC9C,EAAA,OAAO,IAAA;AACT;AAEA,KAAA,CAAM,WAAA,GAAc,iBAAA;AAEb,SAAS,SAAS,MAAA,EAA6B;AACpD,EAAA,OAAO,IAAA;AACT;AAEA,QAAA,CAAS,WAAA,GAAc,oBAAA;ACHvB,SAAS,cAAA,CACP,SAAA,EACA,eAAA,EACA,KAAA,EACS;AACT,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,SAAA,KAAc,eAAA;AAAA,EACvB;AAEA,EAAA,OAAOA,4BAAA,CAAkB,WAAW,eAAe,CAAA;AACrD;AAEO,SAAS,eAAA,CACd,UACA,MAAA,EACM;AAEN,EAAA,KAAA,MAAW,KAAA,IAASC,cAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC9C,IAAA,IAAI,CAACC,oBAAA,CAAe,KAAK,CAAA,EAAG;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,IAAA,KAAS,KAAA,IAAS,KAAA,CAAM,SAAS,QAAA,EAAU;AACnD,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,eAAA;AAAA,QACG,MAAM,KAAA,CAA2C,QAAA;AAAA,QAClD;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAA,CACP,aAAA,EACA,eAAA,EACA,SAAA,EACA,MACA,QAAA,EACc;AACd,EAAA,MAAM,UACJ,QAAA,KAAa,MAAA,GACX,gCAEAC,cAAA,CAACC,cAAA,EAAA,EAAS,UAAqB,QAAA,EAAA,aAAA,EAAc,CAAA;AAGjD,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,uBACED,cAAA,CAACE,cAAA,EAAA,EAAS,IAAA,EACP,QAAA,EAAA,OAAA,EAAA,EADwB,eAE3B,CAAA;AAAA,EAEJ;AAEA,EAAA,uBAAOF,cAAA,CAACG,cAAA,EAAA,EAAgC,QAAA,EAAA,OAAA,EAAA,EAAlB,eAA0B,CAAA;AAClD;AAEO,SAAS,eAAA,CACd,QAAA,EACA,SAAA,EACA,QAAA,EACA,gBAAA,EACyD;AACzD,EAAA,IAAI,gBAAA,GAA8B,IAAA;AAClC,EAAA,IAAI,gBAAA,GAAmB,KAAA;AACvB,EAAA,MAAM,WAA2B,EAAC;AAElC,EAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,IAAA,IAAI,KAAA,CAAM,SAAS,QAAA,EAAU;AAC3B,MAAA,gBAAA,GAAoB,MAAM,KAAA,CAAwB,QAAA;AAClD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM;AAAA,MACJ,OAAA;AAAA,MACA,KAAA,GAAQ,KAAA;AAAA,MACR,SAAA,GAAY,KAAA;AAAA,MACZ;AAAA,QACE,KAAA,CAAM,KAAA;AACV,IAAA,MAAM,kBAAkB,QAAA,GAAW,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,GAAK,OAAA;AAC9D,IAAA,MAAM,WACJ,CAAC,gBAAA,IAAoB,cAAA,CAAe,SAAA,EAAW,iBAAiB,KAAK,CAAA;AAEvE,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,gBAAA,GAAmB,IAAA;AACnB,MAAA,gBAAA,CAAiB,IAAI,eAAe,CAAA;AACpC,MAAA,QAAA,CAAS,IAAA;AAAA,QACP,kBAAA;AAAA,UACG,MAAM,KAAA,CAAqB,QAAA;AAAA,UAC5B,eAAA;AAAA,UACA,SAAA;AAAA,UACA,SAAA;AAAA,UACA;AAAA;AACF,OACF;AAAA,IACF,CAAA,MAAA,IAAW,SAAA,IAAa,gBAAA,CAAiB,GAAA,CAAI,eAAe,CAAA,EAAG;AAC7D,MAAA,QAAA,CAAS,IAAA;AAAA,QACP,kBAAA;AAAA,UACG,MAAM,KAAA,CAAqB,QAAA;AAAA,UAC5B,eAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,UACA;AAAA;AACF,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IACE,CAAC,gBAAA,IACD,SAAA,KAAcC,kBAAA,IACd,qBAAqB,IAAA,EACrB;AACA,IAAA,QAAA,CAAS,IAAA;AAAA,sBACPJ,cAAA,CAACG,cAAA,EAAA,EAAyC,QAAA,EAAA,gBAAA,EAAA,EAA5B,0BAA6C;AAAA,KAC7D;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,UAAU,gBAAA,EAAiB;AACtC;AC1HO,IAAM,YAAA,GAAeE,oBAAuC,IAAI,CAAA;AAEhE,IAAM,aAAA,GAAgBA,oBAA6B,IAAI,CAAA;AAEvD,IAAM,gBAAA,GAAmBA,oBAAgC,IAAI,CAAA;;;ACH7D,IAAM,YAAY,MAAc;AACrC,EAAA,MAAM,MAAA,GAASC,iBAAW,aAAa,CAAA;AAEvC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,MAAA;AACT;;;ACRO,SAAS,aAAa,QAAA,EAAgC;AAC3D,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,KAAA,GAAQC,aAAA;AAAA,IACZ,MAAMC,6BAAA,CAAsB,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5C,CAAC,QAAQ,QAAQ;AAAA,GACnB;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAIC,0BAAA;AAAA,IAC/B,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AAEA,EAAA,MAAM,SAAA,GAAYF,cAAQ,MAAMG,iBAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAE9D,EAAA,OAAOH,aAAA;AAAA,IACL,OAAqB,EAAE,SAAA,EAAW,KAAA,EAAO,aAAA,EAAc,CAAA;AAAA,IACvD,CAAC,SAAA,EAAW,KAAA,EAAO,aAAa;AAAA,GAClC;AACF;ACnBA,SAAS,aAAA,CAAc;AAAA,EACrB,QAAA;AAAA,EACA;AACF,CAAA,EAAkD;AAChD,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,YAAA,CAAa,QAAQ,CAAA;AACvC,EAAA,MAAM,mBAAA,GAAsBI,YAAA,iBAAoB,IAAI,GAAA,EAAK,CAAA;AAEzD,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,WAA2B,EAAC;AAElC,EAAA,eAAA,CAAgB,UAAU,QAAQ,CAAA;AAElC,EAAA,MAAM,EAAE,UAAS,GAAI,eAAA;AAAA,IACnB,QAAA;AAAA,IACA,KAAA,CAAM,IAAA;AAAA,IACN,QAAA;AAAA,IACA,mBAAA,CAAoB;AAAA,GACtB;AAEA,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,IAAA,uBAAOX,cAAAA,CAAAG,mBAAAA,EAAA,EAAG,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,OAAO,IAAA;AACT;AAEA,aAAA,CAAc,WAAA,GAAc,WAAA;AAErB,IAAM,YAAY,MAAA,CAAO,MAAA,CAAO,eAAe,EAAE,KAAA,EAAO,UAAU;;;ACnClE,IAAM,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAKrC,IAAM,aAAA,GAAgB,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;ACYtC,SAAS,eAAkB,KAAA,EAAa;AAC7C,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAIvC,EAAA,OAAOI,aAAAA,CAAQ,MAAM,KAAA,EAAO,CAAC,UAAU,CAAC,CAAA;AAC1C;;;ACpBO,SAAS,iBACd,SAAA,EACA,MAAA,EACA,MAAA,GAAS,KAAA,EACT,oBAAoB,IAAA,EACX;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AAKzB,EAAA,MAAM,YAAA,GAAe,eAAe,MAAM,CAAA;AAE1C,EAAA,MAAM,KAAA,GAAQA,aAAAA;AAAA,IACZ,MACEK,+BAAA,CAAwB,MAAA,EAAQ,SAAA,EAAW,YAAA,EAAc;AAAA,MACvD,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,IACH,CAAC,MAAA,EAAQ,SAAA,EAAW,YAAA,EAAc,QAAQ,iBAAiB;AAAA,GAC7D;AAEA,EAAA,OAAOH,0BAAAA;AAAA,IACL,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AACF;ACxBA,SAAS,iBAAA,CACP,MACA,IAAA,EACS;AACT,EAAA,OACE,IAAA,CAAK,SAAA,KAAc,IAAA,CAAK,SAAA,IACxB,IAAA,CAAK,cAAc,IAAA,CAAK,SAAA,IACxB,IAAA,CAAK,eAAA,KAAoB,IAAA,CAAK,eAAA,IAC9B,KAAK,YAAA,KAAiB,IAAA,CAAK,YAAA,IAC3B,IAAA,CAAK,iBAAA,KAAsB,IAAA,CAAK,iBAAA,IAChC,IAAA,CAAK,OAAA,KAAY,IAAA,CAAK,OAAA,IACtB,IAAA,CAAK,MAAA,KAAW,IAAA,CAAK,UACrB,IAAA,CAAK,KAAA,KAAU,IAAA,CAAK,KAAA,IACpB,IAAA,CAAK,QAAA,KAAa,KAAK,QAAA,IACvB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,WAAW,CAAA,KAAM,KAAK,SAAA,CAAU,IAAA,CAAK,WAAW,CAAA,IACpE,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,YAAY,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,YAAY,CAAA;AAE1E;AAEO,IAAM,IAAA,GAAsBI,UAAA;AAAA,EACjC,CAAC;AAAA,IACC,SAAA;AAAA,IACA,WAAA,GAAc,YAAA;AAAA,IACd,YAAA,GAAe,aAAA;AAAA,IACf,SAAA;AAAA,IACA,eAAA,GAAkB,QAAA;AAAA,IAClB,YAAA,GAAe,KAAA;AAAA,IACf,iBAAA,GAAoB,IAAA;AAAA,IACpB,OAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,GACL,KAAM;AACJ,IAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,IAAA,MAAM,YAAA,GAAe,eAAe,WAAW,CAAA;AAC/C,IAAA,MAAM,aAAA,GAAgB,eAAe,YAAY,CAAA;AAEjD,IAAA,MAAM,QAAA,GAAW,gBAAA;AAAA,MACf,SAAA;AAAA,MACA,YAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,IAAA,GAAON,aAAAA;AAAA,MACX,MAAMO,kBAAA,CAAU,MAAA,EAAQ,SAAA,EAAW,YAAY,CAAA;AAAA,MAC/C,CAAC,MAAA,EAAQ,SAAA,EAAW,YAAY;AAAA,KAClC;AAEA,IAAA,MAAM,WAAA,GAAcC,iBAAA;AAAA,MAClB,CAAC,GAAA,KAAuC;AACtC,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,GAAG,CAAA;AAEX,UAAA,IAAI,IAAI,gBAAA,EAAkB;AACxB,YAAA;AAAA,UACF;AAAA,QACF;AAEA,QAAA,IAAI,CAACC,uBAAA,CAAe,GAAA,CAAI,WAAW,CAAA,IAAK,WAAW,QAAA,EAAU;AAC3D,UAAA;AAAA,QACF;AAEA,QAAA,GAAA,CAAI,cAAA,EAAe;AACnB,QAAA,MAAA,CAAO,SAAS,SAAA,EAAW,YAAA,EAAc,aAAa,CAAA,CAAE,MAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MACxE,CAAA;AAAA,MACA,CAAC,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAW,cAAc,aAAa;AAAA,KAClE;AAEA,IAAA,MAAM,cAAA,GAAiBT,aAAAA;AAAA,MACrB,MAAMU,6BAAA,CAAqB,QAAA,EAAU,eAAA,EAAiB,SAAS,CAAA;AAAA,MAC/D,CAAC,QAAA,EAAU,eAAA,EAAiB,SAAS;AAAA,KACvC;AAEA,IAAA,uBACEjB,cAAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACE,GAAG,KAAA;AAAA,QACJ,IAAA;AAAA,QACA,SAAA,EAAW,cAAA;AAAA,QACX,OAAA,EAAS,WAAA;AAAA,QAER;AAAA;AAAA,KACH;AAAA,EAEJ,CAAA;AAAA,EACA;AACF;AAEA,IAAA,CAAK,WAAA,GAAc,MAAA;AC5FZ,IAAM,eAAe,MAAiB;AAC3C,EAAA,MAAM,SAAA,GAAYM,iBAAW,gBAAgB,CAAA;AAE7C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AAEA,EAAA,OAAO,SAAA;AACT;ACeO,IAAM,gBAAgB,MAAkB;AAC7C,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,OAAOY,wBAAA,CAAcC,gBAAA,CAAa,MAAM,CAAA,CAAE,SAAS,CAAA;AACrD;AC3BO,IAAM,WAAW,MAAwB;AAC9C,EAAA,MAAM,YAAA,GAAeb,iBAAW,YAAY,CAAA;AAE5C,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,YAAA;AACT;ACTO,SAAS,mBAAA,GAAgD;AAC9D,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,KAAA,GAAQC,cAAQ,MAAMa,8BAAA,CAAuB,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEpE,EAAA,OAAOX,0BAAAA;AAAA,IACL,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA,GACR;AACF;ACDO,IAAM,iBAAyC,CAAC;AAAA,EACrD,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAAY,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAYC,8BAAqB,MAAM,CAAA;AAE7C,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,CAAU,OAAA,EAAQ;AAAA,IACpB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,kBAAA,EAAoB,MAAM,CAAC,CAAA;AAE/B,EAAA,MAAM,SAAA,GAAYf,cAAQ,MAAMG,iBAAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAK9D,EAAA,MAAM,KAAA,GAAQH,cAAQ,MAAMgB,yBAAA,CAAkB,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAC/D,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAId,0BAAAA;AAAA,IAC/B,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AAEA,EAAA,MAAM,iBAAA,GAAoBF,aAAAA;AAAA,IACxB,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,aAAA,EAAc,CAAA;AAAA,IACzC,CAAC,SAAA,EAAW,KAAA,EAAO,aAAa;AAAA,GAClC;AAEA,EAAA,uBACEP,cAAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAO,MAAA,EACpB,0BAAAA,cAAAA,CAAC,gBAAA,EAAA,EAAiB,KAAA,EAAO,SAAA,EACvB,0BAAAA,cAAAA,CAAC,YAAA,EAAA,EAAa,OAAO,iBAAA,EAAoB,QAAA,EAAS,GACpD,CAAA,EACF,CAAA;AAEJ","file":"index.js","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, Suspense, 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 fallback?: ReactNode,\n): ReactElement {\n const content =\n fallback === undefined ? (\n matchChildren\n ) : (\n <Suspense fallback={fallback}>{matchChildren}</Suspense>\n );\n\n if (keepAlive) {\n return (\n <Activity mode={mode} key={fullSegmentName}>\n {content}\n </Activity>\n );\n }\n\n return <Fragment key={fullSegmentName}>{content}</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 fallback,\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 fallback,\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 fallback,\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","// 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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\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/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/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 { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { 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\";\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 () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\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.nativeEvent) || 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 () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\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","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\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 { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, 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 announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\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"]}
@@ -63,6 +63,7 @@ declare function useRouterTransition(): RouterTransitionSnapshot;
63
63
  interface RouteProviderProps {
64
64
  router: Router;
65
65
  children: ReactNode;
66
+ announceNavigation?: boolean;
66
67
  }
67
68
  declare const RouterProvider: FC<RouteProviderProps>;
68
69
 
@@ -1 +1 @@
1
- var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),u=require("@real-router/core/api"),s=require("@real-router/route-utils"),n=Object.freeze({}),a=Object.freeze({}),i=e.createContext(null),c=e.createContext(null),l=e.createContext(null),m=()=>{const t=e.useContext(c);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function g(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}var v=e.memo(({routeName:o,routeParams:u=n,routeOptions:s=a,className:i,activeClassName:c="active",activeStrict:l=!1,ignoreQueryParams:v=!0,onClick:p,target:S,children:h,...d})=>{const x=m(),f=g(u),N=g(s),y=function(r,o,u=!1,s=!0){const n=m(),a=g(o),i=e.useMemo(()=>t.createActiveRouteSource(n,r,a,{strict:u,ignoreQueryParams:s}),[n,r,a,u,s]);return e.useSyncExternalStore(i.subscribe,i.getSnapshot,i.getSnapshot)}(o,f,l,v),b=e.useMemo(()=>"function"==typeof x.buildUrl?x.buildUrl(o,f):x.buildPath(o,f),[x,o,f]),R=e.useCallback(e=>{p&&(p(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==S&&(e.preventDefault(),x.navigate(o,f,N).catch(()=>{}))},[p,S,x,o,f,N]),C=e.useMemo(()=>y&&c?i?`${i} ${c}`.trim():c:i??void 0,[y,i,c]);return r.jsx("a",{...d,href:b,className:C,onClick:R,children:h})},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)});v.displayName="Link",exports.Link=v,exports.RouterProvider=({router:u,children:s})=>{const n=e.useMemo(()=>o.getNavigator(u),[u]),a=e.useMemo(()=>t.createRouteSource(u),[u]),{route:m,previousRoute:g}=e.useSyncExternalStore(a.subscribe,a.getSnapshot,a.getSnapshot),v=e.useMemo(()=>({navigator:n,route:m,previousRoute:g}),[n,m,g]);return r.jsx(c,{value:u,children:r.jsx(l,{value:n,children:r.jsx(i,{value:v,children:s})})})},exports.useNavigator=()=>{const t=e.useContext(l);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.useContext(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=function(r){const u=m(),s=e.useMemo(()=>t.createRouteNodeSource(u,r),[u,r]),{route:n,previousRoute:a}=e.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),i=e.useMemo(()=>o.getNavigator(u),[u]);return e.useMemo(()=>({navigator:i,route:n,previousRoute:a}),[i,n,a])},exports.useRouteUtils=()=>{const e=m();return s.getRouteUtils(u.getPluginApi(e).getTree())},exports.useRouter=m,exports.useRouterTransition=function(){const r=m(),o=e.useMemo(()=>t.createTransitionSource(r),[r]);return e.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot)};//# sourceMappingURL=legacy.js.map
1
+ var e=require("dom-utils"),t=require("react"),r=require("@real-router/sources"),o=require("react/jsx-runtime"),u=require("@real-router/core"),s=require("@real-router/core/api"),n=require("@real-router/route-utils"),a=Object.freeze({}),i=Object.freeze({}),c=t.createContext(null),l=t.createContext(null),m=t.createContext(null),g=()=>{const e=t.useContext(l);if(!e)throw new Error("useRouter must be used within a RouterProvider");return e};function v(e){const r=JSON.stringify(e);return t.useMemo(()=>e,[r])}var S=t.memo(({routeName:u,routeParams:s=a,routeOptions:n=i,className:c,activeClassName:l="active",activeStrict:m=!1,ignoreQueryParams:S=!0,onClick:p,target:d,children:h,...N})=>{const x=g(),f=v(s),R=v(n),b=function(e,o,u=!1,s=!0){const n=g(),a=v(o),i=t.useMemo(()=>r.createActiveRouteSource(n,e,a,{strict:u,ignoreQueryParams:s}),[n,e,a,u,s]);return t.useSyncExternalStore(i.subscribe,i.getSnapshot,i.getSnapshot)}(u,f,m,S),y=t.useMemo(()=>e.buildHref(x,u,f),[x,u,f]),C=t.useCallback(t=>{p&&(p(t),t.defaultPrevented)||e.shouldNavigate(t.nativeEvent)&&"_blank"!==d&&(t.preventDefault(),x.navigate(u,f,R).catch(()=>{}))},[p,d,x,u,f,R]),P=t.useMemo(()=>e.buildActiveClassName(b,l,c),[b,l,c]);return o.jsx("a",{...N,href:y,className:P,onClick:C,children:h})},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)});S.displayName="Link",exports.Link=S,exports.RouterProvider=({router:s,children:n,announceNavigation:a})=>{t.useEffect(()=>{if(!a)return;const t=e.createRouteAnnouncer(s);return()=>{t.destroy()}},[a,s]);const i=t.useMemo(()=>u.getNavigator(s),[s]),g=t.useMemo(()=>r.createRouteSource(s),[s]),{route:v,previousRoute:S}=t.useSyncExternalStore(g.subscribe,g.getSnapshot,g.getSnapshot),p=t.useMemo(()=>({navigator:i,route:v,previousRoute:S}),[i,v,S]);return o.jsx(l,{value:s,children:o.jsx(m,{value:i,children:o.jsx(c,{value:p,children:n})})})},exports.useNavigator=()=>{const e=t.useContext(m);if(!e)throw new Error("useNavigator must be used within a RouterProvider");return e},exports.useRoute=()=>{const e=t.useContext(c);if(!e)throw new Error("useRoute must be used within a RouteProvider");return e},exports.useRouteNode=function(e){const o=g(),s=t.useMemo(()=>r.createRouteNodeSource(o,e),[o,e]),{route:n,previousRoute:a}=t.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),i=t.useMemo(()=>u.getNavigator(o),[o]);return t.useMemo(()=>({navigator:i,route:n,previousRoute:a}),[i,n,a])},exports.useRouteUtils=()=>{const e=g();return n.getRouteUtils(s.getPluginApi(e).getTree())},exports.useRouter=g,exports.useRouterTransition=function(){const e=g(),o=t.useMemo(()=>r.createTransitionSource(e),[e]);return t.useSyncExternalStore(o.subscribe,o.getSnapshot,o.getSnapshot)};//# sourceMappingURL=legacy.js.map
@@ -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","useContext","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createTransitionSource","createRouteSource"],"mappings":"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","file":"legacy.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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(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 { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(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 { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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/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","useContext","useMemo","createActiveRouteSource","useSyncExternalStore","memo","buildHref","useCallback","shouldNavigate","buildActiveClassName","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createTransitionSource","useEffect","createRouteAnnouncer","createRouteSource"],"mappings":"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","file":"legacy.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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(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 { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { 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\";\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 () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\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.nativeEvent) || 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 () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\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 { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(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 { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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 { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, 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 announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\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 +1 @@
1
- {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":378,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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/useNavigator.tsx":{"bytes":408,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":981,"imports":[{"path":"@real-router/core/api","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":417,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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":849,"imports":[{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":667,"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/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":23098},"dist/cjs/index.js":{"imports":[{"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","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/sources","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/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":"@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","RouteView","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"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/hooks/useRouteNode.tsx":{"bytesInOutput":701},"src/hooks/useRouter.tsx":{"bytesInOutput":216},"src/context.ts":{"bytesInOutput":164},"src/components/modern/RouteView/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":2418},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":697},"src/hooks/useStableValue.tsx":{"bytesInOutput":170},"src/utils.ts":{"bytesInOutput":140},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":246},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":10778},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":16335},"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/api","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","RouterProvider","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":216},"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":246},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7290}}}
1
+ {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/modern/RouteView/helpers.tsx":{"bytes":3208,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":378,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":2703,"imports":[{"path":"dom-utils","kind":"import-statement","external":true},{"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":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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/useNavigator.tsx":{"bytes":408,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":981,"imports":[{"path":"@real-router/core/api","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":417,"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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1710,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","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.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/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":849,"imports":[{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":667,"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/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_tsx@4.19.4_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":23205},"dist/cjs/index.js":{"imports":[{"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","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"dom-utils","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/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","RouteView","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/modern/RouteView/RouteView.tsx":{"bytesInOutput":712},"src/components/modern/RouteView/components.tsx":{"bytesInOutput":171},"src/components/modern/RouteView/helpers.tsx":{"bytesInOutput":2545},"src/hooks/useRouteNode.tsx":{"bytesInOutput":701},"src/hooks/useRouter.tsx":{"bytesInOutput":216},"src/context.ts":{"bytesInOutput":164},"src/components/modern/RouteView/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":2287},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":697},"src/hooks/useStableValue.tsx":{"bytesInOutput":170},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":246},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1296}},"bytes":10975},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":16108},"dist/cjs/legacy.js":{"imports":[{"path":"dom-utils","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","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/api","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":"dom-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2278},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":216},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/legacy.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":246},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1296}},"bytes":7297}}}
@@ -0,0 +1 @@
1
+ import{createContext as r,memo as e,useMemo as t,useCallback as o,useContext as n,useSyncExternalStore as a,useEffect as i}from"react";import{getNavigator as u}from"@real-router/core";import{createActiveRouteSource as s,createRouteNodeSource as c,createTransitionSource as l,createRouteSource as m}from"@real-router/sources";import{buildHref as v,shouldNavigate as f,buildActiveClassName as g,createRouteAnnouncer as p}from"dom-utils";import{jsx as h}from"react/jsx-runtime";import{getPluginApi as d}from"@real-router/core/api";import{getRouteUtils as N}from"@real-router/route-utils";var S=r(null),b=r(null),y=r(null),P=()=>{const r=n(b);if(!r)throw new Error("useRouter must be used within a RouterProvider");return r};function O(r){const e=P(),o=t(()=>c(e,r),[e,r]),{route:n,previousRoute:i}=a(o.subscribe,o.getSnapshot,o.getSnapshot),s=t(()=>u(e),[e]);return t(()=>({navigator:s,route:n,previousRoute:i}),[s,n,i])}var w=Object.freeze({}),R=Object.freeze({});function C(r){const e=JSON.stringify(r);return t(()=>r,[e])}var k=e(({routeName:r,routeParams:e=w,routeOptions:n=R,className:i,activeClassName:u="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:m,target:p,children:d,...N})=>{const S=P(),b=C(e),y=C(n),O=function(r,e,o=!1,n=!0){const i=P(),u=C(e),c=t(()=>s(i,r,u,{strict:o,ignoreQueryParams:n}),[i,r,u,o,n]);return a(c.subscribe,c.getSnapshot,c.getSnapshot)}(r,b,c,l),k=t(()=>v(S,r,b),[S,r,b]),J=o(e=>{m&&(m(e),e.defaultPrevented)||f(e.nativeEvent)&&"_blank"!==p&&(e.preventDefault(),S.navigate(r,b,y).catch(()=>{}))},[m,p,S,r,b,y]),E=t(()=>g(O,u,i),[O,u,i]);return h("a",{...N,href:k,className:E,onClick:J,children:d})},function(r,e){return r.routeName===e.routeName&&r.className===e.className&&r.activeClassName===e.activeClassName&&r.activeStrict===e.activeStrict&&r.ignoreQueryParams===e.ignoreQueryParams&&r.onClick===e.onClick&&r.target===e.target&&r.style===e.style&&r.children===e.children&&JSON.stringify(r.routeParams)===JSON.stringify(e.routeParams)&&JSON.stringify(r.routeOptions)===JSON.stringify(e.routeOptions)});k.displayName="Link";var J=()=>{const r=n(y);if(!r)throw new Error("useNavigator must be used within a RouterProvider");return r},E=()=>{const r=P();return N(d(r).getTree())},Q=()=>{const r=n(S);if(!r)throw new Error("useRoute must be used within a RouteProvider");return r};function j(){const r=P(),e=t(()=>l(r),[r]);return a(e.subscribe,e.getSnapshot,e.getSnapshot)}var x=({router:r,children:e,announceNavigation:o})=>{i(()=>{if(!o)return;const e=p(r);return()=>{e.destroy()}},[o,r]);const n=t(()=>u(r),[r]),s=t(()=>m(r),[r]),{route:c,previousRoute:l}=a(s.subscribe,s.getSnapshot,s.getSnapshot),v=t(()=>({navigator:n,route:c,previousRoute:l}),[n,c,l]);return h(b,{value:r,children:h(y,{value:n,children:h(S,{value:v,children:e})})})};export{k as Link,x as RouterProvider,J as useNavigator,Q as useRoute,O as useRouteNode,E as useRouteUtils,P as useRouter,j as useRouterTransition};//# sourceMappingURL=chunk-SQL27477.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["useMemo","useSyncExternalStore","useContext","getNavigator","jsx"],"mappings":"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","file":"chunk-SQL27477.mjs","sourcesContent":["// 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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\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","// 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/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 { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { 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\";\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 () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\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.nativeEvent) || 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 () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\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","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\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 { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, 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 announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\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"]}
@@ -17,6 +17,8 @@ interface MatchProps {
17
17
  readonly exact?: boolean;
18
18
  /** Preserve component state when deactivated (React Activity). Defaults to false. */
19
19
  readonly keepAlive?: boolean;
20
+ /** Fallback content to show while children are suspended. */
21
+ readonly fallback?: ReactNode;
20
22
  /** Content to render when matched. */
21
23
  readonly children: ReactNode;
22
24
  }
@@ -1 +1 @@
1
- import{useRouteNode as e}from"./chunk-BINM7GZZ.mjs";export{Link,RouterProvider,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-BINM7GZZ.mjs";import{useRef as r,Children as t,isValidElement as n,Fragment as o,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 d(e){return null}function p(e){return null}function a(e,r,t){return t?e===r:s(e,r)}function m(e,r){for(const o of t.toArray(e))n(o)&&(o.type===d||o.type===p?r.push(o):m(o.props.children,r))}function h(e,r,t,n){return t?c(u,{mode:n,children:e},r):c(o,{children:e},r)}function f({nodeName:t,children:n}){const{route:u}=e(t),s=r(new Set);if(!u)return null;const d=[];m(n,d);const{rendered:f}=function(e,r,t,n){let u=null,s=!1;const l=[];for(const o of e){if(o.type===p){u=o.props.children;continue}const{segment:e,exact:i=!1,keepAlive:c=!1}=o.props,d=t?`${t}.${e}`:e;!s&&a(r,d,i)?(s=!0,n.add(d),l.push(h(o.props.children,d,c,"visible"))):c&&n.has(d)&&l.push(h(o.props.children,d,c,"hidden"))}return s||r!==i||null===u||l.push(c(o,{children:u},"__route-view-not-found__")),{rendered:l,activeMatchFound:s}}(d,u.name,t,s.current);return f.length>0?c(l,{children:f}):null}d.displayName="RouteView.Match",p.displayName="RouteView.NotFound",f.displayName="RouteView";var N=Object.assign(f,{Match:d,NotFound:p});export{N as RouteView};//# sourceMappingURL=index.mjs.map
1
+ import{useRouteNode as e}from"./chunk-SQL27477.mjs";export{Link,RouterProvider,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-SQL27477.mjs";import{useRef as r,Children as t,isValidElement as n,Fragment as o,Activity as u,Suspense as i}from"react";import{UNKNOWN_ROUTE as c}from"@real-router/core";import{startsWithSegment as s}from"@real-router/route-utils";import{jsx as l,Fragment as a}from"react/jsx-runtime";function d(e){return null}function p(e){return null}function f(e,r,t){return t?e===r:s(e,r)}function h(e,r){for(const o of t.toArray(e))n(o)&&(o.type===d||o.type===p?r.push(o):h(o.props.children,r))}function m(e,r,t,n,c){const s=void 0===c?e:l(i,{fallback:c,children:e});return t?l(u,{mode:n,children:s},r):l(o,{children:s},r)}function R({nodeName:t,children:n}){const{route:u}=e(t),i=r(new Set);if(!u)return null;const s=[];h(n,s);const{rendered:d}=function(e,r,t,n){let u=null,i=!1;const s=[];for(const o of e){if(o.type===p){u=o.props.children;continue}const{segment:e,exact:c=!1,keepAlive:l=!1,fallback:a}=o.props,d=t?`${t}.${e}`:e;!i&&f(r,d,c)?(i=!0,n.add(d),s.push(m(o.props.children,d,l,"visible",a))):l&&n.has(d)&&s.push(m(o.props.children,d,l,"hidden",a))}return i||r!==c||null===u||s.push(l(o,{children:u},"__route-view-not-found__")),{rendered:s,activeMatchFound:i}}(s,u.name,t,i.current);return d.length>0?l(a,{children:d}):null}d.displayName="RouteView.Match",p.displayName="RouteView.NotFound",R.displayName="RouteView";var v=Object.assign(R,{Match:d,NotFound:p});export{v as RouteView};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
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"]}
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, Suspense, 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 fallback?: ReactNode,\n): ReactElement {\n const content =\n fallback === undefined ? (\n matchChildren\n ) : (\n <Suspense fallback={fallback}>{matchChildren}</Suspense>\n );\n\n if (keepAlive) {\n return (\n <Activity mode={mode} key={fullSegmentName}>\n {content}\n </Activity>\n );\n }\n\n return <Fragment key={fullSegmentName}>{content}</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 fallback,\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 fallback,\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 fallback,\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"]}
@@ -63,6 +63,7 @@ declare function useRouterTransition(): RouterTransitionSnapshot;
63
63
  interface RouteProviderProps {
64
64
  router: Router;
65
65
  children: ReactNode;
66
+ announceNavigation?: boolean;
66
67
  }
67
68
  declare const RouterProvider: FC<RouteProviderProps>;
68
69
 
@@ -1 +1 @@
1
- export{Link,RouterProvider,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-BINM7GZZ.mjs";//# sourceMappingURL=legacy.mjs.map
1
+ export{Link,RouterProvider,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter,useRouterTransition}from"./chunk-SQL27477.mjs";//# sourceMappingURL=legacy.mjs.map
@@ -1 +1 @@
1
- {"inputs":{"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/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":378,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"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/constants.ts":{"bytes":225,"imports":[],"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/useNavigator.tsx":{"bytes":408,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":981,"imports":[{"path":"@real-router/core/api","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/useRoute.tsx":{"bytes":417,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"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":849,"imports":[{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"}],"format":"esm"},"src/legacy.ts":{"bytes":667,"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/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6842},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-BINM7GZZ.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","RouteView","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"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},"src/index.ts":{"bytesInOutput":0}},"bytes":3746},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-BINM7GZZ.mjs","kind":"import-statement"}],"exports":["Link","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":296},"dist/esm/chunk-BINM7GZZ.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16325},"dist/esm/chunk-BINM7GZZ.mjs":{"imports":[{"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/sources","kind":"import-statement","external":true},{"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/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":"@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","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"inputs":{"src/hooks/useRouter.tsx":{"bytesInOutput":216},"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouteNode.tsx":{"bytesInOutput":701},"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":697},"src/hooks/useStableValue.tsx":{"bytesInOutput":170},"src/utils.ts":{"bytesInOutput":140},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":246},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7289}}}
1
+ {"inputs":{"src/components/modern/RouteView/components.tsx":{"bytes":286,"imports":[],"format":"esm"},"src/components/modern/RouteView/helpers.tsx":{"bytes":3208,"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/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":378,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"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/constants.ts":{"bytes":225,"imports":[],"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/components/Link.tsx":{"bytes":2703,"imports":[{"path":"dom-utils","kind":"import-statement","external":true},{"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":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":408,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":981,"imports":[{"path":"@real-router/core/api","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/useRoute.tsx":{"bytes":417,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"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":1710,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","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":849,"imports":[{"path":"src/components/modern/RouteView/index.ts","kind":"import-statement","original":"./components/modern/RouteView"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"}],"format":"esm"},"src/legacy.ts":{"bytes":667,"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/useRouterTransition.tsx","kind":"import-statement","original":"./hooks/useRouterTransition"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":7176},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-SQL27477.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","RouteView","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/index.ts","inputs":{"src/components/modern/RouteView/RouteView.tsx":{"bytesInOutput":712},"src/components/modern/RouteView/components.tsx":{"bytesInOutput":171},"src/components/modern/RouteView/helpers.tsx":{"bytesInOutput":2545},"src/components/modern/RouteView/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0}},"bytes":3936},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-SQL27477.mjs","kind":"import-statement"}],"exports":["Link","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":296},"dist/esm/chunk-SQL27477.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16098},"dist/esm/chunk-SQL27477.mjs":{"imports":[{"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/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"dom-utils","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/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core/api","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"dom-utils","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","RouterProvider","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter","useRouterTransition"],"inputs":{"src/hooks/useRouter.tsx":{"bytesInOutput":216},"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouteNode.tsx":{"bytesInOutput":701},"src/components/Link.tsx":{"bytesInOutput":2278},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":697},"src/hooks/useStableValue.tsx":{"bytesInOutput":170},"src/hooks/useNavigator.tsx":{"bytesInOutput":250},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":229},"src/hooks/useRoute.tsx":{"bytesInOutput":246},"src/hooks/useRouterTransition.tsx":{"bytesInOutput":397},"src/RouterProvider.tsx":{"bytesInOutput":1296}},"bytes":7296}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/react",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
4
4
  "type": "commonjs",
5
5
  "description": "React integration for Real-Router",
6
6
  "main": "./dist/cjs/index.js",
@@ -64,9 +64,10 @@
64
64
  "license": "MIT",
65
65
  "sideEffects": false,
66
66
  "dependencies": {
67
- "@real-router/core": "^0.38.0",
68
67
  "@real-router/route-utils": "^0.1.5",
69
- "@real-router/sources": "^0.2.5"
68
+ "dom-utils": "^0.2.0",
69
+ "@real-router/sources": "^0.2.5",
70
+ "@real-router/core": "^0.38.0"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@testing-library/dom": "10.4.1",
@@ -1,6 +1,7 @@
1
1
  import { getNavigator } from "@real-router/core";
2
2
  import { createRouteSource } from "@real-router/sources";
3
- import { useMemo, useSyncExternalStore } from "react";
3
+ import { createRouteAnnouncer } from "dom-utils";
4
+ import { useEffect, useMemo, useSyncExternalStore } from "react";
4
5
 
5
6
  import { NavigatorContext, RouteContext, RouterContext } from "./context";
6
7
 
@@ -10,12 +11,26 @@ import type { FC, ReactNode } from "react";
10
11
  export interface RouteProviderProps {
11
12
  router: Router;
12
13
  children: ReactNode;
14
+ announceNavigation?: boolean;
13
15
  }
14
16
 
15
17
  export const RouterProvider: FC<RouteProviderProps> = ({
16
18
  router,
17
19
  children,
20
+ announceNavigation,
18
21
  }) => {
22
+ useEffect(() => {
23
+ if (!announceNavigation) {
24
+ return;
25
+ }
26
+
27
+ const announcer = createRouteAnnouncer(router);
28
+
29
+ return () => {
30
+ announcer.destroy();
31
+ };
32
+ }, [announceNavigation, router]);
33
+
19
34
  const navigator = useMemo(() => getNavigator(router), [router]);
20
35
 
21
36
  // useSyncExternalStore manages the router subscription lifecycle:
@@ -1,10 +1,10 @@
1
+ import { shouldNavigate, buildHref, buildActiveClassName } from "dom-utils";
1
2
  import { memo, useCallback, useMemo } from "react";
2
3
 
3
4
  import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
4
5
  import { useIsActiveRoute } from "../hooks/useIsActiveRoute";
5
6
  import { useRouter } from "../hooks/useRouter";
6
7
  import { useStableValue } from "../hooks/useStableValue";
7
- import { shouldNavigate } from "../utils";
8
8
 
9
9
  import type { LinkProps } from "../types";
10
10
  import type { FC, MouseEvent } from "react";
@@ -54,13 +54,10 @@ export const Link: FC<LinkProps> = memo(
54
54
  ignoreQueryParams,
55
55
  );
56
56
 
57
- const href = useMemo(() => {
58
- if (typeof router.buildUrl === "function") {
59
- return router.buildUrl(routeName, stableParams);
60
- }
61
-
62
- return router.buildPath(routeName, stableParams);
63
- }, [router, routeName, stableParams]);
57
+ const href = useMemo(
58
+ () => buildHref(router, routeName, stableParams),
59
+ [router, routeName, stableParams],
60
+ );
64
61
 
65
62
  const handleClick = useCallback(
66
63
  (evt: MouseEvent<HTMLAnchorElement>) => {
@@ -72,7 +69,7 @@ export const Link: FC<LinkProps> = memo(
72
69
  }
73
70
  }
74
71
 
75
- if (!shouldNavigate(evt) || target === "_blank") {
72
+ if (!shouldNavigate(evt.nativeEvent) || target === "_blank") {
76
73
  return;
77
74
  }
78
75
 
@@ -82,15 +79,10 @@ export const Link: FC<LinkProps> = memo(
82
79
  [onClick, target, router, routeName, stableParams, stableOptions],
83
80
  );
84
81
 
85
- const finalClassName = useMemo(() => {
86
- if (isActive && activeClassName) {
87
- return className
88
- ? `${className} ${activeClassName}`.trim()
89
- : activeClassName;
90
- }
91
-
92
- return className ?? undefined;
93
- }, [isActive, className, activeClassName]);
82
+ const finalClassName = useMemo(
83
+ () => buildActiveClassName(isActive, activeClassName, className),
84
+ [isActive, activeClassName, className],
85
+ );
94
86
 
95
87
  return (
96
88
  <a
@@ -1,6 +1,6 @@
1
1
  import { UNKNOWN_ROUTE } from "@real-router/core";
2
2
  import { startsWithSegment } from "@real-router/route-utils";
3
- import { Activity, Children, Fragment, isValidElement } from "react";
3
+ import { Activity, Children, Fragment, Suspense, isValidElement } from "react";
4
4
 
5
5
  import { Match, NotFound } from "./components";
6
6
 
@@ -45,16 +45,24 @@ function renderMatchElement(
45
45
  fullSegmentName: string,
46
46
  keepAlive: boolean,
47
47
  mode: "visible" | "hidden",
48
+ fallback?: ReactNode,
48
49
  ): ReactElement {
50
+ const content =
51
+ fallback === undefined ? (
52
+ matchChildren
53
+ ) : (
54
+ <Suspense fallback={fallback}>{matchChildren}</Suspense>
55
+ );
56
+
49
57
  if (keepAlive) {
50
58
  return (
51
59
  <Activity mode={mode} key={fullSegmentName}>
52
- {matchChildren}
60
+ {content}
53
61
  </Activity>
54
62
  );
55
63
  }
56
64
 
57
- return <Fragment key={fullSegmentName}>{matchChildren}</Fragment>;
65
+ return <Fragment key={fullSegmentName}>{content}</Fragment>;
58
66
  }
59
67
 
60
68
  export function buildRenderList(
@@ -77,6 +85,7 @@ export function buildRenderList(
77
85
  segment,
78
86
  exact = false,
79
87
  keepAlive = false,
88
+ fallback,
80
89
  } = child.props as MatchProps;
81
90
  const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;
82
91
  const isActive =
@@ -91,6 +100,7 @@ export function buildRenderList(
91
100
  fullSegmentName,
92
101
  keepAlive,
93
102
  "visible",
103
+ fallback,
94
104
  ),
95
105
  );
96
106
  } else if (keepAlive && hasBeenActivated.has(fullSegmentName)) {
@@ -100,6 +110,7 @@ export function buildRenderList(
100
110
  fullSegmentName,
101
111
  keepAlive,
102
112
  "hidden",
113
+ fallback,
103
114
  ),
104
115
  );
105
116
  }
@@ -14,6 +14,8 @@ export interface MatchProps {
14
14
  readonly exact?: boolean;
15
15
  /** Preserve component state when deactivated (React Activity). Defaults to false. */
16
16
  readonly keepAlive?: boolean;
17
+ /** Fallback content to show while children are suspended. */
18
+ readonly fallback?: ReactNode;
17
19
  /** Content to render when matched. */
18
20
  readonly children: ReactNode;
19
21
  }
@@ -1 +0,0 @@
1
- import{createContext as r,memo as e,useMemo as t,useCallback as o,useContext as i,useSyncExternalStore as n}from"react";import{getNavigator as a}from"@real-router/core";import{createActiveRouteSource as u,createRouteNodeSource as s,createTransitionSource as c,createRouteSource as l}from"@real-router/sources";import{jsx as m}from"react/jsx-runtime";import{getPluginApi as v}from"@real-router/core/api";import{getRouteUtils as f}from"@real-router/route-utils";var h=r(null),p=r(null),g=r(null),d=()=>{const r=i(p);if(!r)throw new Error("useRouter must be used within a RouterProvider");return r};function b(r){const e=d(),o=t(()=>s(e,r),[e,r]),{route:i,previousRoute:u}=n(o.subscribe,o.getSnapshot,o.getSnapshot),c=t(()=>a(e),[e]);return t(()=>({navigator:c,route:i,previousRoute:u}),[c,i,u])}var y=Object.freeze({}),N=Object.freeze({});function S(r){const e=JSON.stringify(r);return t(()=>r,[e])}var P=e(({routeName:r,routeParams:e=y,routeOptions:i=N,className:a,activeClassName:s="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:v,target:f,children:h,...p})=>{const g=d(),b=S(e),P=S(i),O=function(r,e,o=!1,i=!0){const a=d(),s=S(e),c=t(()=>u(a,r,s,{strict:o,ignoreQueryParams:i}),[a,r,s,o,i]);return n(c.subscribe,c.getSnapshot,c.getSnapshot)}(r,b,c,l),w=t(()=>"function"==typeof g.buildUrl?g.buildUrl(r,b):g.buildPath(r,b),[g,r,b]),R=o(e=>{v&&(v(e),e.defaultPrevented)||function(r){return!(0!==r.button||r.metaKey||r.altKey||r.ctrlKey||r.shiftKey)}(e)&&"_blank"!==f&&(e.preventDefault(),g.navigate(r,b,P).catch(()=>{}))},[v,f,g,r,b,P]),C=t(()=>O&&s?a?`${a} ${s}`.trim():s:a??void 0,[O,a,s]);return m("a",{...p,href:w,className:C,onClick:R,children:h})},function(r,e){return r.routeName===e.routeName&&r.className===e.className&&r.activeClassName===e.activeClassName&&r.activeStrict===e.activeStrict&&r.ignoreQueryParams===e.ignoreQueryParams&&r.onClick===e.onClick&&r.target===e.target&&r.style===e.style&&r.children===e.children&&JSON.stringify(r.routeParams)===JSON.stringify(e.routeParams)&&JSON.stringify(r.routeOptions)===JSON.stringify(e.routeOptions)});P.displayName="Link";var O=()=>{const r=i(g);if(!r)throw new Error("useNavigator must be used within a RouterProvider");return r},w=()=>{const r=d();return f(v(r).getTree())},R=()=>{const r=i(h);if(!r)throw new Error("useRoute must be used within a RouteProvider");return r};function C(){const r=d(),e=t(()=>c(r),[r]);return n(e.subscribe,e.getSnapshot,e.getSnapshot)}var k=({router:r,children:e})=>{const o=t(()=>a(r),[r]),i=t(()=>l(r),[r]),{route:u,previousRoute:s}=n(i.subscribe,i.getSnapshot,i.getSnapshot),c=t(()=>({navigator:o,route:u,previousRoute:s}),[o,u,s]);return m(p,{value:r,children:m(g,{value:o,children:m(h,{value:c,children:e})})})};export{P as Link,k as RouterProvider,O as useNavigator,R as useRoute,b as useRouteNode,w as useRouteUtils,d as useRouter,C as useRouterTransition};//# sourceMappingURL=chunk-BINM7GZZ.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"names":["useMemo","useSyncExternalStore","useContext","getNavigator","jsx"],"mappings":"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","file":"chunk-BINM7GZZ.mjs","sourcesContent":["// 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 { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\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","// 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/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","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(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/api\";\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","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\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/src/utils.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { MouseEvent } from "react";
2
-
3
- /**
4
- * Check if navigation should be handled by router
5
- */
6
- export function shouldNavigate(evt: MouseEvent): boolean {
7
- return (
8
- evt.button === 0 && // left click
9
- !evt.metaKey &&
10
- !evt.altKey &&
11
- !evt.ctrlKey &&
12
- !evt.shiftKey
13
- );
14
- }