@real-router/react 0.14.5 → 0.14.7

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.
@@ -0,0 +1,2 @@
1
+ let e=require(`react`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`react/jsx-runtime`),i=require(`@real-router/sources`),a=require(`@real-router/core/api`);const o=(0,e.createContext)(null),s=(0,e.createContext)(null),c=(0,e.createContext)(null),l=()=>{let t=(0,e.useContext)(s);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function u(n){let r=l(),a=(0,e.useMemo)(()=>(0,i.createRouteNodeSource)(r,n),[r,n]),{route:o,previousRoute:s}=(0,e.useSyncExternalStore)(a.subscribe,a.getSnapshot,a.getSnapshot),c=(0,e.useMemo)(()=>(0,t.getNavigator)(r),[r]);return(0,e.useMemo)(()=>({navigator:c,route:o,previousRoute:s}),[c,o,s])}const d=`data-real-router-announcer`;function f(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c,l=p(),u=setTimeout(()=>{a=!0},100),d=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=h(e,n,r);t&&t!==s&&a&&(s=t,clearTimeout(c),l.textContent=t,c=setTimeout(()=>{l.textContent=``,s=``},7e3),g())})})});return{destroy(){o=!0,d(),clearTimeout(c),clearTimeout(u),m()}}}function p(){let e=document.querySelector(`[${d}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(d,``),document.body.prepend(t),t}function m(){document.querySelector(`[${d}]`)?.remove()}function h(e,t,n){if(n)return n(e);let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return`${t}${r||document.title||i||globalThis.location.pathname}`}function g(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function _(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function v(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function y(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}const b=Object.freeze({}),x=Object.freeze({});function S(t){return(0,e.useMemo)(()=>t,[JSON.stringify(t)])}function C(t,n,r=!1,a=!0){let o=l(),s=S(n),c=(0,e.useMemo)(()=>(0,i.createActiveRouteSource)(o,t,s,{strict:r,ignoreQueryParams:a}),[o,t,s,r,a]);return(0,e.useSyncExternalStore)(c.subscribe,c.getSnapshot,c.getSnapshot)}function w(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)}const T=(0,e.memo)(({routeName:t,routeParams:n=b,routeOptions:i=x,className:a,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:u,target:d,children:f,...p})=>{let m=l(),h=S(n),g=S(i),w=C(t,h,s,c),T=(0,e.useMemo)(()=>v(m,t,h),[m,t,h]),E=(0,e.useCallback)(e=>{u&&(u(e),e.defaultPrevented)||!_(e.nativeEvent)||d===`_blank`||(e.preventDefault(),m.navigate(t,h,g).catch(()=>{}))},[u,d,m,t,h,g]),D=(0,e.useMemo)(()=>y(w,o,a),[w,o,a]);return(0,r.jsx)(`a`,{...p,href:T,className:D,onClick:E,children:f})},w);T.displayName=`Link`;const E=new WeakMap;function D(){let t=l(),n=(0,e.useMemo)(()=>{let e=E.get(t);return e||(e=(0,i.createErrorSource)(t),E.set(t,e)),e},[t]);return(0,e.useSyncExternalStore)(n.subscribe,n.getSnapshot,n.getSnapshot)}function O({children:t,fallback:n,onError:i}){let a=D(),[o,s]=(0,e.useState)(-1),c=(0,e.useRef)(i);c.current=i,(0,e.useEffect)(()=>{a.error&&c.current?.(a.error,a.toRoute,a.fromRoute)},[a.version]);let l=a.version>o?a.error:null,u=(0,e.useCallback)(()=>{s(a.version)},[a.version]);return(0,r.jsxs)(r.Fragment,{children:[t,l?n(l,u):null]})}const k=()=>{let t=(0,e.useContext)(c);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},A=()=>(0,n.getRouteUtils)((0,a.getPluginApi)(l()).getTree()),j=()=>{let t=(0,e.useContext)(o);if(!t)throw Error(`useRoute must be used within a RouteProvider`);return t};function M(){let t=l(),n=(0,e.useMemo)(()=>(0,i.createTransitionSource)(t),[t]);return(0,e.useSyncExternalStore)(n.subscribe,n.getSnapshot,n.getSnapshot)}const N=({router:n,children:a,announceNavigation:l})=>{(0,e.useEffect)(()=>{if(!l)return;let e=f(n);return()=>{e.destroy()}},[l,n]);let u=(0,e.useMemo)(()=>(0,t.getNavigator)(n),[n]),d=(0,e.useMemo)(()=>(0,i.createRouteSource)(n),[n]),{route:p,previousRoute:m}=(0,e.useSyncExternalStore)(d.subscribe,d.getSnapshot,d.getSnapshot);return(0,r.jsx)(s,{value:n,children:(0,r.jsx)(c,{value:u,children:(0,r.jsx)(o,{value:(0,e.useMemo)(()=>({navigator:u,route:p,previousRoute:m}),[u,p,m]),children:a})})})};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return N}});
2
+ //# sourceMappingURL=RouterProvider-ZVZMfscC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterProvider-ZVZMfscC.js","names":["buildHref","shouldNavigate","buildActiveClassName","createRouteAnnouncer"],"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../../dom-utils/dist/esm/index.mjs","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useRouterError.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"sourcesContent":["// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","const e=`data-real-router-announcer`;function t(e,t){let o=t?.prefix??`Navigated to `,s=t?.getAnnouncementText,c=!0,l=!1,u=!1,d=``,f,p=n(),m=setTimeout(()=>{l=!0},100),h=e.subscribe(({route:e})=>{if(c){c=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(u)return;let t=i(e,o,s);t&&t!==d&&l&&(d=t,clearTimeout(f),p.textContent=t,f=setTimeout(()=>{p.textContent=``,d=``},7e3),a())})})});return{destroy(){u=!0,h(),clearTimeout(f),clearTimeout(m),r()}}}function n(){let t=document.querySelector(`[${e}]`);if(t)return t;let n=document.createElement(`div`);return n.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),n.setAttribute(`aria-live`,`assertive`),n.setAttribute(`aria-atomic`,`true`),n.setAttribute(e,``),document.body.prepend(n),n}function r(){document.querySelector(`[${e}]`)?.remove()}function i(e,t,n){if(n)return n(e);let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return`${t}${r||document.title||i||globalThis.location.pathname}`}function a(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function o(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function s(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route \"${t}\" is not defined. The element will render without an href attribute.`);return}}function c(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}function l(e){e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.getAttribute(`role`)||e.setAttribute(`role`,`link`),e.getAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`))}export{l as applyLinkA11y,c as buildActiveClassName,s as buildHref,t as createRouteAnnouncer,o as shouldNavigate};\n//# sourceMappingURL=index.mjs.map","// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line @eslint-react/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt.nativeEvent) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { createErrorSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { RouterErrorSnapshot, RouterSource } from \"@real-router/sources\";\n\nconst cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();\n\nexport function useRouterError(): RouterErrorSnapshot {\n const router = useRouter();\n const store = useMemo(() => {\n let source = cache.get(router);\n\n if (!source) {\n source = createErrorSource(router);\n cache.set(router, source);\n }\n\n return source;\n }, [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useRouterError } from \"../hooks/useRouterError\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { ReactNode, JSX } from \"react\";\n\nexport interface RouterErrorBoundaryProps {\n readonly children: ReactNode;\n readonly fallback: (error: RouterError, resetError: () => void) => ReactNode;\n readonly onError?: (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void;\n}\n\nexport function RouterErrorBoundary({\n children,\n fallback,\n onError,\n}: RouterErrorBoundaryProps): JSX.Element {\n const snapshot = useRouterError();\n const [dismissedVersion, setDismissedVersion] = useState(-1);\n\n const onErrorRef = useRef(onError);\n\n // eslint-disable-next-line @eslint-react/refs -- \"latest ref\" pattern: sync callback to ref to avoid effect re-runs\n onErrorRef.current = onError;\n\n useEffect(() => {\n if (snapshot.error) {\n onErrorRef.current?.(\n snapshot.error,\n snapshot.toRoute,\n snapshot.fromRoute,\n );\n }\n // eslint-disable-next-line @eslint-react/exhaustive-deps -- onError tracked via ref, snapshot fields accessed inside callback\n }, [snapshot.version]);\n\n const visibleError =\n snapshot.version > dismissedVersion ? snapshot.error : null;\n\n const resetError = useCallback(() => {\n setDismissedVersion(snapshot.version);\n }, [snapshot.version]);\n\n return (\n <>\n {children}\n {visibleError ? fallback(visibleError, resetError) : null}\n </>\n );\n}\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./RouterProvider-Caf5VTGt.js`);let t=require(`react`),n=require(`@real-router/core`),r=require(`@real-router/route-utils`),i=require(`react/jsx-runtime`);function a(e){return null}a.displayName=`RouteView.Match`;function o(e){return null}o.displayName=`RouteView.NotFound`;function s(e,t,n){return n?e===t:(0,r.startsWithSegment)(e,t)}function c(e,n){for(let r of t.Children.toArray(e))(0,t.isValidElement)(r)&&(r.type===a||r.type===o?n.push(r):c(r.props.children,n))}function l(e,n,r,a,o){let s=o===void 0?e:(0,i.jsx)(t.Suspense,{fallback:o,children:e});return r?(0,i.jsx)(t.Activity,{mode:a,children:s},n):(0,i.jsx)(t.Fragment,{children:s},n)}function u(e,r,a,c){let u=null,d=!1,f=[];for(let t of e){if(t.type===o){u=t.props.children;continue}let{segment:e,exact:n=!1,keepAlive:i=!1,fallback:p}=t.props,m=a?`${a}.${e}`:e;!d&&s(r,m,n)?(d=!0,c.add(m),f.push(l(t.props.children,m,i,`visible`,p))):i&&c.has(m)&&f.push(l(t.props.children,m,i,`hidden`,p))}return!d&&r===n.UNKNOWN_ROUTE&&u!==null&&f.push((0,i.jsx)(t.Fragment,{children:u},`__route-view-not-found__`)),{rendered:f,activeMatchFound:d}}function d({nodeName:n,children:r}){let{route:a}=e.c(n),o=(0,t.useRef)(new Set);if(!a)return null;let s=[];c(r,s);let{rendered:l}=u(s,a.name,n,o.current);return l.length>0?(0,i.jsx)(i.Fragment,{children:l}):null}d.displayName=`RouteView`;const f=Object.assign(d,{Match:a,NotFound:o});exports.Link=e.s,exports.RouteView=f,exports.RouterErrorBoundary=e.o,exports.RouterProvider=e.t,exports.useNavigator=e.a,exports.useRoute=e.r,exports.useRouteNode=e.c,exports.useRouteUtils=e.i,exports.useRouter=e.l,exports.useRouterTransition=e.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./RouterProvider-ZVZMfscC.js`);let t=require(`react`),n=require(`@real-router/core`),r=require(`@real-router/route-utils`),i=require(`react/jsx-runtime`);function a(e){return null}a.displayName=`RouteView.Match`;function o(e){return null}o.displayName=`RouteView.NotFound`;function s(e,t,n){return n?e===t:(0,r.startsWithSegment)(e,t)}function c(e,n){for(let r of t.Children.toArray(e))(0,t.isValidElement)(r)&&(r.type===a||r.type===o?n.push(r):c(r.props.children,n))}function l(e,n,r,a,o){let s=o===void 0?e:(0,i.jsx)(t.Suspense,{fallback:o,children:e});return r?(0,i.jsx)(t.Activity,{mode:a,children:s},n):(0,i.jsx)(t.Fragment,{children:s},n)}function u(e,r,a,c){let u=null,d=!1,f=[];for(let t of e){if(t.type===o){u=t.props.children;continue}let{segment:e,exact:n=!1,keepAlive:i=!1,fallback:p}=t.props,m=a?`${a}.${e}`:e;!d&&s(r,m,n)?(d=!0,c.add(m),f.push(l(t.props.children,m,i,`visible`,p))):i&&c.has(m)&&f.push(l(t.props.children,m,i,`hidden`,p))}return!d&&r===n.UNKNOWN_ROUTE&&u!==null&&f.push((0,i.jsx)(t.Fragment,{children:u},`__route-view-not-found__`)),{rendered:f,activeMatchFound:d}}function d({nodeName:n,children:r}){let{route:a}=e.c(n),o=(0,t.useRef)(new Set);if(!a)return null;let s=[];c(r,s);let{rendered:l}=u(s,a.name,n,o.current);return l.length>0?(0,i.jsx)(i.Fragment,{children:l}):null}d.displayName=`RouteView`;const f=Object.assign(d,{Match:a,NotFound:o});exports.Link=e.s,exports.RouteView=f,exports.RouterErrorBoundary=e.o,exports.RouterProvider=e.t,exports.useNavigator=e.a,exports.useRoute=e.r,exports.useRouteNode=e.c,exports.useRouteUtils=e.i,exports.useRouter=e.l,exports.useRouterTransition=e.n;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./RouterProvider-Caf5VTGt.js`);exports.Link=e.s,exports.RouterErrorBoundary=e.o,exports.RouterProvider=e.t,exports.useNavigator=e.a,exports.useRoute=e.r,exports.useRouteNode=e.c,exports.useRouteUtils=e.i,exports.useRouter=e.l,exports.useRouterTransition=e.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./RouterProvider-ZVZMfscC.js`);exports.Link=e.s,exports.RouterErrorBoundary=e.o,exports.RouterProvider=e.t,exports.useNavigator=e.a,exports.useRoute=e.r,exports.useRouteNode=e.c,exports.useRouteUtils=e.i,exports.useRouter=e.l,exports.useRouterTransition=e.n;
@@ -0,0 +1,2 @@
1
+ import{createContext as e,memo as t,useCallback as n,useContext as r,useEffect as i,useMemo as a,useRef as o,useState as s,useSyncExternalStore as c}from"react";import{getNavigator as l}from"@real-router/core";import{getRouteUtils as u}from"@real-router/route-utils";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";import{createActiveRouteSource as m,createErrorSource as h,createRouteNodeSource as g,createRouteSource as _,createTransitionSource as v}from"@real-router/sources";import{getPluginApi as y}from"@real-router/core/api";const b=e(null),x=e(null),S=e(null),C=()=>{let e=r(x);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e};function w(e){let t=C(),n=a(()=>g(t,e),[t,e]),{route:r,previousRoute:i}=c(n.subscribe,n.getSnapshot,n.getSnapshot),o=a(()=>l(t),[t]);return a(()=>({navigator:o,route:r,previousRoute:i}),[o,r,i])}const T=`data-real-router-announcer`;function E(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c,l=D(),u=setTimeout(()=>{a=!0},100),d=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=k(e,n,r);t&&t!==s&&a&&(s=t,clearTimeout(c),l.textContent=t,c=setTimeout(()=>{l.textContent=``,s=``},7e3),A())})})});return{destroy(){o=!0,d(),clearTimeout(c),clearTimeout(u),O()}}}function D(){let e=document.querySelector(`[${T}]`);if(e)return e;let t=document.createElement(`div`);return t.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),t.setAttribute(`aria-live`,`assertive`),t.setAttribute(`aria-atomic`,`true`),t.setAttribute(T,``),document.body.prepend(t),t}function O(){document.querySelector(`[${T}]`)?.remove()}function k(e,t,n){if(n)return n(e);let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return`${t}${r||document.title||i||globalThis.location.pathname}`}function A(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function j(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function M(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function N(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}const P=Object.freeze({}),F=Object.freeze({});function I(e){return a(()=>e,[JSON.stringify(e)])}function L(e,t,n=!1,r=!0){let i=C(),o=I(t),s=a(()=>m(i,e,o,{strict:n,ignoreQueryParams:r}),[i,e,o,n,r]);return c(s.subscribe,s.getSnapshot,s.getSnapshot)}function R(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)}const z=t(({routeName:e,routeParams:t=P,routeOptions:r=F,className:i,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:l,target:u,children:d,...p})=>{let m=C(),h=I(t),g=I(r),_=L(e,h,s,c),v=a(()=>M(m,e,h),[m,e,h]),y=n(t=>{l&&(l(t),t.defaultPrevented)||!j(t.nativeEvent)||u===`_blank`||(t.preventDefault(),m.navigate(e,h,g).catch(()=>{}))},[l,u,m,e,h,g]),b=a(()=>N(_,o,i),[_,o,i]);return f(`a`,{...p,href:v,className:b,onClick:y,children:d})},R);z.displayName=`Link`;const B=new WeakMap;function V(){let e=C(),t=a(()=>{let t=B.get(e);return t||(t=h(e),B.set(e,t)),t},[e]);return c(t.subscribe,t.getSnapshot,t.getSnapshot)}function H({children:e,fallback:t,onError:r}){let a=V(),[c,l]=s(-1),u=o(r);u.current=r,i(()=>{a.error&&u.current?.(a.error,a.toRoute,a.fromRoute)},[a.version]);let f=a.version>c?a.error:null,m=n(()=>{l(a.version)},[a.version]);return p(d,{children:[e,f?t(f,m):null]})}const U=()=>{let e=r(S);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},W=()=>u(y(C()).getTree()),G=()=>{let e=r(b);if(!e)throw Error(`useRoute must be used within a RouteProvider`);return e};function K(){let e=C(),t=a(()=>v(e),[e]);return c(t.subscribe,t.getSnapshot,t.getSnapshot)}const q=({router:e,children:t,announceNavigation:n})=>{i(()=>{if(!n)return;let t=E(e);return()=>{t.destroy()}},[n,e]);let r=a(()=>l(e),[e]),o=a(()=>_(e),[e]),{route:s,previousRoute:u}=c(o.subscribe,o.getSnapshot,o.getSnapshot);return f(x,{value:e,children:f(S,{value:r,children:f(b,{value:a(()=>({navigator:r,route:s,previousRoute:u}),[r,s,u]),children:t})})})};export{U as a,w as c,W as i,C as l,K as n,H as o,G as r,z as s,q as t};
2
+ //# sourceMappingURL=RouterProvider-CYGl-5vr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterProvider-CYGl-5vr.mjs","names":["buildHref","shouldNavigate","buildActiveClassName","createRouteAnnouncer"],"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../../dom-utils/dist/esm/index.mjs","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useRouterError.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"sourcesContent":["// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","const e=`data-real-router-announcer`;function t(e,t){let o=t?.prefix??`Navigated to `,s=t?.getAnnouncementText,c=!0,l=!1,u=!1,d=``,f,p=n(),m=setTimeout(()=>{l=!0},100),h=e.subscribe(({route:e})=>{if(c){c=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(u)return;let t=i(e,o,s);t&&t!==d&&l&&(d=t,clearTimeout(f),p.textContent=t,f=setTimeout(()=>{p.textContent=``,d=``},7e3),a())})})});return{destroy(){u=!0,h(),clearTimeout(f),clearTimeout(m),r()}}}function n(){let t=document.querySelector(`[${e}]`);if(t)return t;let n=document.createElement(`div`);return n.setAttribute(`style`,`position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0`),n.setAttribute(`aria-live`,`assertive`),n.setAttribute(`aria-atomic`,`true`),n.setAttribute(e,``),document.body.prepend(n),n}function r(){document.querySelector(`[${e}]`)?.remove()}function i(e,t,n){if(n)return n(e);let r=document.querySelector(`h1`)?.textContent.trim()??``,i=e.name.startsWith(`@@`)?``:e.name;return`${t}${r||document.title||i||globalThis.location.pathname}`}function a(){let e=document.querySelector(`h1`);e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function o(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function s(e,t,n){try{let r=e.buildUrl;return r?r(t,n):e.buildPath(t,n)}catch{console.error(`[real-router] Route \"${t}\" is not defined. The element will render without an href attribute.`);return}}function c(e,t,n){return e&&t?n?`${n} ${t}`.trim():t:n??void 0}function l(e){e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.getAttribute(`role`)||e.setAttribute(`role`,`link`),e.getAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`))}export{l as applyLinkA11y,c as buildActiveClassName,s as buildHref,t as createRouteAnnouncer,o as shouldNavigate};\n//# sourceMappingURL=index.mjs.map","// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line @eslint-react/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt.nativeEvent) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { createErrorSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { RouterErrorSnapshot, RouterSource } from \"@real-router/sources\";\n\nconst cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();\n\nexport function useRouterError(): RouterErrorSnapshot {\n const router = useRouter();\n const store = useMemo(() => {\n let source = cache.get(router);\n\n if (!source) {\n source = createErrorSource(router);\n cache.set(router, source);\n }\n\n return source;\n }, [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useRouterError } from \"../hooks/useRouterError\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { ReactNode, JSX } from \"react\";\n\nexport interface RouterErrorBoundaryProps {\n readonly children: ReactNode;\n readonly fallback: (error: RouterError, resetError: () => void) => ReactNode;\n readonly onError?: (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void;\n}\n\nexport function RouterErrorBoundary({\n children,\n fallback,\n onError,\n}: RouterErrorBoundaryProps): JSX.Element {\n const snapshot = useRouterError();\n const [dismissedVersion, setDismissedVersion] = useState(-1);\n\n const onErrorRef = useRef(onError);\n\n // eslint-disable-next-line @eslint-react/refs -- \"latest ref\" pattern: sync callback to ref to avoid effect re-runs\n onErrorRef.current = onError;\n\n useEffect(() => {\n if (snapshot.error) {\n onErrorRef.current?.(\n snapshot.error,\n snapshot.toRoute,\n snapshot.fromRoute,\n );\n }\n // eslint-disable-next-line @eslint-react/exhaustive-deps -- onError tracked via ref, snapshot fields accessed inside callback\n }, [snapshot.version]);\n\n const visibleError =\n snapshot.version > dismissedVersion ? snapshot.error : null;\n\n const resetError = useCallback(() => {\n setDismissedVersion(snapshot.version);\n }, [snapshot.version]);\n\n return (\n <>\n {children}\n {visibleError ? fallback(visibleError, resetError) : null}\n </>\n );\n}\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./RouterProvider-CedKqey6.mjs";import{Activity as l,Children as u,Fragment as d,Suspense as f,isValidElement as p,useRef as m}from"react";import{UNKNOWN_ROUTE as h}from"@real-router/core";import{startsWithSegment as g}from"@real-router/route-utils";import{Fragment as _,jsx as v}from"react/jsx-runtime";function y(e){return null}y.displayName=`RouteView.Match`;function b(e){return null}b.displayName=`RouteView.NotFound`;function x(e,t,n){return n?e===t:g(e,t)}function S(e,t){for(let n of u.toArray(e))p(n)&&(n.type===y||n.type===b?t.push(n):S(n.props.children,t))}function C(e,t,n,r,i){let a=i===void 0?e:v(f,{fallback:i,children:e});return n?v(l,{mode:r,children:a},t):v(d,{children:a},t)}function w(e,t,n,r){let i=null,a=!1,o=[];for(let s of e){if(s.type===b){i=s.props.children;continue}let{segment:e,exact:c=!1,keepAlive:l=!1,fallback:u}=s.props,d=n?`${n}.${e}`:e;!a&&x(t,d,c)?(a=!0,r.add(d),o.push(C(s.props.children,d,l,`visible`,u))):l&&r.has(d)&&o.push(C(s.props.children,d,l,`hidden`,u))}return!a&&t===h&&i!==null&&o.push(v(d,{children:i},`__route-view-not-found__`)),{rendered:o,activeMatchFound:a}}function T({nodeName:e,children:n}){let{route:r}=t(e),i=m(new Set);if(!r)return null;let a=[];S(n,a);let{rendered:o}=w(a,r.name,e,i.current);return o.length>0?v(_,{children:o}):null}T.displayName=`RouteView`;const E=Object.assign(T,{Match:y,NotFound:b});export{s as Link,E as RouteView,a as RouterErrorBoundary,c as RouterProvider,e as useNavigator,o as useRoute,t as useRouteNode,n as useRouteUtils,r as useRouter,i as useRouterTransition};
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./RouterProvider-CYGl-5vr.mjs";import{Activity as l,Children as u,Fragment as d,Suspense as f,isValidElement as p,useRef as m}from"react";import{UNKNOWN_ROUTE as h}from"@real-router/core";import{startsWithSegment as g}from"@real-router/route-utils";import{Fragment as _,jsx as v}from"react/jsx-runtime";function y(e){return null}y.displayName=`RouteView.Match`;function b(e){return null}b.displayName=`RouteView.NotFound`;function x(e,t,n){return n?e===t:g(e,t)}function S(e,t){for(let n of u.toArray(e))p(n)&&(n.type===y||n.type===b?t.push(n):S(n.props.children,t))}function C(e,t,n,r,i){let a=i===void 0?e:v(f,{fallback:i,children:e});return n?v(l,{mode:r,children:a},t):v(d,{children:a},t)}function w(e,t,n,r){let i=null,a=!1,o=[];for(let s of e){if(s.type===b){i=s.props.children;continue}let{segment:e,exact:c=!1,keepAlive:l=!1,fallback:u}=s.props,d=n?`${n}.${e}`:e;!a&&x(t,d,c)?(a=!0,r.add(d),o.push(C(s.props.children,d,l,`visible`,u))):l&&r.has(d)&&o.push(C(s.props.children,d,l,`hidden`,u))}return!a&&t===h&&i!==null&&o.push(v(d,{children:i},`__route-view-not-found__`)),{rendered:o,activeMatchFound:a}}function T({nodeName:e,children:n}){let{route:r}=t(e),i=m(new Set);if(!r)return null;let a=[];S(n,a);let{rendered:o}=w(a,r.name,e,i.current);return o.length>0?v(_,{children:o}):null}T.displayName=`RouteView`;const E=Object.assign(T,{Match:y,NotFound:b});export{s as Link,E as RouteView,a as RouterErrorBoundary,c as RouterProvider,e as useNavigator,o as useRoute,t as useRouteNode,n as useRouteUtils,r as useRouter,i as useRouterTransition};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./RouterProvider-CedKqey6.mjs";export{s as Link,a as RouterErrorBoundary,c as RouterProvider,e as useNavigator,o as useRoute,t as useRouteNode,n as useRouteUtils,r as useRouter,i as useRouterTransition};
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./RouterProvider-CYGl-5vr.mjs";export{s as Link,a as RouterErrorBoundary,c as RouterProvider,e as useNavigator,o as useRoute,t as useRouteNode,n as useRouteUtils,r as useRouter,i as useRouterTransition};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/react",
3
- "version": "0.14.5",
3
+ "version": "0.14.7",
4
4
  "type": "commonjs",
