From 0f2499105ace29a7948d0f0398e35d87ec3b058e Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 7 Feb 2025 15:24:17 -0500 Subject: [PATCH] replace contents --- app.js | 32 +++++++++++++++++++ deno.json | 15 +++++++++ hmr.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 29 +++++++++++++++++ van.d.ts | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 255 insertions(+) create mode 100644 app.js create mode 100644 deno.json create mode 100644 hmr.js create mode 100644 index.html create mode 100644 van.d.ts diff --git a/app.js b/app.js new file mode 100644 index 0000000..9783997 --- /dev/null +++ b/app.js @@ -0,0 +1,32 @@ +const CSS = Gale({ + Button:{ + padding: "20px", + background: "blue", + borderRadius: "20px", + color: "white", + fontWeight: "bolder", + ":hover":{ + background: "yellow" + } + } +}); + +const state = vanX.reactive({key1:"value1", key2:"value2", count:7}, "THING") +console.log(state); + +van.add +( + document.body, + van.tags.div + ( + { + class:CSS("Button"), + onclick() + { + state.count++; + } + } + , ()=>state.count + ) +); + diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..3c0c54e --- /dev/null +++ b/deno.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "checkJs": true, + "lib": [ + "dom", + "dom.iterable", + "dom.asynciterable", + "deno.ns", + "deno.unstable" + ] + }, + "imports": { + "entry": "./app.js" + } +} diff --git a/hmr.js b/hmr.js new file mode 100644 index 0000000..6bda29c --- /dev/null +++ b/hmr.js @@ -0,0 +1,92 @@ +//@ts-check +// hmr +const HMR = globalThis.HMR = { + Time: 0, + /** @type {Record} */ + Temp:{}, + Tick() + { + for(const k in HMR.Temp) + { + sessionStorage.setItem(k, HMR.Temp[k]); + } + HMR.Temp = {}; + HMR.Time = 0; + }, + /** @type {(key:string, value:string)=>void} */ + Save(key, value) + { + this.Temp[key] = value; + if(!this.Time) + { + this.Time = setTimeout(this.Tick, 500); + } + console.log("SAVE", key, value); + }, + /** @type {(key:string)=>string|null} */ + Load(key) + { + const value = sessionStorage.getItem(key); + console.log("LOAD", key, value); + return value; + }, + + /** @type {string|undefined} */ + _ID: undefined, + _index: 0, + /** @type {(id:string|undefined = undefined)=>void} */ + StartID(id) + { + this._index = 0; + this._ID = id; + }, + 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; + } + } + +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..e9b9b9b --- /dev/null +++ b/index.html @@ -0,0 +1,29 @@ + + + + + Document + + + + + + + + + + \ No newline at end of file diff --git a/van.d.ts b/van.d.ts new file mode 100644 index 0000000..f29e88b --- /dev/null +++ b/van.d.ts @@ -0,0 +1,87 @@ +export {} +declare global +{ + namespace Van { + + interface State { + val: T + readonly oldVal: T + readonly rawVal: T + } + + // Defining readonly view of State for covariance. + // Basically we want StateView to implement StateView + type StateView = Readonly> + + type Val = State | T + + type Primitive = string | number | boolean | bigint + + // deno-lint-ignore no-explicit-any + type PropValue = Primitive | ((e: any) => void) | null + + type PropValueOrDerived = PropValue | StateView | (() => PropValue) + + type Props = Record & { class?: PropValueOrDerived; is?: string } + + type PropsWithKnownKeys = Partial<{[K in keyof ElementType]: PropValueOrDerived}> + + type ValidChildDomValue = Primitive | Node | null | undefined + + type BindingFunc = ((dom?: Node) => ValidChildDomValue) | ((dom?: Element) => Element) + + type ChildDom = ValidChildDomValue | StateView | BindingFunc | readonly ChildDom[] + + type TagFunc = (first?: Props & PropsWithKnownKeys | ChildDom, ...rest: readonly ChildDom[]) => Result + + type Tags = Readonly>> & { + [K in keyof HTMLElementTagNameMap]: TagFunc + } + } + 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>>) + readonly hydrate: (dom: T, f: (dom: T) => T | null | undefined) => T + }; + + + namespace VanX + { + type StateOf = { readonly [K in keyof T]: Van.State } + type ValueType = T extends (infer V)[] ? V : T[keyof T] + type KeyType = T extends unknown[] ? number : string + type ReplacementFunc = + T extends (infer V)[] ? (items: V[]) => readonly V[] : + (items: [string, T[keyof T]][]) => readonly [string, T[keyof T]][] + } + const vanX:{ + readonly calc: (f: () => R) => R + readonly reactive: (obj: T, HMRKey?:string) => T + readonly noreactive: (obj: T) => T + readonly stateFields: (obj: T) => VanX.StateOf + readonly raw: (obj: T) => T + readonly list: (container: (() => ElementType) | ElementType, items: T,itemFunc: (v: Van.State>, deleter: () => void, k: VanX.KeyType) => Node) => ElementType + readonly replace: (obj: T, replacement: VanX.ReplacementFunc | T) => T + readonly compact: (obj: T) => T + }; + + namespace Gale { + type KeyQuery = "@"; + type KeyPseudo = ":"; + type KeyChild = "."; + type KeyGroup = "^"; + type UserStyles = Partial & {[key: `${KeyQuery|KeyPseudo|KeyChild|KeyGroup}${string}`]: UserStyles } + type UserSheet = Record + type CollectKeys = {[Key in keyof Obj]: Obj[Key] extends object ? Key | CollectKeys : Key }[keyof Obj] + type FilterKeys = Keys extends `${KeyChild|KeyGroup}${infer Rest}` ? Keys : never + type CrossMultiply = A extends string ? B extends string ? `${A}${B}` : never : never + type CrossMultiplyRecord = keyof Rec | { [K in keyof Rec]: K extends string ? CrossMultiply>> : never }[keyof Rec] + type Tier = (selector:string, obj:UserStyles)=>string; + type CreateSheet = (sheet:UserSheet&T)=> ((...args:CrossMultiplyRecord[])=>string)&{css:string} + } + + const Gale:Gale.CreateSheet + +} \ No newline at end of file