refactor: modernize frontend with hoover framework components and docs
- Add quick modal, table, service status, and confirmation dialog components - Refactor all pages (certs, dhcp, proxy, etc.) to use new component patterns - Introduce refactor load utility and render guard for consistent UX - Add hoover documentation and update AGENTS.md, architecture, overview
This commit is contained in:
@@ -5,12 +5,12 @@
|
||||
* batched re-render loop integration with reactivity.js.
|
||||
*/
|
||||
|
||||
import { requestUpdate, setCommitFn } from './reactivity.js';
|
||||
import { requestUpdate, setCommitFn } from './reactivity.js?v=6';
|
||||
import {
|
||||
_vnodeDom, createDom, getDom, patchNode,
|
||||
_vnodeDom, createDom, getDom, patchNode, sweepDom,
|
||||
setMountFn, setUnmountFn,
|
||||
} from './vdom.js';
|
||||
import { mountComponent, unmountComponent } from './component.js';
|
||||
} from './vdom.js?v=6';
|
||||
import { mountComponent, unmountComponent } from './component.js?v=6';
|
||||
|
||||
/** Container → previous root vnodes */
|
||||
export const _renderSlots = new Map();
|
||||
@@ -21,6 +21,9 @@ export const _renderFns = new Map();
|
||||
/** Component key → last normalized #comp output (for _vnodeDom preservation) */
|
||||
export const _compExpandedCache = new Map();
|
||||
|
||||
/** Component key → renderer function (survives normalization that expands #comp) */
|
||||
const _compRegistry = new Map();
|
||||
|
||||
/**
|
||||
* Set up lifecycle callback hooks from vdom.js.
|
||||
* Called once during render initialization.
|
||||
@@ -87,7 +90,7 @@ function commit(container) {
|
||||
* and manage component lifecycle based on key changes.
|
||||
*/
|
||||
function normalizeVNodesWithLifecycle(result, prevVnodes) {
|
||||
const oldEntries = prevVnodes ? collectCompEntries(prevVnodes, []) : [];
|
||||
const oldEntries = [..._compRegistry.entries()].map(([key, renderer]) => ({ key, renderer }));
|
||||
const oldKeyMap = new Map(oldEntries.map(e => [e.key, e]));
|
||||
const newEntries = [];
|
||||
|
||||
@@ -104,6 +107,16 @@ function normalizeVNodesWithLifecycle(result, prevVnodes) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync registry with current render (prevVnodes are normalized and lack #comp tags,
|
||||
// so collectCompEntries always returns [] after the first render)
|
||||
const newKeySet = new Set(newEntries.map(e => e.key));
|
||||
for (const [key] of _compRegistry) {
|
||||
if (!newKeySet.has(key)) _compRegistry.delete(key);
|
||||
}
|
||||
for (const entry of newEntries) {
|
||||
_compRegistry.set(entry.key, entry.renderer);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
@@ -199,6 +212,7 @@ function diffContainer(container, prev, vnodes) {
|
||||
if (d?.parentNode) {
|
||||
if (d.nodeType === Node.ELEMENT_NODE) sweepDom(d);
|
||||
d.parentNode.removeChild(d);
|
||||
lastDom = i > 0 ? getDom(prev[i - 1]) : null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -214,15 +228,25 @@ function diffContainer(container, prev, vnodes) {
|
||||
if (oldDom && oldV.tag === newV.tag) {
|
||||
patchNode(oldDom.nodeType === 1 ? oldDom.parentNode : container, oldV, newV, null);
|
||||
lastDom = getDom(newV);
|
||||
} else {
|
||||
if (oldDom?.nodeType === Node.ELEMENT_NODE) sweepDom(oldDom);
|
||||
} else if (oldDom && !oldDom.parentNode) {
|
||||
// oldDom exists in _vnodeDom but detached from the tree
|
||||
if (oldDom.nodeType === Node.ELEMENT_NODE) sweepDom(oldDom);
|
||||
const nd = createDom(newV);
|
||||
_vnodeDom.set(newV, nd);
|
||||
if (oldDom?.parentNode) {
|
||||
oldDom.parentNode.replaceChild(nd, oldDom);
|
||||
} else if (nd.parentNode !== container) {
|
||||
container.insertBefore(nd, lastDom ? lastDom.nextSibling : null);
|
||||
}
|
||||
container.insertBefore(nd, lastDom ? lastDom.nextSibling : null);
|
||||
lastDom = nd;
|
||||
} else if (oldDom && oldV.tag !== newV.tag) {
|
||||
// tag mismatch — replace old DOM with new
|
||||
if (oldDom.nodeType === Node.ELEMENT_NODE) sweepDom(oldDom);
|
||||
const nd = createDom(newV);
|
||||
_vnodeDom.set(newV, nd);
|
||||
oldDom.parentNode.replaceChild(nd, oldDom);
|
||||
lastDom = nd;
|
||||
} else {
|
||||
// oldDom is null — create and insert new DOM
|
||||
const nd = createDom(newV);
|
||||
_vnodeDom.set(newV, nd);
|
||||
container.insertBefore(nd, lastDom ? lastDom.nextSibling : null);
|
||||
lastDom = nd;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user