5
5
  "description": "React integration for Real-Router",
6
6
  "main": "./dist/cjs/index.js",
@@ -64,10 +64,9 @@
64
64
  "license": "MIT",
65
65
  "sideEffects": false,
66
66
  "dependencies": {
67
- "@real-router/core": "^0.44.0",
68
- "@real-router/route-utils": "^0.1.10",
69
- "@real-router/sources": "^0.4.0",
70
- "dom-utils": "^0.2.6"
67
+ "@real-router/core": "^0.45.0",
68
+ "@real-router/route-utils": "^0.1.11",
69
+ "@real-router/sources": "^0.4.1"
71
70
  },
72
71
  "devDependencies": {
73
72
  "@testing-library/dom": "10.4.1",
@@ -75,7 +74,8 @@
75
74
  "@testing-library/react": "16.3.2",
76
75
  "@testing-library/user-event": "14.6.1",
77
76
  "vitest-react-profiler": "1.12.0",
78
- "@real-router/browser-plugin": "^0.11.3"
77
+ "@real-router/browser-plugin": "^0.11.4",
78
+ "dom-utils": "^0.2.7"
79
79
  },
80
80
  "peerDependencies": {
81
81
  "@types/react": ">=18.0.0",
@@ -1,2 +0,0 @@
1
- let e=require(`react`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`react/jsx-runtime`),i=require(`@real-router/sources`),a=require(`dom-utils`),o=require(`@real-router/core/api`);const s=(0,e.createContext)(null),c=(0,e.createContext)(null),l=(0,e.createContext)(null),u=()=>{let t=(0,e.useContext)(c);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function d(n){let r=u(),a=(0,e.useMemo)(()=>(0,i.createRouteNodeSource)(r,n),[r,n]),{route:o,previousRoute:s}=(0,e.useSyncExternalStore)(a.subscribe,a.getSnapshot,a.getSnapshot),c=(0,e.useMemo)(()=>(0,t.getNavigator)(r),[r]);return(0,e.useMemo)(()=>({navigator:c,route:o,previousRoute:s}),[c,o,s])}const f=Object.freeze({}),p=Object.freeze({});function m(t){return(0,e.useMemo)(()=>t,[JSON.stringify(t)])}function h(t,n,r=!1,a=!0){let o=u(),s=m(n),c=(0,e.useMemo)(()=>(0,i.createActiveRouteSource)(o,t,s,{strict:r,ignoreQueryParams:a}),[o,t,s,r,a]);return(0,e.useSyncExternalStore)(c.subscribe,c.getSnapshot,c.getSnapshot)}function g(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)}const _=(0,e.memo)(({routeName:t,routeParams:n=f,routeOptions:i=p,className:o,activeClassName:s=`active`,activeStrict:c=!1,ignoreQueryParams:l=!0,onClick:d,target:g,children:_,...v})=>{let y=u(),b=m(n),x=m(i),S=h(t,b,c,l),C=(0,e.useMemo)(()=>(0,a.buildHref)(y,t,b),[y,t,b]),w=(0,e.useCallback)(e=>{d&&(d(e),e.defaultPrevented)||!(0,a.shouldNavigate)(e.nativeEvent)||g===`_blank`||(e.preventDefault(),y.navigate(t,b,x).catch(()=>{}))},[d,g,y,t,b,x]),T=(0,e.useMemo)(()=>(0,a.buildActiveClassName)(S,s,o),[S,s,o]);return(0,r.jsx)(`a`,{...v,href:C,className:T,onClick:w,children:_})},g);_.displayName=`Link`;const v=new WeakMap;function y(){let t=u(),n=(0,e.useMemo)(()=>{let e=v.get(t);return e||(e=(0,i.createErrorSource)(t),v.set(t,e)),e},[t]);return(0,e.useSyncExternalStore)(n.subscribe,n.getSnapshot,n.getSnapshot)}function b({children:t,fallback:n,onError:i}){let a=y(),[o,s]=(0,e.useState)(-1),c=(0,e.useRef)(i);c.current=i,(0,e.useEffect)(()=>{a.error&&c.current?.(a.error,a.toRoute,a.fromRoute)},[a.version]);let l=a.version>o?a.error:null,u=(0,e.useCallback)(()=>{s(a.version)},[a.version]);return(0,r.jsxs)(r.Fragment,{children:[t,l?n(l,u):null]})}const x=()=>{let t=(0,e.useContext)(l);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},S=()=>(0,n.getRouteUtils)((0,o.getPluginApi)(u()).getTree()),C=()=>{let t=(0,e.useContext)(s);if(!t)throw Error(`useRoute must be used within a RouteProvider`);return t};function w(){let t=u(),n=(0,e.useMemo)(()=>(0,i.createTransitionSource)(t),[t]);return(0,e.useSyncExternalStore)(n.subscribe,n.getSnapshot,n.getSnapshot)}const T=({router:n,children:o,announceNavigation:u})=>{(0,e.useEffect)(()=>{if(!u)return;let e=(0,a.createRouteAnnouncer)(n);return()=>{e.destroy()}},[u,n]);let d=(0,e.useMemo)(()=>(0,t.getNavigator)(n),[n]),f=(0,e.useMemo)(()=>(0,i.createRouteSource)(n),[n]),{route:p,previousRoute:m}=(0,e.useSyncExternalStore)(f.subscribe,f.getSnapshot,f.getSnapshot);return(0,r.jsx)(c,{value:n,children:(0,r.jsx)(l,{value:d,children:(0,r.jsx)(s,{value:(0,e.useMemo)(()=>({navigator:d,route:p,previousRoute:m}),[d,p,m]),children:o})})})};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return T}});
2
- //# sourceMappingURL=RouterProvider-Caf5VTGt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RouterProvider-Caf5VTGt.js","names":[],"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useRouterError.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"sourcesContent":["// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line @eslint-react/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt.nativeEvent) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { createErrorSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { RouterErrorSnapshot, RouterSource } from \"@real-router/sources\";\n\nconst cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();\n\nexport function useRouterError(): RouterErrorSnapshot {\n const router = useRouter();\n const store = useMemo(() => {\n let source = cache.get(router);\n\n if (!source) {\n source = createErrorSource(router);\n cache.set(router, source);\n }\n\n return source;\n }, [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useRouterError } from \"../hooks/useRouterError\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { ReactNode, JSX } from \"react\";\n\nexport interface RouterErrorBoundaryProps {\n readonly children: ReactNode;\n readonly fallback: (error: RouterError, resetError: () => void) => ReactNode;\n readonly onError?: (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void;\n}\n\nexport function RouterErrorBoundary({\n children,\n fallback,\n onError,\n}: RouterErrorBoundaryProps): JSX.Element {\n const snapshot = useRouterError();\n const [dismissedVersion, setDismissedVersion] = useState(-1);\n\n const onErrorRef = useRef(onError);\n\n // eslint-disable-next-line @eslint-react/refs -- \"latest ref\" pattern: sync callback to ref to avoid effect re-runs\n onErrorRef.current = onError;\n\n useEffect(() => {\n if (snapshot.error) {\n onErrorRef.current?.(\n snapshot.error,\n snapshot.toRoute,\n snapshot.fromRoute,\n );\n }\n // eslint-disable-next-line @eslint-react/exhaustive-deps -- onError tracked via ref, snapshot fields accessed inside callback\n }, [snapshot.version]);\n\n const visibleError =\n snapshot.version > dismissedVersion ? snapshot.error : null;\n\n const resetError = useCallback(() => {\n setDismissedVersion(snapshot.version);\n }, [snapshot.version]);\n\n return (\n <>\n {children}\n {visibleError ? fallback(visibleError, resetError) : null}\n </>\n );\n}\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{createContext as e,memo as t,useCallback as n,useContext as r,useEffect as i,useMemo as a,useRef as o,useState as s,useSyncExternalStore as c}from"react";import{getNavigator as l}from"@real-router/core";import{getRouteUtils as u}from"@real-router/route-utils";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";import{createActiveRouteSource as m,createErrorSource as h,createRouteNodeSource as g,createRouteSource as _,createTransitionSource as v}from"@real-router/sources";import{buildActiveClassName as y,buildHref as b,createRouteAnnouncer as x,shouldNavigate as S}from"dom-utils";import{getPluginApi as C}from"@real-router/core/api";const w=e(null),T=e(null),E=e(null),D=()=>{let e=r(T);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e};function O(e){let t=D(),n=a(()=>g(t,e),[t,e]),{route:r,previousRoute:i}=c(n.subscribe,n.getSnapshot,n.getSnapshot),o=a(()=>l(t),[t]);return a(()=>({navigator:o,route:r,previousRoute:i}),[o,r,i])}const k=Object.freeze({}),A=Object.freeze({});function j(e){return a(()=>e,[JSON.stringify(e)])}function M(e,t,n=!1,r=!0){let i=D(),o=j(t),s=a(()=>m(i,e,o,{strict:n,ignoreQueryParams:r}),[i,e,o,n,r]);return c(s.subscribe,s.getSnapshot,s.getSnapshot)}function N(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)}const P=t(({routeName:e,routeParams:t=k,routeOptions:r=A,className:i,activeClassName:o=`active`,activeStrict:s=!1,ignoreQueryParams:c=!0,onClick:l,target:u,children:d,...p})=>{let m=D(),h=j(t),g=j(r),_=M(e,h,s,c),v=a(()=>b(m,e,h),[m,e,h]),x=n(t=>{l&&(l(t),t.defaultPrevented)||!S(t.nativeEvent)||u===`_blank`||(t.preventDefault(),m.navigate(e,h,g).catch(()=>{}))},[l,u,m,e,h,g]),C=a(()=>y(_,o,i),[_,o,i]);return f(`a`,{...p,href:v,className:C,onClick:x,children:d})},N);P.displayName=`Link`;const F=new WeakMap;function I(){let e=D(),t=a(()=>{let t=F.get(e);return t||(t=h(e),F.set(e,t)),t},[e]);return c(t.subscribe,t.getSnapshot,t.getSnapshot)}function L({children:e,fallback:t,onError:r}){let a=I(),[c,l]=s(-1),u=o(r);u.current=r,i(()=>{a.error&&u.current?.(a.error,a.toRoute,a.fromRoute)},[a.version]);let f=a.version>c?a.error:null,m=n(()=>{l(a.version)},[a.version]);return p(d,{children:[e,f?t(f,m):null]})}const R=()=>{let e=r(E);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},z=()=>u(C(D()).getTree()),B=()=>{let e=r(w);if(!e)throw Error(`useRoute must be used within a RouteProvider`);return e};function V(){let e=D(),t=a(()=>v(e),[e]);return c(t.subscribe,t.getSnapshot,t.getSnapshot)}const H=({router:e,children:t,announceNavigation:n})=>{i(()=>{if(!n)return;let t=x(e);return()=>{t.destroy()}},[n,e]);let r=a(()=>l(e),[e]),o=a(()=>_(e),[e]),{route:s,previousRoute:u}=c(o.subscribe,o.getSnapshot,o.getSnapshot);return f(T,{value:e,children:f(E,{value:r,children:f(w,{value:a(()=>({navigator:r,route:s,previousRoute:u}),[r,s,u]),children:t})})})};export{R as a,O as c,z as i,D as l,V as n,L as o,B as r,P as s,H as t};
2
- //# sourceMappingURL=RouterProvider-CedKqey6.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RouterProvider-CedKqey6.mjs","names":[],"sources":["../../src/context.ts","../../src/hooks/useRouter.tsx","../../src/hooks/useRouteNode.tsx","../../src/constants.ts","../../src/hooks/useStableValue.tsx","../../src/hooks/useIsActiveRoute.tsx","../../src/components/Link.tsx","../../src/hooks/useRouterError.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouterTransition.tsx","../../src/RouterProvider.tsx"],"sourcesContent":["// packages/react/modules/context.ts\n\nimport { createContext } from \"react\";\n\nimport type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\n\nexport const RouteContext = createContext<RouteContextType | null>(null);\n\nexport const RouterContext = createContext<Router | null>(null);\n\nexport const NavigatorContext = createContext<Navigator | null>(null);\n","// packages/react/modules/hooks/useRouter.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouterContext } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = useContext(RouterContext);\n\n if (!router) {\n throw new Error(\"useRouter must be used within a RouterProvider\");\n }\n\n return router;\n};\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteNodeSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const store = useMemo(\n () => createRouteNodeSource(router, nodeName),\n [router, nodeName],\n );\n\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n return useMemo(\n (): RouteContext => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n}\n","// packages/react/modules/constants.ts\n\n/**\n * Stable empty object for default params\n */\nexport const EMPTY_PARAMS = Object.freeze({});\n\n/**\n * Stable empty options object\n */\nexport const EMPTY_OPTIONS = Object.freeze({});\n","// packages/react/modules/hooks/useStableValue.tsx\n\nimport { useMemo } from \"react\";\n\n/**\n * Stabilizes a value reference based on deep equality (via JSON serialization).\n * Returns the same reference until the serialized value changes.\n *\n * Useful for object/array dependencies in hooks like useMemo, useCallback, useEffect\n * to prevent unnecessary re-renders when the value is structurally the same.\n *\n * @example\n * ```tsx\n * const stableParams = useStableValue(routeParams);\n * const href = useMemo(() => {\n * return router.buildUrl(routeName, stableParams);\n * }, [router, routeName, stableParams]);\n * ```\n *\n * @param value - The value to stabilize\n * @returns A stable reference to the value\n */\nexport function useStableValue<T>(value: T): T {\n const serialized = JSON.stringify(value);\n\n // We intentionally use serialized in deps to detect deep changes\n // eslint-disable-next-line @eslint-react/exhaustive-deps\n return useMemo(() => value, [serialized]);\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\nimport { useStableValue } from \"./useStableValue\";\n\nimport type { Params } from \"@real-router/core\";\n\nexport function useIsActiveRoute(\n routeName: string,\n params?: Params,\n strict = false,\n ignoreQueryParams = true,\n): boolean {\n const router = useRouter();\n\n // useStableValue: JSON.stringify memoization of params object.\n // Without it, every render with a new params reference (e.g.,\n // <Link routeParams={{ id: '123' }} />) would recreate the store.\n const stableParams = useStableValue(params);\n\n const store = useMemo(\n () =>\n createActiveRouteSource(router, routeName, stableParams, {\n strict,\n ignoreQueryParams,\n }),\n [router, routeName, stableParams, strict, ignoreQueryParams],\n );\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n}\n","import { shouldNavigate, buildHref, buildActiveClassName } from \"dom-utils\";\nimport { memo, useCallback, useMemo } from \"react\";\n\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { useIsActiveRoute } from \"../hooks/useIsActiveRoute\";\nimport { useRouter } from \"../hooks/useRouter\";\nimport { useStableValue } from \"../hooks/useStableValue\";\n\nimport type { LinkProps } from \"../types\";\nimport type { FC, MouseEvent } from \"react\";\n\nfunction areLinkPropsEqual(\n prev: Readonly<LinkProps>,\n next: Readonly<LinkProps>,\n): boolean {\n return (\n prev.routeName === next.routeName &&\n prev.className === next.className &&\n prev.activeClassName === next.activeClassName &&\n prev.activeStrict === next.activeStrict &&\n prev.ignoreQueryParams === next.ignoreQueryParams &&\n prev.onClick === next.onClick &&\n prev.target === next.target &&\n prev.style === next.style &&\n prev.children === next.children &&\n JSON.stringify(prev.routeParams) === JSON.stringify(next.routeParams) &&\n JSON.stringify(prev.routeOptions) === JSON.stringify(next.routeOptions)\n );\n}\n\nexport const Link: FC<LinkProps> = memo(\n ({\n routeName,\n routeParams = EMPTY_PARAMS,\n routeOptions = EMPTY_OPTIONS,\n className,\n activeClassName = \"active\",\n activeStrict = false,\n ignoreQueryParams = true,\n onClick,\n target,\n children,\n ...props\n }) => {\n const router = useRouter();\n\n const stableParams = useStableValue(routeParams);\n const stableOptions = useStableValue(routeOptions);\n\n const isActive = useIsActiveRoute(\n routeName,\n stableParams,\n activeStrict,\n ignoreQueryParams,\n );\n\n const href = useMemo(\n () => buildHref(router, routeName, stableParams),\n [router, routeName, stableParams],\n );\n\n const handleClick = useCallback(\n (evt: MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt.nativeEvent) || target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router.navigate(routeName, stableParams, stableOptions).catch(() => {});\n },\n [onClick, target, router, routeName, stableParams, stableOptions],\n );\n\n const finalClassName = useMemo(\n () => buildActiveClassName(isActive, activeClassName, className),\n [isActive, activeClassName, className],\n );\n\n return (\n <a\n {...props}\n href={href}\n className={finalClassName}\n onClick={handleClick}\n >\n {children}\n </a>\n );\n },\n areLinkPropsEqual,\n);\n\nLink.displayName = \"Link\";\n","import { createErrorSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { RouterErrorSnapshot, RouterSource } from \"@real-router/sources\";\n\nconst cache = new WeakMap<Router, RouterSource<RouterErrorSnapshot>>();\n\nexport function useRouterError(): RouterErrorSnapshot {\n const router = useRouter();\n const store = useMemo(() => {\n let source = cache.get(router);\n\n if (!source) {\n source = createErrorSource(router);\n cache.set(router, source);\n }\n\n return source;\n }, [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useRouterError } from \"../hooks/useRouterError\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { ReactNode, JSX } from \"react\";\n\nexport interface RouterErrorBoundaryProps {\n readonly children: ReactNode;\n readonly fallback: (error: RouterError, resetError: () => void) => ReactNode;\n readonly onError?: (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void;\n}\n\nexport function RouterErrorBoundary({\n children,\n fallback,\n onError,\n}: RouterErrorBoundaryProps): JSX.Element {\n const snapshot = useRouterError();\n const [dismissedVersion, setDismissedVersion] = useState(-1);\n\n const onErrorRef = useRef(onError);\n\n // eslint-disable-next-line @eslint-react/refs -- \"latest ref\" pattern: sync callback to ref to avoid effect re-runs\n onErrorRef.current = onError;\n\n useEffect(() => {\n if (snapshot.error) {\n onErrorRef.current?.(\n snapshot.error,\n snapshot.toRoute,\n snapshot.fromRoute,\n );\n }\n // eslint-disable-next-line @eslint-react/exhaustive-deps -- onError tracked via ref, snapshot fields accessed inside callback\n }, [snapshot.version]);\n\n const visibleError =\n snapshot.version > dismissedVersion ? snapshot.error : null;\n\n const resetError = useCallback(() => {\n setDismissedVersion(snapshot.version);\n }, [snapshot.version]);\n\n return (\n <>\n {children}\n {visibleError ? fallback(visibleError, resetError) : null}\n </>\n );\n}\n","// packages/react/modules/hooks/useNavigator.tsx\n\nimport { useContext } from \"react\";\n\nimport { NavigatorContext } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = useContext(NavigatorContext);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","// packages/react/modules/hooks/useRouteUtils.tsx\n\nimport { getPluginApi } from \"@real-router/core/api\";\nimport { getRouteUtils } from \"@real-router/route-utils\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteUtils } from \"@real-router/route-utils\";\n\n/**\n * Returns a pre-computed {@link RouteUtils} instance for the current router.\n *\n * Internally retrieves the route tree via `getPluginApi` and delegates\n * to `getRouteUtils`, which caches instances per tree reference (WeakMap).\n *\n * @returns RouteUtils instance with pre-computed chains and siblings\n *\n * @example\n * ```tsx\n * const utils = useRouteUtils();\n *\n * utils.getChain(\"users.profile\");\n * // → [\"users\", \"users.profile\"]\n *\n * utils.getSiblings(\"users\");\n * // → [\"admin\"]\n *\n * utils.isDescendantOf(\"users.profile\", \"users\");\n * // → true\n * ```\n */\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","// packages/react/modules/hooks/useRoute.tsx\n\nimport { useContext } from \"react\";\n\nimport { RouteContext } from \"../context\";\n\nimport type { RouteContext as RouteContextType } from \"../types\";\n\nexport const useRoute = (): RouteContextType => {\n const routeContext = useContext(RouteContext);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouteProvider\");\n }\n\n return routeContext;\n};\n","import { createTransitionSource } from \"@real-router/sources\";\nimport { useMemo, useSyncExternalStore } from \"react\";\n\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\n\nexport function useRouterTransition(): RouterTransitionSnapshot {\n const router = useRouter();\n\n const store = useMemo(() => createTransitionSource(router), [router]);\n\n return useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n}\n","import { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { createRouteAnnouncer } from \"dom-utils\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { NavigatorContext, RouteContext, RouterContext } from \"./context\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { FC, ReactNode } from \"react\";\n\nexport interface RouteProviderProps {\n router: Router;\n children: ReactNode;\n announceNavigation?: boolean;\n}\n\nexport const RouterProvider: FC<RouteProviderProps> = ({\n router,\n children,\n announceNavigation,\n}) => {\n useEffect(() => {\n if (!announceNavigation) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n return () => {\n announcer.destroy();\n };\n }, [announceNavigation, router]);\n\n const navigator = useMemo(() => getNavigator(router), [router]);\n\n // useSyncExternalStore manages the router subscription lifecycle:\n // subscribe connects to router on first listener, unsubscribes on last.\n // This is Strict Mode safe — no useEffect cleanup needed.\n const store = useMemo(() => createRouteSource(router), [router]);\n const { route, previousRoute } = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot, // SSR: router returns same state on server and client\n );\n\n const routeContextValue = useMemo(\n () => ({ navigator, route, previousRoute }),\n [navigator, route, previousRoute],\n );\n\n return (\n <RouterContext value={router}>\n <NavigatorContext value={navigator}>\n <RouteContext value={routeContextValue}>{children}</RouteContext>\n </NavigatorContext>\n </RouterContext>\n );\n};\n"],"mappings":"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"}