1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-24 09:29:37 +01:00
deka-dom-el/dist/esm-with-signals.js

878 lines
26 KiB
JavaScript
Raw Normal View History

// src/signals-common.js
var signals_global = {
isSignal(attributes) {
return false;
2024-05-17 22:13:16 +02:00
},
processReactiveAttribute(obj, key, attr, set) {
return attr;
2024-05-17 22:13:16 +02:00
}
};
function registerReactivity(def, global = true) {
if (global) return Object.assign(signals_global, def);
Object.setPrototypeOf(def, signals_global);
return def;
2024-05-17 22:13:16 +02:00
}
function signals(_this) {
return signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;
2024-05-17 22:13:16 +02:00
}
// src/helpers.js
var hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);
function isUndef(value) {
return typeof value === "undefined";
}
function typeOf(v) {
const t = typeof v;
if (t !== "object") return t;
if (v === null) return "null";
return Object.prototype.toString.call(v);
}
function onAbort(signal2, listener) {
if (!signal2 || !(signal2 instanceof AbortSignal))
return true;
if (signal2.aborted)
return;
signal2.addEventListener("abort", listener);
return function cleanUp() {
signal2.removeEventListener("abort", listener);
};
2024-05-17 22:13:16 +02:00
}
function observedAttributes(instance, observedAttribute2) {
const { observedAttributes: observedAttributes3 = [] } = instance.constructor;
return observedAttributes3.reduce(function(out, name) {
out[kebabToCamel(name)] = observedAttribute2(instance, name);
return out;
2024-05-17 22:13:16 +02:00
}, {});
}
function kebabToCamel(name) {
return name.replace(/-./g, (x) => x[1].toUpperCase());
2024-05-17 22:13:16 +02:00
}
// src/dom-common.js
var enviroment = {
setDeleteAttr,
2024-05-17 22:13:16 +02:00
ssr: "",
D: globalThis.document,
F: globalThis.DocumentFragment,
H: globalThis.HTMLElement,
S: globalThis.SVGElement,
M: globalThis.MutationObserver
};
function setDeleteAttr(obj, prop, val) {
Reflect.set(obj, prop, val);
if (!isUndef(val)) return;
Reflect.deleteProperty(obj, prop);
if (obj instanceof enviroment.H && obj.getAttribute(prop) === "undefined")
return obj.removeAttribute(prop);
if (Reflect.get(obj, prop) === "undefined")
return Reflect.set(obj, prop, "");
}
var keyLTE = "__dde_lifecyclesToEvents";
var evc = "dde:connected";
var evd = "dde:disconnected";
var eva = "dde:attributeChanged";
2024-05-17 22:13:16 +02:00
// src/dom.js
var scopes = [{
2024-05-17 22:13:16 +02:00
get scope() {
return enviroment.D.body;
2024-05-17 22:13:16 +02:00
},
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
prevent: true
}];
var scope = {
2024-05-17 22:13:16 +02:00
get current() {
return scopes[scopes.length - 1];
2024-05-17 22:13:16 +02:00
},
get host() {
return this.current.host;
},
preventDefault() {
const { current } = this;
current.prevent = true;
return current;
2024-05-17 22:13:16 +02:00
},
get state() {
return [...scopes];
2024-05-17 22:13:16 +02:00
},
push(s = {}) {
return scopes.push(Object.assign({}, this.current, { prevent: false }, s));
2024-05-17 22:13:16 +02:00
},
pushRoot() {
return scopes.push(scopes[0]);
2024-05-17 22:13:16 +02:00
},
pop() {
if (scopes.length === 1) return;
return scopes.pop();
2024-05-17 22:13:16 +02:00
}
};
function append(...els) {
this.appendOriginal(...els);
return this;
}
function chainableAppend(el) {
if (el.append === append) return el;
el.appendOriginal = el.append;
el.append = append;
return el;
}
var namespace;
function createElement(tag, attributes, ...addons) {
const s = signals(this);
let scoped = 0;
let el, el_host;
if (Object(attributes) !== attributes || s.isSignal(attributes))
attributes = { textContent: attributes };
switch (true) {
case typeof tag === "function": {
scoped = 1;
scope.push({ scope: tag, host: (...c) => c.length ? (scoped === 1 ? addons.unshift(...c) : c.forEach((c2) => c2(el_host)), void 0) : el_host });
el = tag(attributes || void 0);
const is_fragment = el instanceof enviroment.F;
if (el.nodeName === "#comment") break;
const el_mark = createElement.mark({
2024-05-17 22:13:16 +02:00
type: "component",
name: tag.name,
host: is_fragment ? "this" : "parentElement"
2024-05-17 22:13:16 +02:00
});
el.prepend(el_mark);
if (is_fragment) el_host = el_mark;
2024-05-17 22:13:16 +02:00
break;
}
case tag === "#text":
el = assign.call(this, enviroment.D.createTextNode(""), attributes);
2024-05-17 22:13:16 +02:00
break;
case (tag === "<>" || !tag):
el = assign.call(this, enviroment.D.createDocumentFragment(), attributes);
2024-05-17 22:13:16 +02:00
break;
case Boolean(namespace):
el = assign.call(this, enviroment.D.createElementNS(namespace, tag), attributes);
2024-05-17 22:13:16 +02:00
break;
case !el:
el = assign.call(this, enviroment.D.createElement(tag), attributes);
}
chainableAppend(el);
if (!el_host) el_host = el;
addons.forEach((c) => c(el_host));
if (scoped) scope.pop();
scoped = 2;
return el;
}
function simulateSlots(element, root, mapper) {
if (typeof root !== "object") {
mapper = root;
root = element;
2024-05-17 22:13:16 +02:00
}
const _default = Symbol.for("default");
const slots = Array.from(root.querySelectorAll("slot")).reduce((out, curr) => Reflect.set(out, curr.name || _default, curr) && out, {});
const has_d = hasOwn(slots, _default);
element.append = new Proxy(element.append, {
apply(orig, _, els) {
if (els[0] === root) return orig.apply(element, els);
if (!els.length) return element;
const d = enviroment.D.createDocumentFragment();
for (const el of els) {
if (!el || !el.slot) {
if (has_d) d.append(el);
2024-05-17 22:13:16 +02:00
continue;
}
const name = el.slot;
const slot = slots[name];
elementAttribute(el, "remove", "slot");
if (!slot) continue;
simulateSlotReplace(slot, el, mapper);
Reflect.deleteProperty(slots, name);
2024-05-17 22:13:16 +02:00
}
if (has_d) {
slots[_default].replaceWith(d);
Reflect.deleteProperty(slots, _default);
}
element.append = orig;
return element;
2024-05-17 22:13:16 +02:00
}
});
if (element !== root) {
const els = Array.from(element.childNodes);
els.forEach((el) => el.remove());
element.append(...els);
2024-05-17 22:13:16 +02:00
}
return root;
2024-05-17 22:13:16 +02:00
}
function simulateSlotReplace(slot, element, mapper) {
if (mapper) mapper(slot, element);
2024-05-17 22:13:16 +02:00
try {
slot.replaceWith(assign(element, { className: [element.className, slot.className], dataset: { ...slot.dataset } }));
} catch (_) {
slot.replaceWith(element);
2024-05-17 22:13:16 +02:00
}
}
createElement.mark = function(attrs, is_open = false) {
attrs = Object.entries(attrs).map(([n, v]) => n + `="${v}"`).join(" ");
const end = is_open ? "" : "/";
const out = enviroment.D.createComment(`<dde:mark ${attrs}${enviroment.ssr}${end}>`);
if (is_open) out.end = enviroment.D.createComment("</dde:mark>");
return out;
2024-05-17 22:13:16 +02:00
};
function createElementNS(ns) {
const _this = this;
return function createElementNSCurried(...rest) {
namespace = ns;
const el = createElement.call(_this, ...rest);
namespace = void 0;
return el;
2024-05-17 22:13:16 +02:00
};
}
var assign_context = /* @__PURE__ */ new WeakMap();
var { setDeleteAttr: setDeleteAttr2 } = enviroment;
function assign(element, ...attributes) {
if (!attributes.length) return element;
assign_context.set(element, assignContext(element, this));
for (const [key, value] of Object.entries(Object.assign({}, ...attributes)))
assignAttribute.call(this, element, key, value);
assign_context.delete(element);
return element;
}
function assignAttribute(element, key, value) {
const { setRemoveAttr, s } = assignContext(element, this);
const _this = this;
value = s.processReactiveAttribute(
element,
key,
value,
(key2, value2) => assignAttribute.call(_this, element, key2, value2)
2024-05-17 22:13:16 +02:00
);
const [k] = key;
if ("=" === k) return setRemoveAttr(key.slice(1), value);
if ("." === k) return setDelete(element, key.slice(1), value);
if (/(aria|data)([A-Z])/.test(key)) {
key = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
return setRemoveAttr(key, value);
}
if ("className" === key) key = "class";
switch (key) {
2024-05-17 22:13:16 +02:00
case "xlink:href":
return setRemoveAttr(key, value, "http://www.w3.org/1999/xlink");
2024-05-17 22:13:16 +02:00
case "textContent":
return setDeleteAttr2(element, key, value);
2024-05-17 22:13:16 +02:00
case "style":
if (typeof value !== "object") break;
/* falls through */
2024-05-17 22:13:16 +02:00
case "dataset":
return forEachEntries(s, value, setDelete.bind(null, element[key]));
2024-05-17 22:13:16 +02:00
case "ariaset":
return forEachEntries(s, value, (key2, val) => setRemoveAttr("aria-" + key2, val));
2024-05-17 22:13:16 +02:00
case "classList":
return classListDeclarative.call(_this, element, value);
2024-05-17 22:13:16 +02:00
}
return isPropSetter(element, key) ? setDeleteAttr2(element, key, value) : setRemoveAttr(key, value);
}
function assignContext(element, _this) {
if (assign_context.has(element)) return assign_context.get(element);
const is_svg = element instanceof enviroment.S;
const setRemoveAttr = (is_svg ? setRemoveNS : setRemove).bind(null, element, "Attribute");
const s = signals(_this);
return { setRemoveAttr, s };
}
function classListDeclarative(element, toggle) {
const s = signals(this);
forEachEntries(
s,
toggle,
(class_name, val) => element.classList.toggle(class_name, val === -1 ? void 0 : Boolean(val))
);
return element;
}
function empty(el) {
Array.from(el.children).forEach((el2) => el2.remove());
return el;
}
function elementAttribute(element, op, key, value) {
if (element instanceof enviroment.H)
return element[op + "Attribute"](key, value);
return element[op + "AttributeNS"](null, key, value);
}
function isPropSetter(el, key) {
if (!(key in el)) return false;
const des = getPropDescriptor(el, key);
return !isUndef(des.set);
}
function getPropDescriptor(p, key) {
p = Object.getPrototypeOf(p);
if (!p) return {};
const des = Object.getOwnPropertyDescriptor(p, key);
if (!des) return getPropDescriptor(p, key);
return des;
}
function forEachEntries(s, obj, cb) {
if (typeof obj !== "object" || obj === null) return;
return Object.entries(obj).forEach(function process([key, val]) {
if (!key) return;
val = s.processReactiveAttribute(obj, key, val, cb);
cb(key, val);
});
2024-05-17 22:13:16 +02:00
}
function attrArrToStr(attr) {
return Array.isArray(attr) ? attr.filter(Boolean).join(" ") : attr;
2024-05-17 22:13:16 +02:00
}
function setRemove(obj, prop, key, val) {
return obj[(isUndef(val) ? "remove" : "set") + prop](key, attrArrToStr(val));
2024-05-17 22:13:16 +02:00
}
function setRemoveNS(obj, prop, key, val, ns = null) {
return obj[(isUndef(val) ? "remove" : "set") + prop + "NS"](ns, key, attrArrToStr(val));
2024-05-17 22:13:16 +02:00
}
function setDelete(obj, key, val) {
Reflect.set(obj, key, val);
if (!isUndef(val)) return;
return Reflect.deleteProperty(obj, key);
2024-05-17 22:13:16 +02:00
}
// src/events-observer.js
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
2024-05-17 22:13:16 +02:00
get() {
return () => {
};
}
});
function connectionsChangesObserverConstructor() {
const store = /* @__PURE__ */ new Map();
let is_observing = false;
const observerListener = (stop2) => function(mutations) {
for (const mutation of mutations) {
if (mutation.type !== "childList") continue;
if (observerAdded(mutation.addedNodes, true)) {
stop2();
continue;
2024-05-17 22:13:16 +02:00
}
if (observerRemoved(mutation.removedNodes, true))
stop2();
}
};
const observer = new enviroment.M(observerListener(stop));
2024-05-17 22:13:16 +02:00
return {
observe(element) {
const o = new enviroment.M(observerListener(() => {
2024-05-17 22:13:16 +02:00
}));
o.observe(element, { childList: true, subtree: true });
return () => o.disconnect();
2024-05-17 22:13:16 +02:00
},
onConnected(element, listener) {
start();
const listeners = getElementStore(element);
if (listeners.connected.has(listener)) return;
listeners.connected.add(listener);
listeners.length_c += 1;
2024-05-17 22:13:16 +02:00
},
offConnected(element, listener) {
if (!store.has(element)) return;
const ls = store.get(element);
if (!ls.connected.has(listener)) return;
ls.connected.delete(listener);
ls.length_c -= 1;
cleanWhenOff(element, ls);
2024-05-17 22:13:16 +02:00
},
onDisconnected(element, listener) {
start();
const listeners = getElementStore(element);
if (listeners.disconnected.has(listener)) return;
listeners.disconnected.add(listener);
listeners.length_d += 1;
2024-05-17 22:13:16 +02:00
},
offDisconnected(element, listener) {
if (!store.has(element)) return;
const ls = store.get(element);
if (!ls.disconnected.has(listener)) return;
ls.disconnected.delete(listener);
ls.length_d -= 1;
cleanWhenOff(element, ls);
2024-05-17 22:13:16 +02:00
}
};
function cleanWhenOff(element, ls) {
if (ls.length_c || ls.length_d)
return;
store.delete(element);
stop();
2024-05-17 22:13:16 +02:00
}
function getElementStore(element) {
if (store.has(element)) return store.get(element);
const out = {
2024-05-17 22:13:16 +02:00
connected: /* @__PURE__ */ new WeakSet(),
length_c: 0,
disconnected: /* @__PURE__ */ new WeakSet(),
length_d: 0
};
store.set(element, out);
return out;
2024-05-17 22:13:16 +02:00
}
function start() {
if (is_observing) return;
is_observing = true;
observer.observe(enviroment.D.body, { childList: true, subtree: true });
2024-05-17 22:13:16 +02:00
}
function stop() {
if (!is_observing || store.size) return;
is_observing = false;
observer.disconnect();
2024-05-17 22:13:16 +02:00
}
function requestIdle() {
return new Promise(function(resolve) {
(requestIdleCallback || requestAnimationFrame)(resolve);
2024-05-17 22:13:16 +02:00
});
}
async function collectChildren(element) {
if (store.size > 30)
await requestIdle();
const out = [];
if (!(element instanceof Node)) return out;
for (const el of store.keys()) {
if (el === element || !(el instanceof Node)) continue;
if (element.contains(el))
out.push(el);
}
return out;
2024-05-17 22:13:16 +02:00
}
function observerAdded(addedNodes, is_root) {
let out = false;
for (const element of addedNodes) {
if (is_root) collectChildren(element).then(observerAdded);
if (!store.has(element)) continue;
const ls = store.get(element);
if (!ls.length_c) continue;
element.dispatchEvent(new Event(evc));
ls.connected = /* @__PURE__ */ new WeakSet();
ls.length_c = 0;
if (!ls.length_d) store.delete(element);
out = true;
2024-05-17 22:13:16 +02:00
}
return out;
2024-05-17 22:13:16 +02:00
}
function observerRemoved(removedNodes, is_root) {
let out = false;
for (const element of removedNodes) {
if (is_root) collectChildren(element).then(observerRemoved);
if (!store.has(element)) continue;
const ls = store.get(element);
if (!ls.length_d) continue;
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
out = true;
}
return out;
2024-05-17 22:13:16 +02:00
}
function dispatchRemove(element) {
2024-05-17 22:13:16 +02:00
return () => {
if (element.isConnected) return;
element.dispatchEvent(new Event(evd));
store.delete(element);
2024-05-17 22:13:16 +02:00
};
}
}
// src/customElement.js
function customElementRender(custom_element, target, render, props = observedAttributes2) {
scope.push({
scope: custom_element,
host: (...c) => c.length ? c.forEach((c2) => c2(custom_element)) : custom_element
});
if (typeof props === "function") props = props.call(custom_element, custom_element);
const is_lte = custom_element[keyLTE];
if (!is_lte) lifecyclesToEvents(custom_element);
const out = render.call(custom_element, props);
if (!is_lte) custom_element.dispatchEvent(new Event(evc));
if (target.nodeType === 11 && typeof target.mode === "string")
custom_element.addEventListener(evd, c_ch_o.observe(target), { once: true });
scope.pop();
return target.append(out);
}
function lifecyclesToEvents(class_declaration) {
wrapMethod(class_declaration.prototype, "connectedCallback", function(target, thisArg, detail) {
target.apply(thisArg, detail);
thisArg.dispatchEvent(new Event(evc));
});
wrapMethod(class_declaration.prototype, "disconnectedCallback", function(target, thisArg, detail) {
target.apply(thisArg, detail);
(globalThis.queueMicrotask || setTimeout)(
() => !thisArg.isConnected && thisArg.dispatchEvent(new Event(evd))
2024-05-17 22:13:16 +02:00
);
});
wrapMethod(class_declaration.prototype, "attributeChangedCallback", function(target, thisArg, detail) {
const [attribute, , value] = detail;
thisArg.dispatchEvent(new CustomEvent(eva, {
detail: [attribute, value]
}));
target.apply(thisArg, detail);
});
class_declaration.prototype[keyLTE] = true;
return class_declaration;
2024-05-17 22:13:16 +02:00
}
function wrapMethod(obj, method, apply) {
obj[method] = new Proxy(obj[method] || (() => {
}), { apply });
2024-05-17 22:13:16 +02:00
}
function observedAttributes2(instance) {
return observedAttributes(instance, (i, n) => i.getAttribute(n));
2024-05-17 22:13:16 +02:00
}
// src/events.js
function dispatchEvent(name, options, host) {
if (!options) options = {};
return function dispatch(element, ...d) {
if (host) {
d.unshift(element);
element = typeof host === "function" ? host() : host;
}
const event = d.length ? new CustomEvent(name, Object.assign({ detail: d[0] }, options)) : new Event(name, options);
return element.dispatchEvent(event);
2024-05-17 22:13:16 +02:00
};
}
function on(event, listener, options) {
return function registerElement(element) {
element.addEventListener(event, listener, options);
return element;
2024-05-17 22:13:16 +02:00
};
}
var lifeOptions = (obj) => Object.assign({}, typeof obj === "object" ? obj : null, { once: true });
on.connected = function(listener, options) {
options = lifeOptions(options);
return function registerElement(element) {
element.addEventListener(evc, listener, options);
if (element[keyLTE]) return element;
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
if (c) c_ch_o.onConnected(element, listener);
return element;
2024-05-17 22:13:16 +02:00
};
};
on.disconnected = function(listener, options) {
options = lifeOptions(options);
return function registerElement(element) {
element.addEventListener(evd, listener, options);
if (element[keyLTE]) return element;
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
if (c) c_ch_o.onDisconnected(element, listener);
return element;
2024-05-17 22:13:16 +02:00
};
};
var store_abort = /* @__PURE__ */ new WeakMap();
on.disconnectedAsAbort = function(host) {
if (store_abort.has(host)) return store_abort.get(host);
const a = new AbortController();
store_abort.set(host, a);
host(on.disconnected(() => a.abort()));
return a;
2024-05-17 22:13:16 +02:00
};
var els_attribute_store = /* @__PURE__ */ new WeakSet();
on.attributeChanged = function(listener, options) {
if (typeof options !== "object")
options = {};
return function registerElement(element) {
element.addEventListener(eva, listener, options);
if (element[keyLTE] || els_attribute_store.has(element))
return element;
if (!enviroment.M) return element;
const observer = new enviroment.M(function(mutations) {
for (const { attributeName, target } of mutations)
target.dispatchEvent(
new CustomEvent(eva, { detail: [attributeName, target.getAttribute(attributeName)] })
2024-05-17 22:13:16 +02:00
);
});
const c = onAbort(options.signal, () => observer.disconnect());
if (c) observer.observe(element, { attributes: true });
return element;
2024-05-17 22:13:16 +02:00
};
};
// src/signals-lib.js
var mark = "__dde_signal";
function isSignal(candidate) {
2024-05-17 22:13:16 +02:00
try {
return hasOwn(candidate, mark);
} catch (e) {
return false;
2024-05-17 22:13:16 +02:00
}
}
var stack_watch = [];
var deps = /* @__PURE__ */ new WeakMap();
function signal(value, actions) {
if (typeof value !== "function")
return create(false, value, actions);
if (isSignal(value)) return value;
const out = create(true);
const contextReWatch = function() {
const [origin, ...deps_old] = deps.get(contextReWatch);
deps.set(contextReWatch, /* @__PURE__ */ new Set([origin]));
stack_watch.push(contextReWatch);
write(out, value());
stack_watch.pop();
if (!deps_old.length) return;
const deps_curr = deps.get(contextReWatch);
for (const dep_signal of deps_old) {
if (deps_curr.has(dep_signal)) continue;
removeSignalListener(dep_signal, contextReWatch);
}
2024-05-17 22:13:16 +02:00
};
deps.set(out[mark], contextReWatch);
deps.set(contextReWatch, /* @__PURE__ */ new Set([out]));
contextReWatch();
return out;
}
signal.action = function(s, name, ...a) {
const M = s[mark], { actions } = M;
if (!actions || !(name in actions))
throw new Error(`'${s}' has no action with name '${name}'!`);
actions[name].apply(M, a);
if (M.skip) return delete M.skip;
M.listeners.forEach((l) => l(M.value));
2024-05-17 22:13:16 +02:00
};
signal.on = function on2(s, listener, options = {}) {
const { signal: as } = options;
if (as && as.aborted) return;
if (Array.isArray(s)) return s.forEach((s2) => on2(s2, listener, options));
addSignalListener(s, listener);
if (as) as.addEventListener("abort", () => removeSignalListener(s, listener));
2024-05-17 22:13:16 +02:00
};
signal.symbols = {
//signal: mark,
onclear: Symbol.for("Signal.onclear")
2024-05-17 22:13:16 +02:00
};
signal.clear = function(...signals2) {
for (const s of signals2) {
const M = s[mark];
if (!M) continue;
delete s.toJSON;
M.onclear.forEach((f) => f.call(M));
clearListDeps(s, M);
delete s[mark];
2024-05-17 22:13:16 +02:00
}
function clearListDeps(s, o) {
o.listeners.forEach((l) => {
o.listeners.delete(l);
if (!deps.has(l)) return;
const ls = deps.get(l);
ls.delete(s);
if (ls.size > 1) return;
s.clear(...ls);
deps.delete(l);
2024-05-17 22:13:16 +02:00
});
}
};
var key_reactive = "__dde_reactive";
signal.el = function(s, map) {
const mark_start = createElement.mark({ type: "reactive" }, true);
const mark_end = mark_start.end;
const out = enviroment.D.createDocumentFragment();
out.append(mark_start, mark_end);
const { current } = scope;
let cache = {};
const reRenderReactiveElement = (v) => {
if (!mark_start.parentNode || !mark_end.parentNode)
return removeSignalListener(s, reRenderReactiveElement);
const cache_tmp = cache;
cache = {};
scope.push(current);
let els = map(v, function useCache(key, fun) {
let value;
if (hasOwn(cache_tmp, key)) {
value = cache_tmp[key];
delete cache_tmp[key];
} else
value = fun();
cache[key] = value;
return value;
2024-05-17 22:13:16 +02:00
});
scope.pop();
if (!Array.isArray(els))
els = [els];
const el_start_rm = document.createComment("");
els.push(el_start_rm);
mark_start.after(...els);
let el_r;
while ((el_r = el_start_rm.nextSibling) && el_r !== mark_end)
el_r.remove();
el_start_rm.remove();
if (mark_start.isConnected)
requestCleanUpReactives(current.host());
2024-05-17 22:13:16 +02:00
};
addSignalListener(s, reRenderReactiveElement);
removeSignalsFromElements(s, reRenderReactiveElement, mark_start, map);
reRenderReactiveElement(s());
return out;
2024-05-17 22:13:16 +02:00
};
function requestCleanUpReactives(host) {
if (!host || !host[key_reactive]) return;
(requestIdleCallback || setTimeout)(function() {
host[key_reactive] = host[key_reactive].filter(([s, el]) => el.isConnected ? true : (removeSignalListener(...s), false));
2024-05-17 22:13:16 +02:00
});
}
var observedAttributeActions = {
_set(value) {
this.value = value;
2024-05-17 22:13:16 +02:00
}
};
function observedAttribute(store) {
return function(instance, name) {
const varS = (...args) => !args.length ? read(varS) : instance.setAttribute(name, ...args);
const out = toSignal(varS, instance.getAttribute(name), observedAttributeActions);
store[name] = out;
return out;
2024-05-17 22:13:16 +02:00
};
}
var key_attributes = "__dde_attributes";
signal.observedAttributes = function(element) {
const store = element[key_attributes] = {};
const attrs = observedAttributes(element, observedAttribute(store));
on.attributeChanged(function attributeChangeToSignal({ detail }) {
/*! This maps attributes to signals (`S.observedAttributes`).
2024-05-17 22:13:16 +02:00
* Investigate `__dde_attributes` key of the element.*/
const [name, value] = detail;
const curr = this[key_attributes][name];
if (curr) return signal.action(curr, "_set", value);
})(element);
on.disconnected(function() {
/*! This removes all signals mapped to attributes (`S.observedAttributes`).
2024-05-17 22:13:16 +02:00
* Investigate `__dde_attributes` key of the element.*/
signal.clear(...Object.values(this[key_attributes]));
})(element);
return attrs;
2024-05-17 22:13:16 +02:00
};
var signals_config = {
isSignal,
processReactiveAttribute(element, key, attrs, set) {
if (!isSignal(attrs)) return attrs;
const l = (attr) => {
if (!element.isConnected)
return removeSignalListener(attrs, l);
set(key, attr);
2024-05-17 22:13:16 +02:00
};
addSignalListener(attrs, l);
removeSignalsFromElements(attrs, l, element, key);
return attrs();
2024-05-17 22:13:16 +02:00
}
};
function removeSignalsFromElements(s, listener, ...notes) {
const { current } = scope;
if (current.prevent) return;
current.host(function(element) {
if (!element[key_reactive]) {
element[key_reactive] = [];
on.disconnected(
() => (
/*!
* Clears all Signals listeners added in the current scope/host (`S.el`, `assign`, ?).
* You can investigate the `__dde_reactive` key of the element.
* */
element[key_reactive].forEach(([[s2, listener2]]) => removeSignalListener(s2, listener2, s2[mark] && s2[mark].host && s2[mark].host() === element))
)
)(element);
}
element[key_reactive].push([[s, listener], ...notes]);
2024-05-17 22:13:16 +02:00
});
}
function create(is_readonly, value, actions) {
const varS = is_readonly ? () => read(varS) : (...value2) => value2.length ? write(varS, ...value2) : read(varS);
return toSignal(varS, value, actions, is_readonly);
2024-05-17 22:13:16 +02:00
}
var protoSigal = Object.assign(/* @__PURE__ */ Object.create(null), {
2024-05-17 22:13:16 +02:00
stopPropagation() {
this.skip = true;
2024-05-17 22:13:16 +02:00
}
});
var SignalDefined = class extends Error {
2024-05-17 22:13:16 +02:00
constructor() {
super();
const [curr, ...rest] = this.stack.split("\n");
const curr_file = curr.slice(curr.indexOf("@"), curr.indexOf(".js:") + 4);
this.stack = rest.find((l) => !l.includes(curr_file));
2024-05-17 22:13:16 +02:00
}
};
function toSignal(s, value, actions, readonly = false) {
const onclear = [];
if (typeOf(actions) !== "[object Object]")
actions = {};
const { onclear: ocs } = signal.symbols;
if (actions[ocs]) {
onclear.push(actions[ocs]);
delete actions[ocs];
}
const { host } = scope;
Reflect.defineProperty(s, mark, {
2024-05-17 22:13:16 +02:00
value: {
value,
actions,
onclear,
host,
2024-05-17 22:13:16 +02:00
listeners: /* @__PURE__ */ new Set(),
defined: new SignalDefined().stack,
readonly
2024-05-17 22:13:16 +02:00
},
enumerable: false,
writable: false,
configurable: true
});
s.toJSON = () => s();
s.valueOf = () => s[mark] && s[mark].value;
Object.setPrototypeOf(s[mark], protoSigal);
return s;
}
function currentContext() {
return stack_watch[stack_watch.length - 1];
}
function read(s) {
if (!s[mark]) return;
const { value, listeners } = s[mark];
const context = currentContext();
if (context) listeners.add(context);
if (deps.has(context)) deps.get(context).add(s);
return value;
}
function write(s, value, force) {
if (!s[mark]) return;
const M = s[mark];
if (!force && M.value === value) return;
M.value = value;
M.listeners.forEach((l) => l(value));
return value;
}
function addSignalListener(s, listener) {
if (!s[mark]) return;
return s[mark].listeners.add(listener);
}
function removeSignalListener(s, listener, clear_when_empty) {
const M = s[mark];
if (!M) return;
const out = M.listeners.delete(listener);
if (clear_when_empty && !M.listeners.size) {
signal.clear(s);
if (!deps.has(M)) return out;
const c = deps.get(M);
if (!deps.has(c)) return out;
deps.get(c).forEach((sig) => removeSignalListener(sig, c, true));
2024-05-17 22:13:16 +02:00
}
return out;
2024-05-17 22:13:16 +02:00
}
// signals.js
registerReactivity(signals_config);
2024-05-17 22:13:16 +02:00
export {
signal as S,
assign,
assignAttribute,
chainableAppend,
classListDeclarative,
createElement,
createElementNS,
customElementRender,
lifecyclesToEvents as customElementWithDDE,
dispatchEvent,
createElement as el,
createElementNS as elNS,
elementAttribute,
empty,
isSignal,
lifecyclesToEvents,
observedAttributes2 as observedAttributes,
on,
registerReactivity,
scope,
signal,
simulateSlots
2024-05-17 22:13:16 +02:00
};