@relax.js/core 1.0.4 → 1.0.5
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/dist/DependencyInjection.d.ts +3 -3
- package/dist/collections/LinkedList.d.ts +9 -8
- package/dist/collections/index.js +1 -1
- package/dist/collections/index.js.map +3 -3
- package/dist/collections/index.mjs +1 -1
- package/dist/collections/index.mjs.map +3 -3
- package/dist/di/index.js +1 -1
- package/dist/di/index.js.map +2 -2
- package/dist/di/index.mjs +1 -1
- package/dist/di/index.mjs.map +2 -2
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/forms/FormValidator.d.ts +2 -2
- package/dist/forms/ValidationRules.d.ts +2 -6
- package/dist/forms/index.js +1 -1
- package/dist/forms/index.js.map +3 -3
- package/dist/forms/index.mjs +1 -1
- package/dist/forms/index.mjs.map +3 -3
- package/dist/forms/setFormData.d.ts +39 -1
- package/dist/html/index.js +1 -1
- package/dist/html/index.js.map +3 -3
- package/dist/html/index.mjs +1 -1
- package/dist/html/index.mjs.map +3 -3
- package/dist/http/ServerSentEvents.d.ts +1 -1
- package/dist/http/SimpleWebSocket.d.ts +1 -1
- package/dist/http/index.js +1 -1
- package/dist/http/index.js.map +3 -3
- package/dist/http/index.mjs +1 -1
- package/dist/http/index.mjs.map +3 -3
- package/dist/i18n/icu.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/index.mjs +1 -1
- package/dist/i18n/index.mjs.map +2 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +3 -3
- package/dist/routing/NavigateRouteEvent.d.ts +4 -4
- package/dist/routing/index.js +2 -2
- package/dist/routing/index.js.map +3 -3
- package/dist/routing/index.mjs +3 -3
- package/dist/routing/index.mjs.map +3 -3
- package/dist/routing/navigation.d.ts +1 -1
- package/dist/templates/NodeTemplate.d.ts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +3 -3
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/index.mjs.map +3 -3
- package/docs/GettingStarted.md +7 -0
- package/docs/api.json +34 -12
- package/docs/forms/reading-writing.md +101 -1
- package/docs/setup/bootstrapping.md +154 -0
- package/docs/setup/build-and-deploy.md +183 -0
- package/docs/setup/project-structure.md +170 -0
- package/docs/setup/vite.md +175 -0
- package/package.json +3 -2
- package/docs/api/.nojekyll +0 -1
- package/docs/api/assets/hierarchy.js +0 -1
- package/docs/api/assets/highlight.css +0 -120
- package/docs/api/assets/icons.js +0 -18
- package/docs/api/assets/icons.svg +0 -1
- package/docs/api/assets/main.js +0 -60
- package/docs/api/assets/navigation.js +0 -1
- package/docs/api/assets/search.js +0 -1
- package/docs/api/assets/style.css +0 -1633
- package/docs/api/classes/http.WebSocketClient.html +0 -26
- package/docs/api/classes/i18n.LocaleChangeEvent.html +0 -66
- package/docs/api/classes/index.Blueprint.html +0 -3
- package/docs/api/classes/index.BoundNode.html +0 -3
- package/docs/api/classes/index.DigitsValidation.html +0 -10
- package/docs/api/classes/index.FormValidator.html +0 -32
- package/docs/api/classes/index.HttpError.html +0 -13
- package/docs/api/classes/index.LinkedList.html +0 -26
- package/docs/api/classes/index.NavigateRouteEvent.html +0 -76
- package/docs/api/classes/index.Node.html +0 -15
- package/docs/api/classes/index.PageSelectedEvent.html +0 -61
- package/docs/api/classes/index.Pager.html +0 -4
- package/docs/api/classes/index.RangeValidation.html +0 -15
- package/docs/api/classes/index.RelaxError.html +0 -17
- package/docs/api/classes/index.RequiredValidation.html +0 -10
- package/docs/api/classes/index.RouteError.html +0 -11
- package/docs/api/classes/index.RouteGuardError.html +0 -12
- package/docs/api/classes/index.RouteLink.html +0 -779
- package/docs/api/classes/index.RouteTarget.html +0 -788
- package/docs/api/classes/index.SSEClient.html +0 -13
- package/docs/api/classes/index.SSEDataEvent.html +0 -63
- package/docs/api/classes/index.ServiceCollection.html +0 -28
- package/docs/api/classes/index.ServiceContainer.html +0 -24
- package/docs/api/classes/index.SortChangeEvent.html +0 -61
- package/docs/api/classes/index.TableRenderer.html +0 -5
- package/docs/api/classes/index.TableSorter.html +0 -4
- package/docs/api/enums/index.GuardResult.html +0 -9
- package/docs/api/functions/elements.formError.html +0 -6
- package/docs/api/functions/elements.selectOne.html +0 -6
- package/docs/api/functions/i18n.getCurrentLocale.html +0 -3
- package/docs/api/functions/i18n.loadNamespace.html +0 -7
- package/docs/api/functions/i18n.loadNamespaces.html +0 -6
- package/docs/api/functions/i18n.onMissingTranslation.html +0 -7
- package/docs/api/functions/i18n.setLocale.html +0 -7
- package/docs/api/functions/i18n.setMessageFormatter.html +0 -7
- package/docs/api/functions/i18n.t.html +0 -9
- package/docs/api/functions/index.BooleanConverter.html +0 -6
- package/docs/api/functions/index.ContainerService.html +0 -13
- package/docs/api/functions/index.DateConverter.html +0 -11
- package/docs/api/functions/index.Inject.html +0 -16
- package/docs/api/functions/index.NumberConverter.html +0 -5
- package/docs/api/functions/index.RegisterValidator.html +0 -7
- package/docs/api/functions/index.applyPipes.html +0 -17
- package/docs/api/functions/index.asyncHandler.html +0 -11
- package/docs/api/functions/index.capitalizePipe.html +0 -4
- package/docs/api/functions/index.clearPendingNavigations.html +0 -1
- package/docs/api/functions/index.compileTemplate.html +0 -26
- package/docs/api/functions/index.configure.html +0 -5
- package/docs/api/functions/index.createBluePrint.html +0 -1
- package/docs/api/functions/index.createConverterFromDataType.html +0 -4
- package/docs/api/functions/index.createConverterFromInputType.html +0 -5
- package/docs/api/functions/index.createPipeRegistry.html +0 -12
- package/docs/api/functions/index.currencyPipe.html +0 -9
- package/docs/api/functions/index.datePipe.html +0 -9
- package/docs/api/functions/index.daysAgoPipe.html +0 -8
- package/docs/api/functions/index.defaultPipe.html +0 -5
- package/docs/api/functions/index.defineRoutes.html +0 -8
- package/docs/api/functions/index.del.html +0 -8
- package/docs/api/functions/index.findRouteByName.html +0 -5
- package/docs/api/functions/index.findRouteByUrl.html +0 -4
- package/docs/api/functions/index.firstPipe.html +0 -4
- package/docs/api/functions/index.generateSequentialId.html +0 -21
- package/docs/api/functions/index.get.html +0 -9
- package/docs/api/functions/index.getDataConverter.html +0 -11
- package/docs/api/functions/index.getParentComponent.html +0 -18
- package/docs/api/functions/index.getValidator.html +0 -4
- package/docs/api/functions/index.html.html +0 -19
- package/docs/api/functions/index.joinPipe.html +0 -5
- package/docs/api/functions/index.keysPipe.html +0 -4
- package/docs/api/functions/index.lastPipe.html +0 -4
- package/docs/api/functions/index.lowercasePipe.html +0 -4
- package/docs/api/functions/index.mapFormToClass.html +0 -17
- package/docs/api/functions/index.matchRoute.html +0 -5
- package/docs/api/functions/index.navigate.html +0 -8
- package/docs/api/functions/index.onError.html +0 -8
- package/docs/api/functions/index.piecesPipe.html +0 -8
- package/docs/api/functions/index.post.html +0 -9
- package/docs/api/functions/index.printRoutes.html +0 -2
- package/docs/api/functions/index.put.html +0 -9
- package/docs/api/functions/index.readData.html +0 -17
- package/docs/api/functions/index.registerRouteTarget.html +0 -9
- package/docs/api/functions/index.reportError.html +0 -10
- package/docs/api/functions/index.request.html +0 -8
- package/docs/api/functions/index.resolveValue.html +0 -18
- package/docs/api/functions/index.setFetch.html +0 -6
- package/docs/api/functions/index.setFormData.html +0 -17
- package/docs/api/functions/index.shortenPipe.html +0 -5
- package/docs/api/functions/index.startRouting.html +0 -6
- package/docs/api/functions/index.ternaryPipe.html +0 -6
- package/docs/api/functions/index.trimPipe.html +0 -4
- package/docs/api/functions/index.unregisterRouteTarget.html +0 -3
- package/docs/api/functions/index.uppercasePipe.html +0 -4
- package/docs/api/hierarchy.html +0 -1
- package/docs/api/index.html +0 -323
- package/docs/api/interfaces/http.SimpleDataEvent.html +0 -3
- package/docs/api/interfaces/http.WebSocketAbstraction.html +0 -9
- package/docs/api/interfaces/http.WebSocketCodec.html +0 -4
- package/docs/api/interfaces/http.WebSocketOptions.html +0 -20
- package/docs/api/interfaces/index.CompiledTemplate.html +0 -10
- package/docs/api/interfaces/index.DataLoader.html +0 -19
- package/docs/api/interfaces/index.EngineConfig.html +0 -11
- package/docs/api/interfaces/index.ErrorContext.html +0 -4
- package/docs/api/interfaces/index.FormReaderOptions.html +0 -8
- package/docs/api/interfaces/index.HttpOptions.html +0 -16
- package/docs/api/interfaces/index.HttpResponse.html +0 -17
- package/docs/api/interfaces/index.LoadRoute.html +0 -7
- package/docs/api/interfaces/index.NavigateOptions.html +0 -7
- package/docs/api/interfaces/index.PipeRegistry.html +0 -12
- package/docs/api/interfaces/index.RegistrationOptions.html +0 -22
- package/docs/api/interfaces/index.RenderTemplate.html +0 -7
- package/docs/api/interfaces/index.RequestOptions.html +0 -11
- package/docs/api/interfaces/index.Routable.html +0 -10
- package/docs/api/interfaces/index.Route.html +0 -13
- package/docs/api/interfaces/index.RouteGuard.html +0 -2
- package/docs/api/interfaces/index.RouteValue.html +0 -6
- package/docs/api/interfaces/index.SSEOptions.html +0 -24
- package/docs/api/interfaces/index.ValidationContext.html +0 -8
- package/docs/api/interfaces/index.ValidatorOptions.html +0 -14
- package/docs/api/media/Architecture.md +0 -333
- package/docs/api/media/DependencyInjection.md +0 -277
- package/docs/api/media/GettingStarted.md +0 -231
- package/docs/api/media/HttpClient.md +0 -459
- package/docs/api/media/Pipes.md +0 -211
- package/docs/api/media/Routing.md +0 -332
- package/docs/api/media/WhyRelaxjs.md +0 -336
- package/docs/api/media/forms.md +0 -99
- package/docs/api/media/html.md +0 -175
- package/docs/api/media/i18n.md +0 -354
- package/docs/api/media/utilities.md +0 -143
- package/docs/api/media/validation.md +0 -351
- package/docs/api/modules/collections_Index.html +0 -1
- package/docs/api/modules/di.html +0 -1
- package/docs/api/modules/elements.html +0 -1
- package/docs/api/modules/forms.html +0 -1
- package/docs/api/modules/html.html +0 -1
- package/docs/api/modules/http.html +0 -1
- package/docs/api/modules/i18n.html +0 -1
- package/docs/api/modules/index.html +0 -1
- package/docs/api/modules/routing.html +0 -1
- package/docs/api/modules/utils.html +0 -1
- package/docs/api/modules.html +0 -1
- package/docs/api/types/http.WebSocketFactory.html +0 -2
- package/docs/api/types/i18n.MessageFormatter.html +0 -3
- package/docs/api/types/i18n.MissingTranslationHandler.html +0 -1
- package/docs/api/types/index.Constructor.html +0 -7
- package/docs/api/types/index.ConverterFunc.html +0 -2
- package/docs/api/types/index.DataType.html +0 -2
- package/docs/api/types/index.InputType.html +0 -2
- package/docs/api/types/index.PipeFunction.html +0 -6
- package/docs/api/types/index.RouteData.html +0 -1
- package/docs/api/types/index.RouteMatchResult.html +0 -9
- package/docs/api/types/index.RouteParamType.html +0 -1
- package/docs/api/types/index.RouteSegmentType.html +0 -2
- package/docs/api/types/index.SSEEventFactory.html +0 -5
- package/docs/api/types/index.ServiceScope.html +0 -10
- package/docs/api/types/index.SortColumn.html +0 -3
- package/docs/api/variables/i18n.formatICU.html +0 -3
- package/docs/api/variables/index.container.html +0 -6
- package/docs/api/variables/index.defaultPipes.html +0 -6
- package/docs/api/variables/index.internalRoutes.html +0 -1
- package/docs/api/variables/index.serviceCollection.html +0 -6
|
@@ -14,13 +14,13 @@ export declare class NavigateRouteEvent extends Event {
|
|
|
14
14
|
/**
|
|
15
15
|
* Data supplied to the route.
|
|
16
16
|
*/
|
|
17
|
-
routeData?: RouteData;
|
|
17
|
+
routeData?: RouteData | undefined;
|
|
18
18
|
/**
|
|
19
19
|
* The target can differ from the default target that is defined in the route.
|
|
20
20
|
*
|
|
21
21
|
* undefined means that the default (unnamed) target should be used.
|
|
22
22
|
*/
|
|
23
|
-
routeTarget?: string;
|
|
23
|
+
routeTarget?: string | undefined;
|
|
24
24
|
static NAME: string;
|
|
25
25
|
constructor(
|
|
26
26
|
/**
|
|
@@ -34,13 +34,13 @@ export declare class NavigateRouteEvent extends Event {
|
|
|
34
34
|
/**
|
|
35
35
|
* Data supplied to the route.
|
|
36
36
|
*/
|
|
37
|
-
routeData?: RouteData,
|
|
37
|
+
routeData?: RouteData | undefined,
|
|
38
38
|
/**
|
|
39
39
|
* The target can differ from the default target that is defined in the route.
|
|
40
40
|
*
|
|
41
41
|
* undefined means that the default (unnamed) target should be used.
|
|
42
42
|
*/
|
|
43
|
-
routeTarget?: string, eventInit?: EventInit);
|
|
43
|
+
routeTarget?: string | undefined, eventInit?: EventInit);
|
|
44
44
|
}
|
|
45
45
|
declare global {
|
|
46
46
|
interface HTMLElementEventMap {
|
package/dist/routing/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var M=Object.defineProperty;var
|
|
2
|
-
`))}function J(){
|
|
1
|
+
"use strict";var M=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var G=(r,t)=>{for(var e in t)M(r,e,{get:t[e],enumerable:!0})},z=(r,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of F(t))!q.call(r,n)&&n!==e&&M(r,n,{get:()=>t[n],enumerable:!(o=B(t,n))||o.enumerable});return r};var _=r=>z(M({},"__esModule",{value:!0}),r);var et={};G(et,{GuardResult:()=>x,NavigateRouteEvent:()=>l,RouteError:()=>g,RouteGuardError:()=>m,RouteLink:()=>d,RouteTarget:()=>f,clearPendingNavigations:()=>V,defineRoutes:()=>O,findRouteByName:()=>A,findRouteByUrl:()=>P,internalRoutes:()=>h,matchRoute:()=>T,navigate:()=>v,printRoutes:()=>b,registerRouteTarget:()=>w,startRouting:()=>J,unregisterRouteTarget:()=>N});module.exports=_(et);var x=(n=>(n[n.Allow=0]="Allow",n[n.Deny=1]="Deny",n[n.Continue=2]="Continue",n[n.Stop=3]="Stop",n))(x||{}),g=class extends Error{},m=class extends g{constructor(){super(...arguments);this.isGuard=!0}};var l=class r extends Event{constructor(e,o,n,a,i){super(r.NAME,i);this.route=e;this.urlSegments=o;this.routeData=n;this.routeTarget=a}static{this.NAME="rlx.navigateRoute"}};var p=class extends Error{constructor(e,o){super(e);this.context=o}},H=null;function u(r,t){let e=new p(r,t);if(H){let o=!1;if(H(e,{suppress(){o=!0}}),o)return null}return e}var R=new Map,E=new Map;function w(r,t){if(D(),R.has(r)){let o=u("Duplicate route target",{target:r??"default"});if(o)throw o;return}R.set(r,t);let e=E.get(r);e&&(E.delete(r),t(e))}function N(r){R.delete(r)}function V(){E.clear(),R.clear()}function K(r){let t=R.get(r.routeTarget);t?t(r):E.set(r.routeTarget,r)}var I=!1;function D(){I||(I=!0,document.addEventListener(l.NAME,r=>{K(r)}))}var $=class{constructor(t){this.paramName=t}isMatch(t){return!!/^\d+$/.test(t)}getValue(t){if(/^\d+$/.test(t)===!1)throw new Error(`Path is not a number, parameter name '${this.paramName}', value: '${t}'.`);return parseInt(t)}},C=class{constructor(t){this.paramName=t}isMatch(t){return!0}getValue(t){return t}},k=class{constructor(t){this.value=t}isMatch(t){return t==this.value}getValue(t){return this.value}},L=class{constructor(t,e){this.route=t;this.segments=e}match(t){if(t.length!=this.segments.length)return null;let e=[];var o={};for(let n=0;n<t.length;n++){let a=t[n],i=this.segments[n];if(!i.isMatch(a))return null;if(i.paramName){let s=i.getValue(a);o[i.paramName]=s,e.push(s.toString())}else e.push(a)}return{route:this.route,params:o,urlSegments:e}}buildUrl(t){let e=[];for(let n=0;n<this.segments.length;n++){let a=this.segments[n];if(a.paramName){var o=t[a.paramName];if(!o)throw new Error(`Route "${this.route.name}" did not get value for parameter "${a.paramName} from the provided routeData: "${JSON.stringify(t)}".`);e.push(o.toString())}else e.push(a.getValue("").toString())}return{route:this.route,params:t,urlSegments:e}}};function T(r,t,e){return t===""||t.indexOf("/")>=0?P(r,t||"/"):A(r,t,e)}function A(r,t,e){var o=r.find(i=>i.name===t);if(!o)return null;var n=j(o),a=n.buildUrl(e??{});return a}function P(r,t){let e=t.replace(/^\/|\/$/g,"").split("/"),o=Q(r);for(let n=0;n<o.length;n++){let i=o[n].match(e);if(i)return i}return null}function Q(r){let t=[];return r.forEach(e=>{var o=j(e);t.push(o)}),t}function j(r){var t=[];r.path.replace(/^\/|\/$/g,"").split("/").forEach(n=>{n.substring(0,1)==":"?t.push(new C(n.substring(1))):n.substring(0,1)===";"?t.push(new $(n.substring(1))):n.substring(0,1)==="{"||t.push(new k(n))});var o=new L(r,t);return o}var d=class extends HTMLElement{static get observedAttributes(){return["name","target","params"]}constructor(){super(),this.addEventListener("click",t=>this.handleClick(t))}handleClick(t){t.preventDefault();let e=this.getAttribute("name");if(!e)return;console.log("Calling printRoutes from RouteLink in relaxjs/components"),b();let o={};for(let s of Array.from(this.attributes))if(s.name.startsWith("param-")){let c=s.name.substring(6);o[c]=s.value}let n=this.getAttribute("params"),a;if(n)try{a=JSON.parse(n)}catch(s){let c=u("Failed to parse route params",{element:"r-link",params:n,cause:s});if(c)throw c}let i=this.getAttribute("target");a&&Object.assign(o,a);try{v(e,{params:o,target:i||void 0})}catch(s){if(s instanceof p)throw s;let c=u("Navigation failed",{element:"r-link",route:e,params:o,target:i,cause:s});if(c)throw c}}connectedCallback(){this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.style.cursor="pointer",this.role="link"}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}};var f=class extends HTMLElement{constructor(){super(...arguments);this.name=void 0}connectedCallback(){this.name=this.getAttribute("name")??void 0,this.hasAttribute("dialog")&&(this.dialog=document.createElement("dialog"),this.dialog.addEventListener("close",()=>{this.dialog.replaceChildren()}),this.appendChild(this.dialog)),w(this.name,e=>this.onNavigate(e)),console.log("registered")}disconnectedCallback(){N(this.name)}onNavigate(e){console.log("got nav",e),this.loadComponent(e).catch(o=>{o instanceof p||(o=u("Route navigation failed",{route:e.route.name,routeTarget:e.routeTarget,cause:o})),o&&console.error(o)})}async loadComponent(e){let o=e.route.componentTagName??(e.route.component?customElements.getName(e.route.component):null);if(!o){let a=u("Failed to find component for route",{route:e.route.name,componentTagName:e.route.componentTagName,component:e.route.component?.name,routeData:e.routeData});if(a)throw a;return}await customElements.whenDefined(o);let n=document.createElement(o);await this.applyRouteData(n,e.routeData),this.dialog?(this.dialog.replaceChildren(n),this.dialog.open||this.dialog.showModal()):document.startViewTransition?document.startViewTransition(()=>this.replaceChildren(n)):this.replaceChildren(n)}close(){this.dialog?.close()}async applyRouteData(e,o){if("loadRoute"in e){let n=o??{error:"loadRoute function without mapped route data in the routes"};await e.loadRoute(n)}o&&(e.routeData=o)}};var y;function S(){return y===void 0&&(y=X()??"default"),y}function X(){let r=window.location.pathname;return r=="/index.html"?"default":r.endsWith(".html")?r.slice(1,-5):null}var h=[];function b(){console.log(h)}function O(r){console.log("defining routes1",r),D(),customElements.get("r-route-target")||customElements.define("r-route-target",f),customElements.get("r-link")||customElements.define("r-link",d),console.log("defining routes",r),h.length=0,h.push(...r);var t=[];if(r.forEach(e=>{e.componentTagName&&!customElements.get(e.componentTagName)&&t.push(`Component with tagName '${e.componentTagName}' is not defined in customElements.`),e.component&&!customElements.getName(e.component)&&t.push(`Component '${e.component.name}' is not defined in customElements. Used in route '${JSON.stringify(e)}'.`),e.layout===""&&(console.log("should not use empty string layout.",e),e.layout=void 0)}),t.length>0)throw new Error(t.join(`
|
|
2
|
+
`))}function J(){if(S()==""){let a=window.location.pathname.match(/\/([^\/]+)\.html$/);a&&a[1]!==""?(console.log("setting current layut",a[1]),y=a[1]):(console.log("Setting default layout name"),y="default")}if(Y())return;let r=window.location.pathname.replace(/^\/|\/$/g,"")||"/",t=U(r,{}),e=new URLSearchParams(window.location.search);if(e.size>0&&(t.params??={},e.forEach((n,a)=>{t.params[a]=n})),W(t))return;history.replaceState(t.urlSegments,"","/"+t.urlSegments.join("/"));let o=new l(t.route,t.urlSegments,t.params,t.route.target);document.dispatchEvent(o)}function v(r,t){console.log("navigating to ",r,t);let e=U(r,t);if(W(e))return;let o=t?.target??e.route.target,n=e.urlSegments.join("/");window.location.pathname.replace(/^\/|\/$/g,"")!=n&&history.pushState(e.urlSegments,"","/"+e.urlSegments.join("/"));let i=new l(e.route,e.urlSegments,e.params,o);document.dispatchEvent(i)}function U(r,t){let e=t?.routes??h,o=t?.params,n=T(e,r,o);if(!n){let a=Z(r,o,e);throw console.error(a),new g(a)}if(!tt(n))throw new m("Route guards stopped navigation for route "+r);return n}function W(r){r||console.error("Route result is null, cannot navigate to layout.");let t=(r.route.layout??"default").replace(/\.html?$/,"");if(t===S())return!1;if(console.log("Current layout: "+S(),"Wanted layout: "+t),window.location.hash)throw Error('A redirect failed, does the requsted layout exist? "'+t+'"?');console.log(`requires layout switch from ${S()} to ${t}`);let e={routeName:r.route.name,params:r.params||{}};sessionStorage.setItem("layoutNavigation",JSON.stringify(e));let o=t.indexOf(".htm")>-1?`/${t}#layout`:`/${t}.html#layout`;return console.log("redirecting to ",o),window.location.href=o,!0}function Y(){try{let r=sessionStorage.getItem("layoutNavigation");if(!r)return!1;let t=JSON.parse(r);return sessionStorage.removeItem("layoutNavigation"),console.log("session store navigation ",t),v(t.routeName,{params:t.params}),!0}catch(r){return sessionStorage.removeItem("layoutNavigation"),u("Failed to navigate from session storage",{cause:r}),!1}}function Z(r,t,e){var o="";t?o+=Object.entries(t).map(([a,i])=>`${a}=${i}`).join(", "):o=".";var n=e.map(a=>` * Name: '${a.name}', path: '${a.path}', target: ${a.target??"default"}
|
|
3
3
|
`);return`No route matched '${r}${o}'. Available routes:
|
|
4
4
|
${n}`}function tt(r){if(!r||!r.route.guards||r.route.guards.length==0)return!0;for(let e=0;e<r.route.guards.length;e++){let o=r.route.guards[e];var t=o.check(r);if(t==0)return!0;if(t==3)return!1;if(t==1)throw new m(`Guard ${o.constructor.name} said 'Deny' for ${r.route.name}`)}return!0}
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/routing/index.ts", "../../src/routing/types.ts", "../../src/routing/NavigateRouteEvent.ts", "../../src/errors.ts", "../../src/routing/routeTargetRegistry.ts", "../../src/routing/routeMatching.ts", "../../src/routing/RouteLink.ts", "../../src/routing/RoutingTarget.ts", "../../src/routing/navigation.ts"],
|
|
4
|
-
"sourcesContent": ["export {\r\n GuardResult,\r\n RouteGuard,\r\n Route,\r\n RouteParamType,\r\n RouteData,\r\n Routable,\r\n LoadRoute,\r\n RouteError,\r\n RouteGuardError,\r\n NavigateOptions,\r\n RouteMatchResult,\r\n RouteSegmentType,\r\n RouteValue,\r\n} from './types';\r\n\r\nexport { NavigateRouteEvent } from './NavigateRouteEvent';\r\n\r\nexport {\r\n registerRouteTarget,\r\n unregisterRouteTarget,\r\n clearPendingNavigations,\r\n} from './routeTargetRegistry';\r\n\r\nexport {\r\n matchRoute,\r\n findRouteByName,\r\n findRouteByUrl,\r\n} from './routeMatching';\r\n\r\nexport {\r\n internalRoutes,\r\n defineRoutes,\r\n startRouting,\r\n navigate,\r\n printRoutes,\r\n} from './navigation';\r\n\r\nexport { RouteLink } from './RouteLink';\r\nexport { RouteTarget } from './RoutingTarget';\r\n", "/** @internal */\r\ntype WebComponentConstructor = new (...args: any[]) => HTMLElement;\r\n\r\nexport enum GuardResult {\r\n /**\r\n * Handle route without checking more guards.\r\n */\r\n Allow,\r\n\r\n /**\r\n * Throw a RouteGuardError.\r\n */\r\n Deny,\r\n\r\n /**\r\n * Resume and check other guards.\r\n */\r\n Continue,\r\n\r\n /**\r\n * Do not invoke the rooute nor other guards.\r\n */\r\n Stop\r\n}\r\n\r\nexport interface RouteGuard {\r\n check(route: RouteMatchResult): GuardResult;\r\n}\r\n\r\nexport interface Route {\r\n name?: string;\r\n target?: string;\r\n path: string;\r\n\r\n /**\r\n * HTML file name (without extension).\r\n *\r\n * Define for instance if you have a route that requires a more limited layout. The library\r\n * will automatically load that HTML file and rewrite URL history so that the correct url is displayed.\r\n */\r\n layout?: string;\r\n\r\n /**\r\n * Name of the tag for your web component.\r\n */\r\n componentTagName?: string;\r\n\r\n /**\r\n * Guards used to check if this route can be visited.\r\n */\r\n guards?: RouteGuard[];\r\n\r\n component?: WebComponentConstructor;\r\n}\r\n\r\nexport type RouteParamType = string | number;\r\nexport type RouteData = Record<string, RouteParamType>;\r\n\r\n/**\r\n * Implement to receive typed route parameters via a `routeData` property.\r\n * RouteTarget assigns `routeData` after element creation but before DOM insertion.\r\n * Optional since it's not available at construction time.\r\n *\r\n * For convention-based usage without undefined checks, skip the interface\r\n * and declare `routeData` directly on your component.\r\n *\r\n * @example\r\n * class UserProfile extends HTMLElement implements Routable<{ userName: string }> {\r\n * routeData?: { userName: string };\r\n * }\r\n */\r\nexport interface Routable<T extends RouteData = RouteData> {\r\n routeData?: T;\r\n}\r\n\r\n/**\r\n * Implement to run async initialization before the component is added to the DOM.\r\n * RouteTarget calls `loadRoute()` and awaits it before inserting the element.\r\n *\r\n * @example\r\n * class OrderDetail extends HTMLElement implements LoadRoute<{ orderId: number }> {\r\n * async loadRoute(data: { orderId: number }) {\r\n * this.order = await fetchOrder(data.orderId);\r\n * }\r\n * }\r\n */\r\nexport interface LoadRoute<T extends RouteData = RouteData> {\r\n loadRoute(data: T): void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Result from route matching operations.\r\n * Contains all information needed for navigation and rendering.\r\n */\r\nexport type RouteMatchResult = {\r\n /**\r\n * Matched route configuration\r\n */\r\n route: Route;\r\n\r\n /**\r\n * URL segments used for history state\r\n */\r\n urlSegments: string[];\r\n\r\n /**\r\n * Extracted and type-converted parameters\r\n */\r\n params: RouteData;\r\n};\r\n\r\n/**\r\n * Supported types of route segments\r\n */\r\nexport type RouteSegmentType = 'string' | 'number' | 'path' | 'regex';\r\n\r\n/**\r\n * Strongly typed route segment value\r\n */\r\nexport interface RouteValue {\r\n /**\r\n * Type of parameter for validation\r\n */\r\n type: RouteSegmentType;\r\n\r\n /**\r\n * Actual parameter value\r\n */\r\n value: any;\r\n}\r\n\r\nexport class RouteError extends Error {}\r\nexport class RouteGuardError extends RouteError {\r\n isGuard = true;\r\n}\r\n\r\nexport interface NavigateOptions {\r\n /**\r\n * Optional parameters when using route name\r\n */\r\n params?: Record<string, string | number>;\r\n\r\n /**\r\n * override for route's default target\r\n */\r\n target?: string;\r\n\r\n /**\r\n * When you want to override routes from the globally registered ones.\r\n */\r\n routes?: Route[];\r\n}\r\n", "import type { Route, RouteData } from './types';\r\n\r\n/**\r\n * Event sent to routing targets when a new route should be displayed.\r\n */\r\nexport class NavigateRouteEvent extends Event {\r\n static NAME: string = 'rlx.navigateRoute';\r\n constructor(\r\n /**\r\n * Matched route.\r\n */\r\n public route: Route,\r\n\r\n /**\r\n * The generated url sements which can be used to push the url into the browser history.\r\n */\r\n public urlSegments: string[],\r\n\r\n /**\r\n * Data supplied to the route.\r\n */\r\n public routeData?: RouteData,\r\n\r\n /**\r\n * The target can differ from the default target that is defined in the route.\r\n *\r\n * undefined means that the default (unnamed) target should be used.\r\n */\r\n public routeTarget?: string,\r\n\r\n eventInit?: EventInit\r\n ) {\r\n super(NavigateRouteEvent.NAME, eventInit);\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementEventMap {\r\n 'rlx.navigateRoute': NavigateRouteEvent;\r\n }\r\n interface DocumentEventMap {\r\n 'rlx.navigateRoute': NavigateRouteEvent;\r\n }\r\n}\r\n", "/**\r\n * Global error handling for Relaxjs.\r\n * Register a handler with `onError()` to intercept errors before they throw.\r\n * Call `ctx.suppress()` in the handler to prevent the error from being thrown.\r\n *\r\n * @example\r\n * import { onError } from 'relaxjs';\r\n *\r\n * onError((error, ctx) => {\r\n * logToService(error.message, error.context);\r\n * showToast(error.message);\r\n * ctx.suppress();\r\n * });\r\n */\r\n\r\n/**\r\n * Passed to error handlers to control error behavior.\r\n * Call `suppress()` to prevent the error from being thrown.\r\n */\r\nexport interface ErrorContext {\r\n suppress(): void;\r\n}\r\n\r\n/**\r\n * Error with structured context for debugging.\r\n * The `context` record contains details like route name, component tag, route data.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n * console.log(error.context.route);\r\n * console.log(error.context.componentTagName);\r\n * });\r\n */\r\nexport class RelaxError extends Error {\r\n constructor(\r\n message: string,\r\n public context: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n }\r\n}\r\n\r\n/** @internal */\r\ntype ErrorHandler = (error: RelaxError, ctx: ErrorContext) => void;\r\n\r\nlet handler: ErrorHandler | null = null;\r\n\r\n/**\r\n * Registers a global error handler for Relaxjs errors.\r\n * The handler receives the error and an `ErrorContext`.\r\n * Call `ctx.suppress()` to prevent the error from being thrown.\r\n * Only one handler can be active at a time; subsequent calls replace the previous handler.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n * if (error.context.route === 'optional-panel') {\r\n * ctx.suppress();\r\n * return;\r\n * }\r\n * showErrorDialog(error.message);\r\n * });\r\n */\r\nexport function onError(fn: ErrorHandler) {\r\n handler = fn;\r\n}\r\n\r\n/**\r\n * Reports an error through the global handler.\r\n * Returns the `RelaxError` if it should be thrown, or `null` if the handler suppressed it.\r\n * The caller is responsible for throwing the returned error.\r\n *\r\n * @param message - Human-readable error description\r\n * @param context - Structured data for debugging (route, component, params, cause, etc.)\r\n * @returns The error to throw, or `null` if suppressed\r\n *\r\n * @example\r\n * const error = reportError('Failed to load route component', {\r\n * route: 'user',\r\n * componentTagName: 'user-profile',\r\n * routeData: { id: 123 },\r\n * });\r\n * if (error) throw error;\r\n */\r\nexport function reportError(message: string, context: Record<string, unknown>): RelaxError | null {\r\n const error = new RelaxError(message, context);\r\n if (handler) {\r\n let suppressed = false;\r\n const ctx: ErrorContext = {\r\n suppress() { suppressed = true; },\r\n };\r\n handler(error, ctx);\r\n if (suppressed) {\r\n return null;\r\n }\r\n }\r\n return error;\r\n}\r\n\r\n/**\r\n * Wraps an async function into a synchronous callback suitable for addEventListener.\r\n * Catches promise rejections and reports them through the global error handler.\r\n *\r\n * @param fn - Async function to wrap\r\n * @returns Synchronous function that can be passed to addEventListener\r\n *\r\n * @example\r\n * button.addEventListener('click', asyncHandler(async (e) => {\r\n * await saveData();\r\n * }));\r\n *\r\n * @example\r\n * form.addEventListener('submit', asyncHandler(async (e) => {\r\n * e.preventDefault();\r\n * await submitForm();\r\n * }));\r\n */\r\nexport function asyncHandler<TArgs extends unknown[]>(\r\n fn: (...args: TArgs) => Promise<void>,\r\n): (...args: TArgs) => void {\r\n return function (this: any, ...args: TArgs) {\r\n fn.call(this, ...args).catch((cause: unknown) => {\r\n const error = reportError('Async callback failed', { cause });\r\n if (error) throw error;\r\n });\r\n };\r\n}\r\n", "import { reportError } from '../errors';\r\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\r\n\r\n/** @internal */\r\ntype RouteTargetHandler = (evt: NavigateRouteEvent) => void;\r\nconst targetHandlers = new Map<string | undefined, RouteTargetHandler>();\r\nconst pendingEvents = new Map<string | undefined, NavigateRouteEvent>();\r\n\r\n/**\r\n * Registers a route target handler.\r\n * When a navigation event targets this name, the handler is called directly.\r\n * If a pending event exists for this target, it is replayed immediately.\r\n *\r\n * @param name - Target name, or `undefined` for the default (unnamed) target\r\n * @param handler - Callback that receives the `NavigateRouteEvent`\r\n *\r\n * @example\r\n * registerRouteTarget('sidebar', (evt) => renderComponent(evt));\r\n */\r\nexport function registerRouteTarget(\r\n name: string | undefined,\r\n handler: RouteTargetHandler,\r\n) {\r\n initRouteTargetListener();\r\n if (targetHandlers.has(name)) {\r\n const error = reportError('Duplicate route target', {\r\n target: name ?? 'default',\r\n });\r\n if (error) throw error;\r\n return;\r\n }\r\n targetHandlers.set(name, handler);\r\n\r\n const pending = pendingEvents.get(name);\r\n if (pending) {\r\n pendingEvents.delete(name);\r\n handler(pending);\r\n }\r\n}\r\n\r\n/**\r\n * Unregisters a previously registered route target handler.\r\n *\r\n * @param name - Target name that was passed to `registerRouteTarget`\r\n */\r\nexport function unregisterRouteTarget(name: string | undefined) {\r\n targetHandlers.delete(name);\r\n}\r\n\r\nexport function clearPendingNavigations() {\r\n pendingEvents.clear();\r\n targetHandlers.clear();\r\n}\r\n\r\nfunction dispatchToTarget(evt: NavigateRouteEvent) {\r\n const handler = targetHandlers.get(evt.routeTarget);\r\n if (handler) {\r\n handler(evt);\r\n } else {\r\n pendingEvents.set(evt.routeTarget, evt);\r\n }\r\n}\r\n\r\nlet listenerAttached = false;\r\n\r\nexport function initRouteTargetListener() {\r\n if (listenerAttached) return;\r\n listenerAttached = true;\r\n document.addEventListener(NavigateRouteEvent.NAME, (evt) => {\r\n dispatchToTarget(evt as NavigateRouteEvent);\r\n });\r\n}\r\n", "import type { Route, RouteData, RouteParamType, RouteMatchResult } from './types';\r\n\r\n/**\r\n * Route segment matcher interface.\r\n * Each segment type (string, number, path) implements this\r\n * for parameter extraction and validation.\r\n */\r\ninterface RouteSegment {\r\n /**\r\n * Parameter name when segment is dynamic (:name or ;id)\r\n */\r\n paramName?: string;\r\n\r\n /**\r\n * Validates if URL segment matches pattern\r\n * @param value Segment from URL to validate\r\n */\r\n isMatch(value: string): boolean;\r\n\r\n /**\r\n * Converts URL segment to typed parameter\r\n * @param pathValue Raw value from URL\r\n */\r\n getValue(pathValue: string): RouteParamType;\r\n}\r\n\r\n/**\r\n * Number parameter segment matcher.\r\n * Used for ;id style parameters that must be numbers.\r\n */\r\nclass NumberRouteSegment implements RouteSegment {\r\n constructor(public paramName: string) {}\r\n isMatch(value: string): boolean {\r\n if (/^\\d+$/.test(value)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n getValue(pathValue: string): RouteParamType {\r\n if (/^\\d+$/.test(pathValue) === false) {\r\n throw new Error(\r\n `Path is not a number, parameter name '${this.paramName}', value: '${pathValue}'.`\r\n );\r\n }\r\n return parseInt(pathValue);\r\n }\r\n}\r\n\r\n/**\r\n * String parameter segment matcher.\r\n * Used for :name style parameters.\r\n */\r\nclass StringRouteSegment implements RouteSegment {\r\n constructor(public paramName: string) {}\r\n isMatch(value: string): boolean {\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n * @param pathValue the route data (for route by name) or segment extracted from the url (for url routing).\r\n * @returns\r\n */\r\n getValue(pathValue: string): RouteParamType {\r\n return pathValue;\r\n }\r\n}\r\n\r\n/**\r\n * Static path segment matcher.\r\n * Used for fixed URL parts like 'users' in /users/:id\r\n */\r\nclass PathRouteSegment implements RouteSegment {\r\n constructor(public value: string) {}\r\n isMatch(value: string): boolean {\r\n return value == this.value;\r\n }\r\n\r\n getValue(_pathValue: string): RouteParamType {\r\n return this.value;\r\n }\r\n}\r\n\r\n/**\r\n * Internal route implementation that handles segment matching\r\n * and parameter extraction.\r\n */\r\nclass RouteImp {\r\n constructor(public route: Route, private segments: RouteSegment[]) {}\r\n\r\n /**\r\n * Attempts to match URL segments against route pattern\r\n * @param segments URL parts to match\r\n * @returns Match result with parameters if successful\r\n */\r\n match(segments: string[]): RouteMatchResult | null {\r\n if (segments.length != this.segments.length) {\r\n return null;\r\n }\r\n\r\n const generatedSegments: string[] = [];\r\n var params: RouteData = {};\r\n for (let index = 0; index < segments.length; index++) {\r\n const urlSegment = segments[index];\r\n const ourSegment = this.segments[index];\r\n\r\n if (!ourSegment.isMatch(urlSegment)) {\r\n return null;\r\n }\r\n\r\n if (ourSegment.paramName) {\r\n const value = ourSegment.getValue(urlSegment);\r\n params[ourSegment.paramName] = value;\r\n generatedSegments.push(value.toString());\r\n } else {\r\n generatedSegments.push(urlSegment);\r\n }\r\n }\r\n\r\n return { route: this.route, params, urlSegments: generatedSegments };\r\n }\r\n\r\n /**\r\n * Routing by name and route data, so generate the url segments.\r\n * @param routeData Data to use in the URL.\r\n * @returns Match result with parameters if successful\r\n */\r\n buildUrl(routeData: RouteData): RouteMatchResult | null {\r\n const urlSegments: string[] = [];\r\n for (let index = 0; index < this.segments.length; index++) {\r\n const ourSegment = this.segments[index];\r\n if (ourSegment.paramName) {\r\n var value = routeData[ourSegment.paramName];\r\n if (!value) {\r\n throw new Error(\r\n `Route \"${\r\n this.route.name\r\n }\" did not get value for parameter \"${\r\n ourSegment.paramName\r\n } from the provided routeData: \"${JSON.stringify(\r\n routeData\r\n )}\".`\r\n );\r\n }\r\n\r\n urlSegments.push(value.toString());\r\n } else {\r\n urlSegments.push(ourSegment.getValue('').toString());\r\n }\r\n }\r\n\r\n return { route: this.route, params: routeData, urlSegments };\r\n }\r\n\r\n /**\r\n * Converts string parameters to proper types\r\n * @param routeParams Raw string parameters to convert\r\n */\r\n parseParameters(routeParams: Record<string, string>): RouteData {\r\n const d: Record<string, any> = {};\r\n\r\n this.segments.forEach((segment) => {\r\n if (!segment.paramName) {\r\n return;\r\n }\r\n\r\n if (!segment.isMatch(providedValue)) {\r\n throw new Error(\r\n `Failed to convert parameter ${segment.paramName}, or missing value: ${providedValue}, route: ${this.route.name}.`\r\n );\r\n }\r\n\r\n var providedValue = routeParams[segment.paramName];\r\n if (!providedValue) {\r\n throw new Error(\r\n `Parameter ${segment.paramName} was not provided, route: ${this.route.name}.`\r\n );\r\n }\r\n\r\n var convertedValue = segment.getValue(providedValue);\r\n d[segment.paramName] = convertedValue;\r\n });\r\n\r\n return d;\r\n }\r\n}\r\n\r\n/**\r\n * Match route by either name or URL pattern\r\n * @param routes Available routes\r\n * @param routeNameOrUrl Route name or URL to match\r\n * @param routeData Optional parameters for named routes\r\n */\r\nexport function matchRoute(\r\n routes: Route[],\r\n routeNameOrUrl: string,\r\n routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n if (routeNameOrUrl === '' || routeNameOrUrl.indexOf('/') >= 0) {\r\n return findRouteByUrl(routes, routeNameOrUrl || '/');\r\n } else {\r\n return findRouteByName(routes, routeNameOrUrl, routeData!);\r\n }\r\n}\r\n\r\n/**\r\n * Find route by name and apply parameters\r\n * @param routes Available routes\r\n * @param name Route name to find\r\n * @param routeData Parameters to apply\r\n */\r\nexport function findRouteByName(\r\n routes: Route[],\r\n name: string,\r\n routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n var route = routes.find((x) => x.name === name);\r\n if (!route) {\r\n return null;\r\n }\r\n\r\n var imp = generateRouteImp(route);\r\n var result = imp.buildUrl(routeData);\r\n return result;\r\n}\r\n\r\n/**\r\n * Find route matching URL pattern\r\n * @param routes Available routes\r\n * @param path URL to match\r\n */\r\nexport function findRouteByUrl(\r\n routes: Route[],\r\n path: string\r\n): RouteMatchResult | null {\r\n const urlSegments = path.replace(/^\\/|\\/$/g, '').split('/');\r\n const routeImps = generateRouteImps(routes);\r\n\r\n for (let index = 0; index < routeImps.length; index++) {\r\n const element = routeImps[index];\r\n const m = element.match(urlSegments);\r\n if (m) {\r\n return m;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Generate implementations for all routes\r\n */\r\nfunction generateRouteImps(routes: Route[]) {\r\n const routeImps: RouteImp[] = [];\r\n routes.forEach((route) => {\r\n var imp = generateRouteImp(route);\r\n routeImps.push(imp);\r\n });\r\n\r\n return routeImps;\r\n}\r\n\r\n/**\r\n * Generate implementation for single route\r\n * Parses URL pattern into segment matchers\r\n */\r\nfunction generateRouteImp(route: Route): RouteImp {\r\n var impSegments = [];\r\n const segments = route.path.replace(/^\\/|\\/$/g, '').split('/');\r\n segments.forEach((segment) => {\r\n if (segment.substring(0, 1) == ':') {\r\n impSegments.push(new StringRouteSegment(segment.substring(1)));\r\n } else if (segment.substring(0, 1) === ';') {\r\n impSegments.push(new NumberRouteSegment(segment.substring(1)));\r\n } else if (segment.substring(0, 1) === '{') {\r\n } else {\r\n impSegments.push(new PathRouteSegment(segment));\r\n }\r\n });\r\n\r\n var imp = new RouteImp(route, impSegments);\r\n return imp;\r\n}\r\n", "import { navigate, printRoutes } from './navigation';\r\nimport { RelaxError, reportError } from '../errors';\r\n\r\nexport class RouteLink extends HTMLElement {\r\n static get observedAttributes() {\r\n return ['name', 'target', 'params'];\r\n }\r\n\r\n constructor() {\r\n super();\r\n this.addEventListener('click', e => this.handleClick(e));\r\n }\r\n\r\n private handleClick(e: MouseEvent) {\r\n e.preventDefault();\r\n \r\n const name = this.getAttribute('name');\r\n if (!name) return;\r\n\r\n console.log('Calling printRoutes from RouteLink in relaxjs/components');\r\n printRoutes();\r\n \r\n const params: Record<string, string> = {};\r\n for (const attr of Array.from(this.attributes)) {\r\n if (attr.name.startsWith('param-')) {\r\n const paramName = attr.name.substring(6);\r\n params[paramName] = attr.value;\r\n }\r\n }\r\n\r\n const paramsAttr = this.getAttribute('params');\r\n let additionalParams: Record<string, string | number> | undefined;\r\n if (paramsAttr) {\r\n try {\r\n const parsed = JSON.parse(paramsAttr);\r\n additionalParams = parsed as Record<string, string | number>;\r\n } catch (error) {\r\n const err = reportError('Failed to parse route params', {\r\n element: 'r-link',\r\n params: paramsAttr,\r\n cause: error,\r\n });\r\n if (err) throw err;\r\n }\r\n }\r\n\r\n const target = this.getAttribute('target');\r\n if (additionalParams){\r\n Object.assign(params, additionalParams);\r\n }\r\n\r\n try {\r\n navigate(name, { params, target: target || undefined });\r\n } catch (error) {\r\n if (error instanceof RelaxError) throw error;\r\n const reported = reportError('Navigation failed', {\r\n element: 'r-link',\r\n route: name,\r\n params,\r\n target,\r\n cause: error,\r\n });\r\n if (reported) throw reported;\r\n }\r\n }\r\n\r\n connectedCallback() {\r\n if (!this.hasAttribute('tabindex')) {\r\n this.setAttribute('tabindex', '0');\r\n }\r\n \r\n this.style.cursor = 'pointer';\r\n this.role = 'link';\r\n }\r\n\r\n disconnectedCallback() {\r\n this.removeEventListener('click', this.handleClick);\r\n }\r\n}", "import { registerRouteTarget, unregisterRouteTarget } from './routeTargetRegistry';\r\nimport type { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport type { RouteData, LoadRoute } from './types';\r\nimport { RelaxError, reportError } from '../errors';\r\n\r\n/**\r\n * WebComponent that listens on the `NavigateRouteEvent` event to be able to switch route.\r\n *\r\n * Use the \"name\" attribute to make this non-default target.\r\n * Use the \"dialog\" attribute to render routes inside a native `<dialog>` element\r\n * with built-in focus trapping, backdrop, and Escape-to-close.\r\n *\r\n * @example\r\n * <r-route-target></r-route-target>\r\n * <r-route-target name=\"modal\" dialog></r-route-target>\r\n */\r\nexport class RouteTarget extends HTMLElement {\r\n name?: string = undefined;\r\n private dialog?: HTMLDialogElement;\r\n\r\n connectedCallback() {\r\n this.name = this.getAttribute('name') ?? undefined;\r\n\r\n if (this.hasAttribute('dialog')) {\r\n this.dialog = document.createElement('dialog');\r\n this.dialog.addEventListener('close', () => {\r\n this.dialog!.replaceChildren();\r\n });\r\n this.appendChild(this.dialog);\r\n }\r\n\r\n registerRouteTarget(this.name, (evt) => this.onNavigate(evt));\r\n console.log('registered');\r\n }\r\n\r\n disconnectedCallback() {\r\n unregisterRouteTarget(this.name);\r\n }\r\n\r\n private onNavigate(evt: NavigateRouteEvent) {\r\n console.log('got nav', evt);\r\n this.loadComponent(evt).catch((error) => {\r\n if (!(error instanceof RelaxError)) {\r\n error = reportError('Route navigation failed', {\r\n route: evt.route.name,\r\n routeTarget: evt.routeTarget,\r\n cause: error,\r\n });\r\n }\r\n if (error) {\r\n console.error(error);\r\n }\r\n });\r\n }\r\n\r\n private async loadComponent(evt: NavigateRouteEvent) {\r\n const tagName = evt.route.componentTagName\r\n ?? customElements.getName(evt.route.component);\r\n\r\n if (!tagName) {\r\n const error = reportError('Failed to find component for route', {\r\n route: evt.route.name,\r\n componentTagName: evt.route.componentTagName,\r\n component: evt.route.component?.name,\r\n routeData: evt.routeData,\r\n });\r\n if (error) throw error;\r\n return;\r\n }\r\n\r\n await customElements.whenDefined(tagName);\r\n const element = document.createElement(tagName);\r\n\r\n await this.applyRouteData(element, evt.routeData);\r\n\r\n if (this.dialog) {\r\n this.dialog.replaceChildren(element);\r\n if (!this.dialog.open) {\r\n this.dialog.showModal();\r\n }\r\n } else if (document.startViewTransition) {\r\n document.startViewTransition(() => this.replaceChildren(element));\r\n } else {\r\n this.replaceChildren(element);\r\n }\r\n }\r\n\r\n /** Closes the dialog (only applies to dialog targets). */\r\n close() {\r\n this.dialog?.close();\r\n }\r\n\r\n private async applyRouteData(element: Element, data?: RouteData) {\r\n if ('loadRoute' in element) {\r\n const routeData = data\r\n ?? { error: 'loadRoute function without mapped route data in the routes' };\r\n await (element as unknown as LoadRoute).loadRoute(routeData);\r\n }\r\n\r\n if (data) {\r\n (element as any).routeData = data;\r\n }\r\n }\r\n}\r\n", "/**\r\n * Single Page Application routing system with multiple target support.\r\n * Designed for scenarios where you need:\r\n * - Multiple navigation targets (main content, modals, sidebars)\r\n * - Strongly typed route parameters\r\n * - History management with back/forward support\r\n *\r\n * @example\r\n * // Configure routes\r\n * const routes = [\r\n * { name: 'user', path: '/users/:id' }, // String parameter\r\n * { name: 'order', path: '/orders/;orderId' }, // Number parameter\r\n * { name: 'modal', path: '/detail/:id', target: 'modal' } // Custom target\r\n * ];\r\n */\r\n\r\nimport { reportError } from '../errors';\r\nimport {\r\n GuardResult,\r\n RouteError,\r\n RouteGuardError,\r\n type Route,\r\n type RouteData,\r\n type RouteParamType,\r\n type RouteMatchResult,\r\n type NavigateOptions,\r\n} from './types';\r\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport { matchRoute } from './routeMatching';\r\nimport { initRouteTargetListener } from './routeTargetRegistry';\r\nimport { RouteLink } from './RouteLink';\r\nimport { RouteTarget } from './RoutingTarget';\r\n\r\n/**\r\n * Used to keep track of current main HTML file,\r\n * used when different layouts are supported.\r\n *\r\n * The default page is ALWAYS loaded initially,\r\n * which means that we need to switch layout page\r\n * if someone else is configured for the route.\r\n */\r\nvar currentLayout: string | undefined;\r\n\r\nfunction getCurrentLayout(): string {\r\n if (currentLayout === undefined) {\r\n currentLayout = getLayout() ?? 'default';\r\n }\r\n return currentLayout;\r\n}\r\n\r\nfunction getLayout() {\r\n const path = window.location.pathname;\r\n if (path == '/index.html') {\r\n return 'default';\r\n }\r\n\r\n return path.endsWith('.html') ? path.slice(1, -5) : null;\r\n}\r\n\r\nexport const internalRoutes: Route[] = [];\r\n\r\nexport const MyData = {\r\n routes: []\r\n};\r\n\r\n/**\r\n * Debug helper to print all registered routes to console.\r\n */\r\nexport function printRoutes() {\r\n console.log(internalRoutes);\r\n}\r\n\r\n/**\r\n * Registers application routes with the router.\r\n * Call this at application startup before routing begins.\r\n *\r\n * @param appRoutes - Array of route configurations\r\n * @throws Error if referenced components are not registered\r\n *\r\n * @example\r\n * const routes: Route[] = [\r\n * { name: 'home', path: '/', componentTagName: 'app-home' },\r\n * { name: 'user', path: '/users/:id', componentTagName: 'user-profile' },\r\n * { name: 'login', path: '/auth/', componentTagName: 'login-form', layout: 'noauth' }\r\n * ];\r\n * defineRoutes(routes);\r\n */\r\nexport function defineRoutes(appRoutes: Route[]) {\r\n console.log('defining routes1', appRoutes);\r\n initRouteTargetListener();\r\n if (!customElements.get('r-route-target')) {\r\n customElements.define('r-route-target', RouteTarget);\r\n }\r\n if (!customElements.get('r-link')) {\r\n customElements.define('r-link', RouteLink);\r\n }\r\n console.log('defining routes', appRoutes);\r\n internalRoutes.length = 0;\r\n internalRoutes.push(...appRoutes);\r\n\r\n var errs = [];\r\n appRoutes.forEach((route) => {\r\n if (\r\n route.componentTagName &&\r\n !customElements.get(route.componentTagName)\r\n ) {\r\n errs.push(\r\n `Component with tagName '${route.componentTagName}' is not defined in customElements.`\r\n );\r\n }\r\n if (route.component && !customElements.getName(route.component)) {\r\n errs.push(\r\n `Component '${route.component.name}' is not defined in customElements. Used in route '${JSON.stringify(route)}'.`\r\n );\r\n }\r\n if (route.layout === '') {\r\n console.log('should not use empty string layout.', route);\r\n route.layout = undefined;\r\n }\r\n });\r\n\r\n if (errs.length > 0) {\r\n throw new Error(errs.join('\\n'));\r\n }\r\n}\r\n\r\n/**\r\n * Initializes routing and navigates to the current URL.\r\n * Call this after DOM is ready and routes are defined.\r\n *\r\n * @example\r\n * // In your main application component\r\n * connectedCallback() {\r\n * defineRoutes(routes);\r\n * startRouting();\r\n * }\r\n */\r\nexport function startRouting() {\r\n let newPage = false;\r\n if (getCurrentLayout() == '') {\r\n const path = window.location.pathname;\r\n const match = path.match(/\\/([^\\/]+)\\.html$/);\r\n if (match && match[1] !== '') {\r\n console.log('setting current layut', match[1]);\r\n currentLayout = match[1];\r\n newPage = true;\r\n } else {\r\n console.log('Setting default layout name');\r\n currentLayout = 'default';\r\n }\r\n }\r\n\r\n if (tryLoadRouteFromLayoutNavigation()) {\r\n return;\r\n }\r\n\r\n const currentUrl = window.location.pathname.replace(/^\\/|\\/$/g, '') || '/';\r\n const routeResult = findRoute(currentUrl, {});\r\n\r\n const searchParams = new URLSearchParams(window.location.search);\r\n if (searchParams.size > 0) {\r\n routeResult.params ??= {};\r\n searchParams.forEach((value, key) => {\r\n routeResult.params[key] = value;\r\n });\r\n }\r\n\r\n if (navigateToLayout(routeResult)) {\r\n return;\r\n }\r\n\r\n history.replaceState(\r\n routeResult.urlSegments,\r\n '',\r\n '/' + routeResult.urlSegments.join('/')\r\n );\r\n\r\n const e = new NavigateRouteEvent(\r\n routeResult.route,\r\n routeResult.urlSegments,\r\n routeResult.params,\r\n routeResult.route.target\r\n );\r\n document.dispatchEvent(e);\r\n}\r\n\r\n/**\r\n * Navigates to a route by name or URL.\r\n * Updates browser history and dispatches navigation events.\r\n *\r\n * @param routeNameOrUrl - Route name or URL path to navigate to\r\n * @param options - Navigation options including params and target\r\n *\r\n * @example\r\n * // Navigate by route name\r\n * navigate('user', { params: { id: '123' } });\r\n *\r\n * // Navigate by URL\r\n * navigate('/users/123');\r\n *\r\n * // Navigate to specific target\r\n * navigate('detail', { params: { id: '42' }, target: 'modal' });\r\n */\r\nexport function navigate(routeNameOrUrl: string, options?: NavigateOptions) {\r\n console.log('navigating to ', routeNameOrUrl, options);\r\n const routeResult = findRoute(routeNameOrUrl, options);\r\n if (navigateToLayout(routeResult)) {\r\n return;\r\n }\r\n\r\n const target = options?.target ?? routeResult.route.target;\r\n const ourUrl = routeResult.urlSegments.join('/');\r\n const currentUrl = window.location.pathname.replace(/^\\/|\\/$/g, '');\r\n if (currentUrl != ourUrl) {\r\n history.pushState(\r\n routeResult.urlSegments,\r\n '',\r\n '/' + routeResult.urlSegments.join('/')\r\n );\r\n }\r\n const e = new NavigateRouteEvent(\r\n routeResult.route,\r\n routeResult.urlSegments,\r\n routeResult.params,\r\n target\r\n );\r\n document.dispatchEvent(e);\r\n}\r\n\r\nfunction findRoute(routeNameOrUrl: string, options?: NavigateOptions) {\r\n const theRoutes = options?.routes ?? internalRoutes;\r\n const params = options?.params;\r\n\r\n const routeResult = matchRoute(theRoutes, routeNameOrUrl, params);\r\n if (!routeResult) {\r\n const errorMsg = generateErrorMessage(\r\n routeNameOrUrl,\r\n params,\r\n theRoutes\r\n );\r\n console.error(errorMsg);\r\n throw new RouteError(errorMsg);\r\n }\r\n\r\n if (!checkRouteGuards(routeResult)) {\r\n throw new RouteGuardError('Route guards stopped navigation for route ' + routeNameOrUrl);\r\n }\r\n\r\n return routeResult;\r\n}\r\n\r\nfunction navigateToLayout(routeResult: RouteMatchResult): boolean {\r\n if (!routeResult) {\r\n console.error('Route result is null, cannot navigate to layout.');\r\n }\r\n\r\n const wantedLayout = (routeResult.route.layout ?? 'default').replace(\r\n /\\.html?$/,\r\n ''\r\n );\r\n if (wantedLayout === getCurrentLayout()) {\r\n return false;\r\n }\r\n\r\n console.log(\r\n 'Current layout: ' + getCurrentLayout(),\r\n 'Wanted layout: ' + wantedLayout\r\n );\r\n\r\n // The hash means that we attempted to redirect to the same layout once,\r\n // so if it's there and another redirect is requsted, something is wrong.\r\n //\r\n // Because the push history should remove it if everything worked out.\r\n if (window.location.hash) {\r\n throw Error(\r\n 'A redirect failed, does the requsted layout exist? \"' +\r\n wantedLayout +\r\n '\"?'\r\n );\r\n }\r\n\r\n console.log(\r\n `requires layout switch from ${getCurrentLayout()} to ${wantedLayout}`\r\n );\r\n const navigationState = {\r\n routeName: routeResult.route.name,\r\n params: routeResult.params || {}\r\n };\r\n\r\n sessionStorage.setItem('layoutNavigation', JSON.stringify(navigationState));\r\n const layoutUrl =\r\n wantedLayout.indexOf('.htm') > -1\r\n ? `/${wantedLayout}#layout`\r\n : `/${wantedLayout}.html#layout`;\r\n console.log('redirecting to ', layoutUrl);\r\n window.location.href = layoutUrl;\r\n return true;\r\n}\r\n/**\r\n * Checks session storage for route information and initiates proper navigation\r\n * Should be called when page loads to handle layout transitions\r\n *\r\n * @returns Whether navigation was initiated from session storage\r\n *\r\n * @example\r\n * // Call on page load\r\n * document.addEventListener('DOMContentLoaded', () => {\r\n * if (handleLayoutNavigation()) {\r\n * console.log('Navigation handled from session storage');\r\n * }\r\n * });\r\n */\r\nfunction tryLoadRouteFromLayoutNavigation(): boolean {\r\n try {\r\n const navigationStateJson = sessionStorage.getItem('layoutNavigation');\r\n if (!navigationStateJson) {\r\n return false;\r\n }\r\n\r\n const navigationState = JSON.parse(navigationStateJson);\r\n sessionStorage.removeItem('layoutNavigation');\r\n console.log('session store navigation ', navigationState);\r\n navigate(navigationState.routeName, {\r\n params: navigationState.params\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n sessionStorage.removeItem('layoutNavigation');\r\n reportError('Failed to navigate from session storage', {\r\n cause: error,\r\n });\r\n return false;\r\n }\r\n}\r\n\r\nfunction generateErrorMessage(\r\n routeNameOrUrl: string,\r\n routeParams: Record<string, RouteParamType>,\r\n allRoutes: Route[]\r\n): string {\r\n var routeData = '';\r\n if (routeParams) {\r\n routeData += Object.entries(routeParams)\r\n .map(([key, value]) => `${key}=${value}`)\r\n .join(', ');\r\n } else {\r\n routeData = '.';\r\n }\r\n\r\n var routesStr = allRoutes.map(\r\n (x) =>\r\n ` * Name: '${x.name}', path: '${x.path}', target: ${\r\n x.target ?? 'default'\r\n }\\n`\r\n );\r\n return `No route matched '${routeNameOrUrl}${routeData}'. Available routes:\\n${routesStr}`;\r\n}\r\n\r\nfunction checkRouteGuards(routeResult: RouteMatchResult): boolean {\r\n if (\r\n !routeResult ||\r\n !routeResult.route.guards ||\r\n routeResult.route.guards.length == 0\r\n ) {\r\n return true;\r\n }\r\n\r\n for (let index = 0; index < routeResult.route.guards.length; index++) {\r\n const element = routeResult.route.guards[index];\r\n var result = element.check(routeResult);\r\n if (result == GuardResult.Allow) {\r\n return true;\r\n }\r\n\r\n if (result == GuardResult.Stop) {\r\n return false;\r\n }\r\n\r\n if (result == GuardResult.Deny) {\r\n throw new RouteGuardError(\r\n `Guard ${element.constructor.name} said 'Deny' for ${routeResult.route.name}`\r\n );\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["index_exports", "__export", "GuardResult", "NavigateRouteEvent", "RouteError", "RouteGuardError", "RouteLink", "RouteTarget", "clearPendingNavigations", "defineRoutes", "findRouteByName", "findRouteByUrl", "internalRoutes", "matchRoute", "navigate", "printRoutes", "registerRouteTarget", "startRouting", "unregisterRouteTarget", "__toCommonJS", "GuardResult", "RouteError", "RouteGuardError", "NavigateRouteEvent", "_NavigateRouteEvent", "route", "urlSegments", "routeData", "routeTarget", "eventInit", "RelaxError", "message", "context", "handler", "reportError", "message", "context", "error", "RelaxError", "handler", "suppressed", "targetHandlers", "pendingEvents", "registerRouteTarget", "name", "handler", "initRouteTargetListener", "error", "reportError", "pending", "unregisterRouteTarget", "clearPendingNavigations", "dispatchToTarget", "evt", "listenerAttached", "NavigateRouteEvent", "NumberRouteSegment", "paramName", "value", "pathValue", "StringRouteSegment", "PathRouteSegment", "_pathValue", "RouteImp", "route", "segments", "generatedSegments", "params", "index", "urlSegment", "ourSegment", "routeData", "urlSegments", "
|
|
4
|
+
"sourcesContent": ["export {\r\n GuardResult,\r\n RouteGuard,\r\n Route,\r\n RouteParamType,\r\n RouteData,\r\n Routable,\r\n LoadRoute,\r\n RouteError,\r\n RouteGuardError,\r\n NavigateOptions,\r\n RouteMatchResult,\r\n RouteSegmentType,\r\n RouteValue,\r\n} from './types';\r\n\r\nexport { NavigateRouteEvent } from './NavigateRouteEvent';\r\n\r\nexport {\r\n registerRouteTarget,\r\n unregisterRouteTarget,\r\n clearPendingNavigations,\r\n} from './routeTargetRegistry';\r\n\r\nexport {\r\n matchRoute,\r\n findRouteByName,\r\n findRouteByUrl,\r\n} from './routeMatching';\r\n\r\nexport {\r\n internalRoutes,\r\n defineRoutes,\r\n startRouting,\r\n navigate,\r\n printRoutes,\r\n} from './navigation';\r\n\r\nexport { RouteLink } from './RouteLink';\r\nexport { RouteTarget } from './RoutingTarget';\r\n", "/** @internal */\r\ntype WebComponentConstructor = new (...args: any[]) => HTMLElement;\r\n\r\nexport enum GuardResult {\r\n /**\r\n * Handle route without checking more guards.\r\n */\r\n Allow,\r\n\r\n /**\r\n * Throw a RouteGuardError.\r\n */\r\n Deny,\r\n\r\n /**\r\n * Resume and check other guards.\r\n */\r\n Continue,\r\n\r\n /**\r\n * Do not invoke the rooute nor other guards.\r\n */\r\n Stop\r\n}\r\n\r\nexport interface RouteGuard {\r\n check(route: RouteMatchResult): GuardResult;\r\n}\r\n\r\nexport interface Route {\r\n name?: string;\r\n target?: string;\r\n path: string;\r\n\r\n /**\r\n * HTML file name (without extension).\r\n *\r\n * Define for instance if you have a route that requires a more limited layout. The library\r\n * will automatically load that HTML file and rewrite URL history so that the correct url is displayed.\r\n */\r\n layout?: string;\r\n\r\n /**\r\n * Name of the tag for your web component.\r\n */\r\n componentTagName?: string;\r\n\r\n /**\r\n * Guards used to check if this route can be visited.\r\n */\r\n guards?: RouteGuard[];\r\n\r\n component?: WebComponentConstructor;\r\n}\r\n\r\nexport type RouteParamType = string | number;\r\nexport type RouteData = Record<string, RouteParamType>;\r\n\r\n/**\r\n * Implement to receive typed route parameters via a `routeData` property.\r\n * RouteTarget assigns `routeData` after element creation but before DOM insertion.\r\n * Optional since it's not available at construction time.\r\n *\r\n * For convention-based usage without undefined checks, skip the interface\r\n * and declare `routeData` directly on your component.\r\n *\r\n * @example\r\n * class UserProfile extends HTMLElement implements Routable<{ userName: string }> {\r\n * routeData?: { userName: string };\r\n * }\r\n */\r\nexport interface Routable<T extends RouteData = RouteData> {\r\n routeData?: T;\r\n}\r\n\r\n/**\r\n * Implement to run async initialization before the component is added to the DOM.\r\n * RouteTarget calls `loadRoute()` and awaits it before inserting the element.\r\n *\r\n * @example\r\n * class OrderDetail extends HTMLElement implements LoadRoute<{ orderId: number }> {\r\n * async loadRoute(data: { orderId: number }) {\r\n * this.order = await fetchOrder(data.orderId);\r\n * }\r\n * }\r\n */\r\nexport interface LoadRoute<T extends RouteData = RouteData> {\r\n loadRoute(data: T): void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Result from route matching operations.\r\n * Contains all information needed for navigation and rendering.\r\n */\r\nexport type RouteMatchResult = {\r\n /**\r\n * Matched route configuration\r\n */\r\n route: Route;\r\n\r\n /**\r\n * URL segments used for history state\r\n */\r\n urlSegments: string[];\r\n\r\n /**\r\n * Extracted and type-converted parameters\r\n */\r\n params: RouteData;\r\n};\r\n\r\n/**\r\n * Supported types of route segments\r\n */\r\nexport type RouteSegmentType = 'string' | 'number' | 'path' | 'regex';\r\n\r\n/**\r\n * Strongly typed route segment value\r\n */\r\nexport interface RouteValue {\r\n /**\r\n * Type of parameter for validation\r\n */\r\n type: RouteSegmentType;\r\n\r\n /**\r\n * Actual parameter value\r\n */\r\n value: any;\r\n}\r\n\r\nexport class RouteError extends Error {}\r\nexport class RouteGuardError extends RouteError {\r\n isGuard = true;\r\n}\r\n\r\nexport interface NavigateOptions {\r\n /**\r\n * Optional parameters when using route name\r\n */\r\n params?: Record<string, string | number>;\r\n\r\n /**\r\n * override for route's default target\r\n */\r\n target?: string;\r\n\r\n /**\r\n * When you want to override routes from the globally registered ones.\r\n */\r\n routes?: Route[];\r\n}\r\n", "import type { Route, RouteData } from './types';\r\n\r\n/**\r\n * Event sent to routing targets when a new route should be displayed.\r\n */\r\nexport class NavigateRouteEvent extends Event {\r\n static NAME: string = 'rlx.navigateRoute';\r\n constructor(\r\n /**\r\n * Matched route.\r\n */\r\n public route: Route,\r\n\r\n /**\r\n * The generated url sements which can be used to push the url into the browser history.\r\n */\r\n public urlSegments: string[],\r\n\r\n /**\r\n * Data supplied to the route.\r\n */\r\n public routeData?: RouteData,\r\n\r\n /**\r\n * The target can differ from the default target that is defined in the route.\r\n *\r\n * undefined means that the default (unnamed) target should be used.\r\n */\r\n public routeTarget?: string,\r\n\r\n eventInit?: EventInit\r\n ) {\r\n super(NavigateRouteEvent.NAME, eventInit);\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementEventMap {\r\n 'rlx.navigateRoute': NavigateRouteEvent;\r\n }\r\n interface DocumentEventMap {\r\n 'rlx.navigateRoute': NavigateRouteEvent;\r\n }\r\n}\r\n", "/**\r\n * Global error handling for Relaxjs.\r\n * Register a handler with `onError()` to intercept errors before they throw.\r\n * Call `ctx.suppress()` in the handler to prevent the error from being thrown.\r\n *\r\n * @example\r\n * import { onError } from 'relaxjs';\r\n *\r\n * onError((error, ctx) => {\r\n * logToService(error.message, error.context);\r\n * showToast(error.message);\r\n * ctx.suppress();\r\n * });\r\n */\r\n\r\n/**\r\n * Passed to error handlers to control error behavior.\r\n * Call `suppress()` to prevent the error from being thrown.\r\n */\r\nexport interface ErrorContext {\r\n suppress(): void;\r\n}\r\n\r\n/**\r\n * Error with structured context for debugging.\r\n * The `context` record contains details like route name, component tag, route data.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n * console.log(error.context.route);\r\n * console.log(error.context.componentTagName);\r\n * });\r\n */\r\nexport class RelaxError extends Error {\r\n constructor(\r\n message: string,\r\n public context: Record<string, unknown>,\r\n ) {\r\n super(message);\r\n }\r\n}\r\n\r\n/** @internal */\r\ntype ErrorHandler = (error: RelaxError, ctx: ErrorContext) => void;\r\n\r\nlet handler: ErrorHandler | null = null;\r\n\r\n/**\r\n * Registers a global error handler for Relaxjs errors.\r\n * The handler receives the error and an `ErrorContext`.\r\n * Call `ctx.suppress()` to prevent the error from being thrown.\r\n * Only one handler can be active at a time; subsequent calls replace the previous handler.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n * if (error.context.route === 'optional-panel') {\r\n * ctx.suppress();\r\n * return;\r\n * }\r\n * showErrorDialog(error.message);\r\n * });\r\n */\r\nexport function onError(fn: ErrorHandler) {\r\n handler = fn;\r\n}\r\n\r\n/**\r\n * Reports an error through the global handler.\r\n * Returns the `RelaxError` if it should be thrown, or `null` if the handler suppressed it.\r\n * The caller is responsible for throwing the returned error.\r\n *\r\n * @param message - Human-readable error description\r\n * @param context - Structured data for debugging (route, component, params, cause, etc.)\r\n * @returns The error to throw, or `null` if suppressed\r\n *\r\n * @example\r\n * const error = reportError('Failed to load route component', {\r\n * route: 'user',\r\n * componentTagName: 'user-profile',\r\n * routeData: { id: 123 },\r\n * });\r\n * if (error) throw error;\r\n */\r\nexport function reportError(message: string, context: Record<string, unknown>): RelaxError | null {\r\n const error = new RelaxError(message, context);\r\n if (handler) {\r\n let suppressed = false;\r\n const ctx: ErrorContext = {\r\n suppress() { suppressed = true; },\r\n };\r\n handler(error, ctx);\r\n if (suppressed) {\r\n return null;\r\n }\r\n }\r\n return error;\r\n}\r\n\r\n/**\r\n * Wraps an async function into a synchronous callback suitable for addEventListener.\r\n * Catches promise rejections and reports them through the global error handler.\r\n *\r\n * @param fn - Async function to wrap\r\n * @returns Synchronous function that can be passed to addEventListener\r\n *\r\n * @example\r\n * button.addEventListener('click', asyncHandler(async (e) => {\r\n * await saveData();\r\n * }));\r\n *\r\n * @example\r\n * form.addEventListener('submit', asyncHandler(async (e) => {\r\n * e.preventDefault();\r\n * await submitForm();\r\n * }));\r\n */\r\nexport function asyncHandler<TArgs extends unknown[]>(\r\n fn: (...args: TArgs) => Promise<void>,\r\n): (...args: TArgs) => void {\r\n return function (this: any, ...args: TArgs) {\r\n fn.call(this, ...args).catch((cause: unknown) => {\r\n const error = reportError('Async callback failed', { cause });\r\n if (error) throw error;\r\n });\r\n };\r\n}\r\n", "import { reportError } from '../errors';\r\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\r\n\r\n/** @internal */\r\ntype RouteTargetHandler = (evt: NavigateRouteEvent) => void;\r\nconst targetHandlers = new Map<string | undefined, RouteTargetHandler>();\r\nconst pendingEvents = new Map<string | undefined, NavigateRouteEvent>();\r\n\r\n/**\r\n * Registers a route target handler.\r\n * When a navigation event targets this name, the handler is called directly.\r\n * If a pending event exists for this target, it is replayed immediately.\r\n *\r\n * @param name - Target name, or `undefined` for the default (unnamed) target\r\n * @param handler - Callback that receives the `NavigateRouteEvent`\r\n *\r\n * @example\r\n * registerRouteTarget('sidebar', (evt) => renderComponent(evt));\r\n */\r\nexport function registerRouteTarget(\r\n name: string | undefined,\r\n handler: RouteTargetHandler,\r\n) {\r\n initRouteTargetListener();\r\n if (targetHandlers.has(name)) {\r\n const error = reportError('Duplicate route target', {\r\n target: name ?? 'default',\r\n });\r\n if (error) throw error;\r\n return;\r\n }\r\n targetHandlers.set(name, handler);\r\n\r\n const pending = pendingEvents.get(name);\r\n if (pending) {\r\n pendingEvents.delete(name);\r\n handler(pending);\r\n }\r\n}\r\n\r\n/**\r\n * Unregisters a previously registered route target handler.\r\n *\r\n * @param name - Target name that was passed to `registerRouteTarget`\r\n */\r\nexport function unregisterRouteTarget(name: string | undefined) {\r\n targetHandlers.delete(name);\r\n}\r\n\r\nexport function clearPendingNavigations() {\r\n pendingEvents.clear();\r\n targetHandlers.clear();\r\n}\r\n\r\nfunction dispatchToTarget(evt: NavigateRouteEvent) {\r\n const handler = targetHandlers.get(evt.routeTarget);\r\n if (handler) {\r\n handler(evt);\r\n } else {\r\n pendingEvents.set(evt.routeTarget, evt);\r\n }\r\n}\r\n\r\nlet listenerAttached = false;\r\n\r\nexport function initRouteTargetListener() {\r\n if (listenerAttached) return;\r\n listenerAttached = true;\r\n document.addEventListener(NavigateRouteEvent.NAME, (evt) => {\r\n dispatchToTarget(evt as NavigateRouteEvent);\r\n });\r\n}\r\n", "import type { Route, RouteData, RouteParamType, RouteMatchResult } from './types';\r\n\r\n/**\r\n * Route segment matcher interface.\r\n * Each segment type (string, number, path) implements this\r\n * for parameter extraction and validation.\r\n */\r\ninterface RouteSegment {\r\n /**\r\n * Parameter name when segment is dynamic (:name or ;id)\r\n */\r\n paramName?: string;\r\n\r\n /**\r\n * Validates if URL segment matches pattern\r\n * @param value Segment from URL to validate\r\n */\r\n isMatch(value: string): boolean;\r\n\r\n /**\r\n * Converts URL segment to typed parameter\r\n * @param pathValue Raw value from URL\r\n */\r\n getValue(pathValue: string): RouteParamType;\r\n}\r\n\r\n/**\r\n * Number parameter segment matcher.\r\n * Used for ;id style parameters that must be numbers.\r\n */\r\nclass NumberRouteSegment implements RouteSegment {\r\n constructor(public paramName: string) {}\r\n isMatch(value: string): boolean {\r\n if (/^\\d+$/.test(value)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n getValue(pathValue: string): RouteParamType {\r\n if (/^\\d+$/.test(pathValue) === false) {\r\n throw new Error(\r\n `Path is not a number, parameter name '${this.paramName}', value: '${pathValue}'.`\r\n );\r\n }\r\n return parseInt(pathValue);\r\n }\r\n}\r\n\r\n/**\r\n * String parameter segment matcher.\r\n * Used for :name style parameters.\r\n */\r\nclass StringRouteSegment implements RouteSegment {\r\n constructor(public paramName: string) {}\r\n isMatch(_value: string): boolean {\r\n return true;\r\n }\r\n\r\n /**\r\n *\r\n * @param pathValue the route data (for route by name) or segment extracted from the url (for url routing).\r\n * @returns\r\n */\r\n getValue(pathValue: string): RouteParamType {\r\n return pathValue;\r\n }\r\n}\r\n\r\n/**\r\n * Static path segment matcher.\r\n * Used for fixed URL parts like 'users' in /users/:id\r\n */\r\nclass PathRouteSegment implements RouteSegment {\r\n constructor(public value: string) {}\r\n isMatch(value: string): boolean {\r\n return value == this.value;\r\n }\r\n\r\n getValue(_pathValue: string): RouteParamType {\r\n return this.value;\r\n }\r\n}\r\n\r\n/**\r\n * Internal route implementation that handles segment matching\r\n * and parameter extraction.\r\n */\r\nclass RouteImp {\r\n constructor(public route: Route, private segments: RouteSegment[]) {}\r\n\r\n /**\r\n * Attempts to match URL segments against route pattern\r\n * @param segments URL parts to match\r\n * @returns Match result with parameters if successful\r\n */\r\n match(segments: string[]): RouteMatchResult | null {\r\n if (segments.length != this.segments.length) {\r\n return null;\r\n }\r\n\r\n const generatedSegments: string[] = [];\r\n var params: RouteData = {};\r\n for (let index = 0; index < segments.length; index++) {\r\n const urlSegment = segments[index];\r\n const ourSegment = this.segments[index];\r\n\r\n if (!ourSegment.isMatch(urlSegment)) {\r\n return null;\r\n }\r\n\r\n if (ourSegment.paramName) {\r\n const value = ourSegment.getValue(urlSegment);\r\n params[ourSegment.paramName] = value;\r\n generatedSegments.push(value.toString());\r\n } else {\r\n generatedSegments.push(urlSegment);\r\n }\r\n }\r\n\r\n return { route: this.route, params, urlSegments: generatedSegments };\r\n }\r\n\r\n /**\r\n * Routing by name and route data, so generate the url segments.\r\n * @param routeData Data to use in the URL.\r\n * @returns Match result with parameters if successful\r\n */\r\n buildUrl(routeData: RouteData): RouteMatchResult | null {\r\n const urlSegments: string[] = [];\r\n for (let index = 0; index < this.segments.length; index++) {\r\n const ourSegment = this.segments[index];\r\n if (ourSegment.paramName) {\r\n var value = routeData[ourSegment.paramName];\r\n if (!value) {\r\n throw new Error(\r\n `Route \"${\r\n this.route.name\r\n }\" did not get value for parameter \"${\r\n ourSegment.paramName\r\n } from the provided routeData: \"${JSON.stringify(\r\n routeData\r\n )}\".`\r\n );\r\n }\r\n\r\n urlSegments.push(value.toString());\r\n } else {\r\n urlSegments.push(ourSegment.getValue('').toString());\r\n }\r\n }\r\n\r\n return { route: this.route, params: routeData, urlSegments };\r\n }\r\n\r\n}\r\n\r\n/**\r\n * Match route by either name or URL pattern\r\n * @param routes Available routes\r\n * @param routeNameOrUrl Route name or URL to match\r\n * @param routeData Optional parameters for named routes\r\n */\r\nexport function matchRoute(\r\n routes: Route[],\r\n routeNameOrUrl: string,\r\n routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n if (routeNameOrUrl === '' || routeNameOrUrl.indexOf('/') >= 0) {\r\n return findRouteByUrl(routes, routeNameOrUrl || '/');\r\n } else {\r\n return findRouteByName(routes, routeNameOrUrl, routeData!);\r\n }\r\n}\r\n\r\n/**\r\n * Find route by name and apply parameters\r\n * @param routes Available routes\r\n * @param name Route name to find\r\n * @param routeData Parameters to apply\r\n */\r\nexport function findRouteByName(\r\n routes: Route[],\r\n name: string,\r\n routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n var route = routes.find((x) => x.name === name);\r\n if (!route) {\r\n return null;\r\n }\r\n\r\n var imp = generateRouteImp(route);\r\n var result = imp.buildUrl(routeData ?? {});\r\n return result;\r\n}\r\n\r\n/**\r\n * Find route matching URL pattern\r\n * @param routes Available routes\r\n * @param path URL to match\r\n */\r\nexport function findRouteByUrl(\r\n routes: Route[],\r\n path: string\r\n): RouteMatchResult | null {\r\n const urlSegments = path.replace(/^\\/|\\/$/g, '').split('/');\r\n const routeImps = generateRouteImps(routes);\r\n\r\n for (let index = 0; index < routeImps.length; index++) {\r\n const element = routeImps[index];\r\n const m = element.match(urlSegments);\r\n if (m) {\r\n return m;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Generate implementations for all routes\r\n */\r\nfunction generateRouteImps(routes: Route[]) {\r\n const routeImps: RouteImp[] = [];\r\n routes.forEach((route) => {\r\n var imp = generateRouteImp(route);\r\n routeImps.push(imp);\r\n });\r\n\r\n return routeImps;\r\n}\r\n\r\n/**\r\n * Generate implementation for single route\r\n * Parses URL pattern into segment matchers\r\n */\r\nfunction generateRouteImp(route: Route): RouteImp {\r\n var impSegments: RouteSegment[] = [];\r\n const segments = route.path.replace(/^\\/|\\/$/g, '').split('/');\r\n segments.forEach((segment) => {\r\n if (segment.substring(0, 1) == ':') {\r\n impSegments.push(new StringRouteSegment(segment.substring(1)));\r\n } else if (segment.substring(0, 1) === ';') {\r\n impSegments.push(new NumberRouteSegment(segment.substring(1)));\r\n } else if (segment.substring(0, 1) === '{') {\r\n } else {\r\n impSegments.push(new PathRouteSegment(segment));\r\n }\r\n });\r\n\r\n var imp = new RouteImp(route, impSegments);\r\n return imp;\r\n}\r\n", "import { navigate, printRoutes } from './navigation';\r\nimport { RelaxError, reportError } from '../errors';\r\n\r\nexport class RouteLink extends HTMLElement {\r\n static get observedAttributes() {\r\n return ['name', 'target', 'params'];\r\n }\r\n\r\n constructor() {\r\n super();\r\n this.addEventListener('click', e => this.handleClick(e));\r\n }\r\n\r\n private handleClick(e: MouseEvent) {\r\n e.preventDefault();\r\n \r\n const name = this.getAttribute('name');\r\n if (!name) return;\r\n\r\n console.log('Calling printRoutes from RouteLink in relaxjs/components');\r\n printRoutes();\r\n \r\n const params: Record<string, string> = {};\r\n for (const attr of Array.from(this.attributes)) {\r\n if (attr.name.startsWith('param-')) {\r\n const paramName = attr.name.substring(6);\r\n params[paramName] = attr.value;\r\n }\r\n }\r\n\r\n const paramsAttr = this.getAttribute('params');\r\n let additionalParams: Record<string, string | number> | undefined;\r\n if (paramsAttr) {\r\n try {\r\n const parsed = JSON.parse(paramsAttr);\r\n additionalParams = parsed as Record<string, string | number>;\r\n } catch (error) {\r\n const err = reportError('Failed to parse route params', {\r\n element: 'r-link',\r\n params: paramsAttr,\r\n cause: error,\r\n });\r\n if (err) throw err;\r\n }\r\n }\r\n\r\n const target = this.getAttribute('target');\r\n if (additionalParams){\r\n Object.assign(params, additionalParams);\r\n }\r\n\r\n try {\r\n navigate(name, { params, target: target || undefined });\r\n } catch (error) {\r\n if (error instanceof RelaxError) throw error;\r\n const reported = reportError('Navigation failed', {\r\n element: 'r-link',\r\n route: name,\r\n params,\r\n target,\r\n cause: error,\r\n });\r\n if (reported) throw reported;\r\n }\r\n }\r\n\r\n connectedCallback() {\r\n if (!this.hasAttribute('tabindex')) {\r\n this.setAttribute('tabindex', '0');\r\n }\r\n \r\n this.style.cursor = 'pointer';\r\n this.role = 'link';\r\n }\r\n\r\n disconnectedCallback() {\r\n this.removeEventListener('click', this.handleClick);\r\n }\r\n}", "import { registerRouteTarget, unregisterRouteTarget } from './routeTargetRegistry';\r\nimport type { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport type { RouteData, LoadRoute } from './types';\r\nimport { RelaxError, reportError } from '../errors';\r\n\r\n/**\r\n * WebComponent that listens on the `NavigateRouteEvent` event to be able to switch route.\r\n *\r\n * Use the \"name\" attribute to make this non-default target.\r\n * Use the \"dialog\" attribute to render routes inside a native `<dialog>` element\r\n * with built-in focus trapping, backdrop, and Escape-to-close.\r\n *\r\n * @example\r\n * <r-route-target></r-route-target>\r\n * <r-route-target name=\"modal\" dialog></r-route-target>\r\n */\r\nexport class RouteTarget extends HTMLElement {\r\n name?: string = undefined;\r\n private dialog?: HTMLDialogElement;\r\n\r\n connectedCallback() {\r\n this.name = this.getAttribute('name') ?? undefined;\r\n\r\n if (this.hasAttribute('dialog')) {\r\n this.dialog = document.createElement('dialog');\r\n this.dialog.addEventListener('close', () => {\r\n this.dialog!.replaceChildren();\r\n });\r\n this.appendChild(this.dialog);\r\n }\r\n\r\n registerRouteTarget(this.name, (evt) => this.onNavigate(evt));\r\n console.log('registered');\r\n }\r\n\r\n disconnectedCallback() {\r\n unregisterRouteTarget(this.name);\r\n }\r\n\r\n private onNavigate(evt: NavigateRouteEvent) {\r\n console.log('got nav', evt);\r\n this.loadComponent(evt).catch((error) => {\r\n if (!(error instanceof RelaxError)) {\r\n error = reportError('Route navigation failed', {\r\n route: evt.route.name,\r\n routeTarget: evt.routeTarget,\r\n cause: error,\r\n });\r\n }\r\n if (error) {\r\n console.error(error);\r\n }\r\n });\r\n }\r\n\r\n private async loadComponent(evt: NavigateRouteEvent) {\r\n const tagName = evt.route.componentTagName\r\n ?? (evt.route.component ? customElements.getName(evt.route.component) : null);\r\n\r\n if (!tagName) {\r\n const error = reportError('Failed to find component for route', {\r\n route: evt.route.name,\r\n componentTagName: evt.route.componentTagName,\r\n component: evt.route.component?.name,\r\n routeData: evt.routeData,\r\n });\r\n if (error) throw error;\r\n return;\r\n }\r\n\r\n await customElements.whenDefined(tagName);\r\n const element = document.createElement(tagName);\r\n\r\n await this.applyRouteData(element, evt.routeData);\r\n\r\n if (this.dialog) {\r\n this.dialog.replaceChildren(element);\r\n if (!this.dialog.open) {\r\n this.dialog.showModal();\r\n }\r\n } else if (document.startViewTransition) {\r\n document.startViewTransition(() => this.replaceChildren(element));\r\n } else {\r\n this.replaceChildren(element);\r\n }\r\n }\r\n\r\n /** Closes the dialog (only applies to dialog targets). */\r\n close() {\r\n this.dialog?.close();\r\n }\r\n\r\n private async applyRouteData(element: Element, data?: RouteData) {\r\n if ('loadRoute' in element) {\r\n const routeData = data\r\n ?? { error: 'loadRoute function without mapped route data in the routes' };\r\n await (element as unknown as LoadRoute).loadRoute(routeData);\r\n }\r\n\r\n if (data) {\r\n (element as any).routeData = data;\r\n }\r\n }\r\n}\r\n", "/**\r\n * Single Page Application routing system with multiple target support.\r\n * Designed for scenarios where you need:\r\n * - Multiple navigation targets (main content, modals, sidebars)\r\n * - Strongly typed route parameters\r\n * - History management with back/forward support\r\n *\r\n * @example\r\n * // Configure routes\r\n * const routes = [\r\n * { name: 'user', path: '/users/:id' }, // String parameter\r\n * { name: 'order', path: '/orders/;orderId' }, // Number parameter\r\n * { name: 'modal', path: '/detail/:id', target: 'modal' } // Custom target\r\n * ];\r\n */\r\n\r\nimport { reportError } from '../errors';\r\nimport {\r\n GuardResult,\r\n RouteError,\r\n RouteGuardError,\r\n type Route,\r\n type RouteParamType,\r\n type RouteMatchResult,\r\n type NavigateOptions,\r\n} from './types';\r\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport { matchRoute } from './routeMatching';\r\nimport { initRouteTargetListener } from './routeTargetRegistry';\r\nimport { RouteLink } from './RouteLink';\r\nimport { RouteTarget } from './RoutingTarget';\r\n\r\n/**\r\n * Used to keep track of current main HTML file,\r\n * used when different layouts are supported.\r\n *\r\n * The default page is ALWAYS loaded initially,\r\n * which means that we need to switch layout page\r\n * if someone else is configured for the route.\r\n */\r\nvar currentLayout: string | undefined;\r\n\r\nfunction getCurrentLayout(): string {\r\n if (currentLayout === undefined) {\r\n currentLayout = getLayout() ?? 'default';\r\n }\r\n return currentLayout;\r\n}\r\n\r\nfunction getLayout() {\r\n const path = window.location.pathname;\r\n if (path == '/index.html') {\r\n return 'default';\r\n }\r\n\r\n return path.endsWith('.html') ? path.slice(1, -5) : null;\r\n}\r\n\r\nexport const internalRoutes: Route[] = [];\r\n\r\nexport const MyData = {\r\n routes: []\r\n};\r\n\r\n/**\r\n * Debug helper to print all registered routes to console.\r\n */\r\nexport function printRoutes() {\r\n console.log(internalRoutes);\r\n}\r\n\r\n/**\r\n * Registers application routes with the router.\r\n * Call this at application startup before routing begins.\r\n *\r\n * @param appRoutes - Array of route configurations\r\n * @throws Error if referenced components are not registered\r\n *\r\n * @example\r\n * const routes: Route[] = [\r\n * { name: 'home', path: '/', componentTagName: 'app-home' },\r\n * { name: 'user', path: '/users/:id', componentTagName: 'user-profile' },\r\n * { name: 'login', path: '/auth/', componentTagName: 'login-form', layout: 'noauth' }\r\n * ];\r\n * defineRoutes(routes);\r\n */\r\nexport function defineRoutes(appRoutes: Route[]) {\r\n console.log('defining routes1', appRoutes);\r\n initRouteTargetListener();\r\n if (!customElements.get('r-route-target')) {\r\n customElements.define('r-route-target', RouteTarget);\r\n }\r\n if (!customElements.get('r-link')) {\r\n customElements.define('r-link', RouteLink);\r\n }\r\n console.log('defining routes', appRoutes);\r\n internalRoutes.length = 0;\r\n internalRoutes.push(...appRoutes);\r\n\r\n var errs: string[] = [];\r\n appRoutes.forEach((route) => {\r\n if (\r\n route.componentTagName &&\r\n !customElements.get(route.componentTagName)\r\n ) {\r\n errs.push(\r\n `Component with tagName '${route.componentTagName}' is not defined in customElements.`\r\n );\r\n }\r\n if (route.component && !customElements.getName(route.component)) {\r\n errs.push(\r\n `Component '${route.component.name}' is not defined in customElements. Used in route '${JSON.stringify(route)}'.`\r\n );\r\n }\r\n if (route.layout === '') {\r\n console.log('should not use empty string layout.', route);\r\n route.layout = undefined;\r\n }\r\n });\r\n\r\n if (errs.length > 0) {\r\n throw new Error(errs.join('\\n'));\r\n }\r\n}\r\n\r\n/**\r\n * Initializes routing and navigates to the current URL.\r\n * Call this after DOM is ready and routes are defined.\r\n *\r\n * @example\r\n * // In your main application component\r\n * connectedCallback() {\r\n * defineRoutes(routes);\r\n * startRouting();\r\n * }\r\n */\r\nexport function startRouting() {\r\n if (getCurrentLayout() == '') {\r\n const path = window.location.pathname;\r\n const match = path.match(/\\/([^\\/]+)\\.html$/);\r\n if (match && match[1] !== '') {\r\n console.log('setting current layut', match[1]);\r\n currentLayout = match[1];\r\n } else {\r\n console.log('Setting default layout name');\r\n currentLayout = 'default';\r\n }\r\n }\r\n\r\n if (tryLoadRouteFromLayoutNavigation()) {\r\n return;\r\n }\r\n\r\n const currentUrl = window.location.pathname.replace(/^\\/|\\/$/g, '') || '/';\r\n const routeResult = findRoute(currentUrl, {});\r\n\r\n const searchParams = new URLSearchParams(window.location.search);\r\n if (searchParams.size > 0) {\r\n routeResult.params ??= {};\r\n searchParams.forEach((value, key) => {\r\n routeResult.params[key] = value;\r\n });\r\n }\r\n\r\n if (navigateToLayout(routeResult)) {\r\n return;\r\n }\r\n\r\n history.replaceState(\r\n routeResult.urlSegments,\r\n '',\r\n '/' + routeResult.urlSegments.join('/')\r\n );\r\n\r\n const e = new NavigateRouteEvent(\r\n routeResult.route,\r\n routeResult.urlSegments,\r\n routeResult.params,\r\n routeResult.route.target\r\n );\r\n document.dispatchEvent(e);\r\n}\r\n\r\n/**\r\n * Navigates to a route by name or URL.\r\n * Updates browser history and dispatches navigation events.\r\n *\r\n * @param routeNameOrUrl - Route name or URL path to navigate to\r\n * @param options - Navigation options including params and target\r\n *\r\n * @example\r\n * // Navigate by route name\r\n * navigate('user', { params: { id: '123' } });\r\n *\r\n * // Navigate by URL\r\n * navigate('/users/123');\r\n *\r\n * // Navigate to specific target\r\n * navigate('detail', { params: { id: '42' }, target: 'modal' });\r\n */\r\nexport function navigate(routeNameOrUrl: string, options?: NavigateOptions) {\r\n console.log('navigating to ', routeNameOrUrl, options);\r\n const routeResult = findRoute(routeNameOrUrl, options);\r\n if (navigateToLayout(routeResult)) {\r\n return;\r\n }\r\n\r\n const target = options?.target ?? routeResult.route.target;\r\n const ourUrl = routeResult.urlSegments.join('/');\r\n const currentUrl = window.location.pathname.replace(/^\\/|\\/$/g, '');\r\n if (currentUrl != ourUrl) {\r\n history.pushState(\r\n routeResult.urlSegments,\r\n '',\r\n '/' + routeResult.urlSegments.join('/')\r\n );\r\n }\r\n const e = new NavigateRouteEvent(\r\n routeResult.route,\r\n routeResult.urlSegments,\r\n routeResult.params,\r\n target\r\n );\r\n document.dispatchEvent(e);\r\n}\r\n\r\nfunction findRoute(routeNameOrUrl: string, options?: NavigateOptions) {\r\n const theRoutes = options?.routes ?? internalRoutes;\r\n const params = options?.params;\r\n\r\n const routeResult = matchRoute(theRoutes, routeNameOrUrl, params);\r\n if (!routeResult) {\r\n const errorMsg = generateErrorMessage(\r\n routeNameOrUrl,\r\n params,\r\n theRoutes\r\n );\r\n console.error(errorMsg);\r\n throw new RouteError(errorMsg);\r\n }\r\n\r\n if (!checkRouteGuards(routeResult)) {\r\n throw new RouteGuardError('Route guards stopped navigation for route ' + routeNameOrUrl);\r\n }\r\n\r\n return routeResult;\r\n}\r\n\r\nfunction navigateToLayout(routeResult: RouteMatchResult): boolean {\r\n if (!routeResult) {\r\n console.error('Route result is null, cannot navigate to layout.');\r\n }\r\n\r\n const wantedLayout = (routeResult.route.layout ?? 'default').replace(\r\n /\\.html?$/,\r\n ''\r\n );\r\n if (wantedLayout === getCurrentLayout()) {\r\n return false;\r\n }\r\n\r\n console.log(\r\n 'Current layout: ' + getCurrentLayout(),\r\n 'Wanted layout: ' + wantedLayout\r\n );\r\n\r\n // The hash means that we attempted to redirect to the same layout once,\r\n // so if it's there and another redirect is requsted, something is wrong.\r\n //\r\n // Because the push history should remove it if everything worked out.\r\n if (window.location.hash) {\r\n throw Error(\r\n 'A redirect failed, does the requsted layout exist? \"' +\r\n wantedLayout +\r\n '\"?'\r\n );\r\n }\r\n\r\n console.log(\r\n `requires layout switch from ${getCurrentLayout()} to ${wantedLayout}`\r\n );\r\n const navigationState = {\r\n routeName: routeResult.route.name,\r\n params: routeResult.params || {}\r\n };\r\n\r\n sessionStorage.setItem('layoutNavigation', JSON.stringify(navigationState));\r\n const layoutUrl =\r\n wantedLayout.indexOf('.htm') > -1\r\n ? `/${wantedLayout}#layout`\r\n : `/${wantedLayout}.html#layout`;\r\n console.log('redirecting to ', layoutUrl);\r\n window.location.href = layoutUrl;\r\n return true;\r\n}\r\n/**\r\n * Checks session storage for route information and initiates proper navigation\r\n * Should be called when page loads to handle layout transitions\r\n *\r\n * @returns Whether navigation was initiated from session storage\r\n *\r\n * @example\r\n * // Call on page load\r\n * document.addEventListener('DOMContentLoaded', () => {\r\n * if (handleLayoutNavigation()) {\r\n * console.log('Navigation handled from session storage');\r\n * }\r\n * });\r\n */\r\nfunction tryLoadRouteFromLayoutNavigation(): boolean {\r\n try {\r\n const navigationStateJson = sessionStorage.getItem('layoutNavigation');\r\n if (!navigationStateJson) {\r\n return false;\r\n }\r\n\r\n const navigationState = JSON.parse(navigationStateJson);\r\n sessionStorage.removeItem('layoutNavigation');\r\n console.log('session store navigation ', navigationState);\r\n navigate(navigationState.routeName, {\r\n params: navigationState.params\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n sessionStorage.removeItem('layoutNavigation');\r\n reportError('Failed to navigate from session storage', {\r\n cause: error,\r\n });\r\n return false;\r\n }\r\n}\r\n\r\nfunction generateErrorMessage(\r\n routeNameOrUrl: string,\r\n routeParams: Record<string, RouteParamType> | undefined,\r\n allRoutes: Route[]\r\n): string {\r\n var routeData = '';\r\n if (routeParams) {\r\n routeData += Object.entries(routeParams)\r\n .map(([key, value]) => `${key}=${value}`)\r\n .join(', ');\r\n } else {\r\n routeData = '.';\r\n }\r\n\r\n var routesStr = allRoutes.map(\r\n (x) =>\r\n ` * Name: '${x.name}', path: '${x.path}', target: ${\r\n x.target ?? 'default'\r\n }\\n`\r\n );\r\n return `No route matched '${routeNameOrUrl}${routeData}'. Available routes:\\n${routesStr}`;\r\n}\r\n\r\nfunction checkRouteGuards(routeResult: RouteMatchResult): boolean {\r\n if (\r\n !routeResult ||\r\n !routeResult.route.guards ||\r\n routeResult.route.guards.length == 0\r\n ) {\r\n return true;\r\n }\r\n\r\n for (let index = 0; index < routeResult.route.guards.length; index++) {\r\n const element = routeResult.route.guards[index];\r\n var result = element.check(routeResult);\r\n if (result == GuardResult.Allow) {\r\n return true;\r\n }\r\n\r\n if (result == GuardResult.Stop) {\r\n return false;\r\n }\r\n\r\n if (result == GuardResult.Deny) {\r\n throw new RouteGuardError(\r\n `Guard ${element.constructor.name} said 'Deny' for ${routeResult.route.name}`\r\n );\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["index_exports", "__export", "GuardResult", "NavigateRouteEvent", "RouteError", "RouteGuardError", "RouteLink", "RouteTarget", "clearPendingNavigations", "defineRoutes", "findRouteByName", "findRouteByUrl", "internalRoutes", "matchRoute", "navigate", "printRoutes", "registerRouteTarget", "startRouting", "unregisterRouteTarget", "__toCommonJS", "GuardResult", "RouteError", "RouteGuardError", "NavigateRouteEvent", "_NavigateRouteEvent", "route", "urlSegments", "routeData", "routeTarget", "eventInit", "RelaxError", "message", "context", "handler", "reportError", "message", "context", "error", "RelaxError", "handler", "suppressed", "targetHandlers", "pendingEvents", "registerRouteTarget", "name", "handler", "initRouteTargetListener", "error", "reportError", "pending", "unregisterRouteTarget", "clearPendingNavigations", "dispatchToTarget", "evt", "listenerAttached", "NavigateRouteEvent", "NumberRouteSegment", "paramName", "value", "pathValue", "StringRouteSegment", "_value", "PathRouteSegment", "_pathValue", "RouteImp", "route", "segments", "generatedSegments", "params", "index", "urlSegment", "ourSegment", "routeData", "urlSegments", "matchRoute", "routes", "routeNameOrUrl", "findRouteByUrl", "findRouteByName", "name", "x", "imp", "generateRouteImp", "result", "path", "routeImps", "generateRouteImps", "m", "impSegments", "segment", "RouteLink", "e", "name", "printRoutes", "params", "attr", "paramName", "paramsAttr", "additionalParams", "error", "err", "reportError", "target", "navigate", "RelaxError", "reported", "RouteTarget", "registerRouteTarget", "evt", "unregisterRouteTarget", "error", "RelaxError", "reportError", "tagName", "element", "data", "routeData", "currentLayout", "getCurrentLayout", "getLayout", "path", "internalRoutes", "printRoutes", "internalRoutes", "defineRoutes", "appRoutes", "initRouteTargetListener", "RouteTarget", "RouteLink", "errs", "route", "startRouting", "getCurrentLayout", "match", "currentLayout", "tryLoadRouteFromLayoutNavigation", "currentUrl", "routeResult", "findRoute", "searchParams", "value", "key", "navigateToLayout", "e", "NavigateRouteEvent", "navigate", "routeNameOrUrl", "options", "target", "ourUrl", "theRoutes", "params", "matchRoute", "errorMsg", "generateErrorMessage", "RouteError", "checkRouteGuards", "RouteGuardError", "wantedLayout", "navigationState", "layoutUrl", "navigationStateJson", "error", "reportError", "routeParams", "allRoutes", "routeData", "routesStr", "x", "index", "element", "result"]
|
|
7
7
|
}
|
package/dist/routing/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var w=(n=>(n[n.Allow=0]="Allow",n[n.Deny=1]="Deny",n[n.Continue=2]="Continue",n[n.Stop=3]="Stop",n))(w||{}),m=class extends Error{},p=class extends m{constructor(){super(...arguments);this.isGuard=!0}};var l=class r extends Event{constructor(
|
|
2
|
-
`))}function
|
|
1
|
+
var w=(n=>(n[n.Allow=0]="Allow",n[n.Deny=1]="Deny",n[n.Continue=2]="Continue",n[n.Stop=3]="Stop",n))(w||{}),m=class extends Error{},p=class extends m{constructor(){super(...arguments);this.isGuard=!0}};var l=class r extends Event{constructor(e,o,n,a,i){super(r.NAME,i);this.route=e;this.urlSegments=o;this.routeData=n;this.routeTarget=a}static{this.NAME="rlx.navigateRoute"}};var g=class extends Error{constructor(e,o){super(e);this.context=o}},L=null;function u(r,t){let e=new g(r,t);if(L){let o=!1;if(L(e,{suppress(){o=!0}}),o)return null}return e}var d=new Map,y=new Map;function N(r,t){if(b(),d.has(r)){let o=u("Duplicate route target",{target:r??"default"});if(o)throw o;return}d.set(r,t);let e=y.get(r);e&&(y.delete(r),t(e))}function T(r){d.delete(r)}function O(){y.clear(),d.clear()}function J(r){let t=d.get(r.routeTarget);t?t(r):y.set(r.routeTarget,r)}var A=!1;function b(){A||(A=!0,document.addEventListener(l.NAME,r=>{J(r)}))}var S=class{constructor(t){this.paramName=t}isMatch(t){return!!/^\d+$/.test(t)}getValue(t){if(/^\d+$/.test(t)===!1)throw new Error(`Path is not a number, parameter name '${this.paramName}', value: '${t}'.`);return parseInt(t)}},M=class{constructor(t){this.paramName=t}isMatch(t){return!0}getValue(t){return t}},D=class{constructor(t){this.value=t}isMatch(t){return t==this.value}getValue(t){return this.value}},$=class{constructor(t,e){this.route=t;this.segments=e}match(t){if(t.length!=this.segments.length)return null;let e=[];var o={};for(let n=0;n<t.length;n++){let a=t[n],i=this.segments[n];if(!i.isMatch(a))return null;if(i.paramName){let s=i.getValue(a);o[i.paramName]=s,e.push(s.toString())}else e.push(a)}return{route:this.route,params:o,urlSegments:e}}buildUrl(t){let e=[];for(let n=0;n<this.segments.length;n++){let a=this.segments[n];if(a.paramName){var o=t[a.paramName];if(!o)throw new Error(`Route "${this.route.name}" did not get value for parameter "${a.paramName} from the provided routeData: "${JSON.stringify(t)}".`);e.push(o.toString())}else e.push(a.getValue("").toString())}return{route:this.route,params:t,urlSegments:e}}};function C(r,t,e){return t===""||t.indexOf("/")>=0?H(r,t||"/"):P(r,t,e)}function P(r,t,e){var o=r.find(i=>i.name===t);if(!o)return null;var n=I(o),a=n.buildUrl(e??{});return a}function H(r,t){let e=t.replace(/^\/|\/$/g,"").split("/"),o=U(r);for(let n=0;n<o.length;n++){let i=o[n].match(e);if(i)return i}return null}function U(r){let t=[];return r.forEach(e=>{var o=I(e);t.push(o)}),t}function I(r){var t=[];r.path.replace(/^\/|\/$/g,"").split("/").forEach(n=>{n.substring(0,1)==":"?t.push(new M(n.substring(1))):n.substring(0,1)===";"?t.push(new S(n.substring(1))):n.substring(0,1)==="{"||t.push(new D(n))});var o=new $(r,t);return o}var f=class extends HTMLElement{static get observedAttributes(){return["name","target","params"]}constructor(){super(),this.addEventListener("click",t=>this.handleClick(t))}handleClick(t){t.preventDefault();let e=this.getAttribute("name");if(!e)return;console.log("Calling printRoutes from RouteLink in relaxjs/components"),k();let o={};for(let s of Array.from(this.attributes))if(s.name.startsWith("param-")){let c=s.name.substring(6);o[c]=s.value}let n=this.getAttribute("params"),a;if(n)try{a=JSON.parse(n)}catch(s){let c=u("Failed to parse route params",{element:"r-link",params:n,cause:s});if(c)throw c}let i=this.getAttribute("target");a&&Object.assign(o,a);try{x(e,{params:o,target:i||void 0})}catch(s){if(s instanceof g)throw s;let c=u("Navigation failed",{element:"r-link",route:e,params:o,target:i,cause:s});if(c)throw c}}connectedCallback(){this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.style.cursor="pointer",this.role="link"}disconnectedCallback(){this.removeEventListener("click",this.handleClick)}};var h=class extends HTMLElement{constructor(){super(...arguments);this.name=void 0}connectedCallback(){this.name=this.getAttribute("name")??void 0,this.hasAttribute("dialog")&&(this.dialog=document.createElement("dialog"),this.dialog.addEventListener("close",()=>{this.dialog.replaceChildren()}),this.appendChild(this.dialog)),N(this.name,e=>this.onNavigate(e)),console.log("registered")}disconnectedCallback(){T(this.name)}onNavigate(e){console.log("got nav",e),this.loadComponent(e).catch(o=>{o instanceof g||(o=u("Route navigation failed",{route:e.route.name,routeTarget:e.routeTarget,cause:o})),o&&console.error(o)})}async loadComponent(e){let o=e.route.componentTagName??(e.route.component?customElements.getName(e.route.component):null);if(!o){let a=u("Failed to find component for route",{route:e.route.name,componentTagName:e.route.componentTagName,component:e.route.component?.name,routeData:e.routeData});if(a)throw a;return}await customElements.whenDefined(o);let n=document.createElement(o);await this.applyRouteData(n,e.routeData),this.dialog?(this.dialog.replaceChildren(n),this.dialog.open||this.dialog.showModal()):document.startViewTransition?document.startViewTransition(()=>this.replaceChildren(n)):this.replaceChildren(n)}close(){this.dialog?.close()}async applyRouteData(e,o){if("loadRoute"in e){let n=o??{error:"loadRoute function without mapped route data in the routes"};await e.loadRoute(n)}o&&(e.routeData=o)}};var R;function E(){return R===void 0&&(R=W()??"default"),R}function W(){let r=window.location.pathname;return r=="/index.html"?"default":r.endsWith(".html")?r.slice(1,-5):null}var v=[];function k(){console.log(v)}function B(r){console.log("defining routes1",r),b(),customElements.get("r-route-target")||customElements.define("r-route-target",h),customElements.get("r-link")||customElements.define("r-link",f),console.log("defining routes",r),v.length=0,v.push(...r);var t=[];if(r.forEach(e=>{e.componentTagName&&!customElements.get(e.componentTagName)&&t.push(`Component with tagName '${e.componentTagName}' is not defined in customElements.`),e.component&&!customElements.getName(e.component)&&t.push(`Component '${e.component.name}' is not defined in customElements. Used in route '${JSON.stringify(e)}'.`),e.layout===""&&(console.log("should not use empty string layout.",e),e.layout=void 0)}),t.length>0)throw new Error(t.join(`
|
|
2
|
+
`))}function F(){if(E()==""){let a=window.location.pathname.match(/\/([^\/]+)\.html$/);a&&a[1]!==""?(console.log("setting current layut",a[1]),R=a[1]):(console.log("Setting default layout name"),R="default")}if(q())return;let r=window.location.pathname.replace(/^\/|\/$/g,"")||"/",t=V(r,{}),e=new URLSearchParams(window.location.search);if(e.size>0&&(t.params??={},e.forEach((n,a)=>{t.params[a]=n})),j(t))return;history.replaceState(t.urlSegments,"","/"+t.urlSegments.join("/"));let o=new l(t.route,t.urlSegments,t.params,t.route.target);document.dispatchEvent(o)}function x(r,t){console.log("navigating to ",r,t);let e=V(r,t);if(j(e))return;let o=t?.target??e.route.target,n=e.urlSegments.join("/");window.location.pathname.replace(/^\/|\/$/g,"")!=n&&history.pushState(e.urlSegments,"","/"+e.urlSegments.join("/"));let i=new l(e.route,e.urlSegments,e.params,o);document.dispatchEvent(i)}function V(r,t){let e=t?.routes??v,o=t?.params,n=C(e,r,o);if(!n){let a=G(r,o,e);throw console.error(a),new m(a)}if(!z(n))throw new p("Route guards stopped navigation for route "+r);return n}function j(r){r||console.error("Route result is null, cannot navigate to layout.");let t=(r.route.layout??"default").replace(/\.html?$/,"");if(t===E())return!1;if(console.log("Current layout: "+E(),"Wanted layout: "+t),window.location.hash)throw Error('A redirect failed, does the requsted layout exist? "'+t+'"?');console.log(`requires layout switch from ${E()} to ${t}`);let e={routeName:r.route.name,params:r.params||{}};sessionStorage.setItem("layoutNavigation",JSON.stringify(e));let o=t.indexOf(".htm")>-1?`/${t}#layout`:`/${t}.html#layout`;return console.log("redirecting to ",o),window.location.href=o,!0}function q(){try{let r=sessionStorage.getItem("layoutNavigation");if(!r)return!1;let t=JSON.parse(r);return sessionStorage.removeItem("layoutNavigation"),console.log("session store navigation ",t),x(t.routeName,{params:t.params}),!0}catch(r){return sessionStorage.removeItem("layoutNavigation"),u("Failed to navigate from session storage",{cause:r}),!1}}function G(r,t,e){var o="";t?o+=Object.entries(t).map(([a,i])=>`${a}=${i}`).join(", "):o=".";var n=e.map(a=>` * Name: '${a.name}', path: '${a.path}', target: ${a.target??"default"}
|
|
3
3
|
`);return`No route matched '${r}${o}'. Available routes:
|
|
4
|
-
${n}`}function z(r){if(!r||!r.route.guards||r.route.guards.length==0)return!0;for(let
|
|
4
|
+
${n}`}function z(r){if(!r||!r.route.guards||r.route.guards.length==0)return!0;for(let e=0;e<r.route.guards.length;e++){let o=r.route.guards[e];var t=o.check(r);if(t==0)return!0;if(t==3)return!1;if(t==1)throw new p(`Guard ${o.constructor.name} said 'Deny' for ${r.route.name}`)}return!0}export{w as GuardResult,l as NavigateRouteEvent,m as RouteError,p as RouteGuardError,f as RouteLink,h as RouteTarget,O as clearPendingNavigations,B as defineRoutes,P as findRouteByName,H as findRouteByUrl,v as internalRoutes,C as matchRoute,x as navigate,k as printRoutes,N as registerRouteTarget,F as startRouting,T as unregisterRouteTarget};
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|