@real-router/vue 0.6.3 → 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
@@ -460,11 +460,33 @@ Or in a template:
460
460
 
461
461
  When enabled, a visually hidden `aria-live` region announces each navigation. Focus moves to the first `<h1>` on the new page. See [Accessibility guide](https://github.com/greydragon888/real-router/wiki/Accessibility) for details.
462
462
 
463
+ ## Scroll Restoration
464
+
465
+ Opt-in preservation of scroll position across navigations:
466
+
467
+ ```vue
468
+ <RouterProvider :router="router" :scroll-restoration="{ mode: 'restore' }">
469
+ <!-- Your app -->
470
+ </RouterProvider>
471
+ ```
472
+
473
+ Or via `h()`:
474
+
475
+ ```typescript
476
+ h(
477
+ RouterProvider,
478
+ { router, scrollRestoration: { mode: "restore" } },
479
+ { default: () => [/* Your app */] },
480
+ );
481
+ ```
482
+
483
+ Restores scroll on back/forward, scrolls to top (or `#hash`) on push. Three modes: `"restore"` (default), `"top"`, `"manual"`. Custom containers via `scrollContainer: () => HTMLElement | null`. Prop is reactive — toggling mode at runtime reconfigures the utility (watched by primitive fields, so inline objects with the same fields do not thrash). See [Scroll Restoration guide](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) for details.
484
+
463
485
  ## Documentation
464
486
 
465
487
  Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
466
488
 
467
- - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link)
489
+ - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [Scroll Restoration](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration)
468
490
  - [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition)
469
491
 
470
492
  ## Examples
@@ -265,6 +265,14 @@ declare function useRouterTransition(): ShallowRef<RouterTransitionSnapshot$1>;
265
265
  //#region src/createRouterPlugin.d.ts
266
266
  declare function createRouterPlugin(router: Router): Plugin<[]>;
267
267
  //#endregion
268
+ //#region ../../shared/dom-utils/scroll-restore.d.ts
269
+ type ScrollRestorationMode = "restore" | "top" | "manual";
270
+ interface ScrollRestorationOptions {
271
+ mode?: ScrollRestorationMode | undefined;
272
+ anchorScrolling?: boolean | undefined;
273
+ scrollContainer?: (() => HTMLElement | null) | undefined;
274
+ }
275
+ //#endregion
268
276
  //#region src/RouterProvider.d.ts
269
277
  declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
270
278
  router: {
@@ -275,6 +283,9 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
275
283
  type: BooleanConstructor;
276
284
  default: boolean;
277
285
  };
286
+ scrollRestoration: {
287
+ type: PropType<ScrollRestorationOptions>;
288
+ };
278
289
  }>, () => _$vue.VNode<_$vue.RendererNode, _$vue.RendererElement, {
279
290
  [key: string]: any;
280
291
  }>[] | undefined, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
@@ -286,6 +297,9 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
286
297
  type: BooleanConstructor;
287
298
  default: boolean;
288
299
  };
300
+ scrollRestoration: {
301
+ type: PropType<ScrollRestorationOptions>;
302
+ };
289
303
  }>> & Readonly<{}>, {
290
304
  announceNavigation: boolean;
291
305
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/createRouterPlugin.ts","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`@real-router/sources`),i=require(`@real-router/core/api`);function a(){return null}const o=(0,e.defineComponent)({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:a}),s=(0,e.defineComponent)({name:`RouteView.NotFound`,render:a});function c(e,t,r){return r?e===t:(0,n.startsWithSegment)(e,t)}function l(t){if(Array.isArray(t)){let n=[];for(let r of t)Array.isArray(r)?n.push(...l(r)):(0,e.isVNode)(r)&&n.push(r);return n}return(0,e.isVNode)(t)?[t]:[]}function u(t,n){let r=l(t);for(let t of r)t.type===o||t.type===s?n.push(t):t.type===e.Fragment&&u(t.children,n)}function d(e,n,r){let i=null,a=!1,o,l=[];for(let t of e){if(t.type===s){i=t.children;continue}let e=t.props,u=e?.segment??``,d=e?.exact??!1,f=r?`${r}.${u}`:u;!a&&c(n,f,d)&&(a=!0,o=e?.fallback,l.push(t))}if(!a&&n===t.UNKNOWN_ROUTE&&i!==null){let t=e.filter(e=>e.type===s).at(-1);t&&l.push(t)}return{rendered:l,activeMatchFound:a,fallback:o}}function f(t){let n=(0,e.shallowRef)(t.getSnapshot());return(0,e.onScopeDispose)(t.subscribe(()=>{n.value=t.getSnapshot()})),n}const p=Symbol(`RouterKey`),m=Symbol(`NavigatorKey`),h=Symbol(`RouteKey`),g=()=>{let t=(0,e.inject)(p);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function _(n){let i=g(),a=f((0,r.createRouteNodeSource)(i,n));return{navigator:(0,t.getNavigator)(i),route:(0,e.computed)(()=>a.value.route),previousRoute:(0,e.computed)(()=>a.value.previousRoute)}}function v(e){return e.children?.default?.()??null}function y(t,n){let r=t.get(n);if(r)return r;let i=(0,e.markRaw)((0,e.defineComponent)({name:`KeepAlive-${n}`,setup(e,t){return()=>t.slots.default?.()}}));return t.set(n,i),i}function b(t,n){if(n===void 0)return t;let r=typeof n==`function`?n():n;return(0,e.h)(e.Suspense,{},{default:()=>t,fallback:()=>r})}const x=(0,e.markRaw)((0,e.defineComponent)({name:`KeepAlive-placeholder`,render(){return null}}));function S(t,n,r){let i=t.props?.segment??`__not-found__`,a=y(n,i),o=v(t)??[];return b((0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:i},{default:()=>o})}),r)}function C(e){return e===!0||e===``||e===`keep-alive`}function w(t,n,r){let i=t.props;if(C(i?.keepAlive)&&t.type===o){let r=i?.segment??`__not-found__`,a=y(n,r),o=v(t)??[];return(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:r},{default:()=>o})})])}let a=v(t);return a?(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(x)}),b((0,e.h)(e.Fragment,a),r)]):null}const T=(0,e.defineComponent)({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(t,{slots:n}){let r=_(t.nodeName),i=new Map,a=null,c=!1;function l(e,t){return t===a?c:(a=t,c=e.some(e=>e.type===o&&C(e.props?.keepAlive)),c)}return()=>{let a=r.route.value;if(!a)return null;let c=n.default?.(),f=[];u(c,f);let{rendered:p,fallback:m}=d(f,a.name,t.nodeName);if(p.length===0)return null;let h=p[0];if(t.keepAlive)return S(h,i,m);if(h.type!==o&&h.type!==s)return null;if(l(f,c))return w(h,i,m);let g=v(h);return g?b((0,e.h)(e.Fragment,g),m):null}}}),E=Object.assign(T,{Match:o,NotFound:s}),D=Object.freeze({}),O=Object.freeze({}),k=`data-real-router-announcer`;function A(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=j(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),N(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=ee(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),M()}}}function j(){let e=document.querySelector(`[${k}]`);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(k,``),document.body.prepend(t),t}function M(){document.querySelector(`[${k}]`)?.remove()}function ee(e,t,n,r){if(n)return n(e);let i=r?.textContent.trim()??``,a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function N(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function P(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function F(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function I(e){return e?e.match(/\S+/g)??[]:[]}function L(e,t,n){if(e&&t){let e=I(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=I(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function R(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function z(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const B=(0,e.defineComponent)({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>D},routeOptions:{type:Object,default:()=>O},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0}},setup(t,{slots:n,attrs:i}){let a=g(),o=(0,e.shallowRef)(!1);(0,e.watch)(()=>[t.routeName,t.routeParams,t.activeStrict,t.ignoreQueryParams],([e,t,n,i],s,c)=>{let l=(0,r.createActiveRouteSource)(a,e,t,{strict:n,ignoreQueryParams:i});o.value=l.getSnapshot(),c(l.subscribe(()=>{o.value=l.getSnapshot()}))},{immediate:!0,flush:`sync`});let s=(0,e.computed)(()=>F(a,t.routeName,t.routeParams)),c=(0,e.computed)(()=>L(o.value,t.activeClassName,t.class)),l=e=>{i.onClick!==void 0&&i.onClick!==null&&(z(i.onClick,e),e.defaultPrevented)||!P(e)||t.target===`_blank`||(e.preventDefault(),a.navigate(t.routeName,t.routeParams,t.routeOptions).catch(()=>{}))};return()=>{let r={};for(let e of Object.keys(i))e!==`onClick`&&(r[e]=i[e]);return(0,e.h)(`a`,{...r,href:s.value,class:c.value,target:t.target,onClick:l},n.default?.())}}}),V=(0,e.defineComponent)({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(t,{slots:n}){let i=f((0,r.createDismissableError)(g()));return(0,e.watch)(()=>i.value.version,()=>{i.value.error&&t.onError?.(i.value.error,i.value.toRoute,i.value.fromRoute)},{immediate:!0}),()=>{let r=n.default?.()??[],a=i.value.error?t.fallback(i.value.error,i.value.resetError):null;return(0,e.h)(e.Fragment,null,[...r,a])}}}),H=[];function U(e){return H.push(e),()=>{let t=H.lastIndexOf(e);t!==-1&&H.splice(t,1)}}function W(){let e=H.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const G=new WeakMap;function K(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function q(e,t){return n=>{P(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function J(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function Y(e,t,n){let r=q(t,n),i=J(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),G.set(e,{click:r,keydown:i})}function X(e){let t=G.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),G.delete(e))}const Z={mounted(e,t){let n=W();R(e),e.style.cursor=`pointer`,K(t.value)&&Y(e,n,t.value)},updated(e,t){let n=W();X(e),K(t.value)&&Y(e,n,t.value)},beforeUnmount(e){X(e)}},Q=()=>{let t=(0,e.inject)(m);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},te=()=>(0,n.getRouteUtils)((0,i.getPluginApi)(g()).getTree()),ne=()=>{let t=(0,e.inject)(h);if(!t)throw Error(`useRoute must be used within a RouterProvider`);return t};function re(){return f((0,r.getTransitionSource)(g()))}function $(n){let i=(0,t.getNavigator)(n),a=(0,r.createRouteSource)(n),o=a.getSnapshot(),s=(0,e.shallowRef)(o.route),c=(0,e.shallowRef)(o.previousRoute);return{navigator:i,route:s,previousRoute:c,unsubscribe:a.subscribe(()=>{let e=a.getSnapshot();s.value=e.route,c.value=e.previousRoute})}}function ie(e){return{install(t){let n=U(e),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e);`onUnmount`in t&&t.onUnmount(()=>{n(),o()}),t.provide(p,e),t.provide(m,r),t.provide(h,{navigator:r,route:i,previousRoute:a})}}}const ae=(0,e.defineComponent)({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1}},setup(t,{slots:n}){(0,e.watch)(()=>[t.router,t.announceNavigation],([e,t],n,r)=>{if(!t)return;let i=A(e);r(()=>{i.destroy()})},{immediate:!0});let r=U(t.router),{navigator:i,route:a,previousRoute:o,unsubscribe:s}=$(t.router);return(0,e.onScopeDispose)(()=>{r(),s()}),(0,e.provide)(p,t.router),(0,e.provide)(m,i),(0,e.provide)(h,{navigator:i,route:a,previousRoute:o}),()=>n.default?.()}});exports.Link=B,exports.NavigatorKey=m,exports.RouteKey=h,exports.RouteView=E,exports.RouterErrorBoundary=V,exports.RouterKey=p,exports.RouterProvider=ae,exports.createRouterPlugin=ie,exports.useNavigator=Q,exports.useRoute=ne,exports.useRouteNode=_,exports.useRouteUtils=te,exports.useRouter=g,exports.useRouterTransition=re,exports.vLink=Z;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`),t=require(`@real-router/core`),n=require(`@real-router/route-utils`),r=require(`@real-router/sources`),i=require(`@real-router/core/api`);function a(){return null}const o=(0,e.defineComponent)({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:a}),s=(0,e.defineComponent)({name:`RouteView.NotFound`,render:a});function c(e,t,r){return r?e===t:(0,n.startsWithSegment)(e,t)}function l(t){if(Array.isArray(t)){let n=[];for(let r of t)Array.isArray(r)?n.push(...l(r)):(0,e.isVNode)(r)&&n.push(r);return n}return(0,e.isVNode)(t)?[t]:[]}function u(t,n){let r=l(t);for(let t of r)t.type===o||t.type===s?n.push(t):t.type===e.Fragment&&u(t.children,n)}function d(e,n,r){let i=null,a=!1,o,l=[];for(let t of e){if(t.type===s){i=t.children;continue}let e=t.props,u=e?.segment??``,d=e?.exact??!1,f=r?`${r}.${u}`:u;!a&&c(n,f,d)&&(a=!0,o=e?.fallback,l.push(t))}if(!a&&n===t.UNKNOWN_ROUTE&&i!==null){let t=e.filter(e=>e.type===s).at(-1);t&&l.push(t)}return{rendered:l,activeMatchFound:a,fallback:o}}function f(t){let n=(0,e.shallowRef)(t.getSnapshot());return(0,e.onScopeDispose)(t.subscribe(()=>{n.value=t.getSnapshot()})),n}const p=Symbol(`RouterKey`),m=Symbol(`NavigatorKey`),h=Symbol(`RouteKey`),g=()=>{let t=(0,e.inject)(p);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function _(n){let i=g(),a=f((0,r.createRouteNodeSource)(i,n));return{navigator:(0,t.getNavigator)(i),route:(0,e.computed)(()=>a.value.route),previousRoute:(0,e.computed)(()=>a.value.previousRoute)}}function v(e){return e.children?.default?.()??null}function y(t,n){let r=t.get(n);if(r)return r;let i=(0,e.markRaw)((0,e.defineComponent)({name:`KeepAlive-${n}`,setup(e,t){return()=>t.slots.default?.()}}));return t.set(n,i),i}function b(t,n){if(n===void 0)return t;let r=typeof n==`function`?n():n;return(0,e.h)(e.Suspense,{},{default:()=>t,fallback:()=>r})}const ee=(0,e.markRaw)((0,e.defineComponent)({name:`KeepAlive-placeholder`,render(){return null}}));function x(t,n,r){let i=t.props?.segment??`__not-found__`,a=y(n,i),o=v(t)??[];return b((0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:i},{default:()=>o})}),r)}function S(e){return e===!0||e===``||e===`keep-alive`}function C(t,n,r){let i=t.props;if(S(i?.keepAlive)&&t.type===o){let r=i?.segment??`__not-found__`,a=y(n,r),o=v(t)??[];return(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:r},{default:()=>o})})])}let a=v(t);return a?(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(ee)}),b((0,e.h)(e.Fragment,a),r)]):null}const w=(0,e.defineComponent)({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(t,{slots:n}){let r=_(t.nodeName),i=new Map,a=null,c=!1;function l(e,t){return t===a?c:(a=t,c=e.some(e=>e.type===o&&S(e.props?.keepAlive)),c)}return()=>{let a=r.route.value;if(!a)return null;let c=n.default?.(),f=[];u(c,f);let{rendered:p,fallback:m}=d(f,a.name,t.nodeName);if(p.length===0)return null;let h=p[0];if(t.keepAlive)return x(h,i,m);if(h.type!==o&&h.type!==s)return null;if(l(f,c))return C(h,i,m);let g=v(h);return g?b((0,e.h)(e.Fragment,g),m):null}}}),te=Object.assign(w,{Match:o,NotFound:s}),ne=Object.freeze({}),re=Object.freeze({}),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=null,l,u=D(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),A(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=k(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),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,r){if(n)return n(e);let i=r?.textContent.trim()??``,a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function A(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const j=`real-router:scroll`,M=Object.freeze({destroy:()=>{}});function ie(e,t){if(globalThis.window===void 0)return M;let n=t?.mode??`restore`;if(n===`manual`)return M;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let o=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},s=e=>{let t=i?.();t?t.scrollTop=e:globalThis.scrollTo(0,e)},c=()=>{let e=globalThis.location.hash;if(r&&e.length>1){let t;try{t=decodeURIComponent(e.slice(1))}catch{t=e.slice(1)}let n=document.getElementById(t);if(n){n.scrollIntoView();return}}s(0)},l=!1,u=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;t&&F(N(t),o()),requestAnimationFrame(()=>{if(!l){if(n===`top`||!r){c();return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){s(P()[N(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&F(N(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function N(e){return`${e.name}:${I(e.params)}`}function P(){try{let e=sessionStorage.getItem(j);return e?JSON.parse(e):{}}catch{return{}}}function F(e,t){try{let n=P();n[e]=t,sessionStorage.setItem(j,JSON.stringify(n))}catch{}}function I(e){return JSON.stringify(e,L)}function L(e,t){if(typeof t==`object`&&t&&!Array.isArray(t)){let e={},n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}function R(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function z(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function B(e){return e?e.match(/\S+/g)??[]:[]}function V(e,t,n){if(e&&t){let e=B(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=B(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function H(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function U(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const W=(0,e.defineComponent)({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>ne},routeOptions:{type:Object,default:()=>re},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0}},setup(t,{slots:n,attrs:i}){let a=g(),o=(0,e.shallowRef)(!1);(0,e.watch)(()=>[t.routeName,t.routeParams,t.activeStrict,t.ignoreQueryParams],([e,t,n,i],s,c)=>{let l=(0,r.createActiveRouteSource)(a,e,t,{strict:n,ignoreQueryParams:i});o.value=l.getSnapshot(),c(l.subscribe(()=>{o.value=l.getSnapshot()}))},{immediate:!0,flush:`sync`});let s=(0,e.computed)(()=>z(a,t.routeName,t.routeParams)),c=(0,e.computed)(()=>V(o.value,t.activeClassName,t.class)),l=e=>{i.onClick!==void 0&&i.onClick!==null&&(U(i.onClick,e),e.defaultPrevented)||!R(e)||t.target===`_blank`||(e.preventDefault(),a.navigate(t.routeName,t.routeParams,t.routeOptions).catch(()=>{}))};return()=>{let r={};for(let e of Object.keys(i))e!==`onClick`&&(r[e]=i[e]);return(0,e.h)(`a`,{...r,href:s.value,class:c.value,target:t.target,onClick:l},n.default?.())}}}),G=(0,e.defineComponent)({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(t,{slots:n}){let i=f((0,r.createDismissableError)(g()));return(0,e.watch)(()=>i.value.version,()=>{i.value.error&&t.onError?.(i.value.error,i.value.toRoute,i.value.fromRoute)},{immediate:!0}),()=>{let r=n.default?.()??[],a=i.value.error?t.fallback(i.value.error,i.value.resetError):null;return(0,e.h)(e.Fragment,null,[...r,a])}}}),K=[];function q(e){return K.push(e),()=>{let t=K.lastIndexOf(e);t!==-1&&K.splice(t,1)}}function J(){let e=K.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const Y=new WeakMap;function X(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function ae(e,t){return n=>{R(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function oe(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function Z(e,t,n){let r=ae(t,n),i=oe(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),Y.set(e,{click:r,keydown:i})}function Q(e){let t=Y.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),Y.delete(e))}const se={mounted(e,t){let n=J();H(e),e.style.cursor=`pointer`,X(t.value)&&Z(e,n,t.value)},updated(e,t){let n=J();Q(e),X(t.value)&&Z(e,n,t.value)},beforeUnmount(e){Q(e)}},ce=()=>{let t=(0,e.inject)(m);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},le=()=>(0,n.getRouteUtils)((0,i.getPluginApi)(g()).getTree()),ue=()=>{let t=(0,e.inject)(h);if(!t)throw Error(`useRoute must be used within a RouterProvider`);return t};function de(){return f((0,r.getTransitionSource)(g()))}function $(n){let i=(0,t.getNavigator)(n),a=(0,r.createRouteSource)(n),o=a.getSnapshot(),s=(0,e.shallowRef)(o.route),c=(0,e.shallowRef)(o.previousRoute);return{navigator:i,route:s,previousRoute:c,unsubscribe:a.subscribe(()=>{let e=a.getSnapshot();s.value=e.route,c.value=e.previousRoute})}}function fe(e){return{install(t){let n=q(e),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e);`onUnmount`in t&&t.onUnmount(()=>{n(),o()}),t.provide(p,e),t.provide(m,r),t.provide(h,{navigator:r,route:i,previousRoute:a})}}}const pe=(0,e.defineComponent)({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1},scrollRestoration:{type:Object}},setup(t,{slots:n}){(0,e.watch)(()=>[t.router,t.announceNavigation],([e,t],n,r)=>{if(!t)return;let i=E(e);r(()=>{i.destroy()})},{immediate:!0}),(0,e.watch)(()=>[t.router,t.scrollRestoration!==void 0,t.scrollRestoration?.mode,t.scrollRestoration?.anchorScrolling],([e,n,r,i],a,o)=>{if(!n)return;let s=ie(e,{mode:r,anchorScrolling:i,scrollContainer:t.scrollRestoration?.scrollContainer});o(()=>{s.destroy()})},{immediate:!0});let r=q(t.router),{navigator:i,route:a,previousRoute:o,unsubscribe:s}=$(t.router);return(0,e.onScopeDispose)(()=>{r(),s()}),(0,e.provide)(p,t.router),(0,e.provide)(m,i),(0,e.provide)(h,{navigator:i,route:a,previousRoute:o}),()=>n.default?.()}});exports.Link=W,exports.NavigatorKey=m,exports.RouteKey=h,exports.RouteView=te,exports.RouterErrorBoundary=G,exports.RouterKey=p,exports.RouterProvider=pe,exports.createRouterPlugin=fe,exports.useNavigator=ce,exports.useRoute=ue,exports.useRouteNode=_,exports.useRouteUtils=le,exports.useRouter=g,exports.useRouterTransition=de,exports.vLink=se;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Fragment","UNKNOWN_ROUTE","Suspense","KeepAlive","Fragment","Fragment"],"sources":["../../src/components/RouteView/components.ts","../../src/components/RouteView/helpers.ts","../../src/useRefFromSource.ts","../../src/context.ts","../../src/composables/useRouter.ts","../../src/composables/useRouteNode.ts","../../src/components/RouteView/RouteView.ts","../../src/constants.ts","../../../../shared/dom-utils/route-announcer.ts","../../../../shared/dom-utils/link-utils.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/composables/useRoute.ts","../../src/composables/useRouterTransition.ts","../../src/setupRouteProvision.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts"],"sourcesContent":["import { defineComponent } from \"vue\";\n\nimport type { PropType, VNode } from \"vue\";\n\nfunction renderNull() {\n return null;\n}\n\nexport const Match = defineComponent({\n name: \"RouteView.Match\",\n props: {\n segment: {\n type: String as PropType<string>,\n required: true,\n },\n exact: {\n type: Boolean,\n default: false,\n },\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n render: renderNull,\n});\n\nexport const NotFound = defineComponent({\n name: \"RouteView.NotFound\",\n render: renderNull,\n});\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isVNode } from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nfunction normalizeChildren(children: unknown): VNode[] {\n if (Array.isArray(children)) {\n const result: VNode[] = [];\n\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...normalizeChildren(child));\n } else if (isVNode(child)) {\n result.push(child);\n }\n }\n\n return result;\n }\n\n if (isVNode(children)) {\n return [children];\n }\n\n return [];\n}\n\nexport function collectElements(children: unknown, result: VNode[]): void {\n const vnodes = normalizeChildren(children);\n\n for (const child of vnodes) {\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): {\n rendered: VNode[];\n activeMatchFound: boolean;\n fallback?: FallbackType;\n} {\n let notFoundChildren: unknown = null;\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = child.children;\n continue;\n }\n\n const props = child.props as {\n segment: string;\n exact?: boolean;\n fallback?: FallbackType;\n } | null;\n const segment = props?.segment ?? \"\";\n const exact = props?.exact ?? false;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n fallback = props?.fallback;\n rendered.push(child);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n const nfElements = elements.filter((element) => element.type === NotFound);\n /* v8 ignore next 3 */\n const lastNf = nfElements.at(-1);\n\n if (lastNf) {\n rendered.push(lastNf);\n }\n }\n\n return { rendered, activeMatchFound, fallback };\n}\n","import { shallowRef, onScopeDispose } from \"vue\";\n\nimport type { RouterSource } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRefFromSource<T>(source: RouterSource<T>): ShallowRef<T> {\n const ref = shallowRef(source.getSnapshot());\n\n const unsub = source.subscribe(() => {\n ref.value = source.getSnapshot();\n });\n\n onScopeDispose(unsub);\n\n return ref;\n}\n","import type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n","import { inject } from \"vue\";\n\nimport { RouterKey } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = inject(RouterKey);\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 { computed } from \"vue\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const source = createRouteNodeSource(router, nodeName);\n const snapshot = useRefFromSource(source);\n\n // getNavigator is WeakMap-cached in core; no useMemo equivalent needed.\n const navigator = getNavigator(router);\n\n // Derive route/previousRoute via computed instead of mirroring with a sync\n // watch into two extra shallowRefs. computed shares snapshot's identity so\n // when the underlying source emits the same reference (idempotent or\n // out-of-node nav), consumers don't see a new ref.\n const route = computed(() => snapshot.value.route);\n const previousRoute = computed(() => snapshot.value.previousRoute);\n\n return {\n navigator,\n route,\n previousRoute,\n };\n}\n","import {\n Fragment,\n defineComponent,\n h,\n KeepAlive,\n markRaw,\n Suspense,\n} from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../composables/useRouteNode\";\n\nimport type { Component, VNode } from \"vue\";\n\ntype SlotChildren = Record<string, (() => VNode[]) | undefined> | null;\n\nfunction getSlotContent(vnode: VNode): VNode[] | null {\n const slots = vnode.children as SlotChildren;\n\n return slots?.default?.() ?? null;\n}\n\nfunction getOrCreateWrapper(\n cache: Map<string, Component>,\n segment: string,\n): Component {\n const existing = cache.get(segment);\n\n if (existing) {\n return existing;\n }\n\n const wrapper = markRaw(\n defineComponent({\n name: `KeepAlive-${segment}`,\n setup(_wrapperProps, wrapperCtx) {\n return () => wrapperCtx.slots.default?.();\n },\n }),\n );\n\n cache.set(segment, wrapper);\n\n return wrapper;\n}\n\nfunction wrapWithSuspense(content: VNode, fallback: unknown): VNode {\n if (fallback === undefined) {\n return content;\n }\n\n const fallbackContent =\n typeof fallback === \"function\" ? (fallback as () => VNode)() : fallback;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n const suspenseComponent = Suspense as any;\n\n return h(\n suspenseComponent,\n {},\n {\n default: () => content,\n fallback: () => fallbackContent,\n },\n );\n}\n\nconst emptyKeepAlivePlaceholder = markRaw(\n defineComponent({\n name: \"KeepAlive-placeholder\",\n render() {\n return null;\n },\n }),\n);\n\nfunction renderWithRootKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode {\n const activeProps = activeChild.props as { segment?: string } | null;\n const segment = activeProps?.segment ?? \"__not-found__\";\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n const keepAliveContent = h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n });\n\n return wrapWithSuspense(keepAliveContent, fallback);\n}\n\n// Vue compiles boolean-shorthand template attributes (`<Match keepAlive>`) to\n// an empty string instead of `true`, and converts them to `true` only when the\n// receiving component's prop is declared with `type: Boolean`. `Match` is a\n// marker component (`render: null`) — its props are inspected on the VNode\n// without ever going through Vue's prop-casting pipeline, so the raw `\"\"` (or\n// the hyphenated attribute name) reaches us here. Accept the same trio Vue's\n// runtime does.\nfunction isKeepAliveEnabled(value: unknown): boolean {\n return value === true || value === \"\" || value === \"keep-alive\";\n}\n\nfunction renderWithPerMatchKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode | null {\n const matchProps = activeChild.props as {\n segment?: string;\n keepAlive?: unknown;\n } | null;\n\n if (isKeepAliveEnabled(matchProps?.keepAlive) && activeChild.type === Match) {\n /* v8 ignore start */\n const segment = matchProps?.segment ?? \"__not-found__\";\n /* v8 ignore stop */\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n\n return h(Fragment, [\n h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n }),\n ]);\n }\n\n const content = getSlotContent(activeChild);\n\n /* v8 ignore start */\n if (!content) {\n return null;\n }\n /* v8 ignore stop */\n\n return h(Fragment, [\n h(KeepAlive, null, { default: () => h(emptyKeepAlivePlaceholder) }),\n wrapWithSuspense(h(Fragment, content), fallback),\n ]);\n}\n\nconst RouteViewComponent = defineComponent({\n name: \"RouteView\",\n props: {\n nodeName: {\n type: String,\n required: true,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n const routeContext = useRouteNode(props.nodeName);\n const wrapperCache = new Map<string, Component>();\n\n // Cache per-Match `keepAlive` detection by slot output identity. Slot\n // contents change reference only when the parent re-renders with new\n // children, so steady-state navigations skip the O(n) `.some(...)` scan.\n let lastSlotOutput: unknown = null;\n let lastHasPerMatchKA = false;\n\n function detectPerMatchKA(elements: VNode[], slotOutput: unknown): boolean {\n /* v8 ignore next 3 -- @preserve: Vue's compiled slot wrapper allocates a\n new array per render call in JSDOM tests; identity-cache hits in\n production where parent compiled templates share slot output, but\n is unobservable through TestBed-style assertions. */\n if (slotOutput === lastSlotOutput) {\n return lastHasPerMatchKA;\n }\n\n lastSlotOutput = slotOutput;\n lastHasPerMatchKA = elements.some(\n (element) =>\n element.type === Match &&\n isKeepAliveEnabled(\n (element.props as { keepAlive?: unknown } | null)?.keepAlive,\n ),\n );\n\n return lastHasPerMatchKA;\n }\n\n return (): VNode | null => {\n const route = routeContext.route.value;\n\n if (!route) {\n return null;\n }\n\n const slotOutput = slots.default?.();\n const elements: VNode[] = [];\n\n collectElements(slotOutput, elements);\n\n const { rendered, fallback } = buildRenderList(\n elements,\n route.name,\n props.nodeName,\n );\n\n if (rendered.length === 0) {\n return null;\n }\n\n const activeChild = rendered[0];\n\n if (props.keepAlive) {\n return renderWithRootKA(activeChild, wrapperCache, fallback);\n }\n\n /* v8 ignore start */\n if (activeChild.type !== Match && activeChild.type !== NotFound) {\n return null;\n }\n /* v8 ignore stop */\n\n const hasPerMatchKA = detectPerMatchKA(elements, slotOutput);\n\n if (hasPerMatchKA) {\n return renderWithPerMatchKA(activeChild, wrapperCache, fallback);\n }\n\n const content = getSlotContent(activeChild);\n\n if (!content) {\n return null;\n }\n\n return wrapWithSuspense(h(Fragment, content), fallback);\n };\n },\n});\n\nexport const RouteView = Object.assign(RouteViewComponent, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\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 { Router, State } from \"@real-router/core\";\n\nconst CLEAR_DELAY = 7000;\nconst SAFARI_READY_DELAY = 100;\nconst ANNOUNCER_ATTR = \"data-real-router-announcer\";\nconst INTERNAL_ROUTE_PREFIX = \"@@\";\nconst VISUALLY_HIDDEN =\n \"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\nexport interface RouteAnnouncerOptions {\n prefix?: string;\n getAnnouncementText?: (route: State) => string;\n}\n\nexport function createRouteAnnouncer(\n router: Router,\n options?: RouteAnnouncerOptions,\n): { destroy: () => void } {\n const prefix = options?.prefix ?? \"Navigated to \";\n const getCustomText = options?.getAnnouncementText;\n\n let isInitialNavigation = true;\n let isReady = false;\n let isDestroyed = false;\n let lastAnnouncedText = \"\";\n let pendingText: string | null = null;\n let clearTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const announcer = getOrCreateAnnouncer();\n\n const doAnnounce = (text: string, h1: HTMLElement | null): void => {\n lastAnnouncedText = text;\n clearTimeout(clearTimeoutId);\n announcer.textContent = text;\n clearTimeoutId = setTimeout(() => {\n announcer.textContent = \"\";\n lastAnnouncedText = \"\";\n }, CLEAR_DELAY);\n\n manageFocus(h1);\n };\n\n // Safari-ready delay: announcing before VoiceOver wires up the aria-live region\n // causes the first announcement to be silently dropped. Wait SAFARI_READY_DELAY ms\n // before marking the announcer \"ready\" — any navigation during that window is\n // buffered in pendingText and flushed once the delay expires.\n const safariTimeoutId = setTimeout(() => {\n isReady = true;\n\n if (pendingText !== null && !isDestroyed) {\n const text = pendingText;\n\n pendingText = null;\n doAnnounce(text, document.querySelector<HTMLElement>(\"h1\"));\n }\n }, SAFARI_READY_DELAY);\n\n const unsubscribe = router.subscribe(({ route }) => {\n if (isInitialNavigation) {\n isInitialNavigation = false;\n\n return;\n }\n\n // Double rAF: waits for two paint frames so the incoming route's DOM\n // (including the new <h1>) is fully rendered before resolveText reads it.\n // Single rAF fires before the new route's template has been attached,\n // which would cause resolveText to pick up the OLD h1 or fall back to\n // document.title / route.name prematurely.\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (isDestroyed) {\n return;\n }\n\n const h1 = document.querySelector<HTMLElement>(\"h1\");\n const text = resolveText(route, prefix, getCustomText, h1);\n\n if (!text || text === lastAnnouncedText) {\n return;\n }\n\n if (!isReady) {\n // Defer announcement until Safari-ready window elapses (see safariTimeoutId).\n pendingText = text;\n\n return;\n }\n\n doAnnounce(text, h1);\n });\n });\n });\n\n return {\n destroy() {\n isDestroyed = true;\n unsubscribe();\n clearTimeout(clearTimeoutId);\n clearTimeout(safariTimeoutId);\n removeAnnouncer();\n },\n };\n}\n\nfunction getOrCreateAnnouncer(): HTMLElement {\n const existing = document.querySelector<HTMLElement>(`[${ANNOUNCER_ATTR}]`);\n\n if (existing) {\n return existing;\n }\n\n const element = document.createElement(\"div\");\n\n element.setAttribute(\"style\", VISUALLY_HIDDEN);\n element.setAttribute(\"aria-live\", \"assertive\");\n element.setAttribute(\"aria-atomic\", \"true\");\n element.setAttribute(ANNOUNCER_ATTR, \"\");\n\n document.body.prepend(element);\n\n return element;\n}\n\nfunction removeAnnouncer(): void {\n document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();\n}\n\nfunction resolveText(\n route: State,\n prefix: string,\n getCustomText: ((route: State) => string) | undefined,\n h1: HTMLElement | null,\n): string {\n if (getCustomText) {\n return getCustomText(route);\n }\n\n const h1Text = h1?.textContent.trim() ?? \"\";\n const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX)\n ? \"\"\n : route.name;\n const rawText =\n h1Text || document.title || routeName || globalThis.location.pathname;\n\n return `${prefix}${rawText}`;\n}\n\nfunction manageFocus(h1: HTMLElement | null): void {\n if (!h1) {\n return;\n }\n\n if (!h1.hasAttribute(\"tabindex\")) {\n h1.setAttribute(\"tabindex\", \"-1\");\n }\n\n h1.focus({ preventScroll: true });\n}\n","import type { Router, Params } from \"@real-router/core\";\n\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 &&\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n\ntype BuildUrlFn = (name: string, params: Params) => string | undefined;\n\nexport function buildHref(\n router: Router,\n routeName: string,\n routeParams: Params,\n): string | undefined {\n try {\n const buildUrl = router.buildUrl as BuildUrlFn | undefined;\n\n if (buildUrl) {\n const url = buildUrl(routeName, routeParams);\n\n if (url !== undefined) {\n return url;\n }\n }\n\n return router.buildPath(routeName, routeParams);\n } catch {\n console.error(\n `[real-router] Route \"${routeName}\" is not defined. The element will render without an href attribute.`,\n );\n\n return undefined;\n }\n}\n\nfunction parseTokens(value: string | undefined): string[] {\n return value ? (value.match(/\\S+/g) ?? []) : [];\n}\n\nexport function buildActiveClassName(\n isActive: boolean,\n activeClassName: string | undefined,\n baseClassName: string | undefined,\n): string | undefined {\n if (isActive && activeClassName) {\n const activeTokens = parseTokens(activeClassName);\n\n if (activeTokens.length === 0) {\n return baseClassName ?? undefined;\n }\n if (!baseClassName) {\n return activeTokens.join(\" \");\n }\n\n const baseTokens = parseTokens(baseClassName);\n const seen = new Set(baseTokens);\n\n for (const token of activeTokens) {\n if (!seen.has(token)) {\n seen.add(token);\n baseTokens.push(token);\n }\n }\n\n return baseTokens.join(\" \");\n }\n\n return baseClassName ?? undefined;\n}\n\nexport function shallowEqual(\n prev: object | undefined,\n next: object | undefined,\n): boolean {\n if (Object.is(prev, next)) {\n return true;\n }\n if (!prev || !next) {\n return false;\n }\n\n const prevKeys = Object.keys(prev);\n\n if (prevKeys.length !== Object.keys(next).length) {\n return false;\n }\n\n const prevRecord = prev as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n\n for (const key of prevKeys) {\n if (!Object.is(prevRecord[key], nextRecord[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function applyLinkA11y(element: HTMLElement | null | undefined): void {\n if (!element) {\n return;\n }\n if (\n element instanceof HTMLAnchorElement ||\n element instanceof HTMLButtonElement\n ) {\n return;\n }\n if (!element.hasAttribute(\"role\")) {\n element.setAttribute(\"role\", \"link\");\n }\n if (!element.hasAttribute(\"tabindex\")) {\n element.setAttribute(\"tabindex\", \"0\");\n }\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { defineComponent, h, computed, shallowRef, watch } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport {\n shouldNavigate,\n buildHref,\n buildActiveClassName,\n} from \"../dom-utils/index.js\";\n\nimport type { Params, NavigationOptions } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\ntype OnClickHandler = (evt: MouseEvent) => void;\n\n/**\n * Vue's compiled template binds multiple `@click` handlers as an array.\n * Single render-function `onClick` is a function. Both must be invoked.\n */\nfunction invokeAttributesOnClick(value: unknown, evt: MouseEvent): void {\n if (typeof value === \"function\") {\n (value as OnClickHandler)(evt);\n\n return;\n }\n if (Array.isArray(value)) {\n const handlers = value as OnClickHandler[];\n\n for (const fn of handlers) {\n if (typeof fn === \"function\") {\n fn(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n }\n }\n}\n\nexport const Link = defineComponent({\n name: \"Link\",\n // Disable Vue's automatic attribute fallthrough. Without this, attrs.onClick\n // (function OR array) is auto-attached as a native click listener AND our\n // explicit onClick fires too — user handlers are double-invoked. We invoke\n // attrs.onClick manually inside handleClick to preserve preventDefault.\n inheritAttrs: false,\n props: {\n routeName: {\n type: String,\n required: true,\n },\n routeParams: {\n type: Object as PropType<Params>,\n default: () => EMPTY_PARAMS,\n },\n routeOptions: {\n type: Object as PropType<NavigationOptions>,\n default: () => EMPTY_OPTIONS,\n },\n class: {\n type: String,\n default: undefined,\n },\n activeClassName: {\n type: String,\n default: \"active\",\n },\n activeStrict: {\n type: Boolean,\n default: false,\n },\n ignoreQueryParams: {\n type: Boolean,\n default: true,\n },\n target: {\n type: String,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const router = useRouter();\n\n const isActive = shallowRef(false);\n\n // watch with an explicit dep getter recreates the source ONLY when\n // routeName/routeParams/strict/ignoreQueryParams change — not on every\n // reactive read inside the source factory (the watchEffect alternative\n // would also re-subscribe whenever isActive itself changed).\n watch(\n () =>\n [\n props.routeName,\n props.routeParams,\n props.activeStrict,\n props.ignoreQueryParams,\n ] as const,\n (\n [routeName, routeParams, activeStrict, ignoreQueryParams],\n _prev,\n onCleanup,\n ) => {\n const source = createActiveRouteSource(router, routeName, routeParams, {\n strict: activeStrict,\n ignoreQueryParams,\n });\n\n isActive.value = source.getSnapshot();\n\n const unsub = source.subscribe(() => {\n isActive.value = source.getSnapshot();\n });\n\n onCleanup(unsub);\n },\n { immediate: true, flush: \"sync\" },\n );\n\n const href = computed(() =>\n buildHref(router, props.routeName, props.routeParams),\n );\n\n const finalClassName = computed(() =>\n buildActiveClassName(isActive.value, props.activeClassName, props.class),\n );\n\n const handleClick = (evt: MouseEvent) => {\n // Vue allows attrs.onClick to be a function or an array of functions\n // (compiled templates with multiple @click bindings produce arrays).\n // Both must be invoked; treating arrays as \"no handler\" silently drops\n // user code.\n if (attrs.onClick !== undefined && attrs.onClick !== null) {\n invokeAttributesOnClick(attrs.onClick, evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || props.target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(props.routeName, props.routeParams, props.routeOptions)\n .catch(() => {});\n };\n\n return () => {\n // Build forwarded attrs without `onClick`. Vue's runtime auto-attaches\n // attrs.onClick (function OR array) as a native DOM listener, which would\n // double-invoke user handlers when combined with our explicit `onClick`.\n // We invoke the original attrs.onClick manually inside handleClick so the\n // preventDefault contract is preserved.\n const restAttributes: Record<string, unknown> = {};\n\n for (const key of Object.keys(attrs)) {\n if (key !== \"onClick\") {\n restAttributes[key] = (attrs as Record<string, unknown>)[key];\n }\n }\n\n return h(\n \"a\",\n {\n ...restAttributes,\n href: href.value,\n class: finalClassName.value,\n target: props.target,\n onClick: handleClick,\n },\n slots.default?.(),\n );\n };\n },\n});\n","import { createDismissableError } from \"@real-router/sources\";\nimport { defineComponent, h, watch, Fragment } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { useRefFromSource } from \"../useRefFromSource\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { VNode, PropType } from \"vue\";\n\nexport const RouterErrorBoundary = defineComponent({\n name: \"RouterErrorBoundary\",\n props: {\n fallback: {\n type: Function as PropType<\n (error: RouterError, resetError: () => void) => VNode\n >,\n required: true,\n },\n onError: {\n type: Function as PropType<\n (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void\n >,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const router = useRouter();\n const snapshot = useRefFromSource(createDismissableError(router));\n\n watch(\n () => snapshot.value.version,\n () => {\n if (snapshot.value.error) {\n props.onError?.(\n snapshot.value.error,\n snapshot.value.toRoute,\n snapshot.value.fromRoute,\n );\n }\n },\n { immediate: true },\n );\n\n return () => {\n const children = slots.default?.() ?? [];\n const errorVNode = snapshot.value.error\n ? props.fallback(snapshot.value.error, snapshot.value.resetError)\n : null;\n\n return h(Fragment, null, [...children, errorVNode]);\n };\n },\n});\n\nexport type RouterErrorBoundaryProps = InstanceType<\n typeof RouterErrorBoundary\n>[\"$props\"];\n","import { shouldNavigate, applyLinkA11y } from \"../dom-utils/index.js\";\n\nimport type { Router, NavigationOptions, Params } from \"@real-router/core\";\nimport type { Directive } from \"vue\";\n\nexport interface LinkDirectiveValue {\n name: string;\n params?: Params;\n options?: NavigationOptions;\n}\n\n/**\n * Router stack for nested RouterProviders. The active router is the top of\n * the stack. RouterProvider pushes its router on mount and pops it on unmount,\n * which preserves the parent context when an inner provider tears down.\n *\n * Without the stack, an unmounted child provider would leave the directive\n * pointing at a disposed router, and v-link in the still-mounted parent would\n * navigate via the wrong (or torn-down) instance.\n */\nconst routerStack: Router[] = [];\n\n/**\n * Pushes a router onto the active stack. Returns a release function that\n * removes that exact router from the stack regardless of position — safe\n * across out-of-order provider unmount sequences.\n *\n * @internal Used by RouterProvider during setup/teardown.\n */\nexport function pushDirectiveRouter(router: Router): () => void {\n routerStack.push(router);\n\n return () => {\n const idx = routerStack.lastIndexOf(router);\n\n if (idx !== -1) {\n routerStack.splice(idx, 1);\n }\n };\n}\n\n/**\n * Backwards-compatible alias. Replaces the active router unconditionally and\n * does NOT participate in the stack — use {@link pushDirectiveRouter} from\n * provider code instead. Kept for tests and direct callers.\n */\nexport function setDirectiveRouter(router: Router | null): void {\n if (router === null) {\n routerStack.length = 0;\n\n return;\n }\n if (routerStack.length === 0) {\n routerStack.push(router);\n\n return;\n }\n\n routerStack[routerStack.length - 1] = router;\n}\n\nexport function getDirectiveRouter(): Router {\n const top = routerStack.at(-1);\n\n if (!top) {\n throw new Error(\n \"v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.\",\n );\n }\n\n return top;\n}\n\ninterface Handlers {\n click: (evt: MouseEvent) => void;\n keydown: (evt: KeyboardEvent) => void;\n}\n\n// Single WeakMap halves per-element bookkeeping vs two parallel maps.\nconst handlers = new WeakMap<HTMLElement, Handlers>();\n\n/**\n * Validates a directive binding value before attaching handlers.\n * Returns false (and warns once per call) when the value is missing or\n * has no `name` — silently doing nothing is preferable to a runtime crash\n * inside a click handler.\n */\nfunction isValidBinding(value: unknown): value is LinkDirectiveValue {\n if (value === null || value === undefined) {\n console.error(\n \"[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n if (typeof (value as { name?: unknown }).name !== \"string\") {\n console.error(\n \"[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n\n return true;\n}\n\nfunction createClickHandler(\n router: Router,\n value: LinkDirectiveValue,\n): (evt: MouseEvent) => void {\n return (evt: MouseEvent) => {\n if (!shouldNavigate(evt)) {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n };\n}\n\nfunction createKeydownHandler(\n router: Router,\n value: LinkDirectiveValue,\n element: HTMLElement,\n): (evt: KeyboardEvent) => void {\n return (evt: KeyboardEvent) => {\n if (evt.key === \"Enter\" && !(element instanceof HTMLButtonElement)) {\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n }\n };\n}\n\nfunction attachHandlers(\n element: HTMLElement,\n router: Router,\n value: LinkDirectiveValue,\n): void {\n const click = createClickHandler(router, value);\n const keydown = createKeydownHandler(router, value, element);\n\n element.addEventListener(\"click\", click);\n element.addEventListener(\"keydown\", keydown);\n\n handlers.set(element, { click, keydown });\n}\n\nfunction detachHandlers(element: HTMLElement): void {\n const entry = handlers.get(element);\n\n if (entry) {\n element.removeEventListener(\"click\", entry.click);\n element.removeEventListener(\"keydown\", entry.keydown);\n handlers.delete(element);\n }\n}\n\nexport const vLink: Directive<HTMLElement, LinkDirectiveValue> = {\n mounted(element, binding) {\n const router = getDirectiveRouter();\n\n applyLinkA11y(element);\n\n element.style.cursor = \"pointer\";\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n updated(element, binding) {\n const router = getDirectiveRouter();\n\n detachHandlers(element);\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n beforeUnmount(element) {\n detachHandlers(element);\n },\n};\n","import { inject } from \"vue\";\n\nimport { NavigatorKey } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = inject(NavigatorKey);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { 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\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params } from \"@real-router/core\";\n\nexport const useRoute = <P extends Params = Params>(): RouteContext<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n return routeContext as RouteContext<P>;\n};\n","import { getTransitionSource } from \"@real-router/sources\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRouterTransition(): ShallowRef<RouterTransitionSnapshot> {\n const router = useRouter();\n const source = getTransitionSource(router);\n\n return useRefFromSource(source);\n}\n","// packages/vue/src/setupRouteProvision.ts\n\nimport { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { shallowRef } from \"vue\";\n\nimport type { Router, Navigator, State } from \"@real-router/core\";\nimport type { ShallowRef } from \"vue\";\n\n/**\n * Shared setup for `RouterProvider` (component-scoped) and\n * `createRouterPlugin` (app-scoped). Builds the reactive route refs +\n * subscription bookkeeping in one place; callers wire the result into their\n * provide/inject mechanism and own teardown lifecycle.\n *\n * @internal\n */\nexport interface RouteProvision {\n navigator: Navigator;\n route: ShallowRef<State | undefined>;\n previousRoute: ShallowRef<State | undefined>;\n /** Call when the owning scope tears down to release the router subscription. */\n unsubscribe: () => void;\n}\n\nexport function setupRouteProvision(router: Router): RouteProvision {\n const navigator = getNavigator(router);\n const source = createRouteSource(router);\n const initial = source.getSnapshot();\n\n const route = shallowRef<State | undefined>(initial.route);\n const previousRoute = shallowRef<State | undefined>(initial.previousRoute);\n\n const unsubscribe = source.subscribe(() => {\n const snapshot = source.getSnapshot();\n\n route.value = snapshot.route;\n previousRoute.value = snapshot.previousRoute;\n });\n\n return { navigator, route, previousRoute, unsubscribe };\n}\n","import { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { App, Plugin } from \"vue\";\n\nexport function createRouterPlugin(router: Router): Plugin<[]> {\n return {\n install(app): void {\n const releaseDirective = pushDirectiveRouter(router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(router);\n\n // Vue 3.5+ exposes app.onUnmount for plugin cleanup.\n // On older versions (3.3–3.4), the subscription is cleaned up\n // when the router is garbage-collected (same as vue-router).\n if (\"onUnmount\" in app) {\n (app as App & { onUnmount: (fn: () => void) => void }).onUnmount(() => {\n releaseDirective();\n unsubscribe();\n });\n }\n\n app.provide(RouterKey, router);\n app.provide(NavigatorKey, navigator);\n app.provide(RouteKey, { navigator, route, previousRoute });\n },\n };\n}\n","import { defineComponent, onScopeDispose, provide, watch } from \"vue\";\n\nimport { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { createRouteAnnouncer } from \"./dom-utils/index.js\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\nexport const RouterProvider = defineComponent({\n name: \"RouterProvider\",\n props: {\n router: {\n type: Object as PropType<Router>,\n required: true,\n },\n announceNavigation: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n // Reactive announceNavigation: setting prop true/false at runtime now\n // creates/destroys the announcer accordingly. Prior implementation read\n // the prop only inside onMounted, so toggling it post-mount silently no-op'd.\n watch(\n () => [props.router, props.announceNavigation] as const,\n ([router, enabled], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n onCleanup(() => {\n announcer.destroy();\n });\n },\n { immediate: true },\n );\n\n // Push this provider's router on the v-link directive stack so nested\n // RouterProviders behave like nested DI scopes (LIFO). Release on unmount\n // restores the outer router for any v-link still mounted in the parent.\n const releaseDirective = pushDirectiveRouter(props.router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(props.router);\n\n onScopeDispose(() => {\n releaseDirective();\n unsubscribe();\n });\n\n provide(RouterKey, props.router);\n provide(NavigatorKey, navigator);\n provide(RouteKey, { navigator, route, previousRoute });\n\n return () => slots.default?.();\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Fragment","UNKNOWN_ROUTE","Suspense","KeepAlive","Fragment","Fragment"],"sources":["../../src/components/RouteView/components.ts","../../src/components/RouteView/helpers.ts","../../src/useRefFromSource.ts","../../src/context.ts","../../src/composables/useRouter.ts","../../src/composables/useRouteNode.ts","../../src/components/RouteView/RouteView.ts","../../src/constants.ts","../../../../shared/dom-utils/route-announcer.ts","../../../../shared/dom-utils/scroll-restore.ts","../../../../shared/dom-utils/link-utils.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/composables/useRoute.ts","../../src/composables/useRouterTransition.ts","../../src/setupRouteProvision.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts"],"sourcesContent":["import { defineComponent } from \"vue\";\n\nimport type { PropType, VNode } from \"vue\";\n\nfunction renderNull() {\n return null;\n}\n\nexport const Match = defineComponent({\n name: \"RouteView.Match\",\n props: {\n segment: {\n type: String as PropType<string>,\n required: true,\n },\n exact: {\n type: Boolean,\n default: false,\n },\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n render: renderNull,\n});\n\nexport const NotFound = defineComponent({\n name: \"RouteView.NotFound\",\n render: renderNull,\n});\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isVNode } from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nfunction normalizeChildren(children: unknown): VNode[] {\n if (Array.isArray(children)) {\n const result: VNode[] = [];\n\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...normalizeChildren(child));\n } else if (isVNode(child)) {\n result.push(child);\n }\n }\n\n return result;\n }\n\n if (isVNode(children)) {\n return [children];\n }\n\n return [];\n}\n\nexport function collectElements(children: unknown, result: VNode[]): void {\n const vnodes = normalizeChildren(children);\n\n for (const child of vnodes) {\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): {\n rendered: VNode[];\n activeMatchFound: boolean;\n fallback?: FallbackType;\n} {\n let notFoundChildren: unknown = null;\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = child.children;\n continue;\n }\n\n const props = child.props as {\n segment: string;\n exact?: boolean;\n fallback?: FallbackType;\n } | null;\n const segment = props?.segment ?? \"\";\n const exact = props?.exact ?? false;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n fallback = props?.fallback;\n rendered.push(child);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n const nfElements = elements.filter((element) => element.type === NotFound);\n /* v8 ignore next 3 */\n const lastNf = nfElements.at(-1);\n\n if (lastNf) {\n rendered.push(lastNf);\n }\n }\n\n return { rendered, activeMatchFound, fallback };\n}\n","import { shallowRef, onScopeDispose } from \"vue\";\n\nimport type { RouterSource } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRefFromSource<T>(source: RouterSource<T>): ShallowRef<T> {\n const ref = shallowRef(source.getSnapshot());\n\n const unsub = source.subscribe(() => {\n ref.value = source.getSnapshot();\n });\n\n onScopeDispose(unsub);\n\n return ref;\n}\n","import type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n","import { inject } from \"vue\";\n\nimport { RouterKey } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = inject(RouterKey);\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 { computed } from \"vue\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const source = createRouteNodeSource(router, nodeName);\n const snapshot = useRefFromSource(source);\n\n // getNavigator is WeakMap-cached in core; no useMemo equivalent needed.\n const navigator = getNavigator(router);\n\n // Derive route/previousRoute via computed instead of mirroring with a sync\n // watch into two extra shallowRefs. computed shares snapshot's identity so\n // when the underlying source emits the same reference (idempotent or\n // out-of-node nav), consumers don't see a new ref.\n const route = computed(() => snapshot.value.route);\n const previousRoute = computed(() => snapshot.value.previousRoute);\n\n return {\n navigator,\n route,\n previousRoute,\n };\n}\n","import {\n Fragment,\n defineComponent,\n h,\n KeepAlive,\n markRaw,\n Suspense,\n} from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../composables/useRouteNode\";\n\nimport type { Component, VNode } from \"vue\";\n\ntype SlotChildren = Record<string, (() => VNode[]) | undefined> | null;\n\nfunction getSlotContent(vnode: VNode): VNode[] | null {\n const slots = vnode.children as SlotChildren;\n\n return slots?.default?.() ?? null;\n}\n\nfunction getOrCreateWrapper(\n cache: Map<string, Component>,\n segment: string,\n): Component {\n const existing = cache.get(segment);\n\n if (existing) {\n return existing;\n }\n\n const wrapper = markRaw(\n defineComponent({\n name: `KeepAlive-${segment}`,\n setup(_wrapperProps, wrapperCtx) {\n return () => wrapperCtx.slots.default?.();\n },\n }),\n );\n\n cache.set(segment, wrapper);\n\n return wrapper;\n}\n\nfunction wrapWithSuspense(content: VNode, fallback: unknown): VNode {\n if (fallback === undefined) {\n return content;\n }\n\n const fallbackContent =\n typeof fallback === \"function\" ? (fallback as () => VNode)() : fallback;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n const suspenseComponent = Suspense as any;\n\n return h(\n suspenseComponent,\n {},\n {\n default: () => content,\n fallback: () => fallbackContent,\n },\n );\n}\n\nconst emptyKeepAlivePlaceholder = markRaw(\n defineComponent({\n name: \"KeepAlive-placeholder\",\n render() {\n return null;\n },\n }),\n);\n\nfunction renderWithRootKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode {\n const activeProps = activeChild.props as { segment?: string } | null;\n const segment = activeProps?.segment ?? \"__not-found__\";\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n const keepAliveContent = h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n });\n\n return wrapWithSuspense(keepAliveContent, fallback);\n}\n\n// Vue compiles boolean-shorthand template attributes (`<Match keepAlive>`) to\n// an empty string instead of `true`, and converts them to `true` only when the\n// receiving component's prop is declared with `type: Boolean`. `Match` is a\n// marker component (`render: null`) — its props are inspected on the VNode\n// without ever going through Vue's prop-casting pipeline, so the raw `\"\"` (or\n// the hyphenated attribute name) reaches us here. Accept the same trio Vue's\n// runtime does.\nfunction isKeepAliveEnabled(value: unknown): boolean {\n return value === true || value === \"\" || value === \"keep-alive\";\n}\n\nfunction renderWithPerMatchKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode | null {\n const matchProps = activeChild.props as {\n segment?: string;\n keepAlive?: unknown;\n } | null;\n\n if (isKeepAliveEnabled(matchProps?.keepAlive) && activeChild.type === Match) {\n /* v8 ignore start */\n const segment = matchProps?.segment ?? \"__not-found__\";\n /* v8 ignore stop */\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n\n return h(Fragment, [\n h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n }),\n ]);\n }\n\n const content = getSlotContent(activeChild);\n\n /* v8 ignore start */\n if (!content) {\n return null;\n }\n /* v8 ignore stop */\n\n return h(Fragment, [\n h(KeepAlive, null, { default: () => h(emptyKeepAlivePlaceholder) }),\n wrapWithSuspense(h(Fragment, content), fallback),\n ]);\n}\n\nconst RouteViewComponent = defineComponent({\n name: \"RouteView\",\n props: {\n nodeName: {\n type: String,\n required: true,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n const routeContext = useRouteNode(props.nodeName);\n const wrapperCache = new Map<string, Component>();\n\n // Cache per-Match `keepAlive` detection by slot output identity. Slot\n // contents change reference only when the parent re-renders with new\n // children, so steady-state navigations skip the O(n) `.some(...)` scan.\n let lastSlotOutput: unknown = null;\n let lastHasPerMatchKA = false;\n\n function detectPerMatchKA(elements: VNode[], slotOutput: unknown): boolean {\n /* v8 ignore next 3 -- @preserve: Vue's compiled slot wrapper allocates a\n new array per render call in JSDOM tests; identity-cache hits in\n production where parent compiled templates share slot output, but\n is unobservable through TestBed-style assertions. */\n if (slotOutput === lastSlotOutput) {\n return lastHasPerMatchKA;\n }\n\n lastSlotOutput = slotOutput;\n lastHasPerMatchKA = elements.some(\n (element) =>\n element.type === Match &&\n isKeepAliveEnabled(\n (element.props as { keepAlive?: unknown } | null)?.keepAlive,\n ),\n );\n\n return lastHasPerMatchKA;\n }\n\n return (): VNode | null => {\n const route = routeContext.route.value;\n\n if (!route) {\n return null;\n }\n\n const slotOutput = slots.default?.();\n const elements: VNode[] = [];\n\n collectElements(slotOutput, elements);\n\n const { rendered, fallback } = buildRenderList(\n elements,\n route.name,\n props.nodeName,\n );\n\n if (rendered.length === 0) {\n return null;\n }\n\n const activeChild = rendered[0];\n\n if (props.keepAlive) {\n return renderWithRootKA(activeChild, wrapperCache, fallback);\n }\n\n /* v8 ignore start */\n if (activeChild.type !== Match && activeChild.type !== NotFound) {\n return null;\n }\n /* v8 ignore stop */\n\n const hasPerMatchKA = detectPerMatchKA(elements, slotOutput);\n\n if (hasPerMatchKA) {\n return renderWithPerMatchKA(activeChild, wrapperCache, fallback);\n }\n\n const content = getSlotContent(activeChild);\n\n if (!content) {\n return null;\n }\n\n return wrapWithSuspense(h(Fragment, content), fallback);\n };\n },\n});\n\nexport const RouteView = Object.assign(RouteViewComponent, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\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 { Router, State } from \"@real-router/core\";\n\nconst CLEAR_DELAY = 7000;\nconst SAFARI_READY_DELAY = 100;\nconst ANNOUNCER_ATTR = \"data-real-router-announcer\";\nconst INTERNAL_ROUTE_PREFIX = \"@@\";\nconst VISUALLY_HIDDEN =\n \"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\nexport interface RouteAnnouncerOptions {\n prefix?: string;\n getAnnouncementText?: (route: State) => string;\n}\n\nexport function createRouteAnnouncer(\n router: Router,\n options?: RouteAnnouncerOptions,\n): { destroy: () => void } {\n const prefix = options?.prefix ?? \"Navigated to \";\n const getCustomText = options?.getAnnouncementText;\n\n let isInitialNavigation = true;\n let isReady = false;\n let isDestroyed = false;\n let lastAnnouncedText = \"\";\n let pendingText: string | null = null;\n let clearTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const announcer = getOrCreateAnnouncer();\n\n const doAnnounce = (text: string, h1: HTMLElement | null): void => {\n lastAnnouncedText = text;\n clearTimeout(clearTimeoutId);\n announcer.textContent = text;\n clearTimeoutId = setTimeout(() => {\n announcer.textContent = \"\";\n lastAnnouncedText = \"\";\n }, CLEAR_DELAY);\n\n manageFocus(h1);\n };\n\n // Safari-ready delay: announcing before VoiceOver wires up the aria-live region\n // causes the first announcement to be silently dropped. Wait SAFARI_READY_DELAY ms\n // before marking the announcer \"ready\" — any navigation during that window is\n // buffered in pendingText and flushed once the delay expires.\n const safariTimeoutId = setTimeout(() => {\n isReady = true;\n\n if (pendingText !== null && !isDestroyed) {\n const text = pendingText;\n\n pendingText = null;\n doAnnounce(text, document.querySelector<HTMLElement>(\"h1\"));\n }\n }, SAFARI_READY_DELAY);\n\n const unsubscribe = router.subscribe(({ route }) => {\n if (isInitialNavigation) {\n isInitialNavigation = false;\n\n return;\n }\n\n // Double rAF: waits for two paint frames so the incoming route's DOM\n // (including the new <h1>) is fully rendered before resolveText reads it.\n // Single rAF fires before the new route's template has been attached,\n // which would cause resolveText to pick up the OLD h1 or fall back to\n // document.title / route.name prematurely.\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (isDestroyed) {\n return;\n }\n\n const h1 = document.querySelector<HTMLElement>(\"h1\");\n const text = resolveText(route, prefix, getCustomText, h1);\n\n if (!text || text === lastAnnouncedText) {\n return;\n }\n\n if (!isReady) {\n // Defer announcement until Safari-ready window elapses (see safariTimeoutId).\n pendingText = text;\n\n return;\n }\n\n doAnnounce(text, h1);\n });\n });\n });\n\n return {\n destroy() {\n isDestroyed = true;\n unsubscribe();\n clearTimeout(clearTimeoutId);\n clearTimeout(safariTimeoutId);\n removeAnnouncer();\n },\n };\n}\n\nfunction getOrCreateAnnouncer(): HTMLElement {\n const existing = document.querySelector<HTMLElement>(`[${ANNOUNCER_ATTR}]`);\n\n if (existing) {\n return existing;\n }\n\n const element = document.createElement(\"div\");\n\n element.setAttribute(\"style\", VISUALLY_HIDDEN);\n element.setAttribute(\"aria-live\", \"assertive\");\n element.setAttribute(\"aria-atomic\", \"true\");\n element.setAttribute(ANNOUNCER_ATTR, \"\");\n\n document.body.prepend(element);\n\n return element;\n}\n\nfunction removeAnnouncer(): void {\n document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();\n}\n\nfunction resolveText(\n route: State,\n prefix: string,\n getCustomText: ((route: State) => string) | undefined,\n h1: HTMLElement | null,\n): string {\n if (getCustomText) {\n return getCustomText(route);\n }\n\n const h1Text = h1?.textContent.trim() ?? \"\";\n const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX)\n ? \"\"\n : route.name;\n const rawText =\n h1Text || document.title || routeName || globalThis.location.pathname;\n\n return `${prefix}${rawText}`;\n}\n\nfunction manageFocus(h1: HTMLElement | null): void {\n if (!h1) {\n return;\n }\n\n if (!h1.hasAttribute(\"tabindex\")) {\n h1.setAttribute(\"tabindex\", \"-1\");\n }\n\n h1.focus({ preventScroll: true });\n}\n","import type { Router, State } from \"@real-router/core\";\n\nconst STORAGE_KEY = \"real-router:scroll\";\n\nconst NOOP_INSTANCE: { destroy: () => void } = Object.freeze({\n destroy: () => {\n /* no-op */\n },\n});\n\nexport type ScrollRestorationMode = \"restore\" | \"top\" | \"manual\";\n\nexport interface ScrollRestorationOptions {\n mode?: ScrollRestorationMode | undefined;\n anchorScrolling?: boolean | undefined;\n scrollContainer?: (() => HTMLElement | null) | undefined;\n}\n\ninterface NavigationContext {\n direction?: \"forward\" | \"back\" | \"unknown\";\n navigationType?: \"push\" | \"replace\" | \"traverse\" | \"reload\";\n}\n\nexport function createScrollRestoration(\n router: Router,\n options?: ScrollRestorationOptions,\n): { destroy: () => void } {\n if (typeof globalThis.window === \"undefined\") {\n return NOOP_INSTANCE;\n }\n\n const mode = options?.mode ?? \"restore\";\n\n // mode \"manual\" = utility does nothing. Don't flip history.scrollRestoration,\n // don't subscribe, don't register pagehide — leave the browser's native\n // auto-restore intact for the app to override if it wants to.\n if (mode === \"manual\") {\n return NOOP_INSTANCE;\n }\n\n const anchorEnabled = options?.anchorScrolling ?? true;\n const getContainer = options?.scrollContainer;\n\n const prevScrollRestoration = history.scrollRestoration;\n\n try {\n history.scrollRestoration = \"manual\";\n } catch {\n // Ignore — some embedded contexts may reject the assignment.\n }\n\n // Resolve the container lazily on every event so containers mounted AFTER\n // the provider still get correct scroll handling. Falls back to window when\n // the getter is absent or returns null (pre-mount).\n const readPos = (): number => {\n const element = getContainer?.();\n\n return element ? element.scrollTop : globalThis.scrollY;\n };\n\n const writePos = (top: number): void => {\n const element = getContainer?.();\n\n if (element) {\n element.scrollTop = top;\n } else {\n globalThis.scrollTo(0, top);\n }\n };\n\n const scrollToHashOrTop = (): void => {\n const hash = globalThis.location.hash;\n\n if (anchorEnabled && hash.length > 1) {\n // location.hash is percent-encoded; ids in the DOM are the raw string.\n // Decode for the match. Fall back to the raw slice if the hash contains\n // a malformed escape sequence (decodeURIComponent throws on those).\n let id: string;\n\n try {\n id = decodeURIComponent(hash.slice(1));\n } catch {\n id = hash.slice(1);\n }\n\n // eslint-disable-next-line unicorn/prefer-query-selector -- ids may contain CSS-unsafe chars\n const element = document.getElementById(id);\n\n if (element) {\n element.scrollIntoView();\n\n return;\n }\n }\n\n writePos(0);\n };\n\n let destroyed = false;\n\n const unsubscribe = router.subscribe(({ route, previousRoute }) => {\n const nav = (route.context as { navigation?: NavigationContext })\n .navigation;\n\n // Browsers dispatch reload as the initial navigation after refresh, so\n // previousRoute is undefined and capture is naturally skipped. The\n // pre-refresh position was already persisted via pagehide.\n if (previousRoute) {\n putPos(keyOf(previousRoute), readPos());\n }\n\n // Single rAF so DOM is committed before we read anchors / write scroll.\n // Guard against destroy() racing with the callback.\n requestAnimationFrame(() => {\n if (destroyed) {\n return;\n }\n\n if (mode === \"top\" || !nav) {\n scrollToHashOrTop();\n\n return;\n }\n\n if (nav.navigationType === \"replace\") {\n return;\n }\n\n if (\n nav.direction === \"back\" ||\n nav.navigationType === \"traverse\" ||\n nav.navigationType === \"reload\"\n ) {\n writePos(loadStore()[keyOf(route)] ?? 0);\n\n return;\n }\n\n scrollToHashOrTop();\n });\n });\n\n const onPageHide = (): void => {\n const current = router.getState();\n\n if (current) {\n putPos(keyOf(current), readPos());\n }\n };\n\n globalThis.addEventListener(\"pagehide\", onPageHide);\n\n return {\n destroy: () => {\n if (destroyed) {\n return;\n }\n\n destroyed = true;\n unsubscribe();\n globalThis.removeEventListener(\"pagehide\", onPageHide);\n\n try {\n history.scrollRestoration = prevScrollRestoration;\n } catch {\n // Ignore.\n }\n },\n };\n}\n\nfunction keyOf(state: State): string {\n return `${state.name}:${canonicalJson(state.params)}`;\n}\n\nfunction loadStore(): Record<string, number> {\n try {\n const raw = sessionStorage.getItem(STORAGE_KEY);\n\n return raw ? (JSON.parse(raw) as Record<string, number>) : {};\n } catch {\n return {};\n }\n}\n\nfunction putPos(key: string, pos: number): void {\n try {\n const store = loadStore();\n\n store[key] = pos;\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify(store));\n } catch {\n // Ignore quota / security errors.\n }\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(value, canonicalReplacer);\n}\n\nfunction canonicalReplacer(_key: string, val: unknown): unknown {\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n const sorted: Record<string, unknown> = {};\n // eslint-disable-next-line unicorn/no-array-sort -- ng-packagr uses pre-ES2023 lib; toSorted unavailable\n const keys = Object.keys(val as Record<string, unknown>).sort(\n (left: string, right: string) => left.localeCompare(right),\n );\n\n for (const key of keys) {\n sorted[key] = (val as Record<string, unknown>)[key];\n }\n\n return sorted;\n }\n\n return val;\n}\n","import type { Router, Params } from \"@real-router/core\";\n\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 &&\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n\ntype BuildUrlFn = (name: string, params: Params) => string | undefined;\n\nexport function buildHref(\n router: Router,\n routeName: string,\n routeParams: Params,\n): string | undefined {\n try {\n const buildUrl = router.buildUrl as BuildUrlFn | undefined;\n\n if (buildUrl) {\n const url = buildUrl(routeName, routeParams);\n\n if (url !== undefined) {\n return url;\n }\n }\n\n return router.buildPath(routeName, routeParams);\n } catch {\n console.error(\n `[real-router] Route \"${routeName}\" is not defined. The element will render without an href attribute.`,\n );\n\n return undefined;\n }\n}\n\nfunction parseTokens(value: string | undefined): string[] {\n return value ? (value.match(/\\S+/g) ?? []) : [];\n}\n\nexport function buildActiveClassName(\n isActive: boolean,\n activeClassName: string | undefined,\n baseClassName: string | undefined,\n): string | undefined {\n if (isActive && activeClassName) {\n const activeTokens = parseTokens(activeClassName);\n\n if (activeTokens.length === 0) {\n return baseClassName ?? undefined;\n }\n if (!baseClassName) {\n return activeTokens.join(\" \");\n }\n\n const baseTokens = parseTokens(baseClassName);\n const seen = new Set(baseTokens);\n\n for (const token of activeTokens) {\n if (!seen.has(token)) {\n seen.add(token);\n baseTokens.push(token);\n }\n }\n\n return baseTokens.join(\" \");\n }\n\n return baseClassName ?? undefined;\n}\n\nexport function shallowEqual(\n prev: object | undefined,\n next: object | undefined,\n): boolean {\n if (Object.is(prev, next)) {\n return true;\n }\n if (!prev || !next) {\n return false;\n }\n\n const prevKeys = Object.keys(prev);\n\n if (prevKeys.length !== Object.keys(next).length) {\n return false;\n }\n\n const prevRecord = prev as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n\n for (const key of prevKeys) {\n if (!Object.is(prevRecord[key], nextRecord[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function applyLinkA11y(element: HTMLElement | null | undefined): void {\n if (!element) {\n return;\n }\n if (\n element instanceof HTMLAnchorElement ||\n element instanceof HTMLButtonElement\n ) {\n return;\n }\n if (!element.hasAttribute(\"role\")) {\n element.setAttribute(\"role\", \"link\");\n }\n if (!element.hasAttribute(\"tabindex\")) {\n element.setAttribute(\"tabindex\", \"0\");\n }\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { defineComponent, h, computed, shallowRef, watch } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { shouldNavigate, buildHref, buildActiveClassName } from \"../dom-utils\";\n\nimport type { Params, NavigationOptions } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\ntype OnClickHandler = (evt: MouseEvent) => void;\n\n/**\n * Vue's compiled template binds multiple `@click` handlers as an array.\n * Single render-function `onClick` is a function. Both must be invoked.\n */\nfunction invokeAttributesOnClick(value: unknown, evt: MouseEvent): void {\n if (typeof value === \"function\") {\n (value as OnClickHandler)(evt);\n\n return;\n }\n if (Array.isArray(value)) {\n const handlers = value as OnClickHandler[];\n\n for (const fn of handlers) {\n if (typeof fn === \"function\") {\n fn(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n }\n }\n}\n\nexport const Link = defineComponent({\n name: \"Link\",\n // Disable Vue's automatic attribute fallthrough. Without this, attrs.onClick\n // (function OR array) is auto-attached as a native click listener AND our\n // explicit onClick fires too — user handlers are double-invoked. We invoke\n // attrs.onClick manually inside handleClick to preserve preventDefault.\n inheritAttrs: false,\n props: {\n routeName: {\n type: String,\n required: true,\n },\n routeParams: {\n type: Object as PropType<Params>,\n default: () => EMPTY_PARAMS,\n },\n routeOptions: {\n type: Object as PropType<NavigationOptions>,\n default: () => EMPTY_OPTIONS,\n },\n class: {\n type: String,\n default: undefined,\n },\n activeClassName: {\n type: String,\n default: \"active\",\n },\n activeStrict: {\n type: Boolean,\n default: false,\n },\n ignoreQueryParams: {\n type: Boolean,\n default: true,\n },\n target: {\n type: String,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const router = useRouter();\n\n const isActive = shallowRef(false);\n\n // watch with an explicit dep getter recreates the source ONLY when\n // routeName/routeParams/strict/ignoreQueryParams change — not on every\n // reactive read inside the source factory (the watchEffect alternative\n // would also re-subscribe whenever isActive itself changed).\n watch(\n () =>\n [\n props.routeName,\n props.routeParams,\n props.activeStrict,\n props.ignoreQueryParams,\n ] as const,\n (\n [routeName, routeParams, activeStrict, ignoreQueryParams],\n _prev,\n onCleanup,\n ) => {\n const source = createActiveRouteSource(router, routeName, routeParams, {\n strict: activeStrict,\n ignoreQueryParams,\n });\n\n isActive.value = source.getSnapshot();\n\n const unsub = source.subscribe(() => {\n isActive.value = source.getSnapshot();\n });\n\n onCleanup(unsub);\n },\n { immediate: true, flush: \"sync\" },\n );\n\n const href = computed(() =>\n buildHref(router, props.routeName, props.routeParams),\n );\n\n const finalClassName = computed(() =>\n buildActiveClassName(isActive.value, props.activeClassName, props.class),\n );\n\n const handleClick = (evt: MouseEvent) => {\n // Vue allows attrs.onClick to be a function or an array of functions\n // (compiled templates with multiple @click bindings produce arrays).\n // Both must be invoked; treating arrays as \"no handler\" silently drops\n // user code.\n if (attrs.onClick !== undefined && attrs.onClick !== null) {\n invokeAttributesOnClick(attrs.onClick, evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || props.target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(props.routeName, props.routeParams, props.routeOptions)\n .catch(() => {});\n };\n\n return () => {\n // Build forwarded attrs without `onClick`. Vue's runtime auto-attaches\n // attrs.onClick (function OR array) as a native DOM listener, which would\n // double-invoke user handlers when combined with our explicit `onClick`.\n // We invoke the original attrs.onClick manually inside handleClick so the\n // preventDefault contract is preserved.\n const restAttributes: Record<string, unknown> = {};\n\n for (const key of Object.keys(attrs)) {\n if (key !== \"onClick\") {\n restAttributes[key] = (attrs as Record<string, unknown>)[key];\n }\n }\n\n return h(\n \"a\",\n {\n ...restAttributes,\n href: href.value,\n class: finalClassName.value,\n target: props.target,\n onClick: handleClick,\n },\n slots.default?.(),\n );\n };\n },\n});\n","import { createDismissableError } from \"@real-router/sources\";\nimport { defineComponent, h, watch, Fragment } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { useRefFromSource } from \"../useRefFromSource\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { VNode, PropType } from \"vue\";\n\nexport const RouterErrorBoundary = defineComponent({\n name: \"RouterErrorBoundary\",\n props: {\n fallback: {\n type: Function as PropType<\n (error: RouterError, resetError: () => void) => VNode\n >,\n required: true,\n },\n onError: {\n type: Function as PropType<\n (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void\n >,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const router = useRouter();\n const snapshot = useRefFromSource(createDismissableError(router));\n\n watch(\n () => snapshot.value.version,\n () => {\n if (snapshot.value.error) {\n props.onError?.(\n snapshot.value.error,\n snapshot.value.toRoute,\n snapshot.value.fromRoute,\n );\n }\n },\n { immediate: true },\n );\n\n return () => {\n const children = slots.default?.() ?? [];\n const errorVNode = snapshot.value.error\n ? props.fallback(snapshot.value.error, snapshot.value.resetError)\n : null;\n\n return h(Fragment, null, [...children, errorVNode]);\n };\n },\n});\n\nexport type RouterErrorBoundaryProps = InstanceType<\n typeof RouterErrorBoundary\n>[\"$props\"];\n","import { shouldNavigate, applyLinkA11y } from \"../dom-utils\";\n\nimport type { Router, NavigationOptions, Params } from \"@real-router/core\";\nimport type { Directive } from \"vue\";\n\nexport interface LinkDirectiveValue {\n name: string;\n params?: Params;\n options?: NavigationOptions;\n}\n\n/**\n * Router stack for nested RouterProviders. The active router is the top of\n * the stack. RouterProvider pushes its router on mount and pops it on unmount,\n * which preserves the parent context when an inner provider tears down.\n *\n * Without the stack, an unmounted child provider would leave the directive\n * pointing at a disposed router, and v-link in the still-mounted parent would\n * navigate via the wrong (or torn-down) instance.\n */\nconst routerStack: Router[] = [];\n\n/**\n * Pushes a router onto the active stack. Returns a release function that\n * removes that exact router from the stack regardless of position — safe\n * across out-of-order provider unmount sequences.\n *\n * @internal Used by RouterProvider during setup/teardown.\n */\nexport function pushDirectiveRouter(router: Router): () => void {\n routerStack.push(router);\n\n return () => {\n const idx = routerStack.lastIndexOf(router);\n\n if (idx !== -1) {\n routerStack.splice(idx, 1);\n }\n };\n}\n\n/**\n * Backwards-compatible alias. Replaces the active router unconditionally and\n * does NOT participate in the stack — use {@link pushDirectiveRouter} from\n * provider code instead. Kept for tests and direct callers.\n */\nexport function setDirectiveRouter(router: Router | null): void {\n if (router === null) {\n routerStack.length = 0;\n\n return;\n }\n if (routerStack.length === 0) {\n routerStack.push(router);\n\n return;\n }\n\n routerStack[routerStack.length - 1] = router;\n}\n\nexport function getDirectiveRouter(): Router {\n const top = routerStack.at(-1);\n\n if (!top) {\n throw new Error(\n \"v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.\",\n );\n }\n\n return top;\n}\n\ninterface Handlers {\n click: (evt: MouseEvent) => void;\n keydown: (evt: KeyboardEvent) => void;\n}\n\n// Single WeakMap halves per-element bookkeeping vs two parallel maps.\nconst handlers = new WeakMap<HTMLElement, Handlers>();\n\n/**\n * Validates a directive binding value before attaching handlers.\n * Returns false (and warns once per call) when the value is missing or\n * has no `name` — silently doing nothing is preferable to a runtime crash\n * inside a click handler.\n */\nfunction isValidBinding(value: unknown): value is LinkDirectiveValue {\n if (value === null || value === undefined) {\n console.error(\n \"[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n if (typeof (value as { name?: unknown }).name !== \"string\") {\n console.error(\n \"[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n\n return true;\n}\n\nfunction createClickHandler(\n router: Router,\n value: LinkDirectiveValue,\n): (evt: MouseEvent) => void {\n return (evt: MouseEvent) => {\n if (!shouldNavigate(evt)) {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n };\n}\n\nfunction createKeydownHandler(\n router: Router,\n value: LinkDirectiveValue,\n element: HTMLElement,\n): (evt: KeyboardEvent) => void {\n return (evt: KeyboardEvent) => {\n if (evt.key === \"Enter\" && !(element instanceof HTMLButtonElement)) {\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n }\n };\n}\n\nfunction attachHandlers(\n element: HTMLElement,\n router: Router,\n value: LinkDirectiveValue,\n): void {\n const click = createClickHandler(router, value);\n const keydown = createKeydownHandler(router, value, element);\n\n element.addEventListener(\"click\", click);\n element.addEventListener(\"keydown\", keydown);\n\n handlers.set(element, { click, keydown });\n}\n\nfunction detachHandlers(element: HTMLElement): void {\n const entry = handlers.get(element);\n\n if (entry) {\n element.removeEventListener(\"click\", entry.click);\n element.removeEventListener(\"keydown\", entry.keydown);\n handlers.delete(element);\n }\n}\n\nexport const vLink: Directive<HTMLElement, LinkDirectiveValue> = {\n mounted(element, binding) {\n const router = getDirectiveRouter();\n\n applyLinkA11y(element);\n\n element.style.cursor = \"pointer\";\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n updated(element, binding) {\n const router = getDirectiveRouter();\n\n detachHandlers(element);\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n beforeUnmount(element) {\n detachHandlers(element);\n },\n};\n","import { inject } from \"vue\";\n\nimport { NavigatorKey } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = inject(NavigatorKey);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { 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\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params } from \"@real-router/core\";\n\nexport const useRoute = <P extends Params = Params>(): RouteContext<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n return routeContext as RouteContext<P>;\n};\n","import { getTransitionSource } from \"@real-router/sources\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRouterTransition(): ShallowRef<RouterTransitionSnapshot> {\n const router = useRouter();\n const source = getTransitionSource(router);\n\n return useRefFromSource(source);\n}\n","// packages/vue/src/setupRouteProvision.ts\n\nimport { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { shallowRef } from \"vue\";\n\nimport type { Router, Navigator, State } from \"@real-router/core\";\nimport type { ShallowRef } from \"vue\";\n\n/**\n * Shared setup for `RouterProvider` (component-scoped) and\n * `createRouterPlugin` (app-scoped). Builds the reactive route refs +\n * subscription bookkeeping in one place; callers wire the result into their\n * provide/inject mechanism and own teardown lifecycle.\n *\n * @internal\n */\nexport interface RouteProvision {\n navigator: Navigator;\n route: ShallowRef<State | undefined>;\n previousRoute: ShallowRef<State | undefined>;\n /** Call when the owning scope tears down to release the router subscription. */\n unsubscribe: () => void;\n}\n\nexport function setupRouteProvision(router: Router): RouteProvision {\n const navigator = getNavigator(router);\n const source = createRouteSource(router);\n const initial = source.getSnapshot();\n\n const route = shallowRef<State | undefined>(initial.route);\n const previousRoute = shallowRef<State | undefined>(initial.previousRoute);\n\n const unsubscribe = source.subscribe(() => {\n const snapshot = source.getSnapshot();\n\n route.value = snapshot.route;\n previousRoute.value = snapshot.previousRoute;\n });\n\n return { navigator, route, previousRoute, unsubscribe };\n}\n","import { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { App, Plugin } from \"vue\";\n\nexport function createRouterPlugin(router: Router): Plugin<[]> {\n return {\n install(app): void {\n const releaseDirective = pushDirectiveRouter(router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(router);\n\n // Vue 3.5+ exposes app.onUnmount for plugin cleanup.\n // On older versions (3.3–3.4), the subscription is cleaned up\n // when the router is garbage-collected (same as vue-router).\n if (\"onUnmount\" in app) {\n (app as App & { onUnmount: (fn: () => void) => void }).onUnmount(() => {\n releaseDirective();\n unsubscribe();\n });\n }\n\n app.provide(RouterKey, router);\n app.provide(NavigatorKey, navigator);\n app.provide(RouteKey, { navigator, route, previousRoute });\n },\n };\n}\n","import { defineComponent, onScopeDispose, provide, watch } from \"vue\";\n\nimport { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { createRouteAnnouncer, createScrollRestoration } from \"./dom-utils\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { ScrollRestorationOptions } from \"./dom-utils\";\nimport type { Router } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\nexport const RouterProvider = defineComponent({\n name: \"RouterProvider\",\n props: {\n router: {\n type: Object as PropType<Router>,\n required: true,\n },\n announceNavigation: {\n type: Boolean,\n default: false,\n },\n scrollRestoration: {\n type: Object as PropType<ScrollRestorationOptions>,\n },\n },\n setup(props, { slots }) {\n // Reactive announceNavigation: setting prop true/false at runtime now\n // creates/destroys the announcer accordingly. Prior implementation read\n // the prop only inside onMounted, so toggling it post-mount silently no-op'd.\n watch(\n () => [props.router, props.announceNavigation] as const,\n ([router, enabled], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n onCleanup(() => {\n announcer.destroy();\n });\n },\n { immediate: true },\n );\n\n // Watch by primitives so inline `{ mode: \"restore\" }` doesn't thrash.\n // scrollContainer is a getter invoked lazily on every event inside the\n // utility — swapping its reference doesn't change the resolved element,\n // so we intentionally omit it from watched sources.\n watch(\n () =>\n [\n props.router,\n props.scrollRestoration !== undefined,\n props.scrollRestoration?.mode,\n props.scrollRestoration?.anchorScrolling,\n ] as const,\n ([router, enabled, mode, anchorScrolling], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const sr = createScrollRestoration(router, {\n mode,\n anchorScrolling,\n scrollContainer: props.scrollRestoration?.scrollContainer,\n });\n\n onCleanup(() => {\n sr.destroy();\n });\n },\n { immediate: true },\n );\n\n // Push this provider's router on the v-link directive stack so nested\n // RouterProviders behave like nested DI scopes (LIFO). Release on unmount\n // restores the outer router for any v-link still mounted in the parent.\n const releaseDirective = pushDirectiveRouter(props.router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(props.router);\n\n onScopeDispose(() => {\n releaseDirective();\n unsubscribe();\n });\n\n provide(RouterKey, props.router);\n provide(NavigatorKey, navigator);\n provide(RouteKey, { navigator, route, previousRoute });\n\n return () => slots.default?.();\n },\n});\n"],"mappings":"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"}
@@ -265,6 +265,14 @@ declare function useRouterTransition(): ShallowRef<RouterTransitionSnapshot$1>;
265
265
  //#region src/createRouterPlugin.d.ts
266
266
  declare function createRouterPlugin(router: Router): Plugin<[]>;
267
267
  //#endregion
268
+ //#region ../../shared/dom-utils/scroll-restore.d.ts
269
+ type ScrollRestorationMode = "restore" | "top" | "manual";
270
+ interface ScrollRestorationOptions {
271
+ mode?: ScrollRestorationMode | undefined;
272
+ anchorScrolling?: boolean | undefined;
273
+ scrollContainer?: (() => HTMLElement | null) | undefined;
274
+ }
275
+ //#endregion
268
276
  //#region src/RouterProvider.d.ts
269
277
  declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
270
278
  router: {
@@ -275,6 +283,9 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
275
283
  type: BooleanConstructor;
276
284
  default: boolean;
277
285
  };
286
+ scrollRestoration: {
287
+ type: PropType<ScrollRestorationOptions>;
288
+ };
278
289
  }>, () => _$vue.VNode<_$vue.RendererNode, _$vue.RendererElement, {
279
290
  [key: string]: any;
280
291
  }>[] | undefined, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
@@ -286,6 +297,9 @@ declare const RouterProvider: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
286
297
  type: BooleanConstructor;
287
298
  default: boolean;
288
299
  };
300
+ scrollRestoration: {
301
+ type: PropType<ScrollRestorationOptions>;
302
+ };
289
303
  }>> & Readonly<{}>, {
290
304
  announceNavigation: boolean;
291
305
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/RouteView.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useRouter.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/types.ts","../../src/composables/useRoute.ts","../../src/composables/useRouteNode.ts","../../src/composables/useRouterTransition.ts","../../src/createRouterPlugin.ts","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.ts","../../src/context.ts"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{Fragment as e,KeepAlive as t,Suspense as n,computed as r,defineComponent as i,h as a,inject as o,isVNode as s,markRaw as c,onScopeDispose as l,provide as u,shallowRef as d,watch as f}from"vue";import{UNKNOWN_ROUTE as p,getNavigator as m}from"@real-router/core";import{getRouteUtils as ee,startsWithSegment as te}from"@real-router/route-utils";import{createActiveRouteSource as ne,createDismissableError as re,createRouteNodeSource as ie,createRouteSource as h,getTransitionSource as g}from"@real-router/sources";import{getPluginApi as ae}from"@real-router/core/api";function _(){return null}const v=i({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:_}),y=i({name:`RouteView.NotFound`,render:_});function oe(e,t,n){return n?e===t:te(e,t)}function b(e){if(Array.isArray(e)){let t=[];for(let n of e)Array.isArray(n)?t.push(...b(n)):s(n)&&t.push(n);return t}return s(e)?[e]:[]}function x(t,n){let r=b(t);for(let t of r)t.type===v||t.type===y?n.push(t):t.type===e&&x(t.children,n)}function se(e,t,n){let r=null,i=!1,a,o=[];for(let s of e){if(s.type===y){r=s.children;continue}let e=s.props,c=e?.segment??``,l=e?.exact??!1,u=n?`${n}.${c}`:c;!i&&oe(t,u,l)&&(i=!0,a=e?.fallback,o.push(s))}if(!i&&t===p&&r!==null){let t=e.filter(e=>e.type===y).at(-1);t&&o.push(t)}return{rendered:o,activeMatchFound:i,fallback:a}}function S(e){let t=d(e.getSnapshot());return l(e.subscribe(()=>{t.value=e.getSnapshot()})),t}const C=Symbol(`RouterKey`),w=Symbol(`NavigatorKey`),T=Symbol(`RouteKey`),E=()=>{let e=o(C);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e};function D(e){let t=E(),n=S(ie(t,e));return{navigator:m(t),route:r(()=>n.value.route),previousRoute:r(()=>n.value.previousRoute)}}function O(e){return e.children?.default?.()??null}function k(e,t){let n=e.get(t);if(n)return n;let r=c(i({name:`KeepAlive-${t}`,setup(e,t){return()=>t.slots.default?.()}}));return e.set(t,r),r}function A(e,t){if(t===void 0)return e;let r=typeof t==`function`?t():t;return a(n,{},{default:()=>e,fallback:()=>r})}const ce=c(i({name:`KeepAlive-placeholder`,render(){return null}}));function le(e,n,r){let i=e.props?.segment??`__not-found__`,o=k(n,i),s=O(e)??[];return A(a(t,null,{default:()=>a(o,{key:i},{default:()=>s})}),r)}function j(e){return e===!0||e===``||e===`keep-alive`}function ue(n,r,i){let o=n.props;if(j(o?.keepAlive)&&n.type===v){let i=o?.segment??`__not-found__`,s=k(r,i),c=O(n)??[];return a(e,[a(t,null,{default:()=>a(s,{key:i},{default:()=>c})})])}let s=O(n);return s?a(e,[a(t,null,{default:()=>a(ce)}),A(a(e,s),i)]):null}const M=i({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(t,{slots:n}){let r=D(t.nodeName),i=new Map,o=null,s=!1;function c(e,t){return t===o?s:(o=t,s=e.some(e=>e.type===v&&j(e.props?.keepAlive)),s)}return()=>{let o=r.route.value;if(!o)return null;let s=n.default?.(),l=[];x(s,l);let{rendered:u,fallback:d}=se(l,o.name,t.nodeName);if(u.length===0)return null;let f=u[0];if(t.keepAlive)return le(f,i,d);if(f.type!==v&&f.type!==y)return null;if(c(l,s))return ue(f,i,d);let p=O(f);return p?A(a(e,p),d):null}}}),N=Object.assign(M,{Match:v,NotFound:y}),P=Object.freeze({}),F=Object.freeze({}),I=`data-real-router-announcer`;function L(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=R(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),V(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=B(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),z()}}}function R(){let e=document.querySelector(`[${I}]`);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(I,``),document.body.prepend(t),t}function z(){document.querySelector(`[${I}]`)?.remove()}function B(e,t,n,r){if(n)return n(e);let i=r?.textContent.trim()??``,a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function V(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}function H(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function U(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function W(e){return e?e.match(/\S+/g)??[]:[]}function de(e,t,n){if(e&&t){let e=W(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=W(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function fe(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function pe(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const me=i({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>P},routeOptions:{type:Object,default:()=>F},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0}},setup(e,{slots:t,attrs:n}){let i=E(),o=d(!1);f(()=>[e.routeName,e.routeParams,e.activeStrict,e.ignoreQueryParams],([e,t,n,r],a,s)=>{let c=ne(i,e,t,{strict:n,ignoreQueryParams:r});o.value=c.getSnapshot(),s(c.subscribe(()=>{o.value=c.getSnapshot()}))},{immediate:!0,flush:`sync`});let s=r(()=>U(i,e.routeName,e.routeParams)),c=r(()=>de(o.value,e.activeClassName,e.class)),l=t=>{n.onClick!==void 0&&n.onClick!==null&&(pe(n.onClick,t),t.defaultPrevented)||!H(t)||e.target===`_blank`||(t.preventDefault(),i.navigate(e.routeName,e.routeParams,e.routeOptions).catch(()=>{}))};return()=>{let r={};for(let e of Object.keys(n))e!==`onClick`&&(r[e]=n[e]);return a(`a`,{...r,href:s.value,class:c.value,target:e.target,onClick:l},t.default?.())}}}),he=i({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(t,{slots:n}){let r=S(re(E()));return f(()=>r.value.version,()=>{r.value.error&&t.onError?.(r.value.error,r.value.toRoute,r.value.fromRoute)},{immediate:!0}),()=>{let i=n.default?.()??[],o=r.value.error?t.fallback(r.value.error,r.value.resetError):null;return a(e,null,[...i,o])}}}),G=[];function K(e){return G.push(e),()=>{let t=G.lastIndexOf(e);t!==-1&&G.splice(t,1)}}function q(){let e=G.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const J=new WeakMap;function Y(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function ge(e,t){return n=>{H(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function _e(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function X(e,t,n){let r=ge(t,n),i=_e(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),J.set(e,{click:r,keydown:i})}function Z(e){let t=J.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),J.delete(e))}const Q={mounted(e,t){let n=q();fe(e),e.style.cursor=`pointer`,Y(t.value)&&X(e,n,t.value)},updated(e,t){let n=q();Z(e),Y(t.value)&&X(e,n,t.value)},beforeUnmount(e){Z(e)}},ve=()=>{let e=o(w);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},ye=()=>ee(ae(E()).getTree()),be=()=>{let e=o(T);if(!e)throw Error(`useRoute must be used within a RouterProvider`);return e};function xe(){return S(g(E()))}function $(e){let t=m(e),n=h(e),r=n.getSnapshot(),i=d(r.route),a=d(r.previousRoute);return{navigator:t,route:i,previousRoute:a,unsubscribe:n.subscribe(()=>{let e=n.getSnapshot();i.value=e.route,a.value=e.previousRoute})}}function Se(e){return{install(t){let n=K(e),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e);`onUnmount`in t&&t.onUnmount(()=>{n(),o()}),t.provide(C,e),t.provide(w,r),t.provide(T,{navigator:r,route:i,previousRoute:a})}}}const Ce=i({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1}},setup(e,{slots:t}){f(()=>[e.router,e.announceNavigation],([e,t],n,r)=>{if(!t)return;let i=L(e);r(()=>{i.destroy()})},{immediate:!0});let n=K(e.router),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e.router);return l(()=>{n(),o()}),u(C,e.router),u(w,r),u(T,{navigator:r,route:i,previousRoute:a}),()=>t.default?.()}});export{me as Link,w as NavigatorKey,T as RouteKey,N as RouteView,he as RouterErrorBoundary,C as RouterKey,Ce as RouterProvider,Se as createRouterPlugin,ve as useNavigator,be as useRoute,D as useRouteNode,ye as useRouteUtils,E as useRouter,xe as useRouterTransition,Q as vLink};
1
+ import{Fragment as e,KeepAlive as t,Suspense as n,computed as r,defineComponent as i,h as a,inject as o,isVNode as s,markRaw as c,onScopeDispose as l,provide as u,shallowRef as d,watch as f}from"vue";import{UNKNOWN_ROUTE as p,getNavigator as m}from"@real-router/core";import{getRouteUtils as ee,startsWithSegment as h}from"@real-router/route-utils";import{createActiveRouteSource as te,createDismissableError as ne,createRouteNodeSource as re,createRouteSource as g,getTransitionSource as ie}from"@real-router/sources";import{getPluginApi as ae}from"@real-router/core/api";function _(){return null}const v=i({name:`RouteView.Match`,props:{segment:{type:String,required:!0},exact:{type:Boolean,default:!1},fallback:{type:[Object,Function],default:void 0},keepAlive:{type:Boolean,default:!1}},render:_}),y=i({name:`RouteView.NotFound`,render:_});function oe(e,t,n){return n?e===t:h(e,t)}function b(e){if(Array.isArray(e)){let t=[];for(let n of e)Array.isArray(n)?t.push(...b(n)):s(n)&&t.push(n);return t}return s(e)?[e]:[]}function x(t,n){let r=b(t);for(let t of r)t.type===v||t.type===y?n.push(t):t.type===e&&x(t.children,n)}function se(e,t,n){let r=null,i=!1,a,o=[];for(let s of e){if(s.type===y){r=s.children;continue}let e=s.props,c=e?.segment??``,l=e?.exact??!1,u=n?`${n}.${c}`:c;!i&&oe(t,u,l)&&(i=!0,a=e?.fallback,o.push(s))}if(!i&&t===p&&r!==null){let t=e.filter(e=>e.type===y).at(-1);t&&o.push(t)}return{rendered:o,activeMatchFound:i,fallback:a}}function S(e){let t=d(e.getSnapshot());return l(e.subscribe(()=>{t.value=e.getSnapshot()})),t}const C=Symbol(`RouterKey`),w=Symbol(`NavigatorKey`),T=Symbol(`RouteKey`),E=()=>{let e=o(C);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e};function D(e){let t=E(),n=S(re(t,e));return{navigator:m(t),route:r(()=>n.value.route),previousRoute:r(()=>n.value.previousRoute)}}function O(e){return e.children?.default?.()??null}function k(e,t){let n=e.get(t);if(n)return n;let r=c(i({name:`KeepAlive-${t}`,setup(e,t){return()=>t.slots.default?.()}}));return e.set(t,r),r}function A(e,t){if(t===void 0)return e;let r=typeof t==`function`?t():t;return a(n,{},{default:()=>e,fallback:()=>r})}const ce=c(i({name:`KeepAlive-placeholder`,render(){return null}}));function le(e,n,r){let i=e.props?.segment??`__not-found__`,o=k(n,i),s=O(e)??[];return A(a(t,null,{default:()=>a(o,{key:i},{default:()=>s})}),r)}function j(e){return e===!0||e===``||e===`keep-alive`}function ue(n,r,i){let o=n.props;if(j(o?.keepAlive)&&n.type===v){let i=o?.segment??`__not-found__`,s=k(r,i),c=O(n)??[];return a(e,[a(t,null,{default:()=>a(s,{key:i},{default:()=>c})})])}let s=O(n);return s?a(e,[a(t,null,{default:()=>a(ce)}),A(a(e,s),i)]):null}const de=i({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(t,{slots:n}){let r=D(t.nodeName),i=new Map,o=null,s=!1;function c(e,t){return t===o?s:(o=t,s=e.some(e=>e.type===v&&j(e.props?.keepAlive)),s)}return()=>{let o=r.route.value;if(!o)return null;let s=n.default?.(),l=[];x(s,l);let{rendered:u,fallback:d}=se(l,o.name,t.nodeName);if(u.length===0)return null;let f=u[0];if(t.keepAlive)return le(f,i,d);if(f.type!==v&&f.type!==y)return null;if(c(l,s))return ue(f,i,d);let p=O(f);return p?A(a(e,p),d):null}}}),fe=Object.assign(de,{Match:v,NotFound:y}),pe=Object.freeze({}),me=Object.freeze({}),M=`data-real-router-announcer`;function N(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=P(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),L(t)},f=setTimeout(()=>{if(a=!0,c!==null&&!o){let e=c;c=null,d(e,document.querySelector(`h1`))}},100),p=e.subscribe(({route:e})=>{if(i){i=!1;return}requestAnimationFrame(()=>{requestAnimationFrame(()=>{if(o)return;let t=document.querySelector(`h1`),i=I(e,n,r,t);if(!(!i||i===s)){if(!a){c=i;return}d(i,t)}})})});return{destroy(){o=!0,p(),clearTimeout(l),clearTimeout(f),F()}}}function P(){let e=document.querySelector(`[${M}]`);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(M,``),document.body.prepend(t),t}function F(){document.querySelector(`[${M}]`)?.remove()}function I(e,t,n,r){if(n)return n(e);let i=r?.textContent.trim()??``,a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function L(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const R=`real-router:scroll`,z=Object.freeze({destroy:()=>{}});function he(e,t){if(globalThis.window===void 0)return z;let n=t?.mode??`restore`;if(n===`manual`)return z;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let o=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},s=e=>{let t=i?.();t?t.scrollTop=e:globalThis.scrollTo(0,e)},c=()=>{let e=globalThis.location.hash;if(r&&e.length>1){let t;try{t=decodeURIComponent(e.slice(1))}catch{t=e.slice(1)}let n=document.getElementById(t);if(n){n.scrollIntoView();return}}s(0)},l=!1,u=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;t&&H(B(t),o()),requestAnimationFrame(()=>{if(!l){if(n===`top`||!r){c();return}if(r.navigationType!==`replace`){if(r.direction===`back`||r.navigationType===`traverse`||r.navigationType===`reload`){s(V()[B(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&H(B(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function B(e){return`${e.name}:${ge(e.params)}`}function V(){try{let e=sessionStorage.getItem(R);return e?JSON.parse(e):{}}catch{return{}}}function H(e,t){try{let n=V();n[e]=t,sessionStorage.setItem(R,JSON.stringify(n))}catch{}}function ge(e){return JSON.stringify(e,_e)}function _e(e,t){if(typeof t==`object`&&t&&!Array.isArray(t)){let e={},n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}function U(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function ve(e,t,n){try{let r=e.buildUrl;if(r){let e=r(t,n);if(e!==void 0)return e}return e.buildPath(t,n)}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function W(e){return e?e.match(/\S+/g)??[]:[]}function ye(e,t,n){if(e&&t){let e=W(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=W(n),i=new Set(r);for(let t of e)i.has(t)||(i.add(t),r.push(t));return r.join(` `)}return n??void 0}function be(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function G(e,t){if(typeof e==`function`){e(t);return}if(Array.isArray(e)){let n=e;for(let e of n)if(typeof e==`function`&&(e(t),t.defaultPrevented))return}}const xe=i({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>pe},routeOptions:{type:Object,default:()=>me},class:{type:String,default:void 0},activeClassName:{type:String,default:`active`},activeStrict:{type:Boolean,default:!1},ignoreQueryParams:{type:Boolean,default:!0},target:{type:String,default:void 0}},setup(e,{slots:t,attrs:n}){let i=E(),o=d(!1);f(()=>[e.routeName,e.routeParams,e.activeStrict,e.ignoreQueryParams],([e,t,n,r],a,s)=>{let c=te(i,e,t,{strict:n,ignoreQueryParams:r});o.value=c.getSnapshot(),s(c.subscribe(()=>{o.value=c.getSnapshot()}))},{immediate:!0,flush:`sync`});let s=r(()=>ve(i,e.routeName,e.routeParams)),c=r(()=>ye(o.value,e.activeClassName,e.class)),l=t=>{n.onClick!==void 0&&n.onClick!==null&&(G(n.onClick,t),t.defaultPrevented)||!U(t)||e.target===`_blank`||(t.preventDefault(),i.navigate(e.routeName,e.routeParams,e.routeOptions).catch(()=>{}))};return()=>{let r={};for(let e of Object.keys(n))e!==`onClick`&&(r[e]=n[e]);return a(`a`,{...r,href:s.value,class:c.value,target:e.target,onClick:l},t.default?.())}}}),Se=i({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(t,{slots:n}){let r=S(ne(E()));return f(()=>r.value.version,()=>{r.value.error&&t.onError?.(r.value.error,r.value.toRoute,r.value.fromRoute)},{immediate:!0}),()=>{let i=n.default?.()??[],o=r.value.error?t.fallback(r.value.error,r.value.resetError):null;return a(e,null,[...i,o])}}}),K=[];function q(e){return K.push(e),()=>{let t=K.lastIndexOf(e);t!==-1&&K.splice(t,1)}}function J(){let e=K.at(-1);if(!e)throw Error(`v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.`);return e}const Y=new WeakMap;function X(e){return e==null?(console.error(`[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.`),!1):typeof e.name==`string`?!0:(console.error("[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation."),!1)}function Ce(e,t){return n=>{U(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function we(e,t,n){return r=>{r.key===`Enter`&&!(n instanceof HTMLButtonElement)&&e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{})}}function Z(e,t,n){let r=Ce(t,n),i=we(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),Y.set(e,{click:r,keydown:i})}function Q(e){let t=Y.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),Y.delete(e))}const Te={mounted(e,t){let n=J();be(e),e.style.cursor=`pointer`,X(t.value)&&Z(e,n,t.value)},updated(e,t){let n=J();Q(e),X(t.value)&&Z(e,n,t.value)},beforeUnmount(e){Q(e)}},Ee=()=>{let e=o(w);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},De=()=>ee(ae(E()).getTree()),Oe=()=>{let e=o(T);if(!e)throw Error(`useRoute must be used within a RouterProvider`);return e};function ke(){return S(ie(E()))}function $(e){let t=m(e),n=g(e),r=n.getSnapshot(),i=d(r.route),a=d(r.previousRoute);return{navigator:t,route:i,previousRoute:a,unsubscribe:n.subscribe(()=>{let e=n.getSnapshot();i.value=e.route,a.value=e.previousRoute})}}function Ae(e){return{install(t){let n=q(e),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e);`onUnmount`in t&&t.onUnmount(()=>{n(),o()}),t.provide(C,e),t.provide(w,r),t.provide(T,{navigator:r,route:i,previousRoute:a})}}}const je=i({name:`RouterProvider`,props:{router:{type:Object,required:!0},announceNavigation:{type:Boolean,default:!1},scrollRestoration:{type:Object}},setup(e,{slots:t}){f(()=>[e.router,e.announceNavigation],([e,t],n,r)=>{if(!t)return;let i=N(e);r(()=>{i.destroy()})},{immediate:!0}),f(()=>[e.router,e.scrollRestoration!==void 0,e.scrollRestoration?.mode,e.scrollRestoration?.anchorScrolling],([t,n,r,i],a,o)=>{if(!n)return;let s=he(t,{mode:r,anchorScrolling:i,scrollContainer:e.scrollRestoration?.scrollContainer});o(()=>{s.destroy()})},{immediate:!0});let n=q(e.router),{navigator:r,route:i,previousRoute:a,unsubscribe:o}=$(e.router);return l(()=>{n(),o()}),u(C,e.router),u(w,r),u(T,{navigator:r,route:i,previousRoute:a}),()=>t.default?.()}});export{xe as Link,w as NavigatorKey,T as RouteKey,fe as RouteView,Se as RouterErrorBoundary,C as RouterKey,je as RouterProvider,Ae as createRouterPlugin,Ee as useNavigator,Oe as useRoute,D as useRouteNode,De as useRouteUtils,E as useRouter,ke as useRouterTransition,Te as vLink};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/components/RouteView/components.ts","../../src/components/RouteView/helpers.ts","../../src/useRefFromSource.ts","../../src/context.ts","../../src/composables/useRouter.ts","../../src/composables/useRouteNode.ts","../../src/components/RouteView/RouteView.ts","../../src/constants.ts","../../../../shared/dom-utils/route-announcer.ts","../../../../shared/dom-utils/link-utils.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/composables/useRoute.ts","../../src/composables/useRouterTransition.ts","../../src/setupRouteProvision.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts"],"sourcesContent":["import { defineComponent } from \"vue\";\n\nimport type { PropType, VNode } from \"vue\";\n\nfunction renderNull() {\n return null;\n}\n\nexport const Match = defineComponent({\n name: \"RouteView.Match\",\n props: {\n segment: {\n type: String as PropType<string>,\n required: true,\n },\n exact: {\n type: Boolean,\n default: false,\n },\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n render: renderNull,\n});\n\nexport const NotFound = defineComponent({\n name: \"RouteView.NotFound\",\n render: renderNull,\n});\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isVNode } from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nfunction normalizeChildren(children: unknown): VNode[] {\n if (Array.isArray(children)) {\n const result: VNode[] = [];\n\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...normalizeChildren(child));\n } else if (isVNode(child)) {\n result.push(child);\n }\n }\n\n return result;\n }\n\n if (isVNode(children)) {\n return [children];\n }\n\n return [];\n}\n\nexport function collectElements(children: unknown, result: VNode[]): void {\n const vnodes = normalizeChildren(children);\n\n for (const child of vnodes) {\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): {\n rendered: VNode[];\n activeMatchFound: boolean;\n fallback?: FallbackType;\n} {\n let notFoundChildren: unknown = null;\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = child.children;\n continue;\n }\n\n const props = child.props as {\n segment: string;\n exact?: boolean;\n fallback?: FallbackType;\n } | null;\n const segment = props?.segment ?? \"\";\n const exact = props?.exact ?? false;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n fallback = props?.fallback;\n rendered.push(child);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n const nfElements = elements.filter((element) => element.type === NotFound);\n /* v8 ignore next 3 */\n const lastNf = nfElements.at(-1);\n\n if (lastNf) {\n rendered.push(lastNf);\n }\n }\n\n return { rendered, activeMatchFound, fallback };\n}\n","import { shallowRef, onScopeDispose } from \"vue\";\n\nimport type { RouterSource } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRefFromSource<T>(source: RouterSource<T>): ShallowRef<T> {\n const ref = shallowRef(source.getSnapshot());\n\n const unsub = source.subscribe(() => {\n ref.value = source.getSnapshot();\n });\n\n onScopeDispose(unsub);\n\n return ref;\n}\n","import type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n","import { inject } from \"vue\";\n\nimport { RouterKey } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = inject(RouterKey);\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 { computed } from \"vue\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const source = createRouteNodeSource(router, nodeName);\n const snapshot = useRefFromSource(source);\n\n // getNavigator is WeakMap-cached in core; no useMemo equivalent needed.\n const navigator = getNavigator(router);\n\n // Derive route/previousRoute via computed instead of mirroring with a sync\n // watch into two extra shallowRefs. computed shares snapshot's identity so\n // when the underlying source emits the same reference (idempotent or\n // out-of-node nav), consumers don't see a new ref.\n const route = computed(() => snapshot.value.route);\n const previousRoute = computed(() => snapshot.value.previousRoute);\n\n return {\n navigator,\n route,\n previousRoute,\n };\n}\n","import {\n Fragment,\n defineComponent,\n h,\n KeepAlive,\n markRaw,\n Suspense,\n} from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../composables/useRouteNode\";\n\nimport type { Component, VNode } from \"vue\";\n\ntype SlotChildren = Record<string, (() => VNode[]) | undefined> | null;\n\nfunction getSlotContent(vnode: VNode): VNode[] | null {\n const slots = vnode.children as SlotChildren;\n\n return slots?.default?.() ?? null;\n}\n\nfunction getOrCreateWrapper(\n cache: Map<string, Component>,\n segment: string,\n): Component {\n const existing = cache.get(segment);\n\n if (existing) {\n return existing;\n }\n\n const wrapper = markRaw(\n defineComponent({\n name: `KeepAlive-${segment}`,\n setup(_wrapperProps, wrapperCtx) {\n return () => wrapperCtx.slots.default?.();\n },\n }),\n );\n\n cache.set(segment, wrapper);\n\n return wrapper;\n}\n\nfunction wrapWithSuspense(content: VNode, fallback: unknown): VNode {\n if (fallback === undefined) {\n return content;\n }\n\n const fallbackContent =\n typeof fallback === \"function\" ? (fallback as () => VNode)() : fallback;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n const suspenseComponent = Suspense as any;\n\n return h(\n suspenseComponent,\n {},\n {\n default: () => content,\n fallback: () => fallbackContent,\n },\n );\n}\n\nconst emptyKeepAlivePlaceholder = markRaw(\n defineComponent({\n name: \"KeepAlive-placeholder\",\n render() {\n return null;\n },\n }),\n);\n\nfunction renderWithRootKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode {\n const activeProps = activeChild.props as { segment?: string } | null;\n const segment = activeProps?.segment ?? \"__not-found__\";\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n const keepAliveContent = h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n });\n\n return wrapWithSuspense(keepAliveContent, fallback);\n}\n\n// Vue compiles boolean-shorthand template attributes (`<Match keepAlive>`) to\n// an empty string instead of `true`, and converts them to `true` only when the\n// receiving component's prop is declared with `type: Boolean`. `Match` is a\n// marker component (`render: null`) — its props are inspected on the VNode\n// without ever going through Vue's prop-casting pipeline, so the raw `\"\"` (or\n// the hyphenated attribute name) reaches us here. Accept the same trio Vue's\n// runtime does.\nfunction isKeepAliveEnabled(value: unknown): boolean {\n return value === true || value === \"\" || value === \"keep-alive\";\n}\n\nfunction renderWithPerMatchKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode | null {\n const matchProps = activeChild.props as {\n segment?: string;\n keepAlive?: unknown;\n } | null;\n\n if (isKeepAliveEnabled(matchProps?.keepAlive) && activeChild.type === Match) {\n /* v8 ignore start */\n const segment = matchProps?.segment ?? \"__not-found__\";\n /* v8 ignore stop */\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n\n return h(Fragment, [\n h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n }),\n ]);\n }\n\n const content = getSlotContent(activeChild);\n\n /* v8 ignore start */\n if (!content) {\n return null;\n }\n /* v8 ignore stop */\n\n return h(Fragment, [\n h(KeepAlive, null, { default: () => h(emptyKeepAlivePlaceholder) }),\n wrapWithSuspense(h(Fragment, content), fallback),\n ]);\n}\n\nconst RouteViewComponent = defineComponent({\n name: \"RouteView\",\n props: {\n nodeName: {\n type: String,\n required: true,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n const routeContext = useRouteNode(props.nodeName);\n const wrapperCache = new Map<string, Component>();\n\n // Cache per-Match `keepAlive` detection by slot output identity. Slot\n // contents change reference only when the parent re-renders with new\n // children, so steady-state navigations skip the O(n) `.some(...)` scan.\n let lastSlotOutput: unknown = null;\n let lastHasPerMatchKA = false;\n\n function detectPerMatchKA(elements: VNode[], slotOutput: unknown): boolean {\n /* v8 ignore next 3 -- @preserve: Vue's compiled slot wrapper allocates a\n new array per render call in JSDOM tests; identity-cache hits in\n production where parent compiled templates share slot output, but\n is unobservable through TestBed-style assertions. */\n if (slotOutput === lastSlotOutput) {\n return lastHasPerMatchKA;\n }\n\n lastSlotOutput = slotOutput;\n lastHasPerMatchKA = elements.some(\n (element) =>\n element.type === Match &&\n isKeepAliveEnabled(\n (element.props as { keepAlive?: unknown } | null)?.keepAlive,\n ),\n );\n\n return lastHasPerMatchKA;\n }\n\n return (): VNode | null => {\n const route = routeContext.route.value;\n\n if (!route) {\n return null;\n }\n\n const slotOutput = slots.default?.();\n const elements: VNode[] = [];\n\n collectElements(slotOutput, elements);\n\n const { rendered, fallback } = buildRenderList(\n elements,\n route.name,\n props.nodeName,\n );\n\n if (rendered.length === 0) {\n return null;\n }\n\n const activeChild = rendered[0];\n\n if (props.keepAlive) {\n return renderWithRootKA(activeChild, wrapperCache, fallback);\n }\n\n /* v8 ignore start */\n if (activeChild.type !== Match && activeChild.type !== NotFound) {\n return null;\n }\n /* v8 ignore stop */\n\n const hasPerMatchKA = detectPerMatchKA(elements, slotOutput);\n\n if (hasPerMatchKA) {\n return renderWithPerMatchKA(activeChild, wrapperCache, fallback);\n }\n\n const content = getSlotContent(activeChild);\n\n if (!content) {\n return null;\n }\n\n return wrapWithSuspense(h(Fragment, content), fallback);\n };\n },\n});\n\nexport const RouteView = Object.assign(RouteViewComponent, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\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 { Router, State } from \"@real-router/core\";\n\nconst CLEAR_DELAY = 7000;\nconst SAFARI_READY_DELAY = 100;\nconst ANNOUNCER_ATTR = \"data-real-router-announcer\";\nconst INTERNAL_ROUTE_PREFIX = \"@@\";\nconst VISUALLY_HIDDEN =\n \"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\nexport interface RouteAnnouncerOptions {\n prefix?: string;\n getAnnouncementText?: (route: State) => string;\n}\n\nexport function createRouteAnnouncer(\n router: Router,\n options?: RouteAnnouncerOptions,\n): { destroy: () => void } {\n const prefix = options?.prefix ?? \"Navigated to \";\n const getCustomText = options?.getAnnouncementText;\n\n let isInitialNavigation = true;\n let isReady = false;\n let isDestroyed = false;\n let lastAnnouncedText = \"\";\n let pendingText: string | null = null;\n let clearTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const announcer = getOrCreateAnnouncer();\n\n const doAnnounce = (text: string, h1: HTMLElement | null): void => {\n lastAnnouncedText = text;\n clearTimeout(clearTimeoutId);\n announcer.textContent = text;\n clearTimeoutId = setTimeout(() => {\n announcer.textContent = \"\";\n lastAnnouncedText = \"\";\n }, CLEAR_DELAY);\n\n manageFocus(h1);\n };\n\n // Safari-ready delay: announcing before VoiceOver wires up the aria-live region\n // causes the first announcement to be silently dropped. Wait SAFARI_READY_DELAY ms\n // before marking the announcer \"ready\" — any navigation during that window is\n // buffered in pendingText and flushed once the delay expires.\n const safariTimeoutId = setTimeout(() => {\n isReady = true;\n\n if (pendingText !== null && !isDestroyed) {\n const text = pendingText;\n\n pendingText = null;\n doAnnounce(text, document.querySelector<HTMLElement>(\"h1\"));\n }\n }, SAFARI_READY_DELAY);\n\n const unsubscribe = router.subscribe(({ route }) => {\n if (isInitialNavigation) {\n isInitialNavigation = false;\n\n return;\n }\n\n // Double rAF: waits for two paint frames so the incoming route's DOM\n // (including the new <h1>) is fully rendered before resolveText reads it.\n // Single rAF fires before the new route's template has been attached,\n // which would cause resolveText to pick up the OLD h1 or fall back to\n // document.title / route.name prematurely.\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (isDestroyed) {\n return;\n }\n\n const h1 = document.querySelector<HTMLElement>(\"h1\");\n const text = resolveText(route, prefix, getCustomText, h1);\n\n if (!text || text === lastAnnouncedText) {\n return;\n }\n\n if (!isReady) {\n // Defer announcement until Safari-ready window elapses (see safariTimeoutId).\n pendingText = text;\n\n return;\n }\n\n doAnnounce(text, h1);\n });\n });\n });\n\n return {\n destroy() {\n isDestroyed = true;\n unsubscribe();\n clearTimeout(clearTimeoutId);\n clearTimeout(safariTimeoutId);\n removeAnnouncer();\n },\n };\n}\n\nfunction getOrCreateAnnouncer(): HTMLElement {\n const existing = document.querySelector<HTMLElement>(`[${ANNOUNCER_ATTR}]`);\n\n if (existing) {\n return existing;\n }\n\n const element = document.createElement(\"div\");\n\n element.setAttribute(\"style\", VISUALLY_HIDDEN);\n element.setAttribute(\"aria-live\", \"assertive\");\n element.setAttribute(\"aria-atomic\", \"true\");\n element.setAttribute(ANNOUNCER_ATTR, \"\");\n\n document.body.prepend(element);\n\n return element;\n}\n\nfunction removeAnnouncer(): void {\n document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();\n}\n\nfunction resolveText(\n route: State,\n prefix: string,\n getCustomText: ((route: State) => string) | undefined,\n h1: HTMLElement | null,\n): string {\n if (getCustomText) {\n return getCustomText(route);\n }\n\n const h1Text = h1?.textContent.trim() ?? \"\";\n const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX)\n ? \"\"\n : route.name;\n const rawText =\n h1Text || document.title || routeName || globalThis.location.pathname;\n\n return `${prefix}${rawText}`;\n}\n\nfunction manageFocus(h1: HTMLElement | null): void {\n if (!h1) {\n return;\n }\n\n if (!h1.hasAttribute(\"tabindex\")) {\n h1.setAttribute(\"tabindex\", \"-1\");\n }\n\n h1.focus({ preventScroll: true });\n}\n","import type { Router, Params } from \"@real-router/core\";\n\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 &&\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n\ntype BuildUrlFn = (name: string, params: Params) => string | undefined;\n\nexport function buildHref(\n router: Router,\n routeName: string,\n routeParams: Params,\n): string | undefined {\n try {\n const buildUrl = router.buildUrl as BuildUrlFn | undefined;\n\n if (buildUrl) {\n const url = buildUrl(routeName, routeParams);\n\n if (url !== undefined) {\n return url;\n }\n }\n\n return router.buildPath(routeName, routeParams);\n } catch {\n console.error(\n `[real-router] Route \"${routeName}\" is not defined. The element will render without an href attribute.`,\n );\n\n return undefined;\n }\n}\n\nfunction parseTokens(value: string | undefined): string[] {\n return value ? (value.match(/\\S+/g) ?? []) : [];\n}\n\nexport function buildActiveClassName(\n isActive: boolean,\n activeClassName: string | undefined,\n baseClassName: string | undefined,\n): string | undefined {\n if (isActive && activeClassName) {\n const activeTokens = parseTokens(activeClassName);\n\n if (activeTokens.length === 0) {\n return baseClassName ?? undefined;\n }\n if (!baseClassName) {\n return activeTokens.join(\" \");\n }\n\n const baseTokens = parseTokens(baseClassName);\n const seen = new Set(baseTokens);\n\n for (const token of activeTokens) {\n if (!seen.has(token)) {\n seen.add(token);\n baseTokens.push(token);\n }\n }\n\n return baseTokens.join(\" \");\n }\n\n return baseClassName ?? undefined;\n}\n\nexport function shallowEqual(\n prev: object | undefined,\n next: object | undefined,\n): boolean {\n if (Object.is(prev, next)) {\n return true;\n }\n if (!prev || !next) {\n return false;\n }\n\n const prevKeys = Object.keys(prev);\n\n if (prevKeys.length !== Object.keys(next).length) {\n return false;\n }\n\n const prevRecord = prev as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n\n for (const key of prevKeys) {\n if (!Object.is(prevRecord[key], nextRecord[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function applyLinkA11y(element: HTMLElement | null | undefined): void {\n if (!element) {\n return;\n }\n if (\n element instanceof HTMLAnchorElement ||\n element instanceof HTMLButtonElement\n ) {\n return;\n }\n if (!element.hasAttribute(\"role\")) {\n element.setAttribute(\"role\", \"link\");\n }\n if (!element.hasAttribute(\"tabindex\")) {\n element.setAttribute(\"tabindex\", \"0\");\n }\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { defineComponent, h, computed, shallowRef, watch } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport {\n shouldNavigate,\n buildHref,\n buildActiveClassName,\n} from \"../dom-utils/index.js\";\n\nimport type { Params, NavigationOptions } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\ntype OnClickHandler = (evt: MouseEvent) => void;\n\n/**\n * Vue's compiled template binds multiple `@click` handlers as an array.\n * Single render-function `onClick` is a function. Both must be invoked.\n */\nfunction invokeAttributesOnClick(value: unknown, evt: MouseEvent): void {\n if (typeof value === \"function\") {\n (value as OnClickHandler)(evt);\n\n return;\n }\n if (Array.isArray(value)) {\n const handlers = value as OnClickHandler[];\n\n for (const fn of handlers) {\n if (typeof fn === \"function\") {\n fn(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n }\n }\n}\n\nexport const Link = defineComponent({\n name: \"Link\",\n // Disable Vue's automatic attribute fallthrough. Without this, attrs.onClick\n // (function OR array) is auto-attached as a native click listener AND our\n // explicit onClick fires too — user handlers are double-invoked. We invoke\n // attrs.onClick manually inside handleClick to preserve preventDefault.\n inheritAttrs: false,\n props: {\n routeName: {\n type: String,\n required: true,\n },\n routeParams: {\n type: Object as PropType<Params>,\n default: () => EMPTY_PARAMS,\n },\n routeOptions: {\n type: Object as PropType<NavigationOptions>,\n default: () => EMPTY_OPTIONS,\n },\n class: {\n type: String,\n default: undefined,\n },\n activeClassName: {\n type: String,\n default: \"active\",\n },\n activeStrict: {\n type: Boolean,\n default: false,\n },\n ignoreQueryParams: {\n type: Boolean,\n default: true,\n },\n target: {\n type: String,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const router = useRouter();\n\n const isActive = shallowRef(false);\n\n // watch with an explicit dep getter recreates the source ONLY when\n // routeName/routeParams/strict/ignoreQueryParams change — not on every\n // reactive read inside the source factory (the watchEffect alternative\n // would also re-subscribe whenever isActive itself changed).\n watch(\n () =>\n [\n props.routeName,\n props.routeParams,\n props.activeStrict,\n props.ignoreQueryParams,\n ] as const,\n (\n [routeName, routeParams, activeStrict, ignoreQueryParams],\n _prev,\n onCleanup,\n ) => {\n const source = createActiveRouteSource(router, routeName, routeParams, {\n strict: activeStrict,\n ignoreQueryParams,\n });\n\n isActive.value = source.getSnapshot();\n\n const unsub = source.subscribe(() => {\n isActive.value = source.getSnapshot();\n });\n\n onCleanup(unsub);\n },\n { immediate: true, flush: \"sync\" },\n );\n\n const href = computed(() =>\n buildHref(router, props.routeName, props.routeParams),\n );\n\n const finalClassName = computed(() =>\n buildActiveClassName(isActive.value, props.activeClassName, props.class),\n );\n\n const handleClick = (evt: MouseEvent) => {\n // Vue allows attrs.onClick to be a function or an array of functions\n // (compiled templates with multiple @click bindings produce arrays).\n // Both must be invoked; treating arrays as \"no handler\" silently drops\n // user code.\n if (attrs.onClick !== undefined && attrs.onClick !== null) {\n invokeAttributesOnClick(attrs.onClick, evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || props.target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(props.routeName, props.routeParams, props.routeOptions)\n .catch(() => {});\n };\n\n return () => {\n // Build forwarded attrs without `onClick`. Vue's runtime auto-attaches\n // attrs.onClick (function OR array) as a native DOM listener, which would\n // double-invoke user handlers when combined with our explicit `onClick`.\n // We invoke the original attrs.onClick manually inside handleClick so the\n // preventDefault contract is preserved.\n const restAttributes: Record<string, unknown> = {};\n\n for (const key of Object.keys(attrs)) {\n if (key !== \"onClick\") {\n restAttributes[key] = (attrs as Record<string, unknown>)[key];\n }\n }\n\n return h(\n \"a\",\n {\n ...restAttributes,\n href: href.value,\n class: finalClassName.value,\n target: props.target,\n onClick: handleClick,\n },\n slots.default?.(),\n );\n };\n },\n});\n","import { createDismissableError } from \"@real-router/sources\";\nimport { defineComponent, h, watch, Fragment } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { useRefFromSource } from \"../useRefFromSource\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { VNode, PropType } from \"vue\";\n\nexport const RouterErrorBoundary = defineComponent({\n name: \"RouterErrorBoundary\",\n props: {\n fallback: {\n type: Function as PropType<\n (error: RouterError, resetError: () => void) => VNode\n >,\n required: true,\n },\n onError: {\n type: Function as PropType<\n (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void\n >,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const router = useRouter();\n const snapshot = useRefFromSource(createDismissableError(router));\n\n watch(\n () => snapshot.value.version,\n () => {\n if (snapshot.value.error) {\n props.onError?.(\n snapshot.value.error,\n snapshot.value.toRoute,\n snapshot.value.fromRoute,\n );\n }\n },\n { immediate: true },\n );\n\n return () => {\n const children = slots.default?.() ?? [];\n const errorVNode = snapshot.value.error\n ? props.fallback(snapshot.value.error, snapshot.value.resetError)\n : null;\n\n return h(Fragment, null, [...children, errorVNode]);\n };\n },\n});\n\nexport type RouterErrorBoundaryProps = InstanceType<\n typeof RouterErrorBoundary\n>[\"$props\"];\n","import { shouldNavigate, applyLinkA11y } from \"../dom-utils/index.js\";\n\nimport type { Router, NavigationOptions, Params } from \"@real-router/core\";\nimport type { Directive } from \"vue\";\n\nexport interface LinkDirectiveValue {\n name: string;\n params?: Params;\n options?: NavigationOptions;\n}\n\n/**\n * Router stack for nested RouterProviders. The active router is the top of\n * the stack. RouterProvider pushes its router on mount and pops it on unmount,\n * which preserves the parent context when an inner provider tears down.\n *\n * Without the stack, an unmounted child provider would leave the directive\n * pointing at a disposed router, and v-link in the still-mounted parent would\n * navigate via the wrong (or torn-down) instance.\n */\nconst routerStack: Router[] = [];\n\n/**\n * Pushes a router onto the active stack. Returns a release function that\n * removes that exact router from the stack regardless of position — safe\n * across out-of-order provider unmount sequences.\n *\n * @internal Used by RouterProvider during setup/teardown.\n */\nexport function pushDirectiveRouter(router: Router): () => void {\n routerStack.push(router);\n\n return () => {\n const idx = routerStack.lastIndexOf(router);\n\n if (idx !== -1) {\n routerStack.splice(idx, 1);\n }\n };\n}\n\n/**\n * Backwards-compatible alias. Replaces the active router unconditionally and\n * does NOT participate in the stack — use {@link pushDirectiveRouter} from\n * provider code instead. Kept for tests and direct callers.\n */\nexport function setDirectiveRouter(router: Router | null): void {\n if (router === null) {\n routerStack.length = 0;\n\n return;\n }\n if (routerStack.length === 0) {\n routerStack.push(router);\n\n return;\n }\n\n routerStack[routerStack.length - 1] = router;\n}\n\nexport function getDirectiveRouter(): Router {\n const top = routerStack.at(-1);\n\n if (!top) {\n throw new Error(\n \"v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.\",\n );\n }\n\n return top;\n}\n\ninterface Handlers {\n click: (evt: MouseEvent) => void;\n keydown: (evt: KeyboardEvent) => void;\n}\n\n// Single WeakMap halves per-element bookkeeping vs two parallel maps.\nconst handlers = new WeakMap<HTMLElement, Handlers>();\n\n/**\n * Validates a directive binding value before attaching handlers.\n * Returns false (and warns once per call) when the value is missing or\n * has no `name` — silently doing nothing is preferable to a runtime crash\n * inside a click handler.\n */\nfunction isValidBinding(value: unknown): value is LinkDirectiveValue {\n if (value === null || value === undefined) {\n console.error(\n \"[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n if (typeof (value as { name?: unknown }).name !== \"string\") {\n console.error(\n \"[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n\n return true;\n}\n\nfunction createClickHandler(\n router: Router,\n value: LinkDirectiveValue,\n): (evt: MouseEvent) => void {\n return (evt: MouseEvent) => {\n if (!shouldNavigate(evt)) {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n };\n}\n\nfunction createKeydownHandler(\n router: Router,\n value: LinkDirectiveValue,\n element: HTMLElement,\n): (evt: KeyboardEvent) => void {\n return (evt: KeyboardEvent) => {\n if (evt.key === \"Enter\" && !(element instanceof HTMLButtonElement)) {\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n }\n };\n}\n\nfunction attachHandlers(\n element: HTMLElement,\n router: Router,\n value: LinkDirectiveValue,\n): void {\n const click = createClickHandler(router, value);\n const keydown = createKeydownHandler(router, value, element);\n\n element.addEventListener(\"click\", click);\n element.addEventListener(\"keydown\", keydown);\n\n handlers.set(element, { click, keydown });\n}\n\nfunction detachHandlers(element: HTMLElement): void {\n const entry = handlers.get(element);\n\n if (entry) {\n element.removeEventListener(\"click\", entry.click);\n element.removeEventListener(\"keydown\", entry.keydown);\n handlers.delete(element);\n }\n}\n\nexport const vLink: Directive<HTMLElement, LinkDirectiveValue> = {\n mounted(element, binding) {\n const router = getDirectiveRouter();\n\n applyLinkA11y(element);\n\n element.style.cursor = \"pointer\";\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n updated(element, binding) {\n const router = getDirectiveRouter();\n\n detachHandlers(element);\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n beforeUnmount(element) {\n detachHandlers(element);\n },\n};\n","import { inject } from \"vue\";\n\nimport { NavigatorKey } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = inject(NavigatorKey);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { 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\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params } from \"@real-router/core\";\n\nexport const useRoute = <P extends Params = Params>(): RouteContext<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n return routeContext as RouteContext<P>;\n};\n","import { getTransitionSource } from \"@real-router/sources\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRouterTransition(): ShallowRef<RouterTransitionSnapshot> {\n const router = useRouter();\n const source = getTransitionSource(router);\n\n return useRefFromSource(source);\n}\n","// packages/vue/src/setupRouteProvision.ts\n\nimport { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { shallowRef } from \"vue\";\n\nimport type { Router, Navigator, State } from \"@real-router/core\";\nimport type { ShallowRef } from \"vue\";\n\n/**\n * Shared setup for `RouterProvider` (component-scoped) and\n * `createRouterPlugin` (app-scoped). Builds the reactive route refs +\n * subscription bookkeeping in one place; callers wire the result into their\n * provide/inject mechanism and own teardown lifecycle.\n *\n * @internal\n */\nexport interface RouteProvision {\n navigator: Navigator;\n route: ShallowRef<State | undefined>;\n previousRoute: ShallowRef<State | undefined>;\n /** Call when the owning scope tears down to release the router subscription. */\n unsubscribe: () => void;\n}\n\nexport function setupRouteProvision(router: Router): RouteProvision {\n const navigator = getNavigator(router);\n const source = createRouteSource(router);\n const initial = source.getSnapshot();\n\n const route = shallowRef<State | undefined>(initial.route);\n const previousRoute = shallowRef<State | undefined>(initial.previousRoute);\n\n const unsubscribe = source.subscribe(() => {\n const snapshot = source.getSnapshot();\n\n route.value = snapshot.route;\n previousRoute.value = snapshot.previousRoute;\n });\n\n return { navigator, route, previousRoute, unsubscribe };\n}\n","import { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { App, Plugin } from \"vue\";\n\nexport function createRouterPlugin(router: Router): Plugin<[]> {\n return {\n install(app): void {\n const releaseDirective = pushDirectiveRouter(router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(router);\n\n // Vue 3.5+ exposes app.onUnmount for plugin cleanup.\n // On older versions (3.3–3.4), the subscription is cleaned up\n // when the router is garbage-collected (same as vue-router).\n if (\"onUnmount\" in app) {\n (app as App & { onUnmount: (fn: () => void) => void }).onUnmount(() => {\n releaseDirective();\n unsubscribe();\n });\n }\n\n app.provide(RouterKey, router);\n app.provide(NavigatorKey, navigator);\n app.provide(RouteKey, { navigator, route, previousRoute });\n },\n };\n}\n","import { defineComponent, onScopeDispose, provide, watch } from \"vue\";\n\nimport { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { createRouteAnnouncer } from \"./dom-utils/index.js\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\nexport const RouterProvider = defineComponent({\n name: \"RouterProvider\",\n props: {\n router: {\n type: Object as PropType<Router>,\n required: true,\n },\n announceNavigation: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n // Reactive announceNavigation: setting prop true/false at runtime now\n // creates/destroys the announcer accordingly. Prior implementation read\n // the prop only inside onMounted, so toggling it post-mount silently no-op'd.\n watch(\n () => [props.router, props.announceNavigation] as const,\n ([router, enabled], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n onCleanup(() => {\n announcer.destroy();\n });\n },\n { immediate: true },\n );\n\n // Push this provider's router on the v-link directive stack so nested\n // RouterProviders behave like nested DI scopes (LIFO). Release on unmount\n // restores the outer router for any v-link still mounted in the parent.\n const releaseDirective = pushDirectiveRouter(props.router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(props.router);\n\n onScopeDispose(() => {\n releaseDirective();\n unsubscribe();\n });\n\n provide(RouterKey, props.router);\n provide(NavigatorKey, navigator);\n provide(RouteKey, { navigator, route, previousRoute });\n\n return () => slots.default?.();\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/components/RouteView/components.ts","../../src/components/RouteView/helpers.ts","../../src/useRefFromSource.ts","../../src/context.ts","../../src/composables/useRouter.ts","../../src/composables/useRouteNode.ts","../../src/components/RouteView/RouteView.ts","../../src/constants.ts","../../../../shared/dom-utils/route-announcer.ts","../../../../shared/dom-utils/scroll-restore.ts","../../../../shared/dom-utils/link-utils.ts","../../src/components/Link.ts","../../src/components/RouterErrorBoundary.ts","../../src/directives/vLink.ts","../../src/composables/useNavigator.ts","../../src/composables/useRouteUtils.ts","../../src/composables/useRoute.ts","../../src/composables/useRouterTransition.ts","../../src/setupRouteProvision.ts","../../src/createRouterPlugin.ts","../../src/RouterProvider.ts"],"sourcesContent":["import { defineComponent } from \"vue\";\n\nimport type { PropType, VNode } from \"vue\";\n\nfunction renderNull() {\n return null;\n}\n\nexport const Match = defineComponent({\n name: \"RouteView.Match\",\n props: {\n segment: {\n type: String as PropType<string>,\n required: true,\n },\n exact: {\n type: Boolean,\n default: false,\n },\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n render: renderNull,\n});\n\nexport const NotFound = defineComponent({\n name: \"RouteView.NotFound\",\n render: renderNull,\n});\n","import { UNKNOWN_ROUTE } from \"@real-router/core\";\nimport { startsWithSegment } from \"@real-router/route-utils\";\nimport { Fragment, isVNode } from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\nfunction isSegmentMatch(\n routeName: string,\n fullSegmentName: string,\n exact: boolean,\n): boolean {\n if (exact) {\n return routeName === fullSegmentName;\n }\n\n return startsWithSegment(routeName, fullSegmentName);\n}\n\nfunction normalizeChildren(children: unknown): VNode[] {\n if (Array.isArray(children)) {\n const result: VNode[] = [];\n\n for (const child of children) {\n if (Array.isArray(child)) {\n result.push(...normalizeChildren(child));\n } else if (isVNode(child)) {\n result.push(child);\n }\n }\n\n return result;\n }\n\n if (isVNode(children)) {\n return [children];\n }\n\n return [];\n}\n\nexport function collectElements(children: unknown, result: VNode[]): void {\n const vnodes = normalizeChildren(children);\n\n for (const child of vnodes) {\n if (child.type === Match || child.type === NotFound) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nexport function buildRenderList(\n elements: VNode[],\n routeName: string,\n nodeName: string,\n): {\n rendered: VNode[];\n activeMatchFound: boolean;\n fallback?: FallbackType;\n} {\n let notFoundChildren: unknown = null;\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (child.type === NotFound) {\n notFoundChildren = child.children;\n continue;\n }\n\n const props = child.props as {\n segment: string;\n exact?: boolean;\n fallback?: FallbackType;\n } | null;\n const segment = props?.segment ?? \"\";\n const exact = props?.exact ?? false;\n const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;\n const isActive =\n !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);\n\n if (isActive) {\n activeMatchFound = true;\n fallback = props?.fallback;\n rendered.push(child);\n }\n }\n\n if (\n !activeMatchFound &&\n routeName === UNKNOWN_ROUTE &&\n notFoundChildren !== null\n ) {\n const nfElements = elements.filter((element) => element.type === NotFound);\n /* v8 ignore next 3 */\n const lastNf = nfElements.at(-1);\n\n if (lastNf) {\n rendered.push(lastNf);\n }\n }\n\n return { rendered, activeMatchFound, fallback };\n}\n","import { shallowRef, onScopeDispose } from \"vue\";\n\nimport type { RouterSource } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRefFromSource<T>(source: RouterSource<T>): ShallowRef<T> {\n const ref = shallowRef(source.getSnapshot());\n\n const unsub = source.subscribe(() => {\n ref.value = source.getSnapshot();\n });\n\n onScopeDispose(unsub);\n\n return ref;\n}\n","import type { RouteContext as RouteContextType } from \"./types\";\nimport type { Router, Navigator } from \"@real-router/core\";\nimport type { InjectionKey } from \"vue\";\n\nexport const RouterKey: InjectionKey<Router> = Symbol(\"RouterKey\");\n\nexport const NavigatorKey: InjectionKey<Navigator> = Symbol(\"NavigatorKey\");\n\nexport const RouteKey: InjectionKey<RouteContextType> = Symbol(\"RouteKey\");\n","import { inject } from \"vue\";\n\nimport { RouterKey } from \"../context\";\n\nimport type { Router } from \"@real-router/core\";\n\nexport const useRouter = (): Router => {\n const router = inject(RouterKey);\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 { computed } from \"vue\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouteContext } from \"../types\";\n\nexport function useRouteNode(nodeName: string): RouteContext {\n const router = useRouter();\n\n const source = createRouteNodeSource(router, nodeName);\n const snapshot = useRefFromSource(source);\n\n // getNavigator is WeakMap-cached in core; no useMemo equivalent needed.\n const navigator = getNavigator(router);\n\n // Derive route/previousRoute via computed instead of mirroring with a sync\n // watch into two extra shallowRefs. computed shares snapshot's identity so\n // when the underlying source emits the same reference (idempotent or\n // out-of-node nav), consumers don't see a new ref.\n const route = computed(() => snapshot.value.route);\n const previousRoute = computed(() => snapshot.value.previousRoute);\n\n return {\n navigator,\n route,\n previousRoute,\n };\n}\n","import {\n Fragment,\n defineComponent,\n h,\n KeepAlive,\n markRaw,\n Suspense,\n} from \"vue\";\n\nimport { Match, NotFound } from \"./components\";\nimport { buildRenderList, collectElements } from \"./helpers\";\nimport { useRouteNode } from \"../../composables/useRouteNode\";\n\nimport type { Component, VNode } from \"vue\";\n\ntype SlotChildren = Record<string, (() => VNode[]) | undefined> | null;\n\nfunction getSlotContent(vnode: VNode): VNode[] | null {\n const slots = vnode.children as SlotChildren;\n\n return slots?.default?.() ?? null;\n}\n\nfunction getOrCreateWrapper(\n cache: Map<string, Component>,\n segment: string,\n): Component {\n const existing = cache.get(segment);\n\n if (existing) {\n return existing;\n }\n\n const wrapper = markRaw(\n defineComponent({\n name: `KeepAlive-${segment}`,\n setup(_wrapperProps, wrapperCtx) {\n return () => wrapperCtx.slots.default?.();\n },\n }),\n );\n\n cache.set(segment, wrapper);\n\n return wrapper;\n}\n\nfunction wrapWithSuspense(content: VNode, fallback: unknown): VNode {\n if (fallback === undefined) {\n return content;\n }\n\n const fallbackContent =\n typeof fallback === \"function\" ? (fallback as () => VNode)() : fallback;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n const suspenseComponent = Suspense as any;\n\n return h(\n suspenseComponent,\n {},\n {\n default: () => content,\n fallback: () => fallbackContent,\n },\n );\n}\n\nconst emptyKeepAlivePlaceholder = markRaw(\n defineComponent({\n name: \"KeepAlive-placeholder\",\n render() {\n return null;\n },\n }),\n);\n\nfunction renderWithRootKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode {\n const activeProps = activeChild.props as { segment?: string } | null;\n const segment = activeProps?.segment ?? \"__not-found__\";\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n const keepAliveContent = h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n });\n\n return wrapWithSuspense(keepAliveContent, fallback);\n}\n\n// Vue compiles boolean-shorthand template attributes (`<Match keepAlive>`) to\n// an empty string instead of `true`, and converts them to `true` only when the\n// receiving component's prop is declared with `type: Boolean`. `Match` is a\n// marker component (`render: null`) — its props are inspected on the VNode\n// without ever going through Vue's prop-casting pipeline, so the raw `\"\"` (or\n// the hyphenated attribute name) reaches us here. Accept the same trio Vue's\n// runtime does.\nfunction isKeepAliveEnabled(value: unknown): boolean {\n return value === true || value === \"\" || value === \"keep-alive\";\n}\n\nfunction renderWithPerMatchKA(\n activeChild: VNode,\n wrapperCache: Map<string, Component>,\n fallback: unknown,\n): VNode | null {\n const matchProps = activeChild.props as {\n segment?: string;\n keepAlive?: unknown;\n } | null;\n\n if (isKeepAliveEnabled(matchProps?.keepAlive) && activeChild.type === Match) {\n /* v8 ignore start */\n const segment = matchProps?.segment ?? \"__not-found__\";\n /* v8 ignore stop */\n const WrapperComponent = getOrCreateWrapper(wrapperCache, segment);\n const slotContent = getSlotContent(activeChild) ?? [];\n\n return h(Fragment, [\n h(KeepAlive, null, {\n default: () =>\n h(WrapperComponent, { key: segment }, { default: () => slotContent }),\n }),\n ]);\n }\n\n const content = getSlotContent(activeChild);\n\n /* v8 ignore start */\n if (!content) {\n return null;\n }\n /* v8 ignore stop */\n\n return h(Fragment, [\n h(KeepAlive, null, { default: () => h(emptyKeepAlivePlaceholder) }),\n wrapWithSuspense(h(Fragment, content), fallback),\n ]);\n}\n\nconst RouteViewComponent = defineComponent({\n name: \"RouteView\",\n props: {\n nodeName: {\n type: String,\n required: true,\n },\n keepAlive: {\n type: Boolean,\n default: false,\n },\n },\n setup(props, { slots }) {\n const routeContext = useRouteNode(props.nodeName);\n const wrapperCache = new Map<string, Component>();\n\n // Cache per-Match `keepAlive` detection by slot output identity. Slot\n // contents change reference only when the parent re-renders with new\n // children, so steady-state navigations skip the O(n) `.some(...)` scan.\n let lastSlotOutput: unknown = null;\n let lastHasPerMatchKA = false;\n\n function detectPerMatchKA(elements: VNode[], slotOutput: unknown): boolean {\n /* v8 ignore next 3 -- @preserve: Vue's compiled slot wrapper allocates a\n new array per render call in JSDOM tests; identity-cache hits in\n production where parent compiled templates share slot output, but\n is unobservable through TestBed-style assertions. */\n if (slotOutput === lastSlotOutput) {\n return lastHasPerMatchKA;\n }\n\n lastSlotOutput = slotOutput;\n lastHasPerMatchKA = elements.some(\n (element) =>\n element.type === Match &&\n isKeepAliveEnabled(\n (element.props as { keepAlive?: unknown } | null)?.keepAlive,\n ),\n );\n\n return lastHasPerMatchKA;\n }\n\n return (): VNode | null => {\n const route = routeContext.route.value;\n\n if (!route) {\n return null;\n }\n\n const slotOutput = slots.default?.();\n const elements: VNode[] = [];\n\n collectElements(slotOutput, elements);\n\n const { rendered, fallback } = buildRenderList(\n elements,\n route.name,\n props.nodeName,\n );\n\n if (rendered.length === 0) {\n return null;\n }\n\n const activeChild = rendered[0];\n\n if (props.keepAlive) {\n return renderWithRootKA(activeChild, wrapperCache, fallback);\n }\n\n /* v8 ignore start */\n if (activeChild.type !== Match && activeChild.type !== NotFound) {\n return null;\n }\n /* v8 ignore stop */\n\n const hasPerMatchKA = detectPerMatchKA(elements, slotOutput);\n\n if (hasPerMatchKA) {\n return renderWithPerMatchKA(activeChild, wrapperCache, fallback);\n }\n\n const content = getSlotContent(activeChild);\n\n if (!content) {\n return null;\n }\n\n return wrapWithSuspense(h(Fragment, content), fallback);\n };\n },\n});\n\nexport const RouteView = Object.assign(RouteViewComponent, { Match, NotFound });\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n NotFoundProps as RouteViewNotFoundProps,\n} from \"./types\";\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 { Router, State } from \"@real-router/core\";\n\nconst CLEAR_DELAY = 7000;\nconst SAFARI_READY_DELAY = 100;\nconst ANNOUNCER_ATTR = \"data-real-router-announcer\";\nconst INTERNAL_ROUTE_PREFIX = \"@@\";\nconst VISUALLY_HIDDEN =\n \"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\nexport interface RouteAnnouncerOptions {\n prefix?: string;\n getAnnouncementText?: (route: State) => string;\n}\n\nexport function createRouteAnnouncer(\n router: Router,\n options?: RouteAnnouncerOptions,\n): { destroy: () => void } {\n const prefix = options?.prefix ?? \"Navigated to \";\n const getCustomText = options?.getAnnouncementText;\n\n let isInitialNavigation = true;\n let isReady = false;\n let isDestroyed = false;\n let lastAnnouncedText = \"\";\n let pendingText: string | null = null;\n let clearTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const announcer = getOrCreateAnnouncer();\n\n const doAnnounce = (text: string, h1: HTMLElement | null): void => {\n lastAnnouncedText = text;\n clearTimeout(clearTimeoutId);\n announcer.textContent = text;\n clearTimeoutId = setTimeout(() => {\n announcer.textContent = \"\";\n lastAnnouncedText = \"\";\n }, CLEAR_DELAY);\n\n manageFocus(h1);\n };\n\n // Safari-ready delay: announcing before VoiceOver wires up the aria-live region\n // causes the first announcement to be silently dropped. Wait SAFARI_READY_DELAY ms\n // before marking the announcer \"ready\" — any navigation during that window is\n // buffered in pendingText and flushed once the delay expires.\n const safariTimeoutId = setTimeout(() => {\n isReady = true;\n\n if (pendingText !== null && !isDestroyed) {\n const text = pendingText;\n\n pendingText = null;\n doAnnounce(text, document.querySelector<HTMLElement>(\"h1\"));\n }\n }, SAFARI_READY_DELAY);\n\n const unsubscribe = router.subscribe(({ route }) => {\n if (isInitialNavigation) {\n isInitialNavigation = false;\n\n return;\n }\n\n // Double rAF: waits for two paint frames so the incoming route's DOM\n // (including the new <h1>) is fully rendered before resolveText reads it.\n // Single rAF fires before the new route's template has been attached,\n // which would cause resolveText to pick up the OLD h1 or fall back to\n // document.title / route.name prematurely.\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n if (isDestroyed) {\n return;\n }\n\n const h1 = document.querySelector<HTMLElement>(\"h1\");\n const text = resolveText(route, prefix, getCustomText, h1);\n\n if (!text || text === lastAnnouncedText) {\n return;\n }\n\n if (!isReady) {\n // Defer announcement until Safari-ready window elapses (see safariTimeoutId).\n pendingText = text;\n\n return;\n }\n\n doAnnounce(text, h1);\n });\n });\n });\n\n return {\n destroy() {\n isDestroyed = true;\n unsubscribe();\n clearTimeout(clearTimeoutId);\n clearTimeout(safariTimeoutId);\n removeAnnouncer();\n },\n };\n}\n\nfunction getOrCreateAnnouncer(): HTMLElement {\n const existing = document.querySelector<HTMLElement>(`[${ANNOUNCER_ATTR}]`);\n\n if (existing) {\n return existing;\n }\n\n const element = document.createElement(\"div\");\n\n element.setAttribute(\"style\", VISUALLY_HIDDEN);\n element.setAttribute(\"aria-live\", \"assertive\");\n element.setAttribute(\"aria-atomic\", \"true\");\n element.setAttribute(ANNOUNCER_ATTR, \"\");\n\n document.body.prepend(element);\n\n return element;\n}\n\nfunction removeAnnouncer(): void {\n document.querySelector(`[${ANNOUNCER_ATTR}]`)?.remove();\n}\n\nfunction resolveText(\n route: State,\n prefix: string,\n getCustomText: ((route: State) => string) | undefined,\n h1: HTMLElement | null,\n): string {\n if (getCustomText) {\n return getCustomText(route);\n }\n\n const h1Text = h1?.textContent.trim() ?? \"\";\n const routeName = route.name.startsWith(INTERNAL_ROUTE_PREFIX)\n ? \"\"\n : route.name;\n const rawText =\n h1Text || document.title || routeName || globalThis.location.pathname;\n\n return `${prefix}${rawText}`;\n}\n\nfunction manageFocus(h1: HTMLElement | null): void {\n if (!h1) {\n return;\n }\n\n if (!h1.hasAttribute(\"tabindex\")) {\n h1.setAttribute(\"tabindex\", \"-1\");\n }\n\n h1.focus({ preventScroll: true });\n}\n","import type { Router, State } from \"@real-router/core\";\n\nconst STORAGE_KEY = \"real-router:scroll\";\n\nconst NOOP_INSTANCE: { destroy: () => void } = Object.freeze({\n destroy: () => {\n /* no-op */\n },\n});\n\nexport type ScrollRestorationMode = \"restore\" | \"top\" | \"manual\";\n\nexport interface ScrollRestorationOptions {\n mode?: ScrollRestorationMode | undefined;\n anchorScrolling?: boolean | undefined;\n scrollContainer?: (() => HTMLElement | null) | undefined;\n}\n\ninterface NavigationContext {\n direction?: \"forward\" | \"back\" | \"unknown\";\n navigationType?: \"push\" | \"replace\" | \"traverse\" | \"reload\";\n}\n\nexport function createScrollRestoration(\n router: Router,\n options?: ScrollRestorationOptions,\n): { destroy: () => void } {\n if (typeof globalThis.window === \"undefined\") {\n return NOOP_INSTANCE;\n }\n\n const mode = options?.mode ?? \"restore\";\n\n // mode \"manual\" = utility does nothing. Don't flip history.scrollRestoration,\n // don't subscribe, don't register pagehide — leave the browser's native\n // auto-restore intact for the app to override if it wants to.\n if (mode === \"manual\") {\n return NOOP_INSTANCE;\n }\n\n const anchorEnabled = options?.anchorScrolling ?? true;\n const getContainer = options?.scrollContainer;\n\n const prevScrollRestoration = history.scrollRestoration;\n\n try {\n history.scrollRestoration = \"manual\";\n } catch {\n // Ignore — some embedded contexts may reject the assignment.\n }\n\n // Resolve the container lazily on every event so containers mounted AFTER\n // the provider still get correct scroll handling. Falls back to window when\n // the getter is absent or returns null (pre-mount).\n const readPos = (): number => {\n const element = getContainer?.();\n\n return element ? element.scrollTop : globalThis.scrollY;\n };\n\n const writePos = (top: number): void => {\n const element = getContainer?.();\n\n if (element) {\n element.scrollTop = top;\n } else {\n globalThis.scrollTo(0, top);\n }\n };\n\n const scrollToHashOrTop = (): void => {\n const hash = globalThis.location.hash;\n\n if (anchorEnabled && hash.length > 1) {\n // location.hash is percent-encoded; ids in the DOM are the raw string.\n // Decode for the match. Fall back to the raw slice if the hash contains\n // a malformed escape sequence (decodeURIComponent throws on those).\n let id: string;\n\n try {\n id = decodeURIComponent(hash.slice(1));\n } catch {\n id = hash.slice(1);\n }\n\n // eslint-disable-next-line unicorn/prefer-query-selector -- ids may contain CSS-unsafe chars\n const element = document.getElementById(id);\n\n if (element) {\n element.scrollIntoView();\n\n return;\n }\n }\n\n writePos(0);\n };\n\n let destroyed = false;\n\n const unsubscribe = router.subscribe(({ route, previousRoute }) => {\n const nav = (route.context as { navigation?: NavigationContext })\n .navigation;\n\n // Browsers dispatch reload as the initial navigation after refresh, so\n // previousRoute is undefined and capture is naturally skipped. The\n // pre-refresh position was already persisted via pagehide.\n if (previousRoute) {\n putPos(keyOf(previousRoute), readPos());\n }\n\n // Single rAF so DOM is committed before we read anchors / write scroll.\n // Guard against destroy() racing with the callback.\n requestAnimationFrame(() => {\n if (destroyed) {\n return;\n }\n\n if (mode === \"top\" || !nav) {\n scrollToHashOrTop();\n\n return;\n }\n\n if (nav.navigationType === \"replace\") {\n return;\n }\n\n if (\n nav.direction === \"back\" ||\n nav.navigationType === \"traverse\" ||\n nav.navigationType === \"reload\"\n ) {\n writePos(loadStore()[keyOf(route)] ?? 0);\n\n return;\n }\n\n scrollToHashOrTop();\n });\n });\n\n const onPageHide = (): void => {\n const current = router.getState();\n\n if (current) {\n putPos(keyOf(current), readPos());\n }\n };\n\n globalThis.addEventListener(\"pagehide\", onPageHide);\n\n return {\n destroy: () => {\n if (destroyed) {\n return;\n }\n\n destroyed = true;\n unsubscribe();\n globalThis.removeEventListener(\"pagehide\", onPageHide);\n\n try {\n history.scrollRestoration = prevScrollRestoration;\n } catch {\n // Ignore.\n }\n },\n };\n}\n\nfunction keyOf(state: State): string {\n return `${state.name}:${canonicalJson(state.params)}`;\n}\n\nfunction loadStore(): Record<string, number> {\n try {\n const raw = sessionStorage.getItem(STORAGE_KEY);\n\n return raw ? (JSON.parse(raw) as Record<string, number>) : {};\n } catch {\n return {};\n }\n}\n\nfunction putPos(key: string, pos: number): void {\n try {\n const store = loadStore();\n\n store[key] = pos;\n sessionStorage.setItem(STORAGE_KEY, JSON.stringify(store));\n } catch {\n // Ignore quota / security errors.\n }\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(value, canonicalReplacer);\n}\n\nfunction canonicalReplacer(_key: string, val: unknown): unknown {\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n const sorted: Record<string, unknown> = {};\n // eslint-disable-next-line unicorn/no-array-sort -- ng-packagr uses pre-ES2023 lib; toSorted unavailable\n const keys = Object.keys(val as Record<string, unknown>).sort(\n (left: string, right: string) => left.localeCompare(right),\n );\n\n for (const key of keys) {\n sorted[key] = (val as Record<string, unknown>)[key];\n }\n\n return sorted;\n }\n\n return val;\n}\n","import type { Router, Params } from \"@real-router/core\";\n\nexport function shouldNavigate(evt: MouseEvent): boolean {\n return (\n evt.button === 0 &&\n !evt.metaKey &&\n !evt.altKey &&\n !evt.ctrlKey &&\n !evt.shiftKey\n );\n}\n\ntype BuildUrlFn = (name: string, params: Params) => string | undefined;\n\nexport function buildHref(\n router: Router,\n routeName: string,\n routeParams: Params,\n): string | undefined {\n try {\n const buildUrl = router.buildUrl as BuildUrlFn | undefined;\n\n if (buildUrl) {\n const url = buildUrl(routeName, routeParams);\n\n if (url !== undefined) {\n return url;\n }\n }\n\n return router.buildPath(routeName, routeParams);\n } catch {\n console.error(\n `[real-router] Route \"${routeName}\" is not defined. The element will render without an href attribute.`,\n );\n\n return undefined;\n }\n}\n\nfunction parseTokens(value: string | undefined): string[] {\n return value ? (value.match(/\\S+/g) ?? []) : [];\n}\n\nexport function buildActiveClassName(\n isActive: boolean,\n activeClassName: string | undefined,\n baseClassName: string | undefined,\n): string | undefined {\n if (isActive && activeClassName) {\n const activeTokens = parseTokens(activeClassName);\n\n if (activeTokens.length === 0) {\n return baseClassName ?? undefined;\n }\n if (!baseClassName) {\n return activeTokens.join(\" \");\n }\n\n const baseTokens = parseTokens(baseClassName);\n const seen = new Set(baseTokens);\n\n for (const token of activeTokens) {\n if (!seen.has(token)) {\n seen.add(token);\n baseTokens.push(token);\n }\n }\n\n return baseTokens.join(\" \");\n }\n\n return baseClassName ?? undefined;\n}\n\nexport function shallowEqual(\n prev: object | undefined,\n next: object | undefined,\n): boolean {\n if (Object.is(prev, next)) {\n return true;\n }\n if (!prev || !next) {\n return false;\n }\n\n const prevKeys = Object.keys(prev);\n\n if (prevKeys.length !== Object.keys(next).length) {\n return false;\n }\n\n const prevRecord = prev as Record<string, unknown>;\n const nextRecord = next as Record<string, unknown>;\n\n for (const key of prevKeys) {\n if (!Object.is(prevRecord[key], nextRecord[key])) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function applyLinkA11y(element: HTMLElement | null | undefined): void {\n if (!element) {\n return;\n }\n if (\n element instanceof HTMLAnchorElement ||\n element instanceof HTMLButtonElement\n ) {\n return;\n }\n if (!element.hasAttribute(\"role\")) {\n element.setAttribute(\"role\", \"link\");\n }\n if (!element.hasAttribute(\"tabindex\")) {\n element.setAttribute(\"tabindex\", \"0\");\n }\n}\n","import { createActiveRouteSource } from \"@real-router/sources\";\nimport { defineComponent, h, computed, shallowRef, watch } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { EMPTY_PARAMS, EMPTY_OPTIONS } from \"../constants\";\nimport { shouldNavigate, buildHref, buildActiveClassName } from \"../dom-utils\";\n\nimport type { Params, NavigationOptions } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\ntype OnClickHandler = (evt: MouseEvent) => void;\n\n/**\n * Vue's compiled template binds multiple `@click` handlers as an array.\n * Single render-function `onClick` is a function. Both must be invoked.\n */\nfunction invokeAttributesOnClick(value: unknown, evt: MouseEvent): void {\n if (typeof value === \"function\") {\n (value as OnClickHandler)(evt);\n\n return;\n }\n if (Array.isArray(value)) {\n const handlers = value as OnClickHandler[];\n\n for (const fn of handlers) {\n if (typeof fn === \"function\") {\n fn(evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n }\n }\n}\n\nexport const Link = defineComponent({\n name: \"Link\",\n // Disable Vue's automatic attribute fallthrough. Without this, attrs.onClick\n // (function OR array) is auto-attached as a native click listener AND our\n // explicit onClick fires too — user handlers are double-invoked. We invoke\n // attrs.onClick manually inside handleClick to preserve preventDefault.\n inheritAttrs: false,\n props: {\n routeName: {\n type: String,\n required: true,\n },\n routeParams: {\n type: Object as PropType<Params>,\n default: () => EMPTY_PARAMS,\n },\n routeOptions: {\n type: Object as PropType<NavigationOptions>,\n default: () => EMPTY_OPTIONS,\n },\n class: {\n type: String,\n default: undefined,\n },\n activeClassName: {\n type: String,\n default: \"active\",\n },\n activeStrict: {\n type: Boolean,\n default: false,\n },\n ignoreQueryParams: {\n type: Boolean,\n default: true,\n },\n target: {\n type: String,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const router = useRouter();\n\n const isActive = shallowRef(false);\n\n // watch with an explicit dep getter recreates the source ONLY when\n // routeName/routeParams/strict/ignoreQueryParams change — not on every\n // reactive read inside the source factory (the watchEffect alternative\n // would also re-subscribe whenever isActive itself changed).\n watch(\n () =>\n [\n props.routeName,\n props.routeParams,\n props.activeStrict,\n props.ignoreQueryParams,\n ] as const,\n (\n [routeName, routeParams, activeStrict, ignoreQueryParams],\n _prev,\n onCleanup,\n ) => {\n const source = createActiveRouteSource(router, routeName, routeParams, {\n strict: activeStrict,\n ignoreQueryParams,\n });\n\n isActive.value = source.getSnapshot();\n\n const unsub = source.subscribe(() => {\n isActive.value = source.getSnapshot();\n });\n\n onCleanup(unsub);\n },\n { immediate: true, flush: \"sync\" },\n );\n\n const href = computed(() =>\n buildHref(router, props.routeName, props.routeParams),\n );\n\n const finalClassName = computed(() =>\n buildActiveClassName(isActive.value, props.activeClassName, props.class),\n );\n\n const handleClick = (evt: MouseEvent) => {\n // Vue allows attrs.onClick to be a function or an array of functions\n // (compiled templates with multiple @click bindings produce arrays).\n // Both must be invoked; treating arrays as \"no handler\" silently drops\n // user code.\n if (attrs.onClick !== undefined && attrs.onClick !== null) {\n invokeAttributesOnClick(attrs.onClick, evt);\n\n if (evt.defaultPrevented) {\n return;\n }\n }\n\n if (!shouldNavigate(evt) || props.target === \"_blank\") {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(props.routeName, props.routeParams, props.routeOptions)\n .catch(() => {});\n };\n\n return () => {\n // Build forwarded attrs without `onClick`. Vue's runtime auto-attaches\n // attrs.onClick (function OR array) as a native DOM listener, which would\n // double-invoke user handlers when combined with our explicit `onClick`.\n // We invoke the original attrs.onClick manually inside handleClick so the\n // preventDefault contract is preserved.\n const restAttributes: Record<string, unknown> = {};\n\n for (const key of Object.keys(attrs)) {\n if (key !== \"onClick\") {\n restAttributes[key] = (attrs as Record<string, unknown>)[key];\n }\n }\n\n return h(\n \"a\",\n {\n ...restAttributes,\n href: href.value,\n class: finalClassName.value,\n target: props.target,\n onClick: handleClick,\n },\n slots.default?.(),\n );\n };\n },\n});\n","import { createDismissableError } from \"@real-router/sources\";\nimport { defineComponent, h, watch, Fragment } from \"vue\";\n\nimport { useRouter } from \"../composables/useRouter\";\nimport { useRefFromSource } from \"../useRefFromSource\";\n\nimport type { RouterError, State } from \"@real-router/core\";\nimport type { VNode, PropType } from \"vue\";\n\nexport const RouterErrorBoundary = defineComponent({\n name: \"RouterErrorBoundary\",\n props: {\n fallback: {\n type: Function as PropType<\n (error: RouterError, resetError: () => void) => VNode\n >,\n required: true,\n },\n onError: {\n type: Function as PropType<\n (\n error: RouterError,\n toRoute: State | null,\n fromRoute: State | null,\n ) => void\n >,\n default: undefined,\n },\n },\n setup(props, { slots }) {\n const router = useRouter();\n const snapshot = useRefFromSource(createDismissableError(router));\n\n watch(\n () => snapshot.value.version,\n () => {\n if (snapshot.value.error) {\n props.onError?.(\n snapshot.value.error,\n snapshot.value.toRoute,\n snapshot.value.fromRoute,\n );\n }\n },\n { immediate: true },\n );\n\n return () => {\n const children = slots.default?.() ?? [];\n const errorVNode = snapshot.value.error\n ? props.fallback(snapshot.value.error, snapshot.value.resetError)\n : null;\n\n return h(Fragment, null, [...children, errorVNode]);\n };\n },\n});\n\nexport type RouterErrorBoundaryProps = InstanceType<\n typeof RouterErrorBoundary\n>[\"$props\"];\n","import { shouldNavigate, applyLinkA11y } from \"../dom-utils\";\n\nimport type { Router, NavigationOptions, Params } from \"@real-router/core\";\nimport type { Directive } from \"vue\";\n\nexport interface LinkDirectiveValue {\n name: string;\n params?: Params;\n options?: NavigationOptions;\n}\n\n/**\n * Router stack for nested RouterProviders. The active router is the top of\n * the stack. RouterProvider pushes its router on mount and pops it on unmount,\n * which preserves the parent context when an inner provider tears down.\n *\n * Without the stack, an unmounted child provider would leave the directive\n * pointing at a disposed router, and v-link in the still-mounted parent would\n * navigate via the wrong (or torn-down) instance.\n */\nconst routerStack: Router[] = [];\n\n/**\n * Pushes a router onto the active stack. Returns a release function that\n * removes that exact router from the stack regardless of position — safe\n * across out-of-order provider unmount sequences.\n *\n * @internal Used by RouterProvider during setup/teardown.\n */\nexport function pushDirectiveRouter(router: Router): () => void {\n routerStack.push(router);\n\n return () => {\n const idx = routerStack.lastIndexOf(router);\n\n if (idx !== -1) {\n routerStack.splice(idx, 1);\n }\n };\n}\n\n/**\n * Backwards-compatible alias. Replaces the active router unconditionally and\n * does NOT participate in the stack — use {@link pushDirectiveRouter} from\n * provider code instead. Kept for tests and direct callers.\n */\nexport function setDirectiveRouter(router: Router | null): void {\n if (router === null) {\n routerStack.length = 0;\n\n return;\n }\n if (routerStack.length === 0) {\n routerStack.push(router);\n\n return;\n }\n\n routerStack[routerStack.length - 1] = router;\n}\n\nexport function getDirectiveRouter(): Router {\n const top = routerStack.at(-1);\n\n if (!top) {\n throw new Error(\n \"v-link directive requires a RouterProvider ancestor. Make sure RouterProvider is mounted.\",\n );\n }\n\n return top;\n}\n\ninterface Handlers {\n click: (evt: MouseEvent) => void;\n keydown: (evt: KeyboardEvent) => void;\n}\n\n// Single WeakMap halves per-element bookkeeping vs two parallel maps.\nconst handlers = new WeakMap<HTMLElement, Handlers>();\n\n/**\n * Validates a directive binding value before attaching handlers.\n * Returns false (and warns once per call) when the value is missing or\n * has no `name` — silently doing nothing is preferable to a runtime crash\n * inside a click handler.\n */\nfunction isValidBinding(value: unknown): value is LinkDirectiveValue {\n if (value === null || value === undefined) {\n console.error(\n \"[real-router] v-link directive received null/undefined value. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n if (typeof (value as { name?: unknown }).name !== \"string\") {\n console.error(\n \"[real-router] v-link directive value is missing a string `name` field. The element will not be wired for navigation.\",\n );\n\n return false;\n }\n\n return true;\n}\n\nfunction createClickHandler(\n router: Router,\n value: LinkDirectiveValue,\n): (evt: MouseEvent) => void {\n return (evt: MouseEvent) => {\n if (!shouldNavigate(evt)) {\n return;\n }\n\n evt.preventDefault();\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n };\n}\n\nfunction createKeydownHandler(\n router: Router,\n value: LinkDirectiveValue,\n element: HTMLElement,\n): (evt: KeyboardEvent) => void {\n return (evt: KeyboardEvent) => {\n if (evt.key === \"Enter\" && !(element instanceof HTMLButtonElement)) {\n router\n .navigate(value.name, value.params ?? {}, value.options ?? {})\n .catch(() => {});\n }\n };\n}\n\nfunction attachHandlers(\n element: HTMLElement,\n router: Router,\n value: LinkDirectiveValue,\n): void {\n const click = createClickHandler(router, value);\n const keydown = createKeydownHandler(router, value, element);\n\n element.addEventListener(\"click\", click);\n element.addEventListener(\"keydown\", keydown);\n\n handlers.set(element, { click, keydown });\n}\n\nfunction detachHandlers(element: HTMLElement): void {\n const entry = handlers.get(element);\n\n if (entry) {\n element.removeEventListener(\"click\", entry.click);\n element.removeEventListener(\"keydown\", entry.keydown);\n handlers.delete(element);\n }\n}\n\nexport const vLink: Directive<HTMLElement, LinkDirectiveValue> = {\n mounted(element, binding) {\n const router = getDirectiveRouter();\n\n applyLinkA11y(element);\n\n element.style.cursor = \"pointer\";\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n updated(element, binding) {\n const router = getDirectiveRouter();\n\n detachHandlers(element);\n\n if (!isValidBinding(binding.value)) {\n return;\n }\n\n attachHandlers(element, router, binding.value);\n },\n\n beforeUnmount(element) {\n detachHandlers(element);\n },\n};\n","import { inject } from \"vue\";\n\nimport { NavigatorKey } from \"../context\";\n\nimport type { Navigator } from \"@real-router/core\";\n\nexport const useNavigator = (): Navigator => {\n const navigator = inject(NavigatorKey);\n\n if (!navigator) {\n throw new Error(\"useNavigator must be used within a RouterProvider\");\n }\n\n return navigator;\n};\n","import { 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\nexport const useRouteUtils = (): RouteUtils => {\n const router = useRouter();\n\n return getRouteUtils(getPluginApi(router).getTree());\n};\n","import { inject } from \"vue\";\n\nimport { RouteKey } from \"../context\";\n\nimport type { RouteContext } from \"../types\";\nimport type { Params } from \"@real-router/core\";\n\nexport const useRoute = <P extends Params = Params>(): RouteContext<P> => {\n const routeContext = inject(RouteKey);\n\n if (!routeContext) {\n throw new Error(\"useRoute must be used within a RouterProvider\");\n }\n\n return routeContext as RouteContext<P>;\n};\n","import { getTransitionSource } from \"@real-router/sources\";\n\nimport { useRefFromSource } from \"../useRefFromSource\";\nimport { useRouter } from \"./useRouter\";\n\nimport type { RouterTransitionSnapshot } from \"@real-router/sources\";\nimport type { ShallowRef } from \"vue\";\n\nexport function useRouterTransition(): ShallowRef<RouterTransitionSnapshot> {\n const router = useRouter();\n const source = getTransitionSource(router);\n\n return useRefFromSource(source);\n}\n","// packages/vue/src/setupRouteProvision.ts\n\nimport { getNavigator } from \"@real-router/core\";\nimport { createRouteSource } from \"@real-router/sources\";\nimport { shallowRef } from \"vue\";\n\nimport type { Router, Navigator, State } from \"@real-router/core\";\nimport type { ShallowRef } from \"vue\";\n\n/**\n * Shared setup for `RouterProvider` (component-scoped) and\n * `createRouterPlugin` (app-scoped). Builds the reactive route refs +\n * subscription bookkeeping in one place; callers wire the result into their\n * provide/inject mechanism and own teardown lifecycle.\n *\n * @internal\n */\nexport interface RouteProvision {\n navigator: Navigator;\n route: ShallowRef<State | undefined>;\n previousRoute: ShallowRef<State | undefined>;\n /** Call when the owning scope tears down to release the router subscription. */\n unsubscribe: () => void;\n}\n\nexport function setupRouteProvision(router: Router): RouteProvision {\n const navigator = getNavigator(router);\n const source = createRouteSource(router);\n const initial = source.getSnapshot();\n\n const route = shallowRef<State | undefined>(initial.route);\n const previousRoute = shallowRef<State | undefined>(initial.previousRoute);\n\n const unsubscribe = source.subscribe(() => {\n const snapshot = source.getSnapshot();\n\n route.value = snapshot.route;\n previousRoute.value = snapshot.previousRoute;\n });\n\n return { navigator, route, previousRoute, unsubscribe };\n}\n","import { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { Router } from \"@real-router/core\";\nimport type { App, Plugin } from \"vue\";\n\nexport function createRouterPlugin(router: Router): Plugin<[]> {\n return {\n install(app): void {\n const releaseDirective = pushDirectiveRouter(router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(router);\n\n // Vue 3.5+ exposes app.onUnmount for plugin cleanup.\n // On older versions (3.3–3.4), the subscription is cleaned up\n // when the router is garbage-collected (same as vue-router).\n if (\"onUnmount\" in app) {\n (app as App & { onUnmount: (fn: () => void) => void }).onUnmount(() => {\n releaseDirective();\n unsubscribe();\n });\n }\n\n app.provide(RouterKey, router);\n app.provide(NavigatorKey, navigator);\n app.provide(RouteKey, { navigator, route, previousRoute });\n },\n };\n}\n","import { defineComponent, onScopeDispose, provide, watch } from \"vue\";\n\nimport { NavigatorKey, RouteKey, RouterKey } from \"./context\";\nimport { pushDirectiveRouter } from \"./directives/vLink\";\nimport { createRouteAnnouncer, createScrollRestoration } from \"./dom-utils\";\nimport { setupRouteProvision } from \"./setupRouteProvision\";\n\nimport type { ScrollRestorationOptions } from \"./dom-utils\";\nimport type { Router } from \"@real-router/core\";\nimport type { PropType } from \"vue\";\n\nexport const RouterProvider = defineComponent({\n name: \"RouterProvider\",\n props: {\n router: {\n type: Object as PropType<Router>,\n required: true,\n },\n announceNavigation: {\n type: Boolean,\n default: false,\n },\n scrollRestoration: {\n type: Object as PropType<ScrollRestorationOptions>,\n },\n },\n setup(props, { slots }) {\n // Reactive announceNavigation: setting prop true/false at runtime now\n // creates/destroys the announcer accordingly. Prior implementation read\n // the prop only inside onMounted, so toggling it post-mount silently no-op'd.\n watch(\n () => [props.router, props.announceNavigation] as const,\n ([router, enabled], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const announcer = createRouteAnnouncer(router);\n\n onCleanup(() => {\n announcer.destroy();\n });\n },\n { immediate: true },\n );\n\n // Watch by primitives so inline `{ mode: \"restore\" }` doesn't thrash.\n // scrollContainer is a getter invoked lazily on every event inside the\n // utility — swapping its reference doesn't change the resolved element,\n // so we intentionally omit it from watched sources.\n watch(\n () =>\n [\n props.router,\n props.scrollRestoration !== undefined,\n props.scrollRestoration?.mode,\n props.scrollRestoration?.anchorScrolling,\n ] as const,\n ([router, enabled, mode, anchorScrolling], _prev, onCleanup) => {\n if (!enabled) {\n return;\n }\n\n const sr = createScrollRestoration(router, {\n mode,\n anchorScrolling,\n scrollContainer: props.scrollRestoration?.scrollContainer,\n });\n\n onCleanup(() => {\n sr.destroy();\n });\n },\n { immediate: true },\n );\n\n // Push this provider's router on the v-link directive stack so nested\n // RouterProviders behave like nested DI scopes (LIFO). Release on unmount\n // restores the outer router for any v-link still mounted in the parent.\n const releaseDirective = pushDirectiveRouter(props.router);\n\n const { navigator, route, previousRoute, unsubscribe } =\n setupRouteProvision(props.router);\n\n onScopeDispose(() => {\n releaseDirective();\n unsubscribe();\n });\n\n provide(RouterKey, props.router);\n provide(NavigatorKey, navigator);\n provide(RouteKey, { navigator, route, previousRoute });\n\n return () => slots.default?.();\n },\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/vue",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "type": "commonjs",
5
5
  "description": "Vue 3 integration for Real-Router",
6
6
  "main": "./dist/cjs/index.js",
@@ -51,8 +51,8 @@
51
51
  "sideEffects": false,
52
52
  "dependencies": {
53
53
  "@real-router/core": "^0.50.0",
54
- "@real-router/sources": "^0.7.2",
55
- "@real-router/route-utils": "^0.2.1"
54
+ "@real-router/route-utils": "^0.2.1",
55
+ "@real-router/sources": "^0.7.2"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@testing-library/jest-dom": "6.9.1",
@@ -2,9 +2,10 @@ import { defineComponent, onScopeDispose, provide, watch } from "vue";
2
2
 
3
3
  import { NavigatorKey, RouteKey, RouterKey } from "./context";
4
4
  import { pushDirectiveRouter } from "./directives/vLink";
5
- import { createRouteAnnouncer } from "./dom-utils/index.js";
5
+ import { createRouteAnnouncer, createScrollRestoration } from "./dom-utils";
6
6
  import { setupRouteProvision } from "./setupRouteProvision";
7
7
 
8
+ import type { ScrollRestorationOptions } from "./dom-utils";
8
9
  import type { Router } from "@real-router/core";
9
10
  import type { PropType } from "vue";
10
11
 
@@ -19,6 +20,9 @@ export const RouterProvider = defineComponent({
19
20
  type: Boolean,
20
21
  default: false,
21
22
  },
23
+ scrollRestoration: {
24
+ type: Object as PropType<ScrollRestorationOptions>,
25
+ },
22
26
  },
23
27
  setup(props, { slots }) {
24
28
  // Reactive announceNavigation: setting prop true/false at runtime now
@@ -40,6 +44,36 @@ export const RouterProvider = defineComponent({
40
44
  { immediate: true },
41
45
  );
42
46
 
47
+ // Watch by primitives so inline `{ mode: "restore" }` doesn't thrash.
48
+ // scrollContainer is a getter invoked lazily on every event inside the
49
+ // utility — swapping its reference doesn't change the resolved element,
50
+ // so we intentionally omit it from watched sources.
51
+ watch(
52
+ () =>
53
+ [
54
+ props.router,
55
+ props.scrollRestoration !== undefined,
56
+ props.scrollRestoration?.mode,
57
+ props.scrollRestoration?.anchorScrolling,
58
+ ] as const,
59
+ ([router, enabled, mode, anchorScrolling], _prev, onCleanup) => {
60
+ if (!enabled) {
61
+ return;
62
+ }
63
+
64
+ const sr = createScrollRestoration(router, {
65
+ mode,
66
+ anchorScrolling,
67
+ scrollContainer: props.scrollRestoration?.scrollContainer,
68
+ });
69
+
70
+ onCleanup(() => {
71
+ sr.destroy();
72
+ });
73
+ },
74
+ { immediate: true },
75
+ );
76
+
43
77
  // Push this provider's router on the v-link directive stack so nested
44
78
  // RouterProviders behave like nested DI scopes (LIFO). Release on unmount
45
79
  // restores the outer router for any v-link still mounted in the parent.
@@ -3,11 +3,7 @@ import { defineComponent, h, computed, shallowRef, watch } from "vue";
3
3
 
4
4
  import { useRouter } from "../composables/useRouter";
5
5
  import { EMPTY_PARAMS, EMPTY_OPTIONS } from "../constants";
6
- import {
7
- shouldNavigate,
8
- buildHref,
9
- buildActiveClassName,
10
- } from "../dom-utils/index.js";
6
+ import { shouldNavigate, buildHref, buildActiveClassName } from "../dom-utils";
11
7
 
12
8
  import type { Params, NavigationOptions } from "@real-router/core";
13
9
  import type { PropType } from "vue";
@@ -1,4 +1,4 @@
1
- import { shouldNavigate, applyLinkA11y } from "../dom-utils/index.js";
1
+ import { shouldNavigate, applyLinkA11y } from "../dom-utils";
2
2
 
3
3
  import type { Router, NavigationOptions, Params } from "@real-router/core";
4
4
  import type { Directive } from "vue";