UNPKG

@jadis/core

Version:

Jadis is a minimal JavaScript library for building web interfaces using native Web Components.

3 lines (2 loc) 6.56 kB
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Jadis={})}(this,(function(t){"use strict";function e(t,e){if(!t)throw new Error(e)}const r=t=>t.replace(/[A-Z]+(?![a-z])|[A-Z]/g,((t,e)=>(e?"-":"")+t.toLowerCase()));function s(t,e={},s){const n=document.createElement(t);return Object.entries(e).forEach((([t,e])=>n.setAttribute(r(t),e))),s?.appendChild(n),n}class n extends HTMLElement{static selector;static template="";static observedAttributes=[];shadowRoot;attributesCallback={};_abortController=new AbortController;_isConnected=!1;constructor(){super(),this.shadowRoot=this.attachShadow({mode:"open"}),this.shadowRoot.appendChild(this.buildTemplate())}static createElement(t={},e){return s(this.selector,t,e)}static register(){e(this.selector,`selector is not defined for ${this.name}`),customElements.get(this.typeOfClass.selector)||customElements.define(this.typeOfClass.selector,this.typeOfClass)}get isConnected(){return this._isConnected}connectedCallback(){this._isConnected=!0,setTimeout((()=>this.onConnect?.()))}disconnectedCallback(){this._abortController.abort(),this.onDisconnect?.()}attributeChangedCallback(t,e,r){this.attributesCallback[t]?.(r,e)}get killSignal(){return this._abortController.signal}getElement(t){const r=t.split(">>>").reduce(((t,e)=>(t.shadowRoot??t).querySelector(e)),this);return e(r,`${t} element is not reachable`),r}toggleClass(t,e){e?this.classList.add(t):this.classList.remove(t)}onBus(t,e,r){t.register(e,r,this.killSignal)}useEvents(t){return{register:(t,e)=>{this.addEventListener(t,(({detail:t})=>e(t)),{signal:this.killSignal})},emit:(t,...e)=>{this.dispatchEvent(new CustomEvent(t,{detail:e[0]}))}}}on(t,e,r){t.addEventListener(e,r,{signal:this.killSignal})}buildTemplate(){const t=document.createElement("style");t.textContent=this.templateCss?.()??"";const e=document.createDocumentFragment();e.appendChild(t);const r=this.templateHtml?.();return r&&e.appendChild(r),e}static get typeOfClass(){return this.prototype.constructor}get typeOfConstructor(){return this.constructor}}const o=":",a="history",i="/";class c{_routes=[];routePrefix;namePrefix;constructor(t,e){this.routePrefix=t,this.namePrefix=e??""}static create(t,e){const r=t.startsWith("/")?t:`/${t}`,s=r.endsWith("/")?r:`${r}/`;return new c(s,e)}getRoutes(){return this._routes}addRoute(t,e,r){return this._routes.push({componentSelector:e,path:`${this.routePrefix}${t.startsWith("/")?t.slice(1):t}`,name:r?`${this.namePrefix}${r}`:void 0}),this}addGroup(t){return t.getRoutes().forEach((({path:t,componentSelector:e,name:r})=>{this.addRoute(t,e,r)})),this}}function u(t){return t.includes("-")}t.Bus=class{domElement=document.createElement("div");constructor(t){}register(t,e,r){this.domElement.addEventListener(t,(({detail:t})=>e(t)),{signal:r})}emit(t,...e){this.domElement.dispatchEvent(new CustomEvent(t,{detail:e[0]}))}},t.Jadis=n,t.RouteGroup=c,t.Router=class{_routes=[];_mode;_baseUrl;_parametersRegexp=new RegExp(`${o}\\w+`,"g");_mount;_currentRoute;constructor(t){this._mode=t?.mode??a,this._baseUrl=t?.baseUrl??i,window.addEventListener(this.eventName,(t=>{t.preventDefault(),this.onUrlChange()}))}get config(){return{mode:this._mode,baseUrl:this._baseUrl}}get currentRoute(){return e(this._currentRoute,"No route found"),this._currentRoute}addRoute(t,e,r){const s=t.replace(this._parametersRegexp,"(.+)");return this._routes.push({name:r,path:t,componentSelector:e,regexp:new RegExp(`^${s}$`)}),this}addGroup(t){return t.getRoutes().forEach((({path:t,componentSelector:e,name:r})=>this.addRoute(t,e,r))),this}mountOn(t){this._mount=t,this.onUrlChange()}gotoName(t,r){const s=this.getRouteByName(t);e(s,`No route found for name: ${t}`),this.gotoPath(this.formatPath(s.path,r))}gotoPath(t){const e="hash"===this._mode?`#${t}`:t;window.history.pushState({},"",`${this.baseUrl}/${e}`.replace(/\/{2,}/g,"/")),this.onUrlChange()}get baseUrl(){return this._baseUrl.endsWith("/")?this._baseUrl.slice(0,-1):this._baseUrl}get mountPoint(){return e(this._mount,"No mount point defined"),this._mount}get eventName(){return"hash"===this._mode?"hashchange":"popstate"}get currentUrlPath(){const t=window.location.pathname.startsWith(this.baseUrl)?window.location.pathname.slice(this.baseUrl.length):window.location.pathname,e="hash"===this._mode?window.location.hash.slice(1):t;return e.startsWith("/")?e:`/${e}`}onUrlChange(){const t=this.currentUrlPath,r=this.getRouteByPath(t);e(r,`No route found for path: ${t}`),this._currentRoute=r;const s=this.getComponentToLoad({...r,urlPath:t});this.mountPoint.replaceChildren(s)}formatPath(t,r={}){return this.extractPathParams(t).reduce(((s,n)=>(e(r.hasOwnProperty(n),`Missing parameter "${n}" for path: ${t}`),s.replace(`${o}${n}`,r[n]))),t)}getComponentToLoad(t){const{componentSelector:e}=t;return s(e,this.getRouteParameters(t))}getRouteParameters(t){const{urlPath:r,regexp:s,path:n}=t,o=s.exec(r);return e(o,`No match found for path: ${r}`),this.extractPathParams(n).reduce(((t,e,r)=>({...t,[e]:o[r+1]})),{})}getRouteByName(t){return this._routes.find((({name:e})=>e===t))??null}getRouteByPath(t){return this._routes.find((({regexp:e})=>e.test(t)))??null}extractPathParams(t){return t.split("/").reduce(((t,e)=>e.startsWith(o)?[...t,e.slice(1)]:t),[])}},t.assert=e,t.createElement=s,t.createSelector=t=>(e(u(t),`Custom element name must contain a hyphen: ${t}`),t),t.css=(t,...e)=>t.reduce(((t,r,s)=>`${t}${r}${e[s]??""}`),""),t.html=function(t,...e){const{markup:r,markers:n}=function(t,...e){if("string"==typeof t)return{markup:t,markers:{}};return t.reduce(((t,r,s)=>{const n=e[s];if(n instanceof Node||Array.isArray(n)){const{markers:e,markup:o}=function(t,e){const r=`marker-${e}`;return Array.isArray(t)?t.reduce(((t,e,s)=>({markers:{...t.markers,[`${r}-${s}`]:e},markup:`${t.markup}\x3c!--${r}-${s}--\x3e`})),{markup:"",markers:{}}):{markers:{[r]:t},markup:`\x3c!--${r}--\x3e`}}(n,s);return{markup:`${t.markup}${r}${o}`,markers:{...t.markers,...e}}}return{markup:`${t.markup}${r}${String(n??"")}`,markers:t.markers}}),{markup:"",markers:{}})}(t,...e),o=s("template");o.innerHTML=r;const a=o.content,i=document.createTreeWalker(a,NodeFilter.SHOW_COMMENT),c=[];for(;i.nextNode();){const t=i.currentNode,e=n[t.nodeValue?.trim()??""];e&&t.parentNode&&c.push({target:t,replacement:e})}return c.forEach((({target:t,replacement:e})=>{t.parentNode?.replaceChild(e,t)})),a},t.isComponentSelector=u,t.toKebabCase=r})); //# sourceMappingURL=index.js.map