tina4js 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs.js +1 -1
- package/dist/core.es.js +82 -76
- package/dist/debug.cjs.js +18 -18
- package/dist/debug.es.js +72 -63
- package/dist/index.es.js +1 -1
- package/dist/signal.cjs.js +1 -1
- package/dist/signal.es.js +71 -59
- package/package.json +1 -1
- package/readme.md +5 -0
package/dist/core.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./signal.cjs.js"),N=require("./component.cjs.js"),_=new WeakMap,m="t4:";function b(t,...e){let n=_.get(t);if(!n){n=document.createElement("template");let f="";for(let i=0;i<t.length;i++)f+=t[i],i<e.length&&(E(f)?f+=`__t4_${i}__`:f+=`<!--${m}${i}-->`);n.innerHTML=f,_.set(t,n)}const o=n.content.cloneNode(!0),c=C(o);for(const{marker:f,index:i}of c)S(f,e[i]);const r=y(o);for(const f of r)T(f,e);return o}function C(t){const e=[];return p(t,n=>{if(n.nodeType===8){const o=n.data;if(o&&o.startsWith(m)){const c=parseInt(o.slice(m.length),10);e.push({marker:n,index:c})}}}),e}function y(t){const e=[];return p(t,n=>{n.nodeType===1&&e.push(n)}),e}function p(t,e){const n=t.childNodes;for(let o=0;o<n.length;o++){const c=n[o];e(c),p(c,e)}}function S(t,e){const n=t.parentNode;if(n)if(s.isSignal(e)){const o=document.createTextNode("");n.replaceChild(o,t),s.effect(()=>{o.data=String(e.value??"")})}else if(typeof e=="function"){const o=document.createComment("");n.replaceChild(o,t);let c=[],r=[];s.effect(()=>{var g;for(const d of r)d();r=[];const f=[],i=s._getEffectCollector();s._setEffectCollector(f);const l=e();s._setEffectCollector(i),r=f;for(const d of c)(g=d.parentNode)==null||g.removeChild(d);c=[];const a=h(l),u=o.parentNode;if(u)for(const d of a)u.insertBefore(d,o),c.push(d)})}else if(A(e))n.replaceChild(e,t);else if(e instanceof Node)n.replaceChild(e,t);else if(Array.isArray(e)){const o=document.createDocumentFragment();for(const c of e){const r=h(c);for(const f of r)o.appendChild(f)}n.replaceChild(o,t)}else{const o=document.createTextNode(String(e??""));n.replaceChild(o,t)}}function T(t,e){const n=[];for(const o of Array.from(t.attributes)){const c=o.name,r=o.value;if(c.startsWith("@")){const i=c.slice(1),l=r.match(/__t4_(\d+)__/);if(l){const a=e[parseInt(l[1],10)];typeof a=="function"&&t.addEventListener(i,a)}n.push(c);continue}if(c.startsWith("?")){const i=c.slice(1),l=r.match(/__t4_(\d+)__/);if(l){const a=e[parseInt(l[1],10)];if(s.isSignal(a)){const u=a;s.effect(()=>{u.value?t.setAttribute(i,""):t.removeAttribute(i)})}else a&&t.setAttribute(i,"")}n.push(c);continue}if(c.startsWith(".")){const i=c.slice(1),l=r.match(/__t4_(\d+)__/);if(l){const a=e[parseInt(l[1],10)];s.isSignal(a)?s.effect(()=>{t[i]=a.value}):t[i]=a}n.push(c);continue}const f=r.match(/__t4_(\d+)__/);if(f){const i=e[parseInt(f[1],10)];if(s.isSignal(i)){const l=i;s.effect(()=>{t.setAttribute(c,String(l.value??""))})}else typeof i=="function"?s.effect(()=>{t.setAttribute(c,String(i()??""))}):t.setAttribute(c,String(i??""))}}for(const o of n)t.removeAttribute(o)}function h(t){if(t==null||t===!1)return[];if(A(t))return Array.from(t.childNodes);if(t instanceof Node)return[t];if(Array.isArray(t)){const e=[];for(const n of t)e.push(...h(n));return e}return[document.createTextNode(String(t))]}function A(t){return t!=null&&typeof t=="object"&&t.nodeType===11}function E(t){let e=!1,n=!1,o=!1;for(let c=0;c<t.length;c++){const r=t[c];r==="<"&&!e&&!n&&(o=!0),r===">"&&!e&&!n&&(o=!1),o&&(r==='"'&&!e&&(n=!n),r==="'"&&!n&&(e=!e))}return o}exports.batch=s.batch;exports.computed=s.computed;exports.effect=s.effect;exports.isSignal=s.isSignal;exports.signal=s.signal;exports.Tina4Element=N.Tina4Element;exports.html=b;
|
package/dist/core.es.js
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { i as
|
|
2
|
-
import { b as
|
|
3
|
-
import { T as
|
|
4
|
-
const
|
|
5
|
-
function
|
|
6
|
-
let n =
|
|
1
|
+
import { i as p, e as d, a as b, d as A } from "./signal.es.js";
|
|
2
|
+
import { b as w, c as M, s as R } from "./signal.es.js";
|
|
3
|
+
import { T as F } from "./component.es.js";
|
|
4
|
+
const N = /* @__PURE__ */ new WeakMap(), u = "t4:";
|
|
5
|
+
function W(t, ...e) {
|
|
6
|
+
let n = N.get(t);
|
|
7
7
|
if (!n) {
|
|
8
8
|
n = document.createElement("template");
|
|
9
|
-
let
|
|
10
|
-
for (let
|
|
11
|
-
|
|
12
|
-
n.innerHTML =
|
|
9
|
+
let i = "";
|
|
10
|
+
for (let r = 0; r < t.length; r++)
|
|
11
|
+
i += t[r], r < e.length && (S(i) ? i += `__t4_${r}__` : i += `<!--${u}${r}-->`);
|
|
12
|
+
n.innerHTML = i, N.set(t, n);
|
|
13
13
|
}
|
|
14
|
-
const o = n.content.cloneNode(!0), s =
|
|
15
|
-
for (const { marker:
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
for (const
|
|
19
|
-
|
|
14
|
+
const o = n.content.cloneNode(!0), s = y(o);
|
|
15
|
+
for (const { marker: i, index: r } of s)
|
|
16
|
+
x(i, e[r]);
|
|
17
|
+
const c = T(o);
|
|
18
|
+
for (const i of c)
|
|
19
|
+
E(i, e);
|
|
20
20
|
return o;
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function y(t) {
|
|
23
23
|
const e = [];
|
|
24
|
-
return
|
|
24
|
+
return _(t, (n) => {
|
|
25
25
|
if (n.nodeType === 8) {
|
|
26
26
|
const o = n.data;
|
|
27
|
-
if (o && o.startsWith(
|
|
28
|
-
const s = parseInt(o.slice(
|
|
27
|
+
if (o && o.startsWith(u)) {
|
|
28
|
+
const s = parseInt(o.slice(u.length), 10);
|
|
29
29
|
e.push({ marker: n, index: s });
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}), e;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function T(t) {
|
|
35
35
|
const e = [];
|
|
36
|
-
return
|
|
36
|
+
return _(t, (n) => {
|
|
37
37
|
n.nodeType === 1 && e.push(n);
|
|
38
38
|
}), e;
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function _(t, e) {
|
|
41
41
|
const n = t.childNodes;
|
|
42
42
|
for (let o = 0; o < n.length; o++) {
|
|
43
43
|
const s = n[o];
|
|
44
|
-
e(s),
|
|
44
|
+
e(s), _(s, e);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
function
|
|
47
|
+
function x(t, e) {
|
|
48
48
|
const n = t.parentNode;
|
|
49
49
|
if (n)
|
|
50
|
-
if (
|
|
50
|
+
if (p(e)) {
|
|
51
51
|
const o = document.createTextNode("");
|
|
52
52
|
n.replaceChild(o, t), d(() => {
|
|
53
53
|
o.data = String(e.value ?? "");
|
|
@@ -55,25 +55,31 @@ function b(t, e) {
|
|
|
55
55
|
} else if (typeof e == "function") {
|
|
56
56
|
const o = document.createComment("");
|
|
57
57
|
n.replaceChild(o, t);
|
|
58
|
-
let s = [];
|
|
58
|
+
let s = [], c = [];
|
|
59
59
|
d(() => {
|
|
60
|
-
var
|
|
60
|
+
var g;
|
|
61
|
+
for (const l of c) l();
|
|
62
|
+
c = [];
|
|
63
|
+
const i = [], r = b();
|
|
64
|
+
A(i);
|
|
61
65
|
const f = e();
|
|
62
|
-
|
|
66
|
+
A(r), c = i;
|
|
67
|
+
for (const l of s) (g = l.parentNode) == null || g.removeChild(l);
|
|
63
68
|
s = [];
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
const a = h(f), m = o.parentNode;
|
|
70
|
+
if (m)
|
|
71
|
+
for (const l of a)
|
|
72
|
+
m.insertBefore(l, o), s.push(l);
|
|
67
73
|
});
|
|
68
|
-
} else if (
|
|
74
|
+
} else if (C(e))
|
|
69
75
|
n.replaceChild(e, t);
|
|
70
76
|
else if (e instanceof Node)
|
|
71
77
|
n.replaceChild(e, t);
|
|
72
78
|
else if (Array.isArray(e)) {
|
|
73
79
|
const o = document.createDocumentFragment();
|
|
74
80
|
for (const s of e) {
|
|
75
|
-
const
|
|
76
|
-
for (const
|
|
81
|
+
const c = h(s);
|
|
82
|
+
for (const i of c) o.appendChild(i);
|
|
77
83
|
}
|
|
78
84
|
n.replaceChild(o, t);
|
|
79
85
|
} else {
|
|
@@ -81,88 +87,88 @@ function b(t, e) {
|
|
|
81
87
|
n.replaceChild(o, t);
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
|
-
function
|
|
90
|
+
function E(t, e) {
|
|
85
91
|
const n = [];
|
|
86
92
|
for (const o of Array.from(t.attributes)) {
|
|
87
|
-
const s = o.name,
|
|
93
|
+
const s = o.name, c = o.value;
|
|
88
94
|
if (s.startsWith("@")) {
|
|
89
|
-
const
|
|
90
|
-
if (
|
|
91
|
-
const
|
|
92
|
-
typeof
|
|
95
|
+
const r = s.slice(1), f = c.match(/__t4_(\d+)__/);
|
|
96
|
+
if (f) {
|
|
97
|
+
const a = e[parseInt(f[1], 10)];
|
|
98
|
+
typeof a == "function" && t.addEventListener(r, a);
|
|
93
99
|
}
|
|
94
100
|
n.push(s);
|
|
95
101
|
continue;
|
|
96
102
|
}
|
|
97
103
|
if (s.startsWith("?")) {
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
const
|
|
104
|
+
const r = s.slice(1), f = c.match(/__t4_(\d+)__/);
|
|
105
|
+
if (f) {
|
|
106
|
+
const a = e[parseInt(f[1], 10)];
|
|
107
|
+
if (p(a)) {
|
|
108
|
+
const m = a;
|
|
103
109
|
d(() => {
|
|
104
|
-
|
|
110
|
+
m.value ? t.setAttribute(r, "") : t.removeAttribute(r);
|
|
105
111
|
});
|
|
106
112
|
} else
|
|
107
|
-
|
|
113
|
+
a && t.setAttribute(r, "");
|
|
108
114
|
}
|
|
109
115
|
n.push(s);
|
|
110
116
|
continue;
|
|
111
117
|
}
|
|
112
118
|
if (s.startsWith(".")) {
|
|
113
|
-
const
|
|
114
|
-
if (
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
t[
|
|
118
|
-
}) : t[
|
|
119
|
+
const r = s.slice(1), f = c.match(/__t4_(\d+)__/);
|
|
120
|
+
if (f) {
|
|
121
|
+
const a = e[parseInt(f[1], 10)];
|
|
122
|
+
p(a) ? d(() => {
|
|
123
|
+
t[r] = a.value;
|
|
124
|
+
}) : t[r] = a;
|
|
119
125
|
}
|
|
120
126
|
n.push(s);
|
|
121
127
|
continue;
|
|
122
128
|
}
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
127
|
-
const
|
|
129
|
+
const i = c.match(/__t4_(\d+)__/);
|
|
130
|
+
if (i) {
|
|
131
|
+
const r = e[parseInt(i[1], 10)];
|
|
132
|
+
if (p(r)) {
|
|
133
|
+
const f = r;
|
|
128
134
|
d(() => {
|
|
129
|
-
t.setAttribute(s, String(
|
|
135
|
+
t.setAttribute(s, String(f.value ?? ""));
|
|
130
136
|
});
|
|
131
|
-
} else typeof
|
|
132
|
-
t.setAttribute(s, String(
|
|
133
|
-
}) : t.setAttribute(s, String(
|
|
137
|
+
} else typeof r == "function" ? d(() => {
|
|
138
|
+
t.setAttribute(s, String(r() ?? ""));
|
|
139
|
+
}) : t.setAttribute(s, String(r ?? ""));
|
|
134
140
|
}
|
|
135
141
|
}
|
|
136
142
|
for (const o of n) t.removeAttribute(o);
|
|
137
143
|
}
|
|
138
|
-
function
|
|
144
|
+
function h(t) {
|
|
139
145
|
if (t == null || t === !1) return [];
|
|
140
|
-
if (
|
|
146
|
+
if (C(t)) return Array.from(t.childNodes);
|
|
141
147
|
if (t instanceof Node) return [t];
|
|
142
148
|
if (Array.isArray(t)) {
|
|
143
149
|
const e = [];
|
|
144
|
-
for (const n of t) e.push(...
|
|
150
|
+
for (const n of t) e.push(...h(n));
|
|
145
151
|
return e;
|
|
146
152
|
}
|
|
147
153
|
return [document.createTextNode(String(t))];
|
|
148
154
|
}
|
|
149
|
-
function
|
|
155
|
+
function C(t) {
|
|
150
156
|
return t != null && typeof t == "object" && t.nodeType === 11;
|
|
151
157
|
}
|
|
152
|
-
function
|
|
158
|
+
function S(t) {
|
|
153
159
|
let e = !1, n = !1, o = !1;
|
|
154
160
|
for (let s = 0; s < t.length; s++) {
|
|
155
|
-
const
|
|
156
|
-
|
|
161
|
+
const c = t[s];
|
|
162
|
+
c === "<" && !e && !n && (o = !0), c === ">" && !e && !n && (o = !1), o && (c === '"' && !e && (n = !n), c === "'" && !n && (e = !e));
|
|
157
163
|
}
|
|
158
164
|
return o;
|
|
159
165
|
}
|
|
160
166
|
export {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
F as Tina4Element,
|
|
168
|
+
w as batch,
|
|
169
|
+
M as computed,
|
|
164
170
|
d as effect,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
W as html,
|
|
172
|
+
p as isSignal,
|
|
173
|
+
R as signal
|
|
168
174
|
};
|
package/dist/debug.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("./signal.cjs.js"),A=require("./component.cjs.js"),x=require("./index.cjs.js"),y=require("./api.cjs.js"),l=[],b={add(t,o){const e=t._debugInfo;l.push({ref:new WeakRef(t),label:o,createdAt:(e==null?void 0:e.createdAt)??Date.now(),updateCount:0,subs:new WeakRef((e==null?void 0:e.subs)??new Set)})},onUpdate(t){for(const o of l)if(o.ref.deref()===t){o.updateCount++;break}},getAll(){var o;const t=[];for(let e=l.length-1;e>=0;e--){const n=l[e],r=n.ref.deref();if(!r){l.splice(e,1);continue}const s=n.subs.deref();t.push({label:n.label,value:r.peek(),subscriberCount:s?s.size:0,updateCount:((o=r._debugInfo)==null?void 0:o.updateCount)??n.updateCount,alive:!0})}return t},get count(){return l.length}},a=[],h={onMount(t){a.push({ref:new WeakRef(t),tagName:t.tagName.toLowerCase(),mountedAt:Date.now()})},onUnmount(t){const o=a.findIndex(e=>e.ref.deref()===t);o>=0&&a.splice(o,1)},getAll(){const t=[];for(let o=a.length-1;o>=0;o--){const e=a[o],n=e.ref.deref();if(!n||!n.isConnected){a.splice(o,1);continue}const r={},s=n.constructor;if(s.props)for(const i of Object.keys(s.props))try{r[i]=n.prop(i).peek()}catch{}t.push({tagName:e.tagName,props:r,alive:!0})}return t},get count(){return a.length}},d=[],D=50;let f=null;const p={setGetRoutes(t){f=t},getRegisteredRoutes(){return f?f():[]},onNavigate(t){d.unshift({path:t.path,pattern:t.pattern,params:t.params,durationMs:t.durationMs,timestamp:Date.now()}),d.length>D&&d.pop()},getHistory(){return d},get count(){return d.length}};let M=0;const c=[],m=new Map,E=100,g={onRequest(t){var r;const o=++M,e={id:o,method:t.method??"GET",url:"",hasAuth:!!((r=t.headers)!=null&&r.Authorization),timestamp:Date.now(),pending:!0},n=String(o);m.set(n,e),c.unshift(e),c.length>E&&c.pop()},onResponse(t){for(const[o,e]of m)if(e.pending){e.status=t.status,e.durationMs=Date.now()-e.timestamp,e.pending=!1,t.ok||(e.error=`HTTP ${t.status}`),m.delete(o);break}},getLog(){return c},get count(){return c.length}},w=`
|
|
2
2
|
:host {
|
|
3
3
|
all: initial;
|
|
4
4
|
position: fixed;
|
|
@@ -204,36 +204,36 @@ tr:hover td { background: rgba(255,255,255,0.02); }
|
|
|
204
204
|
border-radius: 50%;
|
|
205
205
|
background: #66bb6a;
|
|
206
206
|
}
|
|
207
|
-
`;function
|
|
207
|
+
`;function L(t){if(t==null)return{text:String(t),cls:"val-null"};if(typeof t=="string")return{text:`"${t.length>30?t.slice(0,30)+"...":t}"`,cls:"val-string"};if(typeof t=="number")return{text:String(t),cls:"val-number"};if(typeof t=="boolean")return{text:String(t),cls:"val-boolean"};if(Array.isArray(t))return{text:`Array(${t.length})`,cls:"val-object"};if(typeof t=="object")try{return{text:JSON.stringify(t).slice(0,40),cls:"val-object"}}catch{}return{text:String(t),cls:"val-object"}}function j(){const t=b.getAll();if(t.length===0)return'<div class="t4-empty">No signals tracked yet.<br>Signals created after debug is enabled will appear here.</div>';let o="";for(let e=0;e<t.length;e++){const n=t[e],{text:r,cls:s}=L(n.value);o+=`<tr>
|
|
208
208
|
<td>${n.label||`signal_${e}`}</td>
|
|
209
|
-
<td><span class="${s}">${
|
|
209
|
+
<td><span class="${s}">${H(r)}</span></td>
|
|
210
210
|
<td>${n.subscriberCount}</td>
|
|
211
211
|
<td>${n.updateCount}</td>
|
|
212
212
|
</tr>`}return`<table>
|
|
213
213
|
<thead><tr><th>Label</th><th>Value</th><th>Subs</th><th>Updates</th></tr></thead>
|
|
214
214
|
<tbody>${o}</tbody>
|
|
215
|
-
</table>`}function
|
|
216
|
-
<td><${
|
|
217
|
-
<td>${
|
|
215
|
+
</table>`}function H(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function z(){const t=h.getAll();if(t.length===0)return'<div class="t4-empty">No Tina4Elements mounted.<br>Custom elements extending Tina4Element will appear here.</div>';let o="";for(const e of t){const n=Object.keys(e.props).length>0?Object.entries(e.props).map(([r,s])=>`${r}=${JSON.stringify(s)??"null"}`).join(", "):"—";o+=`<tr>
|
|
216
|
+
<td><${v(e.tagName)}></td>
|
|
217
|
+
<td>${v(n.length>60?n.slice(0,60)+"...":n)}</td>
|
|
218
218
|
</tr>`}return`<table>
|
|
219
219
|
<thead><tr><th>Element</th><th>Props</th></tr></thead>
|
|
220
220
|
<tbody>${o}</tbody>
|
|
221
|
-
</table>`}function
|
|
222
|
-
<td><span class="route-pattern">${
|
|
221
|
+
</table>`}function v(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function N(t){const o=t<1?"<1ms":`${Math.round(t)}ms`,e=t<5?"duration fast":t<50?"duration":t<200?"duration slow":"duration very-slow";return{text:o,cls:e}}function P(t){return new Date(t).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function I(){const t=p.getRegisteredRoutes(),o=p.getHistory();let e="";if(t.length>0){let n="";for(const r of t)n+=`<tr>
|
|
222
|
+
<td><span class="route-pattern">${_(r.pattern)}</span></td>
|
|
223
223
|
<td>${r.hasGuard?"Yes":"—"}</td>
|
|
224
224
|
</tr>`;e+=`<table>
|
|
225
225
|
<thead><tr><th>Pattern</th><th>Guard</th></tr></thead>
|
|
226
226
|
<tbody>${n}</tbody>
|
|
227
|
-
</table>`}if(o.length>0){e+='<div style="margin-top:8px;padding-top:8px;border-top:1px solid #333;">';let n="";for(const r of o){const{text:s,cls:i}=
|
|
228
|
-
<td>${
|
|
229
|
-
<td>${
|
|
230
|
-
<td>${
|
|
227
|
+
</table>`}if(o.length>0){e+='<div style="margin-top:8px;padding-top:8px;border-top:1px solid #333;">';let n="";for(const r of o){const{text:s,cls:i}=N(r.durationMs),T=Object.keys(r.params).length>0?Object.entries(r.params).map(([S,C])=>`<span class="route-param">${S}=${C}</span>`).join(" "):"";n+=`<tr>
|
|
228
|
+
<td>${P(r.timestamp)}</td>
|
|
229
|
+
<td>${_(r.path)}</td>
|
|
230
|
+
<td>${T||"—"}</td>
|
|
231
231
|
<td><span class="${i}">${s}</span></td>
|
|
232
232
|
</tr>`}e+=`<table>
|
|
233
233
|
<thead><tr><th>Time</th><th>Path</th><th>Params</th><th>Duration</th></tr></thead>
|
|
234
234
|
<tbody>${n}</tbody>
|
|
235
|
-
</table></div>`}else t.length===0&&(e='<div class="t4-empty">No routes registered yet.</div>');return e}function
|
|
236
|
-
<td>${
|
|
235
|
+
</table></div>`}else t.length===0&&(e='<div class="t4-empty">No routes registered yet.</div>');return e}function _(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function q(t){if(t===void 0)return{text:"...",cls:"status-pending"};const o=t<1?"<1ms":`${Math.round(t)}ms`,e=t<100?"duration fast":t<500?"duration":t<2e3?"duration slow":"duration very-slow";return{text:o,cls:e}}function O(t,o){return o?{text:"pending",cls:"status-pending"}:t?t>=200&&t<300?{text:String(t),cls:"status-ok"}:{text:String(t),cls:"status-err"}:{text:"—",cls:""}}function U(t){return new Date(t).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function G(){const t=g.getLog();if(t.length===0)return'<div class="t4-empty">No API calls yet.<br>Requests made via api.get/post/put/patch/delete will appear here.</div>';let o="";for(const e of t){const{text:n,cls:r}=O(e.status,e.pending),{text:s,cls:i}=q(e.durationMs);o+=`<tr>
|
|
236
|
+
<td>${U(e.timestamp)}</td>
|
|
237
237
|
<td><strong>${e.method}</strong></td>
|
|
238
238
|
<td>${B(e.url||"(url)")}</td>
|
|
239
239
|
<td><span class="${r}">${n}</span></td>
|
|
@@ -242,8 +242,8 @@ tr:hover td { background: rgba(255,255,255,0.02); }
|
|
|
242
242
|
</tr>`}return`<table>
|
|
243
243
|
<thead><tr><th>Time</th><th>Method</th><th>URL</th><th>Status</th><th>Duration</th><th>Auth</th></tr></thead>
|
|
244
244
|
<tbody>${o}</tbody>
|
|
245
|
-
</table>`}function B(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}class
|
|
246
|
-
<style>${
|
|
245
|
+
</table>`}function B(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}class F extends HTMLElement{constructor(){super(),this._visible=!0,this._activeTab="signals",this._refreshTimer=null,this._shadow=this.attachShadow({mode:"open"})}connectedCallback(){this._render(),this._startAutoRefresh()}disconnectedCallback(){this._stopAutoRefresh()}toggle(){this._visible=!this._visible,this._render()}show(){this._visible=!0,this._render()}hide(){this._visible=!1,this._render()}_startAutoRefresh(){this._refreshTimer=window.setInterval(()=>{this._visible&&this._renderBody()},1e3)}_stopAutoRefresh(){this._refreshTimer!==null&&(clearInterval(this._refreshTimer),this._refreshTimer=null)}_switchTab(o){this._activeTab=o,this._render()}_getTabContent(){switch(this._activeTab){case"signals":return j();case"components":return z();case"routes":return I();case"api":return G()}}_renderBody(){const o=this._shadow.querySelector(".t4-body");o&&(o.innerHTML=this._getTabContent()),this._updateTabCounts()}_updateTabCounts(){const o={signals:b.count,components:h.count,routes:p.count,api:g.count};for(const[e,n]of Object.entries(o)){const r=this._shadow.querySelector(`[data-tab-count="${e}"]`);r&&(r.textContent=n>0?`(${n})`:"")}}_render(){var n,r;const o=[{id:"signals",label:"Signals"},{id:"components",label:"Components"},{id:"routes",label:"Routes"},{id:"api",label:"API"}];if(!this._visible){this._shadow.innerHTML=`
|
|
246
|
+
<style>${w}</style>
|
|
247
247
|
<div class="t4-mini" id="t4-mini">
|
|
248
248
|
<span class="t4-mini-dot"></span>
|
|
249
249
|
T4 Debug
|
|
@@ -251,7 +251,7 @@ tr:hover td { background: rgba(255,255,255,0.02); }
|
|
|
251
251
|
`,(n=this._shadow.getElementById("t4-mini"))==null||n.addEventListener("click",()=>this.show());return}const e=o.map(s=>`<button class="t4-tab${this._activeTab===s.id?" active":""}" data-tab="${s.id}">
|
|
252
252
|
${s.label}<span class="t4-tab-count" data-tab-count="${s.id}"></span>
|
|
253
253
|
</button>`).join("");this._shadow.innerHTML=`
|
|
254
|
-
<style>${
|
|
254
|
+
<style>${w}</style>
|
|
255
255
|
<div class="t4-debug">
|
|
256
256
|
<div class="t4-header">
|
|
257
257
|
<div>
|
|
@@ -265,4 +265,4 @@ tr:hover td { background: rgba(255,255,255,0.02); }
|
|
|
265
265
|
<div class="t4-tabs">${e}</div>
|
|
266
266
|
<div class="t4-body">${this._getTabContent()}</div>
|
|
267
267
|
</div>
|
|
268
|
-
`,(r=this._shadow.getElementById("t4-close"))==null||r.addEventListener("click",()=>this.hide());for(const s of this._shadow.querySelectorAll(".t4-tab"))s.addEventListener("click",()=>{this._switchTab(s.dataset.tab)});this._updateTabCounts()}}function V(){typeof customElements<"u"&&!customElements.get("tina4-debug")&&customElements.define("tina4-debug",
|
|
268
|
+
`,(r=this._shadow.getElementById("t4-close"))==null||r.addEventListener("click",()=>this.hide());for(const s of this._shadow.querySelectorAll(".t4-tab"))s.addEventListener("click",()=>{this._switchTab(s.dataset.tab)});this._updateTabCounts()}}function V(){typeof customElements<"u"&&!customElements.get("tina4-debug")&&customElements.define("tina4-debug",F)}let u=null,$=!1;function k(){$||($=!0,R.__setDebugSignalHooks((t,o)=>b.add(t,o),t=>b.onUpdate(t)),A.__setDebugComponentHooks(t=>h.onMount(t),t=>h.onUnmount(t)),p.setGetRoutes(x._getRoutes),x.router.on("change",t=>{p.onNavigate(t)}),y.api.intercept("request",t=>(g.onRequest(t),t)),y.api.intercept("response",t=>(g.onResponse(t),t)),typeof document<"u"&&(V(),u=document.createElement("tina4-debug"),document.body.appendChild(u),document.addEventListener("keydown",t=>{t.ctrlKey&&t.shiftKey&&t.key==="D"&&(t.preventDefault(),u==null||u.toggle())})),console.log("%c[tina4] %cDebug overlay enabled %c(Ctrl+Shift+D to toggle)","color:#00d4ff;font-weight:bold","color:#e0e0e0","color:#888"))}k();exports.enableDebug=k;
|
package/dist/debug.es.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { _ as
|
|
2
|
-
import { _ as
|
|
3
|
-
import { _ as
|
|
4
|
-
import { api as
|
|
5
|
-
const d = [],
|
|
1
|
+
import { _ as C } from "./signal.es.js";
|
|
2
|
+
import { _ as S } from "./component.es.js";
|
|
3
|
+
import { _ as R, a as A } from "./index.es.js";
|
|
4
|
+
import { api as x } from "./api.es.js";
|
|
5
|
+
const d = [], b = {
|
|
6
6
|
add(t, o) {
|
|
7
7
|
const e = t._debugInfo;
|
|
8
8
|
d.push({
|
|
@@ -43,7 +43,7 @@ const d = [], p = {
|
|
|
43
43
|
get count() {
|
|
44
44
|
return d.length;
|
|
45
45
|
}
|
|
46
|
-
}, a = [],
|
|
46
|
+
}, a = [], h = {
|
|
47
47
|
onMount(t) {
|
|
48
48
|
a.push({
|
|
49
49
|
ref: new WeakRef(t),
|
|
@@ -77,7 +77,16 @@ const d = [], p = {
|
|
|
77
77
|
get count() {
|
|
78
78
|
return a.length;
|
|
79
79
|
}
|
|
80
|
-
}, l = [], D = 50
|
|
80
|
+
}, l = [], D = 50;
|
|
81
|
+
let f = null;
|
|
82
|
+
const p = {
|
|
83
|
+
/** Set the function that reads registered routes (avoids direct import from router). */
|
|
84
|
+
setGetRoutes(t) {
|
|
85
|
+
f = t;
|
|
86
|
+
},
|
|
87
|
+
getRegisteredRoutes() {
|
|
88
|
+
return f ? f() : [];
|
|
89
|
+
},
|
|
81
90
|
onNavigate(t) {
|
|
82
91
|
l.unshift({
|
|
83
92
|
path: t.path,
|
|
@@ -94,11 +103,11 @@ const d = [], p = {
|
|
|
94
103
|
return l.length;
|
|
95
104
|
}
|
|
96
105
|
};
|
|
97
|
-
let
|
|
98
|
-
const c = [],
|
|
106
|
+
let E = 0;
|
|
107
|
+
const c = [], m = /* @__PURE__ */ new Map(), M = 100, g = {
|
|
99
108
|
onRequest(t) {
|
|
100
109
|
var r;
|
|
101
|
-
const o = ++
|
|
110
|
+
const o = ++E, e = {
|
|
102
111
|
id: o,
|
|
103
112
|
method: t.method ?? "GET",
|
|
104
113
|
url: "",
|
|
@@ -107,12 +116,12 @@ const c = [], g = /* @__PURE__ */ new Map(), E = 100, h = {
|
|
|
107
116
|
timestamp: Date.now(),
|
|
108
117
|
pending: !0
|
|
109
118
|
}, n = String(o);
|
|
110
|
-
|
|
119
|
+
m.set(n, e), c.unshift(e), c.length > M && c.pop();
|
|
111
120
|
},
|
|
112
121
|
onResponse(t) {
|
|
113
|
-
for (const [o, e] of
|
|
122
|
+
for (const [o, e] of m)
|
|
114
123
|
if (e.pending) {
|
|
115
|
-
e.status = t.status, e.durationMs = Date.now() - e.timestamp, e.pending = !1, t.ok || (e.error = `HTTP ${t.status}`),
|
|
124
|
+
e.status = t.status, e.durationMs = Date.now() - e.timestamp, e.pending = !1, t.ok || (e.error = `HTTP ${t.status}`), m.delete(o);
|
|
116
125
|
break;
|
|
117
126
|
}
|
|
118
127
|
},
|
|
@@ -122,7 +131,7 @@ const c = [], g = /* @__PURE__ */ new Map(), E = 100, h = {
|
|
|
122
131
|
get count() {
|
|
123
132
|
return c.length;
|
|
124
133
|
}
|
|
125
|
-
},
|
|
134
|
+
}, y = (
|
|
126
135
|
/* css */
|
|
127
136
|
`
|
|
128
137
|
:host {
|
|
@@ -332,7 +341,7 @@ tr:hover td { background: rgba(255,255,255,0.02); }
|
|
|
332
341
|
}
|
|
333
342
|
`
|
|
334
343
|
);
|
|
335
|
-
function
|
|
344
|
+
function L(t) {
|
|
336
345
|
if (t == null) return { text: String(t), cls: "val-null" };
|
|
337
346
|
if (typeof t == "string") return { text: `"${t.length > 30 ? t.slice(0, 30) + "..." : t}"`, cls: "val-string" };
|
|
338
347
|
if (typeof t == "number") return { text: String(t), cls: "val-number" };
|
|
@@ -345,16 +354,16 @@ function M(t) {
|
|
|
345
354
|
}
|
|
346
355
|
return { text: String(t), cls: "val-object" };
|
|
347
356
|
}
|
|
348
|
-
function
|
|
349
|
-
const t =
|
|
357
|
+
function H() {
|
|
358
|
+
const t = b.getAll();
|
|
350
359
|
if (t.length === 0)
|
|
351
360
|
return '<div class="t4-empty">No signals tracked yet.<br>Signals created after debug is enabled will appear here.</div>';
|
|
352
361
|
let o = "";
|
|
353
362
|
for (let e = 0; e < t.length; e++) {
|
|
354
|
-
const n = t[e], { text: r, cls: s } =
|
|
363
|
+
const n = t[e], { text: r, cls: s } = L(n.value);
|
|
355
364
|
o += `<tr>
|
|
356
365
|
<td>${n.label || `signal_${e}`}</td>
|
|
357
|
-
<td><span class="${s}">${
|
|
366
|
+
<td><span class="${s}">${j(r)}</span></td>
|
|
358
367
|
<td>${n.subscriberCount}</td>
|
|
359
368
|
<td>${n.updateCount}</td>
|
|
360
369
|
</tr>`;
|
|
@@ -364,19 +373,19 @@ function L() {
|
|
|
364
373
|
<tbody>${o}</tbody>
|
|
365
374
|
</table>`;
|
|
366
375
|
}
|
|
367
|
-
function
|
|
376
|
+
function j(t) {
|
|
368
377
|
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
369
378
|
}
|
|
370
|
-
function
|
|
371
|
-
const t =
|
|
379
|
+
function z() {
|
|
380
|
+
const t = h.getAll();
|
|
372
381
|
if (t.length === 0)
|
|
373
382
|
return '<div class="t4-empty">No Tina4Elements mounted.<br>Custom elements extending Tina4Element will appear here.</div>';
|
|
374
383
|
let o = "";
|
|
375
384
|
for (const e of t) {
|
|
376
385
|
const n = Object.keys(e.props).length > 0 ? Object.entries(e.props).map(([r, s]) => `${r}=${JSON.stringify(s) ?? "null"}`).join(", ") : "—";
|
|
377
386
|
o += `<tr>
|
|
378
|
-
<td><${
|
|
379
|
-
<td>${
|
|
387
|
+
<td><${w(e.tagName)}></td>
|
|
388
|
+
<td>${w(n.length > 60 ? n.slice(0, 60) + "..." : n)}</td>
|
|
380
389
|
</tr>`;
|
|
381
390
|
}
|
|
382
391
|
return `<table>
|
|
@@ -384,24 +393,24 @@ function j() {
|
|
|
384
393
|
<tbody>${o}</tbody>
|
|
385
394
|
</table>`;
|
|
386
395
|
}
|
|
387
|
-
function
|
|
396
|
+
function w(t) {
|
|
388
397
|
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
389
398
|
}
|
|
390
|
-
function
|
|
399
|
+
function N(t) {
|
|
391
400
|
const o = t < 1 ? "<1ms" : `${Math.round(t)}ms`, e = t < 5 ? "duration fast" : t < 50 ? "duration" : t < 200 ? "duration slow" : "duration very-slow";
|
|
392
401
|
return { text: o, cls: e };
|
|
393
402
|
}
|
|
394
|
-
function
|
|
403
|
+
function I(t) {
|
|
395
404
|
return new Date(t).toLocaleTimeString("en-US", { hour12: !1, hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
396
405
|
}
|
|
397
|
-
function
|
|
398
|
-
const t =
|
|
406
|
+
function P() {
|
|
407
|
+
const t = p.getRegisteredRoutes(), o = p.getHistory();
|
|
399
408
|
let e = "";
|
|
400
409
|
if (t.length > 0) {
|
|
401
410
|
let n = "";
|
|
402
411
|
for (const r of t)
|
|
403
412
|
n += `<tr>
|
|
404
|
-
<td><span class="route-pattern">${
|
|
413
|
+
<td><span class="route-pattern">${_(r.pattern)}</span></td>
|
|
405
414
|
<td>${r.hasGuard ? "Yes" : "—"}</td>
|
|
406
415
|
</tr>`;
|
|
407
416
|
e += `<table>
|
|
@@ -413,11 +422,11 @@ function I() {
|
|
|
413
422
|
e += '<div style="margin-top:8px;padding-top:8px;border-top:1px solid #333;">';
|
|
414
423
|
let n = "";
|
|
415
424
|
for (const r of o) {
|
|
416
|
-
const { text: s, cls: i } =
|
|
425
|
+
const { text: s, cls: i } = N(r.durationMs), $ = Object.keys(r.params).length > 0 ? Object.entries(r.params).map(([k, T]) => `<span class="route-param">${k}=${T}</span>`).join(" ") : "";
|
|
417
426
|
n += `<tr>
|
|
418
|
-
<td>${
|
|
419
|
-
<td>${
|
|
420
|
-
<td>${
|
|
427
|
+
<td>${I(r.timestamp)}</td>
|
|
428
|
+
<td>${_(r.path)}</td>
|
|
429
|
+
<td>${$ || "—"}</td>
|
|
421
430
|
<td><span class="${i}">${s}</span></td>
|
|
422
431
|
</tr>`;
|
|
423
432
|
}
|
|
@@ -428,29 +437,29 @@ function I() {
|
|
|
428
437
|
} else t.length === 0 && (e = '<div class="t4-empty">No routes registered yet.</div>');
|
|
429
438
|
return e;
|
|
430
439
|
}
|
|
431
|
-
function
|
|
440
|
+
function _(t) {
|
|
432
441
|
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
433
442
|
}
|
|
434
|
-
function
|
|
443
|
+
function O(t) {
|
|
435
444
|
if (t === void 0) return { text: "...", cls: "status-pending" };
|
|
436
445
|
const o = t < 1 ? "<1ms" : `${Math.round(t)}ms`, e = t < 100 ? "duration fast" : t < 500 ? "duration" : t < 2e3 ? "duration slow" : "duration very-slow";
|
|
437
446
|
return { text: o, cls: e };
|
|
438
447
|
}
|
|
439
|
-
function
|
|
448
|
+
function U(t, o) {
|
|
440
449
|
return o ? { text: "pending", cls: "status-pending" } : t ? t >= 200 && t < 300 ? { text: String(t), cls: "status-ok" } : { text: String(t), cls: "status-err" } : { text: "—", cls: "" };
|
|
441
450
|
}
|
|
442
|
-
function
|
|
451
|
+
function q(t) {
|
|
443
452
|
return new Date(t).toLocaleTimeString("en-US", { hour12: !1, hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
444
453
|
}
|
|
445
|
-
function
|
|
446
|
-
const t =
|
|
454
|
+
function G() {
|
|
455
|
+
const t = g.getLog();
|
|
447
456
|
if (t.length === 0)
|
|
448
457
|
return '<div class="t4-empty">No API calls yet.<br>Requests made via api.get/post/put/patch/delete will appear here.</div>';
|
|
449
458
|
let o = "";
|
|
450
459
|
for (const e of t) {
|
|
451
|
-
const { text: n, cls: r } =
|
|
460
|
+
const { text: n, cls: r } = U(e.status, e.pending), { text: s, cls: i } = O(e.durationMs);
|
|
452
461
|
o += `<tr>
|
|
453
|
-
<td>${
|
|
462
|
+
<td>${q(e.timestamp)}</td>
|
|
454
463
|
<td><strong>${e.method}</strong></td>
|
|
455
464
|
<td>${B(e.url || "(url)")}</td>
|
|
456
465
|
<td><span class="${r}">${n}</span></td>
|
|
@@ -466,7 +475,7 @@ function q() {
|
|
|
466
475
|
function B(t) {
|
|
467
476
|
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
468
477
|
}
|
|
469
|
-
class
|
|
478
|
+
class F extends HTMLElement {
|
|
470
479
|
constructor() {
|
|
471
480
|
super(), this._visible = !0, this._activeTab = "signals", this._refreshTimer = null, this._shadow = this.attachShadow({ mode: "open" });
|
|
472
481
|
}
|
|
@@ -499,13 +508,13 @@ class G extends HTMLElement {
|
|
|
499
508
|
_getTabContent() {
|
|
500
509
|
switch (this._activeTab) {
|
|
501
510
|
case "signals":
|
|
502
|
-
return
|
|
511
|
+
return H();
|
|
503
512
|
case "components":
|
|
504
|
-
return
|
|
513
|
+
return z();
|
|
505
514
|
case "routes":
|
|
506
|
-
return
|
|
515
|
+
return P();
|
|
507
516
|
case "api":
|
|
508
|
-
return
|
|
517
|
+
return G();
|
|
509
518
|
}
|
|
510
519
|
}
|
|
511
520
|
_renderBody() {
|
|
@@ -514,10 +523,10 @@ class G extends HTMLElement {
|
|
|
514
523
|
}
|
|
515
524
|
_updateTabCounts() {
|
|
516
525
|
const o = {
|
|
517
|
-
signals:
|
|
518
|
-
components:
|
|
519
|
-
routes:
|
|
520
|
-
api:
|
|
526
|
+
signals: b.count,
|
|
527
|
+
components: h.count,
|
|
528
|
+
routes: p.count,
|
|
529
|
+
api: g.count
|
|
521
530
|
};
|
|
522
531
|
for (const [e, n] of Object.entries(o)) {
|
|
523
532
|
const r = this._shadow.querySelector(`[data-tab-count="${e}"]`);
|
|
@@ -534,7 +543,7 @@ class G extends HTMLElement {
|
|
|
534
543
|
];
|
|
535
544
|
if (!this._visible) {
|
|
536
545
|
this._shadow.innerHTML = `
|
|
537
|
-
<style>${
|
|
546
|
+
<style>${y}</style>
|
|
538
547
|
<div class="t4-mini" id="t4-mini">
|
|
539
548
|
<span class="t4-mini-dot"></span>
|
|
540
549
|
T4 Debug
|
|
@@ -548,7 +557,7 @@ class G extends HTMLElement {
|
|
|
548
557
|
</button>`
|
|
549
558
|
).join("");
|
|
550
559
|
this._shadow.innerHTML = `
|
|
551
|
-
<style>${
|
|
560
|
+
<style>${y}</style>
|
|
552
561
|
<div class="t4-debug">
|
|
553
562
|
<div class="t4-header">
|
|
554
563
|
<div>
|
|
@@ -571,19 +580,19 @@ class G extends HTMLElement {
|
|
|
571
580
|
}
|
|
572
581
|
}
|
|
573
582
|
function V() {
|
|
574
|
-
typeof customElements < "u" && !customElements.get("tina4-debug") && customElements.define("tina4-debug",
|
|
583
|
+
typeof customElements < "u" && !customElements.get("tina4-debug") && customElements.define("tina4-debug", F);
|
|
575
584
|
}
|
|
576
585
|
let u = null, v = !1;
|
|
577
586
|
function W() {
|
|
578
|
-
v || (v = !0,
|
|
579
|
-
(t, o) =>
|
|
580
|
-
(t) =>
|
|
581
|
-
),
|
|
582
|
-
(t) =>
|
|
583
|
-
(t) =>
|
|
584
|
-
), A.on("change", (t) => {
|
|
585
|
-
|
|
586
|
-
}),
|
|
587
|
+
v || (v = !0, C(
|
|
588
|
+
(t, o) => b.add(t, o),
|
|
589
|
+
(t) => b.onUpdate(t)
|
|
590
|
+
), S(
|
|
591
|
+
(t) => h.onMount(t),
|
|
592
|
+
(t) => h.onUnmount(t)
|
|
593
|
+
), p.setGetRoutes(R), A.on("change", (t) => {
|
|
594
|
+
p.onNavigate(t);
|
|
595
|
+
}), x.intercept("request", (t) => (g.onRequest(t), t)), x.intercept("response", (t) => (g.onResponse(t), t)), typeof document < "u" && (V(), u = document.createElement("tina4-debug"), document.body.appendChild(u), document.addEventListener("keydown", (t) => {
|
|
587
596
|
t.ctrlKey && t.shiftKey && t.key === "D" && (t.preventDefault(), u == null || u.toggle());
|
|
588
597
|
})), console.log(
|
|
589
598
|
"%c[tina4] %cDebug overlay enabled %c(Ctrl+Shift+D to toggle)",
|
package/dist/index.es.js
CHANGED
package/dist/signal.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";let s=null,
|
|
1
|
+
"use strict";let c=null,s=null,i=null;function C(t){i=t}function h(){return i}let d=null,_=null;function v(t,n){d=t,_=n}let f=0;const b=new Set;function g(t,n){let e=t;const o=new Set,r={_t4:!0,get value(){if(c&&(o.add(c),s)){const u=c;s.push(()=>o.delete(u))}return e},set value(u){if(Object.is(u,e))return;const a=e;if(e=u,r._debugInfo&&r._debugInfo.updateCount++,_&&_(r,a,u),f>0)for(const l of o)b.add(l);else for(const l of[...o])l()},_subscribe(u){return o.add(u),()=>{o.delete(u)}},peek(){return e}};return d&&(r._debugInfo={label:n,createdAt:Date.now(),updateCount:0,subs:o},d(r,n)),r}function S(t){const n=g(void 0);return p(()=>{n.value=t()}),{_t4:!0,get value(){return n.value},set value(e){throw new Error("[tina4] computed signals are read-only")},_subscribe(e){return n._subscribe(e)},peek(){return n.peek()}}}function p(t){let n=!1,e=[];const o=()=>{if(n)return;for(const l of e)l();e=[];const u=c,a=s;c=o,s=e;try{t()}finally{c=u,s=a}};o();const r=()=>{n=!0;for(const u of e)u();e=[]};return i&&i.push(r),r}function y(t){f++;try{t()}finally{if(f--,f===0){const n=[...b];b.clear();for(const e of n)e()}}}function E(t){return t!==null&&typeof t=="object"&&t._t4===!0}exports.__setDebugSignalHooks=v;exports._getEffectCollector=h;exports._setEffectCollector=C;exports.batch=y;exports.computed=S;exports.effect=p;exports.isSignal=E;exports.signal=g;
|
package/dist/signal.es.js
CHANGED
|
@@ -1,98 +1,110 @@
|
|
|
1
|
-
let s = null, a = null;
|
|
2
|
-
function
|
|
3
|
-
a =
|
|
1
|
+
let s = null, l = null, a = null;
|
|
2
|
+
function v(t) {
|
|
3
|
+
a = t;
|
|
4
4
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
f = e, i = t;
|
|
5
|
+
function C() {
|
|
6
|
+
return a;
|
|
8
7
|
}
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
let d = null, b = null;
|
|
9
|
+
function h(t, n) {
|
|
10
|
+
d = t, b = n;
|
|
11
|
+
}
|
|
12
|
+
let f = 0;
|
|
13
|
+
const p = /* @__PURE__ */ new Set();
|
|
14
|
+
function _(t, n) {
|
|
15
|
+
let e = t;
|
|
16
|
+
const o = /* @__PURE__ */ new Set(), r = {
|
|
14
17
|
_t4: !0,
|
|
15
18
|
get value() {
|
|
16
|
-
|
|
19
|
+
if (s && (o.add(s), l)) {
|
|
20
|
+
const u = s;
|
|
21
|
+
l.push(() => o.delete(u));
|
|
22
|
+
}
|
|
23
|
+
return e;
|
|
17
24
|
},
|
|
18
|
-
set value(
|
|
19
|
-
if (Object.is(
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
for (const
|
|
25
|
+
set value(u) {
|
|
26
|
+
if (Object.is(u, e)) return;
|
|
27
|
+
const i = e;
|
|
28
|
+
if (e = u, r._debugInfo && r._debugInfo.updateCount++, b && b(r, i, u), f > 0)
|
|
29
|
+
for (const c of o) p.add(c);
|
|
23
30
|
else
|
|
24
|
-
for (const
|
|
31
|
+
for (const c of [...o]) c();
|
|
25
32
|
},
|
|
26
|
-
_subscribe(
|
|
27
|
-
return
|
|
28
|
-
|
|
33
|
+
_subscribe(u) {
|
|
34
|
+
return o.add(u), () => {
|
|
35
|
+
o.delete(u);
|
|
29
36
|
};
|
|
30
37
|
},
|
|
31
38
|
peek() {
|
|
32
|
-
return
|
|
39
|
+
return e;
|
|
33
40
|
}
|
|
34
41
|
};
|
|
35
|
-
return
|
|
42
|
+
return d && (r._debugInfo = { label: n, createdAt: Date.now(), updateCount: 0, subs: o }, d(r, n)), r;
|
|
36
43
|
}
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
return
|
|
40
|
-
|
|
44
|
+
function y(t) {
|
|
45
|
+
const n = _(void 0);
|
|
46
|
+
return g(() => {
|
|
47
|
+
n.value = t();
|
|
41
48
|
}), {
|
|
42
49
|
_t4: !0,
|
|
43
50
|
get value() {
|
|
44
|
-
return
|
|
51
|
+
return n.value;
|
|
45
52
|
},
|
|
46
|
-
set value(
|
|
53
|
+
set value(e) {
|
|
47
54
|
throw new Error("[tina4] computed signals are read-only");
|
|
48
55
|
},
|
|
49
|
-
_subscribe(
|
|
50
|
-
return
|
|
56
|
+
_subscribe(e) {
|
|
57
|
+
return n._subscribe(e);
|
|
51
58
|
},
|
|
52
59
|
peek() {
|
|
53
|
-
return
|
|
60
|
+
return n.peek();
|
|
54
61
|
}
|
|
55
62
|
};
|
|
56
63
|
}
|
|
57
|
-
function
|
|
58
|
-
let
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
const
|
|
62
|
-
|
|
64
|
+
function g(t) {
|
|
65
|
+
let n = !1, e = [];
|
|
66
|
+
const o = () => {
|
|
67
|
+
if (n) return;
|
|
68
|
+
for (const c of e) c();
|
|
69
|
+
e = [];
|
|
70
|
+
const u = s, i = l;
|
|
71
|
+
s = o, l = e;
|
|
63
72
|
try {
|
|
64
|
-
|
|
73
|
+
t();
|
|
65
74
|
} finally {
|
|
66
|
-
s =
|
|
75
|
+
s = u, l = i;
|
|
67
76
|
}
|
|
68
77
|
};
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
78
|
+
o();
|
|
79
|
+
const r = () => {
|
|
80
|
+
n = !0;
|
|
81
|
+
for (const u of e) u();
|
|
82
|
+
e = [];
|
|
72
83
|
};
|
|
73
|
-
return a && a.push(
|
|
84
|
+
return a && a.push(r), r;
|
|
74
85
|
}
|
|
75
|
-
function
|
|
76
|
-
|
|
86
|
+
function S(t) {
|
|
87
|
+
f++;
|
|
77
88
|
try {
|
|
78
|
-
|
|
89
|
+
t();
|
|
79
90
|
} finally {
|
|
80
|
-
if (
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
for (const
|
|
91
|
+
if (f--, f === 0) {
|
|
92
|
+
const n = [...p];
|
|
93
|
+
p.clear();
|
|
94
|
+
for (const e of n) e();
|
|
84
95
|
}
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
|
-
function
|
|
88
|
-
return
|
|
98
|
+
function w(t) {
|
|
99
|
+
return t !== null && typeof t == "object" && t._t4 === !0;
|
|
89
100
|
}
|
|
90
101
|
export {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
h as _,
|
|
103
|
+
C as a,
|
|
104
|
+
S as b,
|
|
105
|
+
y as c,
|
|
106
|
+
v as d,
|
|
107
|
+
g as e,
|
|
108
|
+
w as i,
|
|
97
109
|
_ as s
|
|
98
110
|
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -240,6 +240,11 @@ npm run dev # dev server
|
|
|
240
240
|
|
|
241
241
|
## Changelog
|
|
242
242
|
|
|
243
|
+
### 1.0.5
|
|
244
|
+
- **Fix:** Effects now properly unsubscribe from signals on dispose — prevents stale subscriptions accumulating in signal subscriber sets across navigations
|
|
245
|
+
- **Fix:** Function bindings in `html` templates now dispose inner effects when re-evaluated — fixes duplicate DOM nodes from nested reactive lists and conditionals
|
|
246
|
+
- Added 9 new tests covering effect subscription cleanup, inner effect disposal, and multi-navigation accumulation (116 total)
|
|
247
|
+
|
|
243
248
|
### 1.0.4
|
|
244
249
|
- Added router reactive effect cleanup tests (navigate away/back, stale effects, async handlers, stale async discard)
|
|
245
250
|
- Added debug overlay documentation to README and TINA4.md
|