@real-router/preact 0.14.0 → 0.15.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
@@ -157,7 +157,7 @@ Navigation link with automatic active state detection. Re-renders only when its
157
157
  <Link routeName="settings" hash="account">Account</Link>
158
158
  ```
159
159
 
160
- Tri-state: `undefined` preserves the current hash, `""` clears it, a value sets it. Active class is hash-aware — only the matching tab lights up. Live demo: [`examples/web/react/link-hash/`](../../examples/web/react/link-hash/) — behavior is identical across adapters, only template syntax differs. See the [Hash Fragment Support](https://github.com/greydragon888/real-router/wiki/Hash) wiki page for the full surface.
160
+ Tri-state: `undefined` preserves the current hash, `""` clears it, a value sets it. Active class is hash-aware — only the matching tab lights up. Live demo: [`examples/web/react/hash-examples/link-hash/`](../../examples/web/react/hash-examples/link-hash/) — behavior is identical across adapters, only template syntax differs. See the [Hash Fragment Support](https://github.com/greydragon888/real-router/wiki/Hash) wiki page for the full surface.
161
161
 
162
162
  ### `<RouteView>`
163
163
 
@@ -387,6 +387,25 @@ Opt-in preservation of scroll position across navigations:
387
387
 
388
388
  Restores scroll on back/forward, scrolls to top (or `#hash`) on push. Three modes: `"restore"` (default), `"top"`, `"native"`. Custom containers via `scrollContainer: () => HTMLElement | null`. Override the `sessionStorage` key via `storageKey` (default `"real-router:scroll"`) when isolating multiple routers on one origin. Lifecycle tied to the provider — created on mount, destroyed on unmount. Under `@real-router/browser-plugin`, replace transitions now preserve scroll position and programmatic reloads restore from `sessionStorage` (portable via `state.transition.replace` / `state.transition.reload`). See [Scroll Restoration guide](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) for the full behaviour matrix.
389
389
 
