diff --git a/bs/build.js b/bs/build.js index 947928c..5b63582 100755 --- a/bs/build.js +++ b/bs/build.js @@ -7,7 +7,7 @@ const css= echo.css` `; $.api("", true) -.option("--minify", "Level of minification [ full, partial (default) ]") +.option("--minify", "Level of minification [ no, full, partial (default) ]") .action(async function main({ minify= "partial" }){ for(const file_root of files){ const file= file_root+".js"; @@ -17,11 +17,11 @@ $.api("", true) "npx esbuild '::file::'", "--platform=neutral", "--bundle", - minify==="full" ? "--minify" : "--minify-syntax --minify-identifiers", + minifyOption(minify), "--legal-comments=inline", "--packages=external", "--outfile='::out::'" - ].join(" "), { file, out }); + ].filter(Boolean).join(" "), { file, out }); if(esbuild_output.code) return $.exit(esbuild_output.code, echo(esbuild_output.stderr)); echoVariant(esbuild_output.stderr.split("\n")[1].trim()+ " (esbuild)"); @@ -57,6 +57,12 @@ $.api("", true) }) .parse(); +/** @param {"no"|"full"|"partial"} level */ +function minifyOption(level= "partial"){ + if("no"===level) return undefined; + if("full"===level) return "--minify"; + return "--minify-syntax --minify-identifiers"; +} function echoVariant(name){ return echo("%c✓ "+name, css.info+css); } diff --git a/dist/dde-with-signals.js b/dist/dde-with-signals.js index 1535b54..798dde3 100644 --- a/dist/dde-with-signals.js +++ b/dist/dde-with-signals.js @@ -61,7 +61,7 @@ function lt(t, e, n) { return Reflect.set(t, e, ""); } } -var C = "__dde_lifecyclesToEvents", _ = "dde:connected", O = "dde:disconnected", M = "dde:attributeChanged"; +var O = "__dde_lifecyclesToEvents", _ = "dde:connected", C = "dde:disconnected", M = "dde:attributeChanged"; // src/dom.js var A = [{ @@ -102,50 +102,50 @@ function ht(t) { return t.append === Y || (t.appendOriginal = t.append, t.append = Y), t; } var $; -function j(t, e, ...n) { +function P(t, e, ...n) { let r = W(this), o = 0, c, i; switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { case typeof t == "function": { - o = 1, m.push({ scope: t, host: (...v) => v.length ? (o === 1 ? n.unshift(...v) : v.forEach((l) => l(i)), void 0) : i }), c = t(e || void 0); + o = 1, m.push({ scope: t, host: (...v) => v.length ? (o === 1 ? n.unshift(...v) : v.forEach((h) => h(i)), void 0) : i }), c = t(e || void 0); let a = c instanceof d.F; - if (c.nodeName === "#comment") - break; - let h = j.mark({ + if (c.nodeName === "#comment") break; + let l = P.mark({ type: "component", name: t.name, host: a ? "this" : "parentElement" }); - c.prepend(h), a && (i = h); + c.prepend(l), a && (i = l); break; } case t === "#text": - c = P.call(this, d.D.createTextNode(""), e); + c = j.call(this, d.D.createTextNode(""), e); break; case (t === "<>" || !t): - c = P.call(this, d.D.createDocumentFragment(), e); + c = j.call(this, d.D.createDocumentFragment(), e); break; case !!$: - c = P.call(this, d.D.createElementNS($, t), e); + c = j.call(this, d.D.createElementNS($, t), e); break; case !c: - c = P.call(this, d.D.createElement(t), e); + c = j.call(this, d.D.createElement(t), e); } return ht(c), i || (i = c), n.forEach((a) => a(i)), o && m.pop(), o = 2, c; } -function Wt(t, e = t, n = void 0) { +function Wt(t, e, n) { + typeof e != "object" && (n = e, e = t); let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((i, a) => Reflect.set(i, a.name || r, a) && i, {}), c = T(o, r); if (t.append = new Proxy(t.append, { - apply(i, a, h) { - if (!h.length) - return t; + apply(i, a, l) { + if (l[0] === e) return i.apply(t, l); + if (!l.length) return t; let v = d.D.createDocumentFragment(); - for (let l of h) { - if (!l || !l.slot) { - c && v.appendChild(l); + for (let h of l) { + if (!h || !h.slot) { + c && v.append(h); continue; } - let x = l.slot, y = o[x]; - vt(l, "remove", "slot"), y && (bt(y, l, n), Reflect.deleteProperty(o, x)); + let x = h.slot, w = o[x]; + vt(h, "remove", "slot"), w && (bt(w, h, n), Reflect.deleteProperty(o, x)); } return c && (o[r].replaceWith(v), Reflect.deleteProperty(o, r)), t.append = i, t; } @@ -158,12 +158,12 @@ function Wt(t, e = t, n = void 0) { function bt(t, e, n) { n && n(t, e); try { - t.replaceWith(P(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); + t.replaceWith(j(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); } catch { t.replaceWith(e); } } -j.mark = function(t, e = !1) { +P.mark = function(t, e = !1) { t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); let n = e ? "" : "/", r = d.D.createComment(``); return e && (r.end = d.D.createComment("")), r; @@ -172,14 +172,13 @@ function qt(t) { let e = this; return function(...r) { $ = t; - let o = j.call(e, ...r); + let o = P.call(e, ...r); return $ = void 0, o; }; } var U = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: tt } = d; -function P(t, ...e) { - if (!e.length) - return t; +function j(t, ...e) { + if (!e.length) return t; U.set(t, rt(t, this)); for (let [n, r] of Object.entries(Object.assign({}, ...e))) nt.call(this, t, n, r); @@ -191,13 +190,11 @@ function nt(t, e, n) { t, e, n, - (a, h) => nt.call(c, t, a, h) + (a, l) => nt.call(c, t, a, l) ); let [i] = e; - if (i === "=") - return r(e.slice(1), n); - if (i === ".") - return et(t, e.slice(1), n); + if (i === "=") return r(e.slice(1), n); + if (i === ".") return et(t, e.slice(1), n); if (/(aria|data)([A-Z])/.test(e)) return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); switch (e === "className" && (e = "class"), e) { @@ -206,20 +203,19 @@ function nt(t, e, n) { case "textContent": return tt(t, e, n); case "style": - if (typeof n != "object") - break; + if (typeof n != "object") break; + /* falls through */ case "dataset": return I(o, n, et.bind(null, t[e])); case "ariaset": - return I(o, n, (a, h) => r("aria-" + a, h)); + return I(o, n, (a, l) => r("aria-" + a, l)); case "classList": return gt.call(c, t, n); } return Et(t, e) ? tt(t, e, n) : r(e, n); } function rt(t, e) { - if (U.has(t)) - return U.get(t); + if (U.has(t)) return U.get(t); let r = (t instanceof d.S ? xt : mt).bind(null, t, "Attribute"), o = W(e); return { setRemoveAttr: r, s: o }; } @@ -238,14 +234,12 @@ function vt(t, e, n, r) { return t instanceof d.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); } function Et(t, e) { - if (!(e in t)) - return !1; + if (!(e in t)) return !1; let n = ot(t, e); return !S(n.set); } function ot(t, e) { - if (t = Object.getPrototypeOf(t), !t) - return {}; + if (t = Object.getPrototypeOf(t), !t) return {}; let n = Object.getOwnPropertyDescriptor(t, e); return n || ot(t, e); } @@ -270,17 +264,17 @@ function et(t, e, n) { } // src/events-observer.js -var D = d.M ? wt() : new Proxy({}, { +var D = d.M ? yt() : new Proxy({}, { get() { return () => { }; } }); -function wt() { +function yt() { let t = /* @__PURE__ */ new Map(), e = !1, n = (s) => function(u) { for (let f of u) if (f.type === "childList") { - if (l(f.addedNodes, !0)) { + if (h(f.addedNodes, !0)) { s(); continue; } @@ -299,8 +293,7 @@ function wt() { f.connected.has(u) || (f.connected.add(u), f.length_c += 1); }, offConnected(s, u) { - if (!t.has(s)) - return; + if (!t.has(s)) return; let f = t.get(s); f.connected.has(u) && (f.connected.delete(u), f.length_c -= 1, o(s, f)); }, @@ -310,8 +303,7 @@ function wt() { f.disconnected.has(u) || (f.disconnected.add(u), f.length_d += 1); }, offDisconnected(s, u) { - if (!t.has(s)) - return; + if (!t.has(s)) return; let f = t.get(s); f.disconnected.has(u) && (f.disconnected.delete(u), f.length_d -= 1, o(s, f)); } @@ -320,8 +312,7 @@ function wt() { u.length_c || u.length_d || (t.delete(s), a()); } function c(s) { - if (t.has(s)) - return t.get(s); + if (t.has(s)) return t.get(s); let u = { connected: /* @__PURE__ */ new WeakSet(), length_c: 0, @@ -336,25 +327,23 @@ function wt() { function a() { !e || t.size || (e = !1, r.disconnect()); } - function h() { + function l() { return new Promise(function(s) { (requestIdleCallback || requestAnimationFrame)(s); }); } async function v(s) { - t.size > 30 && await h(); + t.size > 30 && await l(); let u = []; - if (!(s instanceof Node)) - return u; + if (!(s instanceof Node)) return u; for (let f of t.keys()) f === s || !(f instanceof Node) || s.contains(f) && u.push(f); return u; } - function l(s, u) { + function h(s, u) { let f = !1; for (let b of s) { - if (u && v(b).then(l), !t.has(b)) - continue; + if (u && v(b).then(h), !t.has(b)) continue; let N = t.get(b); N.length_c && (b.dispatchEvent(new Event(_)), N.connected = /* @__PURE__ */ new WeakSet(), N.length_c = 0, N.length_d || t.delete(b), f = !0); } @@ -363,12 +352,12 @@ function wt() { function x(s, u) { let f = !1; for (let b of s) - u && v(b).then(x), !(!t.has(b) || !t.get(b).length_d) && ((globalThis.queueMicrotask || setTimeout)(y(b)), f = !0); + u && v(b).then(x), !(!t.has(b) || !t.get(b).length_d) && ((globalThis.queueMicrotask || setTimeout)(w(b)), f = !0); return f; } - function y(s) { + function w(s) { return () => { - s.isConnected || (s.dispatchEvent(new Event(O)), t.delete(s)); + s.isConnected || (s.dispatchEvent(new Event(C)), t.delete(s)); }; } } @@ -379,24 +368,24 @@ function Zt(t, e, n, r = _t) { scope: t, host: (...i) => i.length ? i.forEach((a) => a(t)) : t }), typeof r == "function" && (r = r.call(t, t)); - let o = t[C]; - o || yt(t); + let o = t[O]; + o || wt(t); let c = n.call(t, r); - return o || t.dispatchEvent(new Event(_)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(O, D.observe(e), { once: !0 }), m.pop(), e.append(c); + return o || t.dispatchEvent(new Event(_)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(C, D.observe(e), { once: !0 }), m.pop(), e.append(c); } -function yt(t) { +function wt(t) { return J(t.prototype, "connectedCallback", function(e, n, r) { e.apply(n, r), n.dispatchEvent(new Event(_)); }), J(t.prototype, "disconnectedCallback", function(e, n, r) { e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( - () => !n.isConnected && n.dispatchEvent(new Event(O)) + () => !n.isConnected && n.dispatchEvent(new Event(C)) ); }), J(t.prototype, "attributeChangedCallback", function(e, n, r) { let [o, , c] = r; n.dispatchEvent(new CustomEvent(M, { detail: [o, c] })), e.apply(n, r); - }), t.prototype[C] = !0, t; + }), t.prototype[O] = !0, t; } function J(t, e, n) { t[e] = new Proxy(t[e] || (() => { @@ -414,38 +403,36 @@ function Qt(t, e, n) { return o.dispatchEvent(i); }; } -function w(t, e, n) { +function y(t, e, n) { return function(o) { return o.addEventListener(t, e, n), o; }; } var it = (t) => Object.assign({}, typeof t == "object" ? t : null, { once: !0 }); -w.connected = function(t, e) { +y.connected = function(t, e) { return e = it(e), function(r) { - return r.addEventListener(_, t, e), r[C] ? r : r.isConnected ? (r.dispatchEvent(new Event(_)), r) : (q(e.signal, () => D.offConnected(r, t)) && D.onConnected(r, t), r); + return r.addEventListener(_, t, e), r[O] ? r : r.isConnected ? (r.dispatchEvent(new Event(_)), r) : (q(e.signal, () => D.offConnected(r, t)) && D.onConnected(r, t), r); }; }; -w.disconnected = function(t, e) { +y.disconnected = function(t, e) { return e = it(e), function(r) { - return r.addEventListener(O, t, e), r[C] || q(e.signal, () => D.offDisconnected(r, t)) && D.onDisconnected(r, t), r; + return r.addEventListener(C, t, e), r[O] || q(e.signal, () => D.offDisconnected(r, t)) && D.onDisconnected(r, t), r; }; }; var Z = /* @__PURE__ */ new WeakMap(); -w.disconnectedAsAbort = function(t) { - if (Z.has(t)) - return Z.get(t); +y.disconnectedAsAbort = function(t) { + if (Z.has(t)) return Z.get(t); let e = new AbortController(); - return Z.set(t, e), t(w.disconnected(() => e.abort())), e; + return Z.set(t, e), t(y.disconnected(() => e.abort())), e; }; var At = /* @__PURE__ */ new WeakSet(); -w.attributeChanged = function(t, e) { +y.attributeChanged = function(t, e) { return typeof e != "object" && (e = {}), function(r) { - if (r.addEventListener(M, t, e), r[C] || At.has(r) || !d.M) - return r; + if (r.addEventListener(M, t, e), r[O] || At.has(r) || !d.M) return r; let o = new d.M(function(i) { - for (let { attributeName: a, target: h } of i) - h.dispatchEvent( - new CustomEvent(M, { detail: [a, h.getAttribute(a)] }) + for (let { attributeName: a, target: l } of i) + l.dispatchEvent( + new CustomEvent(M, { detail: [a, l.getAttribute(a)] }) ); }); return q(e.signal, () => o.disconnect()) && o.observe(r, { attributes: !0 }), r; @@ -465,12 +452,10 @@ var H = [], g = /* @__PURE__ */ new WeakMap(); function E(t, e) { if (typeof t != "function") return st(!1, t, e); - if (z(t)) - return t; + if (z(t)) return t; let n = st(!0), r = function() { let [o, ...c] = g.get(r); - if (g.set(r, /* @__PURE__ */ new Set([o])), H.push(r), dt(n, t()), H.pop(), !c.length) - return; + if (g.set(r, /* @__PURE__ */ new Set([o])), H.push(r), dt(n, t()), H.pop(), !c.length) return; let i = g.get(r); for (let a of c) i.has(a) || L(a, r); @@ -481,15 +466,13 @@ E.action = function(t, e, ...n) { let r = t[p], { actions: o } = r; if (!o || !(e in o)) throw new Error(`'${t}' has no action with name '${e}'!`); - if (o[e].apply(r, n), r.skip) - return delete r.skip; + if (o[e].apply(r, n), r.skip) return delete r.skip; r.listeners.forEach((c) => c(r.value)); }; E.on = function t(e, n, r = {}) { let { signal: o } = r; if (!(o && o.aborted)) { - if (Array.isArray(e)) - return e.forEach((c) => t(c, n, r)); + if (Array.isArray(e)) return e.forEach((c) => t(c, n, r)); Q(e, n), o && o.addEventListener("abort", () => L(e, n)); } }; @@ -504,8 +487,7 @@ E.clear = function(...t) { } function e(n, r) { r.listeners.forEach((o) => { - if (r.listeners.delete(o), !g.has(o)) - return; + if (r.listeners.delete(o), !g.has(o)) return; let c = g.get(o); c.delete(n), !(c.size > 1) && (n.clear(...c), g.delete(o)); }); @@ -513,23 +495,23 @@ E.clear = function(...t) { }; var R = "__dde_reactive"; E.el = function(t, e) { - let n = j.mark({ type: "reactive" }, !0), r = n.end, o = d.D.createDocumentFragment(); + let n = P.mark({ type: "reactive" }, !0), r = n.end, o = d.D.createDocumentFragment(); o.append(n, r); - let { current: c } = m, i = {}, a = (h) => { + let { current: c } = m, i = {}, a = (l) => { if (!n.parentNode || !r.parentNode) return L(t, a); let v = i; i = {}, m.push(c); - let l = e(h, function(u, f) { + let h = e(l, function(u, f) { let b; return T(v, u) ? (b = v[u], delete v[u]) : b = f(), i[u] = b, b; }); - m.pop(), Array.isArray(l) || (l = [l]); + m.pop(), Array.isArray(h) || (h = [h]); let x = document.createComment(""); - l.push(x), n.after(...l); - let y; - for (; (y = x.nextSibling) && y !== r; ) - y.remove(); + h.push(x), n.after(...h); + let w; + for (; (w = x.nextSibling) && w !== r; ) + w.remove(); x.remove(), n.isConnected && St(c.host()); }; return Q(t, a), ft(t, a, n, e), a(t()), o; @@ -539,27 +521,26 @@ function St(t) { t[R] = t[R].filter(([e, n]) => n.isConnected ? !0 : (L(...e), !1)); }); } -var Ct = { +var Ot = { _set(t) { this.value = t; } }; -function Ot(t) { +function Ct(t) { return function(e, n) { - let r = (...c) => c.length ? e.setAttribute(n, ...c) : K(r), o = at(r, e.getAttribute(n), Ct); + let r = (...c) => c.length ? e.setAttribute(n, ...c) : K(r), o = at(r, e.getAttribute(n), Ot); return t[n] = o, o; }; } var G = "__dde_attributes"; E.observedAttributes = function(t) { - let e = t[G] = {}, n = F(t, Ot(e)); - return w.attributeChanged(function({ detail: o }) { + let e = t[G] = {}, n = F(t, Ct(e)); + return y.attributeChanged(function({ detail: o }) { /*! This maps attributes to signals (`S.observedAttributes`). * Investigate `__dde_attributes` key of the element.*/ let [c, i] = o, a = this[G][c]; - if (a) - return E.action(a, "_set", i); - })(t), w.disconnected(function() { + if (a) return E.action(a, "_set", i); + })(t), y.disconnected(function() { /*! This removes all signals mapped to attributes (`S.observedAttributes`). * Investigate `__dde_attributes` key of the element.*/ E.clear(...Object.values(this[G])); @@ -568,8 +549,7 @@ E.observedAttributes = function(t) { var ut = { isSignal: z, processReactiveAttribute(t, e, n, r) { - if (!z(n)) - return n; + if (!z(n)) return n; let o = (c) => { if (!t.isConnected) return L(n, o); @@ -581,7 +561,7 @@ var ut = { function ft(t, e, ...n) { let { current: r } = m; r.prevent || r.host(function(o) { - o[R] || (o[R] = [], w.disconnected( + o[R] || (o[R] = [], y.disconnected( () => ( /*! * Clears all Signals listeners added in the current scope/host (`S.el`, `assign`, …?). @@ -633,14 +613,12 @@ function Rt() { return H[H.length - 1]; } function K(t) { - if (!t[p]) - return; + if (!t[p]) return; let { value: e, listeners: n } = t[p], r = Rt(); return r && n.add(r), g.has(r) && g.get(r).add(t), e; } function dt(t, e, n) { - if (!t[p]) - return; + if (!t[p]) return; let r = t[p]; if (!(!n && r.value === e)) return r.value = e, r.listeners.forEach((o) => o(e)), e; @@ -651,15 +629,12 @@ function Q(t, e) { } function L(t, e, n) { let r = t[p]; - if (!r) - return; + if (!r) return; let o = r.listeners.delete(e); if (n && !r.listeners.size) { - if (E.clear(t), !g.has(r)) - return o; + if (E.clear(t), !g.has(r)) return o; let c = g.get(r); - if (!g.has(c)) - return o; + if (!g.has(c)) return o; g.get(c).forEach((i) => L(i, c, !0)); } return o; @@ -670,23 +645,23 @@ B(ut); globalThis.dde= { S: E, - assign: P, + assign: j, assignAttribute: nt, chainableAppend: ht, classListDeclarative: gt, - createElement: j, + createElement: P, createElementNS: qt, customElementRender: Zt, - customElementWithDDE: yt, + customElementWithDDE: wt, dispatchEvent: Qt, - el: j, + el: P, elNS: qt, elementAttribute: vt, empty: Ft, isSignal: z, - lifecyclesToEvents: yt, + lifecyclesToEvents: wt, observedAttributes: _t, - on: w, + on: y, registerReactivity: B, scope: m, signal: E, diff --git a/dist/dde.js b/dist/dde.js index b9ebc55..9213f89 100644 --- a/dist/dde.js +++ b/dist/dde.js @@ -98,15 +98,14 @@ function Q(t) { return t.append === $ || (t.appendOriginal = t.append, t.append = $), t; } var T; -function k(t, e, ...n) { +function j(t, e, ...n) { let r = L(this), o = 0, c, f; switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { case typeof t == "function": { - o = 1, S.push({ scope: t, host: (...b) => b.length ? (o === 1 ? n.unshift(...b) : b.forEach((l) => l(f)), void 0) : f }), c = t(e || void 0); + o = 1, S.push({ scope: t, host: (...b) => b.length ? (o === 1 ? n.unshift(...b) : b.forEach((h) => h(f)), void 0) : f }), c = t(e || void 0); let d = c instanceof a.F; - if (c.nodeName === "#comment") - break; - let p = k.mark({ + if (c.nodeName === "#comment") break; + let p = j.mark({ type: "component", name: t.name, host: d ? "this" : "parentElement" @@ -128,20 +127,21 @@ function k(t, e, ...n) { } return Q(c), f || (f = c), n.forEach((d) => d(f)), o && S.pop(), o = 2, c; } -function bt(t, e = t, n = void 0) { +function bt(t, e, n) { + typeof e != "object" && (n = e, e = t); let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((f, d) => Reflect.set(f, d.name || r, d) && f, {}), c = q(o, r); if (t.append = new Proxy(t.append, { apply(f, d, p) { - if (!p.length) - return t; + if (p[0] === e) return f.apply(t, p); + if (!p.length) return t; let b = a.D.createDocumentFragment(); - for (let l of p) { - if (!l || !l.slot) { - c && b.appendChild(l); + for (let h of p) { + if (!h || !h.slot) { + c && b.append(h); continue; } - let A = l.slot, _ = o[A]; - tt(l, "remove", "slot"), _ && (X(_, l, n), Reflect.deleteProperty(o, A)); + let A = h.slot, _ = o[A]; + tt(h, "remove", "slot"), _ && (X(_, h, n), Reflect.deleteProperty(o, A)); } return c && (o[r].replaceWith(b), Reflect.deleteProperty(o, r)), t.append = f, t; } @@ -159,7 +159,7 @@ function X(t, e, n) { t.replaceWith(e); } } -k.mark = function(t, e = !1) { +j.mark = function(t, e = !1) { t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); let n = e ? "" : "/", r = a.D.createComment(``); return e && (r.end = a.D.createComment("")), r; @@ -168,14 +168,13 @@ function gt(t) { let e = this; return function(...r) { T = t; - let o = k.call(e, ...r); + let o = j.call(e, ...r); return T = void 0, o; }; } var P = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: U } = a; function O(t, ...e) { - if (!e.length) - return t; + if (!e.length) return t; P.set(t, B(t, this)); for (let [n, r] of Object.entries(Object.assign({}, ...e))) z.call(this, t, n, r); @@ -190,10 +189,8 @@ function z(t, e, n) { (d, p) => z.call(c, t, d, p) ); let [f] = e; - if (f === "=") - return r(e.slice(1), n); - if (f === ".") - return H(t, e.slice(1), n); + if (f === "=") return r(e.slice(1), n); + if (f === ".") return H(t, e.slice(1), n); if (/(aria|data)([A-Z])/.test(e)) return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); switch (e === "className" && (e = "class"), e) { @@ -202,8 +199,8 @@ function z(t, e, n) { case "textContent": return U(t, e, n); case "style": - if (typeof n != "object") - break; + if (typeof n != "object") break; + /* falls through */ case "dataset": return M(o, n, H.bind(null, t[e])); case "ariaset": @@ -214,8 +211,7 @@ function z(t, e, n) { return et(t, e) ? U(t, e, n) : r(e, n); } function B(t, e) { - if (P.has(t)) - return P.get(t); + if (P.has(t)) return P.get(t); let r = (t instanceof a.S ? rt : nt).bind(null, t, "Attribute"), o = L(e); return { setRemoveAttr: r, s: o }; } @@ -234,14 +230,12 @@ function tt(t, e, n, r) { return t instanceof a.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); } function et(t, e) { - if (!(e in t)) - return !1; + if (!(e in t)) return !1; let n = I(t, e); return !E(n.set); } function I(t, e) { - if (t = Object.getPrototypeOf(t), !t) - return {}; + if (t = Object.getPrototypeOf(t), !t) return {}; let n = Object.getOwnPropertyDescriptor(t, e); return n || I(t, e); } @@ -276,7 +270,7 @@ function ot() { let t = /* @__PURE__ */ new Map(), e = !1, n = (i) => function(u) { for (let s of u) if (s.type === "childList") { - if (l(s.addedNodes, !0)) { + if (h(s.addedNodes, !0)) { i(); continue; } @@ -295,8 +289,7 @@ function ot() { s.connected.has(u) || (s.connected.add(u), s.length_c += 1); }, offConnected(i, u) { - if (!t.has(i)) - return; + if (!t.has(i)) return; let s = t.get(i); s.connected.has(u) && (s.connected.delete(u), s.length_c -= 1, o(i, s)); }, @@ -306,8 +299,7 @@ function ot() { s.disconnected.has(u) || (s.disconnected.add(u), s.length_d += 1); }, offDisconnected(i, u) { - if (!t.has(i)) - return; + if (!t.has(i)) return; let s = t.get(i); s.disconnected.has(u) && (s.disconnected.delete(u), s.length_d -= 1, o(i, s)); } @@ -316,8 +308,7 @@ function ot() { u.length_c || u.length_d || (t.delete(i), d()); } function c(i) { - if (t.has(i)) - return t.get(i); + if (t.has(i)) return t.get(i); let u = { connected: /* @__PURE__ */ new WeakSet(), length_c: 0, @@ -340,26 +331,24 @@ function ot() { async function b(i) { t.size > 30 && await p(); let u = []; - if (!(i instanceof Node)) - return u; + if (!(i instanceof Node)) return u; for (let s of t.keys()) s === i || !(s instanceof Node) || i.contains(s) && u.push(s); return u; } - function l(i, u) { + function h(i, u) { let s = !1; - for (let h of i) { - if (u && b(h).then(l), !t.has(h)) - continue; - let m = t.get(h); - m.length_c && (h.dispatchEvent(new Event(g)), m.connected = /* @__PURE__ */ new WeakSet(), m.length_c = 0, m.length_d || t.delete(h), s = !0); + for (let l of i) { + if (u && b(l).then(h), !t.has(l)) continue; + let m = t.get(l); + m.length_c && (l.dispatchEvent(new Event(g)), m.connected = /* @__PURE__ */ new WeakSet(), m.length_c = 0, m.length_d || t.delete(l), s = !0); } return s; } function A(i, u) { let s = !1; - for (let h of i) - u && b(h).then(A), !(!t.has(h) || !t.get(h).length_d) && ((globalThis.queueMicrotask || setTimeout)(_(h)), s = !0); + for (let l of i) + u && b(l).then(A), !(!t.has(l) || !t.get(l).length_d) && ((globalThis.queueMicrotask || setTimeout)(_(l)), s = !0); return s; } function _(i) { @@ -381,20 +370,20 @@ function Dt(t, e, n, r = it) { return o || t.dispatchEvent(new Event(g)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(y, w.observe(e), { once: !0 }), S.pop(), e.append(c); } function ct(t) { - return W(t.prototype, "connectedCallback", function(e, n, r) { + return k(t.prototype, "connectedCallback", function(e, n, r) { e.apply(n, r), n.dispatchEvent(new Event(g)); - }), W(t.prototype, "disconnectedCallback", function(e, n, r) { + }), k(t.prototype, "disconnectedCallback", function(e, n, r) { e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( () => !n.isConnected && n.dispatchEvent(new Event(y)) ); - }), W(t.prototype, "attributeChangedCallback", function(e, n, r) { + }), k(t.prototype, "attributeChangedCallback", function(e, n, r) { let [o, , c] = r; n.dispatchEvent(new CustomEvent(D, { detail: [o, c] })), e.apply(n, r); }), t.prototype[x] = !0, t; } -function W(t, e, n) { +function k(t, e, n) { t[e] = new Proxy(t[e] || (() => { }), { apply: n }); } @@ -426,18 +415,16 @@ R.disconnected = function(t, e) { return r.addEventListener(y, t, e), r[x] || N(e.signal, () => w.offDisconnected(r, t)) && w.onDisconnected(r, t), r; }; }; -var j = /* @__PURE__ */ new WeakMap(); +var W = /* @__PURE__ */ new WeakMap(); R.disconnectedAsAbort = function(t) { - if (j.has(t)) - return j.get(t); + if (W.has(t)) return W.get(t); let e = new AbortController(); - return j.set(t, e), t(R.disconnected(() => e.abort())), e; + return W.set(t, e), t(R.disconnected(() => e.abort())), e; }; var st = /* @__PURE__ */ new WeakSet(); R.attributeChanged = function(t, e) { return typeof e != "object" && (e = {}), function(r) { - if (r.addEventListener(D, t, e), r[x] || st.has(r) || !a.M) - return r; + if (r.addEventListener(D, t, e), r[x] || st.has(r) || !a.M) return r; let o = new a.M(function(f) { for (let { attributeName: d, target: p } of f) p.dispatchEvent( @@ -453,12 +440,12 @@ globalThis.dde= { assignAttribute: z, chainableAppend: Q, classListDeclarative: Y, - createElement: k, + createElement: j, createElementNS: gt, customElementRender: Dt, customElementWithDDE: ct, dispatchEvent: _t, - el: k, + el: j, elNS: gt, elementAttribute: tt, empty: vt, diff --git a/dist/esm-with-signals.d.ts b/dist/esm-with-signals.d.ts index ec464df..18a5868 100644 --- a/dist/esm-with-signals.d.ts +++ b/dist/esm-with-signals.d.ts @@ -47,7 +47,7 @@ type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagName type textContent= string | ddeSignal; export function el< TAG extends keyof ExtendedHTMLElementTagNameMap, - EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement) + EL extends ExtendedHTMLElementTagNameMap[TAG] >( tag_name: TAG, attrs?: ElementAttributes | textContent, @@ -58,7 +58,7 @@ export function el( ): ddeDocumentFragment export function el( tag_name: string, - attrs?: ElementAttributes, + attrs?: ElementAttributes | textContent, ...addons: ddeElementAddon[] ): ddeHTMLElement @@ -101,7 +101,18 @@ export function elNS( export { elNS as createElementNS } export function chainableAppend(el: EL): EL; -export function simulateSlots(el: EL): EL +/** + * Mapper function (optional). Pass for coppying attributes, this is NOT implemented by {@link simulateSlots} itself! + * */ +type simulateSlotsMapper= (body: HTMLSlotElement, el: HTMLElement)=> void; +/** Simulate slots for ddeComponents */ +export function simulateSlots(root: EL, mapper?: simulateSlotsMapper): EL +/** + * Simulate slots in Custom Elements without using `shadowRoot`. + * @param el Custom Element root element + * @param body Body of the custom element + * */ +export function simulateSlots(el: HTMLElement, body: EL, mapper?: simulateSlotsMapper): EL export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any)=> void; @@ -177,12 +188,12 @@ export const scope: { export function customElementRender< EL extends HTMLElement, - P extends any = Record + P extends any = Record> >( custom_element: EL, target: ShadowRoot | EL, render: (props: P)=> SupportedElement | DocumentFragment, - props?: P | ((...args: any[])=> P) + props?: P | ((el: EL)=> P) ): EL export function customElementWithDDE HTMLElement)>(custom_element: EL): EL export function lifecyclesToEvents HTMLElement)>(custom_element: EL): EL @@ -523,7 +534,7 @@ interface signal{ * */ el(signal: Signal, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment; - observedAttributes(custom_element: HTMLElement): Record>; + observedAttributes(custom_element: HTMLElement): Record>; } export const signal: signal; export const S: signal; diff --git a/dist/esm-with-signals.js b/dist/esm-with-signals.js index e441a79..f718eb8 100644 --- a/dist/esm-with-signals.js +++ b/dist/esm-with-signals.js @@ -59,7 +59,7 @@ function lt(t, e, n) { return Reflect.set(t, e, ""); } } -var C = "__dde_lifecyclesToEvents", _ = "dde:connected", O = "dde:disconnected", M = "dde:attributeChanged"; +var O = "__dde_lifecyclesToEvents", _ = "dde:connected", C = "dde:disconnected", M = "dde:attributeChanged"; // src/dom.js var A = [{ @@ -100,50 +100,50 @@ function ht(t) { return t.append === Y || (t.appendOriginal = t.append, t.append = Y), t; } var $; -function j(t, e, ...n) { +function P(t, e, ...n) { let r = W(this), o = 0, c, i; switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { case typeof t == "function": { - o = 1, m.push({ scope: t, host: (...v) => v.length ? (o === 1 ? n.unshift(...v) : v.forEach((l) => l(i)), void 0) : i }), c = t(e || void 0); + o = 1, m.push({ scope: t, host: (...v) => v.length ? (o === 1 ? n.unshift(...v) : v.forEach((h) => h(i)), void 0) : i }), c = t(e || void 0); let a = c instanceof d.F; - if (c.nodeName === "#comment") - break; - let h = j.mark({ + if (c.nodeName === "#comment") break; + let l = P.mark({ type: "component", name: t.name, host: a ? "this" : "parentElement" }); - c.prepend(h), a && (i = h); + c.prepend(l), a && (i = l); break; } case t === "#text": - c = P.call(this, d.D.createTextNode(""), e); + c = j.call(this, d.D.createTextNode(""), e); break; case (t === "<>" || !t): - c = P.call(this, d.D.createDocumentFragment(), e); + c = j.call(this, d.D.createDocumentFragment(), e); break; case !!$: - c = P.call(this, d.D.createElementNS($, t), e); + c = j.call(this, d.D.createElementNS($, t), e); break; case !c: - c = P.call(this, d.D.createElement(t), e); + c = j.call(this, d.D.createElement(t), e); } return ht(c), i || (i = c), n.forEach((a) => a(i)), o && m.pop(), o = 2, c; } -function Wt(t, e = t, n = void 0) { +function Wt(t, e, n) { + typeof e != "object" && (n = e, e = t); let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((i, a) => Reflect.set(i, a.name || r, a) && i, {}), c = T(o, r); if (t.append = new Proxy(t.append, { - apply(i, a, h) { - if (!h.length) - return t; + apply(i, a, l) { + if (l[0] === e) return i.apply(t, l); + if (!l.length) return t; let v = d.D.createDocumentFragment(); - for (let l of h) { - if (!l || !l.slot) { - c && v.appendChild(l); + for (let h of l) { + if (!h || !h.slot) { + c && v.append(h); continue; } - let x = l.slot, y = o[x]; - vt(l, "remove", "slot"), y && (bt(y, l, n), Reflect.deleteProperty(o, x)); + let x = h.slot, w = o[x]; + vt(h, "remove", "slot"), w && (bt(w, h, n), Reflect.deleteProperty(o, x)); } return c && (o[r].replaceWith(v), Reflect.deleteProperty(o, r)), t.append = i, t; } @@ -156,12 +156,12 @@ function Wt(t, e = t, n = void 0) { function bt(t, e, n) { n && n(t, e); try { - t.replaceWith(P(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); + t.replaceWith(j(e, { className: [e.className, t.className], dataset: { ...t.dataset } })); } catch { t.replaceWith(e); } } -j.mark = function(t, e = !1) { +P.mark = function(t, e = !1) { t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); let n = e ? "" : "/", r = d.D.createComment(``); return e && (r.end = d.D.createComment("")), r; @@ -170,14 +170,13 @@ function qt(t) { let e = this; return function(...r) { $ = t; - let o = j.call(e, ...r); + let o = P.call(e, ...r); return $ = void 0, o; }; } var U = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: tt } = d; -function P(t, ...e) { - if (!e.length) - return t; +function j(t, ...e) { + if (!e.length) return t; U.set(t, rt(t, this)); for (let [n, r] of Object.entries(Object.assign({}, ...e))) nt.call(this, t, n, r); @@ -189,13 +188,11 @@ function nt(t, e, n) { t, e, n, - (a, h) => nt.call(c, t, a, h) + (a, l) => nt.call(c, t, a, l) ); let [i] = e; - if (i === "=") - return r(e.slice(1), n); - if (i === ".") - return et(t, e.slice(1), n); + if (i === "=") return r(e.slice(1), n); + if (i === ".") return et(t, e.slice(1), n); if (/(aria|data)([A-Z])/.test(e)) return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); switch (e === "className" && (e = "class"), e) { @@ -204,20 +201,19 @@ function nt(t, e, n) { case "textContent": return tt(t, e, n); case "style": - if (typeof n != "object") - break; + if (typeof n != "object") break; + /* falls through */ case "dataset": return I(o, n, et.bind(null, t[e])); case "ariaset": - return I(o, n, (a, h) => r("aria-" + a, h)); + return I(o, n, (a, l) => r("aria-" + a, l)); case "classList": return gt.call(c, t, n); } return Et(t, e) ? tt(t, e, n) : r(e, n); } function rt(t, e) { - if (U.has(t)) - return U.get(t); + if (U.has(t)) return U.get(t); let r = (t instanceof d.S ? xt : mt).bind(null, t, "Attribute"), o = W(e); return { setRemoveAttr: r, s: o }; } @@ -236,14 +232,12 @@ function vt(t, e, n, r) { return t instanceof d.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); } function Et(t, e) { - if (!(e in t)) - return !1; + if (!(e in t)) return !1; let n = ot(t, e); return !S(n.set); } function ot(t, e) { - if (t = Object.getPrototypeOf(t), !t) - return {}; + if (t = Object.getPrototypeOf(t), !t) return {}; let n = Object.getOwnPropertyDescriptor(t, e); return n || ot(t, e); } @@ -268,17 +262,17 @@ function et(t, e, n) { } // src/events-observer.js -var D = d.M ? wt() : new Proxy({}, { +var D = d.M ? yt() : new Proxy({}, { get() { return () => { }; } }); -function wt() { +function yt() { let t = /* @__PURE__ */ new Map(), e = !1, n = (s) => function(u) { for (let f of u) if (f.type === "childList") { - if (l(f.addedNodes, !0)) { + if (h(f.addedNodes, !0)) { s(); continue; } @@ -297,8 +291,7 @@ function wt() { f.connected.has(u) || (f.connected.add(u), f.length_c += 1); }, offConnected(s, u) { - if (!t.has(s)) - return; + if (!t.has(s)) return; let f = t.get(s); f.connected.has(u) && (f.connected.delete(u), f.length_c -= 1, o(s, f)); }, @@ -308,8 +301,7 @@ function wt() { f.disconnected.has(u) || (f.disconnected.add(u), f.length_d += 1); }, offDisconnected(s, u) { - if (!t.has(s)) - return; + if (!t.has(s)) return; let f = t.get(s); f.disconnected.has(u) && (f.disconnected.delete(u), f.length_d -= 1, o(s, f)); } @@ -318,8 +310,7 @@ function wt() { u.length_c || u.length_d || (t.delete(s), a()); } function c(s) { - if (t.has(s)) - return t.get(s); + if (t.has(s)) return t.get(s); let u = { connected: /* @__PURE__ */ new WeakSet(), length_c: 0, @@ -334,25 +325,23 @@ function wt() { function a() { !e || t.size || (e = !1, r.disconnect()); } - function h() { + function l() { return new Promise(function(s) { (requestIdleCallback || requestAnimationFrame)(s); }); } async function v(s) { - t.size > 30 && await h(); + t.size > 30 && await l(); let u = []; - if (!(s instanceof Node)) - return u; + if (!(s instanceof Node)) return u; for (let f of t.keys()) f === s || !(f instanceof Node) || s.contains(f) && u.push(f); return u; } - function l(s, u) { + function h(s, u) { let f = !1; for (let b of s) { - if (u && v(b).then(l), !t.has(b)) - continue; + if (u && v(b).then(h), !t.has(b)) continue; let N = t.get(b); N.length_c && (b.dispatchEvent(new Event(_)), N.connected = /* @__PURE__ */ new WeakSet(), N.length_c = 0, N.length_d || t.delete(b), f = !0); } @@ -361,12 +350,12 @@ function wt() { function x(s, u) { let f = !1; for (let b of s) - u && v(b).then(x), !(!t.has(b) || !t.get(b).length_d) && ((globalThis.queueMicrotask || setTimeout)(y(b)), f = !0); + u && v(b).then(x), !(!t.has(b) || !t.get(b).length_d) && ((globalThis.queueMicrotask || setTimeout)(w(b)), f = !0); return f; } - function y(s) { + function w(s) { return () => { - s.isConnected || (s.dispatchEvent(new Event(O)), t.delete(s)); + s.isConnected || (s.dispatchEvent(new Event(C)), t.delete(s)); }; } } @@ -377,24 +366,24 @@ function Zt(t, e, n, r = _t) { scope: t, host: (...i) => i.length ? i.forEach((a) => a(t)) : t }), typeof r == "function" && (r = r.call(t, t)); - let o = t[C]; - o || yt(t); + let o = t[O]; + o || wt(t); let c = n.call(t, r); - return o || t.dispatchEvent(new Event(_)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(O, D.observe(e), { once: !0 }), m.pop(), e.append(c); + return o || t.dispatchEvent(new Event(_)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(C, D.observe(e), { once: !0 }), m.pop(), e.append(c); } -function yt(t) { +function wt(t) { return J(t.prototype, "connectedCallback", function(e, n, r) { e.apply(n, r), n.dispatchEvent(new Event(_)); }), J(t.prototype, "disconnectedCallback", function(e, n, r) { e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( - () => !n.isConnected && n.dispatchEvent(new Event(O)) + () => !n.isConnected && n.dispatchEvent(new Event(C)) ); }), J(t.prototype, "attributeChangedCallback", function(e, n, r) { let [o, , c] = r; n.dispatchEvent(new CustomEvent(M, { detail: [o, c] })), e.apply(n, r); - }), t.prototype[C] = !0, t; + }), t.prototype[O] = !0, t; } function J(t, e, n) { t[e] = new Proxy(t[e] || (() => { @@ -412,38 +401,36 @@ function Qt(t, e, n) { return o.dispatchEvent(i); }; } -function w(t, e, n) { +function y(t, e, n) { return function(o) { return o.addEventListener(t, e, n), o; }; } var it = (t) => Object.assign({}, typeof t == "object" ? t : null, { once: !0 }); -w.connected = function(t, e) { +y.connected = function(t, e) { return e = it(e), function(r) { - return r.addEventListener(_, t, e), r[C] ? r : r.isConnected ? (r.dispatchEvent(new Event(_)), r) : (q(e.signal, () => D.offConnected(r, t)) && D.onConnected(r, t), r); + return r.addEventListener(_, t, e), r[O] ? r : r.isConnected ? (r.dispatchEvent(new Event(_)), r) : (q(e.signal, () => D.offConnected(r, t)) && D.onConnected(r, t), r); }; }; -w.disconnected = function(t, e) { +y.disconnected = function(t, e) { return e = it(e), function(r) { - return r.addEventListener(O, t, e), r[C] || q(e.signal, () => D.offDisconnected(r, t)) && D.onDisconnected(r, t), r; + return r.addEventListener(C, t, e), r[O] || q(e.signal, () => D.offDisconnected(r, t)) && D.onDisconnected(r, t), r; }; }; var Z = /* @__PURE__ */ new WeakMap(); -w.disconnectedAsAbort = function(t) { - if (Z.has(t)) - return Z.get(t); +y.disconnectedAsAbort = function(t) { + if (Z.has(t)) return Z.get(t); let e = new AbortController(); - return Z.set(t, e), t(w.disconnected(() => e.abort())), e; + return Z.set(t, e), t(y.disconnected(() => e.abort())), e; }; var At = /* @__PURE__ */ new WeakSet(); -w.attributeChanged = function(t, e) { +y.attributeChanged = function(t, e) { return typeof e != "object" && (e = {}), function(r) { - if (r.addEventListener(M, t, e), r[C] || At.has(r) || !d.M) - return r; + if (r.addEventListener(M, t, e), r[O] || At.has(r) || !d.M) return r; let o = new d.M(function(i) { - for (let { attributeName: a, target: h } of i) - h.dispatchEvent( - new CustomEvent(M, { detail: [a, h.getAttribute(a)] }) + for (let { attributeName: a, target: l } of i) + l.dispatchEvent( + new CustomEvent(M, { detail: [a, l.getAttribute(a)] }) ); }); return q(e.signal, () => o.disconnect()) && o.observe(r, { attributes: !0 }), r; @@ -463,12 +450,10 @@ var H = [], g = /* @__PURE__ */ new WeakMap(); function E(t, e) { if (typeof t != "function") return st(!1, t, e); - if (z(t)) - return t; + if (z(t)) return t; let n = st(!0), r = function() { let [o, ...c] = g.get(r); - if (g.set(r, /* @__PURE__ */ new Set([o])), H.push(r), dt(n, t()), H.pop(), !c.length) - return; + if (g.set(r, /* @__PURE__ */ new Set([o])), H.push(r), dt(n, t()), H.pop(), !c.length) return; let i = g.get(r); for (let a of c) i.has(a) || L(a, r); @@ -479,15 +464,13 @@ E.action = function(t, e, ...n) { let r = t[p], { actions: o } = r; if (!o || !(e in o)) throw new Error(`'${t}' has no action with name '${e}'!`); - if (o[e].apply(r, n), r.skip) - return delete r.skip; + if (o[e].apply(r, n), r.skip) return delete r.skip; r.listeners.forEach((c) => c(r.value)); }; E.on = function t(e, n, r = {}) { let { signal: o } = r; if (!(o && o.aborted)) { - if (Array.isArray(e)) - return e.forEach((c) => t(c, n, r)); + if (Array.isArray(e)) return e.forEach((c) => t(c, n, r)); Q(e, n), o && o.addEventListener("abort", () => L(e, n)); } }; @@ -502,8 +485,7 @@ E.clear = function(...t) { } function e(n, r) { r.listeners.forEach((o) => { - if (r.listeners.delete(o), !g.has(o)) - return; + if (r.listeners.delete(o), !g.has(o)) return; let c = g.get(o); c.delete(n), !(c.size > 1) && (n.clear(...c), g.delete(o)); }); @@ -511,23 +493,23 @@ E.clear = function(...t) { }; var R = "__dde_reactive"; E.el = function(t, e) { - let n = j.mark({ type: "reactive" }, !0), r = n.end, o = d.D.createDocumentFragment(); + let n = P.mark({ type: "reactive" }, !0), r = n.end, o = d.D.createDocumentFragment(); o.append(n, r); - let { current: c } = m, i = {}, a = (h) => { + let { current: c } = m, i = {}, a = (l) => { if (!n.parentNode || !r.parentNode) return L(t, a); let v = i; i = {}, m.push(c); - let l = e(h, function(u, f) { + let h = e(l, function(u, f) { let b; return T(v, u) ? (b = v[u], delete v[u]) : b = f(), i[u] = b, b; }); - m.pop(), Array.isArray(l) || (l = [l]); + m.pop(), Array.isArray(h) || (h = [h]); let x = document.createComment(""); - l.push(x), n.after(...l); - let y; - for (; (y = x.nextSibling) && y !== r; ) - y.remove(); + h.push(x), n.after(...h); + let w; + for (; (w = x.nextSibling) && w !== r; ) + w.remove(); x.remove(), n.isConnected && St(c.host()); }; return Q(t, a), ft(t, a, n, e), a(t()), o; @@ -537,27 +519,26 @@ function St(t) { t[R] = t[R].filter(([e, n]) => n.isConnected ? !0 : (L(...e), !1)); }); } -var Ct = { +var Ot = { _set(t) { this.value = t; } }; -function Ot(t) { +function Ct(t) { return function(e, n) { - let r = (...c) => c.length ? e.setAttribute(n, ...c) : K(r), o = at(r, e.getAttribute(n), Ct); + let r = (...c) => c.length ? e.setAttribute(n, ...c) : K(r), o = at(r, e.getAttribute(n), Ot); return t[n] = o, o; }; } var G = "__dde_attributes"; E.observedAttributes = function(t) { - let e = t[G] = {}, n = F(t, Ot(e)); - return w.attributeChanged(function({ detail: o }) { + let e = t[G] = {}, n = F(t, Ct(e)); + return y.attributeChanged(function({ detail: o }) { /*! This maps attributes to signals (`S.observedAttributes`). * Investigate `__dde_attributes` key of the element.*/ let [c, i] = o, a = this[G][c]; - if (a) - return E.action(a, "_set", i); - })(t), w.disconnected(function() { + if (a) return E.action(a, "_set", i); + })(t), y.disconnected(function() { /*! This removes all signals mapped to attributes (`S.observedAttributes`). * Investigate `__dde_attributes` key of the element.*/ E.clear(...Object.values(this[G])); @@ -566,8 +547,7 @@ E.observedAttributes = function(t) { var ut = { isSignal: z, processReactiveAttribute(t, e, n, r) { - if (!z(n)) - return n; + if (!z(n)) return n; let o = (c) => { if (!t.isConnected) return L(n, o); @@ -579,7 +559,7 @@ var ut = { function ft(t, e, ...n) { let { current: r } = m; r.prevent || r.host(function(o) { - o[R] || (o[R] = [], w.disconnected( + o[R] || (o[R] = [], y.disconnected( () => ( /*! * Clears all Signals listeners added in the current scope/host (`S.el`, `assign`, …?). @@ -631,14 +611,12 @@ function Rt() { return H[H.length - 1]; } function K(t) { - if (!t[p]) - return; + if (!t[p]) return; let { value: e, listeners: n } = t[p], r = Rt(); return r && n.add(r), g.has(r) && g.get(r).add(t), e; } function dt(t, e, n) { - if (!t[p]) - return; + if (!t[p]) return; let r = t[p]; if (!(!n && r.value === e)) return r.value = e, r.listeners.forEach((o) => o(e)), e; @@ -649,15 +627,12 @@ function Q(t, e) { } function L(t, e, n) { let r = t[p]; - if (!r) - return; + if (!r) return; let o = r.listeners.delete(e); if (n && !r.listeners.size) { - if (E.clear(t), !g.has(r)) - return o; + if (E.clear(t), !g.has(r)) return o; let c = g.get(r); - if (!g.has(c)) - return o; + if (!g.has(c)) return o; g.get(c).forEach((i) => L(i, c, !0)); } return o; @@ -667,23 +642,23 @@ function L(t, e, n) { B(ut); export { E as S, - P as assign, + j as assign, nt as assignAttribute, ht as chainableAppend, gt as classListDeclarative, - j as createElement, + P as createElement, qt as createElementNS, Zt as customElementRender, - yt as customElementWithDDE, + wt as customElementWithDDE, Qt as dispatchEvent, - j as el, + P as el, qt as elNS, vt as elementAttribute, Ft as empty, z as isSignal, - yt as lifecyclesToEvents, + wt as lifecyclesToEvents, _t as observedAttributes, - w as on, + y as on, B as registerReactivity, m as scope, E as signal, diff --git a/dist/esm.d.ts b/dist/esm.d.ts index 30c6c73..4656d84 100644 --- a/dist/esm.d.ts +++ b/dist/esm.d.ts @@ -47,7 +47,7 @@ type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagName type textContent= string | ddeSignal; export function el< TAG extends keyof ExtendedHTMLElementTagNameMap, - EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement) + EL extends ExtendedHTMLElementTagNameMap[TAG] >( tag_name: TAG, attrs?: ElementAttributes | textContent, @@ -58,7 +58,7 @@ export function el( ): ddeDocumentFragment export function el( tag_name: string, - attrs?: ElementAttributes, + attrs?: ElementAttributes | textContent, ...addons: ddeElementAddon[] ): ddeHTMLElement @@ -101,7 +101,18 @@ export function elNS( export { elNS as createElementNS } export function chainableAppend(el: EL): EL; -export function simulateSlots(el: EL): EL +/** + * Mapper function (optional). Pass for coppying attributes, this is NOT implemented by {@link simulateSlots} itself! + * */ +type simulateSlotsMapper= (body: HTMLSlotElement, el: HTMLElement)=> void; +/** Simulate slots for ddeComponents */ +export function simulateSlots(root: EL, mapper?: simulateSlotsMapper): EL +/** + * Simulate slots in Custom Elements without using `shadowRoot`. + * @param el Custom Element root element + * @param body Body of the custom element + * */ +export function simulateSlots(el: HTMLElement, body: EL, mapper?: simulateSlotsMapper): EL export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any)=> void; @@ -177,12 +188,12 @@ export const scope: { export function customElementRender< EL extends HTMLElement, - P extends any = Record + P extends any = Record> >( custom_element: EL, target: ShadowRoot | EL, render: (props: P)=> SupportedElement | DocumentFragment, - props?: P | ((...args: any[])=> P) + props?: P | ((el: EL)=> P) ): EL export function customElementWithDDE HTMLElement)>(custom_element: EL): EL export function lifecyclesToEvents HTMLElement)>(custom_element: EL): EL diff --git a/dist/esm.js b/dist/esm.js index 2df90a5..a5e5b75 100644 --- a/dist/esm.js +++ b/dist/esm.js @@ -96,15 +96,14 @@ function Q(t) { return t.append === $ || (t.appendOriginal = t.append, t.append = $), t; } var T; -function k(t, e, ...n) { +function j(t, e, ...n) { let r = L(this), o = 0, c, f; switch ((Object(e) !== e || r.isSignal(e)) && (e = { textContent: e }), !0) { case typeof t == "function": { - o = 1, S.push({ scope: t, host: (...b) => b.length ? (o === 1 ? n.unshift(...b) : b.forEach((l) => l(f)), void 0) : f }), c = t(e || void 0); + o = 1, S.push({ scope: t, host: (...b) => b.length ? (o === 1 ? n.unshift(...b) : b.forEach((h) => h(f)), void 0) : f }), c = t(e || void 0); let d = c instanceof a.F; - if (c.nodeName === "#comment") - break; - let p = k.mark({ + if (c.nodeName === "#comment") break; + let p = j.mark({ type: "component", name: t.name, host: d ? "this" : "parentElement" @@ -126,20 +125,21 @@ function k(t, e, ...n) { } return Q(c), f || (f = c), n.forEach((d) => d(f)), o && S.pop(), o = 2, c; } -function bt(t, e = t, n = void 0) { +function bt(t, e, n) { + typeof e != "object" && (n = e, e = t); let r = Symbol.for("default"), o = Array.from(e.querySelectorAll("slot")).reduce((f, d) => Reflect.set(f, d.name || r, d) && f, {}), c = q(o, r); if (t.append = new Proxy(t.append, { apply(f, d, p) { - if (!p.length) - return t; + if (p[0] === e) return f.apply(t, p); + if (!p.length) return t; let b = a.D.createDocumentFragment(); - for (let l of p) { - if (!l || !l.slot) { - c && b.appendChild(l); + for (let h of p) { + if (!h || !h.slot) { + c && b.append(h); continue; } - let A = l.slot, _ = o[A]; - tt(l, "remove", "slot"), _ && (X(_, l, n), Reflect.deleteProperty(o, A)); + let A = h.slot, _ = o[A]; + tt(h, "remove", "slot"), _ && (X(_, h, n), Reflect.deleteProperty(o, A)); } return c && (o[r].replaceWith(b), Reflect.deleteProperty(o, r)), t.append = f, t; } @@ -157,7 +157,7 @@ function X(t, e, n) { t.replaceWith(e); } } -k.mark = function(t, e = !1) { +j.mark = function(t, e = !1) { t = Object.entries(t).map(([o, c]) => o + `="${c}"`).join(" "); let n = e ? "" : "/", r = a.D.createComment(``); return e && (r.end = a.D.createComment("")), r; @@ -166,14 +166,13 @@ function gt(t) { let e = this; return function(...r) { T = t; - let o = k.call(e, ...r); + let o = j.call(e, ...r); return T = void 0, o; }; } var P = /* @__PURE__ */ new WeakMap(), { setDeleteAttr: U } = a; function O(t, ...e) { - if (!e.length) - return t; + if (!e.length) return t; P.set(t, B(t, this)); for (let [n, r] of Object.entries(Object.assign({}, ...e))) z.call(this, t, n, r); @@ -188,10 +187,8 @@ function z(t, e, n) { (d, p) => z.call(c, t, d, p) ); let [f] = e; - if (f === "=") - return r(e.slice(1), n); - if (f === ".") - return H(t, e.slice(1), n); + if (f === "=") return r(e.slice(1), n); + if (f === ".") return H(t, e.slice(1), n); if (/(aria|data)([A-Z])/.test(e)) return e = e.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(), r(e, n); switch (e === "className" && (e = "class"), e) { @@ -200,8 +197,8 @@ function z(t, e, n) { case "textContent": return U(t, e, n); case "style": - if (typeof n != "object") - break; + if (typeof n != "object") break; + /* falls through */ case "dataset": return M(o, n, H.bind(null, t[e])); case "ariaset": @@ -212,8 +209,7 @@ function z(t, e, n) { return et(t, e) ? U(t, e, n) : r(e, n); } function B(t, e) { - if (P.has(t)) - return P.get(t); + if (P.has(t)) return P.get(t); let r = (t instanceof a.S ? rt : nt).bind(null, t, "Attribute"), o = L(e); return { setRemoveAttr: r, s: o }; } @@ -232,14 +228,12 @@ function tt(t, e, n, r) { return t instanceof a.H ? t[e + "Attribute"](n, r) : t[e + "AttributeNS"](null, n, r); } function et(t, e) { - if (!(e in t)) - return !1; + if (!(e in t)) return !1; let n = I(t, e); return !E(n.set); } function I(t, e) { - if (t = Object.getPrototypeOf(t), !t) - return {}; + if (t = Object.getPrototypeOf(t), !t) return {}; let n = Object.getOwnPropertyDescriptor(t, e); return n || I(t, e); } @@ -274,7 +268,7 @@ function ot() { let t = /* @__PURE__ */ new Map(), e = !1, n = (i) => function(u) { for (let s of u) if (s.type === "childList") { - if (l(s.addedNodes, !0)) { + if (h(s.addedNodes, !0)) { i(); continue; } @@ -293,8 +287,7 @@ function ot() { s.connected.has(u) || (s.connected.add(u), s.length_c += 1); }, offConnected(i, u) { - if (!t.has(i)) - return; + if (!t.has(i)) return; let s = t.get(i); s.connected.has(u) && (s.connected.delete(u), s.length_c -= 1, o(i, s)); }, @@ -304,8 +297,7 @@ function ot() { s.disconnected.has(u) || (s.disconnected.add(u), s.length_d += 1); }, offDisconnected(i, u) { - if (!t.has(i)) - return; + if (!t.has(i)) return; let s = t.get(i); s.disconnected.has(u) && (s.disconnected.delete(u), s.length_d -= 1, o(i, s)); } @@ -314,8 +306,7 @@ function ot() { u.length_c || u.length_d || (t.delete(i), d()); } function c(i) { - if (t.has(i)) - return t.get(i); + if (t.has(i)) return t.get(i); let u = { connected: /* @__PURE__ */ new WeakSet(), length_c: 0, @@ -338,26 +329,24 @@ function ot() { async function b(i) { t.size > 30 && await p(); let u = []; - if (!(i instanceof Node)) - return u; + if (!(i instanceof Node)) return u; for (let s of t.keys()) s === i || !(s instanceof Node) || i.contains(s) && u.push(s); return u; } - function l(i, u) { + function h(i, u) { let s = !1; - for (let h of i) { - if (u && b(h).then(l), !t.has(h)) - continue; - let m = t.get(h); - m.length_c && (h.dispatchEvent(new Event(g)), m.connected = /* @__PURE__ */ new WeakSet(), m.length_c = 0, m.length_d || t.delete(h), s = !0); + for (let l of i) { + if (u && b(l).then(h), !t.has(l)) continue; + let m = t.get(l); + m.length_c && (l.dispatchEvent(new Event(g)), m.connected = /* @__PURE__ */ new WeakSet(), m.length_c = 0, m.length_d || t.delete(l), s = !0); } return s; } function A(i, u) { let s = !1; - for (let h of i) - u && b(h).then(A), !(!t.has(h) || !t.get(h).length_d) && ((globalThis.queueMicrotask || setTimeout)(_(h)), s = !0); + for (let l of i) + u && b(l).then(A), !(!t.has(l) || !t.get(l).length_d) && ((globalThis.queueMicrotask || setTimeout)(_(l)), s = !0); return s; } function _(i) { @@ -379,20 +368,20 @@ function Dt(t, e, n, r = it) { return o || t.dispatchEvent(new Event(g)), e.nodeType === 11 && typeof e.mode == "string" && t.addEventListener(y, w.observe(e), { once: !0 }), S.pop(), e.append(c); } function ct(t) { - return W(t.prototype, "connectedCallback", function(e, n, r) { + return k(t.prototype, "connectedCallback", function(e, n, r) { e.apply(n, r), n.dispatchEvent(new Event(g)); - }), W(t.prototype, "disconnectedCallback", function(e, n, r) { + }), k(t.prototype, "disconnectedCallback", function(e, n, r) { e.apply(n, r), (globalThis.queueMicrotask || setTimeout)( () => !n.isConnected && n.dispatchEvent(new Event(y)) ); - }), W(t.prototype, "attributeChangedCallback", function(e, n, r) { + }), k(t.prototype, "attributeChangedCallback", function(e, n, r) { let [o, , c] = r; n.dispatchEvent(new CustomEvent(D, { detail: [o, c] })), e.apply(n, r); }), t.prototype[x] = !0, t; } -function W(t, e, n) { +function k(t, e, n) { t[e] = new Proxy(t[e] || (() => { }), { apply: n }); } @@ -424,18 +413,16 @@ R.disconnected = function(t, e) { return r.addEventListener(y, t, e), r[x] || N(e.signal, () => w.offDisconnected(r, t)) && w.onDisconnected(r, t), r; }; }; -var j = /* @__PURE__ */ new WeakMap(); +var W = /* @__PURE__ */ new WeakMap(); R.disconnectedAsAbort = function(t) { - if (j.has(t)) - return j.get(t); + if (W.has(t)) return W.get(t); let e = new AbortController(); - return j.set(t, e), t(R.disconnected(() => e.abort())), e; + return W.set(t, e), t(R.disconnected(() => e.abort())), e; }; var st = /* @__PURE__ */ new WeakSet(); R.attributeChanged = function(t, e) { return typeof e != "object" && (e = {}), function(r) { - if (r.addEventListener(D, t, e), r[x] || st.has(r) || !a.M) - return r; + if (r.addEventListener(D, t, e), r[x] || st.has(r) || !a.M) return r; let o = new a.M(function(f) { for (let { attributeName: d, target: p } of f) p.dispatchEvent( @@ -450,12 +437,12 @@ export { z as assignAttribute, Q as chainableAppend, Y as classListDeclarative, - k as createElement, + j as createElement, gt as createElementNS, Dt as customElementRender, ct as customElementWithDDE, _t as dispatchEvent, - k as el, + j as el, gt as elNS, tt as elementAttribute, vt as empty, diff --git a/docs/global.css b/docs/global.css index 58ba305..7842668 100644 --- a/docs/global.css +++ b/docs/global.css @@ -145,6 +145,7 @@ main > *{ --shiki-token-punctuation: var(--code); --shiki-token-link: #EE0000; white-space: pre; + tab-size: 2; overflow: scroll; } diff --git a/docs/index.html b/docs/index.html index 43f5022..e50d02b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,16 +1,22 @@ -`deka-dom-el` — Introduction

