@dlightjs/dlight
Advanced tools
Comparing version 1.0.0 to 1.0.1
1465
dist/index.js
@@ -1,2 +0,1465 @@ | ||
import{Store as U}from"@dlightjs/store";"global"in U||(typeof window<"u"?U.global=window:typeof global<"u"?U.global=global:U.global={});"document"in U||typeof document<"u"&&(U.document=document);var r={...U,delegatedEvents:new Set};function z(o){r.global=o}function q(o){r.document=o}function $(o,t){return!t||o.length!==t.length?!1:o.every((e,n)=>!(e instanceof Object)&&t[n]===e)}var f={Comp:0,For:1,Cond:2,Env:3,Exp:4,Snippet:5,Try:6},l=class o{_$dlNodeType;constructor(t){this._$dlNodeType=t}get _$el(){return o.toEls(this._$nodes)}static toEls(t){let e=[];return this.loopShallowEls(t,n=>{e.push(n)}),e}static loopShallowEls(t,e){let n=[...t].reverse();for(;n.length>0;){let s=n.pop();"_$dlNodeType"in s?s._$nodes&&n.push(...[...s._$nodes].reverse()):e(s)}}static addParentEl(t,e){t.forEach(n=>{"_$dlNodeType"in n&&(n._$parentEl=e,n._$nodes&&o.addParentEl(n._$nodes,e))})}static getFlowIndexFromNodes(t,e){let n=0,s=[...t].reverse();for(;s.length>0;){let i=s.pop();if(i===e)break;"_$dlNodeType"in i?i._$nodes&&s.push(...[...i._$nodes].reverse()):n++}return n}static appendNodesWithSibling(t,e,n){return n?this.insertNodesBefore(t,e,n):this.appendNodes(t,e)}static appendNodesWithIndex(t,e,n,s){return s=s??e.childNodes.length,s!==n?this.insertNodesBefore(t,e,e.childNodes[n]):this.appendNodes(t,e)}static insertNodesBefore(t,e,n){let s=0;return this.loopShallowEls(t,i=>{e.insertBefore(i,n),s++}),s}static appendNodes(t,e){let n=0;return this.loopShallowEls(t,s=>{e.appendChild(s),n++}),n}static addWillUnmount(t,e){let n=r.global.WillUnmountStore,s=n[n.length-1];s&&s.push(e.bind(null,t))}static addDidUnmount(t,e){let n=r.global.DidUnmountStore,s=n[n.length-1];s&&s.push(e.bind(null,t))}static addDidMount(t,e){r.global.DidMountStore||(r.global.DidMountStore=[]),r.global.DidMountStore.push(e.bind(null,t))}static runDidMount(){let t=r.global.DidMountStore;if(!(!t||t.length===0)){for(let e=t.length-1;e>=0;e--)t[e]();r.global.DidMountStore=[]}}};function P(o,t,e){if(e.length===0)return!1;let n=`$${t}`;return $(e,o[n])?!0:(o[n]=e,!1)}function T(o,t){Object.entries(t).forEach(([e,n])=>{e.startsWith("--")?o.style.setProperty(e,n):o.style[e]=n})}function W(o,t){Object.assign(o.dataset,t)}function L(o,t,e,n){P(o,t,n)||(o[t]=e())}function G(o,t){Object.entries(t).forEach(([e,n])=>{if(e==="style")return T(o,n);if(e==="dataset")return W(o,n);L(o,e,()=>n,[])})}function y(o,t,e,n){P(o,t,n)||o.setAttribute(t,e())}function Y(o,t){Object.entries(t).forEach(([e,n])=>{y(o,e,()=>n,[])})}function J(o,t,e){let n=o[`$on${t}`];n&&o.removeEventListener(t,n),o.addEventListener(t,e),o[`$on${t}`]=e}function Q(o){let t=`$$${o.type}`;for(let e of o.composedPath())if(e[t]&&e[t](o),o.cancelBubble)return}function st(o,t,e){o[`$$${t}`]!==e&&(o[`$$${t}`]=e,r.delegatedEvents.has(t)||(r.delegatedEvents.add(t),r.document.addEventListener(t,Q)))}function it(o){return r.document.createElement(o)}function D(o,t,e){o._$nodes||(o._$nodes=Array.from(o.childNodes)),o._$nodes.splice(e,0,t);let n=l.getFlowIndexFromNodes(o._$nodes,t);l.appendNodesWithIndex([t],o,n),l.addParentEl([t],o)}function C(o,t,e,n){if(t==="style")return T(o,e());if(t==="dataset")return W(o,e());if(t!=="element"){if(t==="prop")return G(o,e());if(t==="attr")return Y(o,e());if(t==="innerHTML")return L(o,"innerHTML",e,n);if(t==="textContent")return L(o,"textContent",e,n);if(t!=="forwardProp"){if(t.startsWith("on"))return J(o,t.slice(2).toLowerCase(),e());y(o,t,e,n)}}}var M=class o extends l{constructor(){super(f.Comp)}_$init(t,e,n,s){this._$notInitd=!0,s&&s._$addForwardProps(this),e&&this._$setContent(()=>e[0],e[1]),t&&t.forEach(([h,d,p])=>{if(h==="props")return this._$setProps(()=>d,p);this._$setProp(h,()=>d,p)}),n&&(this._$children=n),r.global.DLEnvStore&&Object.entries(r.global.DLEnvStore.envs).forEach(([h,[d,p]])=>{if(h==="_$catchable"){this._$catchable=d;return}`$e$${h}`in this&&(p.addNode(this),this._$initEnv(h,d,p))});let i=()=>{this._$callUpdatesBeforeInit(),this.didMount&&l.addDidMount(this,this.didMount.bind(this)),this.willUnmount&&l.addWillUnmount(this,this.willUnmount.bind(this)),l.addDidUnmount(this,this._$setUnmounted.bind(this)),this.didUnmount&&l.addDidUnmount(this,this.didUnmount.bind(this)),this.willMount?.(),this._$nodes=this.Body?.()??[]};this._$catchable?(this._$catchable(i)(),this._$update&&(this._$update=this._$catchable(this._$update.bind(this))),this._$updateDerived=this._$catchable(this._$updateDerived.bind(this)),delete this._$catchable):i()}_$setUnmounted(){this._$unmounted=!0}_$callUpdatesBeforeInit(){let t=Object.getOwnPropertyNames(Object.getPrototypeOf(this)),e=Object.getOwnPropertyNames(this);[...t,...e].forEach(s=>{if(s.startsWith("$w$"))return this[s.slice(3)]();if(s.startsWith("$md$")){let i=s.slice(4);this[i]=this[i]();return}if(s.startsWith("$f$")){let i=s.slice(3);this[i]=this[s],this._$updateDerived(i)}}),delete this._$notInitd}_$setPropToForward(t,e,n){this._$forwardPropsSet.forEach(s=>{let i=t==="_$content";if(s._$dlNodeType===f.Comp){i?s._$setContent(()=>e,n):s._$setProp(t,()=>e,n);return}s instanceof HTMLElement&&(i&&(t="textContent"),C(s,t,()=>e,n))})}_$setForwardProp(t,e,n){let s="_$notInitd"in this;if(!s&&this._$cache(t,n))return;let i=e();t==="_$content"&&this._$contentKey&&(this[this._$contentKey]=i,this._$updateDerived(this._$contentKey)),this[t]=i,this._$updateDerived(t),s?this._$forwardPropsId.push(t):this._$setPropToForward(t,i,n)}_$addForwardProps(t){this._$forwardPropsSet.add(t),this._$forwardPropsId.forEach(e=>{this._$setPropToForward(e,this[e],[])}),l.addWillUnmount(t,this._$forwardPropsSet.delete.bind(this._$forwardPropsSet,t))}_$cache(t,e){if(!e||!e.length)return!1;let n=`$cc$${t}`;return $(e,this[n])?!0:(this[n]=e,!1)}_$setContent(t,e){if("_$forwardProps"in this)return this._$setForwardProp("_$content",t,e);let n=this._$contentKey;n&&(this._$cache(n,e)||(this[n]=t(),this._$updateDerived(n)))}_$setProp(t,e,n){if("_$forwardProps"in this)return this._$setForwardProp(t,e,n);if(!(`$p$${t}`in this)){console.warn(`[${t}] is not a prop in ${this.constructor.name}`);return}this._$cache(t,n)||(this[t]=e(),this._$updateDerived(t))}_$setProps(t,e){if(this._$cache("props",e))return;let n=t();n&&Object.entries(n).forEach(([s,i])=>{this._$setProp(s,()=>i,[])})}_$initEnv(t,e,n){this[t]=e,this[`$en$${t}`]=n}_$updateEnv(t,e,n){`$e$${t}`in this&&n===this[`$en$${t}`]&&(this[t]=e,this._$updateDerived(t))}_$ud(t,e){return this._$updateDerived(e),t}_$updateDerived(t){"_$notInitd"in this||(this[`$s$${t}`]?.forEach(e=>{`$w$${e}`in this?this[e](t):`$md$${e}`in this?this[e]._$update():this[e]=this[`$f$${e}`]}),this._$updateView(t))}_$updateView(t){if(this._$modelCallee)return this._$updateModelCallee();if(!("_$update"in this))return;let e=this[`$$${t}`];e&&("_$depNumsToUpdate"in this?this._$depNumsToUpdate.push(e):(this._$depNumsToUpdate=[e],Promise.resolve().then(()=>{if(this._$unmounted)return;let n=this._$depNumsToUpdate;if(n.length>0){let s=n.reduce((i,h)=>i|h,0);this._$update(s)}delete this._$depNumsToUpdate})))}_$updateModelCallee(){"_$depNumsToUpdate"in this||(this._$depNumsToUpdate=!0,Promise.resolve().then(()=>{this._$unmounted||(this._$modelCallee._$updateDerived(this._$modelKey),delete this._$depNumsToUpdate)}))}static _$updateModel(t,e,n){let s=e()??{},i=s.s??[];s.m?.forEach(([d,p])=>{Object.entries(d).forEach(([c,g])=>{i.push([c,g,p])})}),i.forEach(([d,p,c])=>{t._$setProp(d,()=>p,c)});let h=n();h&&t._$setContent(()=>h[0],h[1])}static _$releaseModel(){delete this._$modelCallee}_$injectModel(t,e,n,s){let i=e()??{},h=i.s??[];i.m?.forEach(([p,c])=>{Object.entries(p).forEach(([g,u])=>{h.push([g,u,c])})});let d=new t;return d._$init(h,n(),null,null),d._$modelCallee=this,d._$modelKey=s,d._$update=o._$updateModel.bind(null,d,e,n),d}},lt=M,at=M;function pt(o,t){o._$updateDerived(t)}var I=class{constructor(){this.envs={},this.currentEnvNodes=[]}addEnvNode(t){this.currentEnvNodes.push(t),this.mergeEnvs()}replaceEnvNodes(t){this.currentEnvNodes=t,this.mergeEnvs()}removeEnvNode(){this.currentEnvNodes.pop(),this.mergeEnvs()}mergeEnvs(){this.envs={},this.currentEnvNodes.forEach(t=>{Object.entries(t.envs).forEach(([e,n])=>{this.envs[e]=[n,t]})})}},S=class extends l{constructor(t,e){super(f.Env),"DLEnvStore"in r.global||(r.global.DLEnvStore=new I),this.envs=t,this.depsArr=e,this.updateNodes=new Set,r.global.DLEnvStore.addEnvNode(this)}cached(t,e){return!t||!t.length?!1:$(t,this.depsArr[e])?!0:(this.depsArr[e]=t,!1)}updateEnv(t,e,n){if(this.cached(n,t))return;let s=e();this.envs[t]=s,r.global.DLEnvStore.currentEnvNodes.includes(this)&&r.global.DLEnvStore.mergeEnvs(),this.updateNodes.forEach(i=>{i._$updateEnv(t,s,this)})}addNode(t){this.updateNodes.add(t),l.addWillUnmount(t,this.updateNodes.delete.bind(this.updateNodes,t))}initNodes(t){this._$nodes=t,r.global.DLEnvStore.removeEnvNode()}};function gt(o,t){let e=r.document.createTextNode(o);return e.$$deps=t,e}function Ut(o,t,e){if($(e,o.$$deps))return;let n=t();o.textContent=n,o.$$deps=e}var K=class{propViewFunc;dlUpdateFunc=new Set;constructor(t){this.propViewFunc=t}build(){let t,e=s=>{t=s,this.dlUpdateFunc.add(s)},n=this.propViewFunc(e);return n.length===0?[]:(t&&l.addWillUnmount(n[0],this.dlUpdateFunc.delete.bind(this.dlUpdateFunc,t)),n)}update(...t){this.dlUpdateFunc.forEach(e=>{e(...t)})}};function xt(o,t){D(o,{_$nodes:t.build(),_$dlNodeType:7},0)}var O=class extends l{constructor(t){super(f.Snippet),this.depsArr=t}cached(t,e){if(!t||!t.length)return!1;let n=Math.log2(e),s=this.depsArr[n];return $(t,s)?!0:(this.depsArr[n]=t,!1)}};var w=class extends l{constructor(t){super(t),r.global.DLEnvStore&&r.global.DLEnvStore.currentEnvNodes.length>0&&(this.savedEnvNodes=[...r.global.DLEnvStore.currentEnvNodes])}initNewNodes(t){l.addParentEl(t,this._$parentEl)}geneNewNodesInEnv(t){if(!this.savedEnvNodes){let s=t();return this.initNewNodes(s),s}let e=r.global.DLEnvStore.currentEnvNodes;r.global.DLEnvStore.replaceEnvNodes(this.savedEnvNodes);let n=t();return r.global.DLEnvStore.replaceEnvNodes(e),this.initNewNodes(n),n}initUnmountStore(){r.global.WillUnmountStore.push([]),r.global.DidUnmountStore.push([])}removeNodes(t){l.loopShallowEls(t,e=>{this._$parentEl.removeChild(e)})}};var j=class o extends w{array;nodeFunc;depNum;nodesMap=new Map;updateArr=[];get _$nodes(){let t=[];for(let e=0;e<this.array.length;e++)t.push(...this.nodesMap.get(this.keys?.[e]??e));return t}constructor(t,e,n,s){super(f.For),this.array=[...t],this.keys=n,this.depNum=e,this.addNodeFunc(s)}addNodeFunc(t){this.nodeFunc=t,this.array.forEach((e,n)=>{this.initUnmountStore();let s=this.keys?.[n]??n,i=t(e,this.updateArr,n);this.nodesMap.set(s,i),this.setUnmountMap(s)}),o.addWillUnmount(this,this.runAllWillUnmount.bind(this)),o.addDidUnmount(this,this.runAllDidUnmount.bind(this))}updateItem(t,e,n){this.updateArr[t]?.(n??this.depNum,e[t])}updateItems(t){for(let e=0;e<this.array.length;e++)this.updateItem(e,this.array,t)}update(t){~this.depNum&t&&this.updateItems(t)}updateArray(t,e){if(e){this.updateWithKey(t,e);return}this.updateWithOutKey(t)}getNewNodes(t,e,n,s){this.initUnmountStore();let i=this.geneNewNodesInEnv(()=>this.nodeFunc(n[t],s??this.updateArr,t));return this.setUnmountMap(e),this.nodesMap.set(e,i),i}setUnmountMap(t){let e=r.global.WillUnmountStore.pop();e&&e.length>0&&(this.willUnmountMap||(this.willUnmountMap=new Map),this.willUnmountMap.set(t,e));let n=r.global.DidUnmountStore.pop();n&&n.length>0&&(this.didUnmountMap||(this.didUnmountMap=new Map),this.didUnmountMap.set(t,n))}runAllWillUnmount(){!this.willUnmountMap||this.willUnmountMap.size===0||(this.willUnmountMap.forEach(t=>{for(let e=0;e<t.length;e++)t[e]?.()}),this.willUnmountMap.clear())}runAllDidUnmount(){!this.didUnmountMap||this.didUnmountMap.size===0||(this.didUnmountMap.forEach(t=>{for(let e=t.length-1;e>=0;e--)t[e]?.()}),this.didUnmountMap.clear())}runWillUnmount(t){if(!this.willUnmountMap||this.willUnmountMap.size===0)return;let e=this.willUnmountMap.get(t);if(e){for(let n=0;n<e.length;n++)e[n]?.();this.willUnmountMap.delete(t)}}runDidUnmount(t){if(!this.didUnmountMap||this.didUnmountMap.size===0)return;let e=this.didUnmountMap.get(t);if(e){for(let n=e.length-1;n>=0;n--)e[n]?.();this.didUnmountMap.delete(t)}}removeNodes(t,e){this.runWillUnmount(e),super.removeNodes(t),this.runDidUnmount(e),this.nodesMap.delete(e)}updateWithOutKey(t){let e=this.array.length,n=t.length;if(e===n){for(let i=0;i<this.array.length;i++)this.updateItem(i,t);this.array=[...t];return}let s=this._$parentEl;if(e<n){let i=o.getFlowIndexFromNodes(s._$nodes,this),h=s.childNodes.length;for(let d=0;d<n;d++){if(d<e){i+=o.getFlowIndexFromNodes(this.nodesMap.get(d)),this.updateItem(d,t);continue}let p=this.getNewNodes(d,d,t);o.appendNodesWithIndex(p,s,i,h)}o.runDidMount(),this.array=[...t];return}for(let i=0;i<n;i++)this.updateItem(i,t);for(let i=n;i<e;i++){let h=this.nodesMap.get(i);this.removeNodes(h,i)}this.updateArr.splice(n,e-n),this.array=[...t]}updateWithKey(t,e){if(e.length!==new Set(e).size)throw new Error("DLight: Duplicate keys in for loop are not allowed");let n=this.keys;if(this.keys=e,o.arrayEqual(n,this.keys)){for(let u=0;u<t.length;u++)this.updateItem(u,t);this.array=[...t];return}let s=this._$parentEl;if(this.keys.length===0){let u=s._$nodes??[];if(u.length===1&&u[0]===this)this.runAllWillUnmount(),s.innerHTML="",this.runAllDidUnmount();else for(let a=0;a<n.length;a++){let m=n[a];this.removeNodes(this.nodesMap.get(m),m)}this.nodesMap.clear(),this.updateArr=[],this.array=[];return}let i=o.getFlowIndexFromNodes(s._$nodes,this);if(n.length===0){let u=s.childNodes[i];for(let a=0;a<this.keys.length;a++){let m=this.getNewNodes(a,this.keys[a],t);o.appendNodesWithSibling(m,s,u)}o.runDidMount(),this.array=[...t];return}let h=[],d=[];for(let u=0;u<n.length;u++){let a=n[u];if(this.keys.includes(a)){h.push(a),d.push(this.updateArr[u]);continue}this.removeNodes(this.nodesMap.get(a),a)}let p=s.childNodes.length,c=i;for(let u=0;u<this.keys.length;u++){let a=this.keys[u],m=h.indexOf(a);if(m!==-1){c+=o.getFlowIndexFromNodes(this.nodesMap.get(a)),d[m]?.(this.depNum,t[u]);continue}d.splice(u,0,null);let _=this.getNewNodes(u,a,t,d);h.splice(u,0,a);let v=o.appendNodesWithIndex(_,s,c,p);c+=v,p+=v}if(o.runDidMount(),o.arrayEqual(this.keys,h)){this.array=[...t],this.updateArr=d;return}c=i;let g=new Map;for(let u=0;u<this.keys.length;u++){let a=this.keys[u],m=h.indexOf(a),_=g.get(a);if(_){let x=o.getFlowIndexFromNodes(_),b=o.toEls(_).pop(),E=s.childNodes[c+x];b!==E&&b.nextSibling!==E&&o.insertNodesBefore(_,s,E),c+=x,delete g[u]}else if(m===u){c+=o.getFlowIndexFromNodes(this.nodesMap.get(a));continue}else{let x=h[u];g.set(x,this.nodesMap.get(x));let b=this.nodesMap.get(a),E=o.toEls(b).pop(),F=s.childNodes[c];E!==F&&E.nextSibling!==F&&(c+=o.insertNodesBefore(b,s,F))}let v=h[u];h[u]=h[m],h[m]=v;let V=d[u];d[u]=d[m],d[m]=V}this.array=[...t],this.updateArr=d}static arrayEqual(t,e){return t.length!==e.length?!1:t.every((n,s)=>n===e[s])}};var N=class extends w{willUnmountFuncs=[];didUnmountFuncs=[];setUnmountFuncs(){this.willUnmountFuncs=r.global.WillUnmountStore.pop(),this.didUnmountFuncs=r.global.DidUnmountStore.pop()}runWillUnmount(){for(let t=0;t<this.willUnmountFuncs.length;t++)this.willUnmountFuncs[t]()}runDidUnmount(){for(let t=this.didUnmountFuncs.length-1;t>=0;t--)this.didUnmountFuncs[t]()}removeNodes(t){this.runWillUnmount(),super.removeNodes(t),this.runDidUnmount()}geneNewNodesInEnv(t){this.initUnmountStore();let e=super.geneNewNodesInEnv(t);return this.setUnmountFuncs(),e}};var A=class o extends N{constructor(t,e){super(f.Exp),this.initUnmountStore(),this._$nodes=o.formatNodes(t),this.setUnmountFuncs(),this.deps=this.parseDeps(e),o.addWillUnmount(this,this.runWillUnmount.bind(this)),o.addDidUnmount(this,this.runDidUnmount.bind(this))}parseDeps(t){return t.map(e=>e?.prototype?._$init?e.toString():e?.propViewFunc?e.propViewFunc.toString():e)}cache(t){return!t||!t.length?!1:(t=this.parseDeps(t),$(t,this.deps)?!0:(this.deps=t,!1))}update(t,e){if(this.cache(e))return;this.removeNodes(this._$nodes);let n=this.geneNewNodesInEnv(()=>o.formatNodes(t()));if(n.length===0){this._$nodes=[];return}let s=this._$parentEl,i=o.getFlowIndexFromNodes(s._$nodes,this),h=s.childNodes[i];o.appendNodesWithSibling(n,s,h),o.runDidMount(),this._$nodes=n}static formatNodes(t){return Array.isArray(t)||(t=[t]),t.flat(1).filter(e=>e!=null&&typeof e!="boolean").map(e=>typeof e=="string"||typeof e=="number"||typeof e=="bigint"?r.document.createTextNode(`${e}`):"propViewFunc"in e?e.build():e).flat(1)}};var H=class o extends N{constructor(t,e){super(f.Cond),this.depNum=t,this.cond=-1,this.condFunc=e,this.initUnmountStore(),this._$nodes=this.condFunc(this),this.setUnmountFuncs(),o.addWillUnmount(this,this.runWillUnmount.bind(this)),o.addDidUnmount(this,this.runDidUnmount.bind(this))}updateCond(t){let e=[this.willUnmountFuncs,this.didUnmountFuncs],n=this.geneNewNodesInEnv(()=>this.condFunc(this));if(this.didntChange){[this.willUnmountFuncs,this.didUnmountFuncs]=e,this.didntChange=!1,this.updateFunc?.(this.depNum,t);return}let s=[this.willUnmountFuncs,this.didUnmountFuncs];if([this.willUnmountFuncs,this.didUnmountFuncs]=e,this._$nodes&&this._$nodes.length>0&&this.removeNodes(this._$nodes),[this.willUnmountFuncs,this.didUnmountFuncs]=s,n.length===0){this._$nodes=[];return}let i=this._$parentEl,h=o.getFlowIndexFromNodes(i._$nodes,this),d=i.childNodes[h];o.appendNodesWithSibling(n,i,d),o.runDidMount(),this._$nodes=n}update(t){~this.depNum&t&&this.updateFunc?.(t)}};var B=class extends N{constructor(t,e){super(f.Try),this.tryFunc=t;let n=this.getCatchable(e);this.envNode=new S({_$catchable:n});let s=t(this.setUpdateFunc.bind(this),n)??[];this.envNode.initNodes(s),this._$nodes=s}update(t){this.updateFunc?.(t)}setUpdateFunc(t){this.updateFunc=t}getCatchable(t){return e=>(...n)=>{try{return e(...n)}catch(s){Promise.resolve().then(()=>{let i=this.geneNewNodesInEnv(()=>t(this.setUpdateFunc.bind(this),s));this._$nodes&&this.removeNodes(this._$nodes);let h=this._$parentEl,d=N.getFlowIndexFromNodes(h._$nodes,this),p=h.childNodes[d];N.appendNodesWithSibling(i,h,p),N.runDidMount(),this._$nodes=i})}}}};function R(){r.global.WillUnmountStore=[],r.global.DidUnmountStore=[]}function Zt(o,t){let e=o;if(typeof o=="string"){let s=r.document.getElementById(o);if(s)e=s;else throw new Error(`DLight: Element with id ${o} not found`)}R(),e.innerHTML="";let n=new t;n._$init(),D(e,n,0),l.runDidMount()}function kt(o,t){return o()}function X(o){return o}var te=X,ee=null;function ne(){console.error("DLight: use() is not supported be called directly. You can only assign `use(model)` to a dlight class property. Any other expressions are not allowed.")}export{te as $,M as CompNode,H as CondNode,S as EnvNode,I as EnvStoreClass,A as ExpNode,j as ForNode,at as Model,K as PropView,O as SnippetNode,B as TryNode,lt as View,it as createElement,gt as createTextNode,st as delegateEvent,X as escape,C as forwardHTMLProp,xt as insertChildren,D as insertNode,kt as manual,Zt as render,ee as required,W as setDataset,q as setDocument,J as setEvent,z as setGlobal,y as setHTMLAttr,Y as setHTMLAttrs,L as setHTMLProp,G as setHTMLProps,T as setStyle,pt as update,Ut as updateText,ne as use}; | ||
// src/store.js | ||
import { Store } from "@dlightjs/store"; | ||
if (!("global" in Store)) { | ||
if (typeof window !== "undefined") { | ||
Store.global = window; | ||
} else if (typeof global !== "undefined") { | ||
Store.global = global; | ||
} else { | ||
Store.global = {}; | ||
} | ||
} | ||
if (!("document" in Store)) { | ||
if (typeof document !== "undefined") { | ||
Store.document = document; | ||
} | ||
} | ||
var DLStore = { ...Store, delegatedEvents: /* @__PURE__ */ new Set() }; | ||
function setGlobal(globalObj) { | ||
DLStore.global = globalObj; | ||
} | ||
function setDocument(customDocument) { | ||
DLStore.document = customDocument; | ||
} | ||
function cached(deps, prevDeps) { | ||
if (!prevDeps || deps.length !== prevDeps.length) return false; | ||
return deps.every((dep, i) => !(dep instanceof Object) && prevDeps[i] === dep); | ||
} | ||
// src/DLNode.js | ||
var DLNodeType = { | ||
Comp: 0, | ||
For: 1, | ||
Cond: 2, | ||
Env: 3, | ||
Exp: 4, | ||
Snippet: 5, | ||
Try: 6 | ||
}; | ||
var DLNode = class _DLNode { | ||
/** | ||
* @brief Node type: HTML, Text, Custom, For, If, Env, Expression | ||
*/ | ||
_$dlNodeType; | ||
/** | ||
* @brief Constructor | ||
* @param nodeType | ||
*/ | ||
constructor(nodeType) { | ||
this._$dlNodeType = nodeType; | ||
} | ||
/** | ||
* @brief Node element | ||
* Either one real element for HTMLNode and TextNode | ||
* Or an array of DLNode for CustomNode, ForNode, IfNode, EnvNode, ExpNode | ||
*/ | ||
get _$el() { | ||
return _DLNode.toEls(this._$nodes); | ||
} | ||
/** | ||
* @brief Loop all child DLNodes to get all the child elements | ||
* @param nodes | ||
* @returns HTMLElement[] | ||
*/ | ||
static toEls(nodes) { | ||
const els = []; | ||
this.loopShallowEls(nodes, (el) => { | ||
els.push(el); | ||
}); | ||
return els; | ||
} | ||
// ---- Loop nodes ---- | ||
/** | ||
* @brief Loop all elements shallowly, | ||
* i.e., don't loop the child nodes of dom elements and only call runFunc on dom elements | ||
* @param nodes | ||
* @param runFunc | ||
*/ | ||
static loopShallowEls(nodes, runFunc) { | ||
const stack = [...nodes].reverse(); | ||
while (stack.length > 0) { | ||
const node = stack.pop(); | ||
if (!("_$dlNodeType" in node)) runFunc(node); | ||
else node._$nodes && stack.push(...[...node._$nodes].reverse()); | ||
} | ||
} | ||
/** | ||
* @brief Add parentEl to all nodes until the first element | ||
* @param nodes | ||
* @param parentEl | ||
*/ | ||
static addParentEl(nodes, parentEl) { | ||
nodes.forEach((node) => { | ||
if ("_$dlNodeType" in node) { | ||
node._$parentEl = parentEl; | ||
node._$nodes && _DLNode.addParentEl(node._$nodes, parentEl); | ||
} | ||
}); | ||
} | ||
// ---- Flow index and add child elements ---- | ||
/** | ||
* @brief Get the total count of dom elements before the stop node | ||
* @param nodes | ||
* @param stopNode | ||
* @returns total count of dom elements | ||
*/ | ||
static getFlowIndexFromNodes(nodes, stopNode) { | ||
let index = 0; | ||
const stack = [...nodes].reverse(); | ||
while (stack.length > 0) { | ||
const node = stack.pop(); | ||
if (node === stopNode) break; | ||
if ("_$dlNodeType" in node) { | ||
node._$nodes && stack.push(...[...node._$nodes].reverse()); | ||
} else { | ||
index++; | ||
} | ||
} | ||
return index; | ||
} | ||
/** | ||
* @brief Given an array of nodes, append them to the parentEl | ||
* 1. If nextSibling is provided, insert the nodes before the nextSibling | ||
* 2. If nextSibling is not provided, append the nodes to the parentEl | ||
* @param nodes | ||
* @param parentEl | ||
* @param nextSibling | ||
* @returns Added element count | ||
*/ | ||
static appendNodesWithSibling(nodes, parentEl, nextSibling) { | ||
if (nextSibling) return this.insertNodesBefore(nodes, parentEl, nextSibling); | ||
return this.appendNodes(nodes, parentEl); | ||
} | ||
/** | ||
* @brief Given an array of nodes, append them to the parentEl using the index | ||
* 1. If the index is the same as the length of the parentEl.childNodes, append the nodes to the parentEl | ||
* 2. If the index is not the same as the length of the parentEl.childNodes, insert the nodes before the node at the index | ||
* @param nodes | ||
* @param parentEl | ||
* @param index | ||
* @param length | ||
* @returns Added element count | ||
*/ | ||
static appendNodesWithIndex(nodes, parentEl, index, length) { | ||
length = length ?? parentEl.childNodes.length; | ||
if (length !== index) | ||
return this.insertNodesBefore(nodes, parentEl, parentEl.childNodes[index]); | ||
return this.appendNodes(nodes, parentEl); | ||
} | ||
/** | ||
* @brief Insert nodes before the nextSibling | ||
* @param nodes | ||
* @param parentEl | ||
* @param nextSibling | ||
* @returns Added element count | ||
*/ | ||
static insertNodesBefore(nodes, parentEl, nextSibling) { | ||
let count = 0; | ||
this.loopShallowEls(nodes, (el) => { | ||
parentEl.insertBefore(el, nextSibling); | ||
count++; | ||
}); | ||
return count; | ||
} | ||
/** | ||
* @brief Append nodes to the parentEl | ||
* @param nodes | ||
* @param parentEl | ||
* @returns Added element count | ||
*/ | ||
static appendNodes(nodes, parentEl) { | ||
let count = 0; | ||
this.loopShallowEls(nodes, (el) => { | ||
parentEl.appendChild(el); | ||
count++; | ||
}); | ||
return count; | ||
} | ||
// ---- Lifecycle ---- | ||
/** | ||
* @brief Add willUnmount function to node | ||
* @param node | ||
* @param func | ||
*/ | ||
static addWillUnmount(node, func) { | ||
const willUnmountStore = DLStore.global.WillUnmountStore; | ||
const currentStore = willUnmountStore[willUnmountStore.length - 1]; | ||
if (!currentStore) return; | ||
currentStore.push(func.bind(null, node)); | ||
} | ||
/** | ||
* @brief Add didUnmount function to node | ||
* @param node | ||
* @param func | ||
*/ | ||
static addDidUnmount(node, func) { | ||
const didUnmountStore = DLStore.global.DidUnmountStore; | ||
const currentStore = didUnmountStore[didUnmountStore.length - 1]; | ||
if (!currentStore) return; | ||
currentStore.push(func.bind(null, node)); | ||
} | ||
/** | ||
* @brief Add didUnmount function to global store | ||
* @param func | ||
*/ | ||
static addDidMount(node, func) { | ||
if (!DLStore.global.DidMountStore) DLStore.global.DidMountStore = []; | ||
DLStore.global.DidMountStore.push(func.bind(null, node)); | ||
} | ||
/** | ||
* @brief Run all didMount functions and reset the global store | ||
*/ | ||
static runDidMount() { | ||
const didMountStore = DLStore.global.DidMountStore; | ||
if (!didMountStore || didMountStore.length === 0) return; | ||
for (let i = didMountStore.length - 1; i >= 0; i--) { | ||
didMountStore[i](); | ||
} | ||
DLStore.global.DidMountStore = []; | ||
} | ||
}; | ||
// src/HTMLNode.js | ||
function cache(el, key, deps) { | ||
if (deps.length === 0) return false; | ||
const cacheKey = `$${key}`; | ||
if (cached(deps, el[cacheKey])) return true; | ||
el[cacheKey] = deps; | ||
return false; | ||
} | ||
function setStyle(el, value) { | ||
Object.entries(value).forEach(([key, value2]) => { | ||
if (key.startsWith("--")) { | ||
el.style.setProperty(key, value2); | ||
} else { | ||
el.style[key] = value2; | ||
} | ||
}); | ||
} | ||
function setDataset(el, value) { | ||
Object.assign(el.dataset, value); | ||
} | ||
function setHTMLProp(el, key, valueFunc, deps) { | ||
if (cache(el, key, deps)) return; | ||
el[key] = valueFunc(); | ||
} | ||
function setHTMLProps(el, value) { | ||
Object.entries(value).forEach(([key, v]) => { | ||
if (key === "style") return setStyle(el, v); | ||
if (key === "dataset") return setDataset(el, v); | ||
setHTMLProp(el, key, () => v, []); | ||
}); | ||
} | ||
function setHTMLAttr(el, key, valueFunc, deps) { | ||
if (cache(el, key, deps)) return; | ||
el.setAttribute(key, valueFunc()); | ||
} | ||
function setHTMLAttrs(el, value) { | ||
Object.entries(value).forEach(([key, v]) => { | ||
setHTMLAttr(el, key, () => v, []); | ||
}); | ||
} | ||
function setEvent(el, key, value) { | ||
const prevEvent = el[`$on${key}`]; | ||
if (prevEvent) el.removeEventListener(key, prevEvent); | ||
el.addEventListener(key, value); | ||
el[`$on${key}`] = value; | ||
} | ||
function eventHandler(e) { | ||
const key = `$$${e.type}`; | ||
for (const node of e.composedPath()) { | ||
if (node[key]) node[key](e); | ||
if (e.cancelBubble) return; | ||
} | ||
} | ||
function delegateEvent(el, key, value) { | ||
if (el[`$$${key}`] === value) return; | ||
el[`$$${key}`] = value; | ||
if (!DLStore.delegatedEvents.has(key)) { | ||
DLStore.delegatedEvents.add(key); | ||
DLStore.document.addEventListener(key, eventHandler); | ||
} | ||
} | ||
function createElement(tag) { | ||
return DLStore.document.createElement(tag); | ||
} | ||
function insertNode(el, node, position) { | ||
if (!el._$nodes) el._$nodes = Array.from(el.childNodes); | ||
el._$nodes.splice(position, 0, node); | ||
const flowIdx = DLNode.getFlowIndexFromNodes(el._$nodes, node); | ||
DLNode.appendNodesWithIndex([node], el, flowIdx); | ||
DLNode.addParentEl([node], el); | ||
} | ||
function forwardHTMLProp(el, key, valueFunc, deps) { | ||
if (key === "style") return setStyle(el, valueFunc()); | ||
if (key === "dataset") return setDataset(el, valueFunc()); | ||
if (key === "element") return; | ||
if (key === "prop") return setHTMLProps(el, valueFunc()); | ||
if (key === "attr") return setHTMLAttrs(el, valueFunc()); | ||
if (key === "innerHTML") return setHTMLProp(el, "innerHTML", valueFunc, deps); | ||
if (key === "textContent") | ||
return setHTMLProp(el, "textContent", valueFunc, deps); | ||
if (key === "forwardProp") return; | ||
if (key.startsWith("on")) { | ||
return setEvent(el, key.slice(2).toLowerCase(), valueFunc()); | ||
} | ||
setHTMLAttr(el, key, valueFunc, deps); | ||
} | ||
// src/CompNode.js | ||
var CompNode = class _CompNode extends DLNode { | ||
/** | ||
* @brief Constructor, Comp type | ||
* @internal | ||
* * key - private property key | ||
* * $$key - dependency number, e.g. 0b1, 0b10, 0b100 | ||
* * $s$key - set of properties that depend on this property | ||
* * $p$key - exist if this property is a prop | ||
* * $e$key - exist if this property is an env | ||
* * $en$key - exist if this property is an env, and it's the innermost env that contains this env | ||
* * $w$key - exist if this property is a watcher | ||
* * $f$key - a function that returns the value of this property, called when the property's dependencies change | ||
* * _$children - children nodes of type PropView | ||
* * _$contentKey - the key key of the content prop | ||
* * _$forwardProps - exist if this node is forwarding props | ||
* * _$forwardPropsId - the keys of the props that this node is forwarding, collected in _$setForwardProp | ||
* * _$forwardPropsSet - contain all the nodes that are forwarding props to this node, collected with _$addForwardProps | ||
*/ | ||
constructor() { | ||
super(DLNodeType.Comp); | ||
} | ||
/** | ||
* @brief Init function, called explicitly in the subclass's constructor | ||
* @param props - Object containing properties | ||
* @param content - Content to be used | ||
* @param children - Child nodes | ||
* @param forwardPropsScope - Scope for forwarding properties | ||
*/ | ||
_$init(props, content, children, forwardPropsScope) { | ||
this._$notInitd = true; | ||
if (forwardPropsScope) forwardPropsScope._$addForwardProps(this); | ||
if (content) this._$setContent(() => content[0], content[1]); | ||
if (props) | ||
props.forEach(([key, value, deps]) => { | ||
if (key === "props") return this._$setProps(() => value, deps); | ||
this._$setProp(key, () => value, deps); | ||
}); | ||
if (children) this._$children = children; | ||
DLStore.global.DLEnvStore && Object.entries(DLStore.global.DLEnvStore.envs).forEach( | ||
([key, [value, envNode]]) => { | ||
if (key === "_$catchable") { | ||
this._$catchable = value; | ||
return; | ||
} | ||
if (!(`$e$${key}` in this)) return; | ||
envNode.addNode(this); | ||
this._$initEnv(key, value, envNode); | ||
} | ||
); | ||
const willCall = () => { | ||
this._$callUpdatesBeforeInit(); | ||
this.didMount && DLNode.addDidMount(this, this.didMount.bind(this)); | ||
this.willUnmount && DLNode.addWillUnmount(this, this.willUnmount.bind(this)); | ||
DLNode.addDidUnmount(this, this._$setUnmounted.bind(this)); | ||
this.didUnmount && DLNode.addDidUnmount(this, this.didUnmount.bind(this)); | ||
this.willMount?.(); | ||
this._$nodes = this.Body?.() ?? []; | ||
}; | ||
if (this._$catchable) { | ||
this._$catchable(willCall)(); | ||
if (this._$update) | ||
this._$update = this._$catchable(this._$update.bind(this)); | ||
this._$updateDerived = this._$catchable(this._$updateDerived.bind(this)); | ||
delete this._$catchable; | ||
} else { | ||
willCall(); | ||
} | ||
} | ||
_$setUnmounted() { | ||
this._$unmounted = true; | ||
} | ||
/** | ||
* @brief Call updates manually before the node is mounted | ||
*/ | ||
_$callUpdatesBeforeInit() { | ||
const protoProps = Object.getOwnPropertyNames(Object.getPrototypeOf(this)); | ||
const ownProps = Object.getOwnPropertyNames(this); | ||
const allProps = [...protoProps, ...ownProps]; | ||
allProps.forEach((key) => { | ||
if (key.startsWith("$w$")) return this[key.slice(3)](); | ||
if (key.startsWith("$md$")) { | ||
const realKey = key.slice(4); | ||
this[realKey] = this[realKey](); | ||
return; | ||
} | ||
if (key.startsWith("$f$")) { | ||
const realKey = key.slice(3); | ||
this[realKey] = this[key]; | ||
this._$updateDerived(realKey); | ||
} | ||
}); | ||
delete this._$notInitd; | ||
} | ||
/** | ||
* @brief Set all the props to forward | ||
* @param key | ||
* @param value | ||
* @param deps | ||
*/ | ||
_$setPropToForward(key, value, deps) { | ||
this._$forwardPropsSet.forEach((node) => { | ||
const isContent = key === "_$content"; | ||
if (node._$dlNodeType === DLNodeType.Comp) { | ||
if (isContent) node._$setContent(() => value, deps); | ||
else node._$setProp(key, () => value, deps); | ||
return; | ||
} | ||
if (node instanceof HTMLElement) { | ||
if (isContent) key = "textContent"; | ||
forwardHTMLProp(node, key, () => value, deps); | ||
} | ||
}); | ||
} | ||
/** | ||
* @brief Define forward props | ||
* @param key | ||
* @param value | ||
*/ | ||
_$setForwardProp(key, valueFunc, deps) { | ||
const notInitd = "_$notInitd" in this; | ||
if (!notInitd && this._$cache(key, deps)) return; | ||
const value = valueFunc(); | ||
if (key === "_$content" && this._$contentKey) { | ||
this[this._$contentKey] = value; | ||
this._$updateDerived(this._$contentKey); | ||
} | ||
this[key] = value; | ||
this._$updateDerived(key); | ||
if (notInitd) this._$forwardPropsId.push(key); | ||
else this._$setPropToForward(key, value, deps); | ||
} | ||
/** | ||
* @brief Add a node to the set of nodes that are forwarding props to this node and init these props | ||
* @param node | ||
*/ | ||
_$addForwardProps(node) { | ||
this._$forwardPropsSet.add(node); | ||
this._$forwardPropsId.forEach((key) => { | ||
this._$setPropToForward(key, this[key], []); | ||
}); | ||
DLNode.addWillUnmount( | ||
node, | ||
this._$forwardPropsSet.delete.bind(this._$forwardPropsSet, node) | ||
); | ||
} | ||
/** | ||
* @brief Cache the deps and return true if the deps are the same as the previous deps | ||
* @param key | ||
* @param deps | ||
* @returns | ||
*/ | ||
_$cache(key, deps) { | ||
if (!deps || !deps.length) return false; | ||
const cacheKey = `$cc$${key}`; | ||
if (cached(deps, this[cacheKey])) return true; | ||
this[cacheKey] = deps; | ||
return false; | ||
} | ||
/** | ||
* @brief Set the content prop, the key is stored in _$contentKey | ||
* @param value | ||
*/ | ||
_$setContent(valueFunc, deps) { | ||
if ("_$forwardProps" in this) | ||
return this._$setForwardProp("_$content", valueFunc, deps); | ||
const contentKey = this._$contentKey; | ||
if (!contentKey) return; | ||
if (this._$cache(contentKey, deps)) return; | ||
this[contentKey] = valueFunc(); | ||
this._$updateDerived(contentKey); | ||
} | ||
/** | ||
* @brief Set a prop directly, if this is a forwarded prop, go and init forwarded props | ||
* @param key | ||
* @param value | ||
* @param deps | ||
*/ | ||
_$setProp(key, valueFunc, deps) { | ||
if ("_$forwardProps" in this) | ||
return this._$setForwardProp(key, valueFunc, deps); | ||
if (!(`$p$${key}` in this)) { | ||
console.warn(`[${key}] is not a prop in ${this.constructor.name}`); | ||
return; | ||
} | ||
if (this._$cache(key, deps)) return; | ||
this[key] = valueFunc(); | ||
this._$updateDerived(key); | ||
} | ||
_$setProps(valueFunc, deps) { | ||
if (this._$cache("props", deps)) return; | ||
const props = valueFunc(); | ||
if (!props) return; | ||
Object.entries(props).forEach(([key, value]) => { | ||
this._$setProp(key, () => value, []); | ||
}); | ||
} | ||
/** | ||
* @brief Init an env, put the corresponding innermost envNode in $en$key | ||
* @param key | ||
* @param value | ||
* @param envNode | ||
*/ | ||
_$initEnv(key, value, envNode) { | ||
this[key] = value; | ||
this[`$en$${key}`] = envNode; | ||
} | ||
// ---- Update functions | ||
/** | ||
* @brief Update an env, called in EnvNode._$update | ||
* @param key | ||
* @param value | ||
* @param envNode | ||
*/ | ||
_$updateEnv(key, value, envNode) { | ||
if (!(`$e$${key}` in this)) return; | ||
if (envNode !== this[`$en$${key}`]) return; | ||
this[key] = value; | ||
this._$updateDerived(key); | ||
} | ||
/** | ||
* @brief Update a prop | ||
*/ | ||
_$ud(exp, key) { | ||
this._$updateDerived(key); | ||
return exp; | ||
} | ||
/** | ||
* @brief Update properties that depend on this property | ||
* @param key | ||
*/ | ||
_$updateDerived(key) { | ||
if ("_$notInitd" in this) return; | ||
this[`$s$${key}`]?.forEach((k) => { | ||
if (`$w$${k}` in this) { | ||
this[k](key); | ||
} else if (`$md$${k}` in this) { | ||
this[k]._$update(); | ||
} else { | ||
this[k] = this[`$f$${k}`]; | ||
} | ||
}); | ||
this._$updateView(key); | ||
} | ||
_$updateView(key) { | ||
if (this._$modelCallee) return this._$updateModelCallee(); | ||
if (!("_$update" in this)) return; | ||
const depNum = this[`$$${key}`]; | ||
if (!depNum) return; | ||
if ("_$depNumsToUpdate" in this) { | ||
this._$depNumsToUpdate.push(depNum); | ||
} else { | ||
this._$depNumsToUpdate = [depNum]; | ||
Promise.resolve().then(() => { | ||
if (this._$unmounted) return; | ||
const depNums = this._$depNumsToUpdate; | ||
if (depNums.length > 0) { | ||
const depNum2 = depNums.reduce((acc, cur) => acc | cur, 0); | ||
this._$update(depNum2); | ||
} | ||
delete this._$depNumsToUpdate; | ||
}); | ||
} | ||
} | ||
_$updateModelCallee() { | ||
if ("_$depNumsToUpdate" in this) return; | ||
this._$depNumsToUpdate = true; | ||
Promise.resolve().then(() => { | ||
if (this._$unmounted) return; | ||
this._$modelCallee._$updateDerived(this._$modelKey); | ||
delete this._$depNumsToUpdate; | ||
}); | ||
} | ||
/** | ||
* @brief Update all props and content of the model | ||
*/ | ||
static _$updateModel(model, propsFunc, contentFunc) { | ||
const props = propsFunc() ?? {}; | ||
const collectedProps = props.s ?? []; | ||
props.m?.forEach(([props2, deps]) => { | ||
Object.entries(props2).forEach(([key, value]) => { | ||
collectedProps.push([key, value, deps]); | ||
}); | ||
}); | ||
collectedProps.forEach(([key, value, deps]) => { | ||
model._$setProp(key, () => value, deps); | ||
}); | ||
const content = contentFunc(); | ||
if (content) model._$setContent(() => content[0], content[1]); | ||
} | ||
static _$releaseModel() { | ||
delete this._$modelCallee; | ||
} | ||
/** | ||
* @brief Inject Dlight model in to a property | ||
* @param ModelCls | ||
* @param props { m: [props, deps], s: [key, value, deps] } | ||
* @param content | ||
* @param key | ||
* @returns | ||
*/ | ||
_$injectModel(ModelCls, propsFunc, contentFunc, key) { | ||
const props = propsFunc() ?? {}; | ||
const collectedProps = props.s ?? []; | ||
props.m?.forEach(([props2, deps]) => { | ||
Object.entries(props2).forEach(([key2, value]) => { | ||
collectedProps.push([key2, value, deps]); | ||
}); | ||
}); | ||
const model = new ModelCls(); | ||
model._$init(collectedProps, contentFunc(), null, null); | ||
model._$modelCallee = this; | ||
model._$modelKey = key; | ||
model._$update = _CompNode._$updateModel.bind( | ||
null, | ||
model, | ||
propsFunc, | ||
contentFunc | ||
); | ||
return model; | ||
} | ||
}; | ||
var View = CompNode; | ||
var Model = CompNode; | ||
function update(dlNode, key) { | ||
dlNode._$updateDerived(key); | ||
} | ||
// src/EnvNode.js | ||
var EnvStoreClass = class { | ||
constructor() { | ||
this.envs = {}; | ||
this.currentEnvNodes = []; | ||
} | ||
/** | ||
* @brief Add a node to the current env and merge envs | ||
* @param node - The node to add | ||
*/ | ||
addEnvNode(node) { | ||
this.currentEnvNodes.push(node); | ||
this.mergeEnvs(); | ||
} | ||
/** | ||
* @brief Replace the current env with the given nodes and merge envs | ||
* @param nodes - The nodes to replace the current environment with | ||
*/ | ||
replaceEnvNodes(nodes) { | ||
this.currentEnvNodes = nodes; | ||
this.mergeEnvs(); | ||
} | ||
/** | ||
* @brief Remove the last node from the current env and merge envs | ||
*/ | ||
removeEnvNode() { | ||
this.currentEnvNodes.pop(); | ||
this.mergeEnvs(); | ||
} | ||
/** | ||
* @brief Merge all the envs in currentEnvNodes, inner envs override outer envs | ||
*/ | ||
mergeEnvs() { | ||
this.envs = {}; | ||
this.currentEnvNodes.forEach((envNode) => { | ||
Object.entries(envNode.envs).forEach(([key, value]) => { | ||
this.envs[key] = [value, envNode]; | ||
}); | ||
}); | ||
} | ||
}; | ||
var EnvNode = class extends DLNode { | ||
constructor(envs, depsArr) { | ||
super(DLNodeType.Env); | ||
if (!("DLEnvStore" in DLStore.global)) | ||
DLStore.global.DLEnvStore = new EnvStoreClass(); | ||
this.envs = envs; | ||
this.depsArr = depsArr; | ||
this.updateNodes = /* @__PURE__ */ new Set(); | ||
DLStore.global.DLEnvStore.addEnvNode(this); | ||
} | ||
cached(deps, name) { | ||
if (!deps || !deps.length) return false; | ||
if (cached(deps, this.depsArr[name])) return true; | ||
this.depsArr[name] = deps; | ||
return false; | ||
} | ||
/** | ||
* @brief Update a specific env, and update all the comp nodes that depend on this env | ||
* @param name - The name of the environment variable to update | ||
* @param value - The new value of the environment variable | ||
*/ | ||
updateEnv(name, valueFunc, deps) { | ||
if (this.cached(deps, name)) return; | ||
const value = valueFunc(); | ||
this.envs[name] = value; | ||
if (DLStore.global.DLEnvStore.currentEnvNodes.includes(this)) { | ||
DLStore.global.DLEnvStore.mergeEnvs(); | ||
} | ||
this.updateNodes.forEach((node) => { | ||
node._$updateEnv(name, value, this); | ||
}); | ||
} | ||
/** | ||
* @brief Add a node to this.updateNodes, delete the node from this.updateNodes when it unmounts | ||
* @param node - The node to add | ||
*/ | ||
addNode(node) { | ||
this.updateNodes.add(node); | ||
DLNode.addWillUnmount( | ||
node, | ||
this.updateNodes.delete.bind(this.updateNodes, node) | ||
); | ||
} | ||
/** | ||
* @brief Set this._$nodes, and exit the current env | ||
* @param nodes - The nodes to set | ||
*/ | ||
initNodes(nodes) { | ||
this._$nodes = nodes; | ||
DLStore.global.DLEnvStore.removeEnvNode(); | ||
} | ||
}; | ||
// src/TextNode.js | ||
function createTextNode(value, deps) { | ||
const node = DLStore.document.createTextNode(value); | ||
node.$$deps = deps; | ||
return node; | ||
} | ||
function updateText(node, valueFunc, deps) { | ||
if (cached(deps, node.$$deps)) return; | ||
const value = valueFunc(); | ||
node.textContent = value; | ||
node.$$deps = deps; | ||
} | ||
// src/PropView.js | ||
var PropView = class { | ||
propViewFunc; | ||
dlUpdateFunc = /* @__PURE__ */ new Set(); | ||
/** | ||
* @brief PropView constructor, accept a function that returns a list of DLNode | ||
* @param propViewFunc - A function that when called, collects and returns an array of DLNode instances | ||
*/ | ||
constructor(propViewFunc) { | ||
this.propViewFunc = propViewFunc; | ||
} | ||
/** | ||
* @brief Build the prop view by calling the propViewFunc and add every single instance of the returned DLNode to dlUpdateNodes | ||
* @returns An array of DLNode instances returned by propViewFunc | ||
*/ | ||
build() { | ||
let update2; | ||
const addUpdate = (updateFunc) => { | ||
update2 = updateFunc; | ||
this.dlUpdateFunc.add(updateFunc); | ||
}; | ||
const newNodes = this.propViewFunc(addUpdate); | ||
if (newNodes.length === 0) return []; | ||
if (update2) { | ||
DLNode.addWillUnmount( | ||
newNodes[0], | ||
this.dlUpdateFunc.delete.bind(this.dlUpdateFunc, update2) | ||
); | ||
} | ||
return newNodes; | ||
} | ||
/** | ||
* @brief Update every node in dlUpdateNodes | ||
* @param changed - A parameter indicating what changed to trigger the update | ||
*/ | ||
update(...args) { | ||
this.dlUpdateFunc.forEach((update2) => { | ||
update2(...args); | ||
}); | ||
} | ||
}; | ||
function insertChildren(el, propView) { | ||
insertNode(el, { _$nodes: propView.build(), _$dlNodeType: 7 }, 0); | ||
} | ||
// src/SnippetNode.js | ||
var SnippetNode = class extends DLNode { | ||
constructor(depsArr) { | ||
super(DLNodeType.Snippet); | ||
this.depsArr = depsArr; | ||
} | ||
cached(deps, changed) { | ||
if (!deps || !deps.length) return false; | ||
const idx = Math.log2(changed); | ||
const prevDeps = this.depsArr[idx]; | ||
if (cached(deps, prevDeps)) return true; | ||
this.depsArr[idx] = deps; | ||
return false; | ||
} | ||
}; | ||
// src/MutableNode/MutableNode.js | ||
var MutableNode = class extends DLNode { | ||
/** | ||
* @brief Mutable node is a node that this._$nodes can be changed, things need to pay attention: | ||
* 1. The environment of the new nodes should be the same as the old nodes | ||
* 2. The new nodes should be added to the parentEl | ||
* 3. The old nodes should be removed from the parentEl | ||
* @param type | ||
*/ | ||
constructor(type) { | ||
super(type); | ||
if (DLStore.global.DLEnvStore && DLStore.global.DLEnvStore.currentEnvNodes.length > 0) { | ||
this.savedEnvNodes = [...DLStore.global.DLEnvStore.currentEnvNodes]; | ||
} | ||
} | ||
/** | ||
* @brief Initialize the new nodes, add parentEl to all nodes | ||
* @param nodes | ||
*/ | ||
initNewNodes(nodes) { | ||
DLNode.addParentEl(nodes, this._$parentEl); | ||
} | ||
/** | ||
* @brief Generate new nodes in the saved environment | ||
* @param newNodesFunc | ||
* @returns | ||
*/ | ||
geneNewNodesInEnv(newNodesFunc) { | ||
if (!this.savedEnvNodes) { | ||
const newNodes2 = newNodesFunc(); | ||
this.initNewNodes(newNodes2); | ||
return newNodes2; | ||
} | ||
const currentEnvNodes = DLStore.global.DLEnvStore.currentEnvNodes; | ||
DLStore.global.DLEnvStore.replaceEnvNodes(this.savedEnvNodes); | ||
const newNodes = newNodesFunc(); | ||
DLStore.global.DLEnvStore.replaceEnvNodes(currentEnvNodes); | ||
this.initNewNodes(newNodes); | ||
return newNodes; | ||
} | ||
initUnmountStore() { | ||
DLStore.global.WillUnmountStore.push([]); | ||
DLStore.global.DidUnmountStore.push([]); | ||
} | ||
/** | ||
* @brief Remove nodes from parentEl and run willUnmount and didUnmount | ||
* @param nodes | ||
* @param removeEl Only remove outermost element | ||
*/ | ||
removeNodes(nodes) { | ||
DLNode.loopShallowEls(nodes, (node) => { | ||
this._$parentEl.removeChild(node); | ||
}); | ||
} | ||
}; | ||
// src/MutableNode/ForNode.js | ||
var ForNode = class _ForNode extends MutableNode { | ||
array; | ||
nodeFunc; | ||
depNum; | ||
nodesMap = /* @__PURE__ */ new Map(); | ||
updateArr = []; | ||
/** | ||
* @brief Getter for nodes | ||
*/ | ||
get _$nodes() { | ||
const nodes = []; | ||
for (let idx = 0; idx < this.array.length; idx++) { | ||
nodes.push(...this.nodesMap.get(this.keys?.[idx] ?? idx)); | ||
} | ||
return nodes; | ||
} | ||
/** | ||
* @brief Constructor, For type | ||
* @param array | ||
* @param nodeFunc | ||
* @param keys | ||
*/ | ||
constructor(array, depNum, keys, nodeFunc) { | ||
super(DLNodeType.For); | ||
this.array = [...array]; | ||
this.keys = keys; | ||
this.depNum = depNum; | ||
this.addNodeFunc(nodeFunc); | ||
} | ||
/** | ||
* @brief To be called immediately after the constructor | ||
* @param nodeFunc | ||
*/ | ||
addNodeFunc(nodeFunc) { | ||
this.nodeFunc = nodeFunc; | ||
this.array.forEach((item, idx) => { | ||
this.initUnmountStore(); | ||
const key = this.keys?.[idx] ?? idx; | ||
const nodes = nodeFunc(item, this.updateArr, idx); | ||
this.nodesMap.set(key, nodes); | ||
this.setUnmountMap(key); | ||
}); | ||
_ForNode.addWillUnmount(this, this.runAllWillUnmount.bind(this)); | ||
_ForNode.addDidUnmount(this, this.runAllDidUnmount.bind(this)); | ||
} | ||
/** | ||
* @brief Update the view related to one item in the array | ||
* @param nodes | ||
* @param item | ||
*/ | ||
updateItem(idx, array, changed) { | ||
this.updateArr[idx]?.(changed ?? this.depNum, array[idx]); | ||
} | ||
updateItems(changed) { | ||
for (let idx = 0; idx < this.array.length; idx++) { | ||
this.updateItem(idx, this.array, changed); | ||
} | ||
} | ||
/** | ||
* @brief Non-array update function | ||
* @param changed | ||
*/ | ||
update(changed) { | ||
if (!(~this.depNum & changed)) return; | ||
this.updateItems(changed); | ||
} | ||
/** | ||
* @brief Array-related update function | ||
* @param newArray | ||
* @param newKeys | ||
*/ | ||
updateArray(newArray, newKeys) { | ||
if (newKeys) { | ||
this.updateWithKey(newArray, newKeys); | ||
return; | ||
} | ||
this.updateWithOutKey(newArray); | ||
} | ||
/** | ||
* @brief Shortcut to generate new nodes with idx and key | ||
*/ | ||
getNewNodes(idx, key, array, updateArr) { | ||
this.initUnmountStore(); | ||
const nodes = this.geneNewNodesInEnv( | ||
() => this.nodeFunc(array[idx], updateArr ?? this.updateArr, idx) | ||
); | ||
this.setUnmountMap(key); | ||
this.nodesMap.set(key, nodes); | ||
return nodes; | ||
} | ||
/** | ||
* @brief Set the unmount map by getting the last unmount map from the global store | ||
* @param key | ||
*/ | ||
setUnmountMap(key) { | ||
const willUnmountMap = DLStore.global.WillUnmountStore.pop(); | ||
if (willUnmountMap && willUnmountMap.length > 0) { | ||
if (!this.willUnmountMap) this.willUnmountMap = /* @__PURE__ */ new Map(); | ||
this.willUnmountMap.set(key, willUnmountMap); | ||
} | ||
const didUnmountMap = DLStore.global.DidUnmountStore.pop(); | ||
if (didUnmountMap && didUnmountMap.length > 0) { | ||
if (!this.didUnmountMap) this.didUnmountMap = /* @__PURE__ */ new Map(); | ||
this.didUnmountMap.set(key, didUnmountMap); | ||
} | ||
} | ||
/** | ||
* @brief Run all the unmount functions and clear the unmount map | ||
*/ | ||
runAllWillUnmount() { | ||
if (!this.willUnmountMap || this.willUnmountMap.size === 0) return; | ||
this.willUnmountMap.forEach((funcs) => { | ||
for (let i = 0; i < funcs.length; i++) funcs[i]?.(); | ||
}); | ||
this.willUnmountMap.clear(); | ||
} | ||
/** | ||
* @brief Run all the unmount functions and clear the unmount map | ||
*/ | ||
runAllDidUnmount() { | ||
if (!this.didUnmountMap || this.didUnmountMap.size === 0) return; | ||
this.didUnmountMap.forEach((funcs) => { | ||
for (let i = funcs.length - 1; i >= 0; i--) funcs[i]?.(); | ||
}); | ||
this.didUnmountMap.clear(); | ||
} | ||
/** | ||
* @brief Run the unmount functions of the given key | ||
* @param key | ||
*/ | ||
runWillUnmount(key) { | ||
if (!this.willUnmountMap || this.willUnmountMap.size === 0) return; | ||
const funcs = this.willUnmountMap.get(key); | ||
if (!funcs) return; | ||
for (let i = 0; i < funcs.length; i++) funcs[i]?.(); | ||
this.willUnmountMap.delete(key); | ||
} | ||
/** | ||
* @brief Run the unmount functions of the given key | ||
*/ | ||
runDidUnmount(key) { | ||
if (!this.didUnmountMap || this.didUnmountMap.size === 0) return; | ||
const funcs = this.didUnmountMap.get(key); | ||
if (!funcs) return; | ||
for (let i = funcs.length - 1; i >= 0; i--) funcs[i]?.(); | ||
this.didUnmountMap.delete(key); | ||
} | ||
/** | ||
* @brief Remove nodes from parentEl and run willUnmount and didUnmount | ||
* @param nodes | ||
* @param key | ||
*/ | ||
removeNodes(nodes, key) { | ||
this.runWillUnmount(key); | ||
super.removeNodes(nodes); | ||
this.runDidUnmount(key); | ||
this.nodesMap.delete(key); | ||
} | ||
/** | ||
* @brief Update the nodes without keys | ||
* @param newArray | ||
*/ | ||
updateWithOutKey(newArray) { | ||
const preLength = this.array.length; | ||
const currLength = newArray.length; | ||
if (preLength === currLength) { | ||
for (let idx = 0; idx < this.array.length; idx++) { | ||
this.updateItem(idx, newArray); | ||
} | ||
this.array = [...newArray]; | ||
return; | ||
} | ||
const parentEl = this._$parentEl; | ||
if (preLength < currLength) { | ||
let flowIndex = _ForNode.getFlowIndexFromNodes(parentEl._$nodes, this); | ||
const length = parentEl.childNodes.length; | ||
for (let idx = 0; idx < currLength; idx++) { | ||
if (idx < preLength) { | ||
flowIndex += _ForNode.getFlowIndexFromNodes(this.nodesMap.get(idx)); | ||
this.updateItem(idx, newArray); | ||
continue; | ||
} | ||
const newNodes = this.getNewNodes(idx, idx, newArray); | ||
_ForNode.appendNodesWithIndex(newNodes, parentEl, flowIndex, length); | ||
} | ||
_ForNode.runDidMount(); | ||
this.array = [...newArray]; | ||
return; | ||
} | ||
for (let idx = 0; idx < currLength; idx++) { | ||
this.updateItem(idx, newArray); | ||
} | ||
for (let idx = currLength; idx < preLength; idx++) { | ||
const nodes = this.nodesMap.get(idx); | ||
this.removeNodes(nodes, idx); | ||
} | ||
this.updateArr.splice(currLength, preLength - currLength); | ||
this.array = [...newArray]; | ||
} | ||
/** | ||
* @brief Update the nodes with keys | ||
* @param newArray | ||
* @param newKeys | ||
*/ | ||
updateWithKey(newArray, newKeys) { | ||
if (newKeys.length !== new Set(newKeys).size) { | ||
throw new Error("DLight: Duplicate keys in for loop are not allowed"); | ||
} | ||
const prevKeys = this.keys; | ||
this.keys = newKeys; | ||
if (_ForNode.arrayEqual(prevKeys, this.keys)) { | ||
for (let idx = 0; idx < newArray.length; idx++) { | ||
this.updateItem(idx, newArray); | ||
} | ||
this.array = [...newArray]; | ||
return; | ||
} | ||
const parentEl = this._$parentEl; | ||
if (this.keys.length === 0) { | ||
const parentNodes = parentEl._$nodes ?? []; | ||
if (parentNodes.length === 1 && parentNodes[0] === this) { | ||
this.runAllWillUnmount(); | ||
parentEl.innerHTML = ""; | ||
this.runAllDidUnmount(); | ||
} else { | ||
for (let prevIdx = 0; prevIdx < prevKeys.length; prevIdx++) { | ||
const prevKey = prevKeys[prevIdx]; | ||
this.removeNodes(this.nodesMap.get(prevKey), prevKey); | ||
} | ||
} | ||
this.nodesMap.clear(); | ||
this.updateArr = []; | ||
this.array = []; | ||
return; | ||
} | ||
const flowIndex = _ForNode.getFlowIndexFromNodes(parentEl._$nodes, this); | ||
if (prevKeys.length === 0) { | ||
const nextSibling = parentEl.childNodes[flowIndex]; | ||
for (let idx = 0; idx < this.keys.length; idx++) { | ||
const newNodes = this.getNewNodes(idx, this.keys[idx], newArray); | ||
_ForNode.appendNodesWithSibling(newNodes, parentEl, nextSibling); | ||
} | ||
_ForNode.runDidMount(); | ||
this.array = [...newArray]; | ||
return; | ||
} | ||
const shuffleKeys = []; | ||
const newUpdateArr = []; | ||
for (let prevIdx = 0; prevIdx < prevKeys.length; prevIdx++) { | ||
const prevKey = prevKeys[prevIdx]; | ||
if (this.keys.includes(prevKey)) { | ||
shuffleKeys.push(prevKey); | ||
newUpdateArr.push(this.updateArr[prevIdx]); | ||
continue; | ||
} | ||
this.removeNodes(this.nodesMap.get(prevKey), prevKey); | ||
} | ||
let length = parentEl.childNodes.length; | ||
let newFlowIndex = flowIndex; | ||
for (let idx = 0; idx < this.keys.length; idx++) { | ||
const key = this.keys[idx]; | ||
const prevIdx = shuffleKeys.indexOf(key); | ||
if (prevIdx !== -1) { | ||
newFlowIndex += _ForNode.getFlowIndexFromNodes(this.nodesMap.get(key)); | ||
newUpdateArr[prevIdx]?.(this.depNum, newArray[idx]); | ||
continue; | ||
} | ||
newUpdateArr.splice(idx, 0, null); | ||
const newNodes = this.getNewNodes(idx, key, newArray, newUpdateArr); | ||
shuffleKeys.splice(idx, 0, key); | ||
const count = _ForNode.appendNodesWithIndex( | ||
newNodes, | ||
parentEl, | ||
newFlowIndex, | ||
length | ||
); | ||
newFlowIndex += count; | ||
length += count; | ||
} | ||
_ForNode.runDidMount(); | ||
if (_ForNode.arrayEqual(this.keys, shuffleKeys)) { | ||
this.array = [...newArray]; | ||
this.updateArr = newUpdateArr; | ||
return; | ||
} | ||
newFlowIndex = flowIndex; | ||
const bufferNodes = /* @__PURE__ */ new Map(); | ||
for (let idx = 0; idx < this.keys.length; idx++) { | ||
const key = this.keys[idx]; | ||
const prevIdx = shuffleKeys.indexOf(key); | ||
const bufferedNode = bufferNodes.get(key); | ||
if (bufferedNode) { | ||
const bufferedFlowIndex = _ForNode.getFlowIndexFromNodes(bufferedNode); | ||
const lastEl = _ForNode.toEls(bufferedNode).pop(); | ||
const nextSibling = parentEl.childNodes[newFlowIndex + bufferedFlowIndex]; | ||
if (lastEl !== nextSibling && lastEl.nextSibling !== nextSibling) { | ||
_ForNode.insertNodesBefore(bufferedNode, parentEl, nextSibling); | ||
} | ||
newFlowIndex += bufferedFlowIndex; | ||
delete bufferNodes[idx]; | ||
} else if (prevIdx === idx) { | ||
newFlowIndex += _ForNode.getFlowIndexFromNodes(this.nodesMap.get(key)); | ||
continue; | ||
} else { | ||
const prevKey = shuffleKeys[idx]; | ||
bufferNodes.set(prevKey, this.nodesMap.get(prevKey)); | ||
const childNodes = this.nodesMap.get(key); | ||
const lastEl = _ForNode.toEls(childNodes).pop(); | ||
const nextSibling = parentEl.childNodes[newFlowIndex]; | ||
if (lastEl !== nextSibling && lastEl.nextSibling !== nextSibling) { | ||
newFlowIndex += _ForNode.insertNodesBefore( | ||
childNodes, | ||
parentEl, | ||
nextSibling | ||
); | ||
} | ||
} | ||
const tempKey = shuffleKeys[idx]; | ||
shuffleKeys[idx] = shuffleKeys[prevIdx]; | ||
shuffleKeys[prevIdx] = tempKey; | ||
const tempUpdateFunc = newUpdateArr[idx]; | ||
newUpdateArr[idx] = newUpdateArr[prevIdx]; | ||
newUpdateArr[prevIdx] = tempUpdateFunc; | ||
} | ||
this.array = [...newArray]; | ||
this.updateArr = newUpdateArr; | ||
} | ||
/** | ||
* @brief Compare two arrays | ||
* @param arr1 | ||
* @param arr2 | ||
* @returns | ||
*/ | ||
static arrayEqual(arr1, arr2) { | ||
if (arr1.length !== arr2.length) return false; | ||
return arr1.every((item, idx) => item === arr2[idx]); | ||
} | ||
}; | ||
// src/MutableNode/FlatNode.js | ||
var FlatNode = class extends MutableNode { | ||
willUnmountFuncs = []; | ||
didUnmountFuncs = []; | ||
setUnmountFuncs() { | ||
this.willUnmountFuncs = DLStore.global.WillUnmountStore.pop(); | ||
this.didUnmountFuncs = DLStore.global.DidUnmountStore.pop(); | ||
} | ||
runWillUnmount() { | ||
for (let i = 0; i < this.willUnmountFuncs.length; i++) | ||
this.willUnmountFuncs[i](); | ||
} | ||
runDidUnmount() { | ||
for (let i = this.didUnmountFuncs.length - 1; i >= 0; i--) | ||
this.didUnmountFuncs[i](); | ||
} | ||
removeNodes(nodes) { | ||
this.runWillUnmount(); | ||
super.removeNodes(nodes); | ||
this.runDidUnmount(); | ||
} | ||
geneNewNodesInEnv(newNodesFunc) { | ||
this.initUnmountStore(); | ||
const nodes = super.geneNewNodesInEnv(newNodesFunc); | ||
this.setUnmountFuncs(); | ||
return nodes; | ||
} | ||
}; | ||
// src/MutableNode/ExpNode.js | ||
var ExpNode = class _ExpNode extends FlatNode { | ||
/** | ||
* @brief Constructor, Exp type, accept a function that returns a list of nodes | ||
* @param nodesFunc | ||
*/ | ||
constructor(value, deps) { | ||
super(DLNodeType.Exp); | ||
this.initUnmountStore(); | ||
this._$nodes = _ExpNode.formatNodes(value); | ||
this.setUnmountFuncs(); | ||
this.deps = this.parseDeps(deps); | ||
_ExpNode.addWillUnmount(this, this.runWillUnmount.bind(this)); | ||
_ExpNode.addDidUnmount(this, this.runDidUnmount.bind(this)); | ||
} | ||
parseDeps(deps) { | ||
return deps.map((dep) => { | ||
if (dep?.prototype?._$init) return dep.toString(); | ||
if (dep?.propViewFunc) return dep.propViewFunc.toString(); | ||
return dep; | ||
}); | ||
} | ||
cache(deps) { | ||
if (!deps || !deps.length) return false; | ||
deps = this.parseDeps(deps); | ||
if (cached(deps, this.deps)) return true; | ||
this.deps = deps; | ||
return false; | ||
} | ||
/** | ||
* @brief Generate new nodes and replace the old nodes | ||
*/ | ||
update(valueFunc, deps) { | ||
if (this.cache(deps)) return; | ||
this.removeNodes(this._$nodes); | ||
const newNodes = this.geneNewNodesInEnv( | ||
() => _ExpNode.formatNodes(valueFunc()) | ||
); | ||
if (newNodes.length === 0) { | ||
this._$nodes = []; | ||
return; | ||
} | ||
const parentEl = this._$parentEl; | ||
const flowIndex = _ExpNode.getFlowIndexFromNodes(parentEl._$nodes, this); | ||
const nextSibling = parentEl.childNodes[flowIndex]; | ||
_ExpNode.appendNodesWithSibling(newNodes, parentEl, nextSibling); | ||
_ExpNode.runDidMount(); | ||
this._$nodes = newNodes; | ||
} | ||
/** | ||
* @brief Format the nodes | ||
* @param nodes | ||
* @returns New nodes | ||
*/ | ||
static formatNodes(nodes) { | ||
if (!Array.isArray(nodes)) nodes = [nodes]; | ||
return nodes.flat(1).filter( | ||
(node) => node !== void 0 && node !== null && typeof node !== "boolean" | ||
).map((node) => { | ||
if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") { | ||
return DLStore.document.createTextNode(`${node}`); | ||
} | ||
if ("propViewFunc" in node) return node.build(); | ||
return node; | ||
}).flat(1); | ||
} | ||
}; | ||
// src/MutableNode/CondNode.js | ||
var CondNode = class _CondNode extends FlatNode { | ||
/** | ||
* @brief Constructor, If type, accept a function that returns a list of nodes | ||
* @param caseFunc | ||
*/ | ||
constructor(depNum, condFunc) { | ||
super(DLNodeType.Cond); | ||
this.depNum = depNum; | ||
this.cond = -1; | ||
this.condFunc = condFunc; | ||
this.initUnmountStore(); | ||
this._$nodes = this.condFunc(this); | ||
this.setUnmountFuncs(); | ||
_CondNode.addWillUnmount(this, this.runWillUnmount.bind(this)); | ||
_CondNode.addDidUnmount(this, this.runDidUnmount.bind(this)); | ||
} | ||
/** | ||
* @brief Update the nodes in the environment | ||
*/ | ||
updateCond(key) { | ||
const prevFuncs = [this.willUnmountFuncs, this.didUnmountFuncs]; | ||
const newNodes = this.geneNewNodesInEnv(() => this.condFunc(this)); | ||
if (this.didntChange) { | ||
; | ||
[this.willUnmountFuncs, this.didUnmountFuncs] = prevFuncs; | ||
this.didntChange = false; | ||
this.updateFunc?.(this.depNum, key); | ||
return; | ||
} | ||
const newFuncs = [this.willUnmountFuncs, this.didUnmountFuncs]; | ||
[this.willUnmountFuncs, this.didUnmountFuncs] = prevFuncs; | ||
this._$nodes && this._$nodes.length > 0 && this.removeNodes(this._$nodes); | ||
[this.willUnmountFuncs, this.didUnmountFuncs] = newFuncs; | ||
if (newNodes.length === 0) { | ||
this._$nodes = []; | ||
return; | ||
} | ||
const parentEl = this._$parentEl; | ||
const flowIndex = _CondNode.getFlowIndexFromNodes(parentEl._$nodes, this); | ||
const nextSibling = parentEl.childNodes[flowIndex]; | ||
_CondNode.appendNodesWithSibling(newNodes, parentEl, nextSibling); | ||
_CondNode.runDidMount(); | ||
this._$nodes = newNodes; | ||
} | ||
/** | ||
* @brief The update function of IfNode's childNodes is stored in the first child node | ||
* @param changed | ||
*/ | ||
update(changed) { | ||
if (!(~this.depNum & changed)) return; | ||
this.updateFunc?.(changed); | ||
} | ||
}; | ||
// src/MutableNode/TryNode.js | ||
var TryNode = class extends FlatNode { | ||
constructor(tryFunc, catchFunc) { | ||
super(DLNodeType.Try); | ||
this.tryFunc = tryFunc; | ||
const catchable = this.getCatchable(catchFunc); | ||
this.envNode = new EnvNode({ _$catchable: catchable }); | ||
const nodes = tryFunc(this.setUpdateFunc.bind(this), catchable) ?? []; | ||
this.envNode.initNodes(nodes); | ||
this._$nodes = nodes; | ||
} | ||
update(changed) { | ||
this.updateFunc?.(changed); | ||
} | ||
setUpdateFunc(updateFunc) { | ||
this.updateFunc = updateFunc; | ||
} | ||
getCatchable(catchFunc) { | ||
return (callback) => (...args) => { | ||
try { | ||
return callback(...args); | ||
} catch (e) { | ||
Promise.resolve().then(() => { | ||
const nodes = this.geneNewNodesInEnv( | ||
() => catchFunc(this.setUpdateFunc.bind(this), e) | ||
); | ||
this._$nodes && this.removeNodes(this._$nodes); | ||
const parentEl = this._$parentEl; | ||
const flowIndex = FlatNode.getFlowIndexFromNodes( | ||
parentEl._$nodes, | ||
this | ||
); | ||
const nextSibling = parentEl.childNodes[flowIndex]; | ||
FlatNode.appendNodesWithSibling(nodes, parentEl, nextSibling); | ||
FlatNode.runDidMount(); | ||
this._$nodes = nodes; | ||
}); | ||
} | ||
}; | ||
} | ||
}; | ||
// src/index.js | ||
function initStore() { | ||
DLStore.global.WillUnmountStore = []; | ||
DLStore.global.DidUnmountStore = []; | ||
} | ||
function render(idOrEl, DL) { | ||
let el = idOrEl; | ||
if (typeof idOrEl === "string") { | ||
const elFound = DLStore.document.getElementById(idOrEl); | ||
if (elFound) el = elFound; | ||
else { | ||
throw new Error(`DLight: Element with id ${idOrEl} not found`); | ||
} | ||
} | ||
initStore(); | ||
el.innerHTML = ""; | ||
const dlNode = new DL(); | ||
dlNode._$init(); | ||
insertNode(el, dlNode, 0); | ||
DLNode.runDidMount(); | ||
} | ||
function manual(callback, _deps) { | ||
return callback(); | ||
} | ||
function escape(arg) { | ||
return arg; | ||
} | ||
var $ = escape; | ||
var required = null; | ||
function use() { | ||
console.error( | ||
"DLight: use() is not supported be called directly. You can only assign `use(model)` to a dlight class property. Any other expressions are not allowed." | ||
); | ||
} | ||
export { | ||
$, | ||
CompNode, | ||
CondNode, | ||
EnvNode, | ||
EnvStoreClass, | ||
ExpNode, | ||
ForNode, | ||
Model, | ||
PropView, | ||
SnippetNode, | ||
TryNode, | ||
View, | ||
createElement, | ||
createTextNode, | ||
delegateEvent, | ||
escape, | ||
forwardHTMLProp, | ||
insertChildren, | ||
insertNode, | ||
manual, | ||
render, | ||
required, | ||
setDataset, | ||
setDocument, | ||
setEvent, | ||
setGlobal, | ||
setHTMLAttr, | ||
setHTMLAttrs, | ||
setHTMLProp, | ||
setHTMLProps, | ||
setStyle, | ||
update, | ||
updateText, | ||
use | ||
}; | ||
//# sourceMappingURL=index.js.map |
import { type Properties } from "csstype" | ||
// ---- Used to determine whether X and Y are equal, return A if equal, otherwise B | ||
type IfEquals<X, Y, A, B> = (<T>() => T extends X ? 1 : 2) extends < | ||
T, | ||
>() => T extends Y ? 1 : 2 | ||
? A | ||
: B | ||
type IfEquals<X, Y, A, B> = | ||
(<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B | ||
@@ -10,0 +7,0 @@ export type OmitIndexSignature<ObjectType> = { |
{ | ||
"name": "@dlightjs/dlight", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "DX-first UI rendering library", | ||
@@ -21,2 +21,12 @@ "author": { | ||
"typings": "dist/index.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs" | ||
}, | ||
"./global": { | ||
"types": "./dist/types/global.d.ts" | ||
} | ||
}, | ||
"dependencies": { | ||
@@ -35,3 +45,3 @@ "csstype": "^3.1.3", | ||
"clean": true, | ||
"minify": true | ||
"minify": false | ||
}, | ||
@@ -38,0 +48,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
304857
17
4033
1