From 1cf2918058b2da627871e7e237c1053448a55f4c Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 7 Feb 2025 15:17:25 -0500 Subject: [PATCH] hmr binding --- app.js | 15 +++--- hmr.js | 120 ++++++++++++++++++++------------------------- index.html | 141 +++++------------------------------------------------ van.d.ts | 9 ++-- 4 files changed, 80 insertions(+), 205 deletions(-) diff --git a/app.js b/app.js index d0dee37..9783997 100644 --- a/app.js +++ b/app.js @@ -1,20 +1,23 @@ const CSS = Gale({ Button:{ padding: "20px", - background: "black", + background: "blue", borderRadius: "20px", color: "white", - fontWeight: "bolder" + fontWeight: "bolder", + ":hover":{ + background: "yellow" + } } -}) +}); -const state = VanX.reactive({key1:"value1", key2:"value2", count:7}, "THING") +const state = vanX.reactive({key1:"value1", key2:"value2", count:7}, "THING") console.log(state); -Van.add +van.add ( document.body, - Van.tags.div + van.tags.div ( { class:CSS("Button"), diff --git a/hmr.js b/hmr.js index 3076c90..6bda29c 100644 --- a/hmr.js +++ b/hmr.js @@ -1,17 +1,17 @@ //@ts-check - -const Gateway = globalThis.Gateway = { +// hmr +const HMR = globalThis.HMR = { Time: 0, /** @type {Record} */ Temp:{}, Tick() { - for(const k in Gateway.Temp) + for(const k in HMR.Temp) { - localStorage.setItem(k, Gateway.Temp[k]); + sessionStorage.setItem(k, HMR.Temp[k]); } - Gateway.Temp = {}; - Gateway.Time = 0; + HMR.Temp = {}; + HMR.Time = 0; }, /** @type {(key:string, value:string)=>void} */ Save(key, value) @@ -26,13 +26,11 @@ const Gateway = globalThis.Gateway = { /** @type {(key:string)=>string|null} */ Load(key) { - const value = localStorage.getItem(key); + const value = sessionStorage.getItem(key); console.log("LOAD", key, value); return value; - } -} + }, -const context = { /** @type {string|undefined} */ _ID: undefined, _index: 0, @@ -42,63 +40,53 @@ const context = { this._index = 0; this._ID = id; }, - CurrentID() + NextID() { return this._ID ? this._ID + "_" + (this._index++) + "_" : ""; + }, + + BindVan() + { + //bind Van + const origninalState = globalThis.van.state; + globalThis.van.state =(value, key="")=> + { + const type = typeof value; + let reader =d=>d; + let writer =d=>d?.toString() || null; + + switch(type) + { + case "boolean" : + reader =(data)=> data === "true"; break; + case "number" : + reader = parseFloat; break; + case "object" : + reader = JSON.parse; + writer = JSON.stringify; + break; + } + + const fullKey = "HMR_" + HMR.NextID() + key; + const stringValue = HMR.Load(fullKey); + const signal = origninalState(/**@type{T}*/(stringValue ? reader(stringValue) : value)); + van.derive(()=>HMR.Save(fullKey, writer(signal.val))); + + return signal; + }; + }, + + BindVanX() + { + //bind VanX + const originalReactive = globalThis.vanX.reactive; + globalThis.vanX.reactive =(obj, id)=> + { + HMR.StartID(id); + const state = originalReactive(obj); + HMR.StartID(); + return state; + } } + } - -/** - * HMR Wrapper for Van.state - * @template T - * @param {T} value - initial value - * @param {string} key - Storage ID - * @returns {Van.State} - */ -export const State =(value, key="")=> -{ - const type = typeof value; - let reader =d=>d; - let writer =d=>d.toString(); - - if(type === "object") - { - reader = JSON.parse; - writer = JSON.stringify; - } - else if(type === "number") - { - reader = parseFloat; - } - else if(type === "boolean") - { - reader =(data)=> data === "true"; - } - /* - switch(type) - { - case "boolean" : - reader =(data)=> data === "true"; break; - case "number" : - reader = parseFloat; break; - case "object" : - reader = JSON.parse; - writer = JSON.stringify; - break; - } - */ - - const fullKey = context.CurrentID() + key - const stringValue = Gateway.Load(fullKey); - const signal = Van.state(/**@type{T}*/(stringValue ? reader(stringValue) : value)); - Van.derive(()=>Gateway.Save(fullKey, writer(signal.val))); - - return signal; -} - -export const Reactive =(obj, id)=> -{ - context.StartID(id); - VanX.reactive(obj); - context.StartID(); -} \ No newline at end of file diff --git a/index.html b/index.html index e8c9b97..e9b9b9b 100644 --- a/index.html +++ b/index.html @@ -3,140 +3,25 @@ Document - -/** - * HMR Wrapper for Van.state - * @template T - * @param {T} value - initial value - * @param {string} key - Storage ID - * @returns {Van.State} - */ -const State =(value, key="")=> -{ - const type = typeof value; - let reader =d=>d; - let writer =d=>d.toString(); + -const Reactive =(obj, id)=> -{ - context.StartID(id); - const state = globalThis.HMRReactive(obj); - context.StartID(); - return state; -} - //bind Van -globalThis.HMRState = globalThis.van.state; -globalThis.van.state =(...args)=>State(...args); - - - - // vanX: - {let e,t,r,{fromEntries:o,entries:l,keys:n,hasOwn:f,getPrototypeOf:a}=Object,{get:i,set:y,deleteProperty:c,ownKeys:s}=Reflect,{state:m,derive:d,add:u}=van,b=1e3,w=Symbol(),A=Symbol(),S=Symbol(),_=Symbol(),g=Symbol(),p=Symbol(),P=e=>(e[A]=1,e),v=e=>e instanceof Object&&!(e instanceof Function)&&!e[p],h=e=>{if(e?.[A]){let t=m();return d(()=>{let r=e();v(t.rawVal)&&v(r)?B(t.rawVal,r):t.val=x(r)}),t}return m(x(e))},F=e=>{let t=Array.isArray(e)?[]:{__proto__:a(e)};for(let[r,o]of l(e))t[r]=h(o);return t[S]=[],t[_]=m(1),t},O={get:(e,t,r)=>t===w?e:f(e,t)?Array.isArray(e)&&"length"===t?(e[_].val,e.length):e[t].val:i(e,t,r),set:(e,o,l,n)=>f(e,o)?Array.isArray(e)&&"length"===o?(l!==e.length&&++e[_].val,e.length=l,1):(e[o].val=x(l),1):o in e?y(e,o,l,n):y(e,o,h(l))&&(++e[_].val,C(e).forEach(E.bind(t,n,o,e[o],r)),1),deleteProperty:(e,t)=>(c(e,t)&&R(e,t),++e[_].val),ownKeys:e=>(e[_].val,s(e))},x=e=>!v(e)||e[w]?e:new Proxy(F(e),O),D=e=>(e[p]=1,e),j=e=>e[w],K=a(m()),N=e=>new Proxy(e,{get:(e,t,r)=>a(e[t]??0)===K?{val:k(e[t].rawVal)}:i(e,t,r)}),k=e=>e?.[w]?new Proxy(N(e[w]),O):e,C=e=>e[S]=e[S].filter(e=>e.t.isConnected),E=(e,t,r,o,{t:l,f:f})=>{let a=Array.isArray(e),i=a?Number(t):t;u(l,()=>l[g][t]=f(r,()=>delete e[t],i)),a&&!o&&i!==e.length-1&&l.insertBefore(l.lastChild,l[g][n(e).find(e=>Number(e)>i)])},R=(e,t)=>{for(let r of C(e)){let e=r.t[g];e[t]?.remove(),delete e[t]}},T=r=>(e??(setTimeout(()=>(e.forEach(C),e=t),b),e=new Set)).add(r),q=(e,t,r)=>{let o={t:e instanceof Function?e():e,f:r},n=t[w];o.t[g]={},n[S].push(o),T(n);for(let[e,r]of l(n))E(t,e,r,1,o);return o.t},z=(e,t)=>{for(let[r,o]of l(t)){let t=e[r];v(t)&&v(o)?z(t,o):e[r]=o}for(let r in e)f(t,r)||delete e[r];let r=n(t),o=Array.isArray(e);if(o||n(e).some((e,t)=>e!==r[t])){let l=e[w];if(o)e.length=t.length;else{++l[_].val;let e={...l};for(let e of r)delete l[e];for(let t of r)l[t]=e[t]}for(let{t:e}of C(l)){let{firstChild:t,[g]:o}=e;for(let l of r)t===o[l]?t=t.nextSibling:e.insertBefore(o[l],t)}}return e},B=(e,n)=>{r=1;try{return z(e,n instanceof Function?Array.isArray(e)?n(e.filter(e=>1)):o(n(l(e))):n)}finally{r=t}},G=e=>Array.isArray(e)?e.filter(e=>1).map(G):v(e)?o(l(e).map(([e,t])=>[e,G(t)])):e;window.vanX={calc:P,reactive:x,noreactive:D,stateFields:j,raw:k,list:q,replace:B,compact:G}} - - //bind VanX - globalThis.HMRReactive = globalThis.vanX.reactive; -globalThis.vanX.reactive =(...args)=>Reactive(...args); - - - // scope casing - globalThis.Van = globalThis.van; - globalThis.VanX = globalThis.vanX; - - - - // gale - {const e=(t,n)=>`${t}{${Object.keys(n).map((t=>{const s=n[t];switch(t[0]){case"@":return e(`@media(max-width:${t.substring(1)})`,s);case":":return e(`&${t}`,s);case".":return e(`${t}`,s);case"^":return e(`&:hover .${t.substring(1)}`,s)}return`${t.replace(/([a-z])([A-Z])/g,"$1-$2")}: ${s};`})).join("\n")}}`;let t=0;globalThis.Gale=n=>{const s=t?"_"+t:"";t++;const r=Object.keys(n).map((t=>e("."+t,n[t]))).join("\n");globalThis.document?.head.insertAdjacentHTML("beforeend",``);const a=(...e)=>{const t=(e,t)=>{const n=t.lastIndexOf(e)+e.length;return n?t.substring(n):t};return e.map((e=>t("^",t(".",e)))).join(s+" ")+s};return a.css=r,a}}; - - // boot - ((t="/")=>{fetch(t+"deno.json").then((t=>t.json())).then((e=>{const n=(t,e)=>{let n=document.createElement("script");n.type=t,n.textContent=e,document.head.appendChild(n)};for(let n in e.imports){const o=e.imports[n];o.startsWith("./")&&(e.imports[n]=t+o.substring(2))}n("importmap",JSON.stringify({imports:e.imports})),n("module",'import "entry";')}))})(); - diff --git a/van.d.ts b/van.d.ts index 16c3cf8..f29e88b 100644 --- a/van.d.ts +++ b/van.d.ts @@ -38,9 +38,8 @@ declare global [K in keyof HTMLElementTagNameMap]: TagFunc } } - - const Van:{ - readonly state: (initVal: T)=> Van.State + const van:{ + readonly state: (initVal: T, HMRKey?:string)=> Van.State readonly derive: (f: () => T) => Van.State readonly add: (dom: Element, ...children: readonly Van.ChildDom[]) => Element readonly tags: Van.Tags & ((namespaceURI: string) => Readonly>>) @@ -57,9 +56,9 @@ declare global T extends (infer V)[] ? (items: V[]) => readonly V[] : (items: [string, T[keyof T]][]) => readonly [string, T[keyof T]][] } - const VanX:{ + const vanX:{ readonly calc: (f: () => R) => R - readonly reactive: (obj: T) => T + readonly reactive: (obj: T, HMRKey?:string) => T readonly noreactive: (obj: T) => T readonly stateFields: (obj: T) => VanX.StateOf readonly raw: (obj: T) => T