`deka-dom-el` — Introduction

Introducing a library.

The library tries to provide pure JavaScript tool(s) to create reactive interfaces.

We start with creating and modifying a static elements and end up with UI templates. From document.createElement to el. Then we go through the native events system and the way to include it declaratively in UI templates. From element.addEventListener to on.

Next step is providing interactivity not only for our UI templates. We introduce signals (S) and how them incorporate to UI templates.

Now we will clarify how the signals are incorporated into our templates with regard to application performance. This is not the only reason the library uses scopes. We will look at how they work in components represented in JavaScript by functions.

import { el } from "./esm-with-signals.js"; +`deka-dom-el` — Introduction

`deka-dom-el` — Introduction

Introducing a library.

The library tries to provide pure JavaScript tool(s) to create reactive interfaces using …

# Event-driven programming (3 parts separation ≡ 3PS)

Let's introduce the basic principle on which the library is built. We'll use the JavaScript listener as a starting point.

// pseudo code! +const onchage= + event=> + console.log("Reacting to the:", event); // A +input.addEventListener("change", onchange); // B +input.dispatchEvent(new Event("change")); // C +

As we can see, in the code at location “A” we define how to react when the function is called with any event as an argument. At that moment, we don't care who/why/how the function was called. Similarly, at point “B”, we reference to a function to be called on the event without caring what the function will do at that time. Finally, at point “C”, we tell the application that a change has occurred, in the input, and we don't care if/how someone is listening for the event.

