tina4js 1.0.1 → 1.0.2
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/TINA4.md +14 -0
- package/dist/component.cjs.js +1 -1
- package/dist/component.es.js +21 -109
- package/dist/core.cjs.js +1 -1
- package/dist/core.es.js +15 -14
- package/dist/debug.cjs.js +18 -18
- package/dist/debug.es.js +2 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +77 -66
- package/dist/signal.cjs.js +1 -0
- package/dist/signal.es.js +98 -0
- package/dist/tina4.cjs.js +1 -1
- package/dist/tina4.es.js +18 -17
- package/package.json +1 -1
- package/readme.md +35 -0
package/TINA4.md
CHANGED
|
@@ -156,6 +156,20 @@ tina4 build --target python
|
|
|
156
156
|
- `formToken` injected into POST/PUT/PATCH/DELETE body
|
|
157
157
|
- Token auto-rotated via `FreshToken` response header
|
|
158
158
|
|
|
159
|
+
## Debug Overlay
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// Always-on
|
|
163
|
+
import 'tina4js/debug';
|
|
164
|
+
|
|
165
|
+
// Dev-only (recommended — stripped from production builds)
|
|
166
|
+
if (import.meta.env.DEV) import('tina4js/debug');
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- Toggle with **Ctrl+Shift+D**
|
|
170
|
+
- Shows: live signal values + subscriber counts, mounted components, route navigation history with timing, API request/response log
|
|
171
|
+
- Zero cost in production when using the `import.meta.env.DEV` guard (tree-shaken by Vite/Rollup)
|
|
172
|
+
|
|
159
173
|
## Framework Size
|
|
160
174
|
|
|
161
175
|
| Module | Gzipped |
|
package/dist/component.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";const p=require("./signal.cjs.js");let r=null,n=null;function u(h,t){r=h,n=t}const e=class e extends HTMLElement{constructor(){super(),this._props={},this._rendered=!1;const t=this.constructor;this._root=t.shadow?this.attachShadow({mode:"open"}):this;for(const[o,s]of Object.entries(t.props))this._props[o]=p.signal(this._coerce(this.getAttribute(o),s))}static get observedAttributes(){return Object.keys(this.props)}connectedCallback(){if(this._rendered)return;this._rendered=!0;const t=this.constructor;if(t.styles&&t.shadow&&this._root instanceof ShadowRoot){const s=document.createElement("style");s.textContent=t.styles,this._root.appendChild(s)}const o=this.render();o&&this._root.appendChild(o),this.onMount(),r&&r(this)}disconnectedCallback(){this.onUnmount(),n&&n(this)}attributeChangedCallback(t,o,s){const c=this.constructor.props[t];c&&this._props[t]&&(this._props[t].value=this._coerce(s,c))}prop(t){if(!this._props[t])throw new Error(`[tina4] Prop '${t}' not declared in static props of <${this.tagName.toLowerCase()}>`);return this._props[t]}emit(t,o){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,...o}))}onMount(){}onUnmount(){}_coerce(t,o){return o===Boolean?t!==null:o===Number?t!==null?Number(t):0:t??""}};e.props={},e.styles="",e.shadow=!0;let i=e;exports.Tina4Element=i;exports.__setDebugComponentHooks=u;
|
package/dist/component.es.js
CHANGED
|
@@ -1,97 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { s as p } from "./signal.es.js";
|
|
2
|
+
let r = null, n = null;
|
|
3
|
+
function a(h, t) {
|
|
4
|
+
r = h, n = t;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
-
const p = /* @__PURE__ */ new Set();
|
|
7
|
-
function _(o, t) {
|
|
8
|
-
let e = o;
|
|
9
|
-
const s = /* @__PURE__ */ new Set(), n = {
|
|
10
|
-
_t4: !0,
|
|
11
|
-
get value() {
|
|
12
|
-
return u && s.add(u), e;
|
|
13
|
-
},
|
|
14
|
-
set value(r) {
|
|
15
|
-
if (Object.is(r, e)) return;
|
|
16
|
-
const g = e;
|
|
17
|
-
if (e = r, n._debugInfo && n._debugInfo.updateCount++, d && d(n, g, r), c > 0)
|
|
18
|
-
for (const a of s) p.add(a);
|
|
19
|
-
else
|
|
20
|
-
for (const a of [...s]) a();
|
|
21
|
-
},
|
|
22
|
-
_subscribe(r) {
|
|
23
|
-
return s.add(r), () => {
|
|
24
|
-
s.delete(r);
|
|
25
|
-
};
|
|
26
|
-
},
|
|
27
|
-
peek() {
|
|
28
|
-
return e;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
return l && (n._debugInfo = { label: t, createdAt: Date.now(), updateCount: 0, subs: s }, l(n, t)), n;
|
|
32
|
-
}
|
|
33
|
-
function y(o) {
|
|
34
|
-
const t = _(void 0);
|
|
35
|
-
return C(() => {
|
|
36
|
-
t.value = o();
|
|
37
|
-
}), {
|
|
38
|
-
_t4: !0,
|
|
39
|
-
get value() {
|
|
40
|
-
return t.value;
|
|
41
|
-
},
|
|
42
|
-
set value(e) {
|
|
43
|
-
throw new Error("[tina4] computed signals are read-only");
|
|
44
|
-
},
|
|
45
|
-
_subscribe(e) {
|
|
46
|
-
return t._subscribe(e);
|
|
47
|
-
},
|
|
48
|
-
peek() {
|
|
49
|
-
return t.peek();
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function C(o) {
|
|
54
|
-
let t = !1;
|
|
55
|
-
const e = () => {
|
|
56
|
-
if (t) return;
|
|
57
|
-
const s = u;
|
|
58
|
-
u = e;
|
|
59
|
-
try {
|
|
60
|
-
o();
|
|
61
|
-
} finally {
|
|
62
|
-
u = s;
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
return e(), () => {
|
|
66
|
-
t = !0;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
function m(o) {
|
|
70
|
-
c++;
|
|
71
|
-
try {
|
|
72
|
-
o();
|
|
73
|
-
} finally {
|
|
74
|
-
if (c--, c === 0) {
|
|
75
|
-
const t = [...p];
|
|
76
|
-
p.clear();
|
|
77
|
-
for (const e of t) e();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function k(o) {
|
|
82
|
-
return o !== null && typeof o == "object" && o._t4 === !0;
|
|
83
|
-
}
|
|
84
|
-
let h = null, f = null;
|
|
85
|
-
function v(o, t) {
|
|
86
|
-
h = o, f = t;
|
|
87
|
-
}
|
|
88
|
-
const i = class i extends HTMLElement {
|
|
6
|
+
const e = class e extends HTMLElement {
|
|
89
7
|
constructor() {
|
|
90
8
|
super(), this._props = {}, this._rendered = !1;
|
|
91
9
|
const t = this.constructor;
|
|
92
10
|
this._root = t.shadow ? this.attachShadow({ mode: "open" }) : this;
|
|
93
|
-
for (const [
|
|
94
|
-
this._props[
|
|
11
|
+
for (const [o, s] of Object.entries(t.props))
|
|
12
|
+
this._props[o] = p(this._coerce(this.getAttribute(o), s));
|
|
95
13
|
}
|
|
96
14
|
static get observedAttributes() {
|
|
97
15
|
return Object.keys(this.props);
|
|
@@ -104,15 +22,15 @@ const i = class i extends HTMLElement {
|
|
|
104
22
|
const s = document.createElement("style");
|
|
105
23
|
s.textContent = t.styles, this._root.appendChild(s);
|
|
106
24
|
}
|
|
107
|
-
const
|
|
108
|
-
|
|
25
|
+
const o = this.render();
|
|
26
|
+
o && this._root.appendChild(o), this.onMount(), r && r(this);
|
|
109
27
|
}
|
|
110
28
|
disconnectedCallback() {
|
|
111
|
-
this.onUnmount(),
|
|
29
|
+
this.onUnmount(), n && n(this);
|
|
112
30
|
}
|
|
113
|
-
attributeChangedCallback(t,
|
|
114
|
-
const
|
|
115
|
-
|
|
31
|
+
attributeChangedCallback(t, o, s) {
|
|
32
|
+
const i = this.constructor.props[t];
|
|
33
|
+
i && this._props[t] && (this._props[t].value = this._coerce(s, i));
|
|
116
34
|
}
|
|
117
35
|
/**
|
|
118
36
|
* Get a reactive signal for a declared prop.
|
|
@@ -135,12 +53,12 @@ const i = class i extends HTMLElement {
|
|
|
135
53
|
* this.emit('activate', { detail: 42 });
|
|
136
54
|
* ```
|
|
137
55
|
*/
|
|
138
|
-
emit(t,
|
|
56
|
+
emit(t, o) {
|
|
139
57
|
this.dispatchEvent(new CustomEvent(t, {
|
|
140
58
|
bubbles: !0,
|
|
141
59
|
composed: !0,
|
|
142
60
|
// crosses shadow DOM boundary
|
|
143
|
-
...
|
|
61
|
+
...o
|
|
144
62
|
}));
|
|
145
63
|
}
|
|
146
64
|
// ── Lifecycle hooks (override in subclass) ──────────────────────
|
|
@@ -151,19 +69,13 @@ const i = class i extends HTMLElement {
|
|
|
151
69
|
onUnmount() {
|
|
152
70
|
}
|
|
153
71
|
// ── Private ─────────────────────────────────────────────────────
|
|
154
|
-
_coerce(t,
|
|
155
|
-
return
|
|
72
|
+
_coerce(t, o) {
|
|
73
|
+
return o === Boolean ? t !== null : o === Number ? t !== null ? Number(t) : 0 : t ?? "";
|
|
156
74
|
}
|
|
157
75
|
};
|
|
158
|
-
|
|
159
|
-
let
|
|
76
|
+
e.props = {}, e.styles = "", e.shadow = !0;
|
|
77
|
+
let c = e;
|
|
160
78
|
export {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
v as a,
|
|
164
|
-
m as b,
|
|
165
|
-
y as c,
|
|
166
|
-
C as e,
|
|
167
|
-
k as i,
|
|
168
|
-
_ as s
|
|
79
|
+
c as T,
|
|
80
|
+
a as _
|
|
169
81
|
};
|
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 a=require("./signal.cjs.js"),_=require("./component.cjs.js"),h=new WeakMap,d="t4:";function A(t,...e){let n=h.get(t);if(!n){n=document.createElement("template");let c="";for(let s=0;s<t.length;s++)c+=t[s],s<e.length&&(T(c)?c+=`__t4_${s}__`:c+=`<!--${d}${s}-->`);n.innerHTML=c,h.set(t,n)}const o=n.content.cloneNode(!0),i=N(o);for(const{marker:c,index:s}of i)y(c,e[s]);const f=b(o);for(const c of f)S(c,e);return o}function N(t){const e=[];return u(t,n=>{if(n.nodeType===8){const o=n.data;if(o&&o.startsWith(d)){const i=parseInt(o.slice(d.length),10);e.push({marker:n,index:i})}}}),e}function b(t){const e=[];return u(t,n=>{n.nodeType===1&&e.push(n)}),e}function u(t,e){const n=t.childNodes;for(let o=0;o<n.length;o++){const i=n[o];e(i),u(i,e)}}function y(t,e){const n=t.parentNode;if(n)if(a.isSignal(e)){const o=document.createTextNode("");n.replaceChild(o,t),a.effect(()=>{o.data=String(e.value??"")})}else if(typeof e=="function"){const o=document.createComment("");n.replaceChild(o,t);let i=[];a.effect(()=>{var l;const f=e();for(const r of i)(l=r.parentNode)==null||l.removeChild(r);i=[];const c=m(f),s=o.parentNode;for(const r of c)s.insertBefore(r,o),i.push(r)})}else if(p(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 i of e){const f=m(i);for(const c of f)o.appendChild(c)}n.replaceChild(o,t)}else{const o=document.createTextNode(String(e??""));n.replaceChild(o,t)}}function S(t,e){const n=[];for(const o of Array.from(t.attributes)){const i=o.name,f=o.value;if(i.startsWith("@")){const s=i.slice(1),l=f.match(/__t4_(\d+)__/);if(l){const r=e[parseInt(l[1],10)];typeof r=="function"&&t.addEventListener(s,r)}n.push(i);continue}if(i.startsWith("?")){const s=i.slice(1),l=f.match(/__t4_(\d+)__/);if(l){const r=e[parseInt(l[1],10)];if(a.isSignal(r)){const g=r;a.effect(()=>{g.value?t.setAttribute(s,""):t.removeAttribute(s)})}else r&&t.setAttribute(s,"")}n.push(i);continue}if(i.startsWith(".")){const s=i.slice(1),l=f.match(/__t4_(\d+)__/);if(l){const r=e[parseInt(l[1],10)];a.isSignal(r)?a.effect(()=>{t[s]=r.value}):t[s]=r}n.push(i);continue}const c=f.match(/__t4_(\d+)__/);if(c){const s=e[parseInt(c[1],10)];if(a.isSignal(s)){const l=s;a.effect(()=>{t.setAttribute(i,String(l.value??""))})}else typeof s=="function"?a.effect(()=>{t.setAttribute(i,String(s()??""))}):t.setAttribute(i,String(s??""))}}for(const o of n)t.removeAttribute(o)}function m(t){if(t==null||t===!1)return[];if(p(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(...m(n));return e}return[document.createTextNode(String(t))]}function p(t){return t!=null&&typeof t=="object"&&t.nodeType===11}function T(t){let e=!1,n=!1,o=!1;for(let i=0;i<t.length;i++){const f=t[i];f==="<"&&!e&&!n&&(o=!0),f===">"&&!e&&!n&&(o=!1),o&&(f==='"'&&!e&&(n=!n),f==="'"&&!n&&(e=!e))}return o}exports.batch=a.batch;exports.computed=a.computed;exports.effect=a.effect;exports.isSignal=a.isSignal;exports.signal=a.signal;exports.Tina4Element=_.Tina4Element;exports.html=A;
|
package/dist/core.es.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { i as l, e as d } from "./
|
|
2
|
-
import {
|
|
1
|
+
import { i as l, e as d } from "./signal.es.js";
|
|
2
|
+
import { b as I, c as W, s as V } from "./signal.es.js";
|
|
3
|
+
import { T as D } from "./component.es.js";
|
|
3
4
|
const u = /* @__PURE__ */ new WeakMap(), m = "t4:";
|
|
4
5
|
function x(t, ...e) {
|
|
5
6
|
let n = u.get(t);
|
|
@@ -20,7 +21,7 @@ function x(t, ...e) {
|
|
|
20
21
|
}
|
|
21
22
|
function A(t) {
|
|
22
23
|
const e = [];
|
|
23
|
-
return
|
|
24
|
+
return h(t, (n) => {
|
|
24
25
|
if (n.nodeType === 8) {
|
|
25
26
|
const o = n.data;
|
|
26
27
|
if (o && o.startsWith(m)) {
|
|
@@ -32,15 +33,15 @@ function A(t) {
|
|
|
32
33
|
}
|
|
33
34
|
function N(t) {
|
|
34
35
|
const e = [];
|
|
35
|
-
return
|
|
36
|
+
return h(t, (n) => {
|
|
36
37
|
n.nodeType === 1 && e.push(n);
|
|
37
38
|
}), e;
|
|
38
39
|
}
|
|
39
|
-
function
|
|
40
|
+
function h(t, e) {
|
|
40
41
|
const n = t.childNodes;
|
|
41
42
|
for (let o = 0; o < n.length; o++) {
|
|
42
43
|
const s = n[o];
|
|
43
|
-
e(s),
|
|
44
|
+
e(s), h(s, e);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
function b(t, e) {
|
|
@@ -60,7 +61,7 @@ function b(t, e) {
|
|
|
60
61
|
const f = e();
|
|
61
62
|
for (const c of s) (a = c.parentNode) == null || a.removeChild(c);
|
|
62
63
|
s = [];
|
|
63
|
-
const r =
|
|
64
|
+
const r = p(f), i = o.parentNode;
|
|
64
65
|
for (const c of r)
|
|
65
66
|
i.insertBefore(c, o), s.push(c);
|
|
66
67
|
});
|
|
@@ -71,7 +72,7 @@ function b(t, e) {
|
|
|
71
72
|
else if (Array.isArray(e)) {
|
|
72
73
|
const o = document.createDocumentFragment();
|
|
73
74
|
for (const s of e) {
|
|
74
|
-
const f =
|
|
75
|
+
const f = p(s);
|
|
75
76
|
for (const r of f) o.appendChild(r);
|
|
76
77
|
}
|
|
77
78
|
n.replaceChild(o, t);
|
|
@@ -134,13 +135,13 @@ function y(t, e) {
|
|
|
134
135
|
}
|
|
135
136
|
for (const o of n) t.removeAttribute(o);
|
|
136
137
|
}
|
|
137
|
-
function
|
|
138
|
+
function p(t) {
|
|
138
139
|
if (t == null || t === !1) return [];
|
|
139
140
|
if (_(t)) return Array.from(t.childNodes);
|
|
140
141
|
if (t instanceof Node) return [t];
|
|
141
142
|
if (Array.isArray(t)) {
|
|
142
143
|
const e = [];
|
|
143
|
-
for (const n of t) e.push(...
|
|
144
|
+
for (const n of t) e.push(...p(n));
|
|
144
145
|
return e;
|
|
145
146
|
}
|
|
146
147
|
return [document.createTextNode(String(t))];
|
|
@@ -157,11 +158,11 @@ function T(t) {
|
|
|
157
158
|
return o;
|
|
158
159
|
}
|
|
159
160
|
export {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
D as Tina4Element,
|
|
162
|
+
I as batch,
|
|
163
|
+
W as computed,
|
|
163
164
|
d as effect,
|
|
164
165
|
x as html,
|
|
165
166
|
l as isSignal,
|
|
166
|
-
|
|
167
|
+
V as signal
|
|
167
168
|
};
|
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 C=require("./signal.cjs.js"),A=require("./component.cjs.js"),_=require("./index.cjs.js"),m=require("./api.cjs.js"),d=[],p={add(t,o){const e=t._debugInfo;d.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 d)if(o.ref.deref()===t){o.updateCount++;break}},getAll(){var o;const t=[];for(let e=d.length-1;e>=0;e--){const n=d[e],r=n.ref.deref();if(!r){d.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 d.length}},a=[],b={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}},l=[],D=50,f={onNavigate(t){l.unshift({path:t.path,pattern:t.pattern,params:t.params,durationMs:t.durationMs,timestamp:Date.now()}),l.length>D&&l.pop()},getHistory(){return l},get count(){return l.length}};let R=0;const c=[],g=new Map,M=100,h={onRequest(t){var r;const o=++R,e={id:o,method:t.method??"GET",url:"",hasAuth:!!((r=t.headers)!=null&&r.Authorization),timestamp:Date.now(),pending:!0},n=String(o);g.set(n,e),c.unshift(e),c.length>M&&c.pop()},onResponse(t){for(const[o,e]of g)if(e.pending){e.status=t.status,e.durationMs=Date.now()-e.timestamp,e.pending=!1,t.ok||(e.error=`HTTP ${t.status}`),g.delete(o);break}},getLog(){return c},get count(){return c.length}},x=`
|
|
2
2
|
:host {
|
|
3
3
|
all: initial;
|
|
4
4
|
position: fixed;
|
|
@@ -204,46 +204,46 @@ 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 E(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 L(){const t=p.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}=E(n.value);o+=`<tr>
|
|
208
208
|
<td>${n.label||`signal_${e}`}</td>
|
|
209
|
-
<td><span class="${s}">${
|
|
209
|
+
<td><span class="${s}">${j(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 j(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function H(){const t=b.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><${y(e.tagName)}></td>
|
|
217
|
+
<td>${y(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 y(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function z(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 N(t){return new Date(t).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function P(){const t=_._getRoutes(),o=f.getHistory();let e="";if(t.length>0){let n="";for(const r of t)n+=`<tr>
|
|
222
|
+
<td><span class="route-pattern">${w(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}=z(r.durationMs),k=Object.keys(r.params).length>0?Object.entries(r.params).map(([T,S])=>`<span class="route-param">${T}=${S}</span>`).join(" "):"";n+=`<tr>
|
|
228
|
+
<td>${N(r.timestamp)}</td>
|
|
229
|
+
<td>${w(r.path)}</td>
|
|
230
|
+
<td>${k||"—"}</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
|
|
235
|
+
</table></div>`}else t.length===0&&(e='<div class="t4-empty">No routes registered yet.</div>');return e}function w(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function I(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 q(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 O(t){return new Date(t).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}function U(){const t=h.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}=q(e.status,e.pending),{text:s,cls:i}=I(e.durationMs);o+=`<tr>
|
|
236
236
|
<td>${O(e.timestamp)}</td>
|
|
237
237
|
<td><strong>${e.method}</strong></td>
|
|
238
|
-
<td>${
|
|
238
|
+
<td>${B(e.url||"(url)")}</td>
|
|
239
239
|
<td><span class="${r}">${n}</span></td>
|
|
240
240
|
<td><span class="${i}">${s}</span></td>
|
|
241
241
|
<td>${e.hasAuth?"Bearer":"—"}</td>
|
|
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
|
|
246
|
-
<style>${
|
|
245
|
+
</table>`}function B(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}class G 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 L();case"components":return H();case"routes":return P();case"api":return U()}}_renderBody(){const o=this._shadow.querySelector(".t4-body");o&&(o.innerHTML=this._getTabContent()),this._updateTabCounts()}_updateTabCounts(){const o={signals:p.count,components:b.count,routes:f.count,api:h.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>${x}</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>${x}</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
|
|
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",G)}let u=null,v=!1;function $(){v||(v=!0,C.__setDebugSignalHooks((t,o)=>p.add(t,o),t=>p.onUpdate(t)),A.__setDebugComponentHooks(t=>b.onMount(t),t=>b.onUnmount(t)),_.router.on("change",t=>{f.onNavigate(t)}),m.api.intercept("request",t=>(h.onRequest(t),t)),m.api.intercept("response",t=>(h.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"))}$();exports.enableDebug=$;
|
package/dist/debug.es.js
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";let
|
|
1
|
+
"use strict";const y=require("./signal.cjs.js");let p=[],a=null,l="history";const c=[];let u=[],w=0;function R(t,e){const r=[];let n;t==="*"?n=".*":n=t.replace(/\{(\w+)\}/g,(f,i)=>(r.push(i),"([^/]+)"));const s=new RegExp(`^${n}$`);typeof e=="function"?p.push({pattern:t,regex:s,paramNames:r,handler:e}):p.push({pattern:t,regex:s,paramNames:r,handler:e.handler,guard:e.guard})}function v(t,e){if(l==="hash")if(e!=null&&e.replace){const r=new URL(location.href);r.hash="#"+t,history.replaceState(null,"",r.toString()),d()}else location.hash="#"+t;else e!=null&&e.replace?history.replaceState(null,"",t):history.pushState(null,"",t),d()}function d(){if(!a)return;const t=performance.now(),e=++w,r=l==="hash"?location.hash.slice(1)||"/":location.pathname;for(const n of p){const s=r.match(n.regex);if(!s)continue;const f={};if(n.paramNames.forEach((o,h)=>{f[o]=decodeURIComponent(s[h+1])}),n.guard){const o=n.guard();if(o===!1)return;if(typeof o=="string"){v(o,{replace:!0});return}}for(const o of u)o();u=[],a.innerHTML="";const i=[];y._setEffectCollector(i);const g=n.handler(f);if(g instanceof Promise)g.then(o=>{if(y._setEffectCollector(null),e!==w){for(const m of i)m();return}E(a,o),u=i;const h=performance.now()-t;for(const m of c)m({path:r,params:f,pattern:n.pattern,durationMs:h})});else{y._setEffectCollector(null),E(a,g),u=i;const o=performance.now()-t;for(const h of c)h({path:r,params:f,pattern:n.pattern,durationMs:o})}return}}function E(t,e){e instanceof DocumentFragment||e instanceof Node?t.appendChild(e):typeof e=="string"?t.innerHTML=e:e!=null&&t.appendChild(document.createTextNode(String(e)))}const _={start(t){if(a=document.querySelector(t.target),!a)throw new Error(`[tina4] Router target '${t.target}' not found in DOM`);l=t.mode??"history",window.addEventListener("popstate",d),l==="hash"&&window.addEventListener("hashchange",d),document.addEventListener("click",e=>{var s;if(e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;const r=e.target.closest("a[href]");if(!r||r.origin!==location.origin||r.hasAttribute("target")||r.hasAttribute("download")||(s=r.getAttribute("rel"))!=null&&s.includes("external"))return;e.preventDefault();const n=l==="hash"?r.getAttribute("href"):r.pathname;v(n)}),d()},on(t,e){return c.push(e),()=>{const r=c.indexOf(e);r>=0&&c.splice(r,1)}}};function x(){return p.map(t=>({pattern:t.pattern,hasGuard:!!t.guard}))}function S(){for(const t of u)t();u=[],w=0,p=[],a=null,l="history",c.length=0}exports._getRoutes=x;exports._resetRouter=S;exports.navigate=v;exports.route=R;exports.router=_;
|
package/dist/index.es.js
CHANGED
|
@@ -1,94 +1,105 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
r
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { a as y } from "./signal.es.js";
|
|
2
|
+
let p = [], a = null, l = "history";
|
|
3
|
+
const c = [];
|
|
4
|
+
let u = [], w = 0;
|
|
5
|
+
function R(t, e) {
|
|
6
|
+
const r = [];
|
|
7
|
+
let n;
|
|
8
|
+
t === "*" ? n = ".*" : n = t.replace(/\{(\w+)\}/g, (f, i) => (r.push(i), "([^/]+)"));
|
|
9
|
+
const s = new RegExp(`^${n}$`);
|
|
10
|
+
typeof e == "function" ? p.push({ pattern: t, regex: s, paramNames: r, handler: e }) : p.push({
|
|
11
|
+
pattern: t,
|
|
12
|
+
regex: s,
|
|
13
|
+
paramNames: r,
|
|
12
14
|
handler: e.handler,
|
|
13
15
|
guard: e.guard
|
|
14
16
|
});
|
|
15
17
|
}
|
|
16
|
-
function
|
|
17
|
-
if (
|
|
18
|
+
function x(t, e) {
|
|
19
|
+
if (l === "hash")
|
|
18
20
|
if (e != null && e.replace) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
+
const r = new URL(location.href);
|
|
22
|
+
r.hash = "#" + t, history.replaceState(null, "", r.toString()), d();
|
|
21
23
|
} else
|
|
22
|
-
location.hash = "#" +
|
|
24
|
+
location.hash = "#" + t;
|
|
23
25
|
else
|
|
24
|
-
e != null && e.replace ? history.replaceState(null, "",
|
|
26
|
+
e != null && e.replace ? history.replaceState(null, "", t) : history.pushState(null, "", t), d();
|
|
25
27
|
}
|
|
26
|
-
function
|
|
27
|
-
if (!
|
|
28
|
-
const
|
|
29
|
-
for (const
|
|
30
|
-
const
|
|
31
|
-
if (!
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
}),
|
|
36
|
-
const
|
|
37
|
-
if (
|
|
38
|
-
if (typeof
|
|
39
|
-
|
|
28
|
+
function d() {
|
|
29
|
+
if (!a) return;
|
|
30
|
+
const t = performance.now(), e = ++w, r = l === "hash" ? location.hash.slice(1) || "/" : location.pathname;
|
|
31
|
+
for (const n of p) {
|
|
32
|
+
const s = r.match(n.regex);
|
|
33
|
+
if (!s) continue;
|
|
34
|
+
const f = {};
|
|
35
|
+
if (n.paramNames.forEach((o, h) => {
|
|
36
|
+
f[o] = decodeURIComponent(s[h + 1]);
|
|
37
|
+
}), n.guard) {
|
|
38
|
+
const o = n.guard();
|
|
39
|
+
if (o === !1) return;
|
|
40
|
+
if (typeof o == "string") {
|
|
41
|
+
x(o, { replace: !0 });
|
|
40
42
|
return;
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
for (const o of u) o();
|
|
46
|
+
u = [], a.innerHTML = "";
|
|
47
|
+
const i = [];
|
|
48
|
+
y(i);
|
|
49
|
+
const m = n.handler(f);
|
|
50
|
+
if (m instanceof Promise)
|
|
51
|
+
m.then((o) => {
|
|
52
|
+
if (y(null), e !== w) {
|
|
53
|
+
for (const g of i) g();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
v(a, o), u = i;
|
|
57
|
+
const h = performance.now() - t;
|
|
58
|
+
for (const g of c) g({ path: r, params: f, pattern: n.pattern, durationMs: h });
|
|
49
59
|
});
|
|
50
60
|
else {
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
for (const
|
|
61
|
+
y(null), v(a, m), u = i;
|
|
62
|
+
const o = performance.now() - t;
|
|
63
|
+
for (const h of c) h({ path: r, params: f, pattern: n.pattern, durationMs: o });
|
|
54
64
|
}
|
|
55
65
|
return;
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
|
-
function
|
|
59
|
-
e instanceof DocumentFragment || e instanceof Node ?
|
|
68
|
+
function v(t, e) {
|
|
69
|
+
e instanceof DocumentFragment || e instanceof Node ? t.appendChild(e) : typeof e == "string" ? t.innerHTML = e : e != null && t.appendChild(document.createTextNode(String(e)));
|
|
60
70
|
}
|
|
61
|
-
const
|
|
62
|
-
start(
|
|
63
|
-
if (
|
|
64
|
-
throw new Error(`[tina4] Router target '${
|
|
65
|
-
|
|
66
|
-
var
|
|
71
|
+
const S = {
|
|
72
|
+
start(t) {
|
|
73
|
+
if (a = document.querySelector(t.target), !a)
|
|
74
|
+
throw new Error(`[tina4] Router target '${t.target}' not found in DOM`);
|
|
75
|
+
l = t.mode ?? "history", window.addEventListener("popstate", d), l === "hash" && window.addEventListener("hashchange", d), document.addEventListener("click", (e) => {
|
|
76
|
+
var s;
|
|
67
77
|
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
68
|
-
const
|
|
69
|
-
if (!
|
|
78
|
+
const r = e.target.closest("a[href]");
|
|
79
|
+
if (!r || r.origin !== location.origin || r.hasAttribute("target") || r.hasAttribute("download") || (s = r.getAttribute("rel")) != null && s.includes("external")) return;
|
|
70
80
|
e.preventDefault();
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
}),
|
|
81
|
+
const n = l === "hash" ? r.getAttribute("href") : r.pathname;
|
|
82
|
+
x(n);
|
|
83
|
+
}), d();
|
|
74
84
|
},
|
|
75
|
-
on(
|
|
76
|
-
return
|
|
77
|
-
const
|
|
78
|
-
|
|
85
|
+
on(t, e) {
|
|
86
|
+
return c.push(e), () => {
|
|
87
|
+
const r = c.indexOf(e);
|
|
88
|
+
r >= 0 && c.splice(r, 1);
|
|
79
89
|
};
|
|
80
90
|
}
|
|
81
91
|
};
|
|
82
|
-
function
|
|
83
|
-
return
|
|
92
|
+
function L() {
|
|
93
|
+
return p.map((t) => ({ pattern: t.pattern, hasGuard: !!t.guard }));
|
|
84
94
|
}
|
|
85
|
-
function
|
|
86
|
-
|
|
95
|
+
function b() {
|
|
96
|
+
for (const t of u) t();
|
|
97
|
+
u = [], w = 0, p = [], a = null, l = "history", c.length = 0;
|
|
87
98
|
}
|
|
88
99
|
export {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
L as _,
|
|
101
|
+
S as a,
|
|
102
|
+
b,
|
|
103
|
+
x as n,
|
|
104
|
+
R as r
|
|
94
105
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";let s=null,f=null;function p(e){f=e}let i=null,a=null;function S(e,t){i=e,a=t}let c=0;const d=new Set;function b(e,t){let n=e;const u=new Set,o={_t4:!0,get value(){return s&&u.add(s),n},set value(r){if(Object.is(r,n))return;const g=n;if(n=r,o._debugInfo&&o._debugInfo.updateCount++,a&&a(o,g,r),c>0)for(const l of u)d.add(l);else for(const l of[...u])l()},_subscribe(r){return u.add(r),()=>{u.delete(r)}},peek(){return n}};return i&&(o._debugInfo={label:t,createdAt:Date.now(),updateCount:0,subs:u},i(o,t)),o}function h(e){const t=b(void 0);return _(()=>{t.value=e()}),{_t4:!0,get value(){return t.value},set value(n){throw new Error("[tina4] computed signals are read-only")},_subscribe(n){return t._subscribe(n)},peek(){return t.peek()}}}function _(e){let t=!1;const n=()=>{if(t)return;const o=s;s=n;try{e()}finally{s=o}};n();const u=()=>{t=!0};return f&&f.push(u),u}function v(e){c++;try{e()}finally{if(c--,c===0){const t=[...d];d.clear();for(const n of t)n()}}}function y(e){return e!==null&&typeof e=="object"&&e._t4===!0}exports.__setDebugSignalHooks=S;exports._setEffectCollector=p;exports.batch=v;exports.computed=h;exports.effect=_;exports.isSignal=y;exports.signal=b;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
let s = null, a = null;
|
|
2
|
+
function g(e) {
|
|
3
|
+
a = e;
|
|
4
|
+
}
|
|
5
|
+
let f = null, i = null;
|
|
6
|
+
function v(e, t) {
|
|
7
|
+
f = e, i = t;
|
|
8
|
+
}
|
|
9
|
+
let c = 0;
|
|
10
|
+
const d = /* @__PURE__ */ new Set();
|
|
11
|
+
function _(e, t) {
|
|
12
|
+
let n = e;
|
|
13
|
+
const u = /* @__PURE__ */ new Set(), r = {
|
|
14
|
+
_t4: !0,
|
|
15
|
+
get value() {
|
|
16
|
+
return s && u.add(s), n;
|
|
17
|
+
},
|
|
18
|
+
set value(o) {
|
|
19
|
+
if (Object.is(o, n)) return;
|
|
20
|
+
const b = n;
|
|
21
|
+
if (n = o, r._debugInfo && r._debugInfo.updateCount++, i && i(r, b, o), c > 0)
|
|
22
|
+
for (const l of u) d.add(l);
|
|
23
|
+
else
|
|
24
|
+
for (const l of [...u]) l();
|
|
25
|
+
},
|
|
26
|
+
_subscribe(o) {
|
|
27
|
+
return u.add(o), () => {
|
|
28
|
+
u.delete(o);
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
peek() {
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
return f && (r._debugInfo = { label: t, createdAt: Date.now(), updateCount: 0, subs: u }, f(r, t)), r;
|
|
36
|
+
}
|
|
37
|
+
function h(e) {
|
|
38
|
+
const t = _(void 0);
|
|
39
|
+
return p(() => {
|
|
40
|
+
t.value = e();
|
|
41
|
+
}), {
|
|
42
|
+
_t4: !0,
|
|
43
|
+
get value() {
|
|
44
|
+
return t.value;
|
|
45
|
+
},
|
|
46
|
+
set value(n) {
|
|
47
|
+
throw new Error("[tina4] computed signals are read-only");
|
|
48
|
+
},
|
|
49
|
+
_subscribe(n) {
|
|
50
|
+
return t._subscribe(n);
|
|
51
|
+
},
|
|
52
|
+
peek() {
|
|
53
|
+
return t.peek();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function p(e) {
|
|
58
|
+
let t = !1;
|
|
59
|
+
const n = () => {
|
|
60
|
+
if (t) return;
|
|
61
|
+
const r = s;
|
|
62
|
+
s = n;
|
|
63
|
+
try {
|
|
64
|
+
e();
|
|
65
|
+
} finally {
|
|
66
|
+
s = r;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
n();
|
|
70
|
+
const u = () => {
|
|
71
|
+
t = !0;
|
|
72
|
+
};
|
|
73
|
+
return a && a.push(u), u;
|
|
74
|
+
}
|
|
75
|
+
function y(e) {
|
|
76
|
+
c++;
|
|
77
|
+
try {
|
|
78
|
+
e();
|
|
79
|
+
} finally {
|
|
80
|
+
if (c--, c === 0) {
|
|
81
|
+
const t = [...d];
|
|
82
|
+
d.clear();
|
|
83
|
+
for (const n of t) n();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function S(e) {
|
|
88
|
+
return e !== null && typeof e == "object" && e._t4 === !0;
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
v as _,
|
|
92
|
+
g as a,
|
|
93
|
+
y as b,
|
|
94
|
+
h as c,
|
|
95
|
+
p as e,
|
|
96
|
+
S as i,
|
|
97
|
+
_ as s
|
|
98
|
+
};
|
package/dist/tina4.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./signal.cjs.js"),r=require("./core.cjs.js"),i=require("./component.cjs.js"),t=require("./index.cjs.js"),a=require("./api.cjs.js"),n=require("./pwa.cjs.js");exports.batch=e.batch;exports.computed=e.computed;exports.effect=e.effect;exports.isSignal=e.isSignal;exports.signal=e.signal;exports.html=r.html;exports.Tina4Element=i.Tina4Element;exports.navigate=t.navigate;exports.route=t.route;exports.router=t.router;exports.api=a.api;exports.pwa=n.pwa;
|
package/dist/tina4.es.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { html as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { b as e, c as o, e as t, i as s, s as m } from "./signal.es.js";
|
|
2
|
+
import { html as f } from "./core.es.js";
|
|
3
|
+
import { T as n } from "./component.es.js";
|
|
4
|
+
import { n as c, r as l, a as g } from "./index.es.js";
|
|
5
|
+
import { api as b } from "./api.es.js";
|
|
6
|
+
import { pwa as T } from "./pwa.es.js";
|
|
6
7
|
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
n as Tina4Element,
|
|
9
|
+
b as api,
|
|
10
|
+
e as batch,
|
|
11
|
+
o as computed,
|
|
12
|
+
t as effect,
|
|
13
|
+
f as html,
|
|
14
|
+
s as isSignal,
|
|
15
|
+
c as navigate,
|
|
16
|
+
T as pwa,
|
|
17
|
+
l as route,
|
|
18
|
+
g as router,
|
|
19
|
+
m as signal
|
|
19
20
|
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -193,6 +193,29 @@ pwa.register({
|
|
|
193
193
|
});
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
+
### Debug Overlay
|
|
197
|
+
|
|
198
|
+
A built-in debug overlay that shows live signal values, component tree, route history, and API calls.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
// Always-on (remove for production)
|
|
202
|
+
import 'tina4js/debug';
|
|
203
|
+
|
|
204
|
+
// Dev-only (recommended) — tree-shaken out of production builds
|
|
205
|
+
if (import.meta.env.DEV) import('tina4js/debug');
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Once enabled, toggle the overlay with **Ctrl+Shift+D**.
|
|
209
|
+
|
|
210
|
+
The overlay shows four tabs:
|
|
211
|
+
|
|
212
|
+
| Tab | What it shows |
|
|
213
|
+
|-----|---------------|
|
|
214
|
+
| **Signals** | All signals with current value, subscriber count, and update count |
|
|
215
|
+
| **Components** | Mounted `Tina4Element` web components |
|
|
216
|
+
| **Routes** | Navigation history with timing |
|
|
217
|
+
| **API** | Intercepted `api.*` requests and responses |
|
|
218
|
+
|
|
196
219
|
---
|
|
197
220
|
|
|
198
221
|
## Deployment Modes
|
|
@@ -215,6 +238,18 @@ npm run build # production build
|
|
|
215
238
|
npm run dev # dev server
|
|
216
239
|
```
|
|
217
240
|
|
|
241
|
+
## Changelog
|
|
242
|
+
|
|
243
|
+
### 1.0.2
|
|
244
|
+
- **Fix:** Router now disposes reactive effects when navigating between routes. Previously, signal subscriptions created by `html` templates survived DOM removal via `innerHTML = ''`, causing duplicate renders when revisiting a page.
|
|
245
|
+
- **Fix:** Stale async route handlers are discarded if navigation occurs before they resolve.
|
|
246
|
+
|
|
247
|
+
### 1.0.1
|
|
248
|
+
- Debug overlay module with signal, component, route, and API inspectors
|
|
249
|
+
- Todo app example and exports map file extension fixes
|
|
250
|
+
- CLI scaffolding tool and TINA4.md AI context file
|
|
251
|
+
- Fetch, PWA, integration, and size tests (102 total)
|
|
252
|
+
|
|
218
253
|
## License
|
|
219
254
|
|
|
220
255
|
MIT
|