@ryupold/vode 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vode.min.mjs CHANGED
@@ -1 +1 @@
1
- function P(f,z,...G){if(!f)throw Error("first argument to vode() must be a tag name or a vode");if(Array.isArray(f))return f;else if(z)return[f,z,...G];else return[f,...G]}function m(f,z,G,...E){if(!f?.parentElement)throw Error("first argument to app() must be a valid HTMLElement inside the <html></html> document");if(!z||typeof z!=="object")throw Error("second argument to app() must be a state object");if(typeof G!=="function")throw Error("third argument to app() must be a function that returns a vode");let q={};q.stats={lastRenderTime:0,renderCount:0,liveEffectCount:0,patchCount:0,renderPatchCount:0},Object.defineProperty(z,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(J)=>{if(!J||typeof J!=="function"&&typeof J!=="object")return;if(q.stats.patchCount++,J?.next){let U=J;q.stats.liveEffectCount++;try{let $=await U.next();while($.done===!1){q.stats.liveEffectCount++;try{q.patch($.value),$=await U.next()}finally{q.stats.liveEffectCount--}}q.patch($.value)}finally{q.stats.liveEffectCount--}}else if(J.then){q.stats.liveEffectCount++;try{let U=await J;q.patch(U)}finally{q.stats.liveEffectCount--}}else if(Array.isArray(J))if(typeof J[0]==="function")if(J.length>1)q.patch(J[0](q.state,...J.slice(1)));else q.patch(J[0](q.state));else q.stats.patchCount--;else if(typeof J==="function")q.patch(J(q.state));else if(q.stats.renderPatchCount++,q.q=C(q.q||{},J,!1),!q.isRendering)q.render()}}),Object.defineProperty(q,"render",{enumerable:!1,configurable:!0,writable:!1,value:()=>requestAnimationFrame(()=>{if(q.isRendering||!q.q)return;q.isRendering=!0;let J=Date.now();try{q.state=C(q.state,q.q,!0),q.q=null;let U=G(q.state);if(q.vode=D(q.state,q.patch,f.parentElement,0,q.vode,U),f.tagName.toUpperCase()!==U[0].toUpperCase())f=q.vode.node,f._vode=q}finally{if(q.isRendering=!1,q.stats.renderCount++,q.stats.lastRenderTime=Date.now()-J,q.q)q.render()}})}),q.patch=z.patch,q.state=z,q.q=null;let B=f;B._vode=q,q.vode=D(z,q.patch,f.parentElement,Array.from(f.parentElement.children).indexOf(f),x(f,!0),G(z));for(let J of E)q.patch(J);return q.patch}function x(f,z){if(f?.nodeType===Node.TEXT_NODE){if(f.nodeValue?.trim()!=="")return z?f:f.nodeValue;return}else if(f.nodeType===Node.COMMENT_NODE)return;else if(f.nodeType===Node.ELEMENT_NODE){let E=[f.tagName.toLowerCase()];if(z)E.node=f;if(f?.hasAttributes()){let q={},B=f.attributes;for(let J of B)q[J.name]=J.value;E.push(q)}if(f.hasChildNodes()){let q=[];for(let B of f.childNodes){let J=B&&x(B,z);if(J)E.push(J);else if(B&&z)q.push(B)}for(let B of q)B.remove()}return E}else return}function h(f,z){if(!f||!Array.isArray(f))throw Error("first argument to memo() must be an array of values to compare");if(typeof z!=="function")throw Error("second argument to memo() must be a function that returns a vode or props object");return z.__memo=f,z}function u(f){if(!f||typeof f!=="object")throw Error("createState() must be called with a state object");return f}function v(f){return f}function c(f){return f?Array.isArray(f)?f[0]:typeof f==="string"||f.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function A(f){if(Array.isArray(f)&&f.length>1&&f[1]&&!Array.isArray(f[1])){if(typeof f[1]==="object"&&f[1].nodeType!==Node.TEXT_NODE)return f[1]}return}function i(f,z){if(!f)return z;if(!z)return f;if(typeof f==="string"&&typeof z==="string"){let G=f.split(" "),E=z.split(" "),q=new Set([...G,...E]);return Array.from(q).join(" ").trim()}else if(typeof f==="string"&&Array.isArray(z)){let G=new Set([...z,...f.split(" ")]);return Array.from(G).join(" ").trim()}else if(Array.isArray(f)&&typeof z==="string"){let G=new Set([...f,...z.split(" ")]);return Array.from(G).join(" ").trim()}else if(Array.isArray(f)&&Array.isArray(z)){let G=new Set([...f,...z]);return Array.from(G).join(" ").trim()}else if(typeof f==="string"&&typeof z==="object")return{[f]:!0,...z};else if(typeof f==="object"&&typeof z==="string")return{...f,[z]:!0};else if(typeof f==="object"&&typeof z==="object")return{...f,...z};else if(typeof f==="object"&&Array.isArray(z)){let G={...f};for(let E of z)G[E]=!0;return G}else if(Array.isArray(f)&&typeof z==="object"){let G={};for(let E of f)G[E]=!0;for(let E of Object.keys(z))G[E]=z[E];return G}throw Error(`cannot merge classes of ${f} (${typeof f}) and ${z} (${typeof z})`)}function R(f){let z=K(f);if(z>0)return f.slice(z);return null}function V(f){return f.length-K(f)}function w(f,z){return f[z+K(f)]}function K(f){return A(f)?2:1}function C(f,z,G){if(!z)return f;for(let E in z){let q=z[E];if(q&&typeof q==="object"){let B=f[E];if(B)if(Array.isArray(q))f[E]=[...q];else if(q instanceof Date&&B!==q)f[E]=new Date(q);else if(Array.isArray(B))f[E]=C({},q,G);else if(typeof B==="object")C(f[E],q,G);else f[E]=C({},q,G);else if(Array.isArray(q))f[E]=[...q];else if(q instanceof Date)f[E]=new Date(q);else f[E]=C({},q,G)}else if(q===void 0&&G)delete f[E];else f[E]=q}return f}function D(f,z,G,E,q,B,J){B=I(f,B,q);let U=!B||typeof B==="number"||typeof B==="boolean";if(B===q||!q&&U)return q;let $=q?.nodeType===Node.TEXT_NODE,W=$?q:q?.node;if(U){W?.onUnmount&&z(W.onUnmount(W)),W?.remove();return}let O=!U&&y(B),F=!U&&b(B),T=!!B&&typeof B!=="string"&&!!(B?.node||B?.nodeType===Node.TEXT_NODE);if(!O&&!F&&!T&&!q)throw Error("Invalid vode: "+typeof B+" "+JSON.stringify(B));else if(T&&O)B=B.wholeText;else if(T&&F)B=[...B];if($&&O){if(W.nodeValue!==B)W.nodeValue=B;return q}if(O&&(!W||!$)){let Y=document.createTextNode(B);if(W)W.onUnmount&&z(W.onUnmount(W)),W.replaceWith(Y);else if(G.childNodes[E])G.insertBefore(Y,G.childNodes[E]);else G.appendChild(Y);return Y}if(F&&(!W||$||q[0]!==B[0])){let Y=B;if(1 in Y)Y[1]=I(f,Y[1],void 0);let H=A(B);J=H?.xmlns||J;let Z=J?document.createElementNS(J,B[0]):document.createElement(B[0]);if(B.node=Z,S(z,Z,void 0,H),W)W.onUnmount&&z(W.onUnmount(W)),W.replaceWith(Z);else if(G.childNodes[E])G.insertBefore(Z,G.childNodes[E]);else G.appendChild(Z);let j=R(B);if(j)for(let X=0;X<j.length;X++){let Q=j[X],L=D(f,z,Z,X,void 0,Q,J);B[H?X+2:X+1]=L}return Z.onMount&&z(Z.onMount(Z)),B}if(!$&&F&&q[0]===B[0]){B.node=W;let Y=B,H=q,Z=!1;if(Y[1]?.__memo){let Q=Y[1];if(Y[1]=I(f,Y[1],H[1]),Q!==Y[1]){let L=A(B);S(z,W,A(q),L),Z=!!L}}else{let Q=A(B);S(z,W,A(q),Q),Z=!!Q}let j=R(B),X=R(q);if(j){for(let Q=0;Q<j.length;Q++){let L=j[Q],_=X&&X[Q],N=D(f,z,W,Q,_,L,J);if(N)B[Z?Q+2:Q+1]=N}for(let Q=j.length;X&&Q<X.length;Q++)if(X[Q]?.node)X[Q].node.remove();else if(X[Q]?.nodeType===Node.TEXT_NODE)X[Q].remove()}for(let Q=j?.length||0;Q<X?.length;Q++)if(X[Q]?.node)X[Q].node.remove();else if(X[Q]?.nodeType===Node.TEXT_NODE)X[Q].remove();return B}return}function b(f){return Array.isArray(f)&&f.length>0&&typeof f[0]==="string"}function y(f){return typeof f==="string"||f?.nodeType===Node.TEXT_NODE}function I(f,z,G){if(typeof z!=="function")return z;let E=z?.__memo,q=G?.__memo;if(Array.isArray(E)&&Array.isArray(q)&&E.length===q.length){let J=!0;for(let U=0;U<E.length;U++)if(E[U]!==q[U]){J=!1;break}if(J)return G}let B=g(z,f);if(typeof B==="object")B.__memo=z?.__memo;return B}function g(f,z){if(typeof f==="function")return g(f(z),z);else return f}function S(f,z,G,E){if(!E&&!G)return;if(G)for(let q in G){let B=G[q],J=E?.[q];if(B!==J)if(E)E[q]=M(f,z,q,B,J);else M(f,z,q,B,void 0)}if(E&&G){for(let q in E)if(!(q in G)){let B=E[q];E[q]=M(f,z,q,void 0,B)}}else if(E)for(let q in E){let B=E[q];E[q]=M(f,z,q,void 0,B)}}function M(f,z,G,E,q){if(G==="style")if(!q)z.style.cssText="";else if(typeof q==="string"){if(E!==q)z.style.cssText=q}else if(E&&typeof E==="object"){for(let B in{...E,...q})if(!E||q[B]!==E[B])z.style[B]=q[B];else if(E[B]&&!q[B])z.style[B]=void 0}else for(let B in q)z.style[B]=q[B];else if(G==="class")if(q)z.setAttribute("class",k(q));else z.removeAttribute("class");else if(G[0]==="o"&&G[1]==="n")if(q){let B=null;if(typeof q==="function"){let J=q;B=(U)=>f([J,U])}else if(Array.isArray(q)){let J=q,U=q[0];if(J.length>1)B=()=>f([U,...J.slice(1)]);else B=($)=>f([U,$])}else if(typeof q==="object")B=()=>f(q);z[G]=B}else z[G]=null;else if(q!==null&&q!==void 0&&q!==!1)z.setAttribute(G,q);else z.removeAttribute(G);return q}function k(f){if(typeof f==="string")return f;else if(Array.isArray(f))return f.map(k).join(" ");else if(typeof f==="object")return Object.keys(f).filter((z)=>f[z]).join(" ");else return""}var s="a",r="abbr",l="address",t="area",n="article",a="aside",d="audio",o="b",e="base",ff="bdi",qf="bdo",zf="blockquote",Bf="body",Ef="br",Gf="button",Jf="canvas",Qf="caption",Uf="cite",Wf="code",Xf="col",Yf="colgroup",Zf="data",$f="datalist",jf="dd",Lf="del",Af="details",Cf="dfn",Hf="dialog",Of="div",Ff="dl",Mf="dt",Df="em",Tf="embed",Rf="fieldset",If="figcaption",Sf="figure",Kf="footer",Nf="form",xf="h1",gf="h2",kf="h3",_f="h4",bf="h5",yf="h6",Pf="head",mf="header",hf="hgroup",uf="hr",vf="html",cf="i",Vf="iframe",wf="img",pf="input",sf="ins",rf="kbd",lf="label",tf="legend",nf="li",af="link",df="main",of="map",ef="mark",fq="menu",qq="meta",zq="meter",Bq="nav",Eq="noscript",Gq="object",Jq="ol",Qq="optgroup",Uq="option",Wq="output",Xq="p",Yq="picture",Zq="pre",$q="progress",jq="q",Lq="rp",Aq="rt",Cq="ruby",Hq="s",Oq="samp",Fq="script",Mq="search",Dq="section",Tq="select",Rq="slot",Iq="small",Sq="source",Kq="span",Nq="strong",xq="style",gq="sub",kq="summary",_q="sup",bq="table",yq="tbody",Pq="td",mq="template",hq="textarea",uq="tfoot",vq="th",cq="thead",iq="time",Vq="title",wq="tr",pq="track",sq="u",rq="ul",lq="var",tq="video",nq="wbr",aq="animate",dq="animateMotion",oq="animateTransform",eq="circle",fz="clipPath",qz="defs",zz="desc",Bz="ellipse",Ez="feBlend",Gz="feColorMatrix",Jz="feComponentTransfer",Qz="feComposite",Uz="feConvolveMatrix",Wz="feDiffuseLighting",Xz="feDisplacementMap",Yz="feDistantLight",Zz="feDropShadow",$z="feFlood",jz="feFuncA",Lz="feFuncB",Az="feFuncG",Cz="feFuncR",Hz="feGaussianBlur",Oz="feImage",Fz="feMerge",Mz="feMergeNode",Dz="feMorphology",Tz="feOffset",Rz="fePointLight",Iz="feSpecularLighting",Sz="feSpotLight",Kz="feTile",Nz="feTurbulence",xz="filter",gz="foreignObject",kz="g",_z="image",bz="line",yz="linearGradient",Pz="marker",mz="mask",hz="metadata",uz="mpath",vz="path",cz="pattern",iz="polygon",Vz="polyline",wz="radialGradient",pz="rect",sz="set",rz="stop",lz="svg",tz="switch",nz="symbol",az="text",dz="textPath",oz="tspan",ez="use",fB="view",qB="annotation",zB="annotation-xml",BB="maction",EB="math",GB="merror",JB="mfrac",QB="mi",UB="mmultiscripts",WB="mn",XB="mo",YB="mover",ZB="mpadded",$B="mphantom",jB="mprescripts",LB="mroot",AB="mrow",CB="ms",HB="mspace",OB="msqrt",FB="mstyle",MB="msub",DB="msubsup",TB="msup",RB="mtable",IB="mtd",SB="mtext",KB="mtr",NB="munder",xB="munderover",gB="semantics";export{P as vode,c as tag,A as props,i as mergeClass,h as memo,x as hydrate,u as createState,v as createPatch,K as childrenStart,R as children,V as childCount,w as child,m as app,nq as WBR,fB as VIEW,tq as VIDEO,lq as VAR,ez as USE,rq as UL,sq as U,oz as TSPAN,pq as TRACK,wq as TR,Vq as TITLE,iq as TIME,cq as THEAD,vq as TH,uq as TFOOT,dz as TEXTPATH,hq as TEXTAREA,az as TEXT,mq as TEMPLATE,Pq as TD,yq as TBODY,bq as TABLE,nz as SYMBOL,tz as SWITCH,lz as SVG,_q as SUP,kq as SUMMARY,gq as SUB,xq as STYLE,Nq as STRONG,rz as STOP,Kq as SPAN,Sq as SOURCE,Iq as SMALL,Rq as SLOT,sz as SET,gB as SEMANTICS,Tq as SELECT,Dq as SECTION,Mq as SEARCH,Fq as SCRIPT,Oq as SAMP,Hq as S,Cq as RUBY,Aq as RT,Lq as RP,pz as RECT,wz as RADIALGRADIENT,jq as Q,$q as PROGRESS,Zq as PRE,Vz as POLYLINE,iz as POLYGON,Yq as PICTURE,cz as PATTERN,vz as PATH,Xq as P,Wq as OUTPUT,Uq as OPTION,Qq as OPTGROUP,Jq as OL,Gq as OBJECT,Eq as NOSCRIPT,Bq as NAV,xB as MUNDEROVER,NB as MUNDER,KB as MTR,SB as MTEXT,IB as MTD,RB as MTABLE,TB as MSUP,DB as MSUBSUP,MB as MSUB,FB as MSTYLE,OB as MSQRT,HB as MSPACE,CB as MS,AB as MROW,LB as MROOT,jB as MPRESCRIPTS,$B as MPHANTOM,uz as MPATH,ZB as MPADDED,YB as MOVER,XB as MO,WB as MN,UB as MMULTISCRIPTS,QB as MI,JB as MFRAC,zq as METER,hz as METADATA,qq as META,GB as MERROR,fq as MENU,EB as MATH,mz as MASK,Pz as MARKER,ef as MARK,of as MAP,df as MAIN,BB as MACTION,af as LINK,yz as LINEARGRADIENT,bz as LINE,nf as LI,tf as LEGEND,lf as LABEL,rf as KBD,sf as INS,pf as INPUT,wf as IMG,_z as IMAGE,Vf as IFRAME,cf as I,vf as HTML,uf as HR,hf as HGROUP,mf as HEADER,Pf as HEAD,yf as H6,bf as H5,_f as H4,kf as H3,gf as H2,xf as H1,kz as G,Nf as FORM,gz as FOREIGNOBJECT,Kf as FOOTER,xz as FILTER,Sf as FIGURE,If as FIGCAPTION,Rf as FIELDSET,Nz as FETURBULENCE,Kz as FETILE,Sz as FESPOTLIGHT,Iz as FESPECULARLIGHTING,Rz as FEPOINTLIGHT,Tz as FEOFFSET,Dz as FEMORPHOLOGY,Mz as FEMERGENODE,Fz as FEMERGE,Oz as FEIMAGE,Hz as FEGAUSSIANBLUR,Cz as FEFUNCR,Az as FEFUNCG,Lz as FEFUNCB,jz as FEFUNCA,$z as FEFLOOD,Zz as FEDROPSHADOW,Yz as FEDISTANTLIGHT,Xz as FEDISPLACEMENTMAP,Wz as FEDIFFUSELIGHTING,Uz as FECONVOLVEMATRIX,Qz as FECOMPOSITE,Jz as FECOMPONENTTRANSFER,Gz as FECOLORMATRIX,Ez as FEBLEND,Tf as EMBED,Df as EM,Bz as ELLIPSE,Mf as DT,Ff as DL,Of as DIV,Hf as DIALOG,Cf as DFN,Af as DETAILS,zz as DESC,Lf as DEL,qz as DEFS,jf as DD,$f as DATALIST,Zf as DATA,Yf as COLGROUP,Xf as COL,Wf as CODE,fz as CLIPPATH,Uf as CITE,eq as CIRCLE,Qf as CAPTION,Jf as CANVAS,Gf as BUTTON,Ef as BR,Bf as BODY,zf as BLOCKQUOTE,qf as BDO,ff as BDI,e as BASE,o as B,d as AUDIO,a as ASIDE,n as ARTICLE,t as AREA,zB as ANNOTATION_XML,qB as ANNOTATION,oq as ANIMATETRANSFORM,dq as ANIMATEMOTION,aq as ANIMATE,l as ADDRESS,r as ABBR,s as A};
1
+ var R={currentViewTransition:void 0,requestAnimationFrame:window.requestAnimationFrame?window.requestAnimationFrame.bind(window):(z)=>z(),startViewTransition:document.startViewTransition?document.startViewTransition.bind(document):null};function u(z,E,...J){if(!z)throw Error("first argument to vode() must be a tag name or a vode");if(Array.isArray(z))return z;else if(E)return[z,E,...J];else return[z,...J]}function v(z,E,J,...G){if(!z?.parentElement)throw Error("first argument to app() must be a valid HTMLElement inside the <html></html> document");if(!E||typeof E!=="object")throw Error("second argument to app() must be a state object");if(typeof J!=="function")throw Error("third argument to app() must be a function that returns a vode");let q={};q.syncRenderer=R.requestAnimationFrame,q.asyncRenderer=R.startViewTransition,q.qSync=null,q.qAsync=null,q.stats={lastSyncRenderTime:0,lastAsyncRenderTime:0,syncRenderCount:0,asyncRenderCount:0,liveEffectCount:0,patchCount:0,syncRenderPatchCount:0,asyncRenderPatchCount:0},Object.defineProperty(E,"patch",{enumerable:!1,configurable:!0,writable:!1,value:async(U,H)=>{if(!U||typeof U!=="function"&&typeof U!=="object")return;if(q.stats.patchCount++,U?.next){let L=U;q.stats.liveEffectCount++;try{let M=await L.next();while(M.done===!1){q.stats.liveEffectCount++;try{q.patch(M.value,H),M=await L.next()}finally{q.stats.liveEffectCount--}}q.patch(M.value,H)}finally{q.stats.liveEffectCount--}}else if(U.then){q.stats.liveEffectCount++;try{let L=await U;q.patch(L,H)}finally{q.stats.liveEffectCount--}}else if(Array.isArray(U))if(U.length>0)for(let L of U)q.patch(L,!document.hidden&&!!q.asyncRenderer);else q.qSync=F(q.qSync||{},q.qAsync,!1),q.qAsync=null,R.currentViewTransition?.skipTransition(),q.stats.syncRenderPatchCount++,q.renderSync();else if(typeof U==="function")q.patch(U(q.state),H);else if(H)q.stats.asyncRenderPatchCount++,q.qAsync=F(q.qAsync||{},U,!1),await q.renderAsync();else q.stats.syncRenderPatchCount++,q.qSync=F(q.qSync||{},U,!1),q.renderSync()}});function B(U){let H=Date.now(),L=J(q.state);if(q.vode=C(q.state,q.patch,z.parentElement,0,q.vode,L),z.tagName.toUpperCase()!==L[0].toUpperCase())z=q.vode.node,z._vode=q;if(!U){if(q.stats.lastSyncRenderTime=Date.now()-H,q.stats.syncRenderCount++,q.isRendering=!1,q.qSync)q.renderSync()}}let Q=B.bind(null,!1),$=B.bind(null,!0);Object.defineProperty(q,"renderSync",{enumerable:!1,configurable:!0,writable:!1,value:()=>{if(q.isRendering||!q.qSync)return;q.isRendering=!0,q.state=F(q.state,q.qSync,!0),q.qSync=null,q.syncRenderer(Q)}}),Object.defineProperty(q,"renderAsync",{enumerable:!1,configurable:!0,writable:!1,value:async()=>{if(q.isAnimating||!q.qAsync)return;if(await R.currentViewTransition?.updateCallbackDone,q.isAnimating||!q.qAsync||document.hidden)return;q.isAnimating=!0;let U=Date.now();try{q.state=F(q.state,q.qAsync,!0),q.qAsync=null,R.currentViewTransition=q.asyncRenderer($),await R.currentViewTransition?.updateCallbackDone}finally{q.stats.lastAsyncRenderTime=Date.now()-U,q.stats.asyncRenderCount++,q.isAnimating=!1}if(q.qAsync)q.renderAsync()}}),q.patch=E.patch,q.state=E;let Y=z;Y._vode=q,q.vode=C(E,q.patch,z.parentElement,Array.from(z.parentElement.children).indexOf(z),x(z,!0),J(E));for(let U of G)q.patch(U);return q.patch}function x(z,E){if(z?.nodeType===Node.TEXT_NODE){if(z.nodeValue?.trim()!=="")return E?z:z.nodeValue;return}else if(z.nodeType===Node.COMMENT_NODE)return;else if(z.nodeType===Node.ELEMENT_NODE){let G=[z.tagName.toLowerCase()];if(E)G.node=z;if(z?.hasAttributes()){let q={},B=z.attributes;for(let Q of B)q[Q.name]=Q.value;G.push(q)}if(z.hasChildNodes()){let q=[];for(let B of z.childNodes){let Q=B&&x(B,E);if(Q)G.push(Q);else if(B&&E)q.push(B)}for(let B of q)B.remove()}return G}else return}function V(z,E){if(!z||!Array.isArray(z))throw Error("first argument to memo() must be an array of values to compare");if(typeof E!=="function")throw Error("second argument to memo() must be a function that returns a vode or props object");return E.__memo=z,E}function w(z){if(!z||typeof z!=="object")throw Error("createState() must be called with a state object");return z}function c(z){return z}function p(z){return z?Array.isArray(z)?z[0]:typeof z==="string"||z.nodeType===Node.TEXT_NODE?"#text":void 0:void 0}function D(z){if(Array.isArray(z)&&z.length>1&&z[1]&&!Array.isArray(z[1])){if(typeof z[1]==="object"&&z[1].nodeType!==Node.TEXT_NODE)return z[1]}return}function f(z){let E=N(z);if(E>0)return z.slice(E);return null}function i(z){return z.length-N(z)}function r(z,E){return z[E+N(z)]}function N(z){return D(z)?2:1}function F(z,E,J){if(!E)return z;for(let G in E){let q=E[G];if(q&&typeof q==="object"){let B=z[G];if(B)if(Array.isArray(q))z[G]=[...q];else if(q instanceof Date&&B!==q)z[G]=new Date(q);else if(Array.isArray(B))z[G]=F({},q,J);else if(typeof B==="object")F(z[G],q,J);else z[G]=F({},q,J);else if(Array.isArray(q))z[G]=[...q];else if(q instanceof Date)z[G]=new Date(q);else z[G]=F({},q,J)}else if(q===void 0&&J)delete z[G];else z[G]=q}return z}function C(z,E,J,G,q,B,Q){B=K(z,B,q);let $=!B||typeof B==="number"||typeof B==="boolean";if(B===q||!q&&$)return q;let Y=q?.nodeType===Node.TEXT_NODE,U=Y?q:q?.node;if($){U?.onUnmount&&E(U.onUnmount(U)),U?.remove();return}let H=!$&&y(B),L=!$&&g(B),M=!!B&&typeof B!=="string"&&!!(B?.node||B?.nodeType===Node.TEXT_NODE);if(!H&&!L&&!M&&!q)throw Error("Invalid vode: "+typeof B+" "+JSON.stringify(B));else if(M&&H)B=B.wholeText;else if(M&&L)B=[...B];if(Y&&H){if(U.nodeValue!==B)U.nodeValue=B;return q}if(H&&(!U||!Y)){let W=document.createTextNode(B);if(U)U.onUnmount&&E(U.onUnmount(U)),U.replaceWith(W);else if(J.childNodes[G])J.insertBefore(W,J.childNodes[G]);else J.appendChild(W);return W}if(L&&(!U||Y||q[0]!==B[0])){let W=B;if(1 in W)W[1]=K(z,W[1],void 0);let I=D(B);Q=I?.xmlns||Q;let j=Q?document.createElementNS(Q,B[0]):document.createElement(B[0]);if(B.node=j,S(z,E,j,void 0,I),U)U.onUnmount&&E(U.onUnmount(U)),U.replaceWith(j);else if(J.childNodes[G])J.insertBefore(j,J.childNodes[G]);else J.appendChild(j);let O=f(B);if(O)for(let Z=0;Z<O.length;Z++){let X=O[Z],T=C(z,E,j,Z,void 0,X,Q);B[I?Z+2:Z+1]=T}return j.onMount&&E(j.onMount(j)),B}if(!Y&&L&&q[0]===B[0]){B.node=U;let W=B,I=q,j=!1;if(W[1]?.__memo){let X=W[1];if(W[1]=K(z,W[1],I[1]),X!==W[1]){let T=D(B);S(z,E,U,D(q),T),j=!!T}}else{let X=D(B);S(z,E,U,D(q),X),j=!!X}let O=f(B),Z=f(q);if(O){for(let X=0;X<O.length;X++){let T=O[X],_=Z&&Z[X],b=C(z,E,U,X,_,T,Q);if(b)B[j?X+2:X+1]=b}for(let X=O.length;Z&&X<Z.length;X++)if(Z[X]?.node)Z[X].node.remove();else if(Z[X]?.nodeType===Node.TEXT_NODE)Z[X].remove()}for(let X=O?.length||0;X<Z?.length;X++)if(Z[X]?.node)Z[X].node.remove();else if(Z[X]?.nodeType===Node.TEXT_NODE)Z[X].remove();return B}return}function g(z){return Array.isArray(z)&&z.length>0&&typeof z[0]==="string"}function y(z){return typeof z==="string"||z?.nodeType===Node.TEXT_NODE}function K(z,E,J){if(typeof E!=="function")return E;let G=E?.__memo,q=J?.__memo;if(Array.isArray(G)&&Array.isArray(q)&&G.length===q.length){let Q=!0;for(let $=0;$<G.length;$++)if(G[$]!==q[$]){Q=!1;break}if(Q)return J}let B=k(E,z);if(typeof B==="object")B.__memo=E?.__memo;return B}function k(z,E){if(typeof z==="function")return k(z(E),E);else return z}function S(z,E,J,G,q){if(!q&&!G)return;if(G)for(let B in G){let Q=G[B],$=q?.[B];if(Q!==$)if(q)q[B]=A(z,E,J,B,Q,$);else A(z,E,J,B,Q,void 0)}if(q&&G){for(let B in q)if(!(B in G)){let Q=q[B];q[B]=A(z,E,J,B,void 0,Q)}}else if(q)for(let B in q){let Q=q[B];q[B]=A(z,E,J,B,void 0,Q)}}function A(z,E,J,G,q,B){if(G==="style")if(!B)J.style.cssText="";else if(typeof B==="string"){if(q!==B)J.style.cssText=B}else if(q&&typeof q==="object"){for(let Q in{...q,...B})if(!q||B[Q]!==q[Q])J.style[Q]=B[Q];else if(q[Q]&&!B[Q])J.style[Q]=void 0}else for(let Q in B)J.style[Q]=B[Q];else if(G==="class")if(B)J.setAttribute("class",P(B));else J.removeAttribute("class");else if(G[0]==="o"&&G[1]==="n")if(B){let Q=null;if(typeof B==="function"){let $=B;Q=(Y)=>E($(z,Y))}else if(typeof B==="object")Q=()=>E(B);J[G]=Q}else J[G]=null;else if(B!==null&&B!==void 0&&B!==!1)J.setAttribute(G,B);else J.removeAttribute(G);return B}function P(z){if(typeof z==="string")return z;else if(Array.isArray(z))return z.map(P).join(" ");else if(typeof z==="object")return Object.keys(z).filter((E)=>z[E]).join(" ");else return""}var s="a",n="abbr",t="address",d="area",a="article",o="aside",e="audio",qq="b",zq="base",Bq="bdi",Eq="bdo",Gq="blockquote",Jq="body",Qq="br",Uq="button",Xq="canvas",Zq="caption",$q="cite",Lq="code",Wq="col",jq="colgroup",Hq="data",Yq="datalist",Oq="dd",Fq="del",Mq="details",Tq="dfn",Rq="dialog",Dq="div",Iq="dl",Aq="dt",Cq="em",fq="embed",Kq="fieldset",Sq="figcaption",Nq="figure",bq="footer",xq="form",kq="h1",Pq="h2",_q="h3",gq="h4",yq="h5",hq="h6",mq="head",uq="header",vq="hgroup",Vq="hr",wq="html",cq="i",pq="iframe",iq="img",rq="input",lq="ins",sq="kbd",nq="label",tq="legend",dq="li",aq="link",oq="main",eq="map",qz="mark",zz="menu",Bz="meta",Ez="meter",Gz="nav",Jz="noscript",Qz="object",Uz="ol",Xz="optgroup",Zz="option",$z="output",Lz="p",Wz="picture",jz="pre",Hz="progress",Yz="q",Oz="rp",Fz="rt",Mz="ruby",Tz="s",Rz="samp",Dz="script",Iz="search",Az="section",Cz="select",fz="slot",Kz="small",Sz="source",Nz="span",bz="strong",xz="style",kz="sub",Pz="summary",_z="sup",gz="table",yz="tbody",hz="td",mz="template",uz="textarea",vz="tfoot",Vz="th",wz="thead",cz="time",pz="title",iz="tr",rz="track",lz="u",sz="ul",nz="var",tz="video",dz="wbr",az="animate",oz="animateMotion",ez="animateTransform",qB="circle",zB="clipPath",BB="defs",EB="desc",GB="ellipse",JB="feBlend",QB="feColorMatrix",UB="feComponentTransfer",XB="feComposite",ZB="feConvolveMatrix",$B="feDiffuseLighting",LB="feDisplacementMap",WB="feDistantLight",jB="feDropShadow",HB="feFlood",YB="feFuncA",OB="feFuncB",FB="feFuncG",MB="feFuncR",TB="feGaussianBlur",RB="feImage",DB="feMerge",IB="feMergeNode",AB="feMorphology",CB="feOffset",fB="fePointLight",KB="feSpecularLighting",SB="feSpotLight",NB="feTile",bB="feTurbulence",xB="filter",kB="foreignObject",PB="g",_B="image",gB="line",yB="linearGradient",hB="marker",mB="mask",uB="metadata",vB="mpath",VB="path",wB="pattern",cB="polygon",pB="polyline",iB="radialGradient",rB="rect",lB="set",sB="stop",nB="svg",tB="switch",dB="symbol",aB="text",oB="textPath",eB="tspan",qE="use",zE="view",BE="annotation",EE="annotation-xml",GE="maction",JE="math",QE="merror",UE="mfrac",XE="mi",ZE="mmultiscripts",$E="mn",LE="mo",WE="mover",jE="mpadded",HE="mphantom",YE="mprescripts",OE="mroot",FE="mrow",ME="ms",TE="mspace",RE="msqrt",DE="mstyle",IE="msub",AE="msubsup",CE="msup",fE="mtable",KE="mtd",SE="mtext",NE="mtr",bE="munder",xE="munderover",kE="semantics";function _E(...z){if(!z||z.length===0)return null;if(z.length===1)return z[0];let E=z[0];for(let J=1;J<z.length;J++){let G=E,q=z[J];if(!G)E=q;else if(!q)continue;else if(typeof G==="string"&&typeof q==="string"){let B=G.split(" "),Q=q.split(" "),$=new Set([...B,...Q]);E=Array.from($).join(" ").trim()}else if(typeof G==="string"&&Array.isArray(q)){let B=new Set([...q,...G.split(" ")]);E=Array.from(B).join(" ").trim()}else if(Array.isArray(G)&&typeof q==="string"){let B=new Set([...G,...q.split(" ")]);E=Array.from(B).join(" ").trim()}else if(Array.isArray(G)&&Array.isArray(q)){let B=new Set([...G,...q]);E=Array.from(B).join(" ").trim()}else if(typeof G==="string"&&typeof q==="object")E={[G]:!0,...q};else if(typeof G==="object"&&typeof q==="string")E={...G,[q]:!0};else if(typeof G==="object"&&typeof q==="object")E={...G,...q};else if(typeof G==="object"&&Array.isArray(q)){let B={...G};for(let Q of q)B[Q]=!0;E=B}else if(Array.isArray(G)&&typeof q==="object"){let B={};for(let Q of G)B[Q]=!0;for(let Q of Object.keys(q))B[Q]=q[Q];E=B}else throw Error(`cannot merge classes of ${G} (${typeof G}) and ${q} (${typeof q})`)}return E}class h{state;path;keys;constructor(z,E){this.state=z;this.path=E;this.keys=E.split(".")}get(){let z=this.keys,E=this.state?this.state[z[0]]:void 0;for(let J=1;J<z.length&&!!E;J++)E=E[z[J]];return E}put(z){this.putDeep(z,this.state)}patch(z){if(Array.isArray(z)){let E=[];for(let J of z)E.push(this.createPatch(J));this.state.patch(E)}this.state.patch(this.createPatch(z))}createPatch(z){let E={};return this.putDeep(z,E),E}putDeep(z,E){let J=this.keys;if(J.length>1){let G=0,q=E[J[G]];if(typeof q!=="object"||q===null)E[J[G]]=q={};for(G=1;G<J.length-1;G++){let B=q;if(q=q[J[G]],typeof q!=="object"||q===null)B[J[G]]=q={}}q[J[G]]=z}else if(typeof E[J[0]]==="object"&&typeof z==="object")Object.assign(E[J[0]],z);else E[J[0]]=z}}class m{state;get;put;patch;constructor(z,E,J,G){this.state=z;this.get=E;this.put=J;this.patch=G}}export{u as vode,p as tag,D as props,_E as mergeClass,V as memo,x as hydrate,R as globals,w as createState,c as createPatch,N as childrenStart,f as children,i as childCount,r as child,v as app,dz as WBR,zE as VIEW,tz as VIDEO,nz as VAR,qE as USE,sz as UL,lz as U,eB as TSPAN,rz as TRACK,iz as TR,pz as TITLE,cz as TIME,wz as THEAD,Vz as TH,vz as TFOOT,oB as TEXTPATH,uz as TEXTAREA,aB as TEXT,mz as TEMPLATE,hz as TD,yz as TBODY,gz as TABLE,dB as SYMBOL,tB as SWITCH,nB as SVG,_z as SUP,Pz as SUMMARY,kz as SUB,xz as STYLE,bz as STRONG,sB as STOP,Nz as SPAN,Sz as SOURCE,Kz as SMALL,fz as SLOT,lB as SET,kE as SEMANTICS,Cz as SELECT,Az as SECTION,Iz as SEARCH,Dz as SCRIPT,Rz as SAMP,Tz as S,Mz as RUBY,Fz as RT,Oz as RP,rB as RECT,iB as RADIALGRADIENT,Yz as Q,Hz as PROGRESS,jz as PRE,pB as POLYLINE,cB as POLYGON,Wz as PICTURE,wB as PATTERN,VB as PATH,Lz as P,$z as OUTPUT,Zz as OPTION,Xz as OPTGROUP,Uz as OL,Qz as OBJECT,Jz as NOSCRIPT,Gz as NAV,xE as MUNDEROVER,bE as MUNDER,NE as MTR,SE as MTEXT,KE as MTD,fE as MTABLE,CE as MSUP,AE as MSUBSUP,IE as MSUB,DE as MSTYLE,RE as MSQRT,TE as MSPACE,ME as MS,FE as MROW,OE as MROOT,YE as MPRESCRIPTS,HE as MPHANTOM,vB as MPATH,jE as MPADDED,WE as MOVER,LE as MO,$E as MN,ZE as MMULTISCRIPTS,XE as MI,UE as MFRAC,Ez as METER,uB as METADATA,Bz as META,QE as MERROR,zz as MENU,JE as MATH,mB as MASK,hB as MARKER,qz as MARK,eq as MAP,oq as MAIN,GE as MACTION,aq as LINK,yB as LINEARGRADIENT,gB as LINE,dq as LI,tq as LEGEND,nq as LABEL,h as KeyStateContext,sq as KBD,lq as INS,rq as INPUT,iq as IMG,_B as IMAGE,pq as IFRAME,cq as I,wq as HTML,Vq as HR,vq as HGROUP,uq as HEADER,mq as HEAD,hq as H6,yq as H5,gq as H4,_q as H3,Pq as H2,kq as H1,PB as G,xq as FORM,kB as FOREIGNOBJECT,bq as FOOTER,xB as FILTER,Nq as FIGURE,Sq as FIGCAPTION,Kq as FIELDSET,bB as FETURBULENCE,NB as FETILE,SB as FESPOTLIGHT,KB as FESPECULARLIGHTING,fB as FEPOINTLIGHT,CB as FEOFFSET,AB as FEMORPHOLOGY,IB as FEMERGENODE,DB as FEMERGE,RB as FEIMAGE,TB as FEGAUSSIANBLUR,MB as FEFUNCR,FB as FEFUNCG,OB as FEFUNCB,YB as FEFUNCA,HB as FEFLOOD,jB as FEDROPSHADOW,WB as FEDISTANTLIGHT,LB as FEDISPLACEMENTMAP,$B as FEDIFFUSELIGHTING,ZB as FECONVOLVEMATRIX,XB as FECOMPOSITE,UB as FECOMPONENTTRANSFER,QB as FECOLORMATRIX,JB as FEBLEND,fq as EMBED,Cq as EM,GB as ELLIPSE,m as DelegateStateContext,Aq as DT,Iq as DL,Dq as DIV,Rq as DIALOG,Tq as DFN,Mq as DETAILS,EB as DESC,Fq as DEL,BB as DEFS,Oq as DD,Yq as DATALIST,Hq as DATA,jq as COLGROUP,Wq as COL,Lq as CODE,zB as CLIPPATH,$q as CITE,qB as CIRCLE,Zq as CAPTION,Xq as CANVAS,Uq as BUTTON,Qq as BR,Jq as BODY,Gq as BLOCKQUOTE,Eq as BDO,Bq as BDI,zq as BASE,qq as B,e as AUDIO,o as ASIDE,a as ARTICLE,d as AREA,EE as ANNOTATION_XML,BE as ANNOTATION,ez as ANIMATETRANSFORM,oz as ANIMATEMOTION,az as ANIMATE,t as ADDRESS,n as ABBR,s as A};
package/dist/vode.mjs CHANGED
@@ -1,4 +1,9 @@
1
1
  // src/vode.ts
2
+ var globals = {
3
+ currentViewTransition: undefined,
4
+ requestAnimationFrame: window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : (cb) => cb(),
5
+ startViewTransition: document.startViewTransition ? document.startViewTransition.bind(document) : null
6
+ };
2
7
  function vode(tag, props, ...children) {
3
8
  if (!tag)
4
9
  throw new Error("first argument to vode() must be a tag name or a vode");
@@ -17,12 +22,16 @@ function app(container, state, dom, ...initialPatches) {
17
22
  if (typeof dom !== "function")
18
23
  throw new Error("third argument to app() must be a function that returns a vode");
19
24
  const _vode = {};
20
- _vode.stats = { lastRenderTime: 0, renderCount: 0, liveEffectCount: 0, patchCount: 0, renderPatchCount: 0 };
25
+ _vode.syncRenderer = globals.requestAnimationFrame;
26
+ _vode.asyncRenderer = globals.startViewTransition;
27
+ _vode.qSync = null;
28
+ _vode.qAsync = null;
29
+ _vode.stats = { lastSyncRenderTime: 0, lastAsyncRenderTime: 0, syncRenderCount: 0, asyncRenderCount: 0, liveEffectCount: 0, patchCount: 0, syncRenderPatchCount: 0, asyncRenderPatchCount: 0 };
21
30
  Object.defineProperty(state, "patch", {
22
31
  enumerable: false,
23
32
  configurable: true,
24
33
  writable: false,
25
- value: async (action) => {
34
+ value: async (action, isAsync) => {
26
35
  if (!action || typeof action !== "function" && typeof action !== "object")
27
36
  return;
28
37
  _vode.stats.patchCount++;
@@ -34,13 +43,13 @@ function app(container, state, dom, ...initialPatches) {
34
43
  while (v.done === false) {
35
44
  _vode.stats.liveEffectCount++;
36
45
  try {
37
- _vode.patch(v.value);
46
+ _vode.patch(v.value, isAsync);
38
47
  v = await generator.next();
39
48
  } finally {
40
49
  _vode.stats.liveEffectCount--;
41
50
  }
42
51
  }
43
- _vode.patch(v.value);
52
+ _vode.patch(v.value, isAsync);
44
53
  } finally {
45
54
  _vode.stats.liveEffectCount--;
46
55
  }
@@ -48,60 +57,96 @@ function app(container, state, dom, ...initialPatches) {
48
57
  _vode.stats.liveEffectCount++;
49
58
  try {
50
59
  const nextState = await action;
51
- _vode.patch(nextState);
60
+ _vode.patch(nextState, isAsync);
52
61
  } finally {
53
62
  _vode.stats.liveEffectCount--;
54
63
  }
55
64
  } else if (Array.isArray(action)) {
56
- if (typeof action[0] === "function") {
57
- if (action.length > 1)
58
- _vode.patch(action[0](_vode.state, ...action.slice(1)));
59
- else
60
- _vode.patch(action[0](_vode.state));
65
+ if (action.length > 0) {
66
+ for (const p of action) {
67
+ _vode.patch(p, !document.hidden && !!_vode.asyncRenderer);
68
+ }
61
69
  } else {
62
- _vode.stats.patchCount--;
70
+ _vode.qSync = mergeState(_vode.qSync || {}, _vode.qAsync, false);
71
+ _vode.qAsync = null;
72
+ globals.currentViewTransition?.skipTransition();
73
+ _vode.stats.syncRenderPatchCount++;
74
+ _vode.renderSync();
63
75
  }
64
76
  } else if (typeof action === "function") {
65
- _vode.patch(action(_vode.state));
77
+ _vode.patch(action(_vode.state), isAsync);
66
78
  } else {
67
- _vode.stats.renderPatchCount++;
68
- _vode.q = mergeState(_vode.q || {}, action, false);
69
- if (!_vode.isRendering)
70
- _vode.render();
79
+ if (isAsync) {
80
+ _vode.stats.asyncRenderPatchCount++;
81
+ _vode.qAsync = mergeState(_vode.qAsync || {}, action, false);
82
+ await _vode.renderAsync();
83
+ } else {
84
+ _vode.stats.syncRenderPatchCount++;
85
+ _vode.qSync = mergeState(_vode.qSync || {}, action, false);
86
+ _vode.renderSync();
87
+ }
71
88
  }
72
89
  }
73
90
  });
74
- Object.defineProperty(_vode, "render", {
91
+ function renderDom(isAsync) {
92
+ const sw = Date.now();
93
+ const vom = dom(_vode.state);
94
+ _vode.vode = render(_vode.state, _vode.patch, container.parentElement, 0, _vode.vode, vom);
95
+ if (container.tagName.toUpperCase() !== vom[0].toUpperCase()) {
96
+ container = _vode.vode.node;
97
+ container._vode = _vode;
98
+ }
99
+ if (!isAsync) {
100
+ _vode.stats.lastSyncRenderTime = Date.now() - sw;
101
+ _vode.stats.syncRenderCount++;
102
+ _vode.isRendering = false;
103
+ if (_vode.qSync)
104
+ _vode.renderSync();
105
+ }
106
+ }
107
+ const sr = renderDom.bind(null, false);
108
+ const ar = renderDom.bind(null, true);
109
+ Object.defineProperty(_vode, "renderSync", {
75
110
  enumerable: false,
76
111
  configurable: true,
77
112
  writable: false,
78
- value: () => requestAnimationFrame(() => {
79
- if (_vode.isRendering || !_vode.q)
113
+ value: () => {
114
+ if (_vode.isRendering || !_vode.qSync)
80
115
  return;
81
116
  _vode.isRendering = true;
117
+ _vode.state = mergeState(_vode.state, _vode.qSync, true);
118
+ _vode.qSync = null;
119
+ _vode.syncRenderer(sr);
120
+ }
121
+ });
122
+ Object.defineProperty(_vode, "renderAsync", {
123
+ enumerable: false,
124
+ configurable: true,
125
+ writable: false,
126
+ value: async () => {
127
+ if (_vode.isAnimating || !_vode.qAsync)
128
+ return;
129
+ await globals.currentViewTransition?.updateCallbackDone;
130
+ if (_vode.isAnimating || !_vode.qAsync || document.hidden)
131
+ return;
132
+ _vode.isAnimating = true;
82
133
  const sw = Date.now();
83
134
  try {
84
- _vode.state = mergeState(_vode.state, _vode.q, true);
85
- _vode.q = null;
86
- const vom = dom(_vode.state);
87
- _vode.vode = render(_vode.state, _vode.patch, container.parentElement, 0, _vode.vode, vom);
88
- if (container.tagName.toUpperCase() !== vom[0].toUpperCase()) {
89
- container = _vode.vode.node;
90
- container._vode = _vode;
91
- }
135
+ _vode.state = mergeState(_vode.state, _vode.qAsync, true);
136
+ _vode.qAsync = null;
137
+ globals.currentViewTransition = _vode.asyncRenderer(ar);
138
+ await globals.currentViewTransition?.updateCallbackDone;
92
139
  } finally {
93
- _vode.isRendering = false;
94
- _vode.stats.renderCount++;
95
- _vode.stats.lastRenderTime = Date.now() - sw;
96
- if (_vode.q) {
97
- _vode.render();
98
- }
140
+ _vode.stats.lastAsyncRenderTime = Date.now() - sw;
141
+ _vode.stats.asyncRenderCount++;
142
+ _vode.isAnimating = false;
99
143
  }
100
- })
144
+ if (_vode.qAsync)
145
+ _vode.renderAsync();
146
+ }
101
147
  });
102
148
  _vode.patch = state.patch;
103
149
  _vode.state = state;
104
- _vode.q = null;
105
150
  const root = container;
106
151
  root._vode = _vode;
107
152
  _vode.vode = render(state, _vode.patch, container.parentElement, Array.from(container.parentElement.children).indexOf(container), hydrate(container, true), dom(state));
@@ -175,49 +220,6 @@ function props(vode2) {
175
220
  }
176
221
  return;
177
222
  }
178
- function mergeClass(a, b) {
179
- if (!a)
180
- return b;
181
- if (!b)
182
- return a;
183
- if (typeof a === "string" && typeof b === "string") {
184
- const aSplit = a.split(" ");
185
- const bSplit = b.split(" ");
186
- const classSet = new Set([...aSplit, ...bSplit]);
187
- return Array.from(classSet).join(" ").trim();
188
- } else if (typeof a === "string" && Array.isArray(b)) {
189
- const classSet = new Set([...b, ...a.split(" ")]);
190
- return Array.from(classSet).join(" ").trim();
191
- } else if (Array.isArray(a) && typeof b === "string") {
192
- const classSet = new Set([...a, ...b.split(" ")]);
193
- return Array.from(classSet).join(" ").trim();
194
- } else if (Array.isArray(a) && Array.isArray(b)) {
195
- const classSet = new Set([...a, ...b]);
196
- return Array.from(classSet).join(" ").trim();
197
- } else if (typeof a === "string" && typeof b === "object") {
198
- return { [a]: true, ...b };
199
- } else if (typeof a === "object" && typeof b === "string") {
200
- return { ...a, [b]: true };
201
- } else if (typeof a === "object" && typeof b === "object") {
202
- return { ...a, ...b };
203
- } else if (typeof a === "object" && Array.isArray(b)) {
204
- const aa = { ...a };
205
- for (const item of b) {
206
- aa[item] = true;
207
- }
208
- return aa;
209
- } else if (Array.isArray(a) && typeof b === "object") {
210
- const aa = {};
211
- for (const item of a) {
212
- aa[item] = true;
213
- }
214
- for (const bKey of Object.keys(b)) {
215
- aa[bKey] = b[bKey];
216
- }
217
- return aa;
218
- }
219
- throw new Error(`cannot merge classes of ${a} (${typeof a}) and ${b} (${typeof b})`);
220
- }
221
223
  function children(vode2) {
222
224
  const start = childrenStart(vode2);
223
225
  if (start > 0) {
@@ -321,7 +323,7 @@ function render(state, patch, parent, childIndex, oldVode, newVode, xmlns) {
321
323
  xmlns = properties?.xmlns || xmlns;
322
324
  const newNode = xmlns ? document.createElementNS(xmlns, newVode[0]) : document.createElement(newVode[0]);
323
325
  newVode.node = newNode;
324
- patchProperties(patch, newNode, undefined, properties);
326
+ patchProperties(state, patch, newNode, undefined, properties);
325
327
  if (oldNode) {
326
328
  oldNode.onUnmount && patch(oldNode.onUnmount(oldNode));
327
329
  oldNode.replaceWith(newNode);
@@ -353,12 +355,12 @@ function render(state, patch, parent, childIndex, oldVode, newVode, xmlns) {
353
355
  newvode[1] = remember(state, newvode[1], oldvode[1]);
354
356
  if (prev !== newvode[1]) {
355
357
  const properties = props(newVode);
356
- patchProperties(patch, oldNode, props(oldVode), properties);
358
+ patchProperties(state, patch, oldNode, props(oldVode), properties);
357
359
  hasProps = !!properties;
358
360
  }
359
361
  } else {
360
362
  const properties = props(newVode);
361
- patchProperties(patch, oldNode, props(oldVode), properties);
363
+ patchProperties(state, patch, oldNode, props(oldVode), properties);
362
364
  hasProps = !!properties;
363
365
  }
364
366
  const newKids = children(newVode);
@@ -424,7 +426,7 @@ function unwrap(c, s) {
424
426
  return c;
425
427
  }
426
428
  }
427
- function patchProperties(patch, node, oldProps, newProps) {
429
+ function patchProperties(s, patch, node, oldProps, newProps) {
428
430
  if (!newProps && !oldProps)
429
431
  return;
430
432
  if (oldProps) {
@@ -433,9 +435,9 @@ function patchProperties(patch, node, oldProps, newProps) {
433
435
  const newValue = newProps?.[key];
434
436
  if (oldValue !== newValue) {
435
437
  if (newProps)
436
- newProps[key] = patchProperty(patch, node, key, oldValue, newValue);
438
+ newProps[key] = patchProperty(s, patch, node, key, oldValue, newValue);
437
439
  else
438
- patchProperty(patch, node, key, oldValue, undefined);
440
+ patchProperty(s, patch, node, key, oldValue, undefined);
439
441
  }
440
442
  }
441
443
  }
@@ -443,17 +445,17 @@ function patchProperties(patch, node, oldProps, newProps) {
443
445
  for (const key in newProps) {
444
446
  if (!(key in oldProps)) {
445
447
  const newValue = newProps[key];
446
- newProps[key] = patchProperty(patch, node, key, undefined, newValue);
448
+ newProps[key] = patchProperty(s, patch, node, key, undefined, newValue);
447
449
  }
448
450
  }
449
451
  } else if (newProps) {
450
452
  for (const key in newProps) {
451
453
  const newValue = newProps[key];
452
- newProps[key] = patchProperty(patch, node, key, undefined, newValue);
454
+ newProps[key] = patchProperty(s, patch, node, key, undefined, newValue);
453
455
  }
454
456
  }
455
457
  }
456
- function patchProperty(patch, node, key, oldValue, newValue) {
458
+ function patchProperty(s, patch, node, key, oldValue, newValue) {
457
459
  if (key === "style") {
458
460
  if (!newValue) {
459
461
  node.style.cssText = "";
@@ -484,15 +486,7 @@ function patchProperty(patch, node, key, oldValue, newValue) {
484
486
  let eventHandler = null;
485
487
  if (typeof newValue === "function") {
486
488
  const action = newValue;
487
- eventHandler = (evt) => patch([action, evt]);
488
- } else if (Array.isArray(newValue)) {
489
- const arr = newValue;
490
- const action = newValue[0];
491
- if (arr.length > 1) {
492
- eventHandler = () => patch([action, ...arr.slice(1)]);
493
- } else {
494
- eventHandler = (evt) => patch([action, evt]);
495
- }
489
+ eventHandler = (evt) => patch(action(s, evt));
496
490
  } else if (typeof newValue === "object") {
497
491
  eventHandler = () => patch(newValue);
498
492
  }
@@ -719,6 +713,132 @@ var MTR = "mtr";
719
713
  var MUNDER = "munder";
720
714
  var MUNDEROVER = "munderover";
721
715
  var SEMANTICS = "semantics";
716
+ // src/merge-class.ts
717
+ function mergeClass(...classes) {
718
+ if (!classes || classes.length === 0)
719
+ return null;
720
+ if (classes.length === 1)
721
+ return classes[0];
722
+ let finalClass = classes[0];
723
+ for (let index = 1;index < classes.length; index++) {
724
+ const a = finalClass, b = classes[index];
725
+ if (!a) {
726
+ finalClass = b;
727
+ } else if (!b) {
728
+ continue;
729
+ } else if (typeof a === "string" && typeof b === "string") {
730
+ const aSplit = a.split(" ");
731
+ const bSplit = b.split(" ");
732
+ const classSet = new Set([...aSplit, ...bSplit]);
733
+ finalClass = Array.from(classSet).join(" ").trim();
734
+ } else if (typeof a === "string" && Array.isArray(b)) {
735
+ const classSet = new Set([...b, ...a.split(" ")]);
736
+ finalClass = Array.from(classSet).join(" ").trim();
737
+ } else if (Array.isArray(a) && typeof b === "string") {
738
+ const classSet = new Set([...a, ...b.split(" ")]);
739
+ finalClass = Array.from(classSet).join(" ").trim();
740
+ } else if (Array.isArray(a) && Array.isArray(b)) {
741
+ const classSet = new Set([...a, ...b]);
742
+ finalClass = Array.from(classSet).join(" ").trim();
743
+ } else if (typeof a === "string" && typeof b === "object") {
744
+ finalClass = { [a]: true, ...b };
745
+ } else if (typeof a === "object" && typeof b === "string") {
746
+ finalClass = { ...a, [b]: true };
747
+ } else if (typeof a === "object" && typeof b === "object") {
748
+ finalClass = { ...a, ...b };
749
+ } else if (typeof a === "object" && Array.isArray(b)) {
750
+ const aa = { ...a };
751
+ for (const item of b) {
752
+ aa[item] = true;
753
+ }
754
+ finalClass = aa;
755
+ } else if (Array.isArray(a) && typeof b === "object") {
756
+ const aa = {};
757
+ for (const item of a) {
758
+ aa[item] = true;
759
+ }
760
+ for (const bKey of Object.keys(b)) {
761
+ aa[bKey] = b[bKey];
762
+ }
763
+ finalClass = aa;
764
+ } else
765
+ throw new Error(`cannot merge classes of ${a} (${typeof a}) and ${b} (${typeof b})`);
766
+ }
767
+ return finalClass;
768
+ }
769
+ // src/state-context.ts
770
+ class KeyStateContext {
771
+ state;
772
+ path;
773
+ keys;
774
+ constructor(state, path) {
775
+ this.state = state;
776
+ this.path = path;
777
+ this.keys = path.split(".");
778
+ }
779
+ get() {
780
+ const keys = this.keys;
781
+ let raw = this.state ? this.state[keys[0]] : undefined;
782
+ for (let i = 1;i < keys.length && !!raw; i++) {
783
+ raw = raw[keys[i]];
784
+ }
785
+ return raw;
786
+ }
787
+ put(value) {
788
+ this.putDeep(value, this.state);
789
+ }
790
+ patch(value) {
791
+ if (Array.isArray(value)) {
792
+ const animation = [];
793
+ for (const v of value) {
794
+ animation.push(this.createPatch(v));
795
+ }
796
+ this.state.patch(animation);
797
+ }
798
+ this.state.patch(this.createPatch(value));
799
+ }
800
+ createPatch(value) {
801
+ const renderPatch = {};
802
+ this.putDeep(value, renderPatch);
803
+ return renderPatch;
804
+ }
805
+ putDeep(value, target) {
806
+ const keys = this.keys;
807
+ if (keys.length > 1) {
808
+ let i = 0;
809
+ let raw = target[keys[i]];
810
+ if (typeof raw !== "object" || raw === null) {
811
+ target[keys[i]] = raw = {};
812
+ }
813
+ for (i = 1;i < keys.length - 1; i++) {
814
+ const p = raw;
815
+ raw = raw[keys[i]];
816
+ if (typeof raw !== "object" || raw === null) {
817
+ p[keys[i]] = raw = {};
818
+ }
819
+ }
820
+ raw[keys[i]] = value;
821
+ } else {
822
+ if (typeof target[keys[0]] === "object" && typeof value === "object")
823
+ Object.assign(target[keys[0]], value);
824
+ else
825
+ target[keys[0]] = value;
826
+ }
827
+ }
828
+ }
829
+
830
+ class DelegateStateContext {
831
+ state;
832
+ get;
833
+ put;
834
+ patch;
835
+ constructor(state, get, put, patch) {
836
+ this.state = state;
837
+ this.get = get;
838
+ this.put = put;
839
+ this.patch = patch;
840
+ }
841
+ }
722
842
  export {
723
843
  vode,
724
844
  tag,
@@ -726,6 +846,7 @@ export {
726
846
  mergeClass,
727
847
  memo,
728
848
  hydrate,
849
+ globals,
729
850
  createState,
730
851
  createPatch,
731
852
  childrenStart,
@@ -840,6 +961,7 @@ export {
840
961
  LI,
841
962
  LEGEND,
842
963
  LABEL,
964
+ KeyStateContext,
843
965
  KBD,
844
966
  INS,
845
967
  INPUT,
@@ -894,6 +1016,7 @@ export {
894
1016
  EMBED,
895
1017
  EM,
896
1018
  ELLIPSE,
1019
+ DelegateStateContext,
897
1020
  DT,
898
1021
  DL,
899
1022
  DIV,
package/index.ts CHANGED
@@ -1,2 +1,6 @@
1
1
  export * from "./src/vode.js";
2
- export * from "./src/vode-tags.js";
2
+
3
+ // utilities
4
+ export * from "./src/vode-tags.js";
5
+ export * from "./src/merge-class.js";
6
+ export * from "./src/state-context.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryupold/vode",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "a minimalist web framework",
5
5
  "author": "Michael Scherbakow (ryupold)",
6
6
  "license": "MIT",
@@ -33,8 +33,8 @@
33
33
  "watch": "tsc -b -w"
34
34
  },
35
35
  "devDependencies": {
36
- "bun": "1.2.23",
37
- "esbuild": "0.25.10",
36
+ "bun": "1.3.1",
37
+ "esbuild": "0.25.11",
38
38
  "typescript": "5.9.3"
39
39
  }
40
40
  }
@@ -0,0 +1,62 @@
1
+ import { ClassProp } from "./vode.js";
2
+
3
+ /** merge `ClassProp`s regardless of structure */
4
+ export function mergeClass(...classes: ClassProp[]): ClassProp {
5
+ if ((!classes || classes.length === 0)) return null;
6
+ if (classes.length === 1) return classes[0];
7
+
8
+ let finalClass: ClassProp = classes[0];
9
+ for (let index = 1; index < classes.length; index++) {
10
+ const a = finalClass, b = classes[index];
11
+ if (!a) {
12
+ finalClass = b;
13
+ }
14
+ else if (!b) {
15
+ continue;
16
+ }
17
+ else if (typeof a === "string" && typeof b === "string") {
18
+ const aSplit = a.split(" ");
19
+ const bSplit = b.split(" ");
20
+ const classSet = new Set([...aSplit, ...bSplit]);
21
+ finalClass = Array.from(classSet).join(" ").trim();
22
+ }
23
+ else if (typeof a === "string" && Array.isArray(b)) {
24
+ const classSet = new Set([...b, ...a.split(" ")]);
25
+ finalClass = Array.from(classSet).join(" ").trim();
26
+ }
27
+ else if (Array.isArray(a) && typeof b === "string") {
28
+ const classSet = new Set([...a, ...b.split(" ")]);
29
+ finalClass = Array.from(classSet).join(" ").trim();
30
+ }
31
+ else if (Array.isArray(a) && Array.isArray(b)) {
32
+ const classSet = new Set([...a, ...b]);
33
+ finalClass = Array.from(classSet).join(" ").trim();
34
+ }
35
+ else if (typeof a === "string" && typeof b === "object") {
36
+ finalClass = { [a]: true, ...b };
37
+ }
38
+ else if (typeof a === "object" && typeof b === "string") {
39
+ finalClass = { ...a, [b]: true };
40
+ }
41
+ else if (typeof a === "object" && typeof b === "object") {
42
+ finalClass = { ...a, ...b };
43
+ } else if (typeof a === "object" && Array.isArray(b)) {
44
+ const aa = { ...a };
45
+ for (const item of b as string[]) {
46
+ (<Record<string, boolean | null | undefined>>aa)[item] = true;
47
+ }
48
+ finalClass = aa;
49
+ } else if (Array.isArray(a) && typeof b === "object") {
50
+ const aa: Record<string, any> = {};
51
+ for (const item of a as string[]) {
52
+ aa[item] = true;
53
+ }
54
+ for (const bKey of Object.keys(b!)) {
55
+ aa[bKey] = (<Record<string, boolean | null | undefined>>b)[bKey];
56
+ }
57
+ finalClass = aa;
58
+ }
59
+ else throw new Error(`cannot merge classes of ${a} (${typeof a}) and ${b} (${typeof b})`);
60
+ }
61
+ return finalClass;
62
+ }