import { el } from "./esm-with-signals.js"; import { S } from "./esm-with-signals.js"; -const clicks= S(0); +const clicks= S(0); // A document.body.append( el().append( el("p", S(()=> - "Hello World "+"🎉".repeat(clicks()) + "Hello World "+"🎉".repeat(clicks()) // B )), el("button", { type: "button", - onclick: ()=> clicks(clicks()+1), - textContent: "Fire" + onclick: ()=> clicks(clicks()+1), // C + textContent: "Fire", }) ) ); -
\ No newline at end of file +

The library introduces a new “type” of variable/constant called signal allowing us to to use introduced 3PS pattern in our applications. As you can see it in the example above.

Also please notice that there is very similar 3PS pattern used for separate creation of UI and business logic.

The 3PS is very simplified definition of the pattern. There are more deep/academic definitions more precisely describe usage in specific situations, see for example MVVM or MVC.

# Organization of the documentation

\ No newline at end of file diff --git a/docs/p02-elements.html b/docs/p02-elements.html index 6dd2412..62b07d5 100644 --- a/docs/p02-elements.html +++ b/docs/p02-elements.html @@ -1,4 +1,4 @@ -`deka-dom-el` — Elements

`deka-dom-el` — Elements

Basic concepts of elements modifications and creations.

Native JavaScript DOM elements creations

Let’s go through all patterns we would like to use and what needs to be improved for better experience.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js +`deka-dom-el` — Elements

`deka-dom-el` — Elements

Basic concepts of elements modifications and creations.

Native JavaScript DOM elements creations

