@real-router/react 0.6.0 → 0.7.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
@@ -207,7 +207,7 @@ const Breadcrumbs = () => {
207
207
 
208
208
  #### `<Link routeName={string} routeParams={object} ...props>`
209
209
 
210
- Navigation link with automatic active state detection.\
210
+ Navigation link with automatic active state detection. Re-renders only when its own active status changes.\
211
211
  `routeName: string` — target route name\
212
212
  `routeParams?: Params` — route parameters\
213
213
  `routeOptions?: { reload?, replace? }` — navigation options\
@@ -229,19 +229,6 @@ import { Link } from "@real-router/react";
229
229
  </Link>;
230
230
  ```
231
231
 
232
- #### `<ConnectedLink ...props>`
233
-
234
- Same as `Link`, but re-renders on every route change.\
235
- Props: same as `Link`\
236
- [Wiki](https://github.com/greydragon888/real-router/wiki/ConnectedLink)
237
-
238
- #### `<BaseLink router={router} ...props>`
239
-
240
- Low-level link component. Requires router instance as prop.\
241
- `router: Router` — router instance\
242
- Props: same as `Link`\
243
- [Wiki](https://github.com/greydragon888/real-router/wiki/BaseLink)
244
-
245
232
  ---
246
233
 
247
234
  ## Migration from React 18
@@ -262,7 +249,7 @@ One import path change. API is identical.
262
249
  | API | react-router5 | @real-router/react |
263
250
  | --------------------------------------------- | ------------- | ------------------ |
264
251
  | `RouterProvider` | ✓ | ✓ |
265
- | `Link`, `ConnectedLink`, `BaseLink` | ✓ | ✓ |
252
+ | `Link` | ✓ | ✓ |
266
253
  | `useRouter`, `useRoute`, `useRouteNode` | ✓ | ✓ |
267
254
  | `withRouter`, `withRoute`, `routeNode` | ✓ | ❌ Use hooks |
268
255
  | `Router`, `Route`, `RouteNode` (render props) | ✓ | ❌ Use hooks |
@@ -1,7 +1,7 @@
1
- import { Router, Params, State, Navigator, NavigationOptions } from '@real-router/core';
1
+ import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
2
2
  export { Navigator } from '@real-router/core';
3
3
  import * as react from 'react';
4
- import { MouseEvent, ReactNode, FC, HTMLAttributes, MouseEventHandler } from 'react';
4
+ import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
5
5
  import { RouteUtils } from '@real-router/route-utils';
6
6
 
7
7
  interface RouteState<P extends Params = Params, MP extends Params = Params> {
@@ -11,39 +11,10 @@ interface RouteState<P extends Params = Params, MP extends Params = Params> {
11
11
  type RouteContext$1 = {
12
12
  navigator: Navigator;
13
13
  } & RouteState;
14
- interface BaseLinkProps$1 {
15
- [key: string]: unknown;
16
- router: Router;
17
- routeName: string;
18
- routeParams?: Params;
19
- routeOptions?: {
20
- [key: string]: unknown;
21
- reload?: boolean;
22
- replace?: boolean;
23
- };
24
- className?: string;
25
- activeClassName?: string;
26
- activeStrict?: boolean;
27
- ignoreQueryParams?: boolean;
28
- onClick?: (evt: MouseEvent<HTMLAnchorElement>) => void;
29
- target?: string;
30
- children?: ReactNode;
31
- previousRoute?: State;
32
- }
33
-
34
- /**
35
- * Optimized BaseLink component with memoization and performance improvements
36
- */
37
- declare const BaseLink: FC<BaseLinkProps$1>;
38
-
39
- interface BaseLinkProps<P extends Params = Params, MP extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
40
- router: Router;
14
+ interface LinkProps<P extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
41
15
  routeName: string;
42
- route?: State<P, MP> | undefined;
43
- previousRoute?: State | undefined;
44
16
  routeParams?: P;
45
17
  routeOptions?: NavigationOptions;
46
- className?: string;
47
18
  activeClassName?: string;
48
19
  activeStrict?: boolean;
49
20
  ignoreQueryParams?: boolean;
@@ -52,9 +23,7 @@ interface BaseLinkProps<P extends Params = Params, MP extends Params = Params> e
52
23
  onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
53
24
  }
54
25
 
55
- declare const Link: FC<Omit<BaseLinkProps, "router">>;
56
-
57
- declare const ConnectedLink: FC<Omit<BaseLinkProps, "router" | "route" | "previousRoute">>;
26
+ declare const Link: FC<LinkProps>;
58
27
 
59
28
  declare function useRouteNode(nodeName: string): RouteContext$1;
60
29
 
@@ -100,4 +69,4 @@ declare const RouteContext: react.Context<RouteContext$1 | null>;
100
69
  declare const RouterContext: react.Context<Router<object> | null>;
101
70
  declare const NavigatorContext: react.Context<Navigator | null>;
102
71
 
103
- export { BaseLink, type BaseLinkProps$1 as BaseLinkProps, ConnectedLink, Link, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter };
72
+ export { Link, type LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter };
package/dist/cjs/index.js CHANGED
@@ -1 +1 @@
1
- var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),u=require("@real-router/route-utils"),s=Object.freeze({}),a=Object.freeze({}),i=e.createContext(null),n=e.createContext(null),c=e.createContext(null),l=()=>{const t=e.use(n);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function v(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}function m(r,o,u=!1,s=!0){const a=l(),i=v(o),n=e.useMemo(()=>t.createActiveRouteSource(a,r,i,{strict:u,ignoreQueryParams:s}),[a,r,i,u,s]);return e.useSyncExternalStore(n.subscribe,n.getSnapshot,n.getSnapshot)}var p=e.memo(({routeName:t,routeParams:o=s,routeOptions:u=a,className:i,activeClassName:n="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:p,target:g,router:x,children:d,...h})=>{const N=v(o),R=v(u),S=m(t,N,c,l),f=e.useMemo(()=>"function"==typeof x.buildUrl?x.buildUrl(t,N):x.buildPath(t,N),[x,t,N]),y=e.useCallback(e=>{p&&(p(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==g&&(e.preventDefault(),x.navigate(t,N,R).catch(()=>{}))},[p,g,x,t,N,R]),b=e.useMemo(()=>S&&n?i?`${i} ${n}`.trim():n:i??void 0,[S,i,n]),{previousRoute:C,...P}=h;return r.jsx("a",{...P,href:f,className:b,onClick:y,"data-route":t,"data-active":S,children:d})},(e,t)=>e.router===t.router&&e.routeName===t.routeName&&JSON.stringify(e.routeParams)===JSON.stringify(t.routeParams)&&JSON.stringify(e.routeOptions)===JSON.stringify(t.routeOptions)&&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.children===t.children);p.displayName="BaseLink";var g=()=>{const t=e.use(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t};exports.BaseLink=p,exports.ConnectedLink=e=>{const t=l(),{route:o}=g(),{routeOptions:u,...s}=e;return r.jsx(p,{router:t,route:o,...s})},exports.Link=e=>{const t=l(),{route:o,previousRoute:u,routeOptions:s,...a}=e;return r.jsx(p,{router:t,...a})},exports.NavigatorContext=c,exports.RouteContext=i,exports.RouterContext=n,exports.RouterProvider=({router:u,children:s})=>{const a=e.useMemo(()=>o.getNavigator(u),[u]),l=e.useMemo(()=>t.createRouteSource(u),[u]),{route:v,previousRoute:m}=e.useSyncExternalStore(l.subscribe,l.getSnapshot,l.getSnapshot),p=e.useMemo(()=>({navigator:a,route:v,previousRoute:m}),[a,v,m]);return r.jsx(n,{value:u,children:r.jsx(c,{value:a,children:r.jsx(i,{value:p,children:s})})})},exports.useIsActiveRoute=m,exports.useNavigator=()=>{const t=e.use(c);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=g,exports.useRouteNode=function(r){const u=l(),s=e.useMemo(()=>t.createRouteNodeSource(u,r),[u,r]),{route:a,previousRoute:i}=e.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),n=e.useMemo(()=>o.getNavigator(u),[u]);return e.useMemo(()=>({navigator:n,route:a,previousRoute:i}),[n,a,i])},exports.useRouteUtils=()=>{const e=l();return u.getRouteUtils(o.getPluginApi(e).getTree())},exports.useRouter=l;//# sourceMappingURL=index.js.map
1
+ var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),u=require("@real-router/route-utils"),s=Object.freeze({}),a=Object.freeze({}),i=e.createContext(null),n=e.createContext(null),c=e.createContext(null),l=()=>{const t=e.use(n);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function m(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}function v(r,o,u=!1,s=!0){const a=l(),i=m(o),n=e.useMemo(()=>t.createActiveRouteSource(a,r,i,{strict:u,ignoreQueryParams:s}),[a,r,i,u,s]);return e.useSyncExternalStore(n.subscribe,n.getSnapshot,n.getSnapshot)}var g=e.memo(({routeName:t,routeParams:o=s,routeOptions:u=a,className:i,activeClassName:n="active",activeStrict:c=!1,ignoreQueryParams:g=!0,onClick:p,target:x,children:d,...h})=>{const N=l(),S=m(o),f=m(u),R=v(t,S,c,g),y=e.useMemo(()=>"function"==typeof N.buildUrl?N.buildUrl(t,S):N.buildPath(t,S),[N,t,S]),b=e.useCallback(e=>{p&&(p(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==x&&(e.preventDefault(),N.navigate(t,S,f).catch(()=>{}))},[p,x,N,t,S,f]),C=e.useMemo(()=>R&&n?i?`${i} ${n}`.trim():n:i??void 0,[R,i,n]);return r.jsx("a",{...h,href:y,className:C,onClick:b,children:d})},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)});g.displayName="Link",exports.Link=g,exports.NavigatorContext=c,exports.RouteContext=i,exports.RouterContext=n,exports.RouterProvider=({router:u,children:s})=>{const a=e.useMemo(()=>o.getNavigator(u),[u]),l=e.useMemo(()=>t.createRouteSource(u),[u]),{route:m,previousRoute:v}=e.useSyncExternalStore(l.subscribe,l.getSnapshot,l.getSnapshot),g=e.useMemo(()=>({navigator:a,route:m,previousRoute:v}),[a,m,v]);return r.jsx(n,{value:u,children:r.jsx(c,{value:a,children:r.jsx(i,{value:g,children:s})})})},exports.useIsActiveRoute=v,exports.useNavigator=()=>{const t=e.use(c);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.use(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=function(r){const u=l(),s=e.useMemo(()=>t.createRouteNodeSource(u,r),[u,r]),{route:a,previousRoute:i}=e.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),n=e.useMemo(()=>o.getNavigator(u),[u]);return e.useMemo(()=>({navigator:n,route:a,previousRoute:i}),[n,a,i])},exports.useRouteUtils=()=>{const e=l();return u.getRouteUtils(o.getPluginApi(e).getTree())},exports.useRouter=l;//# sourceMappingURL=index.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/BaseLink.tsx","../../src/components/Link.tsx","../../src/hooks/useRoute.tsx","../../src/components/ConnectedLink.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createRouteSource"],"mappings":"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","file":"index.js","sourcesContent":["// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","// packages/react/modules/components/BaseLink.tsx\n\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { BaseLinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\n/**\n * Optimized BaseLink component with memoization and performance improvements\n */\nexport const BaseLink: FC<BaseLinkProps> = 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 router,\n children,\n ...props\n }) => {\n // Stabilize object references to prevent unnecessary re-renders\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n // Use optimized hook for active state checking\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n // Build URL with memoization\n const href = useMemo(() => {\n // Use buildUrl if available (browser plugin installed)\n // Otherwise fall back to buildPath (e.g., in SSR or without browser plugin)\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 // Optimized click handler\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n // Call custom onClick if provided\n if (onClick) {\n onClick(evt);\n // Respect preventDefault from custom handler\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n // Check if we should handle navigation\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n // Prevent default link behavior\n evt.preventDefault();\n\n // Perform navigation (fire-and-forget)\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n // Build className efficiently\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 // Filter out previousRoute from props\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { previousRoute, ...restProps } = props;\n\n return (\n <a\n {...restProps}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n data-route={routeName} // For event delegation if needed\n data-active={isActive} // For CSS selectors if needed\n >\n {children}\n </a>\n );\n },\n (prevProps, nextProps) => {\n // Custom comparison for better memoization\n // Check if props that affect rendering have changed\n return (\n prevProps.router === nextProps.router &&\n prevProps.routeName === nextProps.routeName &&\n JSON.stringify(prevProps.routeParams) ===\n JSON.stringify(nextProps.routeParams) &&\n JSON.stringify(prevProps.routeOptions) ===\n JSON.stringify(nextProps.routeOptions) &&\n prevProps.className === nextProps.className &&\n prevProps.activeClassName === nextProps.activeClassName &&\n prevProps.activeStrict === nextProps.activeStrict &&\n prevProps.ignoreQueryParams === nextProps.ignoreQueryParams &&\n prevProps.onClick === nextProps.onClick &&\n prevProps.target === nextProps.target &&\n prevProps.children === nextProps.children\n );\n },\n);\n\nBaseLink.displayName = \"BaseLink\";\n","// packages/react/modules/components/Link.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const Link: FC<Omit<BaseLinkProps, \"router\">> = (props) => {\n const router = useRouter();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { route, previousRoute, routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} {...linkProps} />;\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/components/ConnectedLink.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRoute } from \"../hooks/useRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const ConnectedLink: FC<\n Omit<BaseLinkProps, \"router\" | \"route\" | \"previousRoute\">\n> = (props) => {\n const router = useRouter();\n const { route } = useRoute();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} route={route} {...linkProps} />;\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/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n}) => {\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"]}
1
+ {"version":3,"sources":["../../src/constants.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createRouteSource"],"mappings":"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","file":"index.js","sourcesContent":["// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","import { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(() => {\n if (typeof router.buildUrl === \"function\") {\n return router.buildUrl(routeName, stableParams);\n }\n\n return router.buildPath(routeName, stableParams);\n }, [router, routeName, stableParams]);\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(() => {\n if (isActive && activeClassName) {\n return className\n ? `${className} ${activeClassName}`.trim()\n : activeClassName;\n }\n\n return className ?? undefined;\n }, [isActive, className, activeClassName]);\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { 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,4 +1,4 @@
1
- export { BaseLink, BaseLinkProps, ConnectedLink, Link, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter } from './index.js';
1
+ export { Link, LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter } from './index.js';
2
2
  export { Navigator } from '@real-router/core';
3
3
  import 'react';
4
4
  import '@real-router/route-utils';
@@ -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/route-utils"),s=Object.freeze({}),a=Object.freeze({}),i=e.createContext(null),n=e.createContext(null),c=e.createContext(null),l=()=>{const t=e.use(n);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function v(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}function m(r,o,u=!1,s=!0){const a=l(),i=v(o),n=e.useMemo(()=>t.createActiveRouteSource(a,r,i,{strict:u,ignoreQueryParams:s}),[a,r,i,u,s]);return e.useSyncExternalStore(n.subscribe,n.getSnapshot,n.getSnapshot)}var p=e.memo(({routeName:t,routeParams:o=s,routeOptions:u=a,className:i,activeClassName:n="active",activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:p,target:g,router:x,children:d,...h})=>{const N=v(o),R=v(u),S=m(t,N,c,l),f=e.useMemo(()=>"function"==typeof x.buildUrl?x.buildUrl(t,N):x.buildPath(t,N),[x,t,N]),y=e.useCallback(e=>{p&&(p(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==g&&(e.preventDefault(),x.navigate(t,N,R).catch(()=>{}))},[p,g,x,t,N,R]),b=e.useMemo(()=>S&&n?i?`${i} ${n}`.trim():n:i??void 0,[S,i,n]),{previousRoute:C,...P}=h;return r.jsx("a",{...P,href:f,className:b,onClick:y,"data-route":t,"data-active":S,children:d})},(e,t)=>e.router===t.router&&e.routeName===t.routeName&&JSON.stringify(e.routeParams)===JSON.stringify(t.routeParams)&&JSON.stringify(e.routeOptions)===JSON.stringify(t.routeOptions)&&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.children===t.children);p.displayName="BaseLink";var g=()=>{const t=e.use(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t};exports.BaseLink=p,exports.ConnectedLink=e=>{const t=l(),{route:o}=g(),{routeOptions:u,...s}=e;return r.jsx(p,{router:t,route:o,...s})},exports.Link=e=>{const t=l(),{route:o,previousRoute:u,routeOptions:s,...a}=e;return r.jsx(p,{router:t,...a})},exports.NavigatorContext=c,exports.RouteContext=i,exports.RouterContext=n,exports.RouterProvider=({router:u,children:s})=>{const a=e.useMemo(()=>o.getNavigator(u),[u]),l=e.useMemo(()=>t.createRouteSource(u),[u]),{route:v,previousRoute:m}=e.useSyncExternalStore(l.subscribe,l.getSnapshot,l.getSnapshot),p=e.useMemo(()=>({navigator:a,route:v,previousRoute:m}),[a,v,m]);return r.jsx(n,{value:u,children:r.jsx(c,{value:a,children:r.jsx(i,{value:p,children:s})})})},exports.useIsActiveRoute=m,exports.useNavigator=()=>{const t=e.use(c);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=g,exports.useRouteNode=function(r){const u=l(),s=e.useMemo(()=>t.createRouteNodeSource(u,r),[u,r]),{route:a,previousRoute:i}=e.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),n=e.useMemo(()=>o.getNavigator(u),[u]);return e.useMemo(()=>({navigator:n,route:a,previousRoute:i}),[n,a,i])},exports.useRouteUtils=()=>{const e=l();return u.getRouteUtils(o.getPluginApi(e).getTree())},exports.useRouter=l;//# sourceMappingURL=legacy.js.map
1
+ var e=require("react"),t=require("@real-router/sources"),r=require("react/jsx-runtime"),o=require("@real-router/core"),u=require("@real-router/route-utils"),s=Object.freeze({}),a=Object.freeze({}),i=e.createContext(null),n=e.createContext(null),c=e.createContext(null),l=()=>{const t=e.use(n);if(!t)throw new Error("useRouter must be used within a RouterProvider");return t};function m(t){const r=JSON.stringify(t);return e.useMemo(()=>t,[r])}function v(r,o,u=!1,s=!0){const a=l(),i=m(o),n=e.useMemo(()=>t.createActiveRouteSource(a,r,i,{strict:u,ignoreQueryParams:s}),[a,r,i,u,s]);return e.useSyncExternalStore(n.subscribe,n.getSnapshot,n.getSnapshot)}var g=e.memo(({routeName:t,routeParams:o=s,routeOptions:u=a,className:i,activeClassName:n="active",activeStrict:c=!1,ignoreQueryParams:g=!0,onClick:p,target:x,children:d,...h})=>{const N=l(),S=m(o),f=m(u),R=v(t,S,c,g),y=e.useMemo(()=>"function"==typeof N.buildUrl?N.buildUrl(t,S):N.buildPath(t,S),[N,t,S]),b=e.useCallback(e=>{p&&(p(e),e.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)&&"_blank"!==x&&(e.preventDefault(),N.navigate(t,S,f).catch(()=>{}))},[p,x,N,t,S,f]),C=e.useMemo(()=>R&&n?i?`${i} ${n}`.trim():n:i??void 0,[R,i,n]);return r.jsx("a",{...h,href:y,className:C,onClick:b,children:d})},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)});g.displayName="Link",exports.Link=g,exports.NavigatorContext=c,exports.RouteContext=i,exports.RouterContext=n,exports.RouterProvider=({router:u,children:s})=>{const a=e.useMemo(()=>o.getNavigator(u),[u]),l=e.useMemo(()=>t.createRouteSource(u),[u]),{route:m,previousRoute:v}=e.useSyncExternalStore(l.subscribe,l.getSnapshot,l.getSnapshot),g=e.useMemo(()=>({navigator:a,route:m,previousRoute:v}),[a,m,v]);return r.jsx(n,{value:u,children:r.jsx(c,{value:a,children:r.jsx(i,{value:g,children:s})})})},exports.useIsActiveRoute=v,exports.useNavigator=()=>{const t=e.use(c);if(!t)throw new Error("useNavigator must be used within a RouterProvider");return t},exports.useRoute=()=>{const t=e.use(i);if(!t)throw new Error("useRoute must be used within a RouteProvider");return t},exports.useRouteNode=function(r){const u=l(),s=e.useMemo(()=>t.createRouteNodeSource(u,r),[u,r]),{route:a,previousRoute:i}=e.useSyncExternalStore(s.subscribe,s.getSnapshot,s.getSnapshot),n=e.useMemo(()=>o.getNavigator(u),[u]);return e.useMemo(()=>({navigator:n,route:a,previousRoute:i}),[n,a,i])},exports.useRouteUtils=()=>{const e=l();return u.getRouteUtils(o.getPluginApi(e).getTree())},exports.useRouter=l;//# 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/BaseLink.tsx","../../src/components/Link.tsx","../../src/hooks/useRoute.tsx","../../src/components/ConnectedLink.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","createRouteSource"],"mappings":";;;AAKO,IAAM,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAKrC,IAAM,aAAA,GAAgB,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;ACHtC,IAAM,YAAA,GAAeA,oBAAuC,IAAI;AAEhE,IAAM,aAAA,GAAgBA,oBAA6B,IAAI;AAEvD,IAAM,gBAAA,GAAmBA,oBAAgC,IAAI;;;ACH7D,IAAM,YAAY,MAAc;AACrC,EAAA,MAAM,MAAA,GAASC,UAAI,aAAa,CAAA;AAEhC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,MAAA;AACT;ACMO,SAAS,eAAkB,KAAA,EAAa;AAC7C,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAIvC,EAAA,OAAOC,aAAA,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,MACEC,+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,OAAOC,0BAAA;AAAA,IACL,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AACF;;;AC9BO,SAAS,eAAe,GAAA,EAA0B;AACvD,EAAA,OACE,IAAI,MAAA,KAAW,CAAA;AAAA,EACf,CAAC,GAAA,CAAI,OAAA,IACL,CAAC,GAAA,CAAI,UACL,CAAC,GAAA,CAAI,OAAA,IACL,CAAC,GAAA,CAAI,QAAA;AAET;ACEO,IAAM,QAAA,GAA8BC,UAAA;AAAA,EACzC,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,MAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,GACL,KAAM;AAEJ,IAAA,MAAM,YAAA,GAAe,eAAe,WAAW,CAAA;AAC/C,IAAA,MAAM,aAAA,GAAgB,eAAe,YAAY,CAAA;AAGjD,IAAA,MAAM,QAAA,GAAW,gBAAA;AAAA,MACf,SAAA;AAAA,MACA,YAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAGA,IAAA,MAAM,IAAA,GAAOH,cAAQ,MAAM;AAGzB,MAAA,IAAI,OAAO,MAAA,CAAO,QAAA,KAAa,UAAA,EAAY;AACzC,QAAA,OAAO,MAAA,CAAO,QAAA,CAAS,SAAA,EAAW,YAAY,CAAA;AAAA,MAChD;AAEA,MAAA,OAAO,MAAA,CAAO,SAAA,CAAU,SAAA,EAAW,YAAY,CAAA;AAAA,IACjD,CAAA,EAAG,CAAC,MAAA,EAAQ,SAAA,EAAW,YAAY,CAAC,CAAA;AAGpC,IAAA,MAAM,WAAA,GAAcI,iBAAA;AAAA,MAClB,CAAC,GAAA,KAAuC;AAEtC,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAA,CAAQ,GAAG,CAAA;AAEX,UAAA,IAAI,IAAI,gBAAA,EAAkB;AACxB,YAAA;AAAA,UACF;AAAA,QACF;AAGA,QAAA,IAAI,CAAC,cAAA,CAAe,GAAG,CAAA,IAAK,WAAW,QAAA,EAAU;AAC/C,UAAA;AAAA,QACF;AAGA,QAAA,GAAA,CAAI,cAAA,EAAe;AAGnB,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;AAGA,IAAA,MAAM,cAAA,GAAiBJ,cAAQ,MAAM;AACnC,MAAA,IAAI,YAAY,eAAA,EAAiB;AAC/B,QAAA,OAAO,YACH,CAAA,EAAG,SAAS,IAAI,eAAe,CAAA,CAAA,CAAG,MAAK,GACvC,eAAA;AAAA,MACN;AAEA,MAAA,OAAO,SAAA,IAAa,MAAA;AAAA,IACtB,CAAA,EAAG,CAAC,QAAA,EAAU,SAAA,EAAW,eAAe,CAAC,CAAA;AAIzC,IAAA,MAAM,EAAE,aAAA,EAAe,GAAG,SAAA,EAAU,GAAI,KAAA;AAExC,IAAA,uBACEK,cAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACE,GAAG,SAAA;AAAA,QACJ,IAAA;AAAA,QACA,SAAA,EAAW,cAAA;AAAA,QACX,OAAA,EAAS,WAAA;AAAA,QACT,YAAA,EAAY,SAAA;AAAA,QACZ,aAAA,EAAa,QAAA;AAAA,QAEZ;AAAA;AAAA,KACH;AAAA,EAEJ,CAAA;AAAA,EACA,CAAC,WAAW,SAAA,KAAc;AAGxB,IAAA,OACE,SAAA,CAAU,MAAA,KAAW,SAAA,CAAU,MAAA,IAC/B,SAAA,CAAU,cAAc,SAAA,CAAU,SAAA,IAClC,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,WAAW,MAClC,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,WAAW,CAAA,IACtC,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,YAAY,CAAA,KACnC,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,YAAY,KACvC,SAAA,CAAU,SAAA,KAAc,SAAA,CAAU,SAAA,IAClC,SAAA,CAAU,eAAA,KAAoB,UAAU,eAAA,IACxC,SAAA,CAAU,YAAA,KAAiB,SAAA,CAAU,YAAA,IACrC,SAAA,CAAU,sBAAsB,SAAA,CAAU,iBAAA,IAC1C,SAAA,CAAU,OAAA,KAAY,SAAA,CAAU,OAAA,IAChC,SAAA,CAAU,MAAA,KAAW,SAAA,CAAU,MAAA,IAC/B,SAAA,CAAU,QAAA,KAAa,SAAA,CAAU,QAAA;AAAA,EAErC;AACF;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA;ACxHhB,IAAM,IAAA,GAA0C,CAAC,KAAA,KAAU;AAChE,EAAA,MAAM,SAAS,SAAA,EAAU;AAGzB,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAe,YAAA,EAAc,GAAG,WAAU,GAAI,KAAA;AAE7D,EAAA,uBAAOA,cAAAA,CAAC,QAAA,EAAA,EAAS,MAAA,EAAiB,GAAG,SAAA,EAAW,CAAA;AAClD;ACPO,IAAM,WAAW,MAAwB;AAC9C,EAAA,MAAM,YAAA,GAAeN,UAAI,YAAY,CAAA;AAErC,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,YAAA;AACT;ACPO,IAAM,aAAA,GAET,CAAC,KAAA,KAAU;AACb,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,QAAA,EAAS;AAG3B,EAAA,MAAM,EAAE,YAAA,EAAc,GAAG,SAAA,EAAU,GAAI,KAAA;AAEvC,EAAA,uBAAOM,cAAAA,CAAC,QAAA,EAAA,EAAS,MAAA,EAAgB,KAAA,EAAe,GAAG,SAAA,EAAW,CAAA;AAChE;ACXO,SAAS,aAAa,QAAA,EAAgC;AAC3D,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,KAAA,GAAQL,aAAAA;AAAA,IACZ,MAAMM,6BAAA,CAAsB,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5C,CAAC,QAAQ,QAAQ;AAAA,GACnB;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAIJ,0BAAAA;AAAA,IAC/B,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AAEA,EAAA,MAAM,SAAA,GAAYF,cAAQ,MAAMO,iBAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAE9D,EAAA,OAAOP,aAAAA;AAAA,IACL,OAAqB,EAAE,SAAA,EAAW,KAAA,EAAO,aAAA,EAAc,CAAA;AAAA,IACvD,CAAC,SAAA,EAAW,KAAA,EAAO,aAAa;AAAA,GAClC;AACF;ACpBO,IAAM,eAAe,MAAiB;AAC3C,EAAA,MAAM,SAAA,GAAYD,UAAI,gBAAgB,CAAA;AAEtC,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,OAAOS,wBAAA,CAAcC,iBAAA,CAAa,MAAM,CAAA,CAAE,SAAS,CAAA;AACrD;ACrBO,IAAM,iBAAyC,CAAC;AAAA,EACrD,MAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,SAAA,GAAYT,cAAQ,MAAMO,iBAAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAK9D,EAAA,MAAM,KAAA,GAAQP,cAAQ,MAAMU,yBAAA,CAAkB,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAC/D,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAIR,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,uBACEK,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":"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 { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","// packages/react/modules/components/BaseLink.tsx\n\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { BaseLinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\n/**\n * Optimized BaseLink component with memoization and performance improvements\n */\nexport const BaseLink: FC<BaseLinkProps> = 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 router,\n children,\n ...props\n }) => {\n // Stabilize object references to prevent unnecessary re-renders\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n // Use optimized hook for active state checking\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n // Build URL with memoization\n const href = useMemo(() => {\n // Use buildUrl if available (browser plugin installed)\n // Otherwise fall back to buildPath (e.g., in SSR or without browser plugin)\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 // Optimized click handler\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n // Call custom onClick if provided\n if (onClick) {\n onClick(evt);\n // Respect preventDefault from custom handler\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n // Check if we should handle navigation\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n // Prevent default link behavior\n evt.preventDefault();\n\n // Perform navigation (fire-and-forget)\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n // Build className efficiently\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 // Filter out previousRoute from props\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { previousRoute, ...restProps } = props;\n\n return (\n <a\n {...restProps}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n data-route={routeName} // For event delegation if needed\n data-active={isActive} // For CSS selectors if needed\n >\n {children}\n </a>\n );\n },\n (prevProps, nextProps) => {\n // Custom comparison for better memoization\n // Check if props that affect rendering have changed\n return (\n prevProps.router === nextProps.router &&\n prevProps.routeName === nextProps.routeName &&\n JSON.stringify(prevProps.routeParams) ===\n JSON.stringify(nextProps.routeParams) &&\n JSON.stringify(prevProps.routeOptions) ===\n JSON.stringify(nextProps.routeOptions) &&\n prevProps.className === nextProps.className &&\n prevProps.activeClassName === nextProps.activeClassName &&\n prevProps.activeStrict === nextProps.activeStrict &&\n prevProps.ignoreQueryParams === nextProps.ignoreQueryParams &&\n prevProps.onClick === nextProps.onClick &&\n prevProps.target === nextProps.target &&\n prevProps.children === nextProps.children\n );\n },\n);\n\nBaseLink.displayName = \"BaseLink\";\n","// packages/react/modules/components/Link.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const Link: FC<Omit<BaseLinkProps, \"router\">> = (props) => {\n const router = useRouter();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { route, previousRoute, routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} {...linkProps} />;\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/components/ConnectedLink.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRoute } from \"../hooks/useRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const ConnectedLink: FC<\n Omit<BaseLinkProps, \"router\" | \"route\" | \"previousRoute\">\n> = (props) => {\n const router = useRouter();\n const { route } = useRoute();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} route={route} {...linkProps} />;\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/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n}) => {\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"]}
1
+ {"version":3,"sources":["../../src/constants.ts","../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["createContext","use","useMemo","createActiveRouteSource","useSyncExternalStore","memo","useCallback","jsx","createRouteNodeSource","getNavigator","getRouteUtils","getPluginApi","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 { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","import { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(() => {\n if (typeof router.buildUrl === \"function\") {\n return router.buildUrl(routeName, stableParams);\n }\n\n return router.buildPath(routeName, stableParams);\n }, [router, routeName, stableParams]);\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(() => {\n if (isActive && activeClassName) {\n return className\n ? `${className} ${activeClassName}`.trim()\n : activeClassName;\n }\n\n return className ?? undefined;\n }, [isActive, className, activeClassName]);\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { 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 +1 @@
1
- {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/constants.ts":{"bytes":225,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/BaseLink.tsx":{"bytes":4053,"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/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":511,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./BaseLink"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/ConnectedLink.tsx":{"bytes":631,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./BaseLink"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"../hooks/useRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":782,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./components/BaseLink"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/ConnectedLink.tsx","kind":"import-statement","original":"./components/ConnectedLink"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":782,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./components/BaseLink"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/ConnectedLink.tsx","kind":"import-statement","original":"./components/ConnectedLink"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":18253},"dist/cjs/index.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","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":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":["BaseLink","ConnectedLink","Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/index.ts","inputs":{"src/components/BaseLink.tsx":{"bytesInOutput":2607},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/index.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":243},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/components/ConnectedLink.tsx":{"bytesInOutput":269},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7657},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":18253},"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":"react/jsx-runtime","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":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":["BaseLink","ConnectedLink","Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/legacy.ts","inputs":{"src/components/BaseLink.tsx":{"bytesInOutput":2607},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/legacy.ts":{"bytesInOutput":0},"src/components/Link.tsx":{"bytesInOutput":243},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/components/ConnectedLink.tsx":{"bytesInOutput":269},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7657}}}
1
+ {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/constants.ts":{"bytes":225,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/RouterProvider.tsx":{"bytes":1380,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":666,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"},"src/legacy.ts":{"bytes":666,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"},{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":15376},"dist/cjs/index.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/index.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/index.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":6845},"dist/cjs/legacy.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":15376},"dist/cjs/legacy.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/legacy.ts","inputs":{"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/context.ts":{"bytesInOutput":164},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/utils.ts":{"bytesInOutput":140},"src/legacy.ts":{"bytesInOutput":0},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":6845}}}
@@ -0,0 +1 @@
1
+ import{createContext as e,memo as r,useMemo as t,useCallback as o,use as i,useSyncExternalStore as n}from"react";import{createActiveRouteSource as a,createRouteNodeSource as u,createRouteSource as s}from"@real-router/sources";import{jsx as c}from"react/jsx-runtime";import{getNavigator as l,getPluginApi as m}from"@real-router/core";import{getRouteUtils as v}from"@real-router/route-utils";var f=e(null),h=e(null),g=e(null),p=()=>{const e=i(h);if(!e)throw new Error("useRouter must be used within a RouterProvider");return e};function d(e){const r=JSON.stringify(e);return t(()=>e,[r])}function y(e,r,o=!1,i=!0){const u=p(),s=d(r),c=t(()=>a(u,e,s,{strict:o,ignoreQueryParams:i}),[u,e,s,o,i]);return n(c.subscribe,c.getSnapshot,c.getSnapshot)}var N=Object.freeze({}),b=Object.freeze({}),S=r(({routeName:e,routeParams:r=N,routeOptions:i=b,className:n,activeClassName:a="active",activeStrict:u=!1,ignoreQueryParams:s=!0,onClick:l,target:m,children:v,...f})=>{const h=p(),g=d(r),S=d(i),P=y(e,g,u,s),O=t(()=>"function"==typeof h.buildUrl?h.buildUrl(e,g):h.buildPath(e,g),[h,e,g]),w=o(r=>{l&&(l(r),r.defaultPrevented)||function(e){return!(0!==e.button||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(r)&&"_blank"!==m&&(r.preventDefault(),h.navigate(e,g,S).catch(()=>{}))},[l,m,h,e,g,S]),R=t(()=>P&&a?n?`${n} ${a}`.trim():a:n??void 0,[P,n,a]);return c("a",{...f,href:O,className:R,onClick:w,children:v})},function(e,r){return e.routeName===r.routeName&&e.className===r.className&&e.activeClassName===r.activeClassName&&e.activeStrict===r.activeStrict&&e.ignoreQueryParams===r.ignoreQueryParams&&e.onClick===r.onClick&&e.target===r.target&&e.style===r.style&&e.children===r.children&&JSON.stringify(e.routeParams)===JSON.stringify(r.routeParams)&&JSON.stringify(e.routeOptions)===JSON.stringify(r.routeOptions)});function P(e){const r=p(),o=t(()=>u(r,e),[r,e]),{route:i,previousRoute:a}=n(o.subscribe,o.getSnapshot,o.getSnapshot),s=t(()=>l(r),[r]);return t(()=>({navigator:s,route:i,previousRoute:a}),[s,i,a])}S.displayName="Link";var O=()=>{const e=i(f);if(!e)throw new Error("useRoute must be used within a RouteProvider");return e},w=()=>{const e=i(g);if(!e)throw new Error("useNavigator must be used within a RouterProvider");return e},R=()=>{const e=p();return v(m(e).getTree())},C=({router:e,children:r})=>{const o=t(()=>l(e),[e]),i=t(()=>s(e),[e]),{route:a,previousRoute:u}=n(i.subscribe,i.getSnapshot,i.getSnapshot),m=t(()=>({navigator:o,route:a,previousRoute:u}),[o,a,u]);return c(h,{value:e,children:c(g,{value:o,children:c(f,{value:m,children:r})})})};export{S as Link,g as NavigatorContext,f as RouteContext,h as RouterContext,C as RouterProvider,y as useIsActiveRoute,w as useNavigator,O as useRoute,P as useRouteNode,R as useRouteUtils,p as useRouter};//# sourceMappingURL=chunk-GKE5JASO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/constants.ts","../../src/utils.ts","../../src/components/Link.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["useMemo","useSyncExternalStore","use","getNavigator","jsx"],"mappings":";AAOO,IAAM,YAAA,GAAe,cAAuC,IAAI;AAEhE,IAAM,aAAA,GAAgB,cAA6B,IAAI;AAEvD,IAAM,gBAAA,GAAmB,cAAgC,IAAI;ACH7D,IAAM,YAAY,MAAc;AACrC,EAAA,MAAM,MAAA,GAAS,IAAI,aAAa,CAAA;AAEhC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,MAAA;AACT;ACMO,SAAS,eAAkB,KAAA,EAAa;AAC7C,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAIvC,EAAA,OAAO,OAAA,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,OAAAA;AAAA,IACZ,MACE,uBAAA,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,OAAO,oBAAA;AAAA,IACL,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AACF;;;AC9BO,IAAM,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAKrC,IAAM,aAAA,GAAgB,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;;;ACLtC,SAAS,eAAe,GAAA,EAA0B;AACvD,EAAA,OACE,IAAI,MAAA,KAAW,CAAA;AAAA,EACf,CAAC,GAAA,CAAI,OAAA,IACL,CAAC,GAAA,CAAI,UACL,CAAC,GAAA,CAAI,OAAA,IACL,CAAC,GAAA,CAAI,QAAA;AAET;ACFA,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,GAAsB,IAAA;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,GAAOA,QAAQ,MAAM;AACzB,MAAA,IAAI,OAAO,MAAA,CAAO,QAAA,KAAa,UAAA,EAAY;AACzC,QAAA,OAAO,MAAA,CAAO,QAAA,CAAS,SAAA,EAAW,YAAY,CAAA;AAAA,MAChD;AAEA,MAAA,OAAO,MAAA,CAAO,SAAA,CAAU,SAAA,EAAW,YAAY,CAAA;AAAA,IACjD,CAAA,EAAG,CAAC,MAAA,EAAQ,SAAA,EAAW,YAAY,CAAC,CAAA;AAEpC,IAAA,MAAM,WAAA,GAAc,WAAA;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,CAAC,cAAA,CAAe,GAAG,CAAA,IAAK,WAAW,QAAA,EAAU;AAC/C,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,GAAiBA,QAAQ,MAAM;AACnC,MAAA,IAAI,YAAY,eAAA,EAAiB;AAC/B,QAAA,OAAO,YACH,CAAA,EAAG,SAAS,IAAI,eAAe,CAAA,CAAA,CAAG,MAAK,GACvC,eAAA;AAAA,MACN;AAEA,MAAA,OAAO,SAAA,IAAa,MAAA;AAAA,IACtB,CAAA,EAAG,CAAC,QAAA,EAAU,SAAA,EAAW,eAAe,CAAC,CAAA;AAEzC,IAAA,uBACE,GAAA;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;ACpGZ,SAAS,aAAa,QAAA,EAAgC;AAC3D,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA,MAAM,KAAA,GAAQA,OAAAA;AAAA,IACZ,MAAM,qBAAA,CAAsB,MAAA,EAAQ,QAAQ,CAAA;AAAA,IAC5C,CAAC,QAAQ,QAAQ;AAAA,GACnB;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAIC,oBAAAA;AAAA,IAC/B,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AAEA,EAAA,MAAM,SAAA,GAAYD,QAAQ,MAAM,YAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAE9D,EAAA,OAAOA,OAAAA;AAAA,IACL,OAAqB,EAAE,SAAA,EAAW,KAAA,EAAO,aAAA,EAAc,CAAA;AAAA,IACvD,CAAC,SAAA,EAAW,KAAA,EAAO,aAAa;AAAA,GAClC;AACF;ACpBO,IAAM,WAAW,MAAwB;AAC9C,EAAA,MAAM,YAAA,GAAeE,IAAI,YAAY,CAAA;AAErC,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,YAAA;AACT;ACRO,IAAM,eAAe,MAAiB;AAC3C,EAAA,MAAM,SAAA,GAAYA,IAAI,gBAAgB,CAAA;AAEtC,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,OAAO,aAAA,CAAc,YAAA,CAAa,MAAM,CAAA,CAAE,SAAS,CAAA;AACrD;ACrBO,IAAM,iBAAyC,CAAC;AAAA,EACrD,MAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,SAAA,GAAYF,QAAQ,MAAMG,YAAAA,CAAa,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAK9D,EAAA,MAAM,KAAA,GAAQH,QAAQ,MAAM,iBAAA,CAAkB,MAAM,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAC/D,EAAA,MAAM,EAAE,KAAA,EAAO,aAAA,EAAc,GAAIC,oBAAAA;AAAA,IAC/B,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AAEA,EAAA,MAAM,iBAAA,GAAoBD,OAAAA;AAAA,IACxB,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,aAAA,EAAc,CAAA;AAAA,IACzC,CAAC,SAAA,EAAW,KAAA,EAAO,aAAa;AAAA,GAClC;AAEA,EAAA,uBACEI,GAAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAO,MAAA,EACpB,0BAAAA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,KAAA,EAAO,SAAA,EACvB,0BAAAA,GAAAA,CAAC,YAAA,EAAA,EAAa,OAAO,iBAAA,EAAoB,QAAA,EAAS,GACpD,CAAA,EACF,CAAA;AAEJ","file":"chunk-GKE5JASO.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 { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","// 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","import type { MouseEvent } from \"react\";\n\n/**\n * Check if navigation should be handled by router\n */\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 && // left click\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n","import { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(() => {\n if (typeof router.buildUrl === \"function\") {\n return router.buildUrl(routeName, stableParams);\n }\n\n return router.buildPath(routeName, stableParams);\n }, [router, routeName, stableParams]);\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(() => {\n if (isActive && activeClassName) {\n return className\n ? `${className} ${activeClassName}`.trim()\n : activeClassName;\n }\n\n return className ?? undefined;\n }, [isActive, className, activeClassName]);\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { 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,7 +1,7 @@
1
- import { Router, Params, State, Navigator, NavigationOptions } from '@real-router/core';
1
+ import { Params, NavigationOptions, Navigator, State, Router } from '@real-router/core';
2
2
  export { Navigator } from '@real-router/core';
3
3
  import * as react from 'react';
4
- import { MouseEvent, ReactNode, FC, HTMLAttributes, MouseEventHandler } from 'react';
4
+ import { HTMLAttributes, MouseEventHandler, FC, ReactNode } from 'react';
5
5
  import { RouteUtils } from '@real-router/route-utils';
6
6
 
7
7
  interface RouteState<P extends Params = Params, MP extends Params = Params> {
@@ -11,39 +11,10 @@ interface RouteState<P extends Params = Params, MP extends Params = Params> {
11
11
  type RouteContext$1 = {
12
12
  navigator: Navigator;
13
13
  } & RouteState;
14
- interface BaseLinkProps$1 {
15
- [key: string]: unknown;
16
- router: Router;
17
- routeName: string;
18
- routeParams?: Params;
19
- routeOptions?: {
20
- [key: string]: unknown;
21
- reload?: boolean;
22
- replace?: boolean;
23
- };
24
- className?: string;
25
- activeClassName?: string;
26
- activeStrict?: boolean;
27
- ignoreQueryParams?: boolean;
28
- onClick?: (evt: MouseEvent<HTMLAnchorElement>) => void;
29
- target?: string;
30
- children?: ReactNode;
31
- previousRoute?: State;
32
- }
33
-
34
- /**
35
- * Optimized BaseLink component with memoization and performance improvements
36
- */
37
- declare const BaseLink: FC<BaseLinkProps$1>;
38
-
39
- interface BaseLinkProps<P extends Params = Params, MP extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
40
- router: Router;
14
+ interface LinkProps<P extends Params = Params> extends HTMLAttributes<HTMLAnchorElement> {
41
15
  routeName: string;
42
- route?: State<P, MP> | undefined;
43
- previousRoute?: State | undefined;
44
16
  routeParams?: P;
45
17
  routeOptions?: NavigationOptions;
46
- className?: string;
47
18
  activeClassName?: string;
48
19
  activeStrict?: boolean;
49
20
  ignoreQueryParams?: boolean;
@@ -52,9 +23,7 @@ interface BaseLinkProps<P extends Params = Params, MP extends Params = Params> e
52
23
  onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
53
24
  }
54
25
 
55
- declare const Link: FC<Omit<BaseLinkProps, "router">>;
56
-
57
- declare const ConnectedLink: FC<Omit<BaseLinkProps, "router" | "route" | "previousRoute">>;
26
+ declare const Link: FC<LinkProps>;
58
27
 
59
28
  declare function useRouteNode(nodeName: string): RouteContext$1;
60
29
 
@@ -100,4 +69,4 @@ declare const RouteContext: react.Context<RouteContext$1 | null>;
100
69
  declare const RouterContext: react.Context<Router<object> | null>;
101
70
  declare const NavigatorContext: react.Context<Navigator | null>;
102
71
 
103
- export { BaseLink, type BaseLinkProps$1 as BaseLinkProps, ConnectedLink, Link, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter };
72
+ export { Link, type LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter };
@@ -1 +1 @@
1
- export{BaseLink,ConnectedLink,Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter}from"./chunk-WC4N3BP2.mjs";//# sourceMappingURL=index.mjs.map
1
+ export{Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter}from"./chunk-GKE5JASO.mjs";//# sourceMappingURL=index.mjs.map
@@ -1,4 +1,4 @@
1
- export { BaseLink, BaseLinkProps, ConnectedLink, Link, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter } from './index.mjs';
1
+ export { Link, LinkProps, NavigatorContext, RouteContext, RouterContext, RouterProvider, useIsActiveRoute, useNavigator, useRoute, useRouteNode, useRouteUtils, useRouter } from './index.mjs';
2
2
  export { Navigator } from '@real-router/core';
3
3
  import 'react';
4
4
  import '@real-router/route-utils';
@@ -1 +1 @@
1
- export{BaseLink,ConnectedLink,Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter}from"./chunk-WC4N3BP2.mjs";//# sourceMappingURL=legacy.mjs.map
1
+ export{Link,NavigatorContext,RouteContext,RouterContext,RouterProvider,useIsActiveRoute,useNavigator,useRoute,useRouteNode,useRouteUtils,useRouter}from"./chunk-GKE5JASO.mjs";//# sourceMappingURL=legacy.mjs.map
@@ -1 +1 @@
1
- {"inputs":{"src/constants.ts":{"bytes":225,"imports":[],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[],"format":"esm"},"src/components/BaseLink.tsx":{"bytes":4053,"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/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/components/Link.tsx":{"bytes":511,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./BaseLink"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/components/ConnectedLink.tsx":{"bytes":631,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./BaseLink"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"../hooks/useRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/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":782,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./components/BaseLink"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/ConnectedLink.tsx","kind":"import-statement","original":"./components/ConnectedLink"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"},"src/legacy.ts":{"bytes":782,"imports":[{"path":"src/components/BaseLink.tsx","kind":"import-statement","original":"./components/BaseLink"},{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/components/ConnectedLink.tsx","kind":"import-statement","original":"./components/ConnectedLink"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-WC4N3BP2.mjs","kind":"import-statement"}],"exports":["BaseLink","ConnectedLink","Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":454},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-WC4N3BP2.mjs","kind":"import-statement"}],"exports":["BaseLink","ConnectedLink","Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":454},"dist/esm/chunk-WC4N3BP2.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":18251},"dist/esm/chunk-WC4N3BP2.mjs":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","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":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","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":["BaseLink","ConnectedLink","Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"inputs":{"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/components/BaseLink.tsx":{"bytesInOutput":2607},"src/constants.ts":{"bytesInOutput":77},"src/utils.ts":{"bytesInOutput":140},"src/components/Link.tsx":{"bytesInOutput":243},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/components/ConnectedLink.tsx":{"bytesInOutput":269},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":7630}}}
1
+ {"inputs":{"src/constants.ts":{"bytes":225,"imports":[],"format":"esm"},"src/context.ts":{"bytes":416,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouter.tsx":{"bytes":364,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useStableValue.tsx":{"bytes":976,"imports":[{"path":"react","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useIsActiveRoute.tsx":{"bytes":1060,"imports":[{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"./useStableValue"}],"format":"esm"},"src/utils.ts":{"bytes":293,"imports":[],"format":"esm"},"src/components/Link.tsx":{"bytes":2900,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"../constants"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"../hooks/useIsActiveRoute"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"../hooks/useRouter"},{"path":"src/hooks/useStableValue.tsx","kind":"import-statement","original":"../hooks/useStableValue"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/useRouteNode.tsx":{"bytes":837,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/hooks/useRoute.tsx":{"bytes":403,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useNavigator.tsx":{"bytes":394,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/context.ts","kind":"import-statement","original":"../context"}],"format":"esm"},"src/hooks/useRouteUtils.tsx":{"bytes":977,"imports":[{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./useRouter"}],"format":"esm"},"src/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":666,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"},"src/legacy.ts":{"bytes":666,"imports":[{"path":"src/components/Link.tsx","kind":"import-statement","original":"./components/Link"},{"path":"src/hooks/useRouteNode.tsx","kind":"import-statement","original":"./hooks/useRouteNode"},{"path":"src/hooks/useRoute.tsx","kind":"import-statement","original":"./hooks/useRoute"},{"path":"src/hooks/useNavigator.tsx","kind":"import-statement","original":"./hooks/useNavigator"},{"path":"src/hooks/useRouter.tsx","kind":"import-statement","original":"./hooks/useRouter"},{"path":"src/hooks/useRouteUtils.tsx","kind":"import-statement","original":"./hooks/useRouteUtils"},{"path":"src/hooks/useIsActiveRoute.tsx","kind":"import-statement","original":"./hooks/useIsActiveRoute"},{"path":"src/RouterProvider.tsx","kind":"import-statement","original":"./RouterProvider"},{"path":"src/context.ts","kind":"import-statement","original":"./context"}],"format":"esm"}},"outputs":{"dist/esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/index.mjs":{"imports":[{"path":"dist/esm/chunk-GKE5JASO.mjs","kind":"import-statement"}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":396},"dist/esm/legacy.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/esm/legacy.mjs":{"imports":[{"path":"dist/esm/chunk-GKE5JASO.mjs","kind":"import-statement"}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"entryPoint":"src/legacy.ts","inputs":{"src/legacy.ts":{"bytesInOutput":0}},"bytes":396},"dist/esm/chunk-GKE5JASO.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15374},"dist/esm/chunk-GKE5JASO.mjs":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/route-utils","kind":"import-statement","external":true},{"path":"@real-router/core","kind":"import-statement","external":true},{"path":"@real-router/sources","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["Link","NavigatorContext","RouteContext","RouterContext","RouterProvider","useIsActiveRoute","useNavigator","useRoute","useRouteNode","useRouteUtils","useRouter"],"inputs":{"src/context.ts":{"bytesInOutput":164},"src/hooks/useRouter.tsx":{"bytesInOutput":202},"src/hooks/useIsActiveRoute.tsx":{"bytesInOutput":671},"src/hooks/useStableValue.tsx":{"bytesInOutput":157},"src/components/Link.tsx":{"bytesInOutput":2409},"src/constants.ts":{"bytesInOutput":77},"src/utils.ts":{"bytesInOutput":140},"src/hooks/useRouteNode.tsx":{"bytesInOutput":742},"src/hooks/useRoute.tsx":{"bytesInOutput":225},"src/hooks/useNavigator.tsx":{"bytesInOutput":229},"src/hooks/useRouteUtils.tsx":{"bytesInOutput":225},"src/RouterProvider.tsx":{"bytesInOutput":1001}},"bytes":6818}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/react",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "type": "commonjs",
5
5
  "description": "React integration for Real-Router",
6
6
  "main": "./dist/cjs/index.js",
@@ -65,8 +65,8 @@
65
65
  "sideEffects": false,
66
66
  "dependencies": {
67
67
  "@real-router/core": "^0.35.1",
68
- "@real-router/sources": "^0.1.4",
69
- "@real-router/route-utils": "^0.1.4"
68
+ "@real-router/route-utils": "^0.1.4",
69
+ "@real-router/sources": "^0.1.4"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@testing-library/dom": "10.4.1",
@@ -1,16 +1,109 @@
1
- // packages/react/modules/components/Link.tsx
1
+ import { memo, useCallback, useMemo } from "react";
2
2
 
3
- import { BaseLink } from "./BaseLink";
3
+ import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
4
+ import { useIsActiveRoute } from "../hooks/useIsActiveRoute";
4
5
  import { useRouter } from "../hooks/useRouter";
6
+ import { useStableValue } from "../hooks/useStableValue";
7
+ import { shouldNavigate } from "../utils";
5
8
 
6
- import type { BaseLinkProps } from "./interfaces";
7
- import type { FC } from "react";
9
+ import type { LinkProps } from "../types";
10
+ import type { FC, MouseEvent } from "react";
8
11
 
9
- export const Link: FC<Omit<BaseLinkProps, "router">> = (props) => {
10
- const router = useRouter();
12
+ function areLinkPropsEqual(
13
+ prev: Readonly<LinkProps>,
14
+ next: Readonly<LinkProps>,
15
+ ): boolean {
16
+ return (
17
+ prev.routeName === next.routeName &&
18
+ prev.className === next.className &&
19
+ prev.activeClassName === next.activeClassName &&
20
+ prev.activeStrict === next.activeStrict &&
21
+ prev.ignoreQueryParams === next.ignoreQueryParams &&
22
+ prev.onClick === next.onClick &&
23
+ prev.target === next.target &&
24
+ prev.style === next.style &&
25
+ prev.children === next.children &&
26
+ JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&
27
+ JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)
28
+ );
29
+ }
11
30
 
12
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
- const { route, previousRoute, routeOptions, ...linkProps } = props;
31
+ export const Link: FC<LinkProps> = memo(
32
+ ({
33
+ routeName,
34
+ routeParams = EMPTY_PARAMS,
35
+ routeOptions = EMPTY_OPTIONS,
36
+ className,
37
+ activeClassName = "active",
38
+ activeStrict = false,
39
+ ignoreQueryParams = true,
40
+ onClick,
41
+ target,
42
+ children,
43
+ ...props
44
+ }) => {
45
+ const router = useRouter();
14
46
 
15
- return <BaseLink router={router} {...linkProps} />;
16
- };
47
+ const stableParams = useStableValue(routeParams);
48
+ const stableOptions = useStableValue(routeOptions);
49
+
50
+ const isActive = useIsActiveRoute(
51
+ routeName,
52
+ stableParams,
53
+ activeStrict,
54
+ ignoreQueryParams,
55
+ );
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]);
64
+
65
+ const handleClick = useCallback(
66
+ (evt: MouseEvent<HTMLAnchorElement>) => {
67
+ if (onClick) {
68
+ onClick(evt);
69
+
70
+ if (evt.defaultPrevented) {
71
+ return;
72
+ }
73
+ }
74
+
75
+ if (!shouldNavigate(evt) || target === "_blank") {
76
+ return;
77
+ }
78
+
79
+ evt.preventDefault();
80
+ router.navigate(routeName, stableParams, stableOptions).catch(() => {});
81
+ },
82
+ [onClick, target, router, routeName, stableParams, stableOptions],
83
+ );
84
+
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]);
94
+
95
+ return (
96
+ <a
97
+ {...props}
98
+ href={href}
99
+ className={finalClassName}
100
+ onClick={handleClick}
101
+ >
102
+ {children}
103
+ </a>
104
+ );
105
+ },
106
+ areLinkPropsEqual,
107
+ );
108
+
109
+ Link.displayName = "Link";
package/src/index.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  // Main entry point — React 19.2+
2
2
 
3
3
  // Components
4
- export { BaseLink } from "./components/BaseLink";
5
-
6
4
  export { Link } from "./components/Link";
7
5
 
8
- export { ConnectedLink } from "./components/ConnectedLink";
9
-
10
6
  // Hooks
11
7
  export { useRouteNode } from "./hooks/useRouteNode";
12
8
 
@@ -26,6 +22,6 @@ export { RouterProvider } from "./RouterProvider";
26
22
  export { RouterContext, RouteContext, NavigatorContext } from "./context";
27
23
 
28
24
  // Types
29
- export type { BaseLinkProps } from "./types";
25
+ export type { LinkProps } from "./types";
30
26
 
31
27
  export type { Navigator } from "@real-router/core";
package/src/legacy.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  // Legacy entry point — React 18+
2
2
 
3
3
  // Components
4
- export { BaseLink } from "./components/BaseLink";
5
-
6
4
  export { Link } from "./components/Link";
7
5
 
8
- export { ConnectedLink } from "./components/ConnectedLink";
9
-
10
6
  // Hooks
11
7
  export { useRouteNode } from "./hooks/useRouteNode";
12
8
 
@@ -26,6 +22,6 @@ export { RouterProvider } from "./RouterProvider";
26
22
  export { RouterContext, RouteContext, NavigatorContext } from "./context";
27
23
 
28
24
  // Types
29
- export type { BaseLinkProps } from "./types";
25
+ export type { LinkProps } from "./types";
30
26
 
31
27
  export type { Navigator } from "@real-router/core";
package/src/types.ts CHANGED
@@ -1,7 +1,10 @@
1
- // packages/react/modules/types.ts
2
-
3
- import type { Params, Navigator, Router, State } from "@real-router/core";
4
- import type { MouseEvent, ReactNode } from "react";
1
+ import type {
2
+ NavigationOptions,
3
+ Params,
4
+ Navigator,
5
+ State,
6
+ } from "@real-router/core";
7
+ import type { HTMLAttributes, MouseEventHandler } from "react";
5
8
 
6
9
  export interface RouteState<
7
10
  P extends Params = Params,
@@ -15,22 +18,16 @@ export type RouteContext = {
15
18
  navigator: Navigator;
16
19
  } & RouteState;
17
20
 
18
- export interface BaseLinkProps {
19
- [key: string]: unknown;
20
- router: Router;
21
+ export interface LinkProps<
22
+ P extends Params = Params,
23
+ > extends HTMLAttributes<HTMLAnchorElement> {
21
24
  routeName: string;
22
- routeParams?: Params;
23
- routeOptions?: {
24
- [key: string]: unknown;
25
- reload?: boolean;
26
- replace?: boolean;
27
- };
28
- className?: string;
25
+ routeParams?: P;
26
+ routeOptions?: NavigationOptions;
29
27
  activeClassName?: string;
30
28
  activeStrict?: boolean;
31
29
  ignoreQueryParams?: boolean;
32
- onClick?: (evt: MouseEvent<HTMLAnchorElement>) => void;
33
30
  target?: string;
34
- children?: ReactNode;
35
- previousRoute?: State;
31
+ onClick?: MouseEventHandler<HTMLAnchorElement>;
32
+ onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
36
33
  }
@@ -1 +0,0 @@
1
- import{createContext as r,memo as e,useMemo as t,useCallback as o,useSyncExternalStore as u,use as i}from"react";import{createActiveRouteSource as a,createRouteNodeSource as n,createRouteSource as s}from"@real-router/sources";import{jsx as c}from"react/jsx-runtime";import{getNavigator as l,getPluginApi as m}from"@real-router/core";import{getRouteUtils as v}from"@real-router/route-utils";var p=r(null),f=r(null),h=r(null),d=()=>{const r=i(f);if(!r)throw new Error("useRouter must be used within a RouterProvider");return r};function g(r){const e=JSON.stringify(r);return t(()=>r,[e])}function N(r,e,o=!1,i=!0){const n=d(),s=g(e),c=t(()=>a(n,r,s,{strict:o,ignoreQueryParams:i}),[n,r,s,o,i]);return u(c.subscribe,c.getSnapshot,c.getSnapshot)}var b=Object.freeze({}),y=Object.freeze({}),S=e(({routeName:r,routeParams:e=b,routeOptions:u=y,className:i,activeClassName:a="active",activeStrict:n=!1,ignoreQueryParams:s=!0,onClick:l,target:m,router:v,children:p,...f})=>{const h=g(e),d=g(u),S=N(r,h,n,s),O=t(()=>"function"==typeof v.buildUrl?v.buildUrl(r,h):v.buildPath(r,h),[v,r,h]),P=o(e=>{l&&(l(e),e.defaultPrevented)||function(r){return!(0!==r.button||r.metaKey||r.altKey||r.ctrlKey||r.shiftKey)}(e)&&"_blank"!==m&&(e.preventDefault(),v.navigate(r,h,d).catch(()=>{}))},[l,m,v,r,h,d]),R=t(()=>S&&a?i?`${i} ${a}`.trim():a:i??void 0,[S,i,a]),{previousRoute:w,...C}=f;return c("a",{...C,href:O,className:R,onClick:P,"data-route":r,"data-active":S,children:p})},(r,e)=>r.router===e.router&&r.routeName===e.routeName&&JSON.stringify(r.routeParams)===JSON.stringify(e.routeParams)&&JSON.stringify(r.routeOptions)===JSON.stringify(e.routeOptions)&&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.children===e.children);S.displayName="BaseLink";var O=r=>{const e=d(),{route:t,previousRoute:o,routeOptions:u,...i}=r;return c(S,{router:e,...i})},P=()=>{const r=i(p);if(!r)throw new Error("useRoute must be used within a RouteProvider");return r},R=r=>{const e=d(),{route:t}=P(),{routeOptions:o,...u}=r;return c(S,{router:e,route:t,...u})};function w(r){const e=d(),o=t(()=>n(e,r),[e,r]),{route:i,previousRoute:a}=u(o.subscribe,o.getSnapshot,o.getSnapshot),s=t(()=>l(e),[e]);return t(()=>({navigator:s,route:i,previousRoute:a}),[s,i,a])}var C=()=>{const r=i(h);if(!r)throw new Error("useNavigator must be used within a RouterProvider");return r},k=()=>{const r=d();return v(m(r).getTree())},J=({router:r,children:e})=>{const o=t(()=>l(r),[r]),i=t(()=>s(r),[r]),{route:a,previousRoute:n}=u(i.subscribe,i.getSnapshot,i.getSnapshot),m=t(()=>({navigator:o,route:a,previousRoute:n}),[o,a,n]);return c(f,{value:r,children:c(h,{value:o,children:c(p,{value:m,children:e})})})};export{S as BaseLink,R as ConnectedLink,O as Link,h as NavigatorContext,p as RouteContext,f as RouterContext,J as RouterProvider,N as useIsActiveRoute,C as useNavigator,P as useRoute,w as useRouteNode,k as useRouteUtils,d as useRouter};//# sourceMappingURL=chunk-WC4N3BP2.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/constants.ts","../../src/utils.ts","../../src/components/BaseLink.tsx","../../src/components/Link.tsx","../../src/hooks/useRoute.tsx","../../src/components/ConnectedLink.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/RouterProvider.tsx"],"names":["useMemo","jsx","use","useSyncExternalStore","getNavigator"],"mappings":"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","file":"chunk-WC4N3BP2.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 { use } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = use(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","// 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","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","// packages/react/modules/components/BaseLink.tsx\n\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useStableValue } from \"../hooks/useStableValue\";\nimport { shouldNavigate } from \"../utils\";\n\nimport type { BaseLinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\n/**\n * Optimized BaseLink component with memoization and performance improvements\n */\nexport const BaseLink: FC<BaseLinkProps> = 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 router,\n children,\n ...props\n }) => {\n // Stabilize object references to prevent unnecessary re-renders\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n // Use optimized hook for active state checking\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n // Build URL with memoization\n const href = useMemo(() => {\n // Use buildUrl if available (browser plugin installed)\n // Otherwise fall back to buildPath (e.g., in SSR or without browser plugin)\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 // Optimized click handler\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n // Call custom onClick if provided\n if (onClick) {\n onClick(evt);\n // Respect preventDefault from custom handler\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n // Check if we should handle navigation\n if (!shouldNavigate(evt) || target === \"_blank\") {\n return;\n }\n\n // Prevent default link behavior\n evt.preventDefault();\n\n // Perform navigation (fire-and-forget)\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n // Build className efficiently\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 // Filter out previousRoute from props\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { previousRoute, ...restProps } = props;\n\n return (\n <a\n {...restProps}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n data-route={routeName} // For event delegation if needed\n data-active={isActive} // For CSS selectors if needed\n >\n {children}\n </a>\n );\n },\n (prevProps, nextProps) => {\n // Custom comparison for better memoization\n // Check if props that affect rendering have changed\n return (\n prevProps.router === nextProps.router &&\n prevProps.routeName === nextProps.routeName &&\n JSON.stringify(prevProps.routeParams) ===\n JSON.stringify(nextProps.routeParams) &&\n JSON.stringify(prevProps.routeOptions) ===\n JSON.stringify(nextProps.routeOptions) &&\n prevProps.className === nextProps.className &&\n prevProps.activeClassName === nextProps.activeClassName &&\n prevProps.activeStrict === nextProps.activeStrict &&\n prevProps.ignoreQueryParams === nextProps.ignoreQueryParams &&\n prevProps.onClick === nextProps.onClick &&\n prevProps.target === nextProps.target &&\n prevProps.children === nextProps.children\n );\n },\n);\n\nBaseLink.displayName = \"BaseLink\";\n","// packages/react/modules/components/Link.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const Link: FC<Omit<BaseLinkProps, \"router\">> = (props) => {\n const router = useRouter();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { route, previousRoute, routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} {...linkProps} />;\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { use } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = use(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","// packages/react/modules/components/ConnectedLink.tsx\n\nimport { BaseLink } from \"./BaseLink\";\nimport { useRoute } from \"../hooks/useRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\n\nimport type { BaseLinkProps } from \"./interfaces\";\nimport type { FC } from \"react\";\n\nexport const ConnectedLink: FC<\n Omit<BaseLinkProps, \"router\" | \"route\" | \"previousRoute\">\n> = (props) => {\n const router = useRouter();\n const { route } = useRoute();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { routeOptions, ...linkProps } = props;\n\n return <BaseLink router={router} route={route} {...linkProps} />;\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/hooks/useNavigator.tsx\n\nimport { use } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = use(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { 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,129 +0,0 @@
1
- // packages/react/modules/components/BaseLink.tsx
2
-
3
- import { memo, useCallback, useMemo } from "react";
4
-
5
- import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
6
- import { useIsActiveRoute } from "../hooks/useIsActiveRoute";
7
- import { useStableValue } from "../hooks/useStableValue";
8
- import { shouldNavigate } from "../utils";
9
-
10
- import type { BaseLinkProps } from "../types";
11
- import type { FC, MouseEvent } from "react";
12
-
13
- /**
14
- * Optimized BaseLink component with memoization and performance improvements
15
- */
16
- export const BaseLink: FC<BaseLinkProps> = memo(
17
- ({
18
- routeName,
19
- routeParams = EMPTY_PARAMS,
20
- routeOptions = EMPTY_OPTIONS,
21
- className,
22
- activeClassName = "active",
23
- activeStrict = false,
24
- ignoreQueryParams = true,
25
- onClick,
26
- target,
27
- router,
28
- children,
29
- ...props
30
- }) => {
31
- // Stabilize object references to prevent unnecessary re-renders
32
- const stableParams = useStableValue(routeParams);
33
- const stableOptions = useStableValue(routeOptions);
34
-
35
- // Use optimized hook for active state checking
36
- const isActive = useIsActiveRoute(
37
- routeName,
38
- stableParams,
39
- activeStrict,
40
- ignoreQueryParams,
41
- );
42
-
43
- // Build URL with memoization
44
- const href = useMemo(() => {
45
- // Use buildUrl if available (browser plugin installed)
46
- // Otherwise fall back to buildPath (e.g., in SSR or without browser plugin)
47
- if (typeof router.buildUrl === "function") {
48
- return router.buildUrl(routeName, stableParams);
49
- }
50
-
51
- return router.buildPath(routeName, stableParams);
52
- }, [router, routeName, stableParams]);
53
-
54
- // Optimized click handler
55
- const handleClick = useCallback(
56
- (evt: MouseEvent<HTMLAnchorElement>) => {
57
- // Call custom onClick if provided
58
- if (onClick) {
59
- onClick(evt);
60
- // Respect preventDefault from custom handler
61
- if (evt.defaultPrevented) {
62
- return;
63
- }
64
- }
65
-
66
- // Check if we should handle navigation
67
- if (!shouldNavigate(evt) || target === "_blank") {
68
- return;
69
- }
70
-
71
- // Prevent default link behavior
72
- evt.preventDefault();
73
-
74
- // Perform navigation (fire-and-forget)
75
- router.navigate(routeName, stableParams, stableOptions).catch(() => {});
76
- },
77
- [onClick, target, router, routeName, stableParams, stableOptions],
78
- );
79
-
80
- // Build className efficiently
81
- const finalClassName = useMemo(() => {
82
- if (isActive && activeClassName) {
83
- return className
84
- ? `${className} ${activeClassName}`.trim()
85
- : activeClassName;
86
- }
87
-
88
- return className ?? undefined;
89
- }, [isActive, className, activeClassName]);
90
-
91
- // Filter out previousRoute from props
92
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
93
- const { previousRoute, ...restProps } = props;
94
-
95
- return (
96
- <a
97
- {...restProps}
98
- href={href}
99
- className={finalClassName}
100
- onClick={handleClick}
101
- data-route={routeName} // For event delegation if needed
102
- data-active={isActive} // For CSS selectors if needed
103
- >
104
- {children}
105
- </a>
106
- );
107
- },
108
- (prevProps, nextProps) => {
109
- // Custom comparison for better memoization
110
- // Check if props that affect rendering have changed
111
- return (
112
- prevProps.router === nextProps.router &&
113
- prevProps.routeName === nextProps.routeName &&
114
- JSON.stringify(prevProps.routeParams) ===
115
- JSON.stringify(nextProps.routeParams) &&
116
- JSON.stringify(prevProps.routeOptions) ===
117
- JSON.stringify(nextProps.routeOptions) &&
118
- prevProps.className === nextProps.className &&
119
- prevProps.activeClassName === nextProps.activeClassName &&
120
- prevProps.activeStrict === nextProps.activeStrict &&
121
- prevProps.ignoreQueryParams === nextProps.ignoreQueryParams &&
122
- prevProps.onClick === nextProps.onClick &&
123
- prevProps.target === nextProps.target &&
124
- prevProps.children === nextProps.children
125
- );
126
- },
127
- );
128
-
129
- BaseLink.displayName = "BaseLink";
@@ -1,20 +0,0 @@
1
- // packages/react/modules/components/ConnectedLink.tsx
2
-
3
- import { BaseLink } from "./BaseLink";
4
- import { useRoute } from "../hooks/useRoute";
5
- import { useRouter } from "../hooks/useRouter";
6
-
7
- import type { BaseLinkProps } from "./interfaces";
8
- import type { FC } from "react";
9
-
10
- export const ConnectedLink: FC<
11
- Omit<BaseLinkProps, "router" | "route" | "previousRoute">
12
- > = (props) => {
13
- const router = useRouter();
14
- const { route } = useRoute();
15
-
16
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
- const { routeOptions, ...linkProps } = props;
18
-
19
- return <BaseLink router={router} route={route} {...linkProps} />;
20
- };
@@ -1,28 +0,0 @@
1
- // packages/react/modules/components/interfaces.ts
2
-
3
- import type {
4
- NavigationOptions,
5
- Params,
6
- Router,
7
- State,
8
- } from "@real-router/core";
9
- import type { HTMLAttributes, MouseEventHandler } from "react";
10
-
11
- export interface BaseLinkProps<
12
- P extends Params = Params,
13
- MP extends Params = Params,
14
- > extends HTMLAttributes<HTMLAnchorElement> {
15
- router: Router;
16
- routeName: string;
17
- route?: State<P, MP> | undefined;
18
- previousRoute?: State | undefined;
19
- routeParams?: P;
20
- routeOptions?: NavigationOptions;
21
- className?: string;
22
- activeClassName?: string;
23
- activeStrict?: boolean;
24
- ignoreQueryParams?: boolean;
25
- target?: string;
26
- onClick?: MouseEventHandler<HTMLAnchorElement>;
27
- onMouseOver?: MouseEventHandler<HTMLAnchorElement>;
28
- }