@dotvoid/stacked-router 1.0.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.
Files changed (62) hide show
  1. package/README.md +594 -0
  2. package/dist/components/DefaultLayout.d.ts +4 -0
  3. package/dist/components/DefaultLayout.d.ts.map +1 -0
  4. package/dist/components/ErrorBoundary.d.ts +22 -0
  5. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  6. package/dist/components/ErrorResolver.d.ts +9 -0
  7. package/dist/components/ErrorResolver.d.ts.map +1 -0
  8. package/dist/components/Link.d.ts +29 -0
  9. package/dist/components/Link.d.ts.map +1 -0
  10. package/dist/components/Slots.d.ts +14 -0
  11. package/dist/components/Slots.d.ts.map +1 -0
  12. package/dist/components/StackedView.d.ts +6 -0
  13. package/dist/components/StackedView.d.ts.map +1 -0
  14. package/dist/components/StackedViewGroup.d.ts +6 -0
  15. package/dist/components/StackedViewGroup.d.ts.map +1 -0
  16. package/dist/components/VoidViews.d.ts +6 -0
  17. package/dist/components/VoidViews.d.ts.map +1 -0
  18. package/dist/contexts/RouterContext.d.ts +27 -0
  19. package/dist/contexts/RouterContext.d.ts.map +1 -0
  20. package/dist/contexts/RouterProvider.d.ts +11 -0
  21. package/dist/contexts/RouterProvider.d.ts.map +1 -0
  22. package/dist/contexts/SlotContext.d.ts +6 -0
  23. package/dist/contexts/SlotContext.d.ts.map +1 -0
  24. package/dist/contexts/SlotProvider.d.ts +4 -0
  25. package/dist/contexts/SlotProvider.d.ts.map +1 -0
  26. package/dist/contexts/ViewContext.d.ts +17 -0
  27. package/dist/contexts/ViewContext.d.ts.map +1 -0
  28. package/dist/contexts/ViewProvider.d.ts +10 -0
  29. package/dist/contexts/ViewProvider.d.ts.map +1 -0
  30. package/dist/hooks/useHref.d.ts +14 -0
  31. package/dist/hooks/useHref.d.ts.map +1 -0
  32. package/dist/hooks/useNavigate.d.ts +19 -0
  33. package/dist/hooks/useNavigate.d.ts.map +1 -0
  34. package/dist/hooks/useOpenViews.d.ts +25 -0
  35. package/dist/hooks/useOpenViews.d.ts.map +1 -0
  36. package/dist/hooks/usePrevious.d.ts +2 -0
  37. package/dist/hooks/usePrevious.d.ts.map +1 -0
  38. package/dist/hooks/useRouter.d.ts +2 -0
  39. package/dist/hooks/useRouter.d.ts.map +1 -0
  40. package/dist/hooks/useView.d.ts +2 -0
  41. package/dist/hooks/useView.d.ts.map +1 -0
  42. package/dist/hooks/useViewStack.d.ts +18 -0
  43. package/dist/hooks/useViewStack.d.ts.map +1 -0
  44. package/dist/index.es.js +1112 -0
  45. package/dist/index.umd.js +22 -0
  46. package/dist/lib/RouterRegistry.d.ts +57 -0
  47. package/dist/lib/RouterRegistry.d.ts.map +1 -0
  48. package/dist/lib/allocation.d.ts +23 -0
  49. package/dist/lib/allocation.d.ts.map +1 -0
  50. package/dist/lib/events.d.ts +4 -0
  51. package/dist/lib/events.d.ts.map +1 -0
  52. package/dist/lib/history.d.ts +34 -0
  53. package/dist/lib/history.d.ts.map +1 -0
  54. package/dist/lib/href.d.ts +23 -0
  55. package/dist/lib/href.d.ts.map +1 -0
  56. package/dist/lib/mapRoutes.d.ts +6 -0
  57. package/dist/lib/mapRoutes.d.ts.map +1 -0
  58. package/dist/lib/viewsAreEqual.d.ts +8 -0
  59. package/dist/lib/viewsAreEqual.d.ts.map +1 -0
  60. package/dist/main.d.ts +13 -0
  61. package/dist/main.d.ts.map +1 -0
  62. package/package.json +63 -0
@@ -0,0 +1,22 @@
1
+ (function(x,p){typeof exports=="object"&&typeof module<"u"?p(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],p):(x=typeof globalThis<"u"?globalThis:x||self,p(x.Textbit={},x.React))})(this,(function(x,p){"use strict";var N={exports:{}},V={};/**
2
+ * @license React
3
+ * react-jsx-runtime.production.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */var Q;function we(){if(Q)return V;Q=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(r,o,s){var i=null;if(s!==void 0&&(i=""+s),o.key!==void 0&&(i=""+o.key),"key"in o){s={};for(var c in o)c!=="key"&&(s[c]=o[c])}else s=o;return o=s.ref,{$$typeof:t,type:r,key:i,ref:o!==void 0?o:null,props:s}}return V.Fragment=e,V.jsx=n,V.jsxs=n,V}var C={};/**
10
+ * @license React
11
+ * react-jsx-runtime.development.js
12
+ *
13
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ */var Z;function ge(){return Z||(Z=1,process.env.NODE_ENV!=="production"&&(function(){function t(a){if(a==null)return null;if(typeof a=="function")return a.$$typeof===et?null:a.displayName||a.name||null;if(typeof a=="string")return a;switch(a){case v:return"Fragment";case P:return"Profiler";case E:return"StrictMode";case Qe:return"Suspense";case Ze:return"SuspenseList";case $e:return"Activity"}if(typeof a=="object")switch(typeof a.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),a.$$typeof){case R:return"Portal";case Xe:return(a.displayName||"Context")+".Provider";case I:return(a._context.displayName||"Context")+".Consumer";case Ke:var d=a.render;return a=a.displayName,a||(a=d.displayName||d.name||"",a=a!==""?"ForwardRef("+a+")":"ForwardRef"),a;case qe:return d=a.displayName||null,d!==null?d:t(a.type)||"Memo";case ue:d=a._payload,a=a._init;try{return t(a(d))}catch{}}return null}function e(a){return""+a}function n(a){try{e(a);var d=!1}catch{d=!0}if(d){d=console;var w=d.error,S=typeof Symbol=="function"&&Symbol.toStringTag&&a[Symbol.toStringTag]||a.constructor.name||"Object";return w.call(d,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",S),e(a)}}function r(a){if(a===v)return"<>";if(typeof a=="object"&&a!==null&&a.$$typeof===ue)return"<...>";try{var d=t(a);return d?"<"+d+">":"<...>"}catch{return"<...>"}}function o(){var a=H.A;return a===null?null:a.getOwner()}function s(){return Error("react-stack-top-frame")}function i(a){if(le.call(a,"key")){var d=Object.getOwnPropertyDescriptor(a,"key").get;if(d&&d.isReactWarning)return!1}return a.key!==void 0}function c(a,d){function w(){fe||(fe=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",d))}w.isReactWarning=!0,Object.defineProperty(a,"key",{get:w,configurable:!0})}function u(){var a=t(this.type);return de[a]||(de[a]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),a=this.props.ref,a!==void 0?a:null}function l(a,d,w,S,j,k,J,X){return w=k.ref,a={$$typeof:m,type:a,key:d,props:k,_owner:j},(w!==void 0?w:null)!==null?Object.defineProperty(a,"ref",{enumerable:!1,get:u}):Object.defineProperty(a,"ref",{enumerable:!1,value:null}),a._store={},Object.defineProperty(a._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(a,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(a,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:J}),Object.defineProperty(a,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:X}),Object.freeze&&(Object.freeze(a.props),Object.freeze(a)),a}function h(a,d,w,S,j,k,J,X){var b=d.children;if(b!==void 0)if(S)if(tt(b)){for(S=0;S<b.length;S++)g(b[S]);Object.freeze&&Object.freeze(b)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else g(b);if(le.call(d,"key")){b=t(a);var O=Object.keys(d).filter(function(rt){return rt!=="key"});S=0<O.length?"{key: someKey, "+O.join(": ..., ")+": ...}":"{key: someKey}",me[b+S]||(O=0<O.length?"{"+O.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
18
+ let props = %s;
19
+ <%s {...props} />
20
+ React keys must be passed directly to JSX without using spread:
21
+ let props = %s;
22
+ <%s key={someKey} {...props} />`,S,b,O,b),me[b+S]=!0)}if(b=null,w!==void 0&&(n(w),b=""+w),i(d)&&(n(d.key),b=""+d.key),"key"in d){w={};for(var K in d)K!=="key"&&(w[K]=d[K])}else w=d;return b&&c(w,typeof a=="function"?a.displayName||a.name||"Unknown":a),l(a,b,k,j,o(),w,J,X)}function g(a){typeof a=="object"&&a!==null&&a.$$typeof===m&&a._store&&(a._store.validated=1)}var y=p,m=Symbol.for("react.transitional.element"),R=Symbol.for("react.portal"),v=Symbol.for("react.fragment"),E=Symbol.for("react.strict_mode"),P=Symbol.for("react.profiler"),I=Symbol.for("react.consumer"),Xe=Symbol.for("react.context"),Ke=Symbol.for("react.forward_ref"),Qe=Symbol.for("react.suspense"),Ze=Symbol.for("react.suspense_list"),qe=Symbol.for("react.memo"),ue=Symbol.for("react.lazy"),$e=Symbol.for("react.activity"),et=Symbol.for("react.client.reference"),H=y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,le=Object.prototype.hasOwnProperty,tt=Array.isArray,G=console.createTask?console.createTask:function(){return null};y={react_stack_bottom_frame:function(a){return a()}};var fe,de={},pe=y.react_stack_bottom_frame.bind(y,s)(),he=G(r(s)),me={};C.Fragment=v,C.jsx=function(a,d,w,S,j){var k=1e4>H.recentlyCreatedOwnerStacks++;return h(a,d,w,!1,S,j,k?Error("react-stack-top-frame"):pe,k?G(r(a)):he)},C.jsxs=function(a,d,w,S,j){var k=1e4>H.recentlyCreatedOwnerStacks++;return h(a,d,w,!0,S,j,k?Error("react-stack-top-frame"):pe,k?G(r(a)):he)}})()),C}var q;function ye(){return q||(q=1,process.env.NODE_ENV==="production"?N.exports=we():N.exports=ge()),N.exports}var f=ye();const $=p.createContext({trigger:"init",state:{id:"",views:[]},navigate:()=>{},close:()=>{}});function W(t,...e){t&&t.addEventListener&&t.addEventListener(...e)}function U(t,...e){t&&t.removeEventListener&&t.removeEventListener(...e)}function ee(t,e){window.dispatchEvent(new CustomEvent(t,{detail:e}))}function M(t="",e={}){const n=new URL(t,"http://dummy.base"),r={...Object.fromEntries(n.searchParams.entries()),...e},o=new URLSearchParams(Object.entries(r).map(([u,l])=>[u,String(l)])).toString(),i=t.startsWith("http://")||t.startsWith("https://")?n.origin+n.pathname:n.pathname,c=i.endsWith("/")&&i.length>1?i.slice(0,-1):i;return{url:o?`${c}?${o}`:c,path:n.pathname,queryParams:r}}function ve(t){const e={};for(const[n,r]of new URLSearchParams(t))r==="true"?e[n]=!0:r==="false"?e[n]=!1:Ee(r)?e[n]=r.includes(".")?parseFloat(r):parseInt(r,10):e[n]=r;return e}function Ee(t){return isNaN(+t)?!1:parseInt(t).toString()===t||parseFloat(t).toString()===t}const xe=t=>{try{return new URL(t,window.location.origin).origin!==window.location.origin}catch{return!1}};function A(){const{state:t,length:e}=window.history,{href:n}=window.location;return{state:_e(t)?t:Se(n),length:e}}function D(t,e){history.pushState(e,"",t),ee("pushstate",e)}function _(t,e){history.replaceState(e,"",t),ee("replacestate",e)}function Re(t){const{id:e,views:n}=A().state;if(e===t)return;const r=n.find(o=>o.id===t);r&&_(r.url,{id:r.id,views:n})}function Se(t){const e=crypto.randomUUID(),n=new URL(t),r={id:e,views:[{id:e,url:t,queryParams:ve(n.search),props:{}}]};return _(t,r),r}function be(t,e){const{state:n}=A(),r={...n};let o=-1;for(let s=0;s<r.views.length;s++)if(r.views[s].id===t){te(r.views[s].queryParams,e)||(r.views[s].queryParams=e,o=s);break}if(o>-1){const s=new URL(window.location.href);s.search=new URLSearchParams(Object.entries(e).map(([i,c])=>[i,String(c)])).toString(),r.views[o].url=s.toString(),_(s.toString(),r)}}function ke(t,e){const{state:n}=A(),r={...n};let o=-1;for(let s=0;s<r.views.length;s++)if(r.views[s].id===t){te(r.views[s].props,e)||(r.views[s].props=e,o=s);break}o>-1&&_(window.location.href,r)}function Pe(t,e){const n=[...e.views].filter(o=>o.id!==t),r={...e,views:n};_(n.at(-1)?.url??"",r)}function je(t,e,n,r,o,s){const i=[...o.views],c=crypto.randomUUID(),u=t.getFullPath(n),l=new URL(u,window.location.origin);Object.entries(r).forEach(([E,P])=>{l.searchParams.set(E,String(P))});const h=l.toString(),g=t.getViewComponentByPath(l.pathname),y=g?.params||{},m=i.find(E=>h===E.url);if(s.target!=="_top"&&!s.append&&m?.id===o.id)return;if(!s.append){if(s.target==="_top"){const E=m||{id:c,url:h,meta:g?.meta??void 0,params:y,queryParams:r,props:s.props,target:s?.target,layout:s?.layout};D(h,{id:E.id,views:[E]});return}if(!s.append&&m){_(h,{id:m.id,views:i});return}}if(s.append||s.target==="_void"){i.push({id:c,url:h,meta:g?.meta??void 0,params:y,queryParams:r,props:s.props,target:s?.target,layout:s?.layout}),D(h,{id:c,views:i});return}const R=i.findIndex(E=>E.id===e),v=i.slice(0,R+1);v.push({id:c,url:h,meta:g?.meta??void 0,params:y,queryParams:r,props:s.props,target:s?.target,layout:s?.layout}),D(h,{id:c,views:v})}function _e(t){return!t||typeof t!="object"?!1:"id"in t&&"views"in t&&Array.isArray(t.views)}function te(t,e){if(typeof t!=typeof e)return!1;if(typeof t>"u"||typeof e>"u")return!0;if(Object.keys(t).length!==Object.keys(e).length)return!1;for(const n in t)if(!(n in e)||t[n]!==e[n]||typeof t[n]!=typeof e[n])return!1;return!0}class Te{#e="/";#r={};#o={};#t={};constructor(e,n){this.#e=n?this.#s(n):"/",this.#o=e.layouts||{},this.#t=e.errors||{},this.registerRoutes(e.routes)}registerRoutes(e,n=!1){e.forEach(r=>{const o=[],s=r.path.replace(/\[([^\]]+)\]/g,(c,u)=>(o.push(u),"([^/]+)")),i=new RegExp(`^${s}$`);if(!r.component||!(r.component instanceof Function)||r.path[0]!=="/"){if(n)throw new Error(`Invalid component for route ${r.path||"undefined path"}`);return}this.#r[r.path]={component:r.component,pattern:i,paramKeys:o,originalPath:r.path,layouts:r.layouts?.length?r.layouts.map(c=>({component:c})):this.#a(r.path),meta:r.meta||{breakpoints:[]}}})}#s(e){return e.startsWith("/")||(e="/"+e),e.length>1&&e.endsWith("/")&&(e=e.slice(0,-1)),e}#n(e){return this.#e==="/"?e:e.startsWith(this.#e)?e.slice(this.#e.length)||"/":e}getViewComponentByPath(e){const n=this.#n(e),r=n.length>1&&n.at(-1)==="/"?n.substring(0,n.length-1):n;for(const o in this.#r){const s=this.#r[o],i=r.match(s.pattern);if(i){const c=Object.fromEntries(s.paramKeys.map((u,l)=>[u,i[l+1]]));return{Component:s.component,Layouts:s.layouts,params:c,meta:s.meta}}}return null}getErrorComponentByPath(e){const n=this.#n(e),r=n.length>1&&n.at(-1)==="/"?n.substring(0,n.length-1):n;if(this.#t[r])return this.#t[r];const o=r.split("/").filter(Boolean);for(let s=o.length;s>=1;s--){const i="/"+o.slice(0,s).join("/");if(this.#t[i])return this.#t[i]}return this.#t["/"]?this.#t["/"]:(console.log("No error component found"),null)}get basePath(){return this.#e}getFullPath(e){return this.#e==="/"?e:e==="/"?this.#e:e.startsWith(this.#e)?e:this.#e+e}getPathFromUrl(e){try{let r=new URL(e).pathname;return r=this.#n(r),r.length>1&&r.endsWith("/")&&(r=r.slice(0,-1)),r}catch{return this.#n(e)}}getAllViewComponents(){return Object.values(this.#r).map(e=>({Component:e.component,Layouts:e.layouts,meta:e.meta}))}#a(e){const n=[],r=["/",...e.match(/[^/]+/g)||[]];let o=r[0];for(let s=0;s<r.length;s++){const i=[];for(const c in this.#o){const[u,l]=c.split("#");u===o&&i.push({key:l,component:this.#o[c]})}n.push(...i),o+=r[s+1]}return n}}function Oe({basePath:t,config:e,external:n=[],children:r}){const o=p.useMemo(()=>new Te(e,t),[e,t]),[s,i]=p.useState(F("load",o));return p.useEffect(()=>{for(const c of n??[])import(c.url).then(u=>{if(!Array.isArray(u.routes))throw new Error(`Invalid routes in ${c.url}`);o.registerRoutes(u.routes,!0)}).catch(u=>{console.error(u.message)})},[n,o]),p.useEffect(()=>{t&&t!=="/"&&window.location.pathname==="/"&&window.history.replaceState(null,"",t)},[t]),p.useEffect(()=>{const c=()=>i(F("popstate",o)),u=()=>i(F("pushstate",o)),l=()=>i(F("replacestate",o));return W(window,"popstate",c),W(window,"pushstate",u),W(window,"replacestate",l),()=>{U(window,"popstate",c),U(window,"pushstate",u),U(window,"replacestate",l)}},[o]),f.jsx($.Provider,{value:{clientRouter:o,...s},children:r})}function F(t,e){const{state:n,length:r}=A(),{hash:o,host:s,hostname:i,href:c,origin:u,pathname:l,port:h,protocol:g,search:y}=window.location;return{trigger:t,state:n,length:r,hash:o,host:s,hostname:i,href:c,origin:u,pathname:l,port:h,protocol:g,search:y,navigate:(m,R,v,E)=>{je(e,m,R,v,n,E)},close:m=>{Pe(m,n)}}}function T(){const t=p.useContext($);if(t===void 0)throw new Error("useRouter must be used within a RouterProvider");return t}function Ve(t,e){if(!t||!e)return t===e;if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++){const r=t[n],o=e[n];if(r.id!==o.id||r.url!==o.url||r.layout!==o.layout||r.target!==o.target||!Y(r.params,o.params)||!Y(r.queryParams,o.queryParams)||!Y(r.props,o.props)||r.meta!==o.meta&&(!r.meta||!o.meta||r.meta.type!==o.meta.type))return!1}return!0}function Y(t,e){if(t===e)return!0;if(!t||!e)return!1;const n=Object.keys(t),r=Object.keys(e);if(n.length!==r.length)return!1;for(const o of n)if(t[o]!==e[o])return!1;return!0}function re(){const{state:t,clientRouter:e}=T()||{},n=p.useRef(void 0),r=!Ve(n.current,t.views);return p.useMemo(()=>{const s=[],i=[];return t.views.forEach(c=>{const u=new URL(c.url,"http://dummy.base"),l=e?.getViewComponentByPath(u.pathname),h=c.params||l?.params||{},g=c.meta||l?.meta,y={view:c,meta:g,Component:l?.Component,Layouts:l?.Layouts,params:h};c.target==="_void"?i.push(y):s.push(y)}),n.current=t.views,{viewStack:s,voidViews:i}},[r,e])}const ne=p.createContext({viewId:"",isActive:!1,width:0,queryParams:{},setQueryParams:()=>{},setProps:()=>{},queryParam:()=>{},close:()=>{},state:{id:"",views:[]}});function oe({id:t,width:e,layout:n,children:r,params:o,queryParams:s,props:i}){const{state:c,close:u}=T(),[l,h]=p.useState(t===c.id),[g,y]=p.useState(i||{});return p.useEffect(()=>{h(t===c.id)},[c.id,t]),f.jsx(ne.Provider,{value:{viewId:t,isActive:l,width:e,params:o,queryParams:s,props:g,layout:n,state:c,setProps:(m,R)=>{const v=R?m||{}:{...i,...m};for(const E in v)v[E]===void 0&&delete v[E];y(v),ke(t,v)},setQueryParams:(m,R)=>{const v=R!==!0?{...i||{}}:{};let E=!1;for(const P in m){const I=m[P];typeof I<"u"?(v[P]=I,E=!0):Object.prototype.hasOwnProperty.call(v,P)&&(delete v[P],E=!0)}(E||R===!0)&&be(t,v)},queryParam:m=>i?.[m],close:()=>{u(t)}},children:r})}function Ce(t,e){const n=e.filter(o=>o.view.target!=="_void").map(o=>({id:o.view.id,breakpoints:o.meta?.breakpoints||[]})),r=Ae(t,n);return e.map(({view:o})=>({id:o.id,vw:r.find(s=>s.id===o.id)?.vw||0}))}function Ae(t,e){if(e.length===0)return[];const r=e.map(i=>({id:i.id,minVw:Le(i,t)})),o=r.reduce((i,c)=>i+c.minVw,0);if(o>=100)return r.map(i=>({id:i.id,vw:i.minVw}));const s=100-o;return r.map(i=>{const c=i.minVw/o,u=s*c;return{id:i.id,vw:Number((i.minVw+u).toFixed(0))}})}function Le(t,e){const r=[...t.breakpoints].sort((o,s)=>s.breakpoint-o.breakpoint).find(o=>e>=o.breakpoint);return r?r.minVw:100}function se({children:t}){return f.jsx(f.Fragment,{children:t})}const z=p.createContext({setSlot:()=>{},getSlots:()=>({})});function ae({children:t}){const[e,n]=p.useState({}),r=p.useCallback((s,i,c)=>{n(u=>({...u,[s]:{...u[s],[i]:c}}))},[]),o=p.useCallback(s=>e[s]||{},[e]);return f.jsx(z.Provider,{value:{setSlot:r,getSlots:o},children:t})}function Ne({viewUrl:t,error:e,errorCode:n,errorInfo:r,reset:o}){const{clientRouter:s}=T(),i=s?.getErrorComponentByPath(s?.getPathFromUrl(t)??"/");return i?f.jsx(i,{error:e,errorCode:n??0,errorInfo:r,reset:o}):f.jsxs("div",{style:{margin:"10px",border:"2px solid #ff6b6b",borderRadius:"8px",backgroundColor:"#fff5f5",width:"100%",display:"flex",flexDirection:"column",alignItems:"center",padding:"20px"},children:[f.jsx("h1",{style:{color:"#c92a2a",marginBottom:"10px",fontWeight:"bold"},children:"Unhandled error"}),f.jsx("p",{style:{marginBottom:"15px",textAlign:"center"},children:e.message}),f.jsxs("details",{style:{marginBottom:"15px",width:"100%"},children:[f.jsx("summary",{style:{cursor:"pointer",marginBottom:"10px",textAlign:"center"},children:"Technical details"}),f.jsxs("div",{style:{backgroundColor:"#f8f9fa",padding:"10px",borderRadius:"4px",overflow:"auto",maxHeight:"200px"},children:[f.jsx("h4",{style:{margin:"0 0 10px 0",fontSize:"14px"},children:"Stack Trace:"}),f.jsx("pre",{style:{fontSize:"12px",margin:0,whiteSpace:"pre-wrap"},children:e.stack}),r?.componentStack&&f.jsxs(f.Fragment,{children:[f.jsx("h4",{style:{margin:"15px 0 10px 0",fontSize:"14px"},children:"Component Stack:"}),f.jsx("pre",{style:{fontSize:"12px",margin:0,whiteSpace:"pre-wrap"},children:r.componentStack})]})]})]}),f.jsx("button",{onClick:o,style:{backgroundColor:"#228be6",color:"white",border:"none",padding:"8px 16px",borderRadius:"4px",cursor:"pointer"},children:"Try again"})]})}class B extends p.Component{constructor(e){super(e),this.state={hasError:!!e.error,errorCode:e.errorCode,error:e.error}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,n){console.error(`Error in view ${this.props.viewUrl}:`,e,n),this.setState({errorInfo:n})}reset=()=>{this.setState({hasError:!1,error:void 0,errorInfo:void 0})};render(){return!this.state.hasError||!this.state.error?this.props.children:f.jsx(Ne,{viewUrl:this.props.viewUrl,error:this.state.error,errorCode:this.state.errorCode,errorInfo:this.state.errorInfo,reset:this.reset})}}function We({className:t,style:e={}}){const{viewStack:n}=re(),[r,o]=p.useState(window.innerWidth);p.useEffect(()=>{const u=()=>o(window.innerWidth);return window.addEventListener("resize",u),()=>window.removeEventListener("resize",u)},[]);const s=p.useMemo(()=>Ce(r,n),[r,n]),i=p.useMemo(()=>{let u=0,l=0;for(let h=n.length-1;h>=0;h--)if(u+=s[h]?.vw||0,u>100){l=h+1;break}return n.slice(l)},[s,n]),c=p.useMemo(()=>{const u=n.length-i.length;return i.map((l,h)=>s[h+u].vw)},[s,n.length,i]);return f.jsx(Ue,{views:i,widths:c,style:e,className:t})}function Ue({views:t,widths:e,className:n,style:r={}}){return f.jsx(ae,{children:f.jsx("div",{className:n,style:r,children:t.map(({view:o,params:s,Layouts:i,Component:c},u)=>{if(!c)return f.jsx(B,{viewUrl:o.url,errorCode:404,error:new Error("Not found")},o.id);const l=i?.length?i.filter(h=>h.key===o.layout):[{component:se}];return f.jsx(B,{viewUrl:o.url||"/",children:f.jsx(oe,{id:o.id,width:e[u],params:s,queryParams:o.queryParams,props:o.props,children:ie(l,c,s)},o.id)},o.id)})})})}function ie(t,e,n){if(t.length===0)return f.jsx(e,{...n||{}});const[r,...o]=t,s=r.component;return f.jsx(s,{children:ie(o,e,n)},r.key)}function Fe({className:t,style:e={}}){const{voidViews:n}=re();return f.jsx(Ie,{views:n,style:e,className:t})}function Ie({views:t,className:e,style:n={}}){return f.jsx(ae,{children:f.jsx("div",{className:e,style:n,children:t.map(({view:r,params:o,Layouts:s,Component:i})=>{const c=s?.length?s.filter(u=>u.key===r.layout):[{component:se}];return f.jsx(B,{viewUrl:r.url||"/",children:f.jsx(oe,{id:r.id,width:0,params:o,queryParams:r.queryParams,props:r.props,layout:r.layout,children:ce(c,i,o)},r.id)},r.id)})})})}function ce(t,e,n){if(t.length===0)return e?f.jsx(e,{...n||{}}):null;const[r,...o]=t,s=r.component;return f.jsx(s,{children:ce(o,e,n)},r.key)}function L(){const t=p.useContext(ne);if(t===void 0)throw new Error("useView must be used within a ViewProvider");return t}function Me({children:t,style:e={},className:n}){const{viewId:r}=L(),o=p.useRef(null);return p.useEffect(()=>{if(!o.current)return;const s=()=>{Re(r)},i=o.current;return W(i,"click",s),()=>U(i,"click",s)},[r,o]),f.jsx("div",{ref:o,style:e,className:n,children:t})}function De({href:t,query:e={},children:n,className:r,target:o="_self",onClick:s,props:i,layout:c}){const{navigate:u}=T(),{url:l,queryParams:h}=M(t,e),{viewId:g}=L(),y=R=>{s&&(s(R),R.isDefaultPrevented())||l.startsWith("https://")||l.startsWith("http://")||o==="_blank"||R.metaKey||R.ctrlKey||(R.preventDefault(),u(g,l,h,{append:R.shiftKey,target:o,props:i,layout:c}))},m=xe(l)?"noopener noreferrer":void 0;return f.jsx("a",{rel:m,href:l,onClick:y,className:r,target:o,children:n})}function Ye({slot:t}){const{viewId:e}=L(),{getSlots:n}=p.useContext(z),r=n(e);return f.jsx(f.Fragment,{children:r[t]})}function ze({slot:t,children:e}){const{viewId:n}=L(),{setSlot:r}=p.useContext(z);return p.useEffect(()=>(r(n,t,e),()=>r(n,t,null)),[n,t,e,r]),null}function Be(){const{navigate:t}=T();return(e,n)=>{const{state:r}=A(),{url:o,queryParams:s}=M(e);t(r.id||"",o,s,{append:!1,target:n?.target||"_self",props:n?.props,layout:n?.layout})}}function He(t){const{url:e}=M(t);return e}function Ge(t,e){const{state:n}=T();return p.useMemo(()=>{const o=[];return n.views.forEach(s=>{if(s.meta?.type===t){if(e){const i=s.params||{};if(!Object.entries(e).every(([u,l])=>i[u]===l))return}o.push({id:s.id,url:s.url,params:s.params,queryParams:s.queryParams,props:s.props,layout:s.layout,target:s.target,isActive:s.id===n.id})}}),o},[n.views,n.id,t,e])}function Je(t,e=""){const n=[],r={},o={};return Object.entries(t).forEach(([s,i])=>{let c=s.replace(e,"").replace(/\.tsx$/,"").replace(/\/index$/,"").replace(/([A-Z])/g,h=>`/${h.toLowerCase()}`).replace(/\/\//g,"/").toLowerCase()||"/";c===""||c==="index"?c="/":c&&!c.startsWith("/")&&(c="/"+c);const u=c.match(/^(.*)\/(_error)$/);if(u){const[,h]=u,g=h||"/";o[g]=i.default;return}const l=c.match(/^(.*)\/(_layout(?:\.([^/]+))?)$/);if(l){const[,h,,g]=l,y=h||"/";if(g){const m=`${y}#${g}`;r[m]=i.default}else r[y]=i.default}else c.includes("/_")||n.push({path:c,component:i.default,meta:i.default?.meta||{breakpoints:[]}})}),{routes:n,layouts:r,errors:o}}x.Fill=ze,x.Link=De,x.Outlet=Ye,x.RouterProvider=Oe,x.StackedView=Me,x.StackedViewGroup=We,x.VoidViews=Fe,x.mapRoutes=Je,x.useHref=He,x.useNavigate=Be,x.useOpenViews=Ge,x.useView=L,Object.defineProperty(x,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,57 @@
1
+ import { ErrorInfo } from 'react';
2
+ import { BreakpointWidth } from './allocation';
3
+ export interface PageComponent {
4
+ default: React.ComponentType<unknown>;
5
+ [key: string]: unknown;
6
+ }
7
+ export interface ErrorComponentProps {
8
+ error: Error;
9
+ errorCode?: number;
10
+ errorInfo?: ErrorInfo;
11
+ reset: () => void;
12
+ }
13
+ export interface ViewMetadata {
14
+ type?: string;
15
+ breakpoints?: BreakpointWidth[];
16
+ }
17
+ export interface RouteConfig {
18
+ path: string;
19
+ component: React.ComponentType<unknown>;
20
+ layouts?: React.ComponentType<React.PropsWithChildren>[];
21
+ meta?: ViewMetadata;
22
+ }
23
+ export interface RouterConfig {
24
+ routes: RouteConfig[];
25
+ layouts?: Record<string, React.ComponentType<React.PropsWithChildren>>;
26
+ errors?: Record<string, React.ComponentType<{
27
+ error: Error;
28
+ reset: () => void;
29
+ }>>;
30
+ }
31
+ export interface ParsedRouteLayout {
32
+ key?: string;
33
+ component: React.ComponentType<React.PropsWithChildren>;
34
+ }
35
+ export declare class RouterRegistry {
36
+ #private;
37
+ constructor(config: RouterConfig, basePath?: string);
38
+ registerRoutes(routes: RouteConfig[], throwErrors?: boolean): void;
39
+ getViewComponentByPath(givenPath: string): {
40
+ Component: import('react').ComponentType<unknown>;
41
+ Layouts: ParsedRouteLayout[];
42
+ params: {
43
+ [k: string]: string;
44
+ };
45
+ meta: ViewMetadata;
46
+ } | null;
47
+ getErrorComponentByPath(givenPath: string): React.ComponentType<ErrorComponentProps> | null;
48
+ get basePath(): string;
49
+ getFullPath(routePath: string): string;
50
+ getPathFromUrl(fullUrl: string): string;
51
+ getAllViewComponents(): {
52
+ Component: import('react').ComponentType<unknown>;
53
+ Layouts: ParsedRouteLayout[];
54
+ meta: ViewMetadata;
55
+ }[];
56
+ }
57
+ //# sourceMappingURL=RouterRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterRegistry.d.ts","sourceRoot":"","sources":["../../lib/lib/RouterRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IACvC,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAA;IACxD,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAC,CAAA;CAClF;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;CACxD;AAWD,qBAAa,cAAc;;gBAMb,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM;IAOnD,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,WAAW,UAAQ;IA4DzD,sBAAsB,CAAC,SAAS,EAAE,MAAM;;;;;;;;IA4BxC,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAiC3F,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAkBtC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAqBvC,oBAAoB;;;;;CAmCrB"}
@@ -0,0 +1,23 @@
1
+ import { StackedView } from '../hooks/useViewStack';
2
+ export interface BreakpointWidth {
3
+ breakpoint: number;
4
+ minVw: number;
5
+ }
6
+ export interface ViewAllocation {
7
+ id: string;
8
+ vw: number;
9
+ }
10
+ /**
11
+ * Calculates viewport width percentage allocation for each view based on current screen width.
12
+ * Ignores views that are not relevant to the current transition. (Like void targets).
13
+ *
14
+ * @param screenWidthPx Current screen width in pixels
15
+ * @param views Array of views with their breakpoint definitions
16
+ * @returns Array of view allocations with viewport width percentages
17
+ */
18
+ export declare function calculateAllocations(screenWidthPx: number, viewStack: StackedView[]): ViewAllocation[];
19
+ /**
20
+ * Utility function to generate a responsive CSS width style based on vw percentage
21
+ */
22
+ export declare function getViewWidthStyle(vw: number): React.CSSProperties;
23
+ //# sourceMappingURL=allocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allocation.d.ts","sourceRoot":"","sources":["../../lib/lib/allocation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAOD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAGD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,cAAc,EAAE,CAkBtG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAOjE"}
@@ -0,0 +1,4 @@
1
+ export declare function on<T extends Window | Document | HTMLElement | EventTarget>(obj: T | null, ...args: Parameters<T['addEventListener']>): void;
2
+ export declare function off<T extends Window | Document | HTMLElement | EventTarget>(obj: T | null, ...args: Parameters<T['removeEventListener']>): void;
3
+ export declare function emit(name: string, data: unknown): void;
4
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../lib/lib/events.ts"],"names":[],"mappings":"AAAA,wBAAgB,EAAE,CAAC,CAAC,SAAS,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,EACxE,GAAG,EAAE,CAAC,GAAG,IAAI,EACb,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,GACzC,IAAI,CAIN;AAED,wBAAgB,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,EACzE,GAAG,EAAE,CAAC,GAAG,IAAI,EACb,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,GAC5C,IAAI,CAIN;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,QAI/C"}
@@ -0,0 +1,34 @@
1
+ import { RouterRegistry, ViewMetadata } from './RouterRegistry';
2
+ export interface ViewDef {
3
+ id: string;
4
+ url: string;
5
+ meta?: ViewMetadata;
6
+ params?: Record<string, string>;
7
+ queryParams?: Record<string, string | number | boolean>;
8
+ props?: Record<string, string | number | boolean>;
9
+ layout?: string;
10
+ target?: '_self' | '_top' | '_blank' | '_void';
11
+ }
12
+ export interface ViewState {
13
+ id: string;
14
+ views: ViewDef[];
15
+ }
16
+ export declare function getHistoryState(): {
17
+ state: ViewState;
18
+ length: number;
19
+ };
20
+ /**
21
+ * Focus a specific history view
22
+ */
23
+ export declare function setActiveViewId(toId: string): void;
24
+ export declare function updateQueryParams(id: string, queryParams: Record<string, string | number | boolean>): void;
25
+ export declare function updateProps(id: string, props: Record<string, string | number | boolean>): void;
26
+ export declare function closeView(viewId: string | null, state: ViewState): void;
27
+ export declare function navigateHistory(registry: RouterRegistry, viewId: string | null, path: string, queryParams: Record<string, string | number | boolean>, state: ViewState, options: {
28
+ append: boolean;
29
+ target?: '_self' | '_top' | '_blank' | '_void';
30
+ props?: Record<string, string | number | boolean>;
31
+ layout?: string;
32
+ }): void;
33
+ export declare function paramsAreEqual(a: Record<string, string | number | boolean | undefined> | undefined, b: Record<string, string | number | boolean | undefined> | undefined): boolean;
34
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../lib/lib/history.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpE,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACjD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;CAC/C;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,OAAO,EAAE,CAAA;CACjB;AAED,wBAAgB,eAAe;;;EAY9B;AAYD;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,QAe3C;AAoBD,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,QAyBvD;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,QAmBjD;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,SAAS,QAMjB;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EACtD,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE;IACP,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACjD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,QAqGF;AAUD,wBAAgB,cAAc,CAC5B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAAG,SAAS,EACpE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAAG,SAAS,GACnE,OAAO,CAoBT"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Convert a relative url with params into url and its components.
3
+ */
4
+ export declare function relativeUrl(to?: string, params?: Record<string, string | number | boolean>): {
5
+ url: string;
6
+ path: string;
7
+ queryParams: {
8
+ [x: string]: string | number | boolean;
9
+ };
10
+ };
11
+ /**
12
+ * Parse a query parameter string into a simpler record.
13
+ */
14
+ export declare function parseSearch(search: string | URLSearchParams): Record<string, string | number | boolean>;
15
+ /**
16
+ * Stringify a record of params into a href search query string
17
+ */
18
+ export declare function stringifyParams(params: Record<string, string | number | boolean>): string;
19
+ /**
20
+ * Check whether the given url is an external url or not.
21
+ */
22
+ export declare const isExternalHref: (href: string) => boolean;
23
+ //# sourceMappingURL=href.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../../lib/lib/href.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,WAAW,CACzB,EAAE,GAAE,MAAW,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAM;;;;;;EAyBvD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAgBvG;AAUD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,MAAM,CAezF;AAGD;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,OAQ7C,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { RouterConfig } from './RouterRegistry';
2
+ /**
3
+ * Helper function to discover routes from import.meta.glob
4
+ */
5
+ export declare function mapRoutes(modules: Record<string, unknown>, basePath?: string): RouterConfig;
6
+ //# sourceMappingURL=mapRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapRoutes.d.ts","sourceRoot":"","sources":["../../lib/lib/mapRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,kBAAkB,CAAA;AAGzB;;GAEG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,GAAE,MAAW,GACpB,YAAY,CA2Dd"}
@@ -0,0 +1,8 @@
1
+ import { ViewDef } from './history';
2
+ /**
3
+ * Shallow comparison for view arrays - checks if views have actually changed
4
+ * This helps prevent unnecessary rerenders when state object reference changes
5
+ * but content is the same
6
+ */
7
+ export declare function viewsAreEqual(viewsA: ViewDef[] | undefined, viewsB: ViewDef[] | undefined): boolean;
8
+ //# sourceMappingURL=viewsAreEqual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewsAreEqual.d.ts","sourceRoot":"","sources":["../../lib/lib/viewsAreEqual.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAC7B,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,GAC5B,OAAO,CAmDT"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export { RouterProvider } from './contexts/RouterProvider';
2
+ export { StackedViewGroup } from './components/StackedViewGroup';
3
+ export { VoidViews } from './components/VoidViews';
4
+ export { StackedView } from './components/StackedView';
5
+ export { Link } from './components/Link';
6
+ export { Fill, Outlet } from './components/Slots';
7
+ export { useNavigate } from './hooks/useNavigate';
8
+ export { useHref } from './hooks/useHref';
9
+ export { useView } from './hooks/useView';
10
+ export { useOpenViews } from './hooks/useOpenViews';
11
+ export { mapRoutes } from './lib/mapRoutes';
12
+ export type { PageComponent, ErrorComponentProps, ViewMetadata, RouteConfig, RouterConfig } from './lib/RouterRegistry';
13
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../lib/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGnD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAG3C,YAAY,EACV,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,YAAY,EACb,MAAM,sBAAsB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@dotvoid/stacked-router",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "author": {
7
+ "name": "Danne Lundqvist"
8
+ },
9
+ "main": "./dist/index.umd.js",
10
+ "module": "./dist/index.es.js",
11
+ "types": "./dist/main.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/main.d.ts",
15
+ "import": "./dist/index.es.js",
16
+ "require": "./dist/index.umd.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "dev": "vite",
24
+ "build": "vite build",
25
+ "build:types": "tsc -p tsconfig.lib.json --noEmit false",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "lint": "eslint .",
29
+ "preversion": "npm test && npm run build",
30
+ "postversion": "git push && git push --tags"
31
+ },
32
+ "publishConfig": {
33
+ "registry": "https://registry.npmjs.org/",
34
+ "access": "public"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/dotvoid/stacked-router.git"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "^19.1.1",
42
+ "react-dom": "^19.1.1"
43
+ },
44
+ "devDependencies": {
45
+ "@eslint/js": "^9.35.0",
46
+ "@testing-library/jest-dom": "^6.8.0",
47
+ "@types/react": "^19.1.12",
48
+ "@types/react-dom": "^19.1.9",
49
+ "@vitejs/plugin-react": "^5.0.2",
50
+ "eslint": "^9.35.0",
51
+ "eslint-plugin-react-hooks": "^5.2.0",
52
+ "eslint-plugin-react-refresh": "^0.4.20",
53
+ "globals": "^16.2.0",
54
+ "jsdom": "^26.1.0",
55
+ "ts-node": "^10.9.2",
56
+ "typescript": "^5.9.2",
57
+ "typescript-eslint": "^8.43.0",
58
+ "vite": "^7.1.5",
59
+ "vite-plugin-dts": "^4.5.4",
60
+ "vite-tsconfig-paths": "^5.1.4",
61
+ "vitest": "^3.2.4"
62
+ }
63
+ }