Let’s go through all patterns we would like to use and what needs to be improved for better experience.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js import { assign, el, createElement, @@ -12,7 +12,7 @@ import { classListDeclarative, chainableAppend } from "deka-dom-el"; -

# Creating element(s) (with custom attributes)

You can create a native DOM element by using the document.createElement(). It is also possible to provide a some attribute(s) declaratively using Object.assign(). More precisely, this way you can sets some IDL also known as a JavaScript property.

document.body.append( +

# Creating element(s) (with custom attributes)

You can create a native DOM element by using the document.createElement(). It is also possible to provide a some attribute(s) declaratively using Object.assign(). More precisely, this way you can sets some IDL also known as a JavaScript property.

document.body.append( document.createElement("div") ); console.log( @@ -26,7 +26,7 @@ document.body.append( { textContent: "Element’s text content.", style: "color: coral;" } ) ); -

To make this easier, you can use the el function. Internally in basic examples, it is wrapper around assign(document.createElement(…), { … }).

import { el, assign } from "./esm-with-signals.js"; +

To make this easier, you can use the el function. Internally in basic examples, it is wrapper around assign(document.createElement(…), { … }).

import { el, assign } from "./esm-with-signals.js"; const color= "lightcoral"; document.body.append( el("p", { textContent: "Hello (first time)", style: { color } }) @@ -37,7 +37,7 @@ document.body.append( { textContent: "Hello (second time)", style: { color } } ) ); -

The assign function provides improved behaviour of Object.assign(). You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the element.setAttribute if there is no writable property in the element prototype.

You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from HTMLElement. To see all available IDLs for example for paragraphs, see HTMLParagraphElement. Moreover, the assign provides a way to sets declaratively some convenient properties:

  • It is possible to sets data-*/aria-* attributes using object notation.
  • In opposite, it is also possible to sets data-*/aria-* attribute using camelCase notation.
  • You can use string or object as a value for style property.
  • className (IDL – preffered)/class are ways to add CSS class to the element. You can use string (similarly to class="…" syntax in HTML) or array of strings. This is handy to concat conditional classes.
  • Use classList to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.
  • The assign also accepts the undefined as a value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. For example, natievly the element’s id is removed by setting the IDL to an empty string.
  • You can use = or . to force processing given key as attribute/property of the element.

For processing, the assign internally uses assignAttribute and classListDeclarative.

import { assign, assignAttribute, classListDeclarative } from "./esm-with-signals.js"; +

The assign function provides improved behaviour of Object.assign(). You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback to the element.setAttribute if there is no writable property in the element prototype.

You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements inherits from HTMLElement. To see all available IDLs for example for paragraphs, see HTMLParagraphElement. Moreover, the assign provides a way to sets declaratively some convenient properties:

  • It is possible to sets data-*/aria-* attributes using object notation.
  • In opposite, it is also possible to sets data-*/aria-* attribute using camelCase notation.
  • You can use string or object as a value for style property.
  • className (IDL – preffered)/class are ways to add CSS classes to the element. You can use string (similarly to class="…" syntax in HTML) or array of strings. This is handy to concat conditional classes.
  • Use classList to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.
  • The assign also accepts the undefined as a value for any property to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed as it can be confusing. For example, natievly the element’s id is removed by setting the IDL to an empty string.
  • You can use = or . to force processing given key as attribute/property of the element.

For processing, the assign internally uses assignAttribute and classListDeclarative.

import { assign, assignAttribute, classListDeclarative } from "./esm-with-signals.js"; const paragraph= document.createElement("p"); assignAttribute(paragraph, "textContent", "Hello, world!"); @@ -70,7 +70,7 @@ console.log("paragraph.something=", paragraph.something); document.body.append( paragraph ); -

# Native JavaScript templating

By default, the native JS has no good way to define HTML template using DOM API:

document.body.append( +

# Native JavaScript templating

By default, the native JS has no good way to define HTML template using DOM API:

document.body.append( document.createElement("div"), document.createElement("span"), document.createElement("main") @@ -81,7 +81,7 @@ const template= document.createElement("main").append( document.createElement("span"), ); console.log(typeof template==="undefined"); -

This library therefore overwrites the append method of created elements to always return parent element.

import { el } from "./esm-with-signals.js"; +

This library therefore overwrites the append method of created elements to always return parent element.

import { el } from "./esm-with-signals.js"; document.head.append( el("style").append( "tr, td{ border: 1px solid red; padding: 1em; }", @@ -116,7 +116,7 @@ document.body.append( ) ) ); -

# Basic (state-less) components

You can use functions for encapsulation (repeating) logic. The el accepts function as first argument. In that case, the function should return dom elements and the second argument for el is argument for given element.

import { el } from "./esm-with-signals.js"; +

# Basic (state-less) components

You can use functions for encapsulation (repeating) logic. The el accepts function as first argument. In that case, the function should return dom elements and the second argument for el is argument for given element.

import { el } from "./esm-with-signals.js"; document.head.append( el("style").append( ".class1{ font-weight: bold; }", @@ -133,7 +133,7 @@ function component({ className, textContent }){ el("p", textContent) ); } -

As you can see, in case of state-less/basic components there is no difference between calling component function directly or using el function.

It is nice to use similar naming convention as native DOM API. This allows us to use the destructuring assignment syntax and keep track of the native API (things are best remembered through regular use).

# Creating non-HTML elements

Similarly to the native DOM API (document.createElementNS) for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use the elNS function:

import { elNS, assign } from "./esm-with-signals.js"; +

As you can see, in case of state-less/basic components there is no difference between calling component function directly or using el function.

It is nice to use similar naming convention as native DOM API. This allows us to use the destructuring assignment syntax and keep track of the native API (things are best remembered through regular use).

# Creating non-HTML elements

Similarly to the native DOM API (document.createElementNS) for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use the elNS function:

import { elNS, assign } from "./esm-with-signals.js"; const elSVG= elNS("http://www.w3.org/2000/svg"); const elMath= elNS("http://www.w3.org/1998/Math/MathML"); document.body.append( @@ -144,4 +144,4 @@ document.body.append( console.log( document.body.innerHTML.includes("<svg></svg><math></math>") ) -

# Mnemonic

  • assign(<element>, ...<idl-objects>): <element> — assign properties to the element
  • el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name> — simple element containing only text
  • el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name> — element with more properties
  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • el(<...>, <...>, ...<addons>) — see following page
  • elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments> — typically SVG elements
\ No newline at end of file +

# Mnemonic

  • assign(<element>, ...<idl-objects>): <element> — assign properties to the element
  • el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name> — simple element containing only text
  • el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name> — element with more properties
  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • el(<...>, <...>, ...<addons>) — see following page
  • elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments> — typically SVG elements
\ No newline at end of file diff --git a/docs/p03-events.html b/docs/p03-events.html index 65ce2b6..244b215 100644 --- a/docs/p03-events.html +++ b/docs/p03-events.html @@ -1,8 +1,8 @@ -`deka-dom-el` — Events and Addons

`deka-dom-el` — Events and Addons

Using not only events in UI declaratively.

Listenning to the native DOM events and other Addons

We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called Addon to incorporate not only this in UI templates declaratively.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js +`deka-dom-el` — Events and Addons

`deka-dom-el` — Events and Addons

Using not only events in UI declaratively.

Listenning to the native DOM events and other Addons

We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called Addon to incorporate not only this in UI templates declaratively.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm.js import { on, dispatchEvent } from "deka-dom-el"; /** @type {ddeElementAddon} */ -

# Events and listenners

In JavaScript you can listen to the native DOM events of the given element by using element.addEventListener(type, listener, options). The library provides an alternative (on) accepting the differen order of the arguments:

import { el, on } from "./esm-with-signals.js"; +

# Events and listenners

In JavaScript you can listen to the native DOM events of the given element by using element.addEventListener(type, listener, options). The library provides an alternative (on) accepting the differen order of the arguments:

import { el, on } from "./esm-with-signals.js"; const log= mark=> console.log.bind(console, mark); const button= el("button", "Test click"); @@ -12,7 +12,7 @@ on("click", log("`on`"), { once: true })(button); document.body.append( button ); -

…this is actually one of the two differences. The another one is that on accepts only object as the options (but it is still optional).

The other difference is that there is no off function. You can remove listener declaratively using AbortSignal:

import { el, on } from "./esm-with-signals.js"; +

…this is actually one of the two differences. The another one is that on accepts only object as the options (but it is still optional).

The other difference is that there is no off function. You can remove listener declaratively using AbortSignal:

import { el, on } from "./esm-with-signals.js"; const log= mark=> console.log.bind(console, mark); const abort_controller= new AbortController(); @@ -25,7 +25,7 @@ on("click", log("`on`"), { signal })(button); document.body.append( button, " ", el("button", { textContent: "Off", onclick: ()=> abort_controller.abort() }) ); -

So, there are (typically) three ways to handle events. You can use:

  • el("button", { textContent: "click me", "=onclick": "console.log(event)" })
  • el("button", { textContent: "click me", onclick: console.log })
  • el("button", { textContent: "click me" }, on("click", console.log))

In the first example we force to use HTML attribute (it corresponds to <button onclick="console.log(event)">click me</button>). Side note: this can be useful in case of SSR. To study difference, you can read a nice summary here: GIST @WebReflection/web_events.md.

# Addons

From practical point of view, Addons are just functions that accept any html element as their first parameter. You can see that the on(…) fullfills this requirement.

You can use Addons as ≥3rd argument of el function. This way is possible to extends you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:

import { el, on } from "./esm-with-signals.js"; +

So, there are (typically) three ways to handle events. You can use:

  • el("button", { textContent: "click me", "=onclick": "console.log(event)" })
  • el("button", { textContent: "click me", onclick: console.log })
  • el("button", { textContent: "click me" }, on("click", console.log))

In the first example we force to use HTML attribute (it corresponds to <button onclick="console.log(event)">click me</button>). Side note: this can be useful in case of SSR. To study difference, you can read a nice summary here: GIST @WebReflection/web_events.md.

# Addons

From practical point of view, Addons are just functions that accept any HTML element as their first parameter. You can see that the on(…) fullfills this requirement.

You can use Addons as ≥3rd argument of el function. This way is possible to extends your templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:

import { el, on } from "./esm-with-signals.js"; const abort_controller= new AbortController(); const { signal }= abort_controller; /** @type {ddeElementAddon<HTMLButtonElement>} */ @@ -49,7 +49,7 @@ function update(event){ "\n" ); } -

As the example shows, you can also provide types in JSDoc+TypeScript by using global type ddeElementAddon. Also notice, you can use Addons to get element reference.

# Life-cycle events

Addons are called immediately when the element is created, even it is not connected to live DOM yet. Therefore, you can understand the Addon to be “oncreate” event.

The library provide three additional live-cycle events corresponding to how they are named in a case of custom elements: on.connected, on.disconnected and on.attributeChanged.

import { el, on } from "./esm-with-signals.js"; +

As the example shows, you can also provide types in JSDoc+TypeScript by using global type ddeElementAddon. Also notice, you can use Addons to get element reference.

# Life-cycle events

Addons are called immediately when the element is created, even it is not connected to live DOM yet. Therefore, you can understand the Addon to be “oncreate” event.

The library provide three additional live-cycle events corresponding to how they are named in a case of custom elements: on.connected, on.disconnected and on.attributeChanged.

import { el, on } from "./esm-with-signals.js"; const paragraph= el("p", "See live-cycle events in console.", el=> log({ type: "dde:created", detail: el }), on.connected(log), @@ -67,7 +67,7 @@ document.body.append( function log({ type, detail }){ console.log({ _this: this, type, detail }); } -

For Custom elements, we will later introduce a way to replace *Callback syntax with dde:* events. The on.* functions then listen to the appropriate Custom Elements events (see Custom element lifecycle callbacks | MDN).

But, in case of regular elemnets the MutationObserver | MDN is internaly used to track these events. Therefore, there are some drawbacks:

  • To proper listener registration, you need to use on.* not `on("dde:*", …)`!
  • Use sparingly! Internally, library must loop of all registered events and fires event properly. It is good practice to use the fact that if an element is removed, its children are also removed! In this spirit, we will introduce later the host syntax to register clean up procedures when the component is removed from the app.

To provide intuitive behaviour, similar also to how the life-cycle events works in other frameworks/libraries, deka-dom-el library ensures that on.connected and on.disconnected are called only once and only when the element is (dis)connected to live DOM. The solution is inspired by Vue. For using native behaviour re-(dis)connecting element, use:

  • custom MutationObserver or logic in (dis)connectedCallback or…
  • re-add on.connected or on.disconnected listeners.

# Final notes

The library also provides a method to dispatch the events.

import { el, on, dispatchEvent } from "./esm-with-signals.js"; +

For Custom elements, we will later introduce a way to replace *Callback syntax with dde:* events. The on.* functions then listen to the appropriate Custom Elements events (see Custom element lifecycle callbacks | MDN).

But, in case of regular elemnets the MutationObserver | MDN is internaly used to track these events. Therefore, there are some drawbacks:

  • To proper listener registration, you need to use on.* not `on("dde:*", …)`!
  • Use sparingly! Internally, library must loop of all registered events and fires event properly. It is good practice to use the fact that if an element is removed, its children are also removed! In this spirit, we will introduce later the host syntax to register, clean up procedures when the component is removed from the app.

To provide intuitive behaviour, similar also to how the life-cycle events works in other frameworks/libraries, deka-dom-el library ensures that on.connected and on.disconnected are called only once and only when the element, is (dis)connected to live DOM. The solution is inspired by Vue. For using native behaviour re-(dis)connecting element, use:

  • custom MutationObserver or logic in (dis)connectedCallback or…
  • re-add on.connected or on.disconnected listeners.

# Final notes

The library also provides a method to dispatch the events.

import { el, on, dispatchEvent } from "./esm-with-signals.js"; document.body.append( el("p", "Listenning to `test` event.", on("test", console.log)).append( el("br"), @@ -91,4 +91,4 @@ function dde(){ function ddeOptions(){ dispatchEvent("test", { bubbles: true })(this, "hi"); } -

# Mnemonic

  • on(<event>, <listener>[, <options>])(<element>) — just <element>.addEventListener(<event>, <listener>[, <options>])
  • on.<live-cycle>(<event>, <listener>[, <options>])(<element>) — corresponds to custom elemnets callbacks <live-cycle>Callback(...){...}. To connect to custom element see following page, else it is simulated by MutationObserver.
  • dispatchEvent(<event>[, <options>])(element) — just <element>.dispatchEvent(new Event(<event>[, <options>]))
  • dispatchEvent(<event>[, <options>])(element, detail) — just <element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))
\ No newline at end of file +

# Mnemonic

  • on(<event>, <listener>[, <options>])(<element>) — just <element>.addEventListener(<event>, <listener>[, <options>])
  • on.<live-cycle>(<event>, <listener>[, <options>])(<element>) — corresponds to custom elemnets callbacks <live-cycle>Callback(...){...}. To connect to custom element see following page, else it is simulated by MutationObserver.
  • dispatchEvent(<event>[, <options>])(element) — just <element>.dispatchEvent(new Event(<event>[, <options>]))
  • dispatchEvent(<event>[, <options>])(element, detail) — just <element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))
\ No newline at end of file diff --git a/docs/p04-signals.html b/docs/p04-signals.html index 217de81..710914d 100644 --- a/docs/p04-signals.html +++ b/docs/p04-signals.html @@ -1,10 +1,10 @@ -`deka-dom-el` — Signals and reactivity

`deka-dom-el` — Signals and reactivity

Handling reactivity in UI via signals.

Using signals to manage reactivity

How a program responds to variable data or user interactions is one of the fundamental problems of programming. If we desire to solve the issue in a declarative manner, signals may be a viable approach.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js +`deka-dom-el` — Signals and reactivity

`deka-dom-el` — Signals and reactivity

Handling reactivity in UI via signals.

Using signals to manage reactivity

How a program responds to variable data or user interactions is one of the fundamental problems of programming. If we desire to solve the issue in a declarative manner, signals may be a viable approach.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js import { S, signal } from "deka-dom-el/signals"; S===signal /** @type {ddeSignal} */ /** @type {ddeAction} */ /** @type {ddeActions} */ -

# Introducing signals

Using signals, we split program logic into the three parts. Firstly (α), we create a variable (constant) representing reactive value. Somewhere later, we can register (β) a logic reacting to the signal value changes. Similarly, in a remaining part (γ), we can update the signal value.

import { S } from "./esm-with-signals.js"; +

# Introducing signals

Let’s re-introduce 3PS principle.

Using signals, we split program logic into the three parts. Firstly (α), we create a variable (constant) representing reactive value. Somewhere later, we can register (β) a logic reacting to the signal value changes. Similarly, in a remaining part (γ), we can update the signal value.

import { S } from "./esm-with-signals.js"; // α — `signal` represents a reactive value const signal= S(0); // β — just reacts on signal changes @@ -16,7 +16,7 @@ update(); const interval= 5*1000; setTimeout(clearInterval, 10*interval, setInterval(update, interval)); -

All this is just an example of Event-driven programming and Publish–subscribe pattern (compare for example with fpubsub library). All three parts can be in some manner independent and still connected to the same reactive entity.

Signals are implemented in the library as functions. To see current value of signal, just call it without any arguments console.log(signal()). To update the signal value, pass any argument signal('a new value'). For listenning the signal value changes, use S.on(signal, console.log).

Similarly to the on function to register DOM events listener. You can use AbortController/AbortSignal to off/stop listenning. In example, you also found the way for representing “live” piece of code computation pattern (derived signal):

import { S } from "./esm-with-signals.js"; +

All this is just an example of Event-driven programming and Publish–subscribe pattern (compare for example with fpubsub library). All three parts can be in some manner independent and still connected to the same reactive entity.

Signals are implemented in the library as functions. To see current value of signal, just call it without any arguments console.log(signal()). To update the signal value, pass any argument signal('a new value'). For listenning the signal value changes, use S.on(signal, console.log).

Similarly to the on function to register DOM events listener. You can use AbortController/AbortSignal to off/stop listenning. In example, you also found the way for representing “live” piece of code computation pattern (derived signal):

import { S } from "./esm-with-signals.js"; const signal= S(0); // computation pattern const double= S(()=> 2*signal()); @@ -32,7 +32,7 @@ ac.signal.addEventListener("abort", ()=> setTimeout(()=> clearInterval(id), 2*interval)); setTimeout(()=> ac.abort(), 3*interval) -

# Signals and actions

S(/* primitive */) allows you to declare simple reactive variables, typically around immutable primitive types. However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures.

import { S } from "./esm-with-signals.js"; +

# Signals and actions

S(/* primitive */) allows you to declare simple reactive variables, typically, around immutable primitive types. However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures.

import { S } from "./esm-with-signals.js"; const signal= S(0, { increaseOnlyOdd(add){ console.info(add); @@ -50,7 +50,7 @@ setTimeout( 10*interval, setInterval(oninterval, interval) ); -

…but typical user-case is object/array (maps, sets and other mutable objects):

import { S } from "./esm-with-signals.js"; +

…but typical user-case is object/array (maps, sets and other mutable objects):

import { S } from "./esm-with-signals.js"; const todos= S([], { push(item){ this.value.push(S(item)); @@ -106,7 +106,7 @@ function radio({ textContent, checked= false }){ " ",textContent ) } -

In some way, you can compare it with useReducer hook from React. So, the S(<data>, <actions>) pattern creates a store “machine”. We can then invoke (dispatch) registered action by calling S.action(<signal>, <name>, ...<args>) after the action call the signal calls all its listeners. This can be stopped by calling this.stopPropagation() in the method representing the given action. As it can be seen in examples, the “store” value is available also in the function for given action (this.value).

# Reactive DOM attributes and elements

There are on basic level two distinc situation to mirror dynamic value into the DOM/UI

  1. to change some attribute(s) of existing element(s)
  2. to generate elements itself dynamically – this covers conditions and loops
import { S } from "./esm-with-signals.js"; +

In some way, you can compare it with useReducer hook from React. So, the S(<data>, <actions>) pattern creates a store “machine”. We can then invoke (dispatch) registered action by calling S.action(<signal>, <name>, ...<args>) after the action call the signal calls all its listeners. This can be stopped by calling this.stopPropagation() in the method representing the given action. As it can be seen in examples, the “store” value is available also in the function for given action (this.value).

# Reactive DOM attributes and elements

There are on basic level two distinc situation to mirror dynamic value into the DOM/UI

  1. to change some attribute(s) of existing element(s)
  2. to generate elements itself dynamically – this covers conditions and loops
import { S } from "./esm-with-signals.js"; const count= S(0); import { el } from "./esm-with-signals.js"; @@ -121,7 +121,7 @@ document.head.append( const interval= 5 * 1000; setTimeout(clearInterval, 10*interval, setInterval(()=> count(count()+1), interval)); -

To derived attribute based on value of signal variable just use the signal as a value of the attribute (assign(element, { attribute: S('value') })). assign/el provides ways to glue reactive attributes/classes more granularly into the DOM. Just use dedicated build-in attributes dataset, ariaset and classList.

For computation, you can use the “derived signal” (see above) like assign(element, { textContent: S(()=> 'Hello '+WorldSignal()) }). This is read-only signal its value is computed based on given function and updated when any signal used in the function changes.

To represent part of the template filled dynamically based on the signal value use S.el(signal, DOMgenerator). This was already used in the todo example above or see:

import { S } from "./esm-with-signals.js"; +

To derived attribute based on value of signal variable just use the signal as a value of the attribute (assign(element, { attribute: S('value') })). assign/el provides ways to glue reactive attributes/classes more granularly into the DOM. Just use dedicated build-in attributes dataset, ariaset and classList.

For computation, you can use the “derived signal” (see above) like assign(element, { textContent: S(()=> 'Hello '+WorldSignal()) }). This is read-only signal its value is computed based on given function and updated when any signal used in the function changes.

To represent part of the template filled dynamically based on the signal value use S.el(signal, DOMgenerator). This was already used in the todo example above or see:

import { S } from "./esm-with-signals.js"; const count= S(0, { add(){ this.value= this.value + Math.round(Math.random()*10); } }); @@ -147,4 +147,4 @@ setTimeout(clearInterval, 10*interval, setInterval(function(){ S.action(count, "add"); S.action(numbers, "push", count()); }, interval)); -

# Mnemonic

  • S(<value>) — signal: reactive value
  • S(()=> <computation>) — read-only signal: reactive value dependent on calculation using other signals
  • S.on(<signal>, <listener>[, <options>]) — listen to the signal value changes
  • S.clear(...<signals>) — off and clear signals
  • S(<value>, <actions>) — signal: pattern to create complex reactive objects/arrays
  • S.action(<signal>, <action-name>, ...<action-arguments>) — invoke an action for given signal
  • S.el(<signal>, <function-returning-dom>) — render partial dom structure (template) based on the current signal value
\ No newline at end of file +

# Mnemonic

  • S(<value>) — signal: reactive value
  • S(()=> <computation>) — read-only signal: reactive value dependent on calculation using other signals
  • S.on(<signal>, <listener>[, <options>]) — listen to the signal value changes
  • S.clear(...<signals>) — off and clear signals
  • S(<value>, <actions>) — signal: pattern to create complex reactive objects/arrays
  • S.action(<signal>, <action-name>, ...<action-arguments>) — invoke an action for given signal
  • S.el(<signal>, <function-returning-dom>) — render partial dom structure (template) based on the current signal value
\ No newline at end of file diff --git a/docs/p05-scopes.html b/docs/p05-scopes.html index 70bb807..ab43f49 100644 --- a/docs/p05-scopes.html +++ b/docs/p05-scopes.html @@ -1,7 +1,7 @@ -`deka-dom-el` — Scopes and components

`deka-dom-el` — Scopes and components

Organizing UI into components

Using functions as UI components

For state-less components we can use functions as UI components (see “Elements” page). But in real life, we may need to handle the component live-cycle and provide JavaScript the way to properly use the Garbage collection.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js +`deka-dom-el` — Scopes and components

`deka-dom-el` — Scopes and components

Organizing UI into components

Using functions as UI components

For state-less components we can use functions as UI components (see “Elements” page). But in real life, we may need to handle the component live-cycle and provide JavaScript the way to properly use the Garbage collection.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js import { scope, el } from "deka-dom-el"; /** @type {ddeElementAddon} */ -

The library therefore use scopes to provide these functionalities.

# Scopes and hosts

The host is the name for the element representing the component. This is typically element returned by function. To get reference, you can use scope.host() to applly addons just use scope.host(...<addons>).

import { el, on, scope } from "./esm-with-signals.js"; +

The library therefore use scopes to provide these functionalities.

# Scopes and hosts

The host is the name for the element representing the component. This is typically element returned by function. To get reference, you can use scope.host() to applly addons just use scope.host(...<addons>).

import { el, on, scope } from "./esm-with-signals.js"; const { host }= scope; host( element=> console.log( @@ -34,7 +34,7 @@ function component(){ el("strong", "Component") ); } -

To better understanding we implement function elClass helping to create component as class instances.

import { el } from "./esm-with-signals.js"; +

To better understanding we implement function elClass helping to create component as class instances.

import { el } from "./esm-with-signals.js"; class Test { constructor(params){ this._params= params; @@ -78,7 +78,7 @@ function elClass(_class, attributes, ...addons){ scope.pop(); return element; } -

As you can see, the scope.host() is stored temporarily and synchronously. Therefore, at least in the beginning of using library, it is the good practise to store host in the root of your component. As it may be changed, typically when there is asynchronous code in the component.

import { el, scope, on, dispatchEvent } from "deka-dom-el"; +

As you can see, the scope.host() is stored temporarily and synchronously. Therefore, at least in the beginning of using library, it is the good practise to store host in the root of your component. As it may be changed, typically when there is asynchronous code in the component.

import { el, scope, on, dispatchEvent } from "deka-dom-el"; document.body.append( el(component) ); @@ -114,7 +114,7 @@ function component(){ }); return el("p", textContent, onclickChange); } -

The text content of the paragraph is changing when the value of the signal textContent is changed. Internally, there is association between textContent and the paragraph similar to using S.on(textContent, /* update the paragraph */).

This listener must be removed when the component is removed from the DOM. To do it, the library assign internally on.disconnected(/* remove the listener */)(host()) to the host element.

The library DOM API and signals works ideally when used declaratively. It means, you split your app logic into three parts as it was itroduced in Signals.

/* PSEUDO-CODE!!! */ +

The text content of the paragraph is changing when the value of the signal textContent is changed. Internally, there is association between textContent and the paragraph, similar to using S.on(textContent, /* update the paragraph */).

This listener must be removed when the component is removed from the DOM. To do it, the library assign internally on.disconnected(/* remove the listener */)(host()) to the host element.

The library DOM API and signals works ideally when used declaratively. It means, you split your app logic into three parts as it was itroduced in Signals.

/* PSEUDO-CODE!!! */ import { el } from "deka-dom-el"; import { S } from "deka-dom-el/signals"; function component(){ @@ -149,7 +149,7 @@ function subcomponent({ id }){ /* declarative UI */ return el("li", { textContent, dataId: id }); } -

Strictly speaking, the imperative way of using the library is not prohibited. Just be careful (rather avoid) mixing declarative approach (using signals) and imperative manipulation of elements.

/* PSEUDO-CODE!!! */ +

Strictly speaking, the imperative way of using the library is not prohibited. Just be careful (rather avoid) mixing declarative approach (using signals) and imperative manipulation of elements.

/* PSEUDO-CODE!!! */ import { el, on, scope } from "deka-dom-el"; function component(){ const { host }= scope; @@ -180,4 +180,4 @@ function component(){ * // UNEXPECTEDLY REMOVED!!! * */ } -

# Mnemonic

  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • scope.host() — get current component reference
  • scope.host(...<addons>) — use addons to current component
\ No newline at end of file +

# Mnemonic

  • el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function> — using component represented by function
  • scope.host() — get current component reference
  • scope.host(...<addons>) — use addons to current component
\ No newline at end of file diff --git a/docs/p06-customElement.html b/docs/p06-customElement.html index f6229a7..f37eabe 100644 --- a/docs/p06-customElement.html +++ b/docs/p06-customElement.html @@ -1,4 +1,4 @@ -`deka-dom-el` — Custom elements

`deka-dom-el` — Custom elements

Using custom elements in combinantion with DDE

Using custom elements in combinantion with DDE

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js +`deka-dom-el` — Web Components

`deka-dom-el` — Web Components

Using custom elements in combinantion with DDE

Using web components in combinantion with DDE

The DDE library allows for use within Web Components for dom-tree generation. However, in order to be able to use signals (possibly mapping to registered observedAttributes) and additional functionality is (unfortunately) required to use helpers provided by the library.

// use NPM or for example https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js import { customElementRender, customElementWithDDE, @@ -10,8 +10,8 @@ S.observedAttributes; // “internal” utils import { lifecyclesToEvents } from "deka-dom-el"; -

# Custom Elements Introduction

Using custom elements

class CustomHTMLElement extends HTMLElement{ - static tagName = "custom-element"; // just suggestion, we can use `el(CustomHTMLElement.tagName)` +

# Custom Elements Introduction

Web Components, specifically Custom Elements, are a set of web platform APIs that allow you to create new HTML tags with custom functionality encapsulated within them. This allows for the creation of reusable components that can be used across web applications.

To start with, let’s see how to use native Custom Elements. As starting point please read Using Custom Elementson MDN. To sum up and for mnemonic see following code overview:

export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; // just suggestion, we can use `el(HTMLCustomElement.tagName)` static observedAttributes= [ "custom-attribute" ]; constructor(){ super(); @@ -30,5 +30,213 @@ import { lifecyclesToEvents } from "deka-dom-el"; get customAttribute(){ return this.getAttribute("custom-attribute"); } set customAttribute(value){ this.setAttribute("custom-attribute", value); } } -customElements.define(CustomHTMLElement.tagName, CustomHTMLElement); -

Handy Custom Elements' Patterns

# Mnemonic

  • customElementRender(<custom-element>, <render-function>[, <properties>]) — use function to render DOM structure for given <custom-element>
  • customElementWithDDE(<custom-element>) — register <custom-element> to DDE library, see also `lifecyclesToEvents`, can be also used as decorator
  • observedAttributes(<custom-element>) — returns record of observed attributes (keys uses camelCase)
  • S.observedAttributes(<custom-element>) — returns record of observed attributes (keys uses camelCase and values are signals)
  • lifecyclesToEvents(<class-declaration>) — convert lifecycle methods to events, can be also used as decorator
\ No newline at end of file +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); +

For more advanced use of Custom Elements, the summary Handy Custom Elements Patterns may be useful. Especially pay attention to linking HTML attributes and defining setters/getters, this is very helpful to use in combination with the library (el(HTMLCustomElement.tagName, { customAttribute: "new-value" });).

Also see the Life Cycle Events sections, very similarly we would like to use DDE events. To do it, the library provides function customElementWithDDE

import { customElementWithDDE, el, on } from "./esm-with-signals.js"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + connectedCallback(){ + this.append( + el("p", "Hello from custom element!") + ); + } +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +const instance= el(HTMLCustomElement.tagName); +on.connected( // preffered + e=> console.log("Element connected to the DOM (v1):", e) +)(instance); +instance.addEventListener( + "dde:connected", + e=> console.log("Element connected to the DOM (v2):", e) +); +document.body.append( + instance, +); +

Custom Elements with DDE

The customElementWithDDE function is only (small) part of the inregration of the library. More important for coexistence is render component function as a body of the Custom Element. For that, you can use customElementRender with arguments instance reference, target for connection, render function and optional properties (will be passed to the render function) see later…

import { + customElementRender, + customElementWithDDE, +} from "./esm-with-signals.js"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + static observedAttributes= [ "attr" ]; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent + ); + } + set attr(value){ this.setAttribute("attr", value); } + get attr(){ return this.getAttribute("attr"); } +} + +import { el, on, scope } from "./esm-with-signals.js"; +function ddeComponent({ attr }){ + scope.host( + on.connected(e=> console.log(e.target.outerHTML)), + ); + return el().append( + el("p", `Hello from Custom Element with attribute '${attr}'`) + ); +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName, { attr: "Attribute" }) +); +

…as you can see, you can use components created based on the documentation previously introduced. To unlock full potential, use with combination customElementWithDDE (allows to use livecycle events) and observedAttributes (converts attributes to render function arguments — default) or S.observedAttributes (converts attributes to signals).

import { + customElementRender, + customElementWithDDE, + observedAttributes, + el, on, scope +} from "./esm-with-signals.js"; +import { S } from "./esm-with-signals.js"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + static observedAttributes= [ "attr" ]; + connectedCallback(){ + console.log(observedAttributes(this)); + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent, + S.observedAttributes + ); + } + set attr(value){ this.setAttribute("attr", value); } + get attr(){ return this.getAttribute("attr"); } +} + +/** @param {{ attr: ddeSignal<string, {}> }} props */ +function ddeComponent({ attr }){ + scope.host( + on.connected(e=> console.log(e.target.outerHTML)), + ); + return el().append( + el("p", S(()=> `Hello from Custom Element with attribute '${attr()}'`)) + ); +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName, { attr: "Attribute" }) +); +setTimeout( + ()=> document.querySelector(HTMLCustomElement.tagName).setAttribute("attr", "New Value"), + 3*750 +); +

# Shadow DOM

Shadow DOM is a web platform feature that allows for the encapsulation of a component’s internal DOM tree from the rest of the document. This means that styles and scripts applied to the document will not affect the component’s internal DOM, and vice versa.

import { + el, + customElementRender, + customElementWithDDE, +} from "./esm-with-signals.js"; +function ddeComponent(){ + return el().append( + el("style", ` + .red{ color: firebrick; } + `), + el("p", { className: "red" }).append( + "Hello from ", el("slot", "Custom Element"), "!" + ) + ); +} + +export class A extends HTMLElement{ + static tagName= "custom-element-without"; + connectedCallback(){ + customElementRender( + this, + this, + ddeComponent + ); + } +} +customElementWithDDE(A); +customElements.define(A.tagName, A); +export class B extends HTMLElement{ + static tagName= "custom-element-open"; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent + ); + } +} +customElementWithDDE(B); +customElements.define(B.tagName, B); +export class C extends HTMLElement{ + static tagName= "custom-element-closed"; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "closed" }), + ddeComponent + ); + } +} +customElementWithDDE(C); +customElements.define(C.tagName, C); + +document.body.append( + el(A.tagName).append("Without shadowRoot"), + el("hr"), + el(B.tagName).append("Open shadowRoot"), + el("hr"), + el(C.tagName).append("Closed shadowRoot"), + el("style", ` + .red{ color: crimson; } + `), +); +console.log(A.tagName, "expect modifications"); +document.body.querySelector(A.tagName).querySelector("p").textContent+= " (editable with JS)"; +console.log(B.tagName, "expect modifications"); +document.body.querySelector(B.tagName).shadowRoot.querySelector("p").textContent+= " (editable with JS)"; +console.log(C.tagName, "expect error ↓"); +document.body.querySelector(C.tagName).querySelector("p").textContent+= " (editable with JS)"; +

Regarding to this.attachShadow({ mode: 'open' }) see quick overview Using Shadow DOM. An another source of information can be Shadow DOM in Depth.

Besides the encapsulation, the Shadow DOM allows for using the <slot>element(s). You can simulate this feature using simulateSlots:

import { + customElementRender, + customElementWithDDE, + el, + simulateSlots +} from "./esm-with-signals.js"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-slotting"; + connectedCallback(){ + const c= ()=> simulateSlots(this, ddeComponent()); + customElementRender(this, this, c); + } +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName), + el(HTMLCustomElement.tagName).append( + "Slot" + ), + el(ddeComponentSlot), + el(ddeComponentSlot).append( + "Slot" + ), +); + +function ddeComponent(){ + return el().append( + el("p").append( + "Hello ", el("slot", "World") + ) + ); +} +function ddeComponentSlot(){ + return simulateSlots(el().append( + el("p").append( + "Hello ", el("slot", "World") + ) + )); +} +

To sum up:

  • The use of shadow DOM to encapsulate the internal structure of the custom element, which affects how the custom element can be styled and modified using JavaScript and CSS.
  • The ability to access and modify the internal structure of the custom element using JavaScript, which is affected by the use of shadow DOM and the mode of the shadow DOM.
  • The use of slots to allow for the insertion of content from the parent document into the custom element, which is affected by the use of shadow DOM and the mode of the shadow DOM.

# Mnemonic

  • customElementRender(<custom-element>, <connect-target>, <render-function>[, <properties>]) — use function to render DOM structure for given <custom-element>
  • customElementWithDDE(<custom-element>) — register <custom-element> to DDE library, see also `lifecyclesToEvents`, can be also used as decorator
  • observedAttributes(<custom-element>) — returns record of observed attributes (keys uses camelCase)
  • S.observedAttributes(<custom-element>) — returns record of observed attributes (keys uses camelCase and values are signals)
  • lifecyclesToEvents(<class-declaration>) — convert lifecycle methods to events, can be also used as decorator
  • simulateSlots(<class-instance>, <body>[, <mapper>]) — simulate slots for Custom Elements without shadow DOM
  • simulateSlots(<dde-component>[, <mapper>]) — simulate slots for “dde”/functional components
\ No newline at end of file diff --git a/docs_src/components/code.html.js b/docs_src/components/code.html.js index 9a81953..19ca3b2 100644 --- a/docs_src/components/code.html.js +++ b/docs_src/components/code.html.js @@ -14,15 +14,14 @@ ${host}{ --shiki-token-punctuation: var(--code); --shiki-token-link: #EE0000; white-space: pre; - tab-size: 2;${""/* TODO: allow custom tab size?! */} + tab-size: 2; /* TODO: allow custom tab size?! */ overflow: scroll; } ${host}[data-js=todo]{ border: 1px solid var(--border); border-radius: var(--standard-border-radius); margin-bottom: 1rem; - ${/* to fix shift when → dataJS=done */""} - margin-top: 18.4px; + margin-top: 18.4px; /* to fix shift when → dataJS=done */ padding: 1rem 1.4rem; } `; diff --git a/docs_src/components/examples/customElement/customElementWithDDE.js b/docs_src/components/examples/customElement/customElementWithDDE.js new file mode 100644 index 0000000..367a942 --- /dev/null +++ b/docs_src/components/examples/customElement/customElementWithDDE.js @@ -0,0 +1,23 @@ +import { customElementWithDDE, el, on } from "deka-dom-el"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + connectedCallback(){ + this.append( + el("p", "Hello from custom element!") + ); + } +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +const instance= el(HTMLCustomElement.tagName); +on.connected( // preffered + e=> console.log("Element connected to the DOM (v1):", e) +)(instance); +instance.addEventListener( + "dde:connected", + e=> console.log("Element connected to the DOM (v2):", e) +); +document.body.append( + instance, +); diff --git a/docs_src/components/examples/customElement/dde.js b/docs_src/components/examples/customElement/dde.js new file mode 100644 index 0000000..4cde9a6 --- /dev/null +++ b/docs_src/components/examples/customElement/dde.js @@ -0,0 +1,33 @@ +import { + customElementRender, + customElementWithDDE, +} from "deka-dom-el"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + static observedAttributes= [ "attr" ]; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent + ); + } + set attr(value){ this.setAttribute("attr", value); } + get attr(){ return this.getAttribute("attr"); } +} + +import { el, on, scope } from "deka-dom-el"; +function ddeComponent({ attr }){ + scope.host( + on.connected(e=> console.log(e.target.outerHTML)), + ); + return el().append( + el("p", `Hello from Custom Element with attribute '${attr}'`) + ); +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName, { attr: "Attribute" }) +); diff --git a/docs_src/components/examples/customElement/native-basic.js b/docs_src/components/examples/customElement/native-basic.js index 8559c9d..3a7ff42 100644 --- a/docs_src/components/examples/customElement/native-basic.js +++ b/docs_src/components/examples/customElement/native-basic.js @@ -1,5 +1,5 @@ -class CustomHTMLElement extends HTMLElement{ - static tagName = "custom-element"; // just suggestion, we can use `el(CustomHTMLElement.tagName)` +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; // just suggestion, we can use `el(HTMLCustomElement.tagName)` static observedAttributes= [ "custom-attribute" ]; constructor(){ super(); @@ -18,4 +18,4 @@ class CustomHTMLElement extends HTMLElement{ get customAttribute(){ return this.getAttribute("custom-attribute"); } set customAttribute(value){ this.setAttribute("custom-attribute", value); } } -customElements.define(CustomHTMLElement.tagName, CustomHTMLElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); diff --git a/docs_src/components/examples/customElement/observedAttributes.js b/docs_src/components/examples/customElement/observedAttributes.js new file mode 100644 index 0000000..2b76280 --- /dev/null +++ b/docs_src/components/examples/customElement/observedAttributes.js @@ -0,0 +1,42 @@ +import { + customElementRender, + customElementWithDDE, + observedAttributes, + el, on, scope +} from "deka-dom-el"; +import { S } from "deka-dom-el/signals"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-element"; + static observedAttributes= [ "attr" ]; + connectedCallback(){ + console.log(observedAttributes(this)); + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent, + S.observedAttributes + ); + } + set attr(value){ this.setAttribute("attr", value); } + get attr(){ return this.getAttribute("attr"); } +} + +/** @param {{ attr: ddeSignal }} props */ +function ddeComponent({ attr }){ + scope.host( + on.connected(e=> console.log(e.target.outerHTML)), + ); + return el().append( + el("p", S(()=> `Hello from Custom Element with attribute '${attr()}'`)) + ); +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName, { attr: "Attribute" }) +); +setTimeout( + ()=> document.querySelector(HTMLCustomElement.tagName).setAttribute("attr", "New Value"), + 3*750 +); diff --git a/docs_src/components/examples/customElement/shadowRoot.js b/docs_src/components/examples/customElement/shadowRoot.js new file mode 100644 index 0000000..3aad1ae --- /dev/null +++ b/docs_src/components/examples/customElement/shadowRoot.js @@ -0,0 +1,69 @@ +import { + el, + customElementRender, + customElementWithDDE, +} from "deka-dom-el"; +function ddeComponent(){ + return el().append( + el("style", ` + .red{ color: firebrick; } + `), + el("p", { className: "red" }).append( + "Hello from ", el("slot", "Custom Element"), "!" + ) + ); +} + +export class A extends HTMLElement{ + static tagName= "custom-element-without"; + connectedCallback(){ + customElementRender( + this, + this, + ddeComponent + ); + } +} +customElementWithDDE(A); +customElements.define(A.tagName, A); +export class B extends HTMLElement{ + static tagName= "custom-element-open"; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "open" }), + ddeComponent + ); + } +} +customElementWithDDE(B); +customElements.define(B.tagName, B); +export class C extends HTMLElement{ + static tagName= "custom-element-closed"; + connectedCallback(){ + customElementRender( + this, + this.attachShadow({ mode: "closed" }), + ddeComponent + ); + } +} +customElementWithDDE(C); +customElements.define(C.tagName, C); + +document.body.append( + el(A.tagName).append("Without shadowRoot"), + el("hr"), + el(B.tagName).append("Open shadowRoot"), + el("hr"), + el(C.tagName).append("Closed shadowRoot"), + el("style", ` + .red{ color: crimson; } + `), +); +console.log(A.tagName, "expect modifications"); +document.body.querySelector(A.tagName).querySelector("p").textContent+= " (editable with JS)"; +console.log(B.tagName, "expect modifications"); +document.body.querySelector(B.tagName).shadowRoot.querySelector("p").textContent+= " (editable with JS)"; +console.log(C.tagName, "expect error ↓"); +document.body.querySelector(C.tagName).querySelector("p").textContent+= " (editable with JS)"; diff --git a/docs_src/components/examples/customElement/simulateSlots.js b/docs_src/components/examples/customElement/simulateSlots.js new file mode 100644 index 0000000..59fc900 --- /dev/null +++ b/docs_src/components/examples/customElement/simulateSlots.js @@ -0,0 +1,41 @@ +import { + customElementRender, + customElementWithDDE, + el, + simulateSlots +} from "deka-dom-el"; +export class HTMLCustomElement extends HTMLElement{ + static tagName= "custom-slotting"; + connectedCallback(){ + const c= ()=> simulateSlots(this, ddeComponent()); + customElementRender(this, this, c); + } +} +customElementWithDDE(HTMLCustomElement); +customElements.define(HTMLCustomElement.tagName, HTMLCustomElement); + +document.body.append( + el(HTMLCustomElement.tagName), + el(HTMLCustomElement.tagName).append( + "Slot" + ), + el(ddeComponentSlot), + el(ddeComponentSlot).append( + "Slot" + ), +); + +function ddeComponent(){ + return el().append( + el("p").append( + "Hello ", el("slot", "World") + ) + ); +} +function ddeComponentSlot(){ + return simulateSlots(el().append( + el("p").append( + "Hello ", el("slot", "World") + ) + )); +} diff --git a/docs_src/components/examples/introducing/3ps.js b/docs_src/components/examples/introducing/3ps.js new file mode 100644 index 0000000..75f62d0 --- /dev/null +++ b/docs_src/components/examples/introducing/3ps.js @@ -0,0 +1,6 @@ +// pseudo code! +const onchage= + event=> + console.log("Reacting to the:", event); // A +input.addEventListener("change", onchange); // B +input.dispatchEvent(new Event("change")); // C diff --git a/docs_src/components/examples/helloWorld.js b/docs_src/components/examples/introducing/helloWorld.js similarity index 56% rename from docs_src/components/examples/helloWorld.js rename to docs_src/components/examples/introducing/helloWorld.js index 37d13b1..47c0fe9 100644 --- a/docs_src/components/examples/helloWorld.js +++ b/docs_src/components/examples/introducing/helloWorld.js @@ -1,15 +1,15 @@ import { el } from "deka-dom-el"; import { S } from "deka-dom-el/signals"; -const clicks= S(0); +const clicks= S(0); // A document.body.append( el().append( el("p", S(()=> - "Hello World "+"🎉".repeat(clicks()) + "Hello World "+"🎉".repeat(clicks()) // B )), el("button", { type: "button", - onclick: ()=> clicks(clicks()+1), - textContent: "Fire" + onclick: ()=> clicks(clicks()+1), // C + textContent: "Fire", }) ) ); diff --git a/docs_src/components/mnemonic/customElement-init.js b/docs_src/components/mnemonic/customElement-init.js index c256893..0454726 100644 --- a/docs_src/components/mnemonic/customElement-init.js +++ b/docs_src/components/mnemonic/customElement-init.js @@ -4,7 +4,7 @@ import { mnemonicUl } from "../mnemonicUl.html.js"; export function mnemonic(){ return mnemonicUl().append( el("li").append( - el("code", "customElementRender(, [, ])"), " — use function to render DOM structure for given ", + el("code", "customElementRender(, , [, ])"), " — use function to render DOM structure for given ", ), el("li").append( el("code", "customElementWithDDE()"), " — register to DDE library, see also `lifecyclesToEvents`, can be also used as decorator", @@ -17,6 +17,12 @@ export function mnemonic(){ ), el("li").append( el("code", "lifecyclesToEvents()"), " — convert lifecycle methods to events, can be also used as decorator", - ) + ), + el("li").append( + el("code", "simulateSlots(, [, ])"), " — simulate slots for Custom Elements without shadow DOM", + ), + el("li").append( + el("code", "simulateSlots([, ])"), " — simulate slots for “dde”/functional components", + ), ); } diff --git a/docs_src/index.html.js b/docs_src/index.html.js index 3aa5446..fa8140a 100644 --- a/docs_src/index.html.js +++ b/docs_src/index.html.js @@ -1,41 +1,62 @@ +import { t, T } from "./utils/index.js"; export const info= { href: "./", - title: "Introduction", - description: "Introducing a library.", + title: t`Introduction`, + description: t`Introducing a library.`, }; import { el } from "deka-dom-el"; import { simplePage } from "./layout/simplePage.html.js"; +import { h3 } from "./components/pageUtils.html.js"; import { example } from "./components/example.html.js"; +import { code } from "./components/code.html.js"; +/** @param {string} url */ +const fileURL= url=> new URL(url, import.meta.url); +const references= { + w_mvv:{ + title: t`Wikipedia: Model–view–viewmodel`, + href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel", + }, + w_mvc: { + title: t`Wikipedia: Model–view–controller`, + href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller", + }, +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("p", "The library tries to provide pure JavaScript tool(s) to create reactive interfaces."), - el("p").append( - "We start with creating and modifying a static elements and end up with UI templates.", - " ", - el("i").append( - "From ", el("code", "document.createElement"), " to ", el("code", "el"), "." - ), - " ", - "Then we go through the native events system and the way to include it declaratively in UI templates.", - " ", - el("i").append( - "From ", el("code", "element.addEventListener"), " to ", el("code", "on"), "." - ), - ), - el("p").append( - "Next step is providing interactivity not only for our UI templates.", - " ", - "We introduce signals (", el("code", "S"), ") and how them incorporate to UI templates.", - ), - el("p").append( - "Now we will clarify how the signals are incorporated into our templates with regard ", - "to application performance. This is not the only reason the library uses ", - el("code", "scope"), "s. We will look at how they work in components represented ", - "in JavaScript by functions." - ), - el(example, { src: new URL("./components/examples/helloWorld.js", import.meta.url), page_id }), + el("p", t`The library tries to provide pure JavaScript tool(s) to create reactive interfaces using …`), + + el(h3, t`Event-driven programming (3 parts separation ≡ 3PS)`), + el("p").append(t` + Let's introduce the basic principle on which the library is built. We'll use the JavaScript listener as + a starting point. + `), + el(code, { src: fileURL("./components/examples/introducing/3ps.js"), page_id }), + el("p").append(...T` + As we can see, in the code at location “A” we define ${el("em", t`how to react`)} when the function + is called with any event as an argument. At that moment, we ${el("em", t`don't care who/why/how`)} + the function was called. Similarly, at point “B”, we reference to a function to be called on the event + ${el("em", t`without caring`)} what the function will do at that time. Finally, at point “C”, we tell + the application that a change has occurred, in the input, and we ${el("em", t`don't care if/how someone`)} + is listening for the event. + `), + el(example, { src: fileURL("./components/examples/introducing/helloWorld.js"), page_id }), + el("p").append(...T` + The library introduces a new “type” of variable/constant called ${el("em", t`signal`)} allowing us to + to use introduced 3PS pattern in our applications. As you can see it in the example above. + `), + el("p").append(...T` + Also please notice that there is very similar 3PS pattern used for separate creation of UI and + business logic. + `), + el("p").append(...T` + The 3PS is very simplified definition of the pattern. There are more deep/academic definitions more precisely + describe usage in specific situations, see for example ${el("a", { textContent: t`MVVM`, ...references.w_mvv })} + or ${el("a", { textContent: t`MVC`, ...references.w_mvc })}. + `), + + el(h3, t`Organization of the documentation`), ); } diff --git a/docs_src/p02-elements.html.js b/docs_src/p02-elements.html.js index 5c20766..b26a158 100644 --- a/docs_src/p02-elements.html.js +++ b/docs_src/p02-elements.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Elements", - description: "Basic concepts of elements modifications and creations.", + title: t`Elements`, + description: t`Basic concepts of elements modifications and creations.`, }; import { el } from "deka-dom-el"; @@ -11,113 +12,142 @@ import { mnemonic } from "./components/mnemonic/elements-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); +const references= { + /** document.createElement() */ + mdn_create: { + title: t`MDN documentation page for document.createElement()`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement", + }, + /** Interface Description Language (`el.textContent`) */ + mdn_idl: { + title: t`MDN page about Interface Description Language`, + href: "https://developer.mozilla.org/en-US/docs/Glossary/IDL", + }, + /** HTMLElement */ + mdn_el: { + title: t`MDN documentation page for HTMLElement`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement" + }, + /** HTMLParagraphElement */ + mdn_p: { + title: t`MDN documentation page for HTMLParagraphElement (\`p\` tag)`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement" + }, + /** `[a, b] = [1, 2]` */ + mdn_destruct: { + title: t`MDN page about destructuring assignment syntax (e.g. \`[a, b] = [1, 2]\`)`, + href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment", + }, + /** document.createElementNS() */ + mdn_ns: { + title: t`MDN documentation page for document.createElementNS() (e.g. for SVG elements)`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS", + } +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Native JavaScript DOM elements creations"), - el("p", "Let’s go through all patterns we would like to use and what needs to be improved for better experience."), + el("h2", t`Native JavaScript DOM elements creations`), + el("p", t` + Let’s go through all patterns we would like to use and what needs to be improved for better experience. + `), el(code, { src: fileURL("./components/examples/elements/intro.js"), page_id }), - el(h3, "Creating element(s) (with custom attributes)"), - el("p").append( - "You can create a native DOM element by using the ", - el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement", title: "MDN documentation for document.createElement()" }).append( - el("code", "document.createElement()") - ), ". ", - "It is also possible to provide a some attribute(s) declaratively using ", el("code", "Object.assign()"), ". ", - "More precisely, this way you can sets some ", - el("a", { - href: "https://developer.mozilla.org/en-US/docs/Glossary/IDL", - title: "MDN page about Interface Description Language" - }).append( - el("abbr", { textContent: "IDL", title: "Interface Description Language" }) - ), " also known as a JavaScript property." - ), + el(h3, t`Creating element(s) (with custom attributes)`), + el("p").append(...T` + You can create a native DOM element by using the ${el("a", references.mdn_create).append( + el("code", "document.createElement()") )}. It is also possible to provide a some attribute(s) declaratively + using ${el("code", "Object.assign()")}. More precisely, this way you can sets some + ${el("a", references.mdn_idl).append( el("abbr", { textContent: "IDL", title: "Interface Description Language" }))} + also known as a JavaScript property. + `), el(example, { src: fileURL("./components/examples/elements/nativeCreateElement.js"), page_id }), - el("p").append( - "To make this easier, you can use the ", el("code", "el"), " function. ", - "Internally in basic examples, it is wrapper around ", el("code", "assign(document.createElement(…), { … })"), "." - ), + el("p").append(...T` + To make this easier, you can use the ${el("code", "el")} function. Internally in basic examples, + it is wrapper around ${el("code", "assign(document.createElement(…), { … })")}. + `), el(example, { src: fileURL("./components/examples/elements/dekaCreateElement.js"), page_id }), - el("p").append( - "The ", el("code", "assign"), " function provides improved behaviour of ", el("code", "Object.assign()"), ". ", - "You can declaratively sets any IDL and attribute of the given element. ", - "Function prefers IDL and fallback to the ", el("code", "element.setAttribute"), " if there is no writable property in the element prototype." - ), - el("p").append( - "You can study all JavaScript elements interfaces to the corresponding HTML elements. ", - "All HTML elements inherits from ", el("a", { textContent: "HTMLElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement" }), ". ", - "To see all available IDLs for example for paragraphs, see ", el("a", { textContent: "HTMLParagraphElement", href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement" }), ". ", - "Moreover, the ", el("code", "assign"), " provides a way to sets declaratively some convenient properties:" - ), + el("p").append(...T` + The ${el("code", "assign")} function provides improved behaviour of ${el("code", "Object.assign()")}. + You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback + to the ${el("code", "element.setAttribute")} if there is no writable property in the element prototype. + `), + el("p").append(...T` + You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements + inherits from ${el("a", { textContent: "HTMLElement", ...references.mdn_el })}. To see + all available IDLs for example for paragraphs, see ${el("a", { textContent: "HTMLParagraphElement", ...references.mdn_p })}. + Moreover, the ${el("code", "assign")} provides a way to sets declaratively some convenient properties: + `), el("ul").append( - el("li").append( - "It is possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attributes using object notation." - ), - el("li").append( - "In opposite, it is also possible to sets ", el("code", "data-*"), "/", el("code", "aria-*"), " attribute using camelCase notation." - ), - el("li").append( - "You can use string or object as a value for ", el("code", "style"), " property." - ), - el("li").append( - el("code", "className"), " (IDL – preffered)/", el("code", "class"), " are ways to add CSS class to the element. ", - "You can use string (similarly to ", el("code", "class=\"…\"") ," syntax in HTML) or array of strings. ", - "This is handy to concat conditional classes." - ), - el("li").append( - "Use ", el("code", "classList"), " to toggle specific classes. This will be handy later when the reactivity via signals is beeing introduced.", - ), - el("li").append( - "The ", el("code", "assign"), " also accepts the ", el("code", "undefined"), " as a value for any property to remove it from the element declaratively. ", - "Also for some IDL the corresponding attribute is removed as it can be confusing. ", - el("em").append( - "For example, natievly the element’s ", el("code", "id"), " is removed by setting the IDL to an empty string." - ) - ), - el("li").append( - "You can use ", el("code", "="), " or ", el("code", "."), " to force processing given key as attribute/property of the element." - ) - ), - el("p").append( - "For processing, the ", el("code", "assign"), " internally uses ", el("code", "assignAttribute"), " and ", el("code", "classListDeclarative"), "." + el("li").append(...T` + It is possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attributes using object notation. + `), + el("li").append(...T` + In opposite, it is also possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attribute + using camelCase notation. + `), + el("li").append(...T`You can use string or object as a value for ${el("code", "style")} property.`), + el("li").append(...T` + ${el("code", "className")} (IDL – preffered)/${el("code", "class")} are ways to add CSS classes + to the element. You can use string (similarly to ${el("code", "class=\"…\"")} syntax in HTML) or + array of strings. This is handy to concat conditional classes. + `), + el("li").append(...T` + Use ${el("code", "classList")} to toggle specific classes. This will be handy later when + the reactivity via signals is beeing introduced. + `), + el("li").append(...T` + The ${el("code", "assign")} also accepts the ${el("code", "undefined")} as a value for any property + to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed + as it can be confusing. ${el("em").append(...T`For example, natievly the element’s ${el("code", "id")} + is removed by setting the IDL to an empty string.`)} + `), + el("li").append(...T` + You can use ${el("code", "=")} or ${el("code", ".")} to force processing given key as attribute/property + of the element. + `) ), + el("p").append(...T` + For processing, the ${el("code", "assign")} internally uses ${el("code", "assignAttribute")} and + ${el("code", "classListDeclarative")}. + `), el(example, { src: fileURL("./components/examples/elements/dekaAssign.js"), page_id }), - el(h3, "Native JavaScript templating"), - el("p", "By default, the native JS has no good way to define HTML template using DOM API:"), + el(h3, t`Native JavaScript templating`), + el("p", t`By default, the native JS has no good way to define HTML template using DOM API:`), el(example, { src: fileURL("./components/examples/elements/nativeAppend.js"), page_id }), - el("p").append( - "This library therefore overwrites the ", el("code", "append"), " method of created elements to always return parent element." - ), + el("p").append(...T` + This library therefore overwrites the ${el("code", "append")} method of created elements to always return + parent element. + `), el(example, { src: fileURL("./components/examples/elements/dekaAppend.js"), page_id }), - el(h3, "Basic (state-less) components"), - el("p").append( - "You can use functions for encapsulation (repeating) logic. ", - "The ", el("code", "el"), " accepts function as first argument. ", - "In that case, the function should return dom elements and the second argument for ", el("code", "el"), " is argument for given element." - ), + el(h3, t`Basic (state-less) components`), + el("p").append(...T` + You can use functions for encapsulation (repeating) logic. The ${el("code", "el")} accepts function + as first argument. In that case, the function should return dom elements and the second argument for + ${el("code", "el")} is argument for given element. + `), el(example, { src: fileURL("./components/examples/elements/dekaBasicComponent.js"), page_id }), - el("p").append( - "As you can see, in case of state-less/basic components there is no difference", - " between calling component function directly or using ", el("code", "el"), " function.", - ), - el("p", { className: "notice" }).append( - "It is nice to use similar naming convention as native DOM API. ", - "This allows us to use ", el("a", { textContent: "the destructuring assignment syntax", href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment", title: "Destructuring assignment | MDN" }), - " and keep track of the native API (things are best remembered through regular use).", - ), + el("p").append(...T` + As you can see, in case of state-less/basic components there is no difference between calling component + function directly or using ${el("code", "el")} function. + `), + el("p", { className: "notice" }).append(...T` + It is nice to use similar naming convention as native DOM API. This allows us to use + ${el("a", { textContent: t`the destructuring assignment syntax`, ...references.mdn_destruct })} and keep + track of the native API (things are best remembered through regular use). + `), - el(h3, "Creating non-HTML elements"), - el("p").append( - "Similarly to the native DOM API (", el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS", title: "MDN" }).append(el("code", "document.createElementNS")), ") for non-HTML elements", - " we need to tell JavaScript which kind of the element to create.", - " We can use the ", el("code", "elNS"), " function:" - ), + el(h3, t`Creating non-HTML elements`), + el("p").append(...T` + Similarly to the native DOM API (${el("a", references.mdn_ns).append(el("code", "document.createElementNS"))}) + for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use + the ${el("code", "elNS")} function: + `), el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }), el(mnemonic) diff --git a/docs_src/p03-events.html.js b/docs_src/p03-events.html.js index 9611ed4..9652936 100644 --- a/docs_src/p03-events.html.js +++ b/docs_src/p03-events.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Events and Addons", - description: "Using not only events in UI declaratively.", + title: t`Events and Addons`, + description: t`Using not only events in UI declaratively.`, }; import { el } from "deka-dom-el"; @@ -11,121 +12,136 @@ import { mnemonic } from "./components/mnemonic/events-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); +const references= { + /** element.addEventListener() */ + mdn_listen: { + title: t`MDN documentation page for elemetn.addEventListener`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener", + }, + /** AbortSignal+element.addEventListener */ + mdn_abortListener: { + title: t`MDN documentation page for using AbortSignal with element.addEventListener`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal", + }, + /** comparison listening options by WebReflection */ + web_events: { + href: "https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944", + }, + /** Custom Element lifecycle callbacks */ + mdn_customElement: { + href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks" + }, + /** MutationObserver */ + mdn_mutation: { + href: "https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver", + }, + /** Readding the element to the DOM fix by Vue */ + vue_fix: { + title: t`Vue and Web Components, lifecycle implementation readding the element to the DOM`, + href: "https://vuejs.org/guide/extras/web-components.html#lifecycle", + } +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Listenning to the native DOM events and other Addons"), - el("p").append( - "We quickly introduce helper to listening to the native DOM events.", - " ", - "And library syntax/pattern so-called ", el("em", "Addon"), " to", - " incorporate not only this in UI templates declaratively." - ), + el("h2", t`Listenning to the native DOM events and other Addons`), + el("p").append(...T` + We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called + ${el("em", t`Addon`)} to incorporate not only this in UI templates declaratively. + `), el(code, { src: fileURL("./components/examples/events/intro.js"), page_id }), - el(h3, "Events and listenners"), - el("p").append( - "In JavaScript you can listen to the native DOM events of the given element by using ", - el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener", title: "addEventListener on MDN" }).append( - el("code", "element.addEventListener(type, listener, options)") - ), ".", - " ", - "The library provides an alternative (", el("code", "on"), ") accepting the differen order", - " of the arguments:" - ), + el(h3, t`Events and listenners`), + el("p").append(...T` + In JavaScript you can listen to the native DOM events of the given element by using + ${el("a", references.mdn_listen).append( el("code", "element.addEventListener(type, listener, options)") )}. + The library provides an alternative (${el("code", "on")}) accepting the differen order of the arguments: + `), el(example, { src: fileURL("./components/examples/events/compare.js"), page_id }), - el("p").append( - "…this is actually one of the two differences. The another one is that ", el("code", "on"), - " accepts only object as the ", el("code", "options"), " (but it is still optional)." - ), - el("p", { className: "notice" }).append( - "The other difference is that there is ", el("strong", "no"), " ", el("code", "off"), " function.", - " ", - "You can remove listener declaratively using ", el("a", { textContent: "AbortSignal", href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal", title: "part of addEventListener on MDN" }), - ":" - ), + el("p").append(...T` + …this is actually one of the two differences. The another one is that ${el("code", "on")} accepts only + object as the ${el("code", "options")} (but it is still optional). + `), + el("p", { className: "notice" }).append(...T` + The other difference is that there is ${el("strong", "no")} ${el("code", "off")} function. You can remove + listener declaratively using ${el("a", { textContent: "AbortSignal", ...references.mdn_abortListener })}: + `), el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }), el("div", { className: "notice" }).append( - el("p", "So, there are (typically) three ways to handle events. You can use:"), + el("p", t`So, there are (typically) three ways to handle events. You can use:`), el("ul").append( el("li").append( el("code", `el("button", { textContent: "click me", "=onclick": "console.log(event)" })`)), el("li").append( el("code", `el("button", { textContent: "click me", onclick: console.log })`)), el("li").append( el("code", `el("button", { textContent: "click me" }, on("click", console.log))`)) ), - el("p").append( - "In the first example we force to use HTML attribute (it corresponds to ", el("code", ``), ").", - " ", - el("em", "Side note: this can be useful in case of SSR."), - " ", - "To study difference, you can read a nice summary here: ", el("a", { href: "https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944", textContent: "GIST @WebReflection/web_events.md" }), "." - ) + el("p").append(...T` + In the first example we force to use HTML attribute (it corresponds to + ${el("code", ``)}). ${el("em", t`Side note: + this can be useful in case of SSR.`)} To study difference, you can read a nice summary here: + ${el("a", { textContent: "GIST @WebReflection/web_events.md", ...references.web_events })}. + `) ), - el(h3, "Addons"), - el("p").append( - "From practical point of view, ", el("em", "Addons"), " are just functions that accept any html element", - " as their first parameter. You can see that the ", el("code", "on(…)"), " fullfills this requirement." - ), - el("p").append( - "You can use Addons as ≥3rd argument of ", el("code", "el"), " function. This way is possible to extends", - " you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:" - ), + el(h3, t`Addons`), + el("p").append(...T` + From practical point of view, ${el("em", t`Addons`)} are just functions that accept any HTML element as + their first parameter. You can see that the ${el("code", "on(…)")} fullfills this requirement. + `), + el("p").append(...T` + You can use Addons as ≥3rd argument of ${el("code", "el")} function. This way is possible to extends your + templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners: + `), el(example, { src: fileURL("./components/examples/events/templateWithListeners.js"), page_id }), - el("p").append( - "As the example shows, you can also provide types in JSDoc+TypeScript by using global type ", el("code", "ddeElementAddon"), ".", - " ", - "Also notice, you can use Addons to get element reference.", - ), - el(h3, "Life-cycle events"), - el("p").append( - "Addons are called immediately when the element is created, even it is not connected to live DOM yet.", - " ", - "Therefore, you can understand the Addon to be “oncreate” event." - ), - el("p").append( - "The library provide three additional live-cycle events corresponding to how they are named in", - " a case of custom elements: ", el("code", "on.connected"), ", ", el("code", "on.disconnected"), - " and ", el("code", "on.attributeChanged"), "." - ), + el("p").append(...T` + As the example shows, you can also provide types in JSDoc+TypeScript by using global type + ${el("code", "ddeElementAddon")}. Also notice, you can use Addons to get element reference. + `), + el(h3, t`Life-cycle events`), + el("p").append(...T` + Addons are called immediately when the element is created, even it is not connected to live DOM yet. + Therefore, you can understand the Addon to be “oncreate” event. + `), + el("p").append(...T` + The library provide three additional live-cycle events corresponding to how they are named in a case of + custom elements: ${el("code", "on.connected")}, ${el("code", "on.disconnected")} and ${el("code", "on.attributeChanged")}. + `), el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }), - el("p").append( - "For Custom elements, we will later introduce a way to replace ", el("code", "*Callback"), - " syntax with ", el("code", "dde:*"), " events. The ", el("code", "on.*"), " functions then", - " listen to the appropriate Custom Elements events (see ", el("a", { textContent: "Custom element lifecycle callbacks | MDN", href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks" }), ")." - ), - el("p").append( - "But, in case of regular elemnets the ", el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" }).append(el("code", "MutationObserver"), " | MDN"), - " is internaly used to track these events. Therefore, there are some drawbacks:", - ), + el("p").append(...T` + For Custom elements, we will later introduce a way to replace ${el("code", "*Callback")} syntax with + ${el("code", "dde:*")} events. The ${el("code", "on.*")} functions then listen to the appropriate + Custom Elements events (see ${el("a", { textContent: t`Custom element lifecycle callbacks | MDN`, ...references.mdn_customElement })}). + `), + el("p").append(...T` + But, in case of regular elemnets the ${el("a", references.mdn_mutation).append(el("code", "MutationObserver"), " | MDN")} + is internaly used to track these events. Therefore, there are some drawbacks: + `), el("ul").append( - el("li").append( - "To proper listener registration, you need to use ", el("code", "on.*"), " not `on(\"dde:*\", …)`!" - ), - el("li").append( - "Use sparingly! Internally, library must loop of all registered events and fires event properly.", - " ", - el("strong", "It is good practice to use the fact that if an element is removed, its children are also removed!"), - " ", - "In this spirit, we will introduce later the ", el("strong", "host"), " syntax to register", - " clean up procedures when the component is removed from the app." - ), - ), - el("p").append( - "To provide intuitive behaviour, similar also to how the life-cycle events works in other", - " frameworks/libraries, deka-dom-el library ensures that ", el("code", "on.connected"), - " and ", el("code", "on.disconnected"), " are called only once and only when the element", - " is (dis)connected to live DOM. The solution is inspired by ", el("a", { textContent: "Vue", href: "https://vuejs.org/guide/extras/web-components.html#lifecycle", title: "Vue and Web Components | Lifecycle" }), ".", - " For using native behaviour re-(dis)connecting element, use:" + el("li").append(...T` + To proper listener registration, you need to use ${el("code", "on.*")} not \`on("dde:*", …)\`! + `), + el("li").append(...T` + Use sparingly! Internally, library must loop of all registered events and fires event properly. + ${el("strong", t`It is good practice to use the fact that if an element is removed, its children are + also removed!`)} In this spirit, we will introduce later the ${el("strong", t`host`)} syntax to + register, clean up procedures when the component is removed from the app. + `), ), + el("p").append(...T` + To provide intuitive behaviour, similar also to how the life-cycle events works in other + frameworks/libraries, deka-dom-el library ensures that ${el("code", "on.connected")} and + ${el("code", "on.disconnected")} are called only once and only when the element, is (dis)connected to + live DOM. The solution is inspired by ${el("a", { textContent: "Vue", ...references.vue_fix })}. For using + native behaviour re-(dis)connecting element, use: + `), el("ul").append( - el("li").append("custom ", el("code", "MutationObserver"), " or logic in (dis)", el("code", "connectedCallback"), " or…"), - el("li").append("re-add ", el("code", "on.connected"), " or ", el("code", "on.disconnected"), " listeners.") + el("li").append(...T`custom ${el("code", "MutationObserver")} or logic in (dis)${el("code", "connectedCallback")} or…`), + el("li").append(...T`re-add ${el("code", "on.connected")} or ${el("code", "on.disconnected")} listeners.`) ), - el(h3, "Final notes"), - el("p", "The library also provides a method to dispatch the events."), + el(h3, t`Final notes`), + el("p", t`The library also provides a method to dispatch the events.`), el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }), el(mnemonic) diff --git a/docs_src/p04-signals.html.js b/docs_src/p04-signals.html.js index d7d480c..6cfedc8 100644 --- a/docs_src/p04-signals.html.js +++ b/docs_src/p04-signals.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Signals and reactivity", - description: "Handling reactivity in UI via signals.", + title: t`Signals and reactivity`, + description: t`Handling reactivity in UI via signals.`, }; import { el } from "deka-dom-el"; @@ -11,95 +12,115 @@ import { mnemonic } from "./components/mnemonic/signals-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); - +const references= { + /** Event-driven programming */ + wiki_event_driven: { + title: t`Wikipedia: Event-driven programming`, + href: "https://en.wikipedia.org/wiki/Event-driven_programming", + }, + /** Publish–subscribe pattern */ + wiki_pubsub: { + title: t`Wikipedia: Publish–subscribe pattern`, + href: "https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern", + }, + /** NPM package: fpubsub */ + fpubsub: { + title: t`NPM package: fpubsub`, + href: "https://www.npmjs.com/package/fpubsub", + }, + /** JS Primitives | MDN */ + mdn_primitive: { + title: t`Primitive | MDN`, + href: "https://developer.mozilla.org/en-US/docs/Glossary/Primitive", + }, + /** useReducer */ + mdn_use_reducer: { + title: t`useReducer hook | React docs`, + href: "https://react.dev/reference/react/useReducer", + } +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Using signals to manage reactivity"), - el("p").append( - "How a program responds to variable data or user", - " interactions is one of the fundamental problems of programming.", - " If we desire to solve the issue in a declarative manner,", - " signals may be a viable approach.", - ), + el("h2", t`Using signals to manage reactivity`), + el("p").append(...T` + How a program responds to variable data or user interactions is one of the fundamental problems of + programming. If we desire to solve the issue in a declarative manner, signals may be a viable approach. + `), el(code, { src: fileURL("./components/examples/signals/intro.js"), page_id }), - el(h3, "Introducing signals"), - el("p").append( - "Using signals, we split program logic into the three parts.", - " Firstly (α), we create a variable (constant) representing reactive", - " value. Somewhere later, we can register (β) a logic reacting", - " to the signal value changes. Similarly, in a remaining part (γ), we", - " can update the signal value." - ), + el(h3, t`Introducing signals`), + el("p").append(...T` + Let’s re-introduce + ${el("a", { textContent: t`3PS principle`, href: "./#h-event-driven-programming--parts-separation--ps" })}. + `), + el("p").append(...T` + Using signals, we split program logic into the three parts. Firstly (α), we create a variable (constant) + representing reactive value. Somewhere later, we can register (β) a logic reacting to the signal value + changes. Similarly, in a remaining part (γ), we can update the signal value. + `), el(example, { src: fileURL("./components/examples/signals/signals.js"), page_id }), - el("p").append( - "All this is just an example of ", - el("a", { textContent: "Event-driven programming", href: "https://en.wikipedia.org/wiki/Event-driven_programming", title: "Wikipedia: Event-driven programming" }), - " and ", - el("a", { textContent: "Publish–subscribe pattern", href: "https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern", title: "Wikipedia: Publish–subscribe pattern" }), - " (compare for example with ", el("a", { textContent: "fpubsub library", href: "https://www.npmjs.com/package/fpubsub", title: "NPM package: fpubsub" }), ").", - " All three parts can be in some manner independent and still connected", - " to the same reactive entity." - ), - el("p").append( - "Signals are implemented in the library as functions. To see current value", - " of signal, just call it without any arguments ", el("code", "console.log(signal())"), ".", - " To update the signal value, pass any argument ", el("code", "signal('a new value')"), ".", - " For listenning the signal value changes, use ", el("code", "S.on(signal, console.log)"), "." - ), - el("p").append( - "Similarly to the ", el("code", "on"), " function to register DOM events listener.", - " You can use ", el("code", "AbortController"), "/", el("code", "AbortSignal"), " to", - " ", el("em", "off"), "/stop listenning. In example, you also found the way for representing", - " “live” piece of code computation pattern (derived signal):" - ), + el("p").append(...T` + All this is just an example of + ${el("a", { textContent: t`Event-driven programming`, ...references.wiki_event_driven })} and + ${el("a", { textContent: t`Publish–subscribe pattern`, ...references.wiki_pubsub })} (compare for example + with ${el("a", { textContent: t`fpubsub library`, ...references.fpubsub })}). All three parts can be in + some manner independent and still connected to the same reactive entity. + `), + el("p").append(...T` + Signals are implemented in the library as functions. To see current value of signal, just call it without + any arguments ${el("code", "console.log(signal())")}. To update the signal value, pass any argument + ${el("code", `signal('${t`a new value`}')`)}. For listenning the signal value changes, use + ${el("code", "S.on(signal, console.log)")}. + `), + el("p").append(...T` + Similarly to the ${el("code", "on")} function to register DOM events listener. You can use + ${el("code", "AbortController")}/${el("code", "AbortSignal")} to ${el("em", "off")}/stop listenning. In + example, you also found the way for representing “live” piece of code computation pattern (derived signal): + `), el(example, { src: fileURL("./components/examples/signals/computations-abort.js"), page_id }), - el(h3, "Signals and actions"), - el("p").append( - el("code", "S(/* primitive */)"), " allows you to declare simple reactive variables, typically", - " around ", el("em", "immutable"), " ", el("a", { textContent: "primitive types", title: "Primitive | MDN", href: "https://developer.mozilla.org/en-US/docs/Glossary/Primitive" }), ".", - " ", - "However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures." - ), + el(h3, t`Signals and actions`), + el("p").append(...T` + ${el("code", `S(/* ${t`primitive`} */)`)} allows you to declare simple reactive variables, typically, around + ${el("em", t`immutable`)} ${el("a", { textContent: t`primitive types`, ...references.mdn_primitive })}. + However, it may also be necessary to use reactive arrays, objects, or other complex reactive structures. + `), el(example, { src: fileURL("./components/examples/signals/actions-demo.js"), page_id }), - el("p", "…but typical user-case is object/array (maps, sets and other mutable objects):"), + el("p", t`…but typical user-case is object/array (maps, sets and other mutable objects):`), el(example, { src: fileURL("./components/examples/signals/actions-todos.js"), page_id }), - el("p").append( - "In some way, you can compare it with ", el("a", { textContent: "useReducer", href: "https://react.dev/reference/react/useReducer", title: "useReducer hook | React docs" }), - " hook from React. So, the ", el("code", "S(, )"), " pattern creates", - " a store “machine”. We can then invoke (dispatch) registered action by calling", - " ", el("code", "S.action(, , ...)"), " after the action call", - " the signal calls all its listeners. This can be stopped by calling ", el("code", "this.stopPropagation()"), - " in the method representing the given action. As it can be seen in examples, the “store” value is", - " available also in the function for given action (", el("code", "this.value"), ")." - ), + el("p").append(...T` + In some way, you can compare it with ${el("a", { textContent: "useReducer", ...references.mdn_use_reducer })} + hook from React. So, the ${el("code", "S(, )")} pattern creates a store “machine”. We can + then invoke (dispatch) registered action by calling ${el("code", "S.action(, , ...)")} + after the action call the signal calls all its listeners. This can be stopped by calling + ${el("code", "this.stopPropagation()")} in the method representing the given action. As it can be seen in + examples, the “store” value is available also in the function for given action (${el("code", "this.value")}). + `), - el(h3, "Reactive DOM attributes and elements"), - el("p", "There are on basic level two distinc situation to mirror dynamic value into the DOM/UI"), + el(h3, t`Reactive DOM attributes and elements`), + el("p", t`There are on basic level two distinc situation to mirror dynamic value into the DOM/UI`), el("ol").append( - el("li", "to change some attribute(s) of existing element(s)"), - el("li", "to generate elements itself dynamically – this covers conditions and loops") + el("li", t`to change some attribute(s) of existing element(s)`), + el("li", t`to generate elements itself dynamically – this covers conditions and loops`) ), el(example, { src: fileURL("./components/examples/signals/dom-attrs.js"), page_id }), - el("p").append( - "To derived attribute based on value of signal variable just use the signal as", - " a value of the attribute (", el("code", "assign(element, { attribute: S('value') })"), ").", - " ", el("code", "assign"), "/", el("code", "el"), " provides ways to glue reactive attributes/classes", - " more granularly into the DOM. Just use dedicated build-in attributes ", el("code", "dataset"), ", ", - el("code", "ariaset"), " and ", el("code", "classList"), "." - ), - el("p").append( - "For computation, you can use the “derived signal” (see above) like ", el("code", "assign(element, { textContent: S(()=> 'Hello '+WorldSignal()) })"), ".", - " ", - "This is read-only signal its value is computed based on given function and updated when any signal used in the function changes." - ), - el("p").append( - "To represent part of the template filled dynamically based on the signal value use ", el("code", "S.el(signal, DOMgenerator)"), ".", - " This was already used in the todo example above or see:" - ), + el("p").append(...T` + To derived attribute based on value of signal variable just use the signal as a value of the attribute + (${el("code", "assign(element, { attribute: S('value') })")}). ${el("code", "assign")}/${el("code", "el")} + provides ways to glue reactive attributes/classes more granularly into the DOM. Just use dedicated build-in + attributes ${el("code", "dataset")}, ${el("code", "ariaset")} and ${el("code", "classList")}. + `), + el("p").append(...T` + For computation, you can use the “derived signal” (see above) like + ${el("code", "assign(element, { textContent: S(()=> 'Hello '+WorldSignal()) })")}. This is read-only signal + its value is computed based on given function and updated when any signal used in the function changes. + `), + el("p").append(...T` + To represent part of the template filled dynamically based on the signal value use + ${el("code", "S.el(signal, DOMgenerator)")}. This was already used in the todo example above or see: + `), el(example, { src: fileURL("./components/examples/signals/dom-el.js"), page_id }), el(mnemonic) diff --git a/docs_src/p05-scopes.html.js b/docs_src/p05-scopes.html.js index 78e6cbe..d104ffd 100644 --- a/docs_src/p05-scopes.html.js +++ b/docs_src/p05-scopes.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Scopes and components", - description: "Organizing UI into components", + title: t`Scopes and components`, + description: t`Organizing UI into components`, }; import { el } from "deka-dom-el"; @@ -11,67 +12,74 @@ import { mnemonic } from "./components/mnemonic/scopes-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); - +const references= { + /** Garbage collection on MDN */ + garbage_collection: { + title: t`MDN documentation page for Garbage collection`, + href: "https://developer.mozilla.org/en-US/docs/Glossary/Garbage_collection", + }, + /** Signals */ + signals: { + title: t`Signals section on this library`, + href: "./p04-signals#h-introducing-signals", + } +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Using functions as UI components"), - el("p").append( - "For state-less components we can use functions as UI components (see “Elements” page).", - " But in real life, we may need to handle the component live-cycle and provide", - " JavaScript the way to properly use the ", el("a", { textContent: "Garbage collection", href: "https://developer.mozilla.org/en-US/docs/Glossary/Garbage_collection", title: "Garbage collection | MDN" }), "." - ), + el("h2", t`Using functions as UI components`), + el("p").append(...T` + For state-less components we can use functions as UI components (see “Elements” page). But in real life, + we may need to handle the component live-cycle and provide JavaScript the way to properly use + the ${el("a", { textContent: t`Garbage collection`, ...references.garbage_collection })}. + `), el(code, { src: fileURL("./components/examples/scopes/intro.js"), page_id }), - el("p").append( - "The library therefore use ", el("em", "scopes"), " to provide these functionalities.", - ), + el("p").append(...T`The library therefore use ${el("em", t`scopes`)} to provide these functionalities.`), - el(h3, "Scopes and hosts"), - el("p").append( - "The ", el("strong", "host"), " is the name for the element representing the component.", - " This is typically element returned by function. To get reference, you can use ", - el("code", "scope.host()"), " to applly addons just use ", el("code", "scope.host(...)"), "." - ), + el(h3, t`Scopes and hosts`), + el("p").append(...T` + The ${el("strong", "host")} is the name for the element representing the component. This is typically + element returned by function. To get reference, you can use ${el("code", "scope.host()")} to applly addons + just use ${el("code", "scope.host(...)")}. + `), el(example, { src: fileURL("./components/examples/scopes/scopes-and-hosts.js"), page_id }), - el("p").append( - "To better understanding we implement function ", el("code", "elClass"), " helping to create", - " component as class instances." - ), + el("p").append(...T` + To better understanding we implement function ${el("code", "elClass")} helping to create component as + class instances. + `), el(example, { src: fileURL("./components/examples/scopes/class-component.js"), page_id }), - el("p").append( - "As you can see, the ", el("code", "scope.host()"), " is stored temporarily and synchronously.", - " Therefore, at least in the beginning of using library, it is the good practise to store", - " ", el("code", "host"), " in the root of your component. As it may be changed, typically when", - " there is asynchronous code in the component." - ), + el("p").append(...T` + As you can see, the ${el("code", "scope.host()")} is stored temporarily and synchronously. Therefore, at + least in the beginning of using library, it is the good practise to store ${el("code", "host")} in the root + of your component. As it may be changed, typically when there is asynchronous code in the component. + `), el(code, { src: fileURL("./components/examples/scopes/good-practise.js"), page_id }), - el(h3, "Scopes, signals and cleaning magic"), - el("p").append( - "The ", el("code", "host"), " is internally used to register the cleaning procedure,", - " when the component (", el("code", "host"), " element) is removed from the DOM." - ), + el(h3, t`Scopes, signals and cleaning magic`), + el("p").append(...T` + The ${el("code", "host")} is internally used to register the cleaning procedure, when the component + (${el("code", "host")} element) is removed from the DOM. + `), el(example, { src: fileURL("./components/examples/scopes/cleaning.js"), page_id }), - el("p").append( - "The text content of the paragraph is changing when the value of the signal ", el("code", "textContent"), - " is changed. Internally, there is association between ", el("code", "textContent"), " and the paragraph", - " similar to using ", el("code", "S.on(textContent, /* update the paragraph */)"), "." - ), - el("p").append( - "This listener must be removed when the component is removed from the DOM. To do it, the library", - " assign internally ", el("code", "on.disconnected(/* remove the listener */)(host())"), " to the host element." - ), - el("p", { className: "notice" }).append( - "The library DOM API and signals works ideally when used declaratively.", - " It means, you split your app logic into three parts as it was itroduced in ", el("a", { textContent: "Signals", href: "http://localhost:40911/docs/p04-signals#h-introducing-signals" }), "." - ), + el("p").append(...T` + The text content of the paragraph is changing when the value of the signal ${el("code", "textContent")} + is changed. Internally, there is association between ${el("code", "textContent")} and the paragraph, + similar to using ${el("code", `S.on(textContent, /* ${t`update the paragraph`} */)`)}. + `), + el("p").append(...T` + This listener must be removed when the component is removed from the DOM. To do it, the library assign + internally ${el("code", `on.disconnected(/* ${t`remove the listener`} */)(host())`)} to the host element. + `), + el("p", { className: "notice" }).append(...T` + The library DOM API and signals works ideally when used declaratively. It means, you split your app logic + into three parts as it was itroduced in ${el("a", { textContent: "Signals", ...references.signals })}. + `), el(code, { src: fileURL("./components/examples/scopes/declarative.js"), page_id }), - el("p").append( - "Strictly speaking, the imperative way of using the library is not prohibited.", - " Just be careful (rather avoid) mixing declarative approach (using signals)", - " and imperative manipulation of elements.", - ), + el("p").append(...T` + Strictly speaking, the imperative way of using the library is not prohibited. Just be careful (rather avoid) + mixing declarative approach (using signals) and imperative manipulation of elements. + `), el(code, { src: fileURL("./components/examples/scopes/imperative.js"), page_id }), el(mnemonic) diff --git a/docs_src/p06-customElement.html.js b/docs_src/p06-customElement.html.js index 605e507..8d471f6 100644 --- a/docs_src/p06-customElement.html.js +++ b/docs_src/p06-customElement.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Custom elements", - description: "Using custom elements in combinantion with DDE", + title: t`Web Components`, + description: t`Using custom elements in combinantion with DDE`, }; import { el } from "deka-dom-el"; @@ -11,24 +12,131 @@ import { mnemonic } from "./components/mnemonic/customElement-init.js"; import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); - +const references= { + /** Web Components on MDN */ + mdn_web_components: { + title: t`MDN documentation page for Web Components`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components", + }, + /** observedAttributes on MDN */ + mdn_observedAttributes: { + title: t`MDN documentation page for observedAttributes`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#responding_to_attribute_changes", + }, + /** Custom Elements on MDN */ + mdn_custom_elements: { + title: t`MDN documentation page for Custom Elements`, + href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements", + }, + /** Custom Elements tips from WebReflection */ + custom_elements_tips: { + title: t`Ideas and tips from WebReflection`, + href: "https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4", + }, + /** Shallow DOM on mdn */ + mdn_shadow_dom_depth: { + title: t`MDN documentation page for Shadow DOM`, + href: "https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM", + }, + /** Shallow DOM on mdn */ + mdn_shadow_dom_slot: { + title: t`MDN documentation page for `, + href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot", + }, + /** Shallow DOM */ + shadow_dom_depth: { + title: t`Everything you need to know about Shadow DOM (github repo praveenpuglia/shadow-dom-in-depth)`, + href: "https://github.com/praveenpuglia/shadow-dom-in-depth", + }, +}; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Using custom elements in combinantion with DDE"), - el("p").append( - - ), + el("h2", t`Using web components in combinantion with DDE`), + el("p").append(...T` + The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong", t`Web Components`) )} + for dom-tree generation. However, in order to be able to use signals (possibly mapping to registered + ${el("a", references.mdn_observedAttributes).append( el("code", "observedAttributes") )}) and additional + functionality is (unfortunately) required to use helpers provided by the library. + `), el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }), - el(h3, "Custom Elements Introduction"), - el("p").append( - el("a", { textContent: "Using custom elements", href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements", title: "Article about custom elements on MDN" }) - ), + el(h3, t`Custom Elements Introduction`), + el("p").append(...T` + Web Components, specifically Custom Elements, are a set of web platform APIs that allow you to create + new HTML tags with custom functionality encapsulated within them. This allows for the creation of reusable + components that can be used across web applications. + `), + el("p").append(...T` + To start with, let’s see how to use native Custom Elements. As starting point please read + ${el("a", references.mdn_custom_elements).append( el("strong", t`Using Custom Elements`), t` on MDN` )}. + To sum up and for mnemonic see following code overview: + `), el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }), - el("p").append( - el("a", { textContent: "Handy Custom Elements' Patterns", href: "https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4", title: "Ideas and tips from WebReflection" }) + el("p").append(...T` + For more advanced use of Custom Elements, the summary ${el("a", references.custom_elements_tips) + .append( el("strong", t`Handy Custom Elements Patterns`) )} may be useful. Especially pay attention to + linking HTML attributes and defining setters/getters, this is very helpful to use in combination with + the library (${el("code", `el(HTMLCustomElement.tagName, { customAttribute: "${t`new-value`}" });`)}). + `), + el("p").append(...T` + Also see the Life Cycle Events sections, very similarly we would like to use + ${el("a", { textContent: t`DDE events`, href: "./p03-events.html", title: t`See events part of the library documentation` })}. + To do it, the library provides function ${el("code", "customElementWithDDE")}… + `), + el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }), + + el("h3", t`Custom Elements with DDE`), + el("p").append(...T` + The ${el("code", "customElementWithDDE")} function is only (small) part of the inregration of the library. + More important for coexistence is render component function as a body of the Custom Element. For that, you + can use ${el("code", "customElementRender")} with arguments instance reference, target for connection, + render function and optional properties (will be passed to the render function) see later… + `), + el(example, { src: fileURL("./components/examples/customElement/dde.js"), page_id }), + el("p").append(...T` + …as you can see, you can use components created based on the documentation previously introduced. To unlock + full potential, use with combination ${el("code", "customElementWithDDE")} (allows to use livecycle events) + and ${el("code", "observedAttributes")} (converts attributes to render function arguments — + ${el("em", "default")}) or ${el("code", "S.observedAttributes")} (converts attributes to signals). + `), + el(example, { src: fileURL("./components/examples/customElement/observedAttributes.js"), page_id }), + + + el(h3, t`Shadow DOM`), + el("p").append(...T` + Shadow DOM is a web platform feature that allows for the encapsulation of a component’s internal DOM tree + from the rest of the document. This means that styles and scripts applied to the document will not affect + the component’s internal DOM, and vice versa. + `), + el(example, { src: fileURL("./components/examples/customElement/shadowRoot.js"), page_id }), + el("p").append(...T` + Regarding to ${el("code", "this.attachShadow({ mode: 'open' })")} see quick overview + ${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}. An another source of + information can be ${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}. + `), + el("p").append(...T` + Besides the encapsulation, the Shadow DOM allows for using the ${el("a", references.mdn_shadow_dom_slot).append( + el("strong", t``), t` element(s)`)}. You can simulate this feature using ${el("code", "simulateSlots")}: + `), + el(example, { src: fileURL("./components/examples/customElement/simulateSlots.js"), page_id }), + el("p").append(...T` + To sum up: + `), + el("ul").append( + el("li").append(...T` + The use of shadow DOM to encapsulate the internal structure of the custom element, which affects how + the custom element can be styled and modified using JavaScript and CSS. + `), + el("li").append(...T` + The ability to access and modify the internal structure of the custom element using JavaScript, which + is affected by the use of shadow DOM and the mode of the shadow DOM. + `), + el("li").append(...T` + The use of slots to allow for the insertion of content from the parent document into the custom + element, which is affected by the use of shadow DOM and the mode of the shadow DOM. + `), ), el(mnemonic) diff --git a/docs_src/ssr.js b/docs_src/ssr.js index f6e4466..bb391bc 100644 --- a/docs_src/ssr.js +++ b/docs_src/ssr.js @@ -1,3 +1,4 @@ +export { t } from "./utils/index.js"; export const path_target= { root: "docs/", css: "docs/" diff --git a/docs_src/utils/index.js b/docs_src/utils/index.js new file mode 100644 index 0000000..2975076 --- /dev/null +++ b/docs_src/utils/index.js @@ -0,0 +1,52 @@ +/** + * This is helper to write texts in code more readable + * and doesn’t inpact the finally generated text in HTML. + * + * ```js + * t` + * Hello ${el("b", "world")}! + * How are you? + * ` === "Hello world! How are you?" + * ``` + * + * In future, this can be expanded to allow translations. + * + * ```js + * t(key)`text`; // for example + * ``` + * + * @param {TemplateStringsArray} strings + * @param {...(string|Node)} values + * @returns {(string|Node)[]} + * */ +export function T(strings, ...values){ + const out= []; + tT(s=> out.push(s), strings, ...values); + return out; +} +/** + * Similarly to {@link T}, but for only strings. + * @param {TemplateStringsArray} strings + * @param {...string} values + * @returns {string} + * */ +export function t(strings, ...values){ + let out= ""; + tT(s=> out+= s, strings, ...values); + return out; +} + +/** + * @param {(input: string|Node)=> void} callback + * @param {TemplateStringsArray} strings + * @param {...(string|Node)} values + * */ +function tT(callback, strings, ...values){ + const { length }= strings; + const last= length-1; + for(let i= 0; i toggle(!toggle()) }).append( el("strong", { slot: "name", textContent: "Honzo" }), - el("span", "…default slot") + S.el(toggle, is=> is + ? el("span", "…default slot") + : el("span", "…custom slot") + ) ) ); diff --git a/index.d.ts b/index.d.ts index af12b5e..270cdf2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -47,7 +47,7 @@ type ExtendedHTMLElementTagNameMap= HTMLElementTagNameMap & CustomElementTagName type textContent= string | ddeSignal; export function el< TAG extends keyof ExtendedHTMLElementTagNameMap, - EL extends (TAG extends keyof ExtendedHTMLElementTagNameMap ? ExtendedHTMLElementTagNameMap[TAG] : HTMLElement) + EL extends ExtendedHTMLElementTagNameMap[TAG] >( tag_name: TAG, attrs?: ElementAttributes | textContent, @@ -58,7 +58,7 @@ export function el( ): ddeDocumentFragment export function el( tag_name: string, - attrs?: ElementAttributes, + attrs?: ElementAttributes | textContent, ...addons: ddeElementAddon[] ): ddeHTMLElement @@ -101,7 +101,18 @@ export function elNS( export { elNS as createElementNS } export function chainableAppend(el: EL): EL; -export function simulateSlots(el: EL): EL +/** + * Mapper function (optional). Pass for coppying attributes, this is NOT implemented by {@link simulateSlots} itself! + * */ +type simulateSlotsMapper= (body: HTMLSlotElement, el: HTMLElement)=> void; +/** Simulate slots for ddeComponents */ +export function simulateSlots(root: EL, mapper?: simulateSlotsMapper): EL +/** + * Simulate slots in Custom Elements without using `shadowRoot`. + * @param el Custom Element root element + * @param body Body of the custom element + * */ +export function simulateSlots(el: HTMLElement, body: EL, mapper?: simulateSlotsMapper): EL export function dispatchEvent(name: keyof DocumentEventMap | string, options?: EventInit): (element: SupportedElement, data?: any)=> void; @@ -177,12 +188,12 @@ export const scope: { export function customElementRender< EL extends HTMLElement, - P extends any = Record + P extends any = Record> >( custom_element: EL, target: ShadowRoot | EL, render: (props: P)=> SupportedElement | DocumentFragment, - props?: P | ((...args: any[])=> P) + props?: P | ((el: EL)=> P) ): EL export function customElementWithDDE HTMLElement)>(custom_element: EL): EL export function lifecyclesToEvents HTMLElement)>(custom_element: EL): EL diff --git a/package-lock.json b/package-lock.json index e5f8e38..022a4e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,384 +9,424 @@ "version": "0.8.0", "license": "MIT", "devDependencies": { - "@size-limit/preset-small-lib": "^11.0.1", - "dts-bundler": "^0.1.0", - "esbuild": "^0.19.9", - "jsdom": "^23.0.1", - "jshint": "^2.13.6", - "nodejsscript": "github:jaandrle/nodejsscript#dev-v1", - "size-limit-node-esbuild": "^0.3.0" + "@size-limit/preset-small-lib": "~11.0", + "dts-bundler": "~0.1", + "esbuild": "~0.24", + "jsdom": "~25.0", + "jshint": "~2.13", + "nodejsscript": "^1.0.2", + "size-limit-node-esbuild": "~0.3" }, "engines": { "node": ">=18" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", - "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", - "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", - "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", - "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", - "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", - "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", - "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", - "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", - "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", - "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", - "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", - "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", - "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", - "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", - "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", - "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", - "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", - "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", - "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", "cpu": [ - "x64" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", - "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", - "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", - "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", - "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@nodelib/fs.scandir": { @@ -394,6 +434,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -407,6 +448,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -416,6 +458,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -425,10 +468,11 @@ } }, "node_modules/@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -437,45 +481,478 @@ } }, "node_modules/@size-limit/esbuild": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@size-limit/esbuild/-/esbuild-11.0.1.tgz", - "integrity": "sha512-JXxzmDW7Rch6yxd4u8g6uE21g34oT7fk7Ex2gfDwN4TtciOghI3By4fqxXOwGYkDueEcIw3LXNGjHnTS8Dz5nA==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@size-limit/esbuild/-/esbuild-11.0.3.tgz", + "integrity": "sha512-8DqOU79oMcNH33d8XlECVF/G2ZbuyTP7/GwRswjM+hObGgsSjVZUN2Ikxl9t0zJvvG2bLB8m3uHa9bsCtdnOcw==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.19.8", - "nanoid": "^5.0.4" + "esbuild": "^0.20.1", + "nanoid": "^5.0.6" }, "engines": { "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "size-limit": "11.0.1" + "size-limit": "11.0.3" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@size-limit/esbuild/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/@size-limit/file": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-11.0.1.tgz", - "integrity": "sha512-ioSYJ1WY66kc9+3dgTHi5mT/gcaNNCJ22xU87cjzfKiNxmol+lGsNKbplmrJf+QezvPH9kRIFOWxBjGY+DOt3g==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-11.0.3.tgz", + "integrity": "sha512-fuVZG+dZLLMaEi1siHHK5gU8Vfc4pvjZBxrefwZt9gOinbOgGONauEPZYipaE1tYTZPeJo8o9PuJ8Obbub+MLA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "size-limit": "11.0.1" + "size-limit": "11.0.3" } }, "node_modules/@size-limit/preset-small-lib": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@size-limit/preset-small-lib/-/preset-small-lib-11.0.1.tgz", - "integrity": "sha512-c1N5/wN5FRQ03aOpoCw9ed2TP/1cmjt8vKAeTxO40OSfj6ImkpkMarl7e7pCnBElMULc993aUP5UjFhDN6bU4w==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@size-limit/preset-small-lib/-/preset-small-lib-11.0.3.tgz", + "integrity": "sha512-EolyGohughbRQ7TNiqE3qj+7pun0EH1Aks7eJnoWuUWZz9j3eVJMT9FP5p9oIBUjn808LerZNt2bFnnjxiOjnA==", "dev": true, + "license": "MIT", "dependencies": { - "@size-limit/esbuild": "11.0.1", - "@size-limit/file": "11.0.1", - "size-limit": "11.0.1" + "@size-limit/esbuild": "11.0.3", + "@size-limit/file": "11.0.3", + "size-limit": "11.0.3" }, "peerDependencies": { - "size-limit": "11.0.1" + "size-limit": "11.0.3" } }, "node_modules/@types/glob": { @@ -483,6 +960,7 @@ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" @@ -492,21 +970,24 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mri": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@types/mri/-/mri-1.1.5.tgz", "integrity": "sha512-C6NscC1RO9iz1YmvqPlFdbo/q8krKwrvWsciw2MG+pH+WUgxWKv1VFpY/Y2AAZubzUpA4FH6d+FDtroboN9xMw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", - "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/sade": { @@ -514,6 +995,7 @@ "resolved": "https://registry.npmjs.org/@types/sade/-/sade-1.7.8.tgz", "integrity": "sha512-WGEWfxQ8VHLm3JS4ljRR3MSPqVjY0JMo6zsbBywOjFIxP8Cizxx1p6r6FxOnAOZpUn4VOFoRRTXFmaOLD/+VOQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/mri": "*" } @@ -523,6 +1005,7 @@ "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.15.tgz", "integrity": "sha512-vzmnCHl6hViPu9GNLQJ+DZFd6BQI2DBTUeOvYHqkWQLMfKAAQYMb/xAmZkTogZI/vqXHCWkqDRymDI5p0QTi5Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/glob": "~7.2.0", "@types/node": "*" @@ -533,6 +1016,7 @@ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dev": true, + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -541,10 +1025,11 @@ } }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -557,6 +1042,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -572,6 +1058,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -581,6 +1068,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -595,13 +1083,15 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/any-shell-escape/-/any-shell-escape-0.1.1.tgz", "integrity": "sha512-36j4l5HVkboyRhIWgtMh1I9i8LTdFqVwDEHy1cp+QioJyKgAUG40X0W8s7jakWRta/Sjvm8mUG1fU6Tj8mWagQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -615,6 +1105,7 @@ "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-1.1.2.tgz", "integrity": "sha512-CeTSWB5Bou31xSHeO45ZKgLPRaJbV4I8csRcFYETDBehX7H+1GDO/v+v8G7fZmar1gOmYa6UTXn6d/WIiJbslw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -623,21 +1114,27 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { @@ -645,18 +1142,20 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -667,21 +1166,17 @@ "resolved": "https://registry.npmjs.org/bytes-iec/-/bytes-iec-3.1.1.tgz", "integrity": "sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -694,6 +1189,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -703,6 +1201,7 @@ "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", "dev": true, + "license": "MIT", "dependencies": { "exit": "0.1.2", "glob": "^7.1.1" @@ -716,6 +1215,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -727,13 +1227,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -745,7 +1247,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/console-browserify": { "version": "1.1.0", @@ -760,24 +1263,27 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/css-in-console": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/css-in-console/-/css-in-console-2.0.0.tgz", "integrity": "sha512-Xbphn3qbe/XO67D8dr7Q39qSqi3ddnSsL72nixhKLiUEr8K3oTlk9aCOKRyCVNgPtgWwhynM19jj5mw1n/K2Tg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, + "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" @@ -788,6 +1294,7 @@ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12" } @@ -797,6 +1304,7 @@ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -812,12 +1320,13 @@ "dev": true }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -832,13 +1341,15 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -848,6 +1359,7 @@ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", "dev": true, + "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "entities": "^2.0.0" @@ -863,13 +1375,15 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/dom-serializer/node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, + "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -878,7 +1392,8 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "2.3.0", @@ -904,6 +1419,7 @@ "resolved": "https://registry.npmjs.org/dts-bundler/-/dts-bundler-0.1.0.tgz", "integrity": "sha512-h0llx8DbWDMLJoB/jT5+YghYse1RA7SKDDPG3h0E+ecgkRDFMsr1aa8vaPTmrv6Qta79mme78tIyFStXBxijCg==", "dev": true, + "license": "MIT", "peerDependencies": { "typescript": "^2.4.0" } @@ -912,50 +1428,54 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", - "dev": true + "dev": true, + "license": "BSD-like" }, "node_modules/esbuild": { - "version": "0.19.11", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", - "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.11", - "@esbuild/android-arm": "0.19.11", - "@esbuild/android-arm64": "0.19.11", - "@esbuild/android-x64": "0.19.11", - "@esbuild/darwin-arm64": "0.19.11", - "@esbuild/darwin-x64": "0.19.11", - "@esbuild/freebsd-arm64": "0.19.11", - "@esbuild/freebsd-x64": "0.19.11", - "@esbuild/linux-arm": "0.19.11", - "@esbuild/linux-arm64": "0.19.11", - "@esbuild/linux-ia32": "0.19.11", - "@esbuild/linux-loong64": "0.19.11", - "@esbuild/linux-mips64el": "0.19.11", - "@esbuild/linux-ppc64": "0.19.11", - "@esbuild/linux-riscv64": "0.19.11", - "@esbuild/linux-s390x": "0.19.11", - "@esbuild/linux-x64": "0.19.11", - "@esbuild/netbsd-x64": "0.19.11", - "@esbuild/openbsd-x64": "0.19.11", - "@esbuild/sunos-x64": "0.19.11", - "@esbuild/win32-arm64": "0.19.11", - "@esbuild/win32-ia32": "0.19.11", - "@esbuild/win32-x64": "0.19.11" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/event-target-shim": { @@ -963,6 +1483,7 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -981,6 +1502,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -993,10 +1515,11 @@ } }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -1016,6 +1539,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -1025,10 +1549,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1037,10 +1562,11 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1055,6 +1581,7 @@ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dev": true, + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -1066,7 +1593,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -1074,6 +1602,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1087,6 +1616,8 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1095,7 +1626,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1116,6 +1649,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1128,6 +1662,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1136,12 +1671,13 @@ } }, "node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, + "license": "MIT", "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", + "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", "ignore": "^5.2.4", "path-type": "^5.0.0", @@ -1156,10 +1692,12 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -1172,6 +1710,7 @@ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -1184,6 +1723,7 @@ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", "dev": true, + "license": "MIT", "dependencies": { "domelementtype": "1", "domhandler": "2.3", @@ -1193,10 +1733,11 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -1206,10 +1747,11 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -1223,6 +1765,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -1231,10 +1774,11 @@ } }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -1243,7 +1787,9 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -1253,19 +1799,23 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/inspect-custom-symbol": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/inspect-custom-symbol/-/inspect-custom-symbol-1.1.1.tgz", "integrity": "sha512-GOucsp9EcdlLdhPUyOTvQDnbFJtp2WBWZV1Jqe+mVnkJQBL3w96+fB84C+JL+EKXOspMdB0eMDQPDp5w9fkfZA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, + "license": "MIT", + "peer": true, "engines": { "node": ">= 0.10" } @@ -1275,6 +1825,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -1283,12 +1834,17 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1299,6 +1855,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1308,6 +1865,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1317,6 +1875,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -1329,6 +1888,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -1337,40 +1897,43 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsdom": { - "version": "23.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.1.0.tgz", - "integrity": "sha512-wRscu8dBFxi7O65Cvi0jFRDv0Qa7XEHPix8Qg/vlXHLAMQsRWV1EDeQHBermzXf4Dt7JtFgBLbva3iTcBZDXEQ==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, + "license": "MIT", "dependencies": { - "cssstyle": "^4.0.1", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.16.0", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -1390,6 +1953,7 @@ "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.6.tgz", "integrity": "sha512-IVdB4G0NTTeQZrBoM8C5JFVLjV2KtZ9APgybDA1MK73xb09qFs0jCXyQLnCOp1cSZZZbvhq/6mfXHUTaDkffuQ==", "dev": true, + "license": "MIT", "dependencies": { "cli": "~1.0.0", "console-browserify": "1.1.x", @@ -1407,34 +1971,42 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/just-flatten-it/-/just-flatten-it-2.2.1.tgz", "integrity": "sha512-VwvlzikphspzZL38LiZpoBsFGQy6MnmXYekBeZA8lSNwgSC87zA3a93bCZKkDuOM+djMZhfjd3lXAZyxficKCg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/just-zip-it": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/just-zip-it/-/just-zip-it-2.3.1.tgz", "integrity": "sha512-h8Y3DAVTZRP3Weq7btWYfkYHQGhxiuKzfOO7Ec+x8XaDcBvbOsC2jIdezC6tEzbt+A4fTJTREnj3gF5DyMkFfw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-update-async-hook": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/log-update-async-hook/-/log-update-async-hook-2.0.7.tgz", "integrity": "sha512-V9KpD1AZUBd/oiZ+/Xsgd5rRP9awhgtRiDv5Am4VQCixiDnAbXMdt/yKz41kCzYZtVbwC6YCxnWEF3zjNEwktA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.3.2", "async-exit-hook": "^1.1.2", @@ -1447,17 +2019,19 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -1469,6 +2043,7 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -1478,6 +2053,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -1490,6 +2066,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -1499,6 +2076,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1511,20 +2089,22 @@ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.4.tgz", - "integrity": "sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", "dev": true, "funding": [ { @@ -1532,6 +2112,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.js" }, @@ -1544,6 +2125,7 @@ "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.1.0.tgz", "integrity": "sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==", "dev": true, + "license": "ISC", "dependencies": { "picocolors": "^1.0.0" } @@ -1563,6 +2145,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } @@ -1572,6 +2155,7 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, + "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -1586,27 +2170,30 @@ } }, "node_modules/nodejsscript": { - "version": "1.0.0", - "resolved": "git+ssh://git@github.com/jaandrle/nodejsscript.git#0e368f4f74b4c8f7a30f1f595128b5d0b823015d", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nodejsscript/-/nodejsscript-1.0.2.tgz", + "integrity": "sha512-ofGiso5StUjQbM0lG0dwumJSQMstaU8NZ6CWsGcX4bbTTQGnTvf7GI/2jyG3UqsF79VJTLHHLPVwoqJ+Wn9/rQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/sade": "^1.7.4", - "@types/shelljs": "^0.8.11", - "abort-controller": "^3.0.0", - "css-in-console": "^2.0.0", - "log-update-async-hook": "^2.0.7", - "node-fetch": "^3.3.0", - "sade": "^1.8.1", - "shell-escape-tag": "^2.0.2", - "shelljs": "^0.8.5" + "@types/sade": "~1.7", + "@types/shelljs": "~0.8", + "abort-controller": "~3.0", + "css-in-console": "~2.0", + "log-update-async-hook": "~2.0", + "node-fetch": "~3.3", + "sade": "~1.8", + "shell-escape-tag": "~2.0" }, "bin": { "njs": "bin/index.mjs", "nodejsscript": "bin/index.mjs" }, "engines": { - "node": ">= 16.0.0" + "node": ">= 18.0.0" + }, + "peerDependencies": { + "shelljs": "~0.8" } }, "node_modules/normalize-path": { @@ -1614,21 +2201,24 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true, + "license": "MIT" }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -1638,6 +2228,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^1.0.0" }, @@ -1646,12 +2237,13 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", "dev": true, + "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -1662,6 +2254,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -1674,6 +2267,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1682,13 +2276,16 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -1697,16 +2294,18 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -1714,27 +2313,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -1753,13 +2341,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -1772,6 +2362,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -1784,6 +2375,7 @@ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, + "peer": true, "dependencies": { "resolve": "^1.1.6" }, @@ -1791,17 +2383,13 @@ "node": ">= 0.10" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -1819,16 +2407,18 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" }, "node_modules/run-parallel": { "version": "1.2.0", @@ -1849,6 +2439,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -1858,6 +2449,7 @@ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "dev": true, + "license": "MIT", "dependencies": { "mri": "^1.1.0" }, @@ -1869,13 +2461,15 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, + "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" }, @@ -1888,6 +2482,7 @@ "resolved": "https://registry.npmjs.org/shell-escape-tag/-/shell-escape-tag-2.0.2.tgz", "integrity": "sha512-kqmtJG6VzTahZl8Y3384ldskA9rzoEMdXLoMEBAq9334/UDdmfWl3OtmrGJPlVcyXvcSy3poDKka57gMxskMPw==", "dev": true, + "license": "Artistic-2.0", "dependencies": { "any-shell-escape": "^0.1.1", "inspect-custom-symbol": "^1.1.1", @@ -1900,6 +2495,8 @@ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, + "license": "BSD-3-Clause", + "peer": true, "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -1913,15 +2510,16 @@ } }, "node_modules/size-limit": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-11.0.1.tgz", - "integrity": "sha512-6L80ocVspWPrhIRg8kPl41VypqTGH8/lu9e6TJiSJpkNLtOR2h/EEqdAO/wNJOv/sUVtjX+lVEWrzBpItGP+gQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-11.0.3.tgz", + "integrity": "sha512-opXC+dOlwaKMyCx89WQq5J+LE+WdqtAFwaNwKNJv8xTCNMq6NIIY5LdayTRuRWWdsQM7hvI27afjtofN/m0gIw==", "dev": true, + "license": "MIT", "dependencies": { "bytes-iec": "^3.1.1", - "chokidar": "^3.5.3", - "globby": "^14.0.0", - "lilconfig": "^3.0.0", + "chokidar": "^3.6.0", + "globby": "^14.0.1", + "lilconfig": "^3.1.1", "nanospinner": "^1.1.0", "picocolors": "^1.0.0" }, @@ -1937,6 +2535,7 @@ "resolved": "https://registry.npmjs.org/size-limit-node-esbuild/-/size-limit-node-esbuild-0.3.0.tgz", "integrity": "sha512-wgKcHikiJLnz9pTzZsJXBUaFzWnZsVftmHLKu6eJJx2+wh0EgyzIPhOad/FFVBhErDacAmR4FYD3tgEagr033g==", "dev": true, + "license": "MIT", "dependencies": { "nanoid": "^5.0.3", "size-limit": "^10.0.2", @@ -1954,6 +2553,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -1963,6 +2563,7 @@ "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-10.0.3.tgz", "integrity": "sha512-5k1k2Kykueq5K/PJQclKx2GS1prz4WNNvm+x5CQ2oWLHwmuFnb1z1g412O9aoOFqafXicJTZgZHXRyIe2GZQfA==", "dev": true, + "license": "MIT", "dependencies": { "bytes-iec": "^3.1.1", "chokidar": "^3.5.3", @@ -1983,6 +2584,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -1994,13 +2596,15 @@ "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2015,6 +2619,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -2027,6 +2632,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", "dev": true, + "license": "MIT", "bin": { "strip-json-comments": "cli.js" }, @@ -2039,6 +2645,8 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", + "peer": true, "engines": { "node": ">= 0.4" }, @@ -2050,13 +2658,35 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/tldts": { + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.51.tgz", + "integrity": "sha512-33lfQoL0JsDogIbZ8fgRyvv77GnRtwkNE/MOKocwUgPO1WrSfsq7+vQRKxRQZai5zd+zg97Iv9fpFQSzHyWdLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.51" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.51.tgz", + "integrity": "sha512-bu9oCYYWC1iRjx+3UnAjqCsfrWNZV1ghNQf49b3w5xE8J/tNShHTzp5syWJfwGH+pxUgTTLUnzHnfuydW7wmbg==", + "dev": true, + "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -2065,18 +2695,16 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" + "node": ">=16" } }, "node_modules/tr46": { @@ -2084,6 +2712,7 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, @@ -2092,16 +2721,18 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2114,6 +2745,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "tsc": "bin/tsc", @@ -2124,16 +2756,18 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2141,30 +2775,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, + "license": "MIT", "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -2173,10 +2789,11 @@ } }, "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -2186,6 +2803,7 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -2195,6 +2813,7 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, + "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" }, @@ -2207,6 +2826,7 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -2216,6 +2836,7 @@ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, + "license": "MIT", "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -2229,6 +2850,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2245,13 +2867,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -2273,6 +2897,7 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18" } @@ -2281,7 +2906,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "dev": true, + "license": "MIT" } } } diff --git a/package.json b/package.json index 4c9980c..fa01659 100644 --- a/package.json +++ b/package.json @@ -62,14 +62,12 @@ "limit": "10.5 kB", "gzip": false, "brotli": false - }, { "path": "./signals.js", "limit": "12 kB", "gzip": false, "brotli": false - }, { "path": "./index-with-signals.js", @@ -95,12 +93,12 @@ "typescript" ], "devDependencies": { - "@size-limit/preset-small-lib": "^11.0.1", - "dts-bundler": "^0.1.0", - "esbuild": "^0.19.9", - "jsdom": "^23.0.1", - "jshint": "^2.13.6", - "nodejsscript": "github:jaandrle/nodejsscript#dev-v1", - "size-limit-node-esbuild": "^0.3.0" + "@size-limit/preset-small-lib": "~11.0", + "dts-bundler": "~0.1", + "esbuild": "~0.24", + "jsdom": "~25.0", + "jshint": "~2.13", + "nodejsscript": "^1.0.2", + "size-limit-node-esbuild": "~0.3" } } diff --git a/signals.d.ts b/signals.d.ts index 517f83b..ebae316 100644 --- a/signals.d.ts +++ b/signals.d.ts @@ -55,7 +55,7 @@ interface signal{ * */ el(signal: Signal, el: (v: S)=> Element | Element[] | DocumentFragment): DocumentFragment; - observedAttributes(custom_element: HTMLElement): Record>; + observedAttributes(custom_element: HTMLElement): Record>; } export const signal: signal; export const S: signal; diff --git a/src/dom.js b/src/dom.js index fc56e1a..4c5daa5 100644 --- a/src/dom.js +++ b/src/dom.js @@ -67,18 +67,23 @@ export function createElement(tag, attributes, ...addons){ } import { hasOwn } from "./helpers.js"; /** @param {HTMLElement} element @param {HTMLElement} [root] */ -export function simulateSlots(element, root= element, mapper= undefined){ +export function simulateSlots(element, root, mapper){ + if(typeof root!=="object"){ + mapper= root; + root= element; + } 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= env.D.createDocumentFragment(); for(const el of els){ - if(!el || !el.slot){ if(has_d) d.appendChild(el); continue; } + if(!el || !el.slot){ if(has_d) d.append(el); continue; } const name= el.slot; const slot= slots[name]; elementAttribute(el, "remove", "slot");