This commit is contained in:
Seth Trowbridge 2025-02-03 14:54:44 -05:00
parent f959621812
commit ac9fa7ecea
3 changed files with 104 additions and 14 deletions

4
app.js
View File

@ -15,7 +15,7 @@ const css = Gale({
const Components = { const Components = {
Title() Title()
{ {
const titleString = HMR("title", "default!") const titleString = Van.state("title");
return ()=> div({class:css("Board"), onclick(){ return ()=> div({class:css("Board"), onclick(){
titleString.val = Math.random(); titleString.val = Math.random();
}}, titleString.val); }}, titleString.val);
@ -23,7 +23,7 @@ const Components = {
} }
const {div} = Van.tags; const {div} = Van.tags;
Van.add(document.body, Components.Title()); Van.add(document.querySelector("#app"), Components.Title());
const World = { const World = {

View File

@ -2,6 +2,7 @@
<html> <html>
<head></head> <head></head>
<body> <body>
<h1>Le App</h1>
<div id="app"></div> <div id="app"></div>
<script src="app.js" type="module"></script> <script src="app.js" type="module"></script>
<!--<script src="appx.js" type="module"></script>--> <!--<script src="appx.js" type="module"></script>-->

View File

@ -119,20 +119,109 @@ let handler = ns => ({get: (_, name) => tag.bind(_undefined, ns, name)})
let update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove() let update = (dom, newDom) => newDom ? newDom !== dom && dom.replaceWith(newDom) : dom.remove()
let updateDoms = () => { //let updateDoms = () => {
let iter = 0, derivedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) // let iter = 0, derivedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal)
do { // do {
derivedStates = new Set // derivedStates = new Set
for (let l of new Set(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) // for (let l of new Set(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners))))
derive(l.f, l.s, l._dom), l._dom = _undefined // derive(l.f, l.s, l._dom), l._dom = _undefined
} while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length) // } while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length)
let changedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal) // let changedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal)
changedStates = _undefined // changedStates = _undefined
for (let b of new Set(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) // for (let b of new Set(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings))))
update(b._dom, bind(b.f, b._dom)), b._dom = _undefined // update(b._dom, bind(b.f, b._dom)), b._dom = _undefined
for (let s of changedStatesArray) s._oldVal = s.rawVal // for (let s of changedStatesArray) s._oldVal = s.rawVal
//}
/*********************************************** */
// Map to track state-to-DOM relationships
const stateDomMap = new Map();
function pathHash(/** @type {HTMLElement} */element) {
console.log(element);
const path = [];
let currentElement = element;
while (currentElement && currentElement !== document.body && currentElement.parentNode) {
const siblings = Array.from(currentElement.parentNode.children);
const index = siblings.indexOf(currentElement);
path.unshift(index); // Push the index of the current element at the start of the path
currentElement = currentElement.parentNode;
} }
// Include the body in the path as the final part, with index 0 (since it's the root)
path.unshift(0);
return path.join('-'); // Return the path as a string, e.g., "1-0-0-2"
}
/**
* Logs a relationship between a state and a DOM element.
* @param {any} state - The state object being tracked.
* @param {Element} dom - The DOM element affected by the state.
*/
const trackStateDomRelationship = (state, dom, thing) => {
console.log(state, thing);
const hash = pathHash(dom);
if (!stateDomMap.has(hash)) {
stateDomMap.set(hash, new Set());
}
stateDomMap.get(hash).add(state);
};
// Enhanced updateDoms function
let updateDoms = () => {
let iter = 0;
let derivedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal);
do {
// Clear derivedStates for this iteration
derivedStates = new Set();
// Process listeners for derived states
for (let l of new Set(derivedStatesArray.flatMap(s => s._listeners = keepConnected(s._listeners)))) {
derive(l.f, l.s, l._dom);
// Track which DOM element is being touched by this listener's state
if (l._dom) trackStateDomRelationship(l.s, l._dom);
l._dom = _undefined;
}
} while (++iter < 100 && (derivedStatesArray = [...derivedStates]).length);
// Update bindings for changed states
let changedStatesArray = [...changedStates].filter(s => s.rawVal !== s._oldVal);
changedStates = _undefined;
for (let b of new Set(changedStatesArray.flatMap(s => s._bindings = keepConnected(s._bindings)))) {
// Track which DOM element is being touched by this binding's state
if (b._dom) trackStateDomRelationship(b.f, b._dom);
update(b._dom, bind(b.f, b._dom));
b._dom = _undefined;
}
// Update old values for changed states
for (let s of changedStatesArray) {
s._oldVal = s.rawVal;
}
};
// Debugging helper to log the state-DOM relationships
globalThis.Divulge = () => {
console.log("State-DOM Relationships:");
for (const [state, domSet] of stateDomMap.entries()) {
console.log(state, [...domSet]);
}
};
globalThis.path = pathHash;
/*********************************************** */
export default { export default {
tags: new Proxy(ns => new Proxy(tag, handler(ns)), handler()), tags: new Proxy(ns => new Proxy(tag, handler(ns)), handler()),
hydrate: (dom, f) => update(dom, bind(f, dom)), hydrate: (dom, f) => update(dom, bind(f, dom)),