añadimos persist
This commit is contained in:
@@ -1,12 +1,6 @@
|
|||||||
/*
|
|
||||||
* Sigwork v1.1 - [Sig]nal-based Frontend Frame[work]
|
|
||||||
* Fixed: Memory Leaks, Fragment Lifecycle, and List Reconciler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const isFn = (v) => typeof v === 'function';
|
const isFn = (v) => typeof v === 'function';
|
||||||
const isNode = (v) => v instanceof Node;
|
const isNode = (v) => v instanceof Node;
|
||||||
|
|
||||||
// --- Schedule System ---
|
|
||||||
let isScheduled = false;
|
let isScheduled = false;
|
||||||
const queue = new Set();
|
const queue = new Set();
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
@@ -15,12 +9,11 @@ const tick = () => {
|
|||||||
isScheduled = false;
|
isScheduled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Effects System ---
|
|
||||||
let activeEffect = null;
|
let activeEffect = null;
|
||||||
export const effect = (fn, is_scope = false) => {
|
export const effect = (fn, is_scope = false) => {
|
||||||
let cleanup = null;
|
let cleanup = null;
|
||||||
const run = () => {
|
const run = () => {
|
||||||
stop(); // Limpia antes de re-ejecutar
|
stop();
|
||||||
const prev = activeEffect;
|
const prev = activeEffect;
|
||||||
activeEffect = run;
|
activeEffect = run;
|
||||||
try { cleanup = fn(); } finally { activeEffect = prev; }
|
try { cleanup = fn(); } finally { activeEffect = prev; }
|
||||||
@@ -50,10 +43,10 @@ const track = (subs) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Signals Core ---
|
|
||||||
export const signal = (value) => {
|
export const signal = (value) => {
|
||||||
const subs = new Set();
|
const subs = new Set();
|
||||||
return {
|
return {
|
||||||
|
_isSig: true,
|
||||||
get value() { track(subs); return value; },
|
get value() { track(subs); return value; },
|
||||||
set value(newValue) {
|
set value(newValue) {
|
||||||
if (newValue === value) return;
|
if (newValue === value) return;
|
||||||
@@ -102,6 +95,22 @@ export const reactive = (obj) => {
|
|||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const persist = (key, target) => {
|
||||||
|
const saved = localStorage.getItem(key);
|
||||||
|
if (saved !== null) {
|
||||||
|
const data = JSON.parse(saved);
|
||||||
|
if (target._isSig) target.value = data;
|
||||||
|
else Object.assign(target, data);
|
||||||
|
}
|
||||||
|
effect(() => {
|
||||||
|
const val = target._isSig ? target.value : target;
|
||||||
|
localStorage.setItem(key, JSON.stringify(val));
|
||||||
|
});
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const storage = (key, val) => persist(key, signal(val));
|
||||||
|
|
||||||
export const watch = (source, cb) => {
|
export const watch = (source, cb) => {
|
||||||
let first = true, oldValue;
|
let first = true, oldValue;
|
||||||
return effect(() => {
|
return effect(() => {
|
||||||
@@ -112,7 +121,6 @@ export const watch = (source, cb) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Rendering System ---
|
|
||||||
let context = null;
|
let context = null;
|
||||||
export const onMount = (fn) => context?.m.push(fn);
|
export const onMount = (fn) => context?.m.push(fn);
|
||||||
export const onUnmount = (fn) => context?.u.push(fn);
|
export const onUnmount = (fn) => context?.u.push(fn);
|
||||||
@@ -139,7 +147,6 @@ const render = (fn, ...data) => {
|
|||||||
|
|
||||||
export const h = (tag, props = {}, ...children) => {
|
export const h = (tag, props = {}, ...children) => {
|
||||||
children = children.flat(Infinity);
|
children = children.flat(Infinity);
|
||||||
|
|
||||||
if (isFn(tag)) {
|
if (isFn(tag)) {
|
||||||
const prev = context;
|
const prev = context;
|
||||||
context = { m: [], u: [], p: { ...(prev?.p || {}) } };
|
context = { m: [], u: [], p: { ...(prev?.p || {}) } };
|
||||||
@@ -149,27 +156,21 @@ export const h = (tag, props = {}, ...children) => {
|
|||||||
el = tag(props, { children, emit: (evt, ...args) => props[`on${evt[0].toUpperCase()}${evt.slice(1)}`]?.(...args) });
|
el = tag(props, { children, emit: (evt, ...args) => props[`on${evt[0].toUpperCase()}${evt.slice(1)}`]?.(...args) });
|
||||||
return () => ctx.u.forEach(f => f());
|
return () => ctx.u.forEach(f => f());
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
// Normalización para asegurar que el nodo tenga metadatos
|
|
||||||
const out = isNode(el) ? el : document.createTextNode(String(el));
|
const out = isNode(el) ? el : document.createTextNode(String(el));
|
||||||
out.$c = ctx;
|
out.$c = ctx;
|
||||||
out.$s = stop;
|
out.$s = stop;
|
||||||
context = prev;
|
context = prev;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tag) return children;
|
if (!tag) return children;
|
||||||
|
|
||||||
const isSvg = tag === 'svg' || tag === 'path' || tag === 'circle';
|
const isSvg = tag === 'svg' || tag === 'path' || tag === 'circle';
|
||||||
const el = isSvg ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag);
|
const el = isSvg ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag);
|
||||||
|
|
||||||
for (const key in props) {
|
for (const key in props) {
|
||||||
if (key.startsWith('on')) el.addEventListener(key.slice(2).toLowerCase(), props[key]);
|
if (key.startsWith('on')) el.addEventListener(key.slice(2).toLowerCase(), props[key]);
|
||||||
else if (key === "ref") isFn(props[key]) ? props[key](el) : props[key].value = el;
|
else if (key === "ref") isFn(props[key]) ? props[key](el) : props[key].value = el;
|
||||||
else if (isFn(props[key])) effect(() => el[key] = props[key]());
|
else if (isFn(props[key])) effect(() => el[key] = props[key]());
|
||||||
else el[key] = props[key];
|
else el[key] = props[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
children.forEach(child => append(el, child));
|
children.forEach(child => append(el, child));
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
@@ -197,7 +198,6 @@ const append = (parent, child) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helpers & Built-in ---
|
|
||||||
export const If = (cond, renderFn, fallback = null) => {
|
export const If = (cond, renderFn, fallback = null) => {
|
||||||
let cached, current;
|
let cached, current;
|
||||||
return () => {
|
return () => {
|
||||||
@@ -236,7 +236,6 @@ export const Transition = ({ enter: e, idle, leave: l }, { children: [c] }) => {
|
|||||||
if (!isNode(el)) return el;
|
if (!isNode(el)) return el;
|
||||||
const addClass = c => c && el.classList.add(...c.split(' '));
|
const addClass = c => c && el.classList.add(...c.split(' '));
|
||||||
const removeClass = c => c && el.classList.remove(...c.split(' '));
|
const removeClass = c => c && el.classList.remove(...c.split(' '));
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
addClass(e[1]);
|
addClass(e[1]);
|
||||||
|
|||||||
Reference in New Issue
Block a user