@real-router/vue 0.7.0 → 0.8.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
@@ -491,9 +491,9 @@ Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
491
491
 
492
492
  ## Examples
493
493
 
494
- 14 runnable examples — each is a standalone Vite app. Run: `cd examples/vue/basic && pnpm dev`
494
+ 14 runnable examples — each is a standalone Vite app. Run: `cd examples/web/vue/basic && pnpm dev`
495
495
 
496
- [basic](../../examples/vue/basic) · [nested-routes](../../examples/vue/nested-routes) · [auth-guards](../../examples/vue/auth-guards) · [data-loading](../../examples/vue/data-loading) · [lazy-loading](../../examples/vue/lazy-loading) · [async-guards](../../examples/vue/async-guards) · [hash-routing](../../examples/vue/hash-routing) · [persistent-params](../../examples/vue/persistent-params) · [error-handling](../../examples/vue/error-handling) · [dynamic-routes](../../examples/vue/dynamic-routes) · [plugin-installation](../../examples/vue/plugin-installation) · [v-link-directive](../../examples/vue/v-link-directive) · [keep-alive](../../examples/vue/keep-alive) · [combined](../../examples/vue/combined)
496
+ [basic](../../examples/web/vue/basic) · [nested-routes](../../examples/web/vue/nested-routes) · [auth-guards](../../examples/web/vue/auth-guards) · [data-loading](../../examples/web/vue/data-loading) · [lazy-loading](../../examples/web/vue/lazy-loading) · [async-guards](../../examples/web/vue/async-guards) · [hash-routing](../../examples/web/vue/hash-routing) · [persistent-params](../../examples/web/vue/persistent-params) · [error-handling](../../examples/web/vue/error-handling) · [dynamic-routes](../../examples/web/vue/dynamic-routes) · [plugin-installation](../../examples/web/vue/plugin-installation) · [v-link-directive](../../examples/web/vue/v-link-directive) · [keep-alive](../../examples/web/vue/keep-alive) · [combined](../../examples/web/vue/combined)
497
497
 
498
498
  ## Related Packages
499
499
 
@@ -15,6 +15,10 @@ interface MatchProps {
15
15
  readonly fallback?: VNode | (() => VNode);
16
16
  readonly keepAlive?: boolean;
17
17
  }
18
+ interface SelfProps {
19
+ /** Fallback content while children are suspended. */
20
+ readonly fallback?: VNode | (() => VNode);
21
+ }
18
22
  type NotFoundProps = Record<string, never>;
19
23
  //#endregion
20
24
  //#region src/components/RouteView/RouteView.d.ts
@@ -105,6 +109,7 @@ declare const RouteView: {
105
109
  keepAlive: boolean;
106
110
  exact: boolean;
107
111
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
112
+ Self: _$vue.FunctionalComponent<SelfProps, {}, any, {}>;
108
113
  NotFound: _$vue.DefineComponent<{}, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
109
114
  };
110
115
  //#endregion
@@ -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","../../../../shared/dom-utils/scroll-restore.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 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;
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.Self`,props:{fallback:{type:[Object,Function],default:void 0}},render:a}),c=(0,e.defineComponent)({name:`RouteView.NotFound`,render:a});function l(e,t,r){return r?e===t:(0,n.startsWithSegment)(e,t)}function u(t){if(Array.isArray(t)){let n=[];for(let r of t)Array.isArray(r)?n.push(...u(r)):(0,e.isVNode)(r)&&n.push(r);return n}return(0,e.isVNode)(t)?[t]:[]}function d(t,n){let r=u(t);for(let t of r)t.type===o||t.type===s||t.type===c?n.push(t):t.type===e.Fragment&&d(t.children,n)}function f(e,t){return e.type===c?(t.notFoundChildren=e.children,!0):e.type===s?(t.selfVNode===null&&(t.selfVNode=e,t.selfFallback=e.props?.fallback),!0):!1}function p(e,t,n){let r=e.props,i=r?.segment??``,a=r?.exact??!1;return{isActive:l(t,n?`${n}.${i}`:i,a),fallback:r?.fallback}}function m(e,n,r,i,a){if(i.selfVNode!==null&&n===r)return e.push(i.selfVNode),i.selfFallback;if(n===t.UNKNOWN_ROUTE&&i.notFoundChildren!==null){let t=a.filter(e=>e.type===c).at(-1);t&&e.push(t)}}function h(e,t,n){let r={selfVNode:null,selfFallback:void 0,notFoundChildren:null},i=!1,a,o=[];for(let s of e){if(f(s,r)||i)continue;let e=p(s,t,n);e.isActive&&(i=!0,a=e.fallback,o.push(s))}return i||(a=m(o,t,n,r,e)),{rendered:o,activeMatchFound:i,fallback:a}}function g(t){let n=(0,e.shallowRef)(t.getSnapshot());return(0,e.onScopeDispose)(t.subscribe(()=>{n.value=t.getSnapshot()})),n}const _=Symbol(`RouterKey`),v=Symbol(`NavigatorKey`),y=Symbol(`RouteKey`),b=()=>{let t=(0,e.inject)(_);if(!t)throw Error(`useRouter must be used within a RouterProvider`);return t};function x(n){let i=b(),a=g((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 S(e){return e.children?.default?.()??null}function C(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 w(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 te(t,n,r){let i=t.props?.segment??`__not-found__`,a=C(n,i),o=S(t)??[];return w((0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:i},{default:()=>o})}),r)}function T(e){return e===!0||e===``||e===`keep-alive`}function E(t,n,r){let i=t.props;if(T(i?.keepAlive)&&t.type===o){let r=i?.segment??`__not-found__`,a=C(n,r),o=S(t)??[];return(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(a,{key:r},{default:()=>o})})])}let a=S(t);return a?(0,e.h)(e.Fragment,[(0,e.h)(e.KeepAlive,null,{default:()=>(0,e.h)(ee)}),w((0,e.h)(e.Fragment,a),r)]):null}const ne=(0,e.defineComponent)({name:`RouteView`,props:{nodeName:{type:String,required:!0},keepAlive:{type:Boolean,default:!1}},setup(t,{slots:n}){let r=x(t.nodeName),i=new Map,a=null,l=!1;function u(e,t){return t===a?l:(a=t,l=e.some(e=>e.type===o&&T(e.props?.keepAlive)),l)}return()=>{let a=r.route.value;if(!a)return null;let l=n.default?.(),f=[];d(l,f);let{rendered:p,fallback:m}=h(f,a.name,t.nodeName);if(p.length===0)return null;let g=p[0];if(t.keepAlive)return te(g,i,m);if(g.type!==o&&g.type!==s&&g.type!==c)return null;if(u(f,l))return E(g,i,m);let _=S(g);return _?w((0,e.h)(e.Fragment,_),m):null}}}),re=Object.assign(ne,{Match:o,Self:s,NotFound:c}),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),oe(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=ae(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),ie()}}}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 ie(){document.querySelector(`[${k}]`)?.remove()}function ae(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 oe(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const M=`real-router:scroll`,N=Object.freeze({destroy:()=>{}});function se(e,t){if(globalThis.window===void 0)return N;let n=t?.mode??`restore`;if(n===`manual`)return N;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&&I(P(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(F()[P(e)]??0);return}c()}}})}),d=()=>{let t=e.getState();t&&I(P(t),o())};return globalThis.addEventListener(`pagehide`,d),{destroy:()=>{if(!l){l=!0,u(),globalThis.removeEventListener(`pagehide`,d);try{history.scrollRestoration=a}catch{}}}}}function P(e){return`${e.name}:${L(e.params)}`}function F(){try{let e=sessionStorage.getItem(M);return e?JSON.parse(e):{}}catch{return{}}}function I(e,t){try{let n=F();n[e]=t,sessionStorage.setItem(M,JSON.stringify(n))}catch{}}function L(e){return JSON.stringify(e,R)}function R(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 z(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}function B(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 V(e){return e?e.match(/\S+/g)??[]:[]}function H(e,t,n){if(e&&t){let e=V(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=V(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 U(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function W(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 G=(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=b(),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)(()=>B(a,t.routeName,t.routeParams)),c=(0,e.computed)(()=>H(o.value,t.activeClassName,t.class)),l=e=>{i.onClick!==void 0&&i.onClick!==null&&(W(i.onClick,e),e.defaultPrevented)||!z(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?.())}}}),ce=(0,e.defineComponent)({name:`RouterErrorBoundary`,props:{fallback:{type:Function,required:!0},onError:{type:Function,default:void 0}},setup(t,{slots:n}){let i=g((0,r.createDismissableError)(b()));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 le(e,t){return n=>{z(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function ue(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=le(t,n),i=ue(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 de={mounted(e,t){let n=J();U(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)}},fe=()=>{let t=(0,e.inject)(v);if(!t)throw Error(`useNavigator must be used within a RouterProvider`);return t},pe=()=>(0,n.getRouteUtils)((0,i.getPluginApi)(b()).getTree()),me=()=>{let t=(0,e.inject)(y);if(!t)throw Error(`useRoute must be used within a RouterProvider`);return t};function he(){return g((0,r.getTransitionSource)(b()))}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 ge(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(_,e),t.provide(v,r),t.provide(y,{navigator:r,route:i,previousRoute:a})}}}const _e=(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=A(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=se(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)(_,t.router),(0,e.provide)(v,i),(0,e.provide)(y,{navigator:i,route:a,previousRoute:o}),()=>n.default?.()}});exports.Link=G,exports.NavigatorKey=v,exports.RouteKey=y,exports.RouteView=re,exports.RouterErrorBoundary=ce,exports.RouterKey=_,exports.RouterProvider=_e,exports.createRouterPlugin=ge,exports.useNavigator=fe,exports.useRoute=me,exports.useRouteNode=x,exports.useRouteUtils=pe,exports.useRouter=b,exports.useRouterTransition=he,exports.vLink=de;
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/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":"kOAIA,SAAS,GAAa,CACpB,OAAO,KAGT,MAAa,GAAA,EAAA,EAAA,iBAAwB,CACnC,KAAM,kBACN,MAAO,CACL,QAAS,CACP,KAAM,OACN,SAAU,GACX,CACD,MAAO,CACL,KAAM,QACN,QAAS,GACV,CACD,SAAU,CACR,KAAM,CAAC,OAAQ,SAAS,CACxB,QAAS,IAAA,GACV,CACD,UAAW,CACT,KAAM,QACN,QAAS,GACV,CACF,CACD,OAAQ,EACT,CAAC,CAEW,GAAA,EAAA,EAAA,iBAA2B,CACtC,KAAM,qBACN,OAAQ,EACT,CAAC,CCxBF,SAAS,EACP,EACA,EACA,EACS,CAKT,OAJI,EACK,IAAc,GAGvB,EAAA,EAAA,mBAAyB,EAAW,EAAgB,CAGtD,SAAS,EAAkB,EAA4B,CACrD,GAAI,MAAM,QAAQ,EAAS,CAAE,CAC3B,IAAM,EAAkB,EAAE,CAE1B,IAAK,IAAM,KAAS,EACd,MAAM,QAAQ,EAAM,CACtB,EAAO,KAAK,GAAG,EAAkB,EAAM,CAAC,eACvB,EAAM,EACvB,EAAO,KAAK,EAAM,CAItB,OAAO,EAOT,OAJA,EAAA,EAAA,SAAY,EAAS,CACZ,CAAC,EAAS,CAGZ,EAAE,CAGX,SAAgB,EAAgB,EAAmB,EAAuB,CACxE,IAAM,EAAS,EAAkB,EAAS,CAE1C,IAAK,IAAM,KAAS,EACd,EAAM,OAAS,GAAS,EAAM,OAAS,EACzC,EAAO,KAAK,EAAM,CACT,EAAM,OAASA,EAAAA,UACxB,EAAgB,EAAM,SAAU,EAAO,CAK7C,SAAgB,EACd,EACA,EACA,EAKA,CACA,IAAI,EAA4B,KAC5B,EAAmB,GACnB,EACE,EAAoB,EAAE,CAE5B,IAAK,IAAM,KAAS,EAAU,CAC5B,GAAI,EAAM,OAAS,EAAU,CAC3B,EAAmB,EAAM,SACzB,SAGF,IAAM,EAAQ,EAAM,MAKd,EAAU,GAAO,SAAW,GAC5B,EAAQ,GAAO,OAAS,GACxB,EAAkB,EAAW,GAAG,EAAS,GAAG,IAAY,EAE5D,CAAC,GAAoB,EAAe,EAAW,EAAiB,EAAM,GAGtE,EAAmB,GACnB,EAAW,GAAO,SAClB,EAAS,KAAK,EAAM,EAIxB,GACE,CAAC,GACD,IAAcC,EAAAA,eACd,IAAqB,KACrB,CAGA,IAAM,EAFa,EAAS,OAAQ,GAAY,EAAQ,OAAS,EAAS,CAEhD,GAAG,GAAG,CAE5B,GACF,EAAS,KAAK,EAAO,CAIzB,MAAO,CAAE,WAAU,mBAAkB,WAAU,CCvGjD,SAAgB,EAAoB,EAAwC,CAC1E,IAAM,GAAA,EAAA,EAAA,YAAiB,EAAO,aAAa,CAAC,CAQ5C,OAFA,EAAA,EAAA,gBAJc,EAAO,cAAgB,CACnC,EAAI,MAAQ,EAAO,aAAa,EAChC,CAEmB,CAEd,ECVT,MAAa,EAAkC,OAAO,YAAY,CAErD,EAAwC,OAAO,eAAe,CAE9D,EAA2C,OAAO,WAAW,CCF7D,MAA0B,CACrC,IAAM,GAAA,EAAA,EAAA,QAAgB,EAAU,CAEhC,GAAI,CAAC,EACH,MAAU,MAAM,iDAAiD,CAGnE,OAAO,GCJT,SAAgB,EAAa,EAAgC,CAC3D,IAAM,EAAS,GAAW,CAGpB,EAAW,GAAA,EAAA,EAAA,uBADoB,EAAQ,EAAS,CACb,CAYzC,MAAO,CACL,WAAA,EAAA,EAAA,cAV6B,EAAO,CAWpC,OAAA,EAAA,EAAA,cAL2B,EAAS,MAAM,MAAM,CAMhD,eAAA,EAAA,EAAA,cALmC,EAAS,MAAM,cAAc,CAMjE,CCZH,SAAS,EAAe,EAA8B,CAGpD,OAFc,EAAM,UAEN,WAAW,EAAI,KAG/B,SAAS,EACP,EACA,EACW,CACX,IAAM,EAAW,EAAM,IAAI,EAAQ,CAEnC,GAAI,EACF,OAAO,EAGT,IAAM,GAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBACY,CACd,KAAM,aAAa,IACnB,MAAM,EAAe,EAAY,CAC/B,UAAa,EAAW,MAAM,WAAW,EAE5C,CAAC,CACH,CAID,OAFA,EAAM,IAAI,EAAS,EAAQ,CAEpB,EAGT,SAAS,EAAiB,EAAgB,EAA0B,CAClE,GAAI,IAAa,IAAA,GACf,OAAO,EAGT,IAAM,EACJ,OAAO,GAAa,WAAc,GAA0B,CAAG,EAKjE,OAAA,EAAA,EAAA,GAF0BC,EAAAA,SAIxB,EAAE,CACF,CACE,YAAe,EACf,aAAgB,EACjB,CACF,CAGH,MAAM,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBACY,CACd,KAAM,wBACN,QAAS,CACP,OAAO,MAEV,CAAC,CACH,CAED,SAAS,EACP,EACA,EACA,EACO,CAEP,IAAM,EADc,EAAY,OACH,SAAW,gBAClC,EAAmB,EAAmB,EAAc,EAAQ,CAC5D,EAAc,EAAe,EAAY,EAAI,EAAE,CAMrD,OAAO,GAAA,EAAA,EAAA,GALoBC,EAAAA,UAAW,KAAM,CAC1C,aAAA,EAAA,EAAA,GACI,EAAkB,CAAE,IAAK,EAAS,CAAE,CAAE,YAAe,EAAa,CAAC,CACxE,CAAC,CAEwC,EAAS,CAUrD,SAAS,EAAmB,EAAyB,CACnD,OAAO,IAAU,IAAQ,IAAU,IAAM,IAAU,aAGrD,SAAS,EACP,EACA,EACA,EACc,CACd,IAAM,EAAa,EAAY,MAK/B,GAAI,EAAmB,GAAY,UAAU,EAAI,EAAY,OAAS,EAAO,CAE3E,IAAM,EAAU,GAAY,SAAW,gBAEjC,EAAmB,EAAmB,EAAc,EAAQ,CAC5D,EAAc,EAAe,EAAY,EAAI,EAAE,CAErD,OAAA,EAAA,EAAA,GAASC,EAAAA,SAAU,EAAA,EAAA,EAAA,GACfD,EAAAA,UAAW,KAAM,CACjB,aAAA,EAAA,EAAA,GACI,EAAkB,CAAE,IAAK,EAAS,CAAE,CAAE,YAAe,EAAa,CAAC,CACxE,CAAC,CACH,CAAC,CAGJ,IAAM,EAAU,EAAe,EAAY,CAQ3C,OALK,GAKL,EAAA,EAAA,GAASC,EAAAA,SAAU,EAAA,EAAA,EAAA,GACfD,EAAAA,UAAW,KAAM,CAAE,aAAA,EAAA,EAAA,GAAiB,GAA0B,CAAE,CAAC,CACnE,GAAA,EAAA,EAAA,GAAmBC,EAAAA,SAAU,EAAQ,CAAE,EAAS,CACjD,CAAC,CAPO,KAUX,MAAM,GAAA,EAAA,EAAA,iBAAqC,CACzC,KAAM,YACN,MAAO,CACL,SAAU,CACR,KAAM,OACN,SAAU,GACX,CACD,UAAW,CACT,KAAM,QACN,QAAS,GACV,CACF,CACD,MAAM,EAAO,CAAE,SAAS,CACtB,IAAM,EAAe,EAAa,EAAM,SAAS,CAC3C,EAAe,IAAI,IAKrB,EAA0B,KAC1B,EAAoB,GAExB,SAAS,EAAiB,EAAmB,EAA8B,CAkBzE,OAbI,IAAe,EACV,GAGT,EAAiB,EACjB,EAAoB,EAAS,KAC1B,GACC,EAAQ,OAAS,GACjB,EACG,EAAQ,OAA0C,UACpD,CACJ,CAEM,GAGT,UAA2B,CACzB,IAAM,EAAQ,EAAa,MAAM,MAEjC,GAAI,CAAC,EACH,OAAO,KAGT,IAAM,EAAa,EAAM,WAAW,CAC9B,EAAoB,EAAE,CAE5B,EAAgB,EAAY,EAAS,CAErC,GAAM,CAAE,WAAU,YAAa,EAC7B,EACA,EAAM,KACN,EAAM,SACP,CAED,GAAI,EAAS,SAAW,EACtB,OAAO,KAGT,IAAM,EAAc,EAAS,GAE7B,GAAI,EAAM,UACR,OAAO,EAAiB,EAAa,EAAc,EAAS,CAI9D,GAAI,EAAY,OAAS,GAAS,EAAY,OAAS,EACrD,OAAO,KAMT,GAFsB,EAAiB,EAAU,EAAW,CAG1D,OAAO,EAAqB,EAAa,EAAc,EAAS,CAGlE,IAAM,EAAU,EAAe,EAAY,CAM3C,OAJK,EAIE,GAAA,EAAA,EAAA,GAAmBA,EAAAA,SAAU,EAAQ,CAAE,EAAS,CAH9C,OAMd,CAAC,CAEW,GAAY,OAAO,OAAO,EAAoB,CAAE,QAAO,WAAU,CAAC,CC3OlE,GAAe,OAAO,OAAO,EAAE,CAAC,CAKhC,GAAgB,OAAO,OAAO,EAAE,CAAC,CCJxC,EAAiB,6BAUvB,SAAgB,EACd,EACA,EACyB,CACzB,IAAM,EAAS,GAAS,QAAU,gBAC5B,EAAgB,GAAS,oBAE3B,EAAsB,GACtB,EAAU,GACV,EAAc,GACd,EAAoB,GACpB,EAA6B,KAC7B,EAEE,EAAY,GAAsB,CAElC,GAAc,EAAc,IAAiC,CACjE,EAAoB,EACpB,aAAa,EAAe,CAC5B,EAAU,YAAc,EACxB,EAAiB,eAAiB,CAChC,EAAU,YAAc,GACxB,EAAoB,IACnB,IAAY,CAEf,EAAY,EAAG,EAOX,EAAkB,eAAiB,CAGvC,GAFA,EAAU,GAEN,IAAgB,MAAQ,CAAC,EAAa,CACxC,IAAM,EAAO,EAEb,EAAc,KACd,EAAW,EAAM,SAAS,cAA2B,KAAK,CAAC,GAE5D,IAAmB,CAEhB,EAAc,EAAO,WAAW,CAAE,WAAY,CAClD,GAAI,EAAqB,CACvB,EAAsB,GAEtB,OAQF,0BAA4B,CAC1B,0BAA4B,CAC1B,GAAI,EACF,OAGF,IAAM,EAAK,SAAS,cAA2B,KAAK,CAC9C,EAAO,EAAY,EAAO,EAAQ,EAAe,EAAG,CAEtD,MAAC,GAAQ,IAAS,GAItB,IAAI,CAAC,EAAS,CAEZ,EAAc,EAEd,OAGF,EAAW,EAAM,EAAG,GACpB,EACF,EACF,CAEF,MAAO,CACL,SAAU,CACR,EAAc,GACd,GAAa,CACb,aAAa,EAAe,CAC5B,aAAa,EAAgB,CAC7B,GAAiB,EAEpB,CAGH,SAAS,GAAoC,CAC3C,IAAM,EAAW,SAAS,cAA2B,IAAI,EAAe,GAAG,CAE3E,GAAI,EACF,OAAO,EAGT,IAAM,EAAU,SAAS,cAAc,MAAM,CAS7C,OAPA,EAAQ,aAAa,QAAS,mJAAgB,CAC9C,EAAQ,aAAa,YAAa,YAAY,CAC9C,EAAQ,aAAa,cAAe,OAAO,CAC3C,EAAQ,aAAa,EAAgB,GAAG,CAExC,SAAS,KAAK,QAAQ,EAAQ,CAEvB,EAGT,SAAS,GAAwB,CAC/B,SAAS,cAAc,IAAI,EAAe,GAAG,EAAE,QAAQ,CAGzD,SAAS,EACP,EACA,EACA,EACA,EACQ,CACR,GAAI,EACF,OAAO,EAAc,EAAM,CAG7B,IAAM,EAAS,GAAI,YAAY,MAAM,EAAI,GACnC,EAAY,EAAM,KAAK,WAAW,KAAsB,CAC1D,GACA,EAAM,KAIV,MAAO,GAAG,IAFR,GAAU,SAAS,OAAS,GAAa,WAAW,SAAS,WAKjE,SAAS,EAAY,EAA8B,CAC5C,IAIA,EAAG,aAAa,WAAW,EAC9B,EAAG,aAAa,WAAY,KAAK,CAGnC,EAAG,MAAM,CAAE,cAAe,GAAM,CAAC,EC3JnC,MAAM,EAAc,qBAEd,EAAyC,OAAO,OAAO,CAC3D,YAAe,GAGhB,CAAC,CAeF,SAAgB,GACd,EACA,EACyB,CACzB,GAAW,WAAW,SAAW,OAC/B,OAAO,EAGT,IAAM,EAAO,GAAS,MAAQ,UAK9B,GAAI,IAAS,SACX,OAAO,EAGT,IAAM,EAAgB,GAAS,iBAAmB,GAC5C,EAAe,GAAS,gBAExB,EAAwB,QAAQ,kBAEtC,GAAI,CACF,QAAQ,kBAAoB,cACtB,EAOR,IAAM,MAAwB,CAC5B,IAAM,EAAU,KAAgB,CAEhC,OAAO,EAAU,EAAQ,UAAY,WAAW,SAG5C,EAAY,GAAsB,CACtC,IAAM,EAAU,KAAgB,CAE5B,EACF,EAAQ,UAAY,EAEpB,WAAW,SAAS,EAAG,EAAI,EAIzB,MAAgC,CACpC,IAAM,EAAO,WAAW,SAAS,KAEjC,GAAI,GAAiB,EAAK,OAAS,EAAG,CAIpC,IAAI,EAEJ,GAAI,CACF,EAAK,mBAAmB,EAAK,MAAM,EAAE,CAAC,MAChC,CACN,EAAK,EAAK,MAAM,EAAE,CAIpB,IAAM,EAAU,SAAS,eAAe,EAAG,CAE3C,GAAI,EAAS,CACX,EAAQ,gBAAgB,CAExB,QAIJ,EAAS,EAAE,EAGT,EAAY,GAEV,EAAc,EAAO,WAAW,CAAE,QAAO,mBAAoB,CACjE,IAAM,EAAO,EAAM,QAChB,WAKC,GACF,EAAO,EAAM,EAAc,CAAE,GAAS,CAAC,CAKzC,0BAA4B,CACtB,MAIJ,IAAI,IAAS,OAAS,CAAC,EAAK,CAC1B,GAAmB,CAEnB,OAGE,KAAI,iBAAmB,UAI3B,IACE,EAAI,YAAc,QAClB,EAAI,iBAAmB,YACvB,EAAI,iBAAmB,SACvB,CACA,EAAS,GAAW,CAAC,EAAM,EAAM,GAAK,EAAE,CAExC,OAGF,GAAmB,IACnB,EACF,CAEI,MAAyB,CAC7B,IAAM,EAAU,EAAO,UAAU,CAE7B,GACF,EAAO,EAAM,EAAQ,CAAE,GAAS,CAAC,EAMrC,OAFA,WAAW,iBAAiB,WAAY,EAAW,CAE5C,CACL,YAAe,CACT,MAMJ,CAFA,EAAY,GACZ,GAAa,CACb,WAAW,oBAAoB,WAAY,EAAW,CAEtD,GAAI,CACF,QAAQ,kBAAoB,OACtB,KAIX,CAGH,SAAS,EAAM,EAAsB,CACnC,MAAO,GAAG,EAAM,KAAK,GAAG,EAAc,EAAM,OAAO,GAGrD,SAAS,GAAoC,CAC3C,GAAI,CACF,IAAM,EAAM,eAAe,QAAQ,EAAY,CAE/C,OAAO,EAAO,KAAK,MAAM,EAAI,CAA8B,EAAE,MACvD,CACN,MAAO,EAAE,EAIb,SAAS,EAAO,EAAa,EAAmB,CAC9C,GAAI,CACF,IAAM,EAAQ,GAAW,CAEzB,EAAM,GAAO,EACb,eAAe,QAAQ,EAAa,KAAK,UAAU,EAAM,CAAC,MACpD,GAKV,SAAS,EAAc,EAAwB,CAC7C,OAAO,KAAK,UAAU,EAAO,EAAkB,CAGjD,SAAS,EAAkB,EAAc,EAAuB,CAC9D,GAAoB,OAAO,GAAQ,UAA/B,GAA2C,CAAC,MAAM,QAAQ,EAAI,CAAE,CAClE,IAAM,EAAkC,EAAE,CAEpC,EAAO,OAAO,KAAK,EAA+B,CAAC,MACtD,EAAc,IAAkB,EAAK,cAAc,EAAM,CAC3D,CAED,IAAK,IAAM,KAAO,EAChB,EAAO,GAAQ,EAAgC,GAGjD,OAAO,EAGT,OAAO,ECrNT,SAAgB,EAAe,EAA0B,CACvD,OACE,EAAI,SAAW,GACf,CAAC,EAAI,SACL,CAAC,EAAI,QACL,CAAC,EAAI,SACL,CAAC,EAAI,SAMT,SAAgB,EACd,EACA,EACA,EACoB,CACpB,GAAI,CACF,IAAM,EAAW,EAAO,SAExB,GAAI,EAAU,CACZ,IAAM,EAAM,EAAS,EAAW,EAAY,CAE5C,GAAI,IAAQ,IAAA,GACV,OAAO,EAIX,OAAO,EAAO,UAAU,EAAW,EAAY,MACzC,CACN,QAAQ,MACN,wBAAwB,EAAU,sEACnC,CAED,QAIJ,SAAS,EAAY,EAAqC,CACxD,OAAO,EAAS,EAAM,MAAM,OAAO,EAAI,EAAE,CAAI,EAAE,CAGjD,SAAgB,EACd,EACA,EACA,EACoB,CACpB,GAAI,GAAY,EAAiB,CAC/B,IAAM,EAAe,EAAY,EAAgB,CAEjD,GAAI,EAAa,SAAW,EAC1B,OAAO,GAAiB,IAAA,GAE1B,GAAI,CAAC,EACH,OAAO,EAAa,KAAK,IAAI,CAG/B,IAAM,EAAa,EAAY,EAAc,CACvC,EAAO,IAAI,IAAI,EAAW,CAEhC,IAAK,IAAM,KAAS,EACb,EAAK,IAAI,EAAM,GAClB,EAAK,IAAI,EAAM,CACf,EAAW,KAAK,EAAM,EAI1B,OAAO,EAAW,KAAK,IAAI,CAG7B,OAAO,GAAiB,IAAA,GAgC1B,SAAgB,EAAc,EAA+C,CACtE,IAIH,aAAmB,mBACnB,aAAmB,oBAIhB,EAAQ,aAAa,OAAO,EAC/B,EAAQ,aAAa,OAAQ,OAAO,CAEjC,EAAQ,aAAa,WAAW,EACnC,EAAQ,aAAa,WAAY,IAAI,GCtGzC,SAAS,EAAwB,EAAgB,EAAuB,CACtE,GAAI,OAAO,GAAU,WAAY,CAC9B,EAAyB,EAAI,CAE9B,OAEF,GAAI,MAAM,QAAQ,EAAM,CAAE,CACxB,IAAM,EAAW,EAEjB,IAAK,IAAM,KAAM,EACf,GAAI,OAAO,GAAO,aAChB,EAAG,EAAI,CAEH,EAAI,kBACN,QAOV,MAAa,GAAA,EAAA,EAAA,iBAAuB,CAClC,KAAM,OAKN,aAAc,GACd,MAAO,CACL,UAAW,CACT,KAAM,OACN,SAAU,GACX,CACD,YAAa,CACX,KAAM,OACN,YAAe,GAChB,CACD,aAAc,CACZ,KAAM,OACN,YAAe,GAChB,CACD,MAAO,CACL,KAAM,OACN,QAAS,IAAA,GACV,CACD,gBAAiB,CACf,KAAM,OACN,QAAS,SACV,CACD,aAAc,CACZ,KAAM,QACN,QAAS,GACV,CACD,kBAAmB,CACjB,KAAM,QACN,QAAS,GACV,CACD,OAAQ,CACN,KAAM,OACN,QAAS,IAAA,GACV,CACF,CACD,MAAM,EAAO,CAAE,QAAO,SAAS,CAC7B,IAAM,EAAS,GAAW,CAEpB,GAAA,EAAA,EAAA,YAAsB,GAAM,EAMlC,EAAA,EAAA,WAEI,CACE,EAAM,UACN,EAAM,YACN,EAAM,aACN,EAAM,kBACP,EAED,CAAC,EAAW,EAAa,EAAc,GACvC,EACA,IACG,CACH,IAAM,GAAA,EAAA,EAAA,yBAAiC,EAAQ,EAAW,EAAa,CACrE,OAAQ,EACR,oBACD,CAAC,CAEF,EAAS,MAAQ,EAAO,aAAa,CAMrC,EAJc,EAAO,cAAgB,CACnC,EAAS,MAAQ,EAAO,aAAa,EACrC,CAEc,EAElB,CAAE,UAAW,GAAM,MAAO,OAAQ,CACnC,CAED,IAAM,GAAA,EAAA,EAAA,cACJ,EAAU,EAAQ,EAAM,UAAW,EAAM,YAAY,CACtD,CAEK,GAAA,EAAA,EAAA,cACJ,EAAqB,EAAS,MAAO,EAAM,gBAAiB,EAAM,MAAM,CACzE,CAEK,EAAe,GAAoB,CAKnC,EAAM,UAAY,IAAA,IAAa,EAAM,UAAY,OACnD,EAAwB,EAAM,QAAS,EAAI,CAEvC,EAAI,mBAKN,CAAC,EAAe,EAAI,EAAI,EAAM,SAAW,WAI7C,EAAI,gBAAgB,CACpB,EACG,SAAS,EAAM,UAAW,EAAM,YAAa,EAAM,aAAa,CAChE,UAAY,GAAG,GAGpB,UAAa,CAMX,IAAM,EAA0C,EAAE,CAElD,IAAK,IAAM,KAAO,OAAO,KAAK,EAAM,CAC9B,IAAQ,YACV,EAAe,GAAQ,EAAkC,IAI7D,OAAA,EAAA,EAAA,GACE,IACA,CACE,GAAG,EACH,KAAM,EAAK,MACX,MAAO,EAAe,MACtB,OAAQ,EAAM,OACd,QAAS,EACV,CACD,EAAM,WAAW,CAClB,GAGN,CAAC,CCrKW,GAAA,EAAA,EAAA,iBAAsC,CACjD,KAAM,sBACN,MAAO,CACL,SAAU,CACR,KAAM,SAGN,SAAU,GACX,CACD,QAAS,CACP,KAAM,SAON,QAAS,IAAA,GACV,CACF,CACD,MAAM,EAAO,CAAE,SAAS,CAEtB,IAAM,EAAW,GAAA,EAAA,EAAA,wBADF,GAAW,CACsC,CAAC,CAgBjE,OAdA,EAAA,EAAA,WACQ,EAAS,MAAM,YACf,CACA,EAAS,MAAM,OACjB,EAAM,UACJ,EAAS,MAAM,MACf,EAAS,MAAM,QACf,EAAS,MAAM,UAChB,EAGL,CAAE,UAAW,GAAM,CACpB,KAEY,CACX,IAAM,EAAW,EAAM,WAAW,EAAI,EAAE,CAClC,EAAa,EAAS,MAAM,MAC9B,EAAM,SAAS,EAAS,MAAM,MAAO,EAAS,MAAM,WAAW,CAC/D,KAEJ,OAAA,EAAA,EAAA,GAASC,EAAAA,SAAU,KAAM,CAAC,GAAG,EAAU,EAAW,CAAC,GAGxD,CAAC,CCpCI,EAAwB,EAAE,CAShC,SAAgB,EAAoB,EAA4B,CAG9D,OAFA,EAAY,KAAK,EAAO,KAEX,CACX,IAAM,EAAM,EAAY,YAAY,EAAO,CAEvC,IAAQ,IACV,EAAY,OAAO,EAAK,EAAE,EAyBhC,SAAgB,GAA6B,CAC3C,IAAM,EAAM,EAAY,GAAG,GAAG,CAE9B,GAAI,CAAC,EACH,MAAU,MACR,4FACD,CAGH,OAAO,EAST,MAAM,EAAW,IAAI,QAQrB,SAAS,EAAe,EAA6C,CAgBnE,OAfI,GAAU,MACZ,QAAQ,MACN,8GACD,CAEM,IAEL,OAAQ,EAA6B,MAAS,SAQ3C,IAPL,QAAQ,MACN,uHACD,CAEM,IAMX,SAAS,GACP,EACA,EAC2B,CAC3B,MAAQ,IAAoB,CACrB,EAAe,EAAI,GAIxB,EAAI,gBAAgB,CACpB,EACG,SAAS,EAAM,KAAM,EAAM,QAAU,EAAE,CAAE,EAAM,SAAW,EAAE,CAAC,CAC7D,UAAY,GAAG,GAItB,SAAS,GACP,EACA,EACA,EAC8B,CAC9B,MAAQ,IAAuB,CACzB,EAAI,MAAQ,SAAW,EAAE,aAAmB,oBAC9C,EACG,SAAS,EAAM,KAAM,EAAM,QAAU,EAAE,CAAE,EAAM,SAAW,EAAE,CAAC,CAC7D,UAAY,GAAG,EAKxB,SAAS,EACP,EACA,EACA,EACM,CACN,IAAM,EAAQ,GAAmB,EAAQ,EAAM,CACzC,EAAU,GAAqB,EAAQ,EAAO,EAAQ,CAE5D,EAAQ,iBAAiB,QAAS,EAAM,CACxC,EAAQ,iBAAiB,UAAW,EAAQ,CAE5C,EAAS,IAAI,EAAS,CAAE,QAAO,UAAS,CAAC,CAG3C,SAAS,EAAe,EAA4B,CAClD,IAAM,EAAQ,EAAS,IAAI,EAAQ,CAE/B,IACF,EAAQ,oBAAoB,QAAS,EAAM,MAAM,CACjD,EAAQ,oBAAoB,UAAW,EAAM,QAAQ,CACrD,EAAS,OAAO,EAAQ,EAI5B,MAAa,GAAoD,CAC/D,QAAQ,EAAS,EAAS,CACxB,IAAM,EAAS,GAAoB,CAEnC,EAAc,EAAQ,CAEtB,EAAQ,MAAM,OAAS,UAElB,EAAe,EAAQ,MAAM,EAIlC,EAAe,EAAS,EAAQ,EAAQ,MAAM,EAGhD,QAAQ,EAAS,EAAS,CACxB,IAAM,EAAS,GAAoB,CAEnC,EAAe,EAAQ,CAElB,EAAe,EAAQ,MAAM,EAIlC,EAAe,EAAS,EAAQ,EAAQ,MAAM,EAGhD,cAAc,EAAS,CACrB,EAAe,EAAQ,EAE1B,CCxLY,OAAgC,CAC3C,IAAM,GAAA,EAAA,EAAA,QAAmB,EAAa,CAEtC,GAAI,CAAC,EACH,MAAU,MAAM,oDAAoD,CAGtE,OAAO,GCNI,QAGX,EAAA,EAAA,gBAAA,EAAA,EAAA,cAFe,GAAW,CAEe,CAAC,SAAS,CAAC,CCHzC,OAA6D,CACxE,IAAM,GAAA,EAAA,EAAA,QAAsB,EAAS,CAErC,GAAI,CAAC,EACH,MAAU,MAAM,gDAAgD,CAGlE,OAAO,GCNT,SAAgB,IAA4D,CAI1E,OAAO,GAAA,EAAA,EAAA,qBAHQ,GAAW,CACgB,CAEX,CCajC,SAAgB,EAAoB,EAAgC,CAClE,IAAM,GAAA,EAAA,EAAA,cAAyB,EAAO,CAChC,GAAA,EAAA,EAAA,mBAA2B,EAAO,CAClC,EAAU,EAAO,aAAa,CAE9B,GAAA,EAAA,EAAA,YAAsC,EAAQ,MAAM,CACpD,GAAA,EAAA,EAAA,YAA8C,EAAQ,cAAc,CAS1E,MAAO,CAAE,YAAW,QAAO,gBAAe,YAPtB,EAAO,cAAgB,CACzC,IAAM,EAAW,EAAO,aAAa,CAErC,EAAM,MAAQ,EAAS,MACvB,EAAc,MAAQ,EAAS,eAC/B,CAEqD,CCjCzD,SAAgB,GAAmB,EAA4B,CAC7D,MAAO,CACL,QAAQ,EAAW,CACjB,IAAM,EAAmB,EAAoB,EAAO,CAE9C,CAAE,YAAW,QAAO,gBAAe,eACvC,EAAoB,EAAO,CAKzB,cAAe,GAChB,EAAsD,cAAgB,CACrE,GAAkB,CAClB,GAAa,EACb,CAGJ,EAAI,QAAQ,EAAW,EAAO,CAC9B,EAAI,QAAQ,EAAc,EAAU,CACpC,EAAI,QAAQ,EAAU,CAAE,YAAW,QAAO,gBAAe,CAAC,EAE7D,CClBH,MAAa,IAAA,EAAA,EAAA,iBAAiC,CAC5C,KAAM,iBACN,MAAO,CACL,OAAQ,CACN,KAAM,OACN,SAAU,GACX,CACD,mBAAoB,CAClB,KAAM,QACN,QAAS,GACV,CACD,kBAAmB,CACjB,KAAM,OACP,CACF,CACD,MAAM,EAAO,CAAE,SAAS,EAItB,EAAA,EAAA,WACQ,CAAC,EAAM,OAAQ,EAAM,mBAAmB,EAC7C,CAAC,EAAQ,GAAU,EAAO,IAAc,CACvC,GAAI,CAAC,EACH,OAGF,IAAM,EAAY,EAAqB,EAAO,CAE9C,MAAgB,CACd,EAAU,SAAS,EACnB,EAEJ,CAAE,UAAW,GAAM,CACpB,EAMD,EAAA,EAAA,WAEI,CACE,EAAM,OACN,EAAM,oBAAsB,IAAA,GAC5B,EAAM,mBAAmB,KACzB,EAAM,mBAAmB,gBAC1B,EACF,CAAC,EAAQ,EAAS,EAAM,GAAkB,EAAO,IAAc,CAC9D,GAAI,CAAC,EACH,OAGF,IAAM,EAAK,GAAwB,EAAQ,CACzC,OACA,kBACA,gBAAiB,EAAM,mBAAmB,gBAC3C,CAAC,CAEF,MAAgB,CACd,EAAG,SAAS,EACZ,EAEJ,CAAE,UAAW,GAAM,CACpB,CAKD,IAAM,EAAmB,EAAoB,EAAM,OAAO,CAEpD,CAAE,YAAW,QAAO,gBAAe,eACvC,EAAoB,EAAM,OAAO,CAWnC,OATA,EAAA,EAAA,oBAAqB,CACnB,GAAkB,CAClB,GAAa,EACb,EAEF,EAAA,EAAA,SAAQ,EAAW,EAAM,OAAO,EAChC,EAAA,EAAA,SAAQ,EAAc,EAAU,EAChC,EAAA,EAAA,SAAQ,EAAU,CAAE,YAAW,QAAO,gBAAe,CAAC,KAEzC,EAAM,WAAW,EAEjC,CAAC"}
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 { SelfProps } from \"./types\";\nimport type { FunctionalComponent, 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\n// Type Self via FunctionalComponent<SelfProps> so the SelfProps interface\n// is anchored to the component contract — knip otherwise flags SelfProps\n// as unused even though it's re-exported as RouteViewSelfProps for\n// consumers wrapping Self in custom HOCs.\nconst SelfImpl = defineComponent({\n name: \"RouteView.Self\",\n props: {\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n },\n render: renderNull,\n});\n\nexport const Self = SelfImpl as unknown as FunctionalComponent<SelfProps>;\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, Self } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\ninterface FallbackSlots {\n selfVNode: VNode | null;\n selfFallback: FallbackType;\n notFoundChildren: unknown;\n}\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 (\n child.type === Match ||\n child.type === Self ||\n child.type === NotFound\n ) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nfunction recordFallback(child: VNode, slots: FallbackSlots): boolean {\n if (child.type === NotFound) {\n slots.notFoundChildren = child.children;\n\n return true;\n }\n\n if (child.type === Self) {\n if (slots.selfVNode === null) {\n slots.selfVNode = child;\n const props = child.props as { fallback?: FallbackType } | null;\n\n slots.selfFallback = props?.fallback;\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction evaluateMatch(\n child: VNode,\n routeName: string,\n nodeName: string,\n): { isActive: boolean; fallback: FallbackType } {\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 = isSegmentMatch(routeName, fullSegmentName, exact);\n\n return { isActive, fallback: props?.fallback };\n}\n\nfunction appendFallback(\n rendered: VNode[],\n routeName: string,\n nodeName: string,\n slots: FallbackSlots,\n elements: VNode[],\n): FallbackType {\n if (slots.selfVNode !== null && routeName === nodeName) {\n rendered.push(slots.selfVNode);\n\n return slots.selfFallback;\n }\n\n if (routeName === UNKNOWN_ROUTE && slots.notFoundChildren !== null) {\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 undefined;\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 const slots: FallbackSlots = {\n selfVNode: null,\n selfFallback: undefined,\n notFoundChildren: null,\n };\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (recordFallback(child, slots)) {\n continue;\n }\n\n if (activeMatchFound) {\n continue;\n }\n\n const result = evaluateMatch(child, routeName, nodeName);\n\n if (result.isActive) {\n activeMatchFound = true;\n fallback = result.fallback;\n rendered.push(child);\n }\n }\n\n if (!activeMatchFound) {\n fallback = appendFallback(rendered, routeName, nodeName, slots, elements);\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, Self } 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 (\n activeChild.type !== Match &&\n activeChild.type !== Self &&\n activeChild.type !== NotFound\n ) {\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, {\n Match,\n Self,\n NotFound,\n});\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n SelfProps as RouteViewSelfProps,\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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"}
@@ -15,6 +15,10 @@ interface MatchProps {
15
15
  readonly fallback?: VNode | (() => VNode);
16
16
  readonly keepAlive?: boolean;
17
17
  }
18
+ interface SelfProps {
19
+ /** Fallback content while children are suspended. */
20
+ readonly fallback?: VNode | (() => VNode);
21
+ }
18
22
  type NotFoundProps = Record<string, never>;
19
23
  //#endregion
20
24
  //#region src/components/RouteView/RouteView.d.ts
@@ -105,6 +109,7 @@ declare const RouteView: {
105
109
  keepAlive: boolean;
106
110
  exact: boolean;
107
111
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
112
+ Self: _$vue.FunctionalComponent<SelfProps, {}, any, {}>;
108
113
  NotFound: _$vue.DefineComponent<{}, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
109
114
  };
110
115
  //#endregion
@@ -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","../../../../shared/dom-utils/scroll-restore.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 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};
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 ie,getTransitionSource as ae}from"@real-router/sources";import{getPluginApi as oe}from"@real-router/core/api";function g(){return null}const _=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:g}),v=i({name:`RouteView.Self`,props:{fallback:{type:[Object,Function],default:void 0}},render:g}),y=i({name:`RouteView.NotFound`,render:g});function se(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===_||t.type===v||t.type===y?n.push(t):t.type===e&&x(t.children,n)}function ce(e,t){return e.type===y?(t.notFoundChildren=e.children,!0):e.type===v?(t.selfVNode===null&&(t.selfVNode=e,t.selfFallback=e.props?.fallback),!0):!1}function le(e,t,n){let r=e.props,i=r?.segment??``,a=r?.exact??!1;return{isActive:se(t,n?`${n}.${i}`:i,a),fallback:r?.fallback}}function ue(e,t,n,r,i){if(r.selfVNode!==null&&t===n)return e.push(r.selfVNode),r.selfFallback;if(t===p&&r.notFoundChildren!==null){let t=i.filter(e=>e.type===y).at(-1);t&&e.push(t)}}function de(e,t,n){let r={selfVNode:null,selfFallback:void 0,notFoundChildren:null},i=!1,a,o=[];for(let s of e){if(ce(s,r)||i)continue;let e=le(s,t,n);e.isActive&&(i=!0,a=e.fallback,o.push(s))}return i||(a=ue(o,t,n,r,e)),{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 fe=c(i({name:`KeepAlive-placeholder`,render(){return null}}));function pe(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 me(n,r,i){let o=n.props;if(j(o?.keepAlive)&&n.type===_){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(fe)}),A(a(e,s),i)]):null}const he=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===_&&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}=de(l,o.name,t.nodeName);if(u.length===0)return null;let f=u[0];if(t.keepAlive)return pe(f,i,d);if(f.type!==_&&f.type!==v&&f.type!==y)return null;if(c(l,s))return me(f,i,d);let p=O(f);return p?A(a(e,p),d):null}}}),ge=Object.assign(he,{Match:_,Self:v,NotFound:y}),M=Object.freeze({}),N=Object.freeze({}),P=`data-real-router-announcer`;function F(e,t){let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=I(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),ve(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=_e(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),L()}}}function I(){let e=document.querySelector(`[${P}]`);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(P,``),document.body.prepend(t),t}function L(){document.querySelector(`[${P}]`)?.remove()}function _e(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 ve(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const R=`real-router:scroll`,z=Object.freeze({destroy:()=>{}});function ye(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}:${be(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 be(e){return JSON.stringify(e,xe)}function xe(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 Se(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 Ce(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 we(e){e&&(e instanceof HTMLAnchorElement||e instanceof HTMLButtonElement||(e.hasAttribute(`role`)||e.setAttribute(`role`,`link`),e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`0`)))}function Te(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 Ee=i({name:`Link`,inheritAttrs:!1,props:{routeName:{type:String,required:!0},routeParams:{type:Object,default:()=>M},routeOptions:{type:Object,default:()=>N},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(()=>Se(i,e.routeName,e.routeParams)),c=r(()=>Ce(o.value,e.activeClassName,e.class)),l=t=>{n.onClick!==void 0&&n.onClick!==null&&(Te(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?.())}}}),De=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])}}}),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 Oe(e,t){return n=>{U(n)&&(n.preventDefault(),e.navigate(t.name,t.params??{},t.options??{}).catch(()=>{}))}}function X(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=Oe(t,n),i=X(t,n,e);e.addEventListener(`click`,r),e.addEventListener(`keydown`,i),J.set(e,{click:r,keydown:i})}function Q(e){let t=J.get(e);t&&(e.removeEventListener(`click`,t.click),e.removeEventListener(`keydown`,t.keydown),J.delete(e))}const ke={mounted(e,t){let n=q();we(e),e.style.cursor=`pointer`,Y(t.value)&&Z(e,n,t.value)},updated(e,t){let n=q();Q(e),Y(t.value)&&Z(e,n,t.value)},beforeUnmount(e){Q(e)}},Ae=()=>{let e=o(w);if(!e)throw Error(`useNavigator must be used within a RouterProvider`);return e},je=()=>ee(oe(E()).getTree()),Me=()=>{let e=o(T);if(!e)throw Error(`useRoute must be used within a RouterProvider`);return e};function Ne(){return S(ae(E()))}function $(e){let t=m(e),n=ie(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 Pe(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 Fe=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=F(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=ye(t,{mode:r,anchorScrolling:i,scrollContainer:e.scrollRestoration?.scrollContainer});o(()=>{s.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{Ee as Link,w as NavigatorKey,T as RouteKey,ge as RouteView,De as RouterErrorBoundary,C as RouterKey,Fe as RouterProvider,Pe as createRouterPlugin,Ae as useNavigator,Me as useRoute,D as useRouteNode,je as useRouteUtils,E as useRouter,Ne as useRouterTransition,ke 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/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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"}
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 { SelfProps } from \"./types\";\nimport type { FunctionalComponent, 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\n// Type Self via FunctionalComponent<SelfProps> so the SelfProps interface\n// is anchored to the component contract — knip otherwise flags SelfProps\n// as unused even though it's re-exported as RouteViewSelfProps for\n// consumers wrapping Self in custom HOCs.\nconst SelfImpl = defineComponent({\n name: \"RouteView.Self\",\n props: {\n fallback: {\n type: [Object, Function] as PropType<VNode | (() => VNode)>,\n default: undefined,\n },\n },\n render: renderNull,\n});\n\nexport const Self = SelfImpl as unknown as FunctionalComponent<SelfProps>;\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, Self } from \"./components\";\n\nimport type { VNode } from \"vue\";\n\ntype FallbackType = VNode | (() => VNode) | undefined;\n\ninterface FallbackSlots {\n selfVNode: VNode | null;\n selfFallback: FallbackType;\n notFoundChildren: unknown;\n}\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 (\n child.type === Match ||\n child.type === Self ||\n child.type === NotFound\n ) {\n result.push(child);\n } else if (child.type === Fragment) {\n collectElements(child.children, result);\n }\n }\n}\n\nfunction recordFallback(child: VNode, slots: FallbackSlots): boolean {\n if (child.type === NotFound) {\n slots.notFoundChildren = child.children;\n\n return true;\n }\n\n if (child.type === Self) {\n if (slots.selfVNode === null) {\n slots.selfVNode = child;\n const props = child.props as { fallback?: FallbackType } | null;\n\n slots.selfFallback = props?.fallback;\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction evaluateMatch(\n child: VNode,\n routeName: string,\n nodeName: string,\n): { isActive: boolean; fallback: FallbackType } {\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 = isSegmentMatch(routeName, fullSegmentName, exact);\n\n return { isActive, fallback: props?.fallback };\n}\n\nfunction appendFallback(\n rendered: VNode[],\n routeName: string,\n nodeName: string,\n slots: FallbackSlots,\n elements: VNode[],\n): FallbackType {\n if (slots.selfVNode !== null && routeName === nodeName) {\n rendered.push(slots.selfVNode);\n\n return slots.selfFallback;\n }\n\n if (routeName === UNKNOWN_ROUTE && slots.notFoundChildren !== null) {\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 undefined;\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 const slots: FallbackSlots = {\n selfVNode: null,\n selfFallback: undefined,\n notFoundChildren: null,\n };\n let activeMatchFound = false;\n let fallback: FallbackType = undefined;\n const rendered: VNode[] = [];\n\n for (const child of elements) {\n if (recordFallback(child, slots)) {\n continue;\n }\n\n if (activeMatchFound) {\n continue;\n }\n\n const result = evaluateMatch(child, routeName, nodeName);\n\n if (result.isActive) {\n activeMatchFound = true;\n fallback = result.fallback;\n rendered.push(child);\n }\n }\n\n if (!activeMatchFound) {\n fallback = appendFallback(rendered, routeName, nodeName, slots, elements);\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, Self } 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 (\n activeChild.type !== Match &&\n activeChild.type !== Self &&\n activeChild.type !== NotFound\n ) {\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, {\n Match,\n Self,\n NotFound,\n});\n\nexport type {\n RouteViewProps,\n MatchProps as RouteViewMatchProps,\n SelfProps as RouteViewSelfProps,\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.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "commonjs",
5
5
  "description": "Vue 3 integration for Real-Router",
6
6
  "main": "./dist/cjs/index.js",
@@ -50,7 +50,7 @@
50
50
  "license": "MIT",
51
51
  "sideEffects": false,
52
52
  "dependencies": {
53
- "@real-router/core": "^0.50.0",
53
+ "@real-router/core": "^0.50.1",
54
54
  "@real-router/route-utils": "^0.2.1",
55
55
  "@real-router/sources": "^0.7.2"
56
56
  },
@@ -58,7 +58,7 @@
58
58
  "@testing-library/jest-dom": "6.9.1",
59
59
  "@vue/test-utils": "2.4.6",
60
60
  "vue": "3.5.13",
61
- "@real-router/browser-plugin": "^0.14.0"
61
+ "@real-router/browser-plugin": "^0.15.1"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "vue": ">=3.3.0"
@@ -7,7 +7,7 @@ import {
7
7
  Suspense,
8
8
  } from "vue";
9
9
 
10
- import { Match, NotFound } from "./components";
10
+ import { Match, NotFound, Self } from "./components";
11
11
  import { buildRenderList, collectElements } from "./helpers";
12
12
  import { useRouteNode } from "../../composables/useRouteNode";
13
13
 
@@ -214,7 +214,11 @@ const RouteViewComponent = defineComponent({
214
214
  }
215
215
 
216
216
  /* v8 ignore start */
217
- if (activeChild.type !== Match && activeChild.type !== NotFound) {
217
+ if (
218
+ activeChild.type !== Match &&
219
+ activeChild.type !== Self &&
220
+ activeChild.type !== NotFound
221
+ ) {
218
222
  return null;
219
223
  }
220
224
  /* v8 ignore stop */
@@ -236,10 +240,15 @@ const RouteViewComponent = defineComponent({
236
240
  },
237
241
  });
238
242
 
239
- export const RouteView = Object.assign(RouteViewComponent, { Match, NotFound });
243
+ export const RouteView = Object.assign(RouteViewComponent, {
244
+ Match,
245
+ Self,
246
+ NotFound,
247
+ });
240
248
 
241
249
  export type {
242
250
  RouteViewProps,
243
251
  MatchProps as RouteViewMatchProps,
252
+ SelfProps as RouteViewSelfProps,
244
253
  NotFoundProps as RouteViewNotFoundProps,
245
254
  } from "./types";
@@ -1,6 +1,7 @@
1
1
  import { defineComponent } from "vue";
2
2
 
3
- import type { PropType, VNode } from "vue";
3
+ import type { SelfProps } from "./types";
4
+ import type { FunctionalComponent, PropType, VNode } from "vue";
4
5
 
5
6
  function renderNull() {
6
7
  return null;
@@ -29,6 +30,23 @@ export const Match = defineComponent({
29
30
  render: renderNull,
30
31
  });
31
32
 
33
+ // Type Self via FunctionalComponent<SelfProps> so the SelfProps interface
34
+ // is anchored to the component contract — knip otherwise flags SelfProps
35
+ // as unused even though it's re-exported as RouteViewSelfProps for
36
+ // consumers wrapping Self in custom HOCs.
37
+ const SelfImpl = defineComponent({
38
+ name: "RouteView.Self",
39
+ props: {
40
+ fallback: {
41
+ type: [Object, Function] as PropType<VNode | (() => VNode)>,
42
+ default: undefined,
43
+ },
44
+ },
45
+ render: renderNull,
46
+ });
47
+
48
+ export const Self = SelfImpl as unknown as FunctionalComponent<SelfProps>;
49
+
32
50
  export const NotFound = defineComponent({
33
51
  name: "RouteView.NotFound",
34
52
  render: renderNull,
@@ -2,12 +2,18 @@ import { UNKNOWN_ROUTE } from "@real-router/core";
2
2
  import { startsWithSegment } from "@real-router/route-utils";
3
3
  import { Fragment, isVNode } from "vue";
4
4
 
5
- import { Match, NotFound } from "./components";
5
+ import { Match, NotFound, Self } from "./components";
6
6
 
7
7
  import type { VNode } from "vue";
8
8
 
9
9
  type FallbackType = VNode | (() => VNode) | undefined;
10
10
 
11
+ interface FallbackSlots {
12
+ selfVNode: VNode | null;
13
+ selfFallback: FallbackType;
14
+ notFoundChildren: unknown;
15
+ }
16
+
11
17
  function isSegmentMatch(
12
18
  routeName: string,
13
19
  fullSegmentName: string,
@@ -46,7 +52,11 @@ export function collectElements(children: unknown, result: VNode[]): void {
46
52
  const vnodes = normalizeChildren(children);
47
53
 
48
54
  for (const child of vnodes) {
49
- if (child.type === Match || child.type === NotFound) {
55
+ if (
56
+ child.type === Match ||
57
+ child.type === Self ||
58
+ child.type === NotFound
59
+ ) {
50
60
  result.push(child);
51
61
  } else if (child.type === Fragment) {
52
62
  collectElements(child.children, result);
@@ -54,6 +64,71 @@ export function collectElements(children: unknown, result: VNode[]): void {
54
64
  }
55
65
  }
56
66
 
67
+ function recordFallback(child: VNode, slots: FallbackSlots): boolean {
68
+ if (child.type === NotFound) {
69
+ slots.notFoundChildren = child.children;
70
+
71
+ return true;
72
+ }
73
+
74
+ if (child.type === Self) {
75
+ if (slots.selfVNode === null) {
76
+ slots.selfVNode = child;
77
+ const props = child.props as { fallback?: FallbackType } | null;
78
+
79
+ slots.selfFallback = props?.fallback;
80
+ }
81
+
82
+ return true;
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+ function evaluateMatch(
89
+ child: VNode,
90
+ routeName: string,
91
+ nodeName: string,
92
+ ): { isActive: boolean; fallback: FallbackType } {
93
+ const props = child.props as {
94
+ segment: string;
95
+ exact?: boolean;
96
+ fallback?: FallbackType;
97
+ } | null;
98
+ const segment = props?.segment ?? "";
99
+ const exact = props?.exact ?? false;
100
+ const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;
101
+ const isActive = isSegmentMatch(routeName, fullSegmentName, exact);
102
+
103
+ return { isActive, fallback: props?.fallback };
104
+ }
105
+
106
+ function appendFallback(
107
+ rendered: VNode[],
108
+ routeName: string,
109
+ nodeName: string,
110
+ slots: FallbackSlots,
111
+ elements: VNode[],
112
+ ): FallbackType {
113
+ if (slots.selfVNode !== null && routeName === nodeName) {
114
+ rendered.push(slots.selfVNode);
115
+
116
+ return slots.selfFallback;
117
+ }
118
+
119
+ if (routeName === UNKNOWN_ROUTE && slots.notFoundChildren !== null) {
120
+ const nfElements = elements.filter((element) => element.type === NotFound);
121
+ /* v8 ignore next 3 */
122
+ const lastNf = nfElements.at(-1);
123
+
124
+ if (lastNf) {
125
+ rendered.push(lastNf);
126
+ }
127
+ }
128
+
129
+ return undefined;
130
+ }
131
+
57
132
  export function buildRenderList(
58
133
  elements: VNode[],
59
134
  routeName: string,
@@ -63,47 +138,35 @@ export function buildRenderList(
63
138
  activeMatchFound: boolean;
64
139
  fallback?: FallbackType;
65
140
  } {
66
- let notFoundChildren: unknown = null;
141
+ const slots: FallbackSlots = {
142
+ selfVNode: null,
143
+ selfFallback: undefined,
144
+ notFoundChildren: null,
145
+ };
67
146
  let activeMatchFound = false;
68
147
  let fallback: FallbackType = undefined;
69
148
  const rendered: VNode[] = [];
70
149
 
71
150
  for (const child of elements) {
72
- if (child.type === NotFound) {
73
- notFoundChildren = child.children;
151
+ if (recordFallback(child, slots)) {
74
152
  continue;
75
153
  }
76
154
 
77
- const props = child.props as {
78
- segment: string;
79
- exact?: boolean;
80
- fallback?: FallbackType;
81
- } | null;
82
- const segment = props?.segment ?? "";
83
- const exact = props?.exact ?? false;
84
- const fullSegmentName = nodeName ? `${nodeName}.${segment}` : segment;
85
- const isActive =
86
- !activeMatchFound && isSegmentMatch(routeName, fullSegmentName, exact);
87
-
88
- if (isActive) {
155
+ if (activeMatchFound) {
156
+ continue;
157
+ }
158
+
159
+ const result = evaluateMatch(child, routeName, nodeName);
160
+
161
+ if (result.isActive) {
89
162
  activeMatchFound = true;
90
- fallback = props?.fallback;
163
+ fallback = result.fallback;
91
164
  rendered.push(child);
92
165
  }
93
166
  }
94
167
 
95
- if (
96
- !activeMatchFound &&
97
- routeName === UNKNOWN_ROUTE &&
98
- notFoundChildren !== null
99
- ) {
100
- const nfElements = elements.filter((element) => element.type === NotFound);
101
- /* v8 ignore next 3 */
102
- const lastNf = nfElements.at(-1);
103
-
104
- if (lastNf) {
105
- rendered.push(lastNf);
106
- }
168
+ if (!activeMatchFound) {
169
+ fallback = appendFallback(rendered, routeName, nodeName, slots, elements);
107
170
  }
108
171
 
109
172
  return { rendered, activeMatchFound, fallback };
@@ -3,5 +3,6 @@ export { RouteView } from "./RouteView";
3
3
  export type {
4
4
  RouteViewProps,
5
5
  RouteViewMatchProps,
6
+ RouteViewSelfProps,
6
7
  RouteViewNotFoundProps,
7
8
  } from "./RouteView";
@@ -12,4 +12,9 @@ export interface MatchProps {
12
12
  readonly keepAlive?: boolean;
13
13
  }
14
14
 
15
+ export interface SelfProps {
16
+ /** Fallback content while children are suspended. */
17
+ readonly fallback?: VNode | (() => VNode);
18
+ }
19
+
15
20
  export type NotFoundProps = Record<string, never>;