390
+ ## Scroll Spy
391
+
392
+ Opt-in router-coordinated `IntersectionObserver` scroll spy — the URL hash tracks the topmost visible anchor as the user scrolls, syncing `state.context.url.hash` so sibling `<Link hash>` highlights stay current:
393
+
394
+ ```tsx
395
+ <RouterProvider
396
+ router={router}
397
+ scrollSpy={{ selector: "[id]:is(h2,h3)" }}
398
+ >
399
+ {/* Your app */}
400
+ </RouterProvider>
401
+ ```
402
+
403
+ Emits a forced same-route transition with `{ hash, replace: true, force: true, hashChange: true }` — the same write API as `<Link hash>` (#532), just with `replace: true` so the spy doesn't pollute history. Anti-flicker gates: `isTransitioning` (skip emits during transitions), `coolingDown` (skip emits during smooth `scrollIntoView` after a `<Link hash>` click; cleared on `scrollend` or 500 ms timeout), and `selfEmitting` (spy doesn't rate-limit itself). Hardcoded internals: `IntersectionObserver.threshold = 0`, rAF + 150 ms trailing debounce, MutationObserver re-observe debounced 250 ms.
404
+
405
+ Options: `{ selector: string, rootMargin?: string, scrollContainer?: () => HTMLElement | null }`. Default `rootMargin`: `"-20% 0px -60% 0px"`. Empty `selector` / `undefined` = off. SSR / browsers without `IntersectionObserver` = NOOP. Requires `browser-plugin` or `navigation-plugin` (hash-plugin / memory-plugin → warn-once + NOOP).
406
+
407
+ Behaviour is identical to the React adapter — see the [React Scroll Spy demo](../../examples/web/react/hash-examples/scroll-spy/) (12 sections, TOC sidebar, 10 e2e scenarios) and the [Scroll Spy guide](https://github.com/greydragon888/real-router/wiki/Scroll-Spy).
408
+
390
409
  ## View Transitions
391
410
 
392
411
  Opt-in animated route transitions via the browser's [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API):
@@ -403,7 +422,7 @@ No-op on unsupported browsers (Firefox as of 2026-04, SSR). Customization is pur
403
422
 
404
423
  Full documentation: [Wiki](https://github.com/greydragon888/real-router/wiki)
405
424
 
406
- - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [Scroll Restoration](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) · [View Transitions](https://github.com/greydragon888/real-router/wiki/View-Transitions)
425
+ - [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [RouterErrorBoundary](https://github.com/greydragon888/real-router/wiki/RouterErrorBoundary) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [Scroll Restoration](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration) · [Scroll Spy](https://github.com/greydragon888/real-router/wiki/Scroll-Spy) · [View Transitions](https://github.com/greydragon888/real-router/wiki/View-Transitions)
407
426
  - [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator) · [useRouteUtils](https://github.com/greydragon888/real-router/wiki/useRouteUtils) · [useRouterTransition](https://github.com/greydragon888/real-router/wiki/useRouterTransition) · [useRouteExit](https://github.com/greydragon888/real-router/wiki/useRouteExit) · [useRouteEnter](https://github.com/greydragon888/real-router/wiki/useRouteEnter)
408
427
 
409
428
  ## Examples
@@ -372,12 +372,73 @@ interface ScrollRestorationOptions {
372
372
  storageKey?: string | undefined;
373
373
  }
374
374
  //#endregion
375
+ //#region ../../shared/dom-utils/scroll-spy.d.ts
376
+ /**
377
+ * Router-coordinated scroll spy (#575).
378
+ *
379
+ * On `IntersectionObserver` notifications the utility picks the topmost
380
+ * visible anchor inside the configured scroll container and emits a forced
381
+ * same-route transition with `{ hash, replace: true, force: true, hashChange:
382
+ * true }` through `router.navigate(...)`. The URL plugin
383
+ * (`@real-router/browser-plugin` or `@real-router/navigation-plugin`) updates
384
+ * `state.context.url.hash` so sibling hash-aware `<Link hash>` re-highlights
385
+ * via the standard `createActiveRouteSource` pipeline.
386
+ *
387
+ * **Anti-flicker gates** (RFC §5.2):
388
+ * 1. `getTransitionSource(router).getSnapshot().isTransitioning` — skip emits
389
+ * while a transition is in-flight (re-entrant lock).
390
+ * 2. `coolingDown` — set on a user-driven hash transition (e.g. `<Link hash>`
391
+ * click + smooth `scrollIntoView`). Cleared on `scrollend` or after a
392
+ * 500ms safety timeout. Spy's own emits are excluded via the synchronous
393
+ * `selfEmitting` flag — required so the spy doesn't rate-limit itself.
394
+ *
395
+ * **Self-healing** (RFC §7.3): if the initial URL contains a hash without a
396
+ * matching `id` (e.g. `/page#nonexistent`), the first IO event emitted right
397
+ * after observe()-ing picks the topmost real anchor and corrects the URL.
398
+ *
399
+ * **Hash-only transition pipeline cost** (RFC §5.3): for same-route same-
400
+ * params hash-only navigations, `getTransitionPath` returns empty
401
+ * `toDeactivate` / `toActivate` arrays, so `runGuards` is a no-op. The only
402
+ * work is the URL plugin's `onTransitionSuccess` write and the
403
+ * `getTransitionSource` flip — cheap.
404
+ *
405
+ * **Architecture**: decomposed into 4 private subsystem closure factories
406
+ * (`createUrlPluginDetector`, `createCooldown`, `createDebouncer`,
407
+ * `createObserverPair`). The main `createScrollSpy` wires them together
408
+ * around the shared `silenced` / `destroyed` / `selfEmitting` flags and the
409
+ * `flush()` emit logic. Each subsystem owns its state + cleanup; `destroy()`
410
+ * delegates to each. See section banners below.
411
+ *
412
+ * @returns A `ScrollSpy` handle whose `destroy()` is idempotent.
413
+ */
414
+ interface ScrollSpyOptions {
415
+ /**
416
+ * CSS selector for anchor candidates. Empty string `""` or `undefined`
417
+ * disables the spy (returns a NOOP handle). Common values:
418
+ * `"[id]"`, `"[id]:is(h1,h2,h3)"`, `"section[id]"`.
419
+ */
420
+ selector: string;
421
+ /**
422
+ * `IntersectionObserver` `rootMargin`. Default
423
+ * `"-20% 0px -60% 0px"` — an anchor is considered "active" once it crosses
424
+ * into the top 20 % of the viewport (or scroll container).
425
+ */
426
+ rootMargin?: string | undefined;
427
+ /**
428
+ * Lazy getter for the scrollable container. Resolved on every event.
429
+ * `null` (or missing getter) falls back to the window viewport
430
+ * (`root: null` on the `IntersectionObserver`).
431
+ */
432
+ scrollContainer?: (() => HTMLElement | null) | undefined;
433
+ }
434
+ //#endregion
375
435
  //#region src/RouterProvider.d.ts
376
436
  interface RouteProviderProps {
377
437
  router: Router;
378
438
  children: ComponentChildren;
379
439
  announceNavigation?: boolean;
380
440
  scrollRestoration?: ScrollRestorationOptions;
441
+ scrollSpy?: ScrollSpyOptions;
381
442
  viewTransitions?: boolean;
382
443
  }
383
444
  declare const RouterProvider: FunctionComponent<RouteProviderProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/components/RouteView/types.ts","../../src/components/RouteView/components.tsx","../../src/components/RouteView/RouteView.tsx","../../src/types.ts","../../src/components/Link.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useRouter.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRouterTransition.tsx","../../src/hooks/useRouteExit.tsx","../../src/hooks/useRouteEnter.tsx","../../../../shared/dom-utils/scroll-restore.ts","../../src/RouterProvider.tsx","../../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/components.tsx","../../src/components/RouteView/RouteView.tsx","../../src/types.ts","../../src/components/Link.tsx","../../src/components/RouterErrorBoundary.tsx","../../src/hooks/useRouter.tsx","../../src/hooks/useNavigator.tsx","../../src/hooks/useRouteUtils.tsx","../../src/hooks/useRoute.tsx","../../src/hooks/useRouteNode.tsx","../../src/hooks/useRouterTransition.tsx","../../src/hooks/useRouteExit.tsx","../../src/hooks/useRouteEnter.tsx","../../../../shared/dom-utils/scroll-restore.ts","../../../../shared/dom-utils/scroll-spy.ts","../../src/RouterProvider.tsx","../../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`});const e=require(`./useRoute-B3rj5MXo.js`);let t=require(`preact/hooks`),n=require(`@real-router/core`),r=require(`@real-router/route-utils`),i=require(`preact`),a=require(`preact/compat`),o=require(`preact/jsx-runtime`),s=require(`@real-router/sources`),c=require(`@real-router/core/api`);function l(e){return null}l.displayName=`RouteView.Match`;function u(e){return null}u.displayName=`RouteView.Self`;function d(e){return null}d.displayName=`RouteView.NotFound`;function f(e,t,n){return t===``?!1:n?e===t:(0,r.startsWithSegment)(e,t)}function p(e,t){for(let n of(0,i.toChildArray)(e))(0,i.isValidElement)(n)&&(n.type===l||n.type===u||n.type===d?t.push(n):p(n.props.children,t))}function m(e,t,n){return(0,o.jsx)(i.Fragment,{children:n===void 0?e:(0,o.jsx)(a.Suspense,{fallback:n,children:e})},t)}function h(e){return e.type===d||e.type===u}function g(e,t){if(e.type===d){t.notFoundChildren=e.props.children;return}t.selfFound||=(t.selfChildren=e.props.children,t.selfFallback=e.props.fallback,!0)}function _(e,t,n,r){let{segment:i,exact:a=!1,fallback:o,children:s}=e.props,c=n?`${n}.${i}`:i;return!r&&f(t,c,a)?m(s,c,o):null}function v(e,t,r,a){if(a.selfFound&&t===r){e.push(m(a.selfChildren,`__route-view-self__`,a.selfFallback));return}t===n.UNKNOWN_ROUTE&&a.notFoundChildren!==null&&e.push((0,o.jsx)(i.Fragment,{children:a.notFoundChildren},`__route-view-not-found__`))}function y(e,t,n){let r={selfChildren:null,selfFallback:void 0,selfFound:!1,notFoundChildren:null},i=!1,a=[];for(let o of e){if(h(o)){g(o,r);continue}let e=_(o,t,n,i);e!==null&&(i=!0,a.push(e))}return i||v(a,t,n,r),{rendered:a,activeMatchFound:i}}function b(e,n,r){let[i,a]=(0,t.useState)(n);return(0,t.useEffect)(()=>{let t=()=>{a(e=>{let t=n();return Object.is(e,t)?e:t})};return t(),e(t)},[e,n]),i}const x=e.a(e.n,`useNavigator`),S=e.a(e.i,`useRouter`);function C(e){let n=S(),r=x(),i=(0,s.createRouteNodeSource)(n,e),{route:a,previousRoute:o}=b(i.subscribe,i.getSnapshot,i.getSnapshot);return(0,t.useMemo)(()=>({navigator:r,route:a,previousRoute:o}),[r,a,o])}function w({nodeName:e,children:n}){let{route:r}=C(e),i=(0,t.useMemo)(()=>{let e=[];return p(n,e),e},[n]),a=r?.name,s=(0,t.useMemo)(()=>a===void 0?[]:y(i,a,e).rendered,[i,a,e]);return s.length>0?(0,o.jsx)(o.Fragment,{children:s}):null}w.displayName=`RouteView`;const T=Object.assign(w,{Match:l,Self:u,NotFound:d}),E=Object.freeze({}),D=Object.freeze({}),O=`data-real-router-announcer`,k=Object.freeze({destroy:()=>{}});function ee(e,t){if(typeof document>`u`)return k;let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=te(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),M(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=j(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),A()}}}function te(){let e=document.querySelector(`[${O}]`);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(O,``),(document.body??document.documentElement).prepend(t),t}function A(){document.querySelector(`[${O}]`)?.remove()}function j(e,t,n,r){if(n)try{let t=n(e);if(t)return t}catch(e){console.error(`[real-router] getAnnouncementText threw; falling back to default resolution.`,e)}let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function M(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const N=Object.freeze({destroy:()=>{}});function P(e,t){if(globalThis.window===void 0)return N;let n=t?.mode??`restore`;if(n===`native`)return N;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s,c=()=>{if(s!==void 0)return s;try{let e=sessionStorage.getItem(o);s=e?JSON.parse(e):{}}catch{s={}}return s},l=(e,t)=>{try{let n=c();if(n[e]===t)return;n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},u=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let d=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},f=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},p=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}f(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}f(0)},m=!1,h=!1,g=e=>{try{return I(e)}catch{return h||(h=!0,console.error(`[real-router] scroll-restore: route "${e.name}" has params that cannot be canonicalized (e.g. BigInt or cyclic structure). Scroll position will not be captured or restored for this route.`)),null}},_=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;if(t){let e=g(t);e!==null&&l(e,d())}requestAnimationFrame(()=>{if(!m){if(n===`top`){p(e);return}if(!(e.transition.replace||r?.navigationType===`replace`)){if(e.transition.reload||r?.navigationType===`reload`){let t=g(e);f(t===null?0:c()[t]??0);return}if(r?.direction===`back`||r?.navigationType===`traverse`){let t=g(e);f(t===null?0:c()[t]??0);return}p(e)}}})}),v=()=>{let t=e.getState();if(t){let e=g(t);e!==null&&l(e,d())}};return globalThis.addEventListener(`pagehide`,v),{destroy:()=>{if(!m){m=!0,_(),globalThis.removeEventListener(`pagehide`,v);try{history.scrollRestoration=u}catch{}}}}}const F=new WeakMap;function I(e){let t=F.get(e);if(t!==void 0)return t;let n=`${e.name}:${L(e.params)}`;return F.set(e,n),n}function L(e){return JSON.stringify(e,R)}function R(e,t){if(typeof t==`function`)return`<fn>`;if(typeof t==`symbol`)return`<sym>`;if(typeof t==`object`&&t&&!Array.isArray(t)){let e=Object.create(null),n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const z=Object.freeze({destroy:()=>{}});function B(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return z;let t=null,n=null,r=!1,i=()=>{t?.(),t=null},a=e.subscribeLeave(({signal:e})=>{if(!e.aborted)return r=!1,i(),new Promise(a=>{let o=new Promise(e=>{t=e});e.addEventListener(`abort`,()=>{r||(i(),n?.skipTransition?.(),a())},{once:!0});try{n=document.startViewTransition(()=>(a(),o))}catch{i(),a()}})}),o=e.subscribe(()=>{let e=t;r=!0,t=null,e===null?n=null:setTimeout(()=>{e(),n=null},0)});return{destroy:()=>{a(),o(),n?.skipTransition?.(),n=null,i()}}}function V(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}const H=/%[\dA-Fa-f]{2}/;function U(e){if(H.test(e))try{return encodeURI(decodeURIComponent(e)).replaceAll(`#`,`%23`)}catch{}return encodeURI(e).replaceAll(`#`,`%23`)}function W(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(typeof e==`string`&&e.length>0)return e}let s=e.buildPath(t,n);if(typeof s!=`string`||s.length===0){console.error(`[real-router] Route "${t}" yielded an empty path. The element will render without an href attribute.`);return}return a?`${s}#${U(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function G(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&X(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}const K=/\s/,q=/\S+/g;function J(e){return e?K.test(e)?e.match(q)??[]:[e]:[]}function Y(e,t,n){if(e&&t){let e=J(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=J(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 X(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],i[e]))return!1;return!0}function Z(e,n,r=!1,i=!0,a){let o=S(),c=(0,t.useMemo)(()=>a===void 0?{strict:r,ignoreQueryParams:i}:{strict:r,ignoreQueryParams:i,hash:a},[r,i,a]),l=(0,t.useMemo)(()=>(0,s.createActiveRouteSource)(o,e,n,c),[o,e,n,c]);return b(l.subscribe,l.getSnapshot,l.getSnapshot)}function ne(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&e.hash===t.hash&&X(e.routeParams,t.routeParams)&&X(e.routeOptions,t.routeOptions)}const Q=(0,a.memo)(({routeName:e,routeParams:t=E,routeOptions:n=D,className:r,activeClassName:i=`active`,activeStrict:a=!1,ignoreQueryParams:s=!0,hash:c,onClick:l,target:u,children:d,...f})=>{let p=S(),m=Z(e,t,a,s,c),h=W(p,e,t,c===void 0?void 0:{hash:c}),g=r=>{l&&(l(r),r.defaultPrevented)||!V(r)||u===`_blank`||(r.preventDefault(),G(p,e,t,c,n).catch(()=>{}))},_=Y(m,i,r);return(0,o.jsx)(`a`,{...f,href:h,className:_,onClick:g,children:d})},ne);Q.displayName=`Link`;function re({children:e,fallback:n,onError:r}){let a=(0,s.createDismissableError)(S()),c=b(a.subscribe,a.getSnapshot,a.getSnapshot),l=(0,t.useRef)(r);return(0,t.useLayoutEffect)(()=>{l.current=r}),(0,t.useEffect)(()=>{c.error&&l.current?.(c.error,c.toRoute,c.fromRoute)},[c.version]),(0,o.jsxs)(i.Fragment,{children:[e,c.error?n(c.error,c.resetError):null]})}const $=()=>(0,r.getRouteUtils)((0,c.getPluginApi)(S()).getTree());function ie(){let e=(0,s.getTransitionSource)(S());return b(e.subscribe,e.getSnapshot,e.getSnapshot)}function ae(e,n){let r=S(),i=(0,t.useRef)(e),a=n?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{i.current=e}),(0,t.useEffect)(()=>r.subscribeLeave(({route:e,nextRoute:t,signal:n})=>{if(!(a&&e.name===t.name)&&!n.aborted)return i.current({route:e,nextRoute:t,signal:n})}),[r,a])}function oe(n,r){let{route:i,previousRoute:a}=e.t(),o=(0,t.useRef)(n),s=(0,t.useRef)(null),c=r?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{o.current=n}),(0,t.useEffect)(()=>{i.transition.from&&(c&&i.transition.from===i.name||s.current===i||!a||(s.current=i,o.current({route:i,previousRoute:a})))},[i,a,c])}const se=({router:r,children:i,announceNavigation:a,scrollRestoration:c,viewTransitions:l})=>{(0,t.useEffect)(()=>{if(!a)return;let e=ee(r);return()=>{e.destroy()}},[a,r]);let u=c?.mode,d=c?.anchorScrolling,f=c?.behavior,p=c?.storageKey,m=c!==void 0;(0,t.useEffect)(()=>{if(!m)return;let e=P(r,{mode:u,anchorScrolling:d,behavior:f,storageKey:p,scrollContainer:c.scrollContainer});return()=>{e.destroy()}},[r,m,u,d,f,p]),(0,t.useEffect)(()=>{if(!l)return;let e=B(r);return()=>{e.destroy()}},[r,l]);let h=(0,n.getNavigator)(r),g=(0,t.useMemo)(()=>(0,s.createRouteSource)(r),[r]),{route:_,previousRoute:v}=b(g.subscribe,g.getSnapshot,g.getSnapshot),y=(0,t.useMemo)(()=>({navigator:h,route:_,previousRoute:v}),[h,_,v]);return(0,o.jsx)(e.i.Provider,{value:r,children:(0,o.jsx)(e.n.Provider,{value:h,children:(0,o.jsx)(e.r.Provider,{value:y,children:i})})})};exports.Link=Q,exports.NavigatorContext=e.n,exports.RouteContext=e.r,exports.RouteView=T,exports.RouterContext=e.i,exports.RouterErrorBoundary=re,exports.RouterProvider=se,exports.useNavigator=x,exports.useRoute=e.t,exports.useRouteEnter=oe,exports.useRouteExit=ae,exports.useRouteNode=C,exports.useRouteUtils=$,exports.useRouter=S,exports.useRouterTransition=ie;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./useRoute-B3rj5MXo.js`);let t=require(`preact/hooks`),n=require(`@real-router/core`),r=require(`@real-router/route-utils`),i=require(`preact`),a=require(`preact/compat`),o=require(`preact/jsx-runtime`),s=require(`@real-router/sources`),c=require(`@real-router/core/api`);function l(e){return null}l.displayName=`RouteView.Match`;function u(e){return null}u.displayName=`RouteView.Self`;function d(e){return null}d.displayName=`RouteView.NotFound`;function f(e,t,n){return t===``?!1:n?e===t:(0,r.startsWithSegment)(e,t)}function p(e,t){for(let n of(0,i.toChildArray)(e))(0,i.isValidElement)(n)&&(n.type===l||n.type===u||n.type===d?t.push(n):p(n.props.children,t))}function m(e,t,n){return(0,o.jsx)(i.Fragment,{children:n===void 0?e:(0,o.jsx)(a.Suspense,{fallback:n,children:e})},t)}function h(e){return e.type===d||e.type===u}function g(e,t){if(e.type===d){t.notFoundChildren=e.props.children;return}t.selfFound||=(t.selfChildren=e.props.children,t.selfFallback=e.props.fallback,!0)}function _(e,t,n,r){let{segment:i,exact:a=!1,fallback:o,children:s}=e.props,c=n?`${n}.${i}`:i;return!r&&f(t,c,a)?m(s,c,o):null}function v(e,t,r,a){if(a.selfFound&&t===r){e.push(m(a.selfChildren,`__route-view-self__`,a.selfFallback));return}t===n.UNKNOWN_ROUTE&&a.notFoundChildren!==null&&e.push((0,o.jsx)(i.Fragment,{children:a.notFoundChildren},`__route-view-not-found__`))}function y(e,t,n){let r={selfChildren:null,selfFallback:void 0,selfFound:!1,notFoundChildren:null},i=!1,a=[];for(let o of e){if(h(o)){g(o,r);continue}let e=_(o,t,n,i);e!==null&&(i=!0,a.push(e))}return i||v(a,t,n,r),{rendered:a,activeMatchFound:i}}function b(e,n,r){let[i,a]=(0,t.useState)(n);return(0,t.useEffect)(()=>{let t=()=>{a(e=>{let t=n();return Object.is(e,t)?e:t})};return t(),e(t)},[e,n]),i}const x=e.a(e.n,`useNavigator`),S=e.a(e.i,`useRouter`);function C(e){let n=S(),r=x(),i=(0,s.createRouteNodeSource)(n,e),{route:a,previousRoute:o}=b(i.subscribe,i.getSnapshot,i.getSnapshot);return(0,t.useMemo)(()=>({navigator:r,route:a,previousRoute:o}),[r,a,o])}function w({nodeName:e,children:n}){let{route:r}=C(e),i=(0,t.useMemo)(()=>{let e=[];return p(n,e),e},[n]),a=r?.name,s=(0,t.useMemo)(()=>a===void 0?[]:y(i,a,e).rendered,[i,a,e]);return s.length>0?(0,o.jsx)(o.Fragment,{children:s}):null}w.displayName=`RouteView`;const T=Object.assign(w,{Match:l,Self:u,NotFound:d}),ee=Object.freeze({}),te=Object.freeze({}),E=`data-real-router-announcer`,D=Object.freeze({destroy:()=>{}});function O(e,t){if(typeof document>`u`)return D;let n=t?.prefix??`Navigated to `,r=t?.getAnnouncementText,i=!0,a=!1,o=!1,s=``,c=null,l,u=k(),d=(e,t)=>{s=e,clearTimeout(l),u.textContent=e,l=setTimeout(()=>{u.textContent=``,s=``},7e3),ne(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=j(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),A()}}}function k(){let e=document.querySelector(`[${E}]`);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(E,``),(document.body??document.documentElement).prepend(t),t}function A(){document.querySelector(`[${E}]`)?.remove()}function j(e,t,n,r){if(n)try{let t=n(e);if(t)return t}catch(e){console.error(`[real-router] getAnnouncementText threw; falling back to default resolution.`,e)}let i=(r?.textContent??``).trim(),a=e.name.startsWith(`@@`)?``:e.name;return`${t}${i||document.title||a||globalThis.location.pathname}`}function ne(e){e&&(e.hasAttribute(`tabindex`)||e.setAttribute(`tabindex`,`-1`),e.focus({preventScroll:!0}))}const M=Object.freeze({destroy:()=>{}});function N(e,t){if(globalThis.window===void 0)return M;let n=t?.mode??`restore`;if(n===`native`)return M;let r=t?.anchorScrolling??!0,i=t?.scrollContainer,a=t?.behavior??`auto`,o=t?.storageKey??`real-router:scroll`,s,c=()=>{if(s!==void 0)return s;try{let e=sessionStorage.getItem(o);s=e?JSON.parse(e):{}}catch{s={}}return s},l=(e,t)=>{try{let n=c();if(n[e]===t)return;n[e]=t,sessionStorage.setItem(o,JSON.stringify(n))}catch{}},u=history.scrollRestoration;try{history.scrollRestoration=`manual`}catch{}let d=()=>{let e=i?.();return e?e.scrollTop:globalThis.scrollY},f=e=>{let t=i?.();t?t.scrollTo({top:e,left:0,behavior:a}):globalThis.scrollTo({top:e,left:0,behavior:a})},p=e=>{if(!i){globalThis.scrollTo({top:e,left:0,behavior:a});return}let t=0,n=()=>{if(h)return;let r=i();if(r){if(r.scrollTo({top:e,left:0,behavior:a}),a!==`smooth`&&Math.abs(r.scrollTop-e)<=1)return}else globalThis.scrollTo({top:e,left:0,behavior:a});t>=10||(t+=1,requestAnimationFrame(n))};n()},m=e=>{let t=e.context?.url?.hash;if(t!==void 0){if(r&&t.length>0){let e=document.getElementById(t);if(e){e.scrollIntoView({behavior:a});return}}f(0);return}let n=globalThis.location.hash;if(r&&n.length>1){let e;try{e=decodeURIComponent(n.slice(1))}catch{e=n.slice(1)}let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:a});return}}f(0)},h=!1,g=!1,_=e=>{try{return F(e)}catch{return g||(g=!0,console.error(`[real-router] scroll-restore: route "${e.name}" has params that cannot be canonicalized (e.g. BigInt or cyclic structure). Scroll position will not be captured or restored for this route.`)),null}},v=e.subscribe(({route:e,previousRoute:t})=>{let r=e.context.navigation;if(t){let e=_(t);e!==null&&l(e,d())}requestAnimationFrame(()=>{if(!h){if(n===`top`){m(e);return}if(e.transition.reload||r?.navigationType===`reload`){let t=_(e);p(t===null?0:c()[t]??0);return}if(r?.direction===`back`||r?.navigationType===`traverse`){let t=_(e);p(t===null?0:c()[t]??0);return}e.transition.replace||r?.navigationType===`replace`||m(e)}})}),y=()=>{let t=e.getState();if(t){let e=_(t);e!==null&&l(e,d())}};return globalThis.addEventListener(`pagehide`,y),{destroy:()=>{if(!h){h=!0,v(),globalThis.removeEventListener(`pagehide`,y);try{history.scrollRestoration=u}catch{}}}}}const P=new WeakMap;function F(e){let t=P.get(e);if(t!==void 0)return t;let n=`${e.name}:${I(e.params)}`;return P.set(e,n),n}function I(e){return JSON.stringify(e,L)}function L(e,t){if(typeof t==`function`)return`<fn>`;if(typeof t==`symbol`)return`<sym>`;if(typeof t==`object`&&t&&!Array.isArray(t)){let e=Object.create(null),n=Object.keys(t).sort((e,t)=>e.localeCompare(t));for(let r of n)e[r]=t[r];return e}return t}const R=Object.freeze({destroy:()=>{}}),z=e=>e.context?.url,B=e=>{let t=null,n=1/0,r=null,i=-1/0;for(let a of e){if(!a.isIntersecting)continue;let e=a.rootBounds?.top??0,o=a.boundingClientRect.top-e;o>=0?o<n&&(t=a,n=o):o>i&&(r=a,i=o)}return t??r},V=(e,t)=>{let n=null,r=e=>{let n=e.context;n&&n.url===void 0&&(console.warn(`[real-router] scroll-spy: state.context.url is not claimed. Spy requires browser-plugin or navigation-plugin. Disabling.`),t())},i=e.getState();if(i)r(i);else{let t=!1;n=e.subscribe(({route:e})=>{t||(t=!0,r(e),n?.(),n=null)})}return{destroy(){n?.(),n=null}}},H=e=>{let t=!1,n=null,r=null,i=null,a=()=>{n!==null&&(clearTimeout(n),n=null),i&&(r??globalThis).removeEventListener(`scrollend`,i),i=null,r=null,t=!1};return{get active(){return t},start(){a(),t=!0;let o=()=>{a()};i=o,r=e(),(r??globalThis).addEventListener(`scrollend`,o,{once:!0}),n=setTimeout(o,500)},destroy(){a()}}},U=(e,t)=>{let n=null,r=null;return{schedule(){n===null&&(n=requestAnimationFrame(()=>{n=null,r!==null&&clearTimeout(r),r=setTimeout(()=>{r=null,e()},t)}))},destroy(){n!==null&&(cancelAnimationFrame(n),n=null),r!==null&&(clearTimeout(r),r=null)}}},W=(e,t,n,r,i,a)=>{let o=new Set,s=new Map,c=!1,l=null,u=new IntersectionObserver(e=>{if(!a()){for(let t of e)s.set(t.target,t);r()}},{root:n(),rootMargin:t,threshold:0}),d=()=>{let t=n()??document,r;try{r=t.querySelectorAll(e)}catch{i();return}let a=new Set;for(let e of r){let t=e.id;t&&!c&&(a.has(t)&&(c=!0,console.warn(`[real-router] scroll-spy: duplicate id "${t}" observed. Selection picks the topmost visible match deterministically.`)),a.add(t)),!o.has(e)&&(u.observe(e),o.add(e))}},f=()=>{for(let e of o)e.isConnected||(u.unobserve(e),o.delete(e),s.delete(e));d()};d();let p=n()??document.body,m=new MutationObserver(()=>{l!==null&&clearTimeout(l),l=setTimeout(()=>{l=null,f()},250)});return m.observe(p,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`id`]}),{pending:s,destroy(){u.disconnect(),m.disconnect(),l!==null&&(clearTimeout(l),l=null),o.clear(),s.clear()}}};function G(e,t){if(typeof document>`u`||typeof IntersectionObserver>`u`)return R;let{selector:n}=t;if(!n)return R;let r=t.rootMargin??`-20% 0px -60% 0px`,i=t.scrollContainer,a=()=>i?.()??null,o=!1,c=!1,l=!1,u=()=>c||o,d=null,f=(0,s.getTransitionSource)(e),p=V(e,()=>{c=!0}),m=H(a),h=U(()=>{d?.()},150),g=W(n,r,a,()=>{h.schedule()},()=>{c||(c=!0,console.warn(`[real-router] scroll-spy: invalid selector "${n}". Disabling.`))},u);d=()=>{if(o||c){g.pending.clear();return}if(f.getSnapshot().isTransitioning||m.active||g.pending.size===0)return;let t=B(g.pending.values());if(g.pending.clear(),!t)return;let n=t.target.id;if(!n)return;let r=e.getState();if(!r||n===(z(r)?.hash??``))return;let i={hash:n,replace:!0,force:!0,hashChange:!0};l=!0,e.navigate(r.name,r.params,i).catch(()=>{}).finally(()=>{l=!1})};let _=e.subscribe(({route:e})=>{l||z(e)?.hashChanged&&m.start()});return{destroy(){o||(o=!0,_(),g.destroy(),h.destroy(),m.destroy(),p.destroy())}}}const K=Object.freeze({destroy:()=>{}});function re(e){if(typeof document>`u`||typeof document.startViewTransition!=`function`)return K;let t=null,n=null,r=!1,i=()=>{t?.(),t=null},a=e.subscribeLeave(({signal:e})=>{if(!e.aborted)return r=!1,i(),new Promise(a=>{let o=new Promise(e=>{t=e});e.addEventListener(`abort`,()=>{r||(i(),n?.skipTransition?.(),a())},{once:!0});try{n=document.startViewTransition(()=>(a(),o))}catch{i(),a()}})}),o=e.subscribe(()=>{let e=t;r=!0,t=null,e===null?n=null:setTimeout(()=>{e(),n=null},0)});return{destroy:()=>{a(),o(),n?.skipTransition?.(),n=null,i()}}}function q(e){return e.button===0&&!e.metaKey&&!e.altKey&&!e.ctrlKey&&!e.shiftKey}const J=/%[\dA-Fa-f]{2}/;function Y(e){if(J.test(e))try{return encodeURI(decodeURIComponent(e)).replaceAll(`#`,`%23`)}catch{}return encodeURI(e).replaceAll(`#`,`%23`)}function X(e,t,n,r){try{let i=r?.hash,a;i!==void 0&&(a=i.startsWith(`#`)?i.slice(1):i);let o=e.buildUrl;if(o){let e=o(t,n,a===void 0?void 0:{hash:a});if(typeof e==`string`&&e.length>0)return e}let s=e.buildPath(t,n);if(typeof s!=`string`||s.length===0){console.error(`[real-router] Route "${t}" yielded an empty path. The element will render without an href attribute.`);return}return a?`${s}#${Y(a)}`:s}catch{console.error(`[real-router] Route "${t}" is not defined. The element will render without an href attribute.`);return}}function ie(e,t,n,r,i){let a={...i};r!==void 0&&(a.hash=r);let o=e.getState();if(o?.name===t&&Q(o.params,n)){let e=o.context?.url?.hash??``;e!==(r??e)&&(a.force=!0,a.hashChange=!0)}return e.navigate(t,n,a)}const ae=/\s/,oe=/\S+/g;function Z(e){return e?ae.test(e)?e.match(oe)??[]:[e]:[]}function se(e,t,n){if(e&&t){let e=Z(t);if(e.length===0)return n??void 0;if(!n)return e.join(` `);let r=Z(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 Q(e,t){if(Object.is(e,t))return!0;if(!e||!t)return!1;let n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;let r=e,i=t;for(let e of n)if(!Object.prototype.hasOwnProperty.call(t,e)||!Object.is(r[e],i[e]))return!1;return!0}function ce(e,n,r=!1,i=!0,a){let o=S(),c=(0,t.useMemo)(()=>a===void 0?{strict:r,ignoreQueryParams:i}:{strict:r,ignoreQueryParams:i,hash:a},[r,i,a]),l=(0,t.useMemo)(()=>(0,s.createActiveRouteSource)(o,e,n,c),[o,e,n,c]);return b(l.subscribe,l.getSnapshot,l.getSnapshot)}function le(e,t){return e.routeName===t.routeName&&e.className===t.className&&e.activeClassName===t.activeClassName&&e.activeStrict===t.activeStrict&&e.ignoreQueryParams===t.ignoreQueryParams&&e.onClick===t.onClick&&e.target===t.target&&e.style===t.style&&e.children===t.children&&e.hash===t.hash&&Q(e.routeParams,t.routeParams)&&Q(e.routeOptions,t.routeOptions)}const $=(0,a.memo)(({routeName:e,routeParams:t=ee,routeOptions:n=te,className:r,activeClassName:i=`active`,activeStrict:a=!1,ignoreQueryParams:s=!0,hash:c,onClick:l,target:u,children:d,...f})=>{let p=S(),m=ce(e,t,a,s,c),h=X(p,e,t,c===void 0?void 0:{hash:c}),g=r=>{l&&(l(r),r.defaultPrevented)||!q(r)||u===`_blank`||(r.preventDefault(),ie(p,e,t,c,n).catch(()=>{}))},_=se(m,i,r);return(0,o.jsx)(`a`,{...f,href:h,className:_,onClick:g,children:d})},le);$.displayName=`Link`;function ue({children:e,fallback:n,onError:r}){let a=(0,s.createDismissableError)(S()),c=b(a.subscribe,a.getSnapshot,a.getSnapshot),l=(0,t.useRef)(r);return(0,t.useLayoutEffect)(()=>{l.current=r}),(0,t.useEffect)(()=>{c.error&&l.current?.(c.error,c.toRoute,c.fromRoute)},[c.version]),(0,o.jsxs)(i.Fragment,{children:[e,c.error?n(c.error,c.resetError):null]})}const de=()=>(0,r.getRouteUtils)((0,c.getPluginApi)(S()).getTree());function fe(){let e=(0,s.getTransitionSource)(S());return b(e.subscribe,e.getSnapshot,e.getSnapshot)}function pe(e,n){let r=S(),i=(0,t.useRef)(e),a=n?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{i.current=e}),(0,t.useEffect)(()=>r.subscribeLeave(({route:e,nextRoute:t,signal:n})=>{if(!(a&&e.name===t.name)&&!n.aborted)return i.current({route:e,nextRoute:t,signal:n})}),[r,a])}function me(n,r){let{route:i,previousRoute:a}=e.t(),o=(0,t.useRef)(n),s=(0,t.useRef)(null),c=r?.skipSameRoute??!0;(0,t.useLayoutEffect)(()=>{o.current=n}),(0,t.useEffect)(()=>{i.transition.from&&(c&&i.transition.from===i.name||s.current===i||!a||(s.current=i,o.current({route:i,previousRoute:a})))},[i,a,c])}const he=({router:r,children:i,announceNavigation:a,scrollRestoration:c,scrollSpy:l,viewTransitions:u})=>{(0,t.useEffect)(()=>{if(!a)return;let e=O(r);return()=>{e.destroy()}},[a,r]);let d=c?.mode,f=c?.anchorScrolling,p=c?.behavior,m=c?.storageKey,h=c!==void 0;(0,t.useEffect)(()=>{if(!h)return;let e=N(r,{mode:d,anchorScrolling:f,behavior:p,storageKey:m,scrollContainer:c.scrollContainer});return()=>{e.destroy()}},[r,h,d,f,p,m]);let g=l?.selector,_=l?.rootMargin,v=l!==void 0&&g!==void 0&&g!==``;(0,t.useEffect)(()=>{if(!v)return;let e=G(r,{selector:g,rootMargin:_,scrollContainer:l.scrollContainer});return()=>{e.destroy()}},[r,v,g,_]),(0,t.useEffect)(()=>{if(!u)return;let e=re(r);return()=>{e.destroy()}},[r,u]);let y=(0,n.getNavigator)(r),x=(0,t.useMemo)(()=>(0,s.createRouteSource)(r),[r]),{route:S,previousRoute:C}=b(x.subscribe,x.getSnapshot,x.getSnapshot),w=(0,t.useMemo)(()=>({navigator:y,route:S,previousRoute:C}),[y,S,C]);return(0,o.jsx)(e.i.Provider,{value:r,children:(0,o.jsx)(e.n.Provider,{value:y,children:(0,o.jsx)(e.r.Provider,{value:w,children:i})})})};exports.Link=$,exports.NavigatorContext=e.n,exports.RouteContext=e.r,exports.RouteView=T,exports.RouterContext=e.i,exports.RouterErrorBoundary=ue,exports.RouterProvider=he,exports.useNavigator=x,exports.useRoute=e.t,exports.useRouteEnter=me,exports.useRouteExit=pe,exports.useRouteNode=C,exports.useRouteUtils=de,exports.useRouter=S,exports.useRouterTransition=fe;
2
2
  //# sourceMappingURL=index.js.map