{ "version": 3, "sources": ["../src/ContentRaw.ts", "../src/Directives.ts", "../src/OperationAttr.ts", "../src/ContentTemplateResult.ts", "../src/ContentText.ts", "../src/ContentComponent.ts", "../src/ContentArray.ts", "../src/ContentBase.ts", "../src/OperationContent.ts", "../src/HtmlBuilder.ts", "../src/WebComponent.ts", "../src/app.ts", "../src/memo.ts", "../src/_iife.ts"], "sourcesContent": ["import { Content } from \"./ContentBase\";\r\n\r\nexport class RawHtml {\r\n html:string;\r\n constructor(html:string) {\r\n this.html=html;\r\n } \r\n}\r\n\r\nexport function CreateContentRaw(v:RawHtml,setContent:(newContent:Node)=>void):Content {\r\n let t2=document.createElement(\"template\");\r\n t2.innerHTML=v.html;\r\n setContent(t2.content);\r\n return {\r\n Update:(nv:RawHtml)=>{},\r\n Unload:()=>{},\r\n MatchForUpdate:(nv:RawHtml)=> nv.html===v.html\r\n }\r\n}", "export type DirectiveFunc= (el:HTMLElement,value:any,mods:string[],redraw:()=>Promise) => (nv:any)=> void;\r\n\r\nexport const Directives=new Map;\r\n\r\ndeclare type MyFileItem = { name: string, size: number, type: string, lastModified: number };\r\ndeclare type MyFileInputValue = { id: string, files: MyFileItem[] };\r\n\r\nDirectives.set(\"validity\", (el:HTMLElement,v:any,mods:string[],redraw:()=>Promise) => {\r\n // \r\n const inp=el;\r\n function SetIt(v:any) {\r\n if(typeof v !==\"string\") throw new Error(\"Katla: #validity value must be string\");\r\n inp.setCustomValidity(v);\r\n }\r\n SetIt(v);\r\n return SetIt;\r\n });\r\n\r\n \r\nDirectives.set(\"ref\", (el:HTMLElement,v:any,mods:string[],redraw:()=>Promise) => {\r\n if(typeof v !==\"function\") throw new Error(\"Katla: #ref value must be function\");\r\n v(el);\r\n return ()=>{}\r\n });\r\n\r\n\r\nDirectives.set(\"bind\",(el:HTMLElement,bindTo:any,mods:string[],redraw:()=>Promise) => {\r\n let tp=el.tagName.toLowerCase();\r\n if(tp===\"input\") {\r\n tp=(el).type;\r\n if(!tp) tp=\"text\";\r\n tp=tp.toLowerCase();\r\n }\r\n\r\n let BoundVal:any;\r\n let SetVal:(v:string|number|boolean|MyFileInputValue)=>void;\r\n let LastVal:any;\r\n \r\n const DoTrim=mods.indexOf(\"notrim\")<0 && (el.tagName==\"TEXTAREA\" || (\r\n el.tagName==\"INPUT\" && [\"text\", \"email\", \"search\", \"url\"].includes((el).type)));\r\n\r\n function GetValueValue():string|number {\r\n let vv:string|number=(el).value;\r\n if(tp===\"number\" || tp===\"range\" || mods.indexOf(\"number\")>=0) vv=parseInt(vv);\r\n if(DoTrim) vv=(vv).trim();\r\n return vv;\r\n }\r\n\r\n function SetElemProp() {\r\n SetVal=undefined;\r\n if(Array.isArray(bindTo) && bindTo.length===2) {\r\n if (Array.isArray(bindTo[0]) && typeof bindTo[1]===\"number\") {\r\n // #bind=${[Array,number]} \r\n BoundVal=bindTo[0][bindTo[1]];\r\n SetVal=v=>bindTo[0][bindTo[1]]=v;\r\n } else if (typeof bindTo[0]===\"object\" && typeof bindTo[1]===\"string\") {\r\n // #bind=${[object,propName]} \r\n if(!bindTo[0].hasOwnProperty(bindTo[1])) throw new Error(\"Katla: \" + tp + \" #bind to object does not have property '\" + bindTo[1] + \"'\");\r\n BoundVal=bindTo[0][bindTo[1]];\r\n SetVal=v=>bindTo[0][bindTo[1]]=v;\r\n } else if (typeof bindTo[0]===\"function\" && typeof bindTo[1]===\"function\") {\r\n // #bind=${[getFunc,setFunc]} - DEPRECATED\r\n BoundVal=bindTo[0]();\r\n SetVal=bindTo[1];\r\n } else if (typeof bindTo[1]===\"function\") {\r\n // #bind=${[value,setFunc]}\r\n BoundVal=bindTo[0];\r\n SetVal=bindTo[1];\r\n }\r\n } else if(Array.isArray(bindTo) && bindTo.length===1 && Array.isArray(bindTo[0])) {\r\n // #bind=${[Array]}\r\n if(tp!==\"checkbox\") throw new Error(\"Katla: Can only #bind to [Array] with input/checkbox\"); \r\n BoundVal=bindTo[0];\r\n SetVal=()=>{}; //dummy to prevent error\r\n } \r\n if(!SetVal) throw new Error(\"Katla: Can only #bind to {object}.PropName / [Object,string] / [Array,number] / [value,setFunc] / [Array]\");\r\n\r\n if(tp===\"radio\") {\r\n if(!el.hasAttribute(\"value\")) throw new Error(\"Katla: input/radio element missing 'value' attribute - for #bind\");\r\n let vv=GetValueValue(); \r\n let value=BoundVal===vv;\r\n if(value===LastVal) return;\r\n (el).checked=value;\r\n LastVal=value;\r\n } else if(tp===\"checkbox\") {\r\n if(typeof BoundVal===\"boolean\") {\r\n if(BoundVal===LastVal) return;\r\n (el).checked=BoundVal; \r\n LastVal=BoundVal;\r\n return; \r\n } else {\r\n if(!Array.isArray(BoundVal)) throw new Error(\"Katla: #bind value for input/checkbox must be either boolean or array\");\r\n if(!el.hasAttribute(\"value\")) throw new Error(\"Katla: input/checkbox element missing 'value' attribute - for #bind with array value\");\r\n let vv=GetValueValue(); \r\n let value=BoundVal.indexOf(vv)>=0;\r\n if(value===LastVal) return;\r\n (el).checked=value;\r\n LastVal=value;\r\n }\r\n } else if (tp === \"file\") {\r\n if (!BoundVal || !BoundVal.files || (BoundVal).files.length === 0) (el).value = \"\"; \r\n } else {\r\n if(BoundVal===LastVal) return;\r\n (el).value= Number.isNaN(BoundVal) ? '': BoundVal.toString();\r\n LastVal=BoundVal;\r\n }\r\n }\r\n\r\n SetElemProp();\r\n\r\n function MyHandler(e:Event) {\r\n let vv=GetValueValue();\r\n if(tp===\"radio\") {\r\n if(!(el).checked) return;\r\n SetVal(vv);\r\n LastVal=vv;\r\n } else if (tp===\"checkbox\") {\r\n let ck=(el).checked;\r\n if(typeof BoundVal===\"boolean\") {\r\n SetVal(ck);\r\n } else {\r\n let i=BoundVal.indexOf(vv);\r\n if(ck && i<0) BoundVal.push(vv);\r\n if(!ck && i>=0) BoundVal.splice(i,1); \r\n }\r\n LastVal=ck;\r\n } else if (tp===\"file\") {\r\n if (!el.id) el.id = 'file-' + (Math.floor(Math.random() * Date.now()).toString(36));\r\n SetVal({ id: el.id, files: Array.from((el).files).map(f => { name: f.name, size: f.size, type: f.type, lastModified: f.lastModified }) });\r\n } else {\r\n SetVal(vv);\r\n LastVal=vv;\r\n if(DoTrim && e.type===\"change\" && (el).value!==LastVal) (el).value=LastVal;\r\n }\r\n\r\n if(mods.indexOf(\"noredraw\")<0) redraw();\r\n }\r\n\r\n const HasEagerMod=mods.indexOf(\"eager\")>=0;\r\n if(HasEagerMod) el.addEventListener(\"input\", MyHandler);\r\n if(!HasEagerMod || DoTrim) el.addEventListener(\"change\", MyHandler);\r\n\r\n \r\n return (nv:any)=>{ \r\n bindTo=nv;\r\n SetElemProp();\r\n }\r\n});\r\n\r\n", "import { Directives } from \"./Directives\";\r\nimport { Operation } from \"./OperationBase\";\r\nimport {ComponentType} from \"./ContentComponent\";\r\n\r\nexport function CreateOperationAttr(node:HTMLElement,name:string,getVal:(args:any[])=>any,curComp:ComponentType,content:any): Operation {\r\n let LastVar=content;\r\n let DirUpdate:(v:any)=>void;\r\n\r\n if (name.charAt(0)===\"@\") {\r\n // event\r\n if(typeof content !==\"function\") throw new Error(\"Katla: '\" + name + \"' handler must be function\");\r\n let parts=name.substr(1).split(\"|\");\r\n node.addEventListener(parts[0], e => {\r\n if(parts.indexOf(\"self\")>0 && e.target!==node) return;\r\n if(parts.indexOf(\"default\")<1) e.preventDefault();\r\n if(parts.indexOf(\"stop\")>0) e.stopPropagation();\r\n let frv=LastVar(e);\r\n if(!parts.includes(\"noredraw\")) {\r\n if (frv instanceof Promise) {\r\n frv.then(() => curComp.$redraw());\r\n } else {\r\n curComp.$redraw();\r\n }\r\n }\r\n },\r\n { capture: parts.indexOf(\"capture\")>0,\r\n once: parts.indexOf(\"once\")>0,\r\n passive: parts.indexOf(\"passive\")>0 }); \r\n\r\n\r\n } else if (name.charAt(0)===\".\") {\r\n // property\r\n (node)[name.substr(1)]=content;\r\n\r\n } else if (name.charAt(0)===\"#\") {\r\n // directive\r\n let parts=name.substr(1).split(\"|\");\r\n let hh=Directives.get(parts[0]); \r\n if(hh===undefined) throw new Error(\"Katla: Unknown directive '#\"+parts[0] + \"'\");\r\n DirUpdate=hh(node,content,parts.slice(1),()=>curComp.$redraw());\r\n\r\n } else {\r\n // plain old attribute\r\n if(content===false || content===null || content===undefined) {\r\n // Do nothing - on creation there is no need to remove attribute if null (won't be there)\r\n } else if(content===true) {\r\n node.setAttribute(name,\"\");\r\n } else {\r\n node.setAttribute(name,content.toString());\r\n }\r\n }\r\n\r\n return {\r\n GetData:getVal,\r\n Update: (v:any)=> {\r\n if(v===LastVar && typeof v !==\"object\") return;\r\n LastVar=v;\r\n if (name.charAt(0)===\"@\") {\r\n // event\r\n if(typeof v !==\"function\") throw new Error(\"Katla: \" + name + \" handler must be function\");\r\n // do nothing - LastVar already set to new function reference\r\n } else if(name.charAt(0)===\".\") {\r\n // property\r\n (node)[name.substr(1)]=v;\r\n } else if(name.charAt(0)===\"#\") {\r\n // directive\r\n DirUpdate(v);\r\n } else {\r\n if(v===false || v===null || v===undefined) {\r\n node.removeAttribute(name);\r\n } else if(v===true) {\r\n node.setAttribute(name,\"\");\r\n } else {\r\n node.setAttribute(name,v.toString()); \r\n }\r\n }\r\n },\r\n \r\n Unload:()=>{}\r\n }\r\n}\r\n", "import { Content } from \"./ContentBase\";\r\nimport { HtmlBuilder } from \"./HtmlBuilder\";\r\nimport {ComponentType} from \"./ContentComponent\";\r\n\r\nexport function CreateContentTemplateResult(tr:TemplateResult,setContent:(newContent:Node)=>void,curComp:ComponentType):Content {\r\n let Live=tr.bldr.MakeLive(tr.args,curComp);\r\n setContent(Live.ContentNode);\r\n return {\r\n Update:(v:TemplateResult)=>Live.Update(v.args),\r\n Unload:Live.Unload,\r\n MatchForUpdate:(v:TemplateResult)=>v.bldr===tr.bldr\r\n }\r\n}\r\n\r\nexport class TemplateResult {\r\n bldr:HtmlBuilder;\r\n args:any[];\r\n constructor(bldr:HtmlBuilder,args:any[]) {\r\n this.bldr=bldr;\r\n this.args=args;\r\n }\r\n}", "import { Content } from \"./ContentBase\";\r\n\r\nexport function CreateContentText(v:string|number|object,setContent:(newContent:Node)=>void):Content {\r\n let ctNode=document.createTextNode(v.toString());\r\n setContent(ctNode);\r\n return {\r\n Update:newV=>{\r\n if(newV!==v) {\r\n v=newV;\r\n ctNode.data=newV.toString();\r\n }\r\n },\r\n Unload:()=>{},\r\n MatchForUpdate:v=>true\r\n }\r\n}", "import {GetContentType, ContentType, CreateContent, Content} from \"./ContentBase\";\r\n\r\nexport type ComponentType = {\r\n render:()=>any;\r\n load?:()=>void;\r\n unload?:()=>void;\r\n $get?:(key:string)=>any;\r\n $set?:(key:string,v:any)=>void;\r\n $parent?:ComponentType;\r\n $redraw?:()=>Promise;\r\n /** @deprecated Use .$redraw instead */\r\n $app?:{redraw:()=>Promise}; // only for backwards compat\r\n}\r\n\r\nexport type ComponentWrapper=[new()=>ComponentType] |\r\n [new()=>ComponentType,Object] |\r\n [new()=>ComponentType,Object,(c:ComponentType)=>void];\r\n\r\n\r\nexport function HookUpContext(comp:ComponentType,parentComp:ComponentType=null) {\r\n let CtxValues:Map;\r\n comp.$get=(key:string):any=>{\r\n if(CtxValues && CtxValues.has(key)) return CtxValues.get(key);\r\n if(parentComp) return parentComp.$get(key);\r\n return undefined;\r\n };\r\n comp.$set=(key:string,v:any)=>{\r\n if(!CtxValues) CtxValues=new Map();\r\n CtxValues.set(key,v);\r\n }\r\n}\r\n\r\nexport function CreateContentComponent(cw:ComponentWrapper,setContent:(newContent:Node)=>void, curComp:ComponentType):Content {\r\n let comp = new cw[0];\r\n comp.$parent=curComp;\r\n comp.$redraw=()=>curComp.$redraw();\r\n comp.$app={redraw:()=>curComp.$redraw()}; // only for backwards compat\r\n HookUpContext(comp,curComp);\r\n\r\n if(cw.length>1) Object.assign(comp,cw[1]);\r\n if(cw.length>2) cw[2](comp);\r\n if(comp.load) comp.load();\r\n if(!comp.render || typeof comp.render!==\"function\") throw new Error(\"Katla: Component must have .render method\");\r\n let Output=comp.render();\r\n let ctType=GetContentType(Output);\r\n let Content=CreateContent(Output,setContent,comp);\r\n \r\n let WasUnloaded=false;\r\n return {\r\n Update:(v:ComponentWrapper)=>{\r\n if(WasUnloaded) return;\r\n cw=v;\r\n if(cw.length>1) Object.assign(comp,cw[1]);\r\n Output=comp.render();\r\n let ctType2=GetContentType(Output);\r\n if(ctType2===ContentType.NoChange) return;\r\n if(ctType===ctType2 && Content.MatchForUpdate(Output)) {\r\n Content.Update(Output)\r\n } else {\r\n Content.Unload();\r\n ctType=ctType2;\r\n Content=CreateContent(Output,setContent,comp);\r\n }\r\n },\r\n Unload:()=>{\r\n if(WasUnloaded) return;\r\n if(comp.unload) comp.unload();\r\n Content.Unload();\r\n WasUnloaded=true;\r\n },\r\n MatchForUpdate:(v:ComponentWrapper)=> cw[0] === v[0]\r\n }\r\n}\r\n", "import {CreateOperationContent} from \"./OperationContent\";\r\nimport { Content } from \"./ContentBase\";\r\nimport {ComponentType} from \"./ContentComponent\";\r\nimport {Operation} from \"./OperationBase\";\r\n\r\nexport function CreateContentArray(v:any[],setContent:(newContent:Node)=>void,curComp:ComponentType):Content {\r\n let arrOps:Operation[]=[];\r\n let Comments:Comment[]=[];\r\n\r\n function AddOne(content:any) {\r\n const idx=arrOps.length;\r\n let cmt=document.createComment(\"\");\r\n let cc=Comments[idx];\r\n Comments.splice(idx,0,cmt);\r\n cc.parentNode.insertBefore(cmt, cc);\r\n arrOps.push(CreateOperationContent((newContent:Node)=>{\r\n let r=document.createRange();\r\n r.setStartAfter(Comments[idx]);\r\n r.setEndBefore(Comments[idx+1]);\r\n r.deleteContents();\r\n if(newContent) r.insertNode(newContent);\r\n },-1,curComp,content));\r\n }\r\n \r\n function RemoveOne(idx:number) {\r\n let r=document.createRange();\r\n r.setStartAfter(Comments[idx]);\r\n r.setEndAfter(Comments[idx+1]);\r\n r.deleteContents();\r\n Comments.splice(idx+1,1);\r\n arrOps[idx].Unload();\r\n arrOps.splice(idx,1);\r\n }\r\n \r\n //let tmpl=document.createElement(\"template\");\r\n let frag=new DocumentFragment();\r\n let cmt=document.createComment(\"\");\r\n Comments.push(cmt);\r\n frag.append(cmt);\r\n for(const itm of v) AddOne(itm);\r\n setContent(frag);\r\n \r\n return {\r\n Update:items=>{\r\n for(let i=0;i{arrOps.forEach(op=>op.Unload());arrOps=[]},\r\n\r\n MatchForUpdate:v=>true\r\n }\r\n}\r\n", "import { CreateContentTemplateResult, TemplateResult } from \"./ContentTemplateResult\";\r\nimport { CreateContentRaw,RawHtml } from \"./ContentRaw\";\r\nimport { CreateContentText } from \"./ContentText\";\r\nimport { ComponentType, CreateContentComponent} from \"./ContentComponent\";\r\nimport { CreateContentArray } from \"./ContentArray\";\r\n\r\nexport type Content={\r\n Update:(v:any)=>void;\r\n Unload:()=>void;\r\n MatchForUpdate:(v:any)=>boolean;\r\n}\r\n\r\nexport const enum ContentType {\r\n Null,\r\n Text,\r\n Component,\r\n Raw,\r\n TemplateResult,\r\n NoChange,\r\n Array,\r\n}\r\n\r\nexport function GetContentType(v:any):ContentType {\r\n if(v===null || v===\"\" || v===false) return ContentType.Null;\r\n if(v instanceof TemplateResult) return ContentType.TemplateResult;\r\n if(Array.isArray(v)) return v.length>0 && typeof v[0]===\"function\" ? ContentType.Component : ContentType.Array;\r\n if(v instanceof RawHtml) return ContentType.Raw;\r\n if(v instanceof NoChange) return ContentType.NoChange;\r\n if(typeof v ===\"string\" || typeof v===\"number\" || typeof v===\"object\") return ContentType.Text;\r\n throw new Error(\"Katla: Unknown content type: \" + typeof v);\r\n}\r\n\r\nexport function CreateContent(v:any,setContent:(newContent:Node)=>void,curComp:ComponentType):Content {\r\n let tp=GetContentType(v)\r\n switch(tp) {\r\n case ContentType.Null:\r\n setContent(null);\r\n return {Update:v=>{},Unload:()=>{},MatchForUpdate:v=>true};\r\n case ContentType.Text:\r\n return CreateContentText(v,setContent);\r\n case ContentType.Component:\r\n return CreateContentComponent(v,setContent,curComp);\r\n case ContentType.Raw:\r\n return CreateContentRaw(v,setContent);\r\n case ContentType.TemplateResult:\r\n return CreateContentTemplateResult(v,setContent,curComp);\r\n case ContentType.Array:\r\n return CreateContentArray(v,setContent,curComp);\r\n case ContentType.NoChange:\r\n throw new Error(\"Katla: NoChange at creation\");\r\n } \r\n}\r\n\r\nexport class NoChange {\r\n}", "import { GetContentType,ContentType,CreateContent,Content } from \"./ContentBase\";\r\nimport { Operation } from \"./OperationBase\";\r\nimport {ComponentType} from \"./ContentComponent\";\r\n\r\nexport function CreateOperationContent(setContent:(newContent:Node)=>void, varIdx:number, curComp:ComponentType, content:any):Operation {\r\n let ctType=GetContentType(content);\r\n let Content:Content;\r\n\r\n let rv:Operation= {\r\n GetData: (args:any[])=> args[varIdx],\r\n Update: (v:any)=> {\r\n let ctType2=GetContentType(v);\r\n if(ctType2===ContentType.NoChange) return;\r\n if(ctType===ctType2 && Content.MatchForUpdate(v)) {\r\n Content.Update(v)\r\n } else {\r\n Content.Unload();\r\n ctType=ctType2;\r\n Content=CreateContent(v,setContent,curComp);\r\n }\r\n },\r\n Unload:()=> ()=> Content.Unload(),\r\n }\r\n\r\n Content=CreateContent(content,setContent,curComp);\r\n return rv;\r\n}\r\n\r\n\r\n", "import { CreateOperationAttr } from \"./OperationAttr\";\r\nimport { Operation } from \"./OperationBase\";\r\nimport {CreateOperationContent, OperationContent} from \"./OperationContent\";\r\nimport {ComponentType} from \"./ContentComponent\";\r\n\r\ntype PlaceHolder = {\r\n path:number[],\r\n CreateOp:(node:HTMLElement,curComp:ComponentType,args:any[])=>Operation|null\r\n}\r\n\r\nexport class HtmlBuilder {\r\n #phs:PlaceHolder[]=[];\r\n #tmpl=document.createElement(\"template\");\r\n\r\n constructor(fixed:TemplateStringsArray) {\r\n let x=\"\";\r\n for(let i=0;i'; \r\n }\r\n x+=fixed[fixed.length-1];\r\n this.#tmpl.innerHTML=x;\r\n this.#FillPlaceHolders(this.#tmpl.content,[]); \r\n }\r\n\r\n #InAttr(x:string) {\r\n return x.lastIndexOf(\"<\") > x.lastIndexOf(\">\");\r\n }\r\n\r\n // is a function because it needs to call itself recursively\r\n #FillPlaceHolders(node:Node,path:number[]) {\r\n let cn:Node,x:string,k:number,fvID:number,attr:Attr,cnPath:number[];\r\n for(let i=0;icn;\r\n // if this is a