@tooey/ui 1.0.0 → 1.4.0
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/tooey.d.ts +61 -3
- package/dist/tooey.d.ts.map +1 -0
- package/dist/tooey.esm.js +1 -1
- package/dist/tooey.esm.js.map +3 -3
- package/dist/tooey.js +1 -1
- package/dist/tooey.js.map +3 -3
- package/package.json +9 -5
- package/readme.md +27 -0
package/dist/tooey.d.ts
CHANGED
|
@@ -31,6 +31,28 @@
|
|
|
31
31
|
*/
|
|
32
32
|
type StateValue = unknown;
|
|
33
33
|
type StateStore = Record<string, Signal<StateValue>>;
|
|
34
|
+
type ThemeValue = string | number;
|
|
35
|
+
type ThemeCategory = Record<string, ThemeValue>;
|
|
36
|
+
interface Theme {
|
|
37
|
+
colors?: ThemeCategory;
|
|
38
|
+
spacing?: ThemeCategory;
|
|
39
|
+
radius?: ThemeCategory;
|
|
40
|
+
fonts?: ThemeCategory;
|
|
41
|
+
[key: string]: ThemeCategory | undefined;
|
|
42
|
+
}
|
|
43
|
+
interface TooeyPlugin {
|
|
44
|
+
name: string;
|
|
45
|
+
onInit?(instance: TooeyInstance): void;
|
|
46
|
+
onDestroy?(instance: TooeyInstance): void;
|
|
47
|
+
beforeRender?(spec: NodeSpec, ctx: RenderContext): NodeSpec;
|
|
48
|
+
afterRender?(el: HTMLElement, spec: NodeSpec): void;
|
|
49
|
+
onStateChange?(key: string, oldVal: unknown, newVal: unknown): void;
|
|
50
|
+
extend?: Record<string, (this: TooeyInstance, ...args: unknown[]) => unknown>;
|
|
51
|
+
}
|
|
52
|
+
interface RenderOptions {
|
|
53
|
+
theme?: Theme;
|
|
54
|
+
plugins?: TooeyPlugin[];
|
|
55
|
+
}
|
|
34
56
|
interface Signal<T> {
|
|
35
57
|
(): T;
|
|
36
58
|
set(v: T | ((prev: T) => T)): void;
|
|
@@ -39,6 +61,7 @@ interface Signal<T> {
|
|
|
39
61
|
type Op = '+' | '-' | '!' | '~' | '<' | '>' | 'X' | '.';
|
|
40
62
|
type EventHandler = [string, Op, unknown?] | (() => void) | string;
|
|
41
63
|
interface Props {
|
|
64
|
+
show?: string;
|
|
42
65
|
g?: number | string;
|
|
43
66
|
p?: number | string;
|
|
44
67
|
m?: number | string;
|
|
@@ -108,6 +131,7 @@ interface Props {
|
|
|
108
131
|
s?: Record<string, unknown>;
|
|
109
132
|
}
|
|
110
133
|
type ComponentType = 'V' | 'H' | 'D' | 'G' | 'T' | 'B' | 'I' | 'Ta' | 'S' | 'C' | 'R' | 'Tb' | 'Th' | 'Tbd' | 'Tr' | 'Td' | 'Tc' | 'Ul' | 'Ol' | 'Li' | 'M' | 'L' | 'Sv';
|
|
134
|
+
type Component<P extends Props = Props> = (props?: P, children?: NodeSpec[]) => NodeSpec;
|
|
111
135
|
type StateRef = {
|
|
112
136
|
$: string;
|
|
113
137
|
};
|
|
@@ -129,7 +153,9 @@ interface MapNode {
|
|
|
129
153
|
key?: string;
|
|
130
154
|
}
|
|
131
155
|
type Content = string | number | StateRef | NodeSpec[] | IfNode | MapNode;
|
|
132
|
-
type
|
|
156
|
+
type FunctionNodeSpec = [Component<any>, Content?, (Props & Record<string, unknown>)?];
|
|
157
|
+
type BuiltinNodeSpec = [ComponentType, Content?, Props?];
|
|
158
|
+
type NodeSpec = BuiltinNodeSpec | FunctionNodeSpec | IfNode | MapNode;
|
|
133
159
|
interface TooeySpec {
|
|
134
160
|
s?: Record<string, StateValue>;
|
|
135
161
|
r: NodeSpec;
|
|
@@ -143,6 +169,8 @@ type ErrorHandler = (error: ErrorInfo) => void;
|
|
|
143
169
|
interface RenderContext {
|
|
144
170
|
cleanups: Array<() => void>;
|
|
145
171
|
state: StateStore;
|
|
172
|
+
theme?: Theme;
|
|
173
|
+
plugins?: TooeyPlugin[];
|
|
146
174
|
onError?: ErrorHandler;
|
|
147
175
|
}
|
|
148
176
|
interface ErrorBoundaryNode {
|
|
@@ -154,6 +182,24 @@ interface ErrorBoundaryNode {
|
|
|
154
182
|
declare function signal<T>(initial: T): Signal<T>;
|
|
155
183
|
declare function batch(fn: () => void): void;
|
|
156
184
|
declare function effect(fn: () => void, ctx?: RenderContext): () => void;
|
|
185
|
+
interface ComputedSignal<T> {
|
|
186
|
+
(): T;
|
|
187
|
+
sub(fn: () => void): () => void;
|
|
188
|
+
}
|
|
189
|
+
declare function computed<T>(fn: () => T): ComputedSignal<T>;
|
|
190
|
+
interface AsyncState<T> {
|
|
191
|
+
data: T | null;
|
|
192
|
+
loading: boolean;
|
|
193
|
+
error: string | null;
|
|
194
|
+
[key: string]: unknown;
|
|
195
|
+
}
|
|
196
|
+
interface AsyncSpec<T> {
|
|
197
|
+
s: AsyncState<T>;
|
|
198
|
+
init(instance: TooeyInstance): Promise<void>;
|
|
199
|
+
}
|
|
200
|
+
declare function async$<T>(promiseOrFn: Promise<T> | (() => Promise<T>), options?: {
|
|
201
|
+
onError?: (error: Error) => void;
|
|
202
|
+
}): AsyncSpec<T>;
|
|
157
203
|
interface TooeyInstance {
|
|
158
204
|
state: StateStore;
|
|
159
205
|
el: HTMLElement | null;
|
|
@@ -161,8 +207,19 @@ interface TooeyInstance {
|
|
|
161
207
|
update(newSpec: TooeySpec): void;
|
|
162
208
|
get(key: string): unknown;
|
|
163
209
|
set(key: string, value: unknown): void;
|
|
210
|
+
[key: string]: unknown;
|
|
211
|
+
}
|
|
212
|
+
declare function render(container: HTMLElement, spec: TooeySpec, options?: RenderOptions): TooeyInstance;
|
|
213
|
+
interface CreateTooeyOptions {
|
|
214
|
+
theme?: Theme;
|
|
215
|
+
plugins?: TooeyPlugin[];
|
|
216
|
+
}
|
|
217
|
+
interface TooeyFactory {
|
|
218
|
+
render: (container: HTMLElement, spec: TooeySpec) => TooeyInstance;
|
|
219
|
+
theme: Theme;
|
|
220
|
+
plugins?: TooeyPlugin[];
|
|
164
221
|
}
|
|
165
|
-
declare function
|
|
222
|
+
declare function createTooey(themeOrOptions: Theme | CreateTooeyOptions): TooeyFactory;
|
|
166
223
|
declare function $(name: string): StateRef;
|
|
167
224
|
declare const V: "V";
|
|
168
225
|
declare const H: "H";
|
|
@@ -187,4 +244,5 @@ declare const Li: "Li";
|
|
|
187
244
|
declare const M: "M";
|
|
188
245
|
declare const L: "L";
|
|
189
246
|
declare const Sv: "Sv";
|
|
190
|
-
export { render, signal, effect, batch, $, V, H, D, G, T, B, I, Ta, S, C, R, Tb, Th, Tbd, Tr, Td, Tc, Ul, Ol, Li, M, L, Sv, TooeySpec, NodeSpec, Props, StateRef, TooeyInstance, IfNode, MapNode, ErrorBoundaryNode, ErrorInfo, ErrorHandler };
|
|
247
|
+
export { render, createTooey, signal, effect, batch, computed, async$, $, V, H, D, G, T, B, I, Ta, S, C, R, Tb, Th, Tbd, Tr, Td, Tc, Ul, Ol, Li, M, L, Sv, TooeySpec, NodeSpec, Props, StateRef, TooeyInstance, TooeyFactory, CreateTooeyOptions, IfNode, MapNode, ErrorBoundaryNode, ErrorInfo, ErrorHandler, Component, Theme, RenderOptions, TooeyPlugin, ComputedSignal, AsyncSpec };
|
|
248
|
+
//# sourceMappingURL=tooey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooey.d.ts","sourceRoot":"","sources":["../src/tooey.ts"],"names":[],"mappings":"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"}
|
package/dist/tooey.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function D(n){return typeof n=="object"&&n!==null&&"boundary"in n&&n.boundary===!0}function O(n){let e=document.createElement("div");return e.style.cssText="padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px",e.textContent=`[tooey error] ${n.message}`,e}var v=null,H=0,C=new Set;function $(n){let e=n,t=new Set,s=()=>(v&&t.add(v),e);return s.set=o=>{let l=typeof o=="function"?o(e):o;l!==e&&(e=l,H>0?t.forEach(r=>C.add(r)):t.forEach(r=>r()))},s.sub=o=>(t.add(o),()=>t.delete(o)),s}function W(n){H++;try{n()}finally{if(H--,H===0){let e=C;C=new Set,e.forEach(t=>t())}}}function w(n,e){let t=!0,s=()=>{if(t){v=s;try{n()}finally{v=null}}};s();let o=()=>{t=!1,v=null};return e&&e.cleanups.push(o),o}function j(n,e,t){try{switch(e){case"+":n.set(s=>s+(typeof t=="number"?t:1));break;case"-":n.set(s=>s-(typeof t=="number"?t:1));break;case"!":n.set(t);break;case"~":n.set(s=>!s);break;case"<":n.set(s=>[...s,t]);break;case">":n.set(s=>[t,...s]);break;case"X":n.set(s=>{let o=s;return typeof t=="number"?o.filter((l,r)=>r!==t):typeof t=="function"?o.filter((l,r)=>!t(l,r)):o.filter(l=>l!==t)});break;case".":Array.isArray(t)&&t.length===2&&n.set(s=>({...s,[t[0]]:t[1]}));break}}catch(s){console.warn("[tooey] state operation error:",e,s)}}function L(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&"$"in n}function N(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("if"in n||"?"in n)}function R(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("map"in n||"m"in n)}function p(n,e){if(L(n)){let t=e[n.$];if(!t){console.warn(`[tooey] unknown state key: "${n.$}"`);return}return t()}return n}function u(n){if(n!==void 0)return typeof n=="number"?`${n}px`:n}var z={c:"center",sb:"space-between",sa:"space-around",se:"space-evenly",fe:"flex-end",fs:"flex-start",st:"stretch",bl:"baseline"};function A(n){if(n!==void 0)return z[n]||n}function U(n){if(typeof n!="string"||n.length<2)return null;let e=n[n.length-1];if(e==="+"||e==="-"||e==="~")return[n.slice(0,-1),e];let t=n.indexOf("!");if(t>0){let s=n.slice(0,t),o=n.slice(t+1),l=o;return o==="true"?l=!0:o==="false"?l=!1:!isNaN(Number(o))&&o!==""&&(l=Number(o)),[s,"!",l]}return null}var P=["http:","https:","mailto:","tel:","ftp:"];function q(n){if(!n||typeof n!="string")return!1;if(n.startsWith("/")||n.startsWith("#")||n.startsWith("."))return!0;try{let e=new URL(n,window.location.href);return P.includes(e.protocol)}catch{let e=n.toLowerCase().trim();return!["javascript:","data:","vbscript:"].some(s=>e.startsWith(s))}}function B(n,e){return n?q(n)?n:(console.warn(`[tooey] blocked unsafe URL in ${e}: "${n.slice(0,50)}..."`),null):null}function b(n,e,t,s,o){if(typeof n=="function")return n;let l;if(typeof n=="string"){let h=U(n);h?l=h:o==="+"?l=[n,"+"]:o==="-"?l=[n,"-"]:l=[n,"~"]}else l=n;let[r,a,d]=l;return()=>{let h=e[r];if(!h){console.warn(`[tooey] click handler: unknown state key "${r}"`);return}let i=d;if(s&&typeof i=="string"){if(i==="$index")i=s.index;else if(i==="$item")i=s.item;else if(i.startsWith("$item.")){let c=i.substring(6);i=s.item?.[c]}}if(a==="!"&&d===void 0&&t){let c=t.target;i=c.type==="checkbox"?c.checked:c.value}j(h,a,i)}}function _(n,e){let t=n.style;if(e.g!==void 0&&(t.gap=u(e.g)),e.p!==void 0&&(t.padding=u(e.p)),e.m!==void 0&&(t.margin=u(e.m)),e.w!==void 0&&(t.width=u(e.w)),e.h!==void 0&&(t.height=u(e.h)),e.mw!==void 0&&(t.maxWidth=u(e.mw)),e.mh!==void 0&&(t.maxHeight=u(e.mh)),e.bg!==void 0&&(t.background=e.bg),e.fg!==void 0&&(t.color=e.fg),e.o!==void 0&&(t.opacity=String(e.o)),e.r!==void 0&&(t.borderRadius=u(e.r)),e.bw!==void 0&&(t.borderWidth=u(e.bw)),e.bc!==void 0&&(t.borderColor=e.bc),e.bs!==void 0&&(t.borderStyle=e.bs),e.pos!==void 0){let s={rel:"relative",abs:"absolute",fix:"fixed",sticky:"sticky"};t.position=s[e.pos]||e.pos}e.z!==void 0&&(t.zIndex=String(e.z)),e.t!==void 0&&(t.top=u(e.t)),e.l!==void 0&&(t.left=u(e.l)),(typeof e.b=="number"||typeof e.b=="string"&&!Array.isArray(e.b))&&(t.bottom=u(e.b)),e.rt!==void 0&&(t.right=u(e.rt)),e.fs!==void 0&&(t.fontSize=u(e.fs)),e.fw!==void 0&&(t.fontWeight=String(e.fw)),e.ff!==void 0&&(t.fontFamily=e.ff),e.ta!==void 0&&(t.textAlign=e.ta),e.td!==void 0&&(t.textDecoration=e.td),e.lh!==void 0&&(t.lineHeight=typeof e.lh=="number"?String(e.lh):e.lh),e.ls!==void 0&&(t.letterSpacing=u(e.ls)),e.ai!==void 0&&(t.alignItems=A(e.ai)),e.jc!==void 0&&(t.justifyContent=A(e.jc)),e.flw!==void 0&&(t.flexWrap=A(e.flw)),e.cur!==void 0&&(t.cursor=e.cur),e.ov!==void 0&&(t.overflow=e.ov),e.pe!==void 0&&(t.pointerEvents=e.pe),e.us!==void 0&&(t.userSelect=e.us),e.sh!==void 0&&(t.boxShadow=e.sh),e.tr!==void 0&&(t.transform=e.tr),e.s&&Object.entries(e.s).forEach(([s,o])=>{t[s]=String(o)})}function y(n,e,t){let{state:s}=e;if(D(n)){let i=document.createElement("div");i.style.display="contents";try{let c={cleanups:[],state:s,onError:n.onError||e.onError},f=y(n.child,c,t);f&&(i.appendChild(f),e.cleanups.push(...c.cleanups))}catch(c){let f={message:c instanceof Error?c.message:String(c),stack:c instanceof Error?c.stack:void 0};if(n.onError&&n.onError(f),n.fallback)try{let m=y(n.fallback,e,t);m&&i.appendChild(m)}catch{i.appendChild(O(f))}else i.appendChild(O(f))}return i}if(N(n)){let i=document.createElement("div");i.style.display="contents";let c=null,f=null,m=n.if??n["?"],S=n.then??n.t,g=n.else??n.e,E=n.eq??n.is;return w(()=>{f&&(f.cleanups.forEach(I=>I()),f.cleanups=[]),c&&(i.innerHTML="",c=null);let k=typeof m=="string"?s[m]?.():p(m,s),M;E!==void 0?M=k===E:M=!!k;let T=M?S:g;T&&(f={cleanups:[],state:s},Array.isArray(T)&&T.length>0&&Array.isArray(T[0])?T.forEach(I=>{let V=y(I,f,t);V&&i.appendChild(V)}):(c=y(T,f,t),c&&i.appendChild(c)))},e),i}if(R(n)){let i=document.createElement("div");i.style.display="contents";let c=null,f=n.map??n.m,m=n.as??n.a;return w(()=>{c&&(c.cleanups.forEach(E=>E()),c.cleanups=[]),i.innerHTML="";let g=typeof f=="string"?s[f]?.():p(f,s);!Array.isArray(g)||!m||(c={cleanups:[],state:s},g.forEach((E,x)=>{let k=y(m,c,{item:E,index:x});k&&i.appendChild(k)}))},e),i}if(!Array.isArray(n)||n.length===0)return console.warn("[tooey] invalid node spec:",n),null;let[o,l,r={}]=n,a;switch(o){case"V":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="column";break;case"H":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="row";break;case"G":a=document.createElement("div"),a.style.display="grid",r.cols&&(a.style.gridTemplateColumns=typeof r.cols=="number"?`repeat(${r.cols}, 1fr)`:r.cols),r.rows&&(a.style.gridTemplateRows=typeof r.rows=="number"?`repeat(${r.rows}, 1fr)`:r.rows);break;case"D":a=document.createElement("div");break;case"T":a=document.createElement("span");break;case"B":a=document.createElement("button");break;case"I":a=document.createElement("input"),a.type=r.type||"text",r.ph&&(a.placeholder=r.ph),r.ro&&(a.readOnly=!0);break;case"Ta":a=document.createElement("textarea"),r.ph&&(a.placeholder=r.ph),r.rw&&(a.rows=r.rw),r.ro&&(a.readOnly=!0);break;case"S":a=document.createElement("select"),r.opts&&r.opts.forEach(i=>{let c=document.createElement("option");c.value=i.v,c.textContent=i.l,a.appendChild(c)});break;case"C":a=document.createElement("input"),a.type="checkbox";break;case"R":a=document.createElement("input"),a.type="radio";break;case"Tb":a=document.createElement("table");break;case"Th":a=document.createElement("thead");break;case"Tbd":a=document.createElement("tbody");break;case"Tr":a=document.createElement("tr");break;case"Td":a=document.createElement("td"),r.sp&&(a.colSpan=r.sp),r.rsp&&(a.rowSpan=r.rsp);break;case"Tc":a=document.createElement("th"),r.sp&&(a.colSpan=r.sp),r.rsp&&(a.rowSpan=r.rsp);break;case"Ul":a=document.createElement("ul");break;case"Ol":a=document.createElement("ol");break;case"Li":a=document.createElement("li");break;case"M":if(a=document.createElement("img"),r.src){let i=B(r.src,"src");i&&(a.src=i)}r.alt&&(a.alt=r.alt);break;case"L":if(a=document.createElement("a"),r.href){let i=B(r.href,"href");i&&(a.href=i)}break;case"Sv":a=document.createElementNS("http://www.w3.org/2000/svg","svg");break;default:console.warn(`[tooey] unknown component type: ${o}`),a=document.createElement("div")}if(r.cls&&(a.className=r.cls),r.id&&(a.id=r.id),r.dis&&(a.disabled=!0),_(a,r),l!==void 0){if(Array.isArray(l)&&l.length>0&&(Array.isArray(l[0])||N(l[0])||R(l[0])))l.forEach(i=>{let c=y(i,e,t);c&&a.appendChild(c)});else if(N(l)||R(l)){let i=y(l,e,t);i&&a.appendChild(i)}else if(L(l))w(()=>{let i=p(l,s);o==="I"||o==="Ta"?a.value=String(i??""):o==="C"||o==="R"?a.checked=!!i:a.textContent=String(i??"")},e);else if(typeof l=="string"||typeof l=="number"){let i=String(l);t&&(typeof t.item=="object"&&t.item!==null&&(i=i.replace(/\$item\.(\w+)/g,(c,f)=>String(t.item[f]??""))),i=i.replace(/\$item/g,String(t.item)),i=i.replace(/\$index/g,String(t.index))),o==="I"||o==="Ta"?a.value=i:o!=="S"&&(a.textContent=i)}}r.v!==void 0&&L(r.v)&&w(()=>{let i=p(r.v,s);o==="I"||o==="S"||o==="Ta"?a.value=String(i??""):(o==="C"||o==="R")&&(a.checked=!!i)},e),r.ch!==void 0&&(L(r.ch)?w(()=>{let i=p(r.ch,s);a.checked=!!i},e):a.checked=!!r.ch);let d=(i,c)=>{a.addEventListener(i,c),e.cleanups.push(()=>a.removeEventListener(i,c))},h=o==="B"&&(typeof l=="string"||typeof l=="number")?String(l):void 0;if(r.c&&d("click",i=>b(r.c,s,i,t,h)()),r.x){let i=r.x;d("input",c=>{if(typeof i=="function")i();else{let f,m;if(typeof i=="string"){let g=U(i);g?[f,m]=g:(f=i,m="!")}else[f,m]=i;let S=s[f];if(S){let g=c.target,E=o==="C"||o==="R"?g.checked:g.value;j(S,m,E)}}})}return r.f&&d("focus",i=>b(r.f,s,i,t)()),r.bl&&d("blur",i=>b(r.bl,s,i,t)()),r.k&&d("keydown",i=>b(r.k,s,i,t)()),r.ku&&d("keyup",i=>b(r.ku,s,i,t)()),r.kp&&d("keypress",i=>b(r.kp,s,i,t)()),r.e&&d("mouseenter",i=>b(r.e,s,i,t)()),r.lv&&d("mouseleave",i=>b(r.lv,s,i,t)()),r.sub&&d("submit",i=>{i.preventDefault(),b(r.sub,s,i,t)()}),a}function G(n,e){if(!n)throw new Error("[tooey] render requires a valid container element");if(!e||!e.r)throw new Error("[tooey] render requires a spec with a root node (r)");let t={};e.s&&Object.entries(e.s).forEach(([r,a])=>{t[r]=$(a)});let s={cleanups:[],state:t};n.innerHTML="";let o=y(e.r,s);o&&n.appendChild(o);let l={state:t,el:o,destroy(){s.cleanups.forEach(r=>r()),s.cleanups=[],n.innerHTML=""},update(r){if(r.s&&W(()=>{Object.entries(r.s).forEach(([a,d])=>{t[a]?t[a].set(d):t[a]=$(d)})}),r.r){s.cleanups.forEach(d=>d()),s.cleanups=[],n.innerHTML="";let a=y(r.r,s);a&&n.appendChild(a),l.el=a}},get(r){return t[r]?.()},set(r,a){t[r]&&t[r].set(a)}};return l}function F(n){return{$:n}}var K="V",X="H",J="D",Q="G",Y="T",Z="B",ee="I",ne="Ta",te="S",re="C",ie="R",ae="Tb",se="Th",oe="Tbd",le="Tr",ce="Td",fe="Tc",de="Ul",ue="Ol",me="Li",ge="M",be="L",ye="Sv";export{F as $,Z as B,re as C,J as D,Q as G,X as H,ee as I,be as L,me as Li,ge as M,ue as Ol,ie as R,te as S,ye as Sv,Y as T,ne as Ta,ae as Tb,oe as Tbd,fe as Tc,ce as Td,se as Th,le as Tr,de as Ul,K as V,W as batch,w as effect,G as render,$ as signal};
|
|
1
|
+
function $(n){return typeof n=="object"&&n!==null&&"boundary"in n&&n.boundary===!0}function O(n){let e=document.createElement("div");return e.style.cssText="padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px",e.textContent=`[tooey error] ${n.message}`,e}var T=null,L=0,I=new Set;function U(n){let e=n,i=new Set,r=(()=>(T&&i.add(T),e));return r.set=c=>{let d=typeof c=="function"?c(e):c;d!==e&&(e=d,L>0?i.forEach(t=>I.add(t)):i.forEach(t=>t()))},r.sub=c=>(i.add(c),()=>i.delete(c)),r}function z(n){L++;try{n()}finally{if(L--,L===0){let e=I;I=new Set,e.forEach(i=>i())}}}function v(n,e){let i=!0,r=()=>{if(i){T=r;try{n()}finally{T=null}}};r();let c=()=>{i=!1,T=null};return e&&e.cleanups.push(c),c}function Q(n){let e,i=!0,r=new Set,c=()=>{i=!0,L>0?r.forEach(t=>I.add(t)):r.forEach(t=>t())},d=(()=>{if(T&&r.add(T),i){let t=T;T=c;try{e=n()}finally{T=t}i=!1}return e});return d.sub=t=>(r.add(t),()=>r.delete(t)),d}function Y(n,e){return{s:{data:null,loading:!0,error:null},async init(i){try{let c=await(typeof n=="function"?n():n);i.set("data",c),i.set("loading",!1)}catch(r){let c=r instanceof Error?r.message:String(r);i.set("error",c),i.set("loading",!1),e?.onError&&r instanceof Error&&e.onError(r)}}}}function D(n,e,i){try{switch(e){case"+":n.set(r=>r+(typeof i=="number"?i:1));break;case"-":n.set(r=>r-(typeof i=="number"?i:1));break;case"!":n.set(i);break;case"~":n.set(r=>!r);break;case"<":n.set(r=>[...r,i]);break;case">":n.set(r=>[i,...r]);break;case"X":n.set(r=>{let c=r;return typeof i=="number"?c.filter((d,t)=>t!==i):typeof i=="function"?c.filter((d,t)=>!i(d,t)):c.filter(d=>d!==i)});break;case".":Array.isArray(i)&&i.length===2&&n.set(r=>({...r,[i[0]]:i[1]}));break}}catch(r){console.warn("[tooey] state operation error:",e,r)}}function R(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&"$"in n}function C(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("if"in n||"?"in n)}function N(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("map"in n||"m"in n)}function H(n,e){if(R(n)){let i=e[n.$];if(!i){console.warn(`[tooey] unknown state key: "${n.$}"`);return}return i()}return n}function _(n){if(n!==void 0)return typeof n=="number"?`${n}px`:n}function q(n,e){if(!e)return;let i=["colors","spacing","radius","fonts"];for(let r of i){let c=e[r];if(c&&n in c)return c[n]}for(let[r,c]of Object.entries(e))if(c&&!i.includes(r)&&n in c)return c[n]}var F={c:"center",sb:"space-between",sa:"space-around",se:"space-evenly",fe:"flex-end",fs:"flex-start",st:"stretch",bl:"baseline"};function P(n){if(n!==void 0)return F[n]||n}function W(n){if(typeof n!="string"||n.length<2)return null;let e=n[n.length-1];if(e==="+"||e==="-"||e==="~")return[n.slice(0,-1),e];let i=n.indexOf("!");if(i>0){let r=n.slice(0,i),c=n.slice(i+1),d=c;return c==="true"?d=!0:c==="false"?d=!1:!isNaN(Number(c))&&c!==""&&(d=Number(c)),[r,"!",d]}return null}var G=["http:","https:","mailto:","tel:","ftp:"];function K(n){if(!n||typeof n!="string")return!1;if(n.startsWith("/")||n.startsWith("#")||n.startsWith("."))return!0;try{let e=new URL(n,window.location.href);return G.includes(e.protocol)}catch{let e=n.toLowerCase().trim();return!["javascript:","data:","vbscript:"].some(r=>e.startsWith(r))}}function j(n,e){return n?K(n)?n:(console.warn(`[tooey] blocked unsafe URL in ${e}: "${n.slice(0,50)}..."`),null):null}function S(n,e,i,r,c){if(typeof n=="function")return n;let d;if(typeof n=="string"){let a=W(n);a?d=a:c==="+"?d=[n,"+"]:c==="-"?d=[n,"-"]:d=[n,"~"]}else d=n;let[t,s,g]=d;return()=>{let a=e[t];if(!a){console.warn(`[tooey] click handler: unknown state key "${t}"`);return}let l=g;if(r&&typeof l=="string"){if(l==="$index")l=r.index;else if(l==="$item")l=r.item;else if(l.startsWith("$item.")){let m=l.substring(6);l=r.item?.[m]}}if(s==="!"&&g===void 0&&i){let m=i.target;l=m.type==="checkbox"?m.checked:m.value}D(a,s,l)}}function x(n,e){if(n!==void 0){if(typeof n=="string"&&n.startsWith("$")){let i=n.slice(1),r=q(i,e);if(r!==void 0)return r;console.warn(`[tooey] unknown theme token: "${n}"`);return}return n}}function X(n,e,i){let r=n.style,c=t=>{let s=x(t,i);return _(s)},d=t=>{if(t===void 0)return;let s=x(t,i);return s!==void 0?String(s):void 0};if(e.g!==void 0){let t=c(e.g);t&&(r.gap=t)}if(e.p!==void 0){let t=c(e.p);t&&(r.padding=t)}if(e.m!==void 0){let t=c(e.m);t&&(r.margin=t)}if(e.w!==void 0){let t=c(e.w);t&&(r.width=t)}if(e.h!==void 0){let t=c(e.h);t&&(r.height=t)}if(e.mw!==void 0){let t=c(e.mw);t&&(r.maxWidth=t)}if(e.mh!==void 0){let t=c(e.mh);t&&(r.maxHeight=t)}if(e.bg!==void 0){let t=d(e.bg);t&&(r.background=t)}if(e.fg!==void 0){let t=d(e.fg);t&&(r.color=t)}if(e.o!==void 0&&(r.opacity=String(e.o)),e.r!==void 0){let t=c(e.r);t&&(r.borderRadius=t)}if(e.bw!==void 0){let t=c(e.bw);t&&(r.borderWidth=t)}if(e.bc!==void 0){let t=d(e.bc);t&&(r.borderColor=t)}if(e.bs!==void 0&&(r.borderStyle=e.bs),e.pos!==void 0){let t={rel:"relative",abs:"absolute",fix:"fixed",sticky:"sticky"};r.position=t[e.pos]||e.pos}if(e.z!==void 0&&(r.zIndex=String(e.z)),e.t!==void 0){let t=c(e.t);t&&(r.top=t)}if(e.l!==void 0){let t=c(e.l);t&&(r.left=t)}if(typeof e.b=="number"||typeof e.b=="string"&&!Array.isArray(e.b)){let t=c(e.b);t&&(r.bottom=t)}if(e.rt!==void 0){let t=c(e.rt);t&&(r.right=t)}if(e.fs!==void 0){let t=c(e.fs);t&&(r.fontSize=t)}if(e.fw!==void 0&&(r.fontWeight=String(e.fw)),e.ff!==void 0){let t=d(e.ff);t&&(r.fontFamily=t)}if(e.ta!==void 0&&(r.textAlign=e.ta),e.td!==void 0&&(r.textDecoration=e.td),e.lh!==void 0&&(r.lineHeight=typeof e.lh=="number"?String(e.lh):e.lh),e.ls!==void 0){let t=c(e.ls);t&&(r.letterSpacing=t)}if(e.ai!==void 0&&(r.alignItems=P(e.ai)),e.jc!==void 0&&(r.justifyContent=P(e.jc)),e.flw!==void 0&&(r.flexWrap=P(e.flw)),e.cur!==void 0&&(r.cursor=e.cur),e.ov!==void 0&&(r.overflow=e.ov),e.pe!==void 0&&(r.pointerEvents=e.pe),e.us!==void 0&&(r.userSelect=e.us),e.sh!==void 0){let t=d(e.sh);t&&(r.boxShadow=t)}e.tr!==void 0&&(r.transform=e.tr),e.s&&Object.entries(e.s).forEach(([t,s])=>{let g=x(s,i);g!==void 0&&(r[t]=String(g))})}function b(n,e,i){let{state:r}=e;if($(n)){let o=document.createElement("div");o.style.display="contents";try{let u={cleanups:[],state:r,onError:n.onError||e.onError},f=b(n.child,u,i);f&&(o.appendChild(f),e.cleanups.push(...u.cleanups))}catch(u){let f={message:u instanceof Error?u.message:String(u),stack:u instanceof Error?u.stack:void 0};if(n.onError&&n.onError(f),n.fallback)try{let y=b(n.fallback,e,i);y&&o.appendChild(y)}catch{o.appendChild(O(f))}else o.appendChild(O(f))}return o}if(C(n)){let o=document.createElement("div");o.style.display="contents";let u=null,f=null,y=n.if??n["?"],p=n.then??n.t,h=n.else??n.e,E=n.eq??n.is;return v(()=>{f&&(f.cleanups.forEach(V=>V()),f.cleanups=[]),u&&(o.innerHTML="",u=null);let w=typeof y=="string"?r[y]?.():H(y,r),A;E!==void 0?A=w===E:A=!!w;let k=A?p:h;k&&(f={cleanups:[],state:r},Array.isArray(k)&&k.length>0&&Array.isArray(k[0])?k.forEach(V=>{let B=b(V,f,i);B&&o.appendChild(B)}):(u=b(k,f,i),u&&o.appendChild(u)))},e),o}if(N(n)){let o=document.createElement("div");o.style.display="contents";let u=null,f=n.map??n.m,y=n.as??n.a;return v(()=>{u&&(u.cleanups.forEach(E=>E()),u.cleanups=[]),o.innerHTML="";let h=typeof f=="string"?r[f]?.():H(f,r);!Array.isArray(h)||!y||(u={cleanups:[],state:r},h.forEach((E,M)=>{let w=b(y,u,{item:E,index:M});w&&o.appendChild(w)}))},e),o}if(!Array.isArray(n)||n.length===0)return console.warn("[tooey] invalid node spec:",n),null;let c=n;if(e.plugins)for(let o of e.plugins)o.beforeRender&&(c=o.beforeRender(c,e));if(!Array.isArray(c))return b(c,e,i);let[d,t,s={}]=c;if(typeof d=="function"){let o=Array.isArray(t)&&t.length>0&&(Array.isArray(t[0])||C(t[0])||N(t[0])||typeof t[0]=="function")?t:void 0,u=d(s,o);return b(u,e,i)}let g=d;if(s.show!==void 0){let o=s.show,u=document.createElement("div");u.style.display="contents";let f=null,y=null;return v(()=>{if(y&&(y.cleanups.forEach(w=>w()),y.cleanups=[]),f&&(u.innerHTML="",f=null),!r[o]?.())return;let{show:E,...M}=s;y={cleanups:[],state:r,theme:e.theme,plugins:e.plugins},f=b([g,t,M],y,i),f&&(u.appendChild(f),e.cleanups.push(...y.cleanups))},e),u}let a;switch(g){case"V":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="column";break;case"H":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="row";break;case"G":a=document.createElement("div"),a.style.display="grid",s.cols&&(a.style.gridTemplateColumns=typeof s.cols=="number"?`repeat(${s.cols}, 1fr)`:s.cols),s.rows&&(a.style.gridTemplateRows=typeof s.rows=="number"?`repeat(${s.rows}, 1fr)`:s.rows);break;case"D":a=document.createElement("div");break;case"T":a=document.createElement("span");break;case"B":a=document.createElement("button");break;case"I":a=document.createElement("input"),a.type=s.type||"text",s.ph&&(a.placeholder=s.ph),s.ro&&(a.readOnly=!0);break;case"Ta":a=document.createElement("textarea"),s.ph&&(a.placeholder=s.ph),s.rw&&(a.rows=s.rw),s.ro&&(a.readOnly=!0);break;case"S":a=document.createElement("select"),s.opts&&s.opts.forEach(o=>{let u=document.createElement("option");u.value=o.v,u.textContent=o.l,a.appendChild(u)});break;case"C":a=document.createElement("input"),a.type="checkbox";break;case"R":a=document.createElement("input"),a.type="radio";break;case"Tb":a=document.createElement("table");break;case"Th":a=document.createElement("thead");break;case"Tbd":a=document.createElement("tbody");break;case"Tr":a=document.createElement("tr");break;case"Td":a=document.createElement("td"),s.sp&&(a.colSpan=s.sp),s.rsp&&(a.rowSpan=s.rsp);break;case"Tc":a=document.createElement("th"),s.sp&&(a.colSpan=s.sp),s.rsp&&(a.rowSpan=s.rsp);break;case"Ul":a=document.createElement("ul");break;case"Ol":a=document.createElement("ol");break;case"Li":a=document.createElement("li");break;case"M":if(a=document.createElement("img"),s.src){let o=j(s.src,"src");o&&(a.src=o)}s.alt&&(a.alt=s.alt);break;case"L":if(a=document.createElement("a"),s.href){let o=j(s.href,"href");o&&(a.href=o)}break;case"Sv":a=document.createElementNS("http://www.w3.org/2000/svg","svg");break;default:console.warn(`[tooey] unknown component type: ${g}`),a=document.createElement("div")}if(s.cls&&(a.className=s.cls),s.id&&(a.id=s.id),s.dis&&(a.disabled=!0),X(a,s,e.theme),t!==void 0){if(Array.isArray(t)&&t.length>0&&(Array.isArray(t[0])||C(t[0])||N(t[0])||$(t[0])))t.forEach(o=>{let u=b(o,e,i);u&&a.appendChild(u)});else if(C(t)||N(t)||$(t)){let o=b(t,e,i);o&&a.appendChild(o)}else if(R(t))v(()=>{let o=H(t,r);g==="I"||g==="Ta"?a.value=String(o??""):g==="C"||g==="R"?a.checked=!!o:a.textContent=String(o??"")},e);else if(typeof t=="string"||typeof t=="number"){let o=String(t);i&&(typeof i.item=="object"&&i.item!==null&&(o=o.replace(/\$item\.(\w+)/g,(u,f)=>String(i.item[f]??""))),o=o.replace(/\$item/g,String(i.item)),o=o.replace(/\$index/g,String(i.index))),g==="I"||g==="Ta"?a.value=o:g!=="S"&&(a.textContent=o)}}s.v!==void 0&&R(s.v)&&v(()=>{let o=H(s.v,r);g==="I"||g==="S"||g==="Ta"?a.value=String(o??""):(g==="C"||g==="R")&&(a.checked=!!o)},e),s.ch!==void 0&&(R(s.ch)?v(()=>{let o=H(s.ch,r);a.checked=!!o},e):a.checked=!!s.ch);let l=(o,u)=>{a.addEventListener(o,u),e.cleanups.push(()=>a.removeEventListener(o,u))},m=g==="B"&&(typeof t=="string"||typeof t=="number")?String(t):void 0;if(s.c&&l("click",o=>S(s.c,r,o,i,m)()),s.x){let o=s.x;l("input",u=>{if(typeof o=="function")o();else{let f,y;if(typeof o=="string"){let h=W(o);h?[f,y]=h:(f=o,y="!")}else[f,y]=o;let p=r[f];if(p){let h=u.target,E=g==="C"||g==="R"?h.checked:h.value;D(p,y,E)}}})}if(s.f&&l("focus",o=>S(s.f,r,o,i)()),s.bl&&l("blur",o=>S(s.bl,r,o,i)()),s.k&&l("keydown",o=>S(s.k,r,o,i)()),s.ku&&l("keyup",o=>S(s.ku,r,o,i)()),s.kp&&l("keypress",o=>S(s.kp,r,o,i)()),s.e&&l("mouseenter",o=>S(s.e,r,o,i)()),s.lv&&l("mouseleave",o=>S(s.lv,r,o,i)()),s.sub&&l("submit",o=>{o.preventDefault(),S(s.sub,r,o,i)()}),e.plugins)for(let o of e.plugins)o.afterRender&&o.afterRender(a,c);return a}function J(n,e,i){if(!n)throw new Error("[tooey] render requires a valid container element");if(!e||!e.r)throw new Error("[tooey] render requires a spec with a root node (r)");let r=i?.theme,c=i?.plugins||[],d=(l,m)=>{let o=U(m),u=o.set.bind(o);return o.set=f=>{let y=o();u(f);let p=o();y!==p&&c.forEach(h=>h.onStateChange?.(l,y,p))},o},t={};e.s&&Object.entries(e.s).forEach(([l,m])=>{t[l]=d(l,m)});let s={cleanups:[],state:t,theme:r,plugins:c};n.innerHTML="";let g=b(e.r,s);g&&n.appendChild(g);let a={state:t,el:g,destroy(){c.forEach(l=>l.onDestroy?.(a)),s.cleanups.forEach(l=>l()),s.cleanups=[],n.innerHTML=""},update(l){if(l.s&&z(()=>{Object.entries(l.s).forEach(([m,o])=>{t[m]?t[m].set(o):t[m]=d(m,o)})}),l.r){s.cleanups.forEach(o=>o()),s.cleanups=[],n.innerHTML="";let m=b(l.r,s);m&&n.appendChild(m),a.el=m}},get(l){return t[l]?.()},set(l,m){t[l]&&t[l].set(m)}};return c.forEach(l=>{l.extend&&Object.entries(l.extend).forEach(([m,o])=>{a[m]=o.bind(a)})}),c.forEach(l=>l.onInit?.(a)),a}function Z(n){let e=n&&("theme"in n||"plugins"in n),i=e?n.theme:n,r=e?n.plugins:void 0;return{render:(c,d)=>J(c,d,{theme:i,plugins:r}),theme:i,plugins:r}}function ee(n){return{$:n}}var ne="V",te="H",re="D",oe="G",ie="T",se="B",ae="I",ce="Ta",le="S",ue="C",de="R",fe="Tb",ge="Th",me="Tbd",ye="Tr",he="Td",be="Tc",Te="Ul",pe="Ol",Ee="Li",Se="M",we="L",ke="Sv";export{ee as $,se as B,ue as C,re as D,oe as G,te as H,ae as I,we as L,Ee as Li,Se as M,pe as Ol,de as R,le as S,ke as Sv,ie as T,ce as Ta,fe as Tb,me as Tbd,be as Tc,he as Td,ge as Th,ye as Tr,Te as Ul,ne as V,Y as async$,z as batch,Q as computed,Z as createTooey,v as effect,J as render,U as signal};
|
|
2
2
|
//# sourceMappingURL=tooey.esm.js.map
|
package/dist/tooey.esm.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/tooey.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * tooey - token-efficient ui library for llms\n *\n * component types:\n * layout: V (vstack), H (hstack), D (div), G (grid)\n * text & buttons: T (text/span), B (button)\n * inputs: I (input), Ta (textarea), S (select), C (checkbox), R (radio)\n * tables: Tb (table), Th (thead), Tbd (tbody), Tr (tr), Td (td), Tc (th)\n * lists: Ul (ul), Ol (ol), Li (li)\n * media & links: M (image), L (link), Sv (svg)\n *\n * props (short keys):\n * spacing: g (gap), p (padding), m (margin), w (width), h (height), mw, mh\n * colors: bg (background), fg (color), o (opacity)\n * borders: r (border-radius), bw (border-width), bc (border-color), bs (border-style)\n * positioning: pos (position), z (z-index), t (top), l (left), rt (right)\n * typography: fs (font-size), fw (font-weight), ff (font-family), ta, td, lh, ls\n * layout: ai (align-items), jc (justify-content), flw (flex-wrap), cols, rows\n * shortcuts: c=center, sb=space-between, fe=flex-end, fs=flex-start, st=stretch\n * misc: cur (cursor), ov (overflow), pe (pointer-events), us (user-select), sh, tr\n * element-specific: v (value), ph (placeholder), type, href, src, alt, dis, ch, ro, opts\n *\n * events: c (click), x (input/change), f (focus), bl (blur), k (keydown), ku, kp, e, lv, sub\n * shorthand: \"state+\" (increment), \"state-\" (decrement), \"state~\" (toggle), \"state!val\" (set)\n *\n * state operations: + (increment), - (decrement), ! (set), ~ (toggle), < (append), > (prepend), X (remove), . (set prop)\n *\n * control flow (short form): {?: cond, t: [...], e: [...]} | {m: state, a: [...]}\n * control flow (long form): {if: state, then: [...], else: [...]} | {map: state, as: [...]}\n * equality check: {?: \"state\", is: 0, t: [...]} or {?: {$:\"state\"}, is: 0, t: [...]}\n */\n\n// ============ types ============\n\ntype StateValue = unknown;\ntype StateStore = Record<string, Signal<StateValue>>;\n\ninterface Signal<T> {\n (): T;\n set(v: T | ((prev: T) => T)): void;\n sub(fn: () => void): () => void;\n}\n\ntype Op = '+' | '-' | '!' | '~' | '<' | '>' | 'X' | '.';\ntype EventHandler = [string, Op, unknown?] | (() => void) | string;\n\ninterface Props {\n // spacing/sizing\n g?: number | string;\n p?: number | string;\n m?: number | string;\n w?: number | string;\n h?: number | string;\n mw?: number | string;\n mh?: number | string;\n // colors\n bg?: string;\n fg?: string;\n o?: number;\n // borders\n r?: number | string;\n bw?: number | string;\n bc?: string;\n bs?: string;\n // positioning\n pos?: 'rel' | 'abs' | 'fix' | 'sticky' | string;\n z?: number;\n t?: number | string;\n l?: number | string;\n b?: number | string;\n rt?: number | string;\n // typography\n fs?: number | string;\n fw?: number | string;\n ff?: string;\n ta?: string;\n td?: string;\n lh?: number | string;\n ls?: number | string;\n // layout\n ai?: string;\n jc?: string;\n flw?: string;\n cols?: number | string;\n rows?: number | string;\n // misc\n cur?: string;\n ov?: string;\n pe?: string;\n us?: string;\n sh?: string;\n tr?: string;\n // element-specific\n v?: unknown;\n ph?: string;\n type?: string;\n href?: string;\n src?: string;\n alt?: string;\n dis?: boolean;\n ch?: unknown;\n ro?: boolean;\n opts?: Array<{v: string, l: string}>;\n cls?: string;\n id?: string;\n rw?: number;\n sp?: number;\n rsp?: number;\n // events\n c?: EventHandler;\n x?: EventHandler;\n f?: EventHandler;\n bl?: EventHandler;\n k?: EventHandler;\n ku?: EventHandler;\n kp?: EventHandler;\n e?: EventHandler;\n lv?: EventHandler;\n sub?: EventHandler;\n // custom styles\n s?: Record<string, unknown>;\n}\n\ntype ComponentType =\n | 'V' | 'H' | 'D' | 'G'\n | 'T' | 'B'\n | 'I' | 'Ta' | 'S' | 'C' | 'R'\n | 'Tb' | 'Th' | 'Tbd' | 'Tr' | 'Td' | 'Tc'\n | 'Ul' | 'Ol' | 'Li'\n | 'M' | 'L' | 'Sv';\n\ntype StateRef = { $: string };\n\ninterface IfNode {\n // Long form\n if?: StateRef | string;\n then?: NodeSpec | NodeSpec[];\n else?: NodeSpec | NodeSpec[];\n // Short form\n '?'?: StateRef | string;\n t?: NodeSpec | NodeSpec[];\n e?: NodeSpec | NodeSpec[];\n // Equality check (works with both forms)\n eq?: unknown;\n is?: unknown;\n}\n\ninterface MapNode {\n // Long form\n map?: StateRef | string;\n as?: NodeSpec;\n // Short form\n m?: StateRef | string;\n a?: NodeSpec;\n key?: string;\n}\n\ntype Content = string | number | StateRef | NodeSpec[] | IfNode | MapNode;\ntype NodeSpec = [ComponentType, Content?, Props?] | IfNode | MapNode;\n\ninterface TooeySpec {\n s?: Record<string, StateValue>;\n r: NodeSpec;\n}\n\n// ============ render context for cleanup ============\n\ninterface ErrorInfo {\n message: string;\n componentType?: string;\n stack?: string;\n}\n\ntype ErrorHandler = (error: ErrorInfo) => void;\n\ninterface RenderContext {\n cleanups: Array<() => void>;\n state: StateStore;\n onError?: ErrorHandler;\n}\n\n// ============ error boundary ============\n\ninterface ErrorBoundaryNode {\n boundary: true;\n child: NodeSpec;\n fallback?: NodeSpec;\n onError?: ErrorHandler;\n}\n\nfunction isErrorBoundaryNode(v: unknown): v is ErrorBoundaryNode {\n return typeof v === 'object' && v !== null && 'boundary' in v && (v as ErrorBoundaryNode).boundary === true;\n}\n\nfunction createErrorFallback(error: ErrorInfo): HTMLElement {\n const el = document.createElement('div');\n el.style.cssText = 'padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px';\n el.textContent = `[tooey error] ${error.message}`;\n return el;\n}\n\n// ============ signals ============\n\nlet currentEffect: (() => void) | null = null;\nlet batchDepth = 0;\nlet pendingEffects = new Set<() => void>();\n\nfunction signal<T>(initial: T): Signal<T> {\n let value = initial;\n const subscribers = new Set<() => void>();\n\n const sig = (() => {\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n return value;\n }) as Signal<T>;\n\n sig.set = (v: T | ((prev: T) => T)) => {\n const newValue = typeof v === 'function' ? (v as (prev: T) => T)(value) : v;\n if (newValue !== value) {\n value = newValue;\n if (batchDepth > 0) {\n subscribers.forEach(fn => pendingEffects.add(fn));\n } else {\n subscribers.forEach(fn => fn());\n }\n }\n };\n\n sig.sub = (fn: () => void) => {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n };\n\n return sig;\n}\n\nfunction batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n const effects = pendingEffects;\n pendingEffects = new Set();\n effects.forEach(fn => fn());\n }\n }\n}\n\nfunction effect(fn: () => void, ctx?: RenderContext): () => void {\n let isActive = true;\n\n const execute = () => {\n if (!isActive) return;\n currentEffect = execute;\n try {\n fn();\n } finally {\n currentEffect = null;\n }\n };\n\n execute();\n\n const cleanup = () => {\n isActive = false;\n currentEffect = null;\n };\n\n if (ctx) {\n ctx.cleanups.push(cleanup);\n }\n\n return cleanup;\n}\n\n// ============ state operations ============\n\nfunction applyOp(state: Signal<StateValue>, op: Op, val?: unknown): void {\n try {\n switch (op) {\n case '+':\n state.set((v: StateValue) => (v as number) + (typeof val === 'number' ? val : 1));\n break;\n case '-':\n state.set((v: StateValue) => (v as number) - (typeof val === 'number' ? val : 1));\n break;\n case '!':\n state.set(val);\n break;\n case '~':\n state.set((v: StateValue) => !v);\n break;\n case '<':\n state.set((v: StateValue) => [...(v as unknown[]), val]);\n break;\n case '>':\n state.set((v: StateValue) => [val, ...(v as unknown[])]);\n break;\n case 'X':\n state.set((v: StateValue) => {\n const arr = v as unknown[];\n if (typeof val === 'number') {\n return arr.filter((_, i) => i !== val);\n } else if (typeof val === 'function') {\n return arr.filter((item, i) => !(val as (item: unknown, i: number) => boolean)(item, i));\n }\n return arr.filter(item => item !== val);\n });\n break;\n case '.':\n if (Array.isArray(val) && val.length === 2) {\n state.set((v: StateValue) => ({ ...(v as Record<string, unknown>), [val[0]]: val[1] }));\n }\n break;\n }\n } catch (err) {\n console.warn('[tooey] state operation error:', op, err);\n }\n}\n\n// ============ helpers ============\n\nfunction isStateRef(v: unknown): v is StateRef {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && '$' in v;\n}\n\nfunction isIfNode(v: unknown): v is IfNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('if' in v || '?' in v);\n}\n\nfunction isMapNode(v: unknown): v is MapNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('map' in v || 'm' in v);\n}\n\nfunction resolveValue(content: unknown, state: StateStore): unknown {\n if (isStateRef(content)) {\n const sig = state[content.$];\n if (!sig) {\n console.warn(`[tooey] unknown state key: \"${content.$}\"`);\n return undefined;\n }\n return sig();\n }\n return content;\n}\n\nfunction resolveCssValue(val: number | string | undefined): string | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'number') return `${val}px`;\n return val;\n}\n\n// Style value shortcuts for common layout values\nconst styleShortcuts: Record<string, string> = {\n 'c': 'center',\n 'sb': 'space-between',\n 'sa': 'space-around',\n 'se': 'space-evenly',\n 'fe': 'flex-end',\n 'fs': 'flex-start',\n 'st': 'stretch',\n 'bl': 'baseline',\n};\n\nfunction expandStyleValue(val: string | undefined): string | undefined {\n if (val === undefined) return undefined;\n return styleShortcuts[val] || val;\n}\n\n// Parse string-based event handler shorthand\n// Format: \"stateName+\" | \"stateName-\" | \"stateName~\" | \"stateName!value\"\nfunction parseEventShorthand(str: string): [string, Op, unknown?] | null {\n if (typeof str !== 'string' || str.length < 2) return null;\n\n const lastChar = str[str.length - 1];\n\n // Simple ops: +, -, ~\n if (lastChar === '+' || lastChar === '-' || lastChar === '~') {\n return [str.slice(0, -1), lastChar as Op];\n }\n\n // Set operation with value: \"state!value\"\n const bangIdx = str.indexOf('!');\n if (bangIdx > 0) {\n const stateKey = str.slice(0, bangIdx);\n const valStr = str.slice(bangIdx + 1);\n // Try to parse as number or boolean\n let val: unknown = valStr;\n if (valStr === 'true') val = true;\n else if (valStr === 'false') val = false;\n else if (!isNaN(Number(valStr)) && valStr !== '') val = Number(valStr);\n return [stateKey, '!', val];\n }\n\n return null;\n}\n\n// XSS protection - escape HTML entities (kept for future use, textContent provides protection now)\nfunction _escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n// URL validation - prevent dangerous protocols\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nfunction isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n\n // Allow relative URLs and anchors\n if (url.startsWith('/') || url.startsWith('#') || url.startsWith('.')) {\n return true;\n }\n\n try {\n const parsed = new URL(url, window.location.href);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n // If URL parsing fails, check for dangerous patterns directly\n const lowerUrl = url.toLowerCase().trim();\n const dangerousPatterns = ['javascript:', 'data:', 'vbscript:'];\n return !dangerousPatterns.some(pattern => lowerUrl.startsWith(pattern));\n }\n}\n\nfunction sanitizeUrl(url: string, propName: string): string | null {\n if (!url) return null;\n\n if (!isValidUrl(url)) {\n console.warn(`[tooey] blocked unsafe URL in ${propName}: \"${url.slice(0, 50)}...\"`);\n return null;\n }\n\n return url;\n}\n\nfunction createHandler(\n handler: EventHandler,\n state: StateStore,\n event?: Event,\n itemContext?: { item: unknown, index: number },\n buttonText?: string\n): () => void {\n if (typeof handler === 'function') {\n return handler;\n }\n\n // Handle string shorthand: \"state+\", \"state-\", \"state~\", \"state!value\"\n let normalizedHandler: [string, Op, unknown?];\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n normalizedHandler = parsed;\n } else {\n // Plain state key - infer operation from button text if available\n if (buttonText === '+') {\n normalizedHandler = [handler, '+'];\n } else if (buttonText === '-') {\n normalizedHandler = [handler, '-'];\n } else {\n // Default to toggle for plain state key\n normalizedHandler = [handler, '~'];\n }\n }\n } else {\n normalizedHandler = handler;\n }\n\n const [stateKey, op, val] = normalizedHandler;\n return () => {\n const sig = state[stateKey];\n if (!sig) {\n console.warn(`[tooey] click handler: unknown state key \"${stateKey}\"`);\n return;\n }\n let actualVal = val;\n // Resolve $item and $index in event handler values\n if (itemContext && typeof actualVal === 'string') {\n if (actualVal === '$index') {\n actualVal = itemContext.index;\n } else if (actualVal === '$item') {\n actualVal = itemContext.item;\n } else if (actualVal.startsWith('$item.')) {\n const key = actualVal.substring(6);\n actualVal = (itemContext.item as Record<string, unknown>)?.[key];\n }\n }\n if (op === '!' && val === undefined && event) {\n const target = event.target as HTMLInputElement;\n actualVal = target.type === 'checkbox' ? target.checked : target.value;\n }\n applyOp(sig, op, actualVal);\n };\n}\n\n// ============ styles ============\n\nfunction applyStyles(el: HTMLElement, props: Props): void {\n const style = el.style;\n\n if (props.g !== undefined) style.gap = resolveCssValue(props.g)!;\n if (props.p !== undefined) style.padding = resolveCssValue(props.p)!;\n if (props.m !== undefined) style.margin = resolveCssValue(props.m)!;\n if (props.w !== undefined) style.width = resolveCssValue(props.w)!;\n if (props.h !== undefined) style.height = resolveCssValue(props.h)!;\n if (props.mw !== undefined) style.maxWidth = resolveCssValue(props.mw)!;\n if (props.mh !== undefined) style.maxHeight = resolveCssValue(props.mh)!;\n\n if (props.bg !== undefined) style.background = props.bg;\n if (props.fg !== undefined) style.color = props.fg;\n if (props.o !== undefined) style.opacity = String(props.o);\n\n if (props.r !== undefined) style.borderRadius = resolveCssValue(props.r)!;\n if (props.bw !== undefined) style.borderWidth = resolveCssValue(props.bw)!;\n if (props.bc !== undefined) style.borderColor = props.bc;\n if (props.bs !== undefined) style.borderStyle = props.bs;\n\n if (props.pos !== undefined) {\n const posMap: Record<string, string> = {\n rel: 'relative', abs: 'absolute', fix: 'fixed', sticky: 'sticky'\n };\n style.position = posMap[props.pos] || props.pos;\n }\n if (props.z !== undefined) style.zIndex = String(props.z);\n if (props.t !== undefined) style.top = resolveCssValue(props.t)!;\n if (props.l !== undefined) style.left = resolveCssValue(props.l)!;\n if (typeof props.b === 'number' || (typeof props.b === 'string' && !Array.isArray(props.b))) {\n style.bottom = resolveCssValue(props.b as number | string)!;\n }\n if (props.rt !== undefined) style.right = resolveCssValue(props.rt)!;\n\n if (props.fs !== undefined) style.fontSize = resolveCssValue(props.fs)!;\n if (props.fw !== undefined) style.fontWeight = String(props.fw);\n if (props.ff !== undefined) style.fontFamily = props.ff;\n if (props.ta !== undefined) style.textAlign = props.ta;\n if (props.td !== undefined) style.textDecoration = props.td;\n if (props.lh !== undefined) style.lineHeight = typeof props.lh === 'number' ? String(props.lh) : props.lh;\n if (props.ls !== undefined) style.letterSpacing = resolveCssValue(props.ls)!;\n\n if (props.ai !== undefined) style.alignItems = expandStyleValue(props.ai)!;\n if (props.jc !== undefined) style.justifyContent = expandStyleValue(props.jc)!;\n if (props.flw !== undefined) style.flexWrap = expandStyleValue(props.flw)!\n\n if (props.cur !== undefined) style.cursor = props.cur;\n if (props.ov !== undefined) style.overflow = props.ov;\n if (props.pe !== undefined) style.pointerEvents = props.pe;\n if (props.us !== undefined) style.userSelect = props.us;\n if (props.sh !== undefined) style.boxShadow = props.sh;\n if (props.tr !== undefined) style.transform = props.tr;\n\n if (props.s) {\n Object.entries(props.s).forEach(([key, val]) => {\n (style as unknown as Record<string, string>)[key] = String(val);\n });\n }\n}\n\n// ============ renderer ============\n\nfunction createElement(\n spec: NodeSpec,\n ctx: RenderContext,\n itemContext?: { item: unknown, index: number }\n): HTMLElement | null {\n const { state } = ctx;\n\n // handle error boundary node\n if (isErrorBoundaryNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n try {\n const childCtx: RenderContext = {\n cleanups: [],\n state,\n onError: spec.onError || ctx.onError,\n };\n const child = createElement(spec.child, childCtx, itemContext);\n if (child) {\n placeholder.appendChild(child);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n } catch (err) {\n const errorInfo: ErrorInfo = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n\n if (spec.onError) {\n spec.onError(errorInfo);\n }\n\n if (spec.fallback) {\n try {\n const fallbackEl = createElement(spec.fallback, ctx, itemContext);\n if (fallbackEl) placeholder.appendChild(fallbackEl);\n } catch {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n } else {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n }\n\n return placeholder;\n }\n\n // handle reactive if node (supports both long and short form)\n if (isIfNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n // Normalize short form to long form\n const ifCond = spec.if ?? spec['?'];\n const thenBranch = spec.then ?? spec.t;\n const elseBranch = spec.else ?? spec.e;\n const eqValue = spec.eq ?? spec.is;\n\n const updateIf = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const rawValue = typeof ifCond === 'string'\n ? state[ifCond]?.()\n : resolveValue(ifCond, state);\n\n // Handle equality check (eq or is)\n let condition: boolean;\n if (eqValue !== undefined) {\n condition = rawValue === eqValue;\n } else {\n condition = Boolean(rawValue);\n }\n\n const branch = condition ? thenBranch : elseBranch;\n if (!branch) return;\n\n childCtx = { cleanups: [], state };\n\n if (Array.isArray(branch) && branch.length > 0 && Array.isArray(branch[0])) {\n (branch as NodeSpec[]).forEach(child => {\n const el = createElement(child, childCtx!, itemContext);\n if (el) placeholder.appendChild(el);\n });\n } else {\n currentEl = createElement(branch as NodeSpec, childCtx, itemContext);\n if (currentEl) placeholder.appendChild(currentEl);\n }\n };\n\n effect(updateIf, ctx);\n return placeholder;\n }\n\n // handle reactive map node (supports both long and short form)\n if (isMapNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let childCtx: RenderContext | null = null;\n\n // Normalize short form to long form\n const mapSource = spec.map ?? spec.m;\n const asTemplate = spec.as ?? spec.a;\n\n const updateMap = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n placeholder.innerHTML = '';\n\n const arr = (typeof mapSource === 'string'\n ? state[mapSource]?.()\n : resolveValue(mapSource, state)) as unknown[];\n\n if (!Array.isArray(arr) || !asTemplate) return;\n\n childCtx = { cleanups: [], state };\n\n arr.forEach((item, index) => {\n const el = createElement(asTemplate, childCtx!, { item, index });\n if (el) placeholder.appendChild(el);\n });\n };\n\n effect(updateMap, ctx);\n return placeholder;\n }\n\n // validate spec structure\n if (!Array.isArray(spec) || (spec as unknown[]).length === 0) {\n console.warn('[tooey] invalid node spec:', spec);\n return null;\n }\n\n const [type, content, props = {}] = spec as [ComponentType, Content?, Props?];\n let el: HTMLElement;\n\n switch (type) {\n case 'V':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'column';\n break;\n case 'H':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'row';\n break;\n case 'G':\n el = document.createElement('div');\n el.style.display = 'grid';\n if (props.cols) {\n el.style.gridTemplateColumns = typeof props.cols === 'number'\n ? `repeat(${props.cols}, 1fr)` : props.cols;\n }\n if (props.rows) {\n el.style.gridTemplateRows = typeof props.rows === 'number'\n ? `repeat(${props.rows}, 1fr)` : props.rows;\n }\n break;\n case 'D':\n el = document.createElement('div');\n break;\n case 'T':\n el = document.createElement('span');\n break;\n case 'B':\n el = document.createElement('button');\n break;\n case 'I':\n el = document.createElement('input');\n (el as HTMLInputElement).type = props.type || 'text';\n if (props.ph) (el as HTMLInputElement).placeholder = props.ph;\n if (props.ro) (el as HTMLInputElement).readOnly = true;\n break;\n case 'Ta':\n el = document.createElement('textarea');\n if (props.ph) (el as HTMLTextAreaElement).placeholder = props.ph;\n if (props.rw) (el as HTMLTextAreaElement).rows = props.rw;\n if (props.ro) (el as HTMLTextAreaElement).readOnly = true;\n break;\n case 'S':\n el = document.createElement('select');\n if (props.opts) {\n props.opts.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt.v;\n option.textContent = opt.l;\n el.appendChild(option);\n });\n }\n break;\n case 'C':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'checkbox';\n break;\n case 'R':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'radio';\n break;\n case 'Tb':\n el = document.createElement('table');\n break;\n case 'Th':\n el = document.createElement('thead');\n break;\n case 'Tbd':\n el = document.createElement('tbody');\n break;\n case 'Tr':\n el = document.createElement('tr');\n break;\n case 'Td':\n el = document.createElement('td');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Tc':\n el = document.createElement('th');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Ul':\n el = document.createElement('ul');\n break;\n case 'Ol':\n el = document.createElement('ol');\n break;\n case 'Li':\n el = document.createElement('li');\n break;\n case 'M':\n el = document.createElement('img');\n if (props.src) {\n const safeSrc = sanitizeUrl(props.src, 'src');\n if (safeSrc) (el as HTMLImageElement).src = safeSrc;\n }\n if (props.alt) (el as HTMLImageElement).alt = props.alt;\n break;\n case 'L':\n el = document.createElement('a');\n if (props.href) {\n const safeHref = sanitizeUrl(props.href, 'href');\n if (safeHref) (el as HTMLAnchorElement).href = safeHref;\n }\n break;\n case 'Sv':\n el = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as unknown as HTMLElement;\n break;\n default:\n console.warn(`[tooey] unknown component type: ${type}`);\n el = document.createElement('div');\n }\n\n if (props.cls) el.className = props.cls;\n if (props.id) el.id = props.id;\n if (props.dis) (el as HTMLButtonElement).disabled = true;\n\n applyStyles(el, props);\n\n // handle content\n if (content !== undefined) {\n if (Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]))) {\n (content as NodeSpec[]).forEach(childSpec => {\n const child = createElement(childSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n });\n } else if (isIfNode(content) || isMapNode(content)) {\n const child = createElement(content as NodeSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n } else if (isStateRef(content)) {\n effect(() => {\n const val = resolveValue(content, state);\n if (type === 'I') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n } else {\n // textContent provides XSS protection by not parsing HTML\n el.textContent = String(val ?? '');\n }\n }, ctx);\n } else if (typeof content === 'string' || typeof content === 'number') {\n let textContent = String(content);\n if (itemContext) {\n // handle object property access first (before $item replacement)\n if (typeof itemContext.item === 'object' && itemContext.item !== null) {\n textContent = textContent.replace(/\\$item\\.(\\w+)/g, (_, key) => {\n return String((itemContext.item as Record<string, unknown>)[key] ?? '');\n });\n }\n textContent = textContent.replace(/\\$item/g, String(itemContext.item));\n textContent = textContent.replace(/\\$index/g, String(itemContext.index));\n }\n // XSS protection for static content\n if (type === 'I') {\n (el as HTMLInputElement).value = textContent;\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = textContent;\n } else if (type !== 'S') {\n // don't set textContent for select (would clear options)\n el.textContent = textContent;\n }\n }\n }\n\n // handle value binding for inputs\n if (props.v !== undefined && isStateRef(props.v)) {\n effect(() => {\n const val = resolveValue(props.v!, state);\n if (type === 'I' || type === 'S' || type === 'Ta') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n }\n }, ctx);\n }\n\n // handle checked binding\n if (props.ch !== undefined) {\n if (isStateRef(props.ch as unknown)) {\n effect(() => {\n const val = resolveValue(props.ch as unknown as StateRef, state);\n (el as HTMLInputElement).checked = Boolean(val);\n }, ctx);\n } else {\n (el as HTMLInputElement).checked = Boolean(props.ch);\n }\n }\n\n // event handlers with cleanup tracking\n const addEventListener = (event: string, handler: (e: Event) => void) => {\n el.addEventListener(event, handler);\n ctx.cleanups.push(() => el.removeEventListener(event, handler));\n };\n\n // Get button text for implicit operation inference\n const buttonText = type === 'B' && (typeof content === 'string' || typeof content === 'number')\n ? String(content)\n : undefined;\n\n if (props.c) {\n addEventListener('click', (e) => createHandler(props.c!, state, e, itemContext, buttonText)());\n }\n if (props.x) {\n const handler = props.x;\n addEventListener('input', (e) => {\n if (typeof handler === 'function') {\n handler();\n } else {\n // Normalize string shorthand to array form\n let stateKey: string;\n let op: Op;\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n [stateKey, op] = parsed;\n } else {\n // Plain state key defaults to set (!) for input\n stateKey = handler;\n op = '!';\n }\n } else {\n [stateKey, op] = handler;\n }\n const sig = state[stateKey];\n if (sig) {\n const target = e.target as HTMLInputElement;\n const val = (type === 'C' || type === 'R') ? target.checked : target.value;\n applyOp(sig, op, val);\n }\n }\n });\n }\n if (props.f) {\n addEventListener('focus', (e) => createHandler(props.f!, state, e, itemContext)());\n }\n if (props.bl) {\n addEventListener('blur', (e) => createHandler(props.bl!, state, e, itemContext)());\n }\n if (props.k) {\n addEventListener('keydown', (e) => createHandler(props.k!, state, e, itemContext)());\n }\n if (props.ku) {\n addEventListener('keyup', (e) => createHandler(props.ku!, state, e, itemContext)());\n }\n if (props.kp) {\n addEventListener('keypress', (e) => createHandler(props.kp!, state, e, itemContext)());\n }\n if (props.e) {\n addEventListener('mouseenter', (e) => createHandler(props.e!, state, e, itemContext)());\n }\n if (props.lv) {\n addEventListener('mouseleave', (e) => createHandler(props.lv!, state, e, itemContext)());\n }\n if (props.sub) {\n addEventListener('submit', (e) => {\n e.preventDefault();\n createHandler(props.sub!, state, e, itemContext)();\n });\n }\n\n return el;\n}\n\n// ============ main api ============\n\ninterface TooeyInstance {\n state: StateStore;\n el: HTMLElement | null;\n destroy(): void;\n update(newSpec: TooeySpec): void;\n get(key: string): unknown;\n set(key: string, value: unknown): void;\n}\n\nfunction render(container: HTMLElement, spec: TooeySpec): TooeyInstance {\n if (!container) {\n throw new Error('[tooey] render requires a valid container element');\n }\n if (!spec || !spec.r) {\n throw new Error('[tooey] render requires a spec with a root node (r)');\n }\n\n const state: StateStore = {};\n if (spec.s) {\n Object.entries(spec.s).forEach(([key, val]) => {\n state[key] = signal(val);\n });\n }\n\n const ctx: RenderContext = { cleanups: [], state };\n\n container.innerHTML = '';\n const el = createElement(spec.r, ctx);\n if (el) container.appendChild(el);\n\n const instance: TooeyInstance = {\n state,\n el,\n destroy() {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n },\n update(newSpec: TooeySpec) {\n if (newSpec.s) {\n batch(() => {\n Object.entries(newSpec.s!).forEach(([key, val]) => {\n if (state[key]) {\n state[key].set(val);\n } else {\n state[key] = signal(val);\n }\n });\n });\n }\n if (newSpec.r) {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n const newEl = createElement(newSpec.r, ctx);\n if (newEl) container.appendChild(newEl);\n instance.el = newEl;\n }\n },\n get(key: string) {\n return state[key]?.();\n },\n set(key: string, value: unknown) {\n if (state[key]) {\n state[key].set(value);\n }\n }\n };\n\n return instance;\n}\n\n// ============ convenience helpers ============\n\nfunction $(name: string): StateRef {\n return { $: name };\n}\n\n// component type constants\nconst V = 'V' as const;\nconst H = 'H' as const;\nconst D = 'D' as const;\nconst G = 'G' as const;\nconst T = 'T' as const;\nconst B = 'B' as const;\nconst I = 'I' as const;\nconst Ta = 'Ta' as const;\nconst S = 'S' as const;\nconst C = 'C' as const;\nconst R = 'R' as const;\nconst Tb = 'Tb' as const;\nconst Th = 'Th' as const;\nconst Tbd = 'Tbd' as const;\nconst Tr = 'Tr' as const;\nconst Td = 'Td' as const;\nconst Tc = 'Tc' as const;\nconst Ul = 'Ul' as const;\nconst Ol = 'Ol' as const;\nconst Li = 'Li' as const;\nconst M = 'M' as const;\nconst L = 'L' as const;\nconst Sv = 'Sv' as const;\n\nexport {\n render,\n signal,\n effect,\n batch,\n $,\n V, H, D, G,\n T, B,\n I, Ta, S, C, R,\n Tb, Th, Tbd, Tr, Td, Tc,\n Ul, Ol, Li,\n M, L, Sv,\n TooeySpec,\n NodeSpec,\n Props,\n StateRef,\n TooeyInstance,\n IfNode,\n MapNode,\n ErrorBoundaryNode,\n ErrorInfo,\n ErrorHandler\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["isErrorBoundaryNode", "v", "createErrorFallback", "error", "el", "currentEffect", "batchDepth", "pendingEffects", "signal", "initial", "value", "subscribers", "sig", "newValue", "fn", "batch", "effects", "effect", "ctx", "isActive", "execute", "cleanup", "applyOp", "state", "op", "val", "arr", "_", "i", "item", "
|
|
4
|
+
"sourcesContent": ["/**\n * tooey - token-efficient ui library for llms\n *\n * component types:\n * layout: V (vstack), H (hstack), D (div), G (grid)\n * text & buttons: T (text/span), B (button)\n * inputs: I (input), Ta (textarea), S (select), C (checkbox), R (radio)\n * tables: Tb (table), Th (thead), Tbd (tbody), Tr (tr), Td (td), Tc (th)\n * lists: Ul (ul), Ol (ol), Li (li)\n * media & links: M (image), L (link), Sv (svg)\n *\n * props (short keys):\n * spacing: g (gap), p (padding), m (margin), w (width), h (height), mw, mh\n * colors: bg (background), fg (color), o (opacity)\n * borders: r (border-radius), bw (border-width), bc (border-color), bs (border-style)\n * positioning: pos (position), z (z-index), t (top), l (left), rt (right)\n * typography: fs (font-size), fw (font-weight), ff (font-family), ta, td, lh, ls\n * layout: ai (align-items), jc (justify-content), flw (flex-wrap), cols, rows\n * shortcuts: c=center, sb=space-between, fe=flex-end, fs=flex-start, st=stretch\n * misc: cur (cursor), ov (overflow), pe (pointer-events), us (user-select), sh, tr\n * element-specific: v (value), ph (placeholder), type, href, src, alt, dis, ch, ro, opts\n *\n * events: c (click), x (input/change), f (focus), bl (blur), k (keydown), ku, kp, e, lv, sub\n * shorthand: \"state+\" (increment), \"state-\" (decrement), \"state~\" (toggle), \"state!val\" (set)\n *\n * state operations: + (increment), - (decrement), ! (set), ~ (toggle), < (append), > (prepend), X (remove), . (set prop)\n *\n * control flow (short form): {?: cond, t: [...], e: [...]} | {m: state, a: [...]}\n * control flow (long form): {if: state, then: [...], else: [...]} | {map: state, as: [...]}\n * equality check: {?: \"state\", is: 0, t: [...]} or {?: {$:\"state\"}, is: 0, t: [...]}\n */\n\n// ============ types ============\n\ntype StateValue = unknown;\ntype StateStore = Record<string, Signal<StateValue>>;\n\n// ============ theming ============\n\ntype ThemeValue = string | number;\ntype ThemeCategory = Record<string, ThemeValue>;\n\ninterface Theme {\n colors?: ThemeCategory;\n spacing?: ThemeCategory;\n radius?: ThemeCategory;\n fonts?: ThemeCategory;\n [key: string]: ThemeCategory | undefined;\n}\n\n// ============ plugins ============\n\ninterface TooeyPlugin {\n name: string;\n\n // lifecycle hooks\n onInit?(instance: TooeyInstance): void;\n onDestroy?(instance: TooeyInstance): void;\n\n // render hooks\n beforeRender?(spec: NodeSpec, ctx: RenderContext): NodeSpec;\n afterRender?(el: HTMLElement, spec: NodeSpec): void;\n\n // state hooks\n onStateChange?(key: string, oldVal: unknown, newVal: unknown): void;\n\n // extend instance with custom methods\n extend?: Record<string, (this: TooeyInstance, ...args: unknown[]) => unknown>;\n}\n\ninterface RenderOptions {\n theme?: Theme;\n plugins?: TooeyPlugin[];\n}\n\ninterface Signal<T> {\n (): T;\n set(v: T | ((prev: T) => T)): void;\n sub(fn: () => void): () => void;\n}\n\ntype Op = '+' | '-' | '!' | '~' | '<' | '>' | 'X' | '.';\ntype EventHandler = [string, Op, unknown?] | (() => void) | string;\n\ninterface Props {\n // conditional rendering\n show?: string; // state key - component only renders when state is truthy\n // spacing/sizing\n g?: number | string;\n p?: number | string;\n m?: number | string;\n w?: number | string;\n h?: number | string;\n mw?: number | string;\n mh?: number | string;\n // colors\n bg?: string;\n fg?: string;\n o?: number;\n // borders\n r?: number | string;\n bw?: number | string;\n bc?: string;\n bs?: string;\n // positioning\n pos?: 'rel' | 'abs' | 'fix' | 'sticky' | string;\n z?: number;\n t?: number | string;\n l?: number | string;\n b?: number | string;\n rt?: number | string;\n // typography\n fs?: number | string;\n fw?: number | string;\n ff?: string;\n ta?: string;\n td?: string;\n lh?: number | string;\n ls?: number | string;\n // layout\n ai?: string;\n jc?: string;\n flw?: string;\n cols?: number | string;\n rows?: number | string;\n // misc\n cur?: string;\n ov?: string;\n pe?: string;\n us?: string;\n sh?: string;\n tr?: string;\n // element-specific\n v?: unknown;\n ph?: string;\n type?: string;\n href?: string;\n src?: string;\n alt?: string;\n dis?: boolean;\n ch?: unknown;\n ro?: boolean;\n opts?: Array<{v: string, l: string}>;\n cls?: string;\n id?: string;\n rw?: number;\n sp?: number;\n rsp?: number;\n // events\n c?: EventHandler;\n x?: EventHandler;\n f?: EventHandler;\n bl?: EventHandler;\n k?: EventHandler;\n ku?: EventHandler;\n kp?: EventHandler;\n e?: EventHandler;\n lv?: EventHandler;\n sub?: EventHandler;\n // custom styles\n s?: Record<string, unknown>;\n}\n\ntype ComponentType =\n | 'V' | 'H' | 'D' | 'G'\n | 'T' | 'B'\n | 'I' | 'Ta' | 'S' | 'C' | 'R'\n | 'Tb' | 'Th' | 'Tbd' | 'Tr' | 'Td' | 'Tc'\n | 'Ul' | 'Ol' | 'Li'\n | 'M' | 'L' | 'Sv';\n\n// function component type - returns a NodeSpec\ntype Component<P extends Props = Props> = (props?: P, children?: NodeSpec[]) => NodeSpec;\n\ntype StateRef = { $: string };\n\ninterface IfNode {\n // long form\n if?: StateRef | string;\n then?: NodeSpec | NodeSpec[];\n else?: NodeSpec | NodeSpec[];\n // short form\n '?'?: StateRef | string;\n t?: NodeSpec | NodeSpec[];\n e?: NodeSpec | NodeSpec[];\n // equality check (works with both forms)\n eq?: unknown;\n is?: unknown;\n}\n\ninterface MapNode {\n // long form\n map?: StateRef | string;\n as?: NodeSpec;\n // short form\n m?: StateRef | string;\n a?: NodeSpec;\n key?: string;\n}\n\ntype Content = string | number | StateRef | NodeSpec[] | IfNode | MapNode;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype FunctionNodeSpec = [Component<any>, Content?, (Props & Record<string, unknown>)?];\ntype BuiltinNodeSpec = [ComponentType, Content?, Props?];\ntype NodeSpec = BuiltinNodeSpec | FunctionNodeSpec | IfNode | MapNode;\n\ninterface TooeySpec {\n s?: Record<string, StateValue>;\n r: NodeSpec;\n}\n\n// ============ render context for cleanup ============\n\ninterface ErrorInfo {\n message: string;\n componentType?: string;\n stack?: string;\n}\n\ntype ErrorHandler = (error: ErrorInfo) => void;\n\ninterface RenderContext {\n cleanups: Array<() => void>;\n state: StateStore;\n theme?: Theme;\n plugins?: TooeyPlugin[];\n onError?: ErrorHandler;\n}\n\n// ============ error boundary ============\n\ninterface ErrorBoundaryNode {\n boundary: true;\n child: NodeSpec;\n fallback?: NodeSpec;\n onError?: ErrorHandler;\n}\n\nfunction isErrorBoundaryNode(v: unknown): v is ErrorBoundaryNode {\n return typeof v === 'object' && v !== null && 'boundary' in v && (v as ErrorBoundaryNode).boundary === true;\n}\n\nfunction createErrorFallback(error: ErrorInfo): HTMLElement {\n const el = document.createElement('div');\n el.style.cssText = 'padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px';\n el.textContent = `[tooey error] ${error.message}`;\n return el;\n}\n\n// ============ signals ============\n\nlet currentEffect: (() => void) | null = null;\nlet batchDepth = 0;\nlet pendingEffects = new Set<() => void>();\n\nfunction signal<T>(initial: T): Signal<T> {\n let value = initial;\n const subscribers = new Set<() => void>();\n\n const sig = (() => {\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n return value;\n }) as Signal<T>;\n\n sig.set = (v: T | ((prev: T) => T)) => {\n const newValue = typeof v === 'function' ? (v as (prev: T) => T)(value) : v;\n if (newValue !== value) {\n value = newValue;\n if (batchDepth > 0) {\n subscribers.forEach(fn => pendingEffects.add(fn));\n } else {\n subscribers.forEach(fn => fn());\n }\n }\n };\n\n sig.sub = (fn: () => void) => {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n };\n\n return sig;\n}\n\nfunction batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n const effects = pendingEffects;\n pendingEffects = new Set();\n effects.forEach(fn => fn());\n }\n }\n}\n\nfunction effect(fn: () => void, ctx?: RenderContext): () => void {\n let isActive = true;\n\n const execute = () => {\n if (!isActive) return;\n currentEffect = execute;\n try {\n fn();\n } finally {\n currentEffect = null;\n }\n };\n\n execute();\n\n const cleanup = () => {\n isActive = false;\n currentEffect = null;\n };\n\n if (ctx) {\n ctx.cleanups.push(cleanup);\n }\n\n return cleanup;\n}\n\n// computed signal - derives value from other signals and auto-updates\ninterface ComputedSignal<T> {\n (): T;\n sub(fn: () => void): () => void;\n}\n\nfunction computed<T>(fn: () => T): ComputedSignal<T> {\n let cachedValue: T;\n let isDirty = true;\n const subscribers = new Set<() => void>();\n\n // re-compute and notify subscribers when dependencies change\n const recompute = () => {\n isDirty = true;\n // notify all subscribers that the value may have changed\n if (batchDepth > 0) {\n subscribers.forEach(sub => pendingEffects.add(sub));\n } else {\n subscribers.forEach(sub => sub());\n }\n };\n\n const sig = (() => {\n // track this computed as a dependency if inside an effect\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n\n // recompute if dirty\n if (isDirty) {\n // track dependencies by running the computation inside an effect context\n const prevEffect = currentEffect;\n currentEffect = recompute;\n try {\n cachedValue = fn();\n } finally {\n currentEffect = prevEffect;\n }\n isDirty = false;\n }\n\n return cachedValue;\n }) as ComputedSignal<T>;\n\n sig.sub = (subFn: () => void) => {\n subscribers.add(subFn);\n return () => subscribers.delete(subFn);\n };\n\n return sig;\n}\n\n// async$ helper - handle async data with loading states\ninterface AsyncState<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n [key: string]: unknown; // index signature for TooeySpec.s compatibility\n}\n\ninterface AsyncSpec<T> {\n s: AsyncState<T>;\n init(instance: TooeyInstance): Promise<void>;\n}\n\nfunction async$<T>(\n promiseOrFn: Promise<T> | (() => Promise<T>),\n options?: { onError?: (error: Error) => void }\n): AsyncSpec<T> {\n return {\n s: {\n data: null,\n loading: true,\n error: null\n },\n async init(instance: TooeyInstance) {\n try {\n const promise = typeof promiseOrFn === 'function' ? promiseOrFn() : promiseOrFn;\n const data = await promise;\n instance.set('data', data);\n instance.set('loading', false);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n instance.set('error', errorMessage);\n instance.set('loading', false);\n if (options?.onError && err instanceof Error) {\n options.onError(err);\n }\n }\n }\n };\n}\n\n// ============ state operations ============\n\nfunction applyOp(state: Signal<StateValue>, op: Op, val?: unknown): void {\n try {\n switch (op) {\n case '+':\n state.set((v: StateValue) => (v as number) + (typeof val === 'number' ? val : 1));\n break;\n case '-':\n state.set((v: StateValue) => (v as number) - (typeof val === 'number' ? val : 1));\n break;\n case '!':\n state.set(val);\n break;\n case '~':\n state.set((v: StateValue) => !v);\n break;\n case '<':\n state.set((v: StateValue) => [...(v as unknown[]), val]);\n break;\n case '>':\n state.set((v: StateValue) => [val, ...(v as unknown[])]);\n break;\n case 'X':\n state.set((v: StateValue) => {\n const arr = v as unknown[];\n if (typeof val === 'number') {\n return arr.filter((_, i) => i !== val);\n } else if (typeof val === 'function') {\n return arr.filter((item, i) => !(val as (item: unknown, i: number) => boolean)(item, i));\n }\n return arr.filter(item => item !== val);\n });\n break;\n case '.':\n if (Array.isArray(val) && val.length === 2) {\n state.set((v: StateValue) => ({ ...(v as Record<string, unknown>), [val[0]]: val[1] }));\n }\n break;\n }\n } catch (err) {\n console.warn('[tooey] state operation error:', op, err);\n }\n}\n\n// ============ helpers ============\n\nfunction isStateRef(v: unknown): v is StateRef {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && '$' in v;\n}\n\nfunction isIfNode(v: unknown): v is IfNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('if' in v || '?' in v);\n}\n\nfunction isMapNode(v: unknown): v is MapNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('map' in v || 'm' in v);\n}\n\nfunction resolveValue(content: unknown, state: StateStore): unknown {\n if (isStateRef(content)) {\n const sig = state[content.$];\n if (!sig) {\n console.warn(`[tooey] unknown state key: \"${content.$}\"`);\n return undefined;\n }\n return sig();\n }\n return content;\n}\n\nfunction resolveCssValue(val: number | string | undefined): string | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'number') return `${val}px`;\n return val;\n}\n\nfunction resolveThemeValue(token: string, theme: Theme | undefined): ThemeValue | undefined {\n if (!theme) return undefined;\n\n // try direct category lookup: $primary -> colors.primary, $md -> spacing.md, etc.\n // check in order of most common usage\n const categories: (keyof Theme)[] = ['colors', 'spacing', 'radius', 'fonts'];\n\n for (const category of categories) {\n const cat = theme[category];\n if (cat && token in cat) {\n return cat[token];\n }\n }\n\n // check any custom categories\n for (const [key, cat] of Object.entries(theme)) {\n if (cat && !categories.includes(key as keyof Theme) && token in cat) {\n return cat[token];\n }\n }\n\n return undefined;\n}\n\n// style value shortcuts for common layout values\nconst styleShortcuts: Record<string, string> = {\n 'c': 'center',\n 'sb': 'space-between',\n 'sa': 'space-around',\n 'se': 'space-evenly',\n 'fe': 'flex-end',\n 'fs': 'flex-start',\n 'st': 'stretch',\n 'bl': 'baseline',\n};\n\nfunction expandStyleValue(val: string | undefined): string | undefined {\n if (val === undefined) return undefined;\n return styleShortcuts[val] || val;\n}\n\n// parse string-based event handler shorthand\n// format: \"stateName+\" | \"stateName-\" | \"stateName~\" | \"stateName!value\"\nfunction parseEventShorthand(str: string): [string, Op, unknown?] | null {\n if (typeof str !== 'string' || str.length < 2) return null;\n\n const lastChar = str[str.length - 1];\n\n // simple ops: +, -, ~\n if (lastChar === '+' || lastChar === '-' || lastChar === '~') {\n return [str.slice(0, -1), lastChar as Op];\n }\n\n // set operation with value: \"state!value\"\n const bangIdx = str.indexOf('!');\n if (bangIdx > 0) {\n const stateKey = str.slice(0, bangIdx);\n const valStr = str.slice(bangIdx + 1);\n // try to parse as number or boolean\n let val: unknown = valStr;\n if (valStr === 'true') val = true;\n else if (valStr === 'false') val = false;\n else if (!isNaN(Number(valStr)) && valStr !== '') val = Number(valStr);\n return [stateKey, '!', val];\n }\n\n return null;\n}\n\n// xss protection - escape html entities (kept for future use, textContent provides protection now)\nfunction _escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n// url validation - prevent dangerous protocols\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nfunction isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n\n // allow relative urls and anchors\n if (url.startsWith('/') || url.startsWith('#') || url.startsWith('.')) {\n return true;\n }\n\n try {\n const parsed = new URL(url, window.location.href);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n // if url parsing fails, check for dangerous patterns directly\n const lowerUrl = url.toLowerCase().trim();\n const dangerousPatterns = ['javascript:', 'data:', 'vbscript:'];\n return !dangerousPatterns.some(pattern => lowerUrl.startsWith(pattern));\n }\n}\n\nfunction sanitizeUrl(url: string, propName: string): string | null {\n if (!url) return null;\n\n if (!isValidUrl(url)) {\n console.warn(`[tooey] blocked unsafe URL in ${propName}: \"${url.slice(0, 50)}...\"`);\n return null;\n }\n\n return url;\n}\n\nfunction createHandler(\n handler: EventHandler,\n state: StateStore,\n event?: Event,\n itemContext?: { item: unknown, index: number },\n buttonText?: string\n): () => void {\n if (typeof handler === 'function') {\n return handler;\n }\n\n // handle string shorthand: \"state+\", \"state-\", \"state~\", \"state!value\"\n let normalizedHandler: [string, Op, unknown?];\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n normalizedHandler = parsed;\n } else {\n // plain state key - infer operation from button text if available\n if (buttonText === '+') {\n normalizedHandler = [handler, '+'];\n } else if (buttonText === '-') {\n normalizedHandler = [handler, '-'];\n } else {\n // default to toggle for plain state key\n normalizedHandler = [handler, '~'];\n }\n }\n } else {\n normalizedHandler = handler;\n }\n\n const [stateKey, op, val] = normalizedHandler;\n return () => {\n const sig = state[stateKey];\n if (!sig) {\n console.warn(`[tooey] click handler: unknown state key \"${stateKey}\"`);\n return;\n }\n let actualVal = val;\n // resolve $item and $index in event handler values\n if (itemContext && typeof actualVal === 'string') {\n if (actualVal === '$index') {\n actualVal = itemContext.index;\n } else if (actualVal === '$item') {\n actualVal = itemContext.item;\n } else if (actualVal.startsWith('$item.')) {\n const key = actualVal.substring(6);\n actualVal = (itemContext.item as Record<string, unknown>)?.[key];\n }\n }\n if (op === '!' && val === undefined && event) {\n const target = event.target as HTMLInputElement;\n actualVal = target.type === 'checkbox' ? target.checked : target.value;\n }\n applyOp(sig, op, actualVal);\n };\n}\n\n// ============ styles ============\n\nfunction resolveStyleValue(val: string | number | undefined, theme: Theme | undefined): string | number | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'string' && val.startsWith('$')) {\n const token = val.slice(1);\n const themeVal = resolveThemeValue(token, theme);\n if (themeVal !== undefined) return themeVal;\n console.warn(`[tooey] unknown theme token: \"${val}\"`);\n return undefined;\n }\n return val;\n}\n\nfunction applyStyles(el: HTMLElement, props: Props, theme?: Theme): void {\n const style = el.style;\n\n // helper to resolve and apply css value with theme token support\n const resolve = (val: string | number | undefined): string | undefined => {\n const resolved = resolveStyleValue(val, theme);\n return resolveCssValue(resolved as string | number | undefined);\n };\n\n // helper for string values that support theme tokens\n const resolveStr = (val: string | undefined): string | undefined => {\n if (val === undefined) return undefined;\n const resolved = resolveStyleValue(val, theme);\n return resolved !== undefined ? String(resolved) : undefined;\n };\n\n if (props.g !== undefined) { const v = resolve(props.g); if (v) style.gap = v; }\n if (props.p !== undefined) { const v = resolve(props.p); if (v) style.padding = v; }\n if (props.m !== undefined) { const v = resolve(props.m); if (v) style.margin = v; }\n if (props.w !== undefined) { const v = resolve(props.w); if (v) style.width = v; }\n if (props.h !== undefined) { const v = resolve(props.h); if (v) style.height = v; }\n if (props.mw !== undefined) { const v = resolve(props.mw); if (v) style.maxWidth = v; }\n if (props.mh !== undefined) { const v = resolve(props.mh); if (v) style.maxHeight = v; }\n\n if (props.bg !== undefined) { const v = resolveStr(props.bg); if (v) style.background = v; }\n if (props.fg !== undefined) { const v = resolveStr(props.fg); if (v) style.color = v; }\n if (props.o !== undefined) style.opacity = String(props.o);\n\n if (props.r !== undefined) { const v = resolve(props.r); if (v) style.borderRadius = v; }\n if (props.bw !== undefined) { const v = resolve(props.bw); if (v) style.borderWidth = v; }\n if (props.bc !== undefined) { const v = resolveStr(props.bc); if (v) style.borderColor = v; }\n if (props.bs !== undefined) style.borderStyle = props.bs;\n\n if (props.pos !== undefined) {\n const posMap: Record<string, string> = {\n rel: 'relative', abs: 'absolute', fix: 'fixed', sticky: 'sticky'\n };\n style.position = posMap[props.pos] || props.pos;\n }\n if (props.z !== undefined) style.zIndex = String(props.z);\n if (props.t !== undefined) { const v = resolve(props.t); if (v) style.top = v; }\n if (props.l !== undefined) { const v = resolve(props.l); if (v) style.left = v; }\n if (typeof props.b === 'number' || (typeof props.b === 'string' && !Array.isArray(props.b))) {\n const v = resolve(props.b as number | string);\n if (v) style.bottom = v;\n }\n if (props.rt !== undefined) { const v = resolve(props.rt); if (v) style.right = v; }\n\n if (props.fs !== undefined) { const v = resolve(props.fs); if (v) style.fontSize = v; }\n if (props.fw !== undefined) style.fontWeight = String(props.fw);\n if (props.ff !== undefined) { const v = resolveStr(props.ff); if (v) style.fontFamily = v; }\n if (props.ta !== undefined) style.textAlign = props.ta;\n if (props.td !== undefined) style.textDecoration = props.td;\n if (props.lh !== undefined) style.lineHeight = typeof props.lh === 'number' ? String(props.lh) : props.lh;\n if (props.ls !== undefined) { const v = resolve(props.ls); if (v) style.letterSpacing = v; }\n\n if (props.ai !== undefined) style.alignItems = expandStyleValue(props.ai)!;\n if (props.jc !== undefined) style.justifyContent = expandStyleValue(props.jc)!;\n if (props.flw !== undefined) style.flexWrap = expandStyleValue(props.flw)!\n\n if (props.cur !== undefined) style.cursor = props.cur;\n if (props.ov !== undefined) style.overflow = props.ov;\n if (props.pe !== undefined) style.pointerEvents = props.pe;\n if (props.us !== undefined) style.userSelect = props.us;\n if (props.sh !== undefined) { const v = resolveStr(props.sh); if (v) style.boxShadow = v; }\n if (props.tr !== undefined) style.transform = props.tr;\n\n if (props.s) {\n Object.entries(props.s).forEach(([key, val]) => {\n const resolved = resolveStyleValue(val as string | number | undefined, theme);\n if (resolved !== undefined) {\n (style as unknown as Record<string, string>)[key] = String(resolved);\n }\n });\n }\n}\n\n// ============ renderer ============\n\nfunction createElement(\n spec: NodeSpec,\n ctx: RenderContext,\n itemContext?: { item: unknown, index: number }\n): HTMLElement | null {\n const { state } = ctx;\n\n // handle error boundary node\n if (isErrorBoundaryNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n try {\n const childCtx: RenderContext = {\n cleanups: [],\n state,\n onError: spec.onError || ctx.onError,\n };\n const child = createElement(spec.child, childCtx, itemContext);\n if (child) {\n placeholder.appendChild(child);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n } catch (err) {\n const errorInfo: ErrorInfo = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n\n if (spec.onError) {\n spec.onError(errorInfo);\n }\n\n if (spec.fallback) {\n try {\n const fallbackEl = createElement(spec.fallback, ctx, itemContext);\n if (fallbackEl) placeholder.appendChild(fallbackEl);\n } catch {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n } else {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n }\n\n return placeholder;\n }\n\n // handle reactive if node (supports both long and short form)\n if (isIfNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n // normalize short form to long form\n const ifCond = spec.if ?? spec['?'];\n const thenBranch = spec.then ?? spec.t;\n const elseBranch = spec.else ?? spec.e;\n const eqValue = spec.eq ?? spec.is;\n\n const updateIf = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const rawValue = typeof ifCond === 'string'\n ? state[ifCond]?.()\n : resolveValue(ifCond, state);\n\n // handle equality check (eq or is)\n let condition: boolean;\n if (eqValue !== undefined) {\n condition = rawValue === eqValue;\n } else {\n condition = Boolean(rawValue);\n }\n\n const branch = condition ? thenBranch : elseBranch;\n if (!branch) return;\n\n childCtx = { cleanups: [], state };\n\n if (Array.isArray(branch) && branch.length > 0 && Array.isArray(branch[0])) {\n (branch as NodeSpec[]).forEach(child => {\n const el = createElement(child, childCtx!, itemContext);\n if (el) placeholder.appendChild(el);\n });\n } else {\n currentEl = createElement(branch as NodeSpec, childCtx, itemContext);\n if (currentEl) placeholder.appendChild(currentEl);\n }\n };\n\n effect(updateIf, ctx);\n return placeholder;\n }\n\n // handle reactive map node (supports both long and short form)\n if (isMapNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let childCtx: RenderContext | null = null;\n\n // normalize short form to long form\n const mapSource = spec.map ?? spec.m;\n const asTemplate = spec.as ?? spec.a;\n\n const updateMap = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n placeholder.innerHTML = '';\n\n const arr = (typeof mapSource === 'string'\n ? state[mapSource]?.()\n : resolveValue(mapSource, state)) as unknown[];\n\n if (!Array.isArray(arr) || !asTemplate) return;\n\n childCtx = { cleanups: [], state };\n\n arr.forEach((item, index) => {\n const el = createElement(asTemplate, childCtx!, { item, index });\n if (el) placeholder.appendChild(el);\n });\n };\n\n effect(updateMap, ctx);\n return placeholder;\n }\n\n // validate spec structure\n if (!Array.isArray(spec) || (spec as unknown[]).length === 0) {\n console.warn('[tooey] invalid node spec:', spec);\n return null;\n }\n\n // apply beforeRender hooks from plugins\n let processedSpec: NodeSpec = spec;\n if (ctx.plugins) {\n for (const plugin of ctx.plugins) {\n if (plugin.beforeRender) {\n processedSpec = plugin.beforeRender(processedSpec, ctx);\n }\n }\n }\n\n // if beforeRender transformed spec to a non-array type, recurse\n if (!Array.isArray(processedSpec)) {\n return createElement(processedSpec, ctx, itemContext);\n }\n\n // handle function components\n const [first, content, props = {}] = processedSpec as [ComponentType | Component, Content?, Props?];\n if (typeof first === 'function') {\n // function component: call it with (props, children)\n const children = Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]) || typeof content[0] === 'function')\n ? content as NodeSpec[]\n : undefined;\n const resolved = (first as Component)(props, children);\n return createElement(resolved, ctx, itemContext);\n }\n\n const type = first as ComponentType;\n\n // handle show prop - conditional rendering based on state\n if (props.show !== undefined) {\n const showKey = props.show;\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n const updateShow = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const showValue = state[showKey]?.();\n if (!showValue) return;\n\n // create the element without the show prop to avoid infinite recursion\n const { show: _, ...propsWithoutShow } = props;\n childCtx = { cleanups: [], state, theme: ctx.theme, plugins: ctx.plugins };\n currentEl = createElement([type, content, propsWithoutShow as Props], childCtx, itemContext);\n if (currentEl) {\n placeholder.appendChild(currentEl);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n };\n\n effect(updateShow, ctx);\n return placeholder;\n }\n\n let el: HTMLElement;\n\n switch (type) {\n case 'V':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'column';\n break;\n case 'H':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'row';\n break;\n case 'G':\n el = document.createElement('div');\n el.style.display = 'grid';\n if (props.cols) {\n el.style.gridTemplateColumns = typeof props.cols === 'number'\n ? `repeat(${props.cols}, 1fr)` : props.cols;\n }\n if (props.rows) {\n el.style.gridTemplateRows = typeof props.rows === 'number'\n ? `repeat(${props.rows}, 1fr)` : props.rows;\n }\n break;\n case 'D':\n el = document.createElement('div');\n break;\n case 'T':\n el = document.createElement('span');\n break;\n case 'B':\n el = document.createElement('button');\n break;\n case 'I':\n el = document.createElement('input');\n (el as HTMLInputElement).type = props.type || 'text';\n if (props.ph) (el as HTMLInputElement).placeholder = props.ph;\n if (props.ro) (el as HTMLInputElement).readOnly = true;\n break;\n case 'Ta':\n el = document.createElement('textarea');\n if (props.ph) (el as HTMLTextAreaElement).placeholder = props.ph;\n if (props.rw) (el as HTMLTextAreaElement).rows = props.rw;\n if (props.ro) (el as HTMLTextAreaElement).readOnly = true;\n break;\n case 'S':\n el = document.createElement('select');\n if (props.opts) {\n props.opts.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt.v;\n option.textContent = opt.l;\n el.appendChild(option);\n });\n }\n break;\n case 'C':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'checkbox';\n break;\n case 'R':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'radio';\n break;\n case 'Tb':\n el = document.createElement('table');\n break;\n case 'Th':\n el = document.createElement('thead');\n break;\n case 'Tbd':\n el = document.createElement('tbody');\n break;\n case 'Tr':\n el = document.createElement('tr');\n break;\n case 'Td':\n el = document.createElement('td');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Tc':\n el = document.createElement('th');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Ul':\n el = document.createElement('ul');\n break;\n case 'Ol':\n el = document.createElement('ol');\n break;\n case 'Li':\n el = document.createElement('li');\n break;\n case 'M':\n el = document.createElement('img');\n if (props.src) {\n const safeSrc = sanitizeUrl(props.src, 'src');\n if (safeSrc) (el as HTMLImageElement).src = safeSrc;\n }\n if (props.alt) (el as HTMLImageElement).alt = props.alt;\n break;\n case 'L':\n el = document.createElement('a');\n if (props.href) {\n const safeHref = sanitizeUrl(props.href, 'href');\n if (safeHref) (el as HTMLAnchorElement).href = safeHref;\n }\n break;\n case 'Sv':\n el = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as unknown as HTMLElement;\n break;\n default:\n console.warn(`[tooey] unknown component type: ${type}`);\n el = document.createElement('div');\n }\n\n if (props.cls) el.className = props.cls;\n if (props.id) el.id = props.id;\n if (props.dis) (el as HTMLButtonElement).disabled = true;\n\n applyStyles(el, props, ctx.theme);\n\n // handle content\n if (content !== undefined) {\n if (Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]) || isErrorBoundaryNode(content[0]))) {\n (content as NodeSpec[]).forEach(childSpec => {\n const child = createElement(childSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n });\n } else if (isIfNode(content) || isMapNode(content) || isErrorBoundaryNode(content)) {\n const child = createElement(content as NodeSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n } else if (isStateRef(content)) {\n effect(() => {\n const val = resolveValue(content, state);\n if (type === 'I') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n } else {\n // textContent provides XSS protection by not parsing HTML\n el.textContent = String(val ?? '');\n }\n }, ctx);\n } else if (typeof content === 'string' || typeof content === 'number') {\n let textContent = String(content);\n if (itemContext) {\n // handle object property access first (before $item replacement)\n if (typeof itemContext.item === 'object' && itemContext.item !== null) {\n textContent = textContent.replace(/\\$item\\.(\\w+)/g, (_, key) => {\n return String((itemContext.item as Record<string, unknown>)[key] ?? '');\n });\n }\n textContent = textContent.replace(/\\$item/g, String(itemContext.item));\n textContent = textContent.replace(/\\$index/g, String(itemContext.index));\n }\n // xss protection for static content\n if (type === 'I') {\n (el as HTMLInputElement).value = textContent;\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = textContent;\n } else if (type !== 'S') {\n // don't set textContent for select (would clear options)\n el.textContent = textContent;\n }\n }\n }\n\n // handle value binding for inputs\n if (props.v !== undefined && isStateRef(props.v)) {\n effect(() => {\n const val = resolveValue(props.v!, state);\n if (type === 'I' || type === 'S' || type === 'Ta') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n }\n }, ctx);\n }\n\n // handle checked binding\n if (props.ch !== undefined) {\n if (isStateRef(props.ch as unknown)) {\n effect(() => {\n const val = resolveValue(props.ch as unknown as StateRef, state);\n (el as HTMLInputElement).checked = Boolean(val);\n }, ctx);\n } else {\n (el as HTMLInputElement).checked = Boolean(props.ch);\n }\n }\n\n // event handlers with cleanup tracking\n const addEventListener = (event: string, handler: (e: Event) => void) => {\n el.addEventListener(event, handler);\n ctx.cleanups.push(() => el.removeEventListener(event, handler));\n };\n\n // get button text for implicit operation inference\n const buttonText = type === 'B' && (typeof content === 'string' || typeof content === 'number')\n ? String(content)\n : undefined;\n\n if (props.c) {\n addEventListener('click', (e) => createHandler(props.c!, state, e, itemContext, buttonText)());\n }\n if (props.x) {\n const handler = props.x;\n addEventListener('input', (e) => {\n if (typeof handler === 'function') {\n handler();\n } else {\n // normalize string shorthand to array form\n let stateKey: string;\n let op: Op;\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n [stateKey, op] = parsed;\n } else {\n // plain state key defaults to set (!) for input\n stateKey = handler;\n op = '!';\n }\n } else {\n [stateKey, op] = handler;\n }\n const sig = state[stateKey];\n if (sig) {\n const target = e.target as HTMLInputElement;\n const val = (type === 'C' || type === 'R') ? target.checked : target.value;\n applyOp(sig, op, val);\n }\n }\n });\n }\n if (props.f) {\n addEventListener('focus', (e) => createHandler(props.f!, state, e, itemContext)());\n }\n if (props.bl) {\n addEventListener('blur', (e) => createHandler(props.bl!, state, e, itemContext)());\n }\n if (props.k) {\n addEventListener('keydown', (e) => createHandler(props.k!, state, e, itemContext)());\n }\n if (props.ku) {\n addEventListener('keyup', (e) => createHandler(props.ku!, state, e, itemContext)());\n }\n if (props.kp) {\n addEventListener('keypress', (e) => createHandler(props.kp!, state, e, itemContext)());\n }\n if (props.e) {\n addEventListener('mouseenter', (e) => createHandler(props.e!, state, e, itemContext)());\n }\n if (props.lv) {\n addEventListener('mouseleave', (e) => createHandler(props.lv!, state, e, itemContext)());\n }\n if (props.sub) {\n addEventListener('submit', (e) => {\n e.preventDefault();\n createHandler(props.sub!, state, e, itemContext)();\n });\n }\n\n // apply afterRender hooks from plugins\n if (ctx.plugins) {\n for (const plugin of ctx.plugins) {\n if (plugin.afterRender) {\n plugin.afterRender(el, processedSpec);\n }\n }\n }\n\n return el;\n}\n\n// ============ main api ============\n\ninterface TooeyInstance {\n state: StateStore;\n el: HTMLElement | null;\n destroy(): void;\n update(newSpec: TooeySpec): void;\n get(key: string): unknown;\n set(key: string, value: unknown): void;\n // allow dynamic extension by plugins\n [key: string]: unknown;\n}\n\nfunction render(container: HTMLElement, spec: TooeySpec, options?: RenderOptions): TooeyInstance {\n if (!container) {\n throw new Error('[tooey] render requires a valid container element');\n }\n if (!spec || !spec.r) {\n throw new Error('[tooey] render requires a spec with a root node (r)');\n }\n\n const theme = options?.theme;\n const plugins = options?.plugins || [];\n\n // helper to create signals with plugin state change notification\n const createStateSignal = (key: string, initial: StateValue): Signal<StateValue> => {\n const sig = signal(initial);\n const originalSet = sig.set.bind(sig);\n sig.set = (v: StateValue | ((prev: StateValue) => StateValue)) => {\n const oldVal = sig();\n originalSet(v);\n const newVal = sig();\n if (oldVal !== newVal) {\n plugins.forEach(p => p.onStateChange?.(key, oldVal, newVal));\n }\n };\n return sig;\n };\n\n const state: StateStore = {};\n if (spec.s) {\n Object.entries(spec.s).forEach(([key, val]) => {\n state[key] = createStateSignal(key, val);\n });\n }\n\n const ctx: RenderContext = { cleanups: [], state, theme, plugins };\n\n container.innerHTML = '';\n const el = createElement(spec.r, ctx);\n if (el) container.appendChild(el);\n\n const instance: TooeyInstance = {\n state,\n el,\n destroy() {\n // call onDestroy hooks\n plugins.forEach(p => p.onDestroy?.(instance));\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n },\n update(newSpec: TooeySpec) {\n if (newSpec.s) {\n batch(() => {\n Object.entries(newSpec.s!).forEach(([key, val]) => {\n if (state[key]) {\n state[key].set(val);\n } else {\n state[key] = createStateSignal(key, val);\n }\n });\n });\n }\n if (newSpec.r) {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n const newEl = createElement(newSpec.r, ctx);\n if (newEl) container.appendChild(newEl);\n instance.el = newEl;\n }\n },\n get(key: string) {\n return state[key]?.();\n },\n set(key: string, value: unknown) {\n if (state[key]) {\n state[key].set(value);\n }\n }\n };\n\n // apply plugin extend methods\n plugins.forEach(plugin => {\n if (plugin.extend) {\n Object.entries(plugin.extend).forEach(([name, fn]) => {\n instance[name] = fn.bind(instance);\n });\n }\n });\n\n // call onInit hooks\n plugins.forEach(p => p.onInit?.(instance));\n\n return instance;\n}\n\n// ============ factory function ============\n\ninterface CreateTooeyOptions {\n theme?: Theme;\n plugins?: TooeyPlugin[];\n}\n\ninterface TooeyFactory {\n render: (container: HTMLElement, spec: TooeySpec) => TooeyInstance;\n theme: Theme;\n plugins?: TooeyPlugin[];\n}\n\n// createTooey supports both a Theme directly (backward compatible) or CreateTooeyOptions\nfunction createTooey(themeOrOptions: Theme | CreateTooeyOptions): TooeyFactory {\n // detect if it's a theme (has colors/spacing/radius/fonts) or options (has theme/plugins keys)\n const isOptions = themeOrOptions && ('theme' in themeOrOptions || 'plugins' in themeOrOptions);\n const theme = isOptions ? (themeOrOptions as CreateTooeyOptions).theme : (themeOrOptions as Theme);\n const plugins = isOptions ? (themeOrOptions as CreateTooeyOptions).plugins : undefined;\n return {\n render: (container: HTMLElement, spec: TooeySpec) => render(container, spec, { theme, plugins }),\n theme: theme!,\n plugins\n };\n}\n\n// ============ convenience helpers ============\n\nfunction $(name: string): StateRef {\n return { $: name };\n}\n\n// component type constants\nconst V = 'V' as const;\nconst H = 'H' as const;\nconst D = 'D' as const;\nconst G = 'G' as const;\nconst T = 'T' as const;\nconst B = 'B' as const;\nconst I = 'I' as const;\nconst Ta = 'Ta' as const;\nconst S = 'S' as const;\nconst C = 'C' as const;\nconst R = 'R' as const;\nconst Tb = 'Tb' as const;\nconst Th = 'Th' as const;\nconst Tbd = 'Tbd' as const;\nconst Tr = 'Tr' as const;\nconst Td = 'Td' as const;\nconst Tc = 'Tc' as const;\nconst Ul = 'Ul' as const;\nconst Ol = 'Ol' as const;\nconst Li = 'Li' as const;\nconst M = 'M' as const;\nconst L = 'L' as const;\nconst Sv = 'Sv' as const;\n\nexport {\n render,\n createTooey,\n signal,\n effect,\n batch,\n computed,\n async$,\n $,\n V, H, D, G,\n T, B,\n I, Ta, S, C, R,\n Tb, Th, Tbd, Tr, Td, Tc,\n Ul, Ol, Li,\n M, L, Sv,\n TooeySpec,\n NodeSpec,\n Props,\n StateRef,\n TooeyInstance,\n TooeyFactory,\n CreateTooeyOptions,\n IfNode,\n MapNode,\n ErrorBoundaryNode,\n ErrorInfo,\n ErrorHandler,\n Component,\n Theme,\n RenderOptions,\n TooeyPlugin,\n ComputedSignal,\n AsyncSpec\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isErrorBoundaryNode", "v", "createErrorFallback", "error", "el", "currentEffect", "batchDepth", "pendingEffects", "signal", "initial", "value", "subscribers", "sig", "newValue", "fn", "batch", "effects", "effect", "ctx", "isActive", "execute", "cleanup", "computed", "cachedValue", "isDirty", "recompute", "sub", "prevEffect", "subFn", "async$", "promiseOrFn", "options", "instance", "data", "err", "errorMessage", "applyOp", "state", "op", "val", "arr", "_", "i", "item", "isStateRef", "isIfNode", "isMapNode", "resolveValue", "content", "resolveCssValue", "resolveThemeValue", "token", "theme", "categories", "category", "cat", "key", "styleShortcuts", "expandStyleValue", "parseEventShorthand", "str", "lastChar", "bangIdx", "stateKey", "valStr", "SAFE_URL_PROTOCOLS", "isValidUrl", "url", "parsed", "lowerUrl", "pattern", "sanitizeUrl", "propName", "createHandler", "handler", "state", "event", "itemContext", "buttonText", "normalizedHandler", "parseEventShorthand", "stateKey", "op", "val", "sig", "actualVal", "key", "target", "applyOp", "resolveStyleValue", "theme", "token", "themeVal", "resolveThemeValue", "applyStyles", "el", "props", "style", "resolve", "resolved", "resolveCssValue", "resolveStr", "v", "posMap", "expandStyleValue", "createElement", "spec", "ctx", "isErrorBoundaryNode", "placeholder", "childCtx", "child", "err", "errorInfo", "fallbackEl", "createErrorFallback", "isIfNode", "currentEl", "ifCond", "thenBranch", "elseBranch", "eqValue", "effect", "fn", "rawValue", "resolveValue", "condition", "branch", "isMapNode", "mapSource", "asTemplate", "arr", "item", "index", "processedSpec", "plugin", "first", "content", "children", "type", "showKey", "_", "propsWithoutShow", "opt", "option", "safeSrc", "safeHref", "childSpec", "isStateRef", "textContent", "addEventListener", "e", "render", "container", "options", "plugins", "createStateSignal", "initial", "signal", "originalSet", "oldVal", "newVal", "p", "instance", "newSpec", "batch", "newEl", "value", "name", "createTooey", "themeOrOptions", "isOptions", "$", "V", "H", "D", "G", "T", "B", "I", "Ta", "S", "C", "R", "Tb", "Th", "Tbd", "Tr", "Td", "Tc", "Ul", "Ol", "Li", "M", "L", "Sv"]
|
|
7
7
|
}
|
package/dist/tooey.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var tooey=(()=>{var N=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var _=(n,e)=>{for(var t in e)N(n,t,{get:e[t],enumerable:!0})},G=(n,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of P(e))!q.call(n,o)&&o!==t&&N(n,o,{get:()=>e[o],enumerable:!(s=z(e,o))||s.enumerable});return n};var F=n=>G(N({},"__esModule",{value:!0}),n);var ve={};_(ve,{$:()=>ee,B:()=>se,C:()=>fe,D:()=>re,G:()=>ie,H:()=>te,I:()=>oe,L:()=>we,Li:()=>Se,M:()=>ke,Ol:()=>Te,R:()=>de,S:()=>ce,Sv:()=>pe,T:()=>ae,Ta:()=>le,Tb:()=>ue,Tbd:()=>ge,Tc:()=>Ee,Td:()=>ye,Th:()=>me,Tr:()=>be,Ul:()=>he,V:()=>ne,batch:()=>U,effect:()=>S,render:()=>Z,signal:()=>V});function K(n){return typeof n=="object"&&n!==null&&"boundary"in n&&n.boundary===!0}function B(n){let e=document.createElement("div");return e.style.cssText="padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px",e.textContent=`[tooey error] ${n.message}`,e}var v=null,H=0,x=new Set;function V(n){let e=n,t=new Set,s=()=>(v&&t.add(v),e);return s.set=o=>{let l=typeof o=="function"?o(e):o;l!==e&&(e=l,H>0?t.forEach(r=>x.add(r)):t.forEach(r=>r()))},s.sub=o=>(t.add(o),()=>t.delete(o)),s}function U(n){H++;try{n()}finally{if(H--,H===0){let e=x;x=new Set,e.forEach(t=>t())}}}function S(n,e){let t=!0,s=()=>{if(t){v=s;try{n()}finally{v=null}}};s();let o=()=>{t=!1,v=null};return e&&e.cleanups.push(o),o}function D(n,e,t){try{switch(e){case"+":n.set(s=>s+(typeof t=="number"?t:1));break;case"-":n.set(s=>s-(typeof t=="number"?t:1));break;case"!":n.set(t);break;case"~":n.set(s=>!s);break;case"<":n.set(s=>[...s,t]);break;case">":n.set(s=>[t,...s]);break;case"X":n.set(s=>{let o=s;return typeof t=="number"?o.filter((l,r)=>r!==t):typeof t=="function"?o.filter((l,r)=>!t(l,r)):o.filter(l=>l!==t)});break;case".":Array.isArray(t)&&t.length===2&&n.set(s=>({...s,[t[0]]:t[1]}));break}}catch(s){console.warn("[tooey] state operation error:",e,s)}}function L(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&"$"in n}function R(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("if"in n||"?"in n)}function A(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("map"in n||"m"in n)}function p(n,e){if(L(n)){let t=e[n.$];if(!t){console.warn(`[tooey] unknown state key: "${n.$}"`);return}return t()}return n}function u(n){if(n!==void 0)return typeof n=="number"?`${n}px`:n}var X={c:"center",sb:"space-between",sa:"space-around",se:"space-evenly",fe:"flex-end",fs:"flex-start",st:"stretch",bl:"baseline"};function C(n){if(n!==void 0)return X[n]||n}function W(n){if(typeof n!="string"||n.length<2)return null;let e=n[n.length-1];if(e==="+"||e==="-"||e==="~")return[n.slice(0,-1),e];let t=n.indexOf("!");if(t>0){let s=n.slice(0,t),o=n.slice(t+1),l=o;return o==="true"?l=!0:o==="false"?l=!1:!isNaN(Number(o))&&o!==""&&(l=Number(o)),[s,"!",l]}return null}var J=["http:","https:","mailto:","tel:","ftp:"];function Q(n){if(!n||typeof n!="string")return!1;if(n.startsWith("/")||n.startsWith("#")||n.startsWith("."))return!0;try{let e=new URL(n,window.location.href);return J.includes(e.protocol)}catch{let e=n.toLowerCase().trim();return!["javascript:","data:","vbscript:"].some(s=>e.startsWith(s))}}function j(n,e){return n?Q(n)?n:(console.warn(`[tooey] blocked unsafe URL in ${e}: "${n.slice(0,50)}..."`),null):null}function b(n,e,t,s,o){if(typeof n=="function")return n;let l;if(typeof n=="string"){let h=W(n);h?l=h:o==="+"?l=[n,"+"]:o==="-"?l=[n,"-"]:l=[n,"~"]}else l=n;let[r,a,d]=l;return()=>{let h=e[r];if(!h){console.warn(`[tooey] click handler: unknown state key "${r}"`);return}let i=d;if(s&&typeof i=="string"){if(i==="$index")i=s.index;else if(i==="$item")i=s.item;else if(i.startsWith("$item.")){let c=i.substring(6);i=s.item?.[c]}}if(a==="!"&&d===void 0&&t){let c=t.target;i=c.type==="checkbox"?c.checked:c.value}D(h,a,i)}}function Y(n,e){let t=n.style;if(e.g!==void 0&&(t.gap=u(e.g)),e.p!==void 0&&(t.padding=u(e.p)),e.m!==void 0&&(t.margin=u(e.m)),e.w!==void 0&&(t.width=u(e.w)),e.h!==void 0&&(t.height=u(e.h)),e.mw!==void 0&&(t.maxWidth=u(e.mw)),e.mh!==void 0&&(t.maxHeight=u(e.mh)),e.bg!==void 0&&(t.background=e.bg),e.fg!==void 0&&(t.color=e.fg),e.o!==void 0&&(t.opacity=String(e.o)),e.r!==void 0&&(t.borderRadius=u(e.r)),e.bw!==void 0&&(t.borderWidth=u(e.bw)),e.bc!==void 0&&(t.borderColor=e.bc),e.bs!==void 0&&(t.borderStyle=e.bs),e.pos!==void 0){let s={rel:"relative",abs:"absolute",fix:"fixed",sticky:"sticky"};t.position=s[e.pos]||e.pos}e.z!==void 0&&(t.zIndex=String(e.z)),e.t!==void 0&&(t.top=u(e.t)),e.l!==void 0&&(t.left=u(e.l)),(typeof e.b=="number"||typeof e.b=="string"&&!Array.isArray(e.b))&&(t.bottom=u(e.b)),e.rt!==void 0&&(t.right=u(e.rt)),e.fs!==void 0&&(t.fontSize=u(e.fs)),e.fw!==void 0&&(t.fontWeight=String(e.fw)),e.ff!==void 0&&(t.fontFamily=e.ff),e.ta!==void 0&&(t.textAlign=e.ta),e.td!==void 0&&(t.textDecoration=e.td),e.lh!==void 0&&(t.lineHeight=typeof e.lh=="number"?String(e.lh):e.lh),e.ls!==void 0&&(t.letterSpacing=u(e.ls)),e.ai!==void 0&&(t.alignItems=C(e.ai)),e.jc!==void 0&&(t.justifyContent=C(e.jc)),e.flw!==void 0&&(t.flexWrap=C(e.flw)),e.cur!==void 0&&(t.cursor=e.cur),e.ov!==void 0&&(t.overflow=e.ov),e.pe!==void 0&&(t.pointerEvents=e.pe),e.us!==void 0&&(t.userSelect=e.us),e.sh!==void 0&&(t.boxShadow=e.sh),e.tr!==void 0&&(t.transform=e.tr),e.s&&Object.entries(e.s).forEach(([s,o])=>{t[s]=String(o)})}function y(n,e,t){let{state:s}=e;if(K(n)){let i=document.createElement("div");i.style.display="contents";try{let c={cleanups:[],state:s,onError:n.onError||e.onError},f=y(n.child,c,t);f&&(i.appendChild(f),e.cleanups.push(...c.cleanups))}catch(c){let f={message:c instanceof Error?c.message:String(c),stack:c instanceof Error?c.stack:void 0};if(n.onError&&n.onError(f),n.fallback)try{let m=y(n.fallback,e,t);m&&i.appendChild(m)}catch{i.appendChild(B(f))}else i.appendChild(B(f))}return i}if(R(n)){let i=document.createElement("div");i.style.display="contents";let c=null,f=null,m=n.if??n["?"],k=n.then??n.t,g=n.else??n.e,E=n.eq??n.is;return S(()=>{f&&(f.cleanups.forEach(I=>I()),f.cleanups=[]),c&&(i.innerHTML="",c=null);let w=typeof m=="string"?s[m]?.():p(m,s),M;E!==void 0?M=w===E:M=!!w;let T=M?k:g;T&&(f={cleanups:[],state:s},Array.isArray(T)&&T.length>0&&Array.isArray(T[0])?T.forEach(I=>{let $=y(I,f,t);$&&i.appendChild($)}):(c=y(T,f,t),c&&i.appendChild(c)))},e),i}if(A(n)){let i=document.createElement("div");i.style.display="contents";let c=null,f=n.map??n.m,m=n.as??n.a;return S(()=>{c&&(c.cleanups.forEach(E=>E()),c.cleanups=[]),i.innerHTML="";let g=typeof f=="string"?s[f]?.():p(f,s);!Array.isArray(g)||!m||(c={cleanups:[],state:s},g.forEach((E,O)=>{let w=y(m,c,{item:E,index:O});w&&i.appendChild(w)}))},e),i}if(!Array.isArray(n)||n.length===0)return console.warn("[tooey] invalid node spec:",n),null;let[o,l,r={}]=n,a;switch(o){case"V":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="column";break;case"H":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="row";break;case"G":a=document.createElement("div"),a.style.display="grid",r.cols&&(a.style.gridTemplateColumns=typeof r.cols=="number"?`repeat(${r.cols}, 1fr)`:r.cols),r.rows&&(a.style.gridTemplateRows=typeof r.rows=="number"?`repeat(${r.rows}, 1fr)`:r.rows);break;case"D":a=document.createElement("div");break;case"T":a=document.createElement("span");break;case"B":a=document.createElement("button");break;case"I":a=document.createElement("input"),a.type=r.type||"text",r.ph&&(a.placeholder=r.ph),r.ro&&(a.readOnly=!0);break;case"Ta":a=document.createElement("textarea"),r.ph&&(a.placeholder=r.ph),r.rw&&(a.rows=r.rw),r.ro&&(a.readOnly=!0);break;case"S":a=document.createElement("select"),r.opts&&r.opts.forEach(i=>{let c=document.createElement("option");c.value=i.v,c.textContent=i.l,a.appendChild(c)});break;case"C":a=document.createElement("input"),a.type="checkbox";break;case"R":a=document.createElement("input"),a.type="radio";break;case"Tb":a=document.createElement("table");break;case"Th":a=document.createElement("thead");break;case"Tbd":a=document.createElement("tbody");break;case"Tr":a=document.createElement("tr");break;case"Td":a=document.createElement("td"),r.sp&&(a.colSpan=r.sp),r.rsp&&(a.rowSpan=r.rsp);break;case"Tc":a=document.createElement("th"),r.sp&&(a.colSpan=r.sp),r.rsp&&(a.rowSpan=r.rsp);break;case"Ul":a=document.createElement("ul");break;case"Ol":a=document.createElement("ol");break;case"Li":a=document.createElement("li");break;case"M":if(a=document.createElement("img"),r.src){let i=j(r.src,"src");i&&(a.src=i)}r.alt&&(a.alt=r.alt);break;case"L":if(a=document.createElement("a"),r.href){let i=j(r.href,"href");i&&(a.href=i)}break;case"Sv":a=document.createElementNS("http://www.w3.org/2000/svg","svg");break;default:console.warn(`[tooey] unknown component type: ${o}`),a=document.createElement("div")}if(r.cls&&(a.className=r.cls),r.id&&(a.id=r.id),r.dis&&(a.disabled=!0),Y(a,r),l!==void 0){if(Array.isArray(l)&&l.length>0&&(Array.isArray(l[0])||R(l[0])||A(l[0])))l.forEach(i=>{let c=y(i,e,t);c&&a.appendChild(c)});else if(R(l)||A(l)){let i=y(l,e,t);i&&a.appendChild(i)}else if(L(l))S(()=>{let i=p(l,s);o==="I"||o==="Ta"?a.value=String(i??""):o==="C"||o==="R"?a.checked=!!i:a.textContent=String(i??"")},e);else if(typeof l=="string"||typeof l=="number"){let i=String(l);t&&(typeof t.item=="object"&&t.item!==null&&(i=i.replace(/\$item\.(\w+)/g,(c,f)=>String(t.item[f]??""))),i=i.replace(/\$item/g,String(t.item)),i=i.replace(/\$index/g,String(t.index))),o==="I"||o==="Ta"?a.value=i:o!=="S"&&(a.textContent=i)}}r.v!==void 0&&L(r.v)&&S(()=>{let i=p(r.v,s);o==="I"||o==="S"||o==="Ta"?a.value=String(i??""):(o==="C"||o==="R")&&(a.checked=!!i)},e),r.ch!==void 0&&(L(r.ch)?S(()=>{let i=p(r.ch,s);a.checked=!!i},e):a.checked=!!r.ch);let d=(i,c)=>{a.addEventListener(i,c),e.cleanups.push(()=>a.removeEventListener(i,c))},h=o==="B"&&(typeof l=="string"||typeof l=="number")?String(l):void 0;if(r.c&&d("click",i=>b(r.c,s,i,t,h)()),r.x){let i=r.x;d("input",c=>{if(typeof i=="function")i();else{let f,m;if(typeof i=="string"){let g=W(i);g?[f,m]=g:(f=i,m="!")}else[f,m]=i;let k=s[f];if(k){let g=c.target,E=o==="C"||o==="R"?g.checked:g.value;D(k,m,E)}}})}return r.f&&d("focus",i=>b(r.f,s,i,t)()),r.bl&&d("blur",i=>b(r.bl,s,i,t)()),r.k&&d("keydown",i=>b(r.k,s,i,t)()),r.ku&&d("keyup",i=>b(r.ku,s,i,t)()),r.kp&&d("keypress",i=>b(r.kp,s,i,t)()),r.e&&d("mouseenter",i=>b(r.e,s,i,t)()),r.lv&&d("mouseleave",i=>b(r.lv,s,i,t)()),r.sub&&d("submit",i=>{i.preventDefault(),b(r.sub,s,i,t)()}),a}function Z(n,e){if(!n)throw new Error("[tooey] render requires a valid container element");if(!e||!e.r)throw new Error("[tooey] render requires a spec with a root node (r)");let t={};e.s&&Object.entries(e.s).forEach(([r,a])=>{t[r]=V(a)});let s={cleanups:[],state:t};n.innerHTML="";let o=y(e.r,s);o&&n.appendChild(o);let l={state:t,el:o,destroy(){s.cleanups.forEach(r=>r()),s.cleanups=[],n.innerHTML=""},update(r){if(r.s&&U(()=>{Object.entries(r.s).forEach(([a,d])=>{t[a]?t[a].set(d):t[a]=V(d)})}),r.r){s.cleanups.forEach(d=>d()),s.cleanups=[],n.innerHTML="";let a=y(r.r,s);a&&n.appendChild(a),l.el=a}},get(r){return t[r]?.()},set(r,a){t[r]&&t[r].set(a)}};return l}function ee(n){return{$:n}}var ne="V",te="H",re="D",ie="G",ae="T",se="B",oe="I",le="Ta",ce="S",fe="C",de="R",ue="Tb",me="Th",ge="Tbd",be="Tr",ye="Td",Ee="Tc",he="Ul",Te="Ol",Se="Li",ke="M",we="L",pe="Sv";return F(ve);})();
|
|
1
|
+
"use strict";var tooey=(()=>{var $=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var X=(n,e)=>{for(var i in e)$(n,i,{get:e[i],enumerable:!0})},J=(n,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of G(e))!K.call(n,c)&&c!==i&&$(n,c,{get:()=>e[c],enumerable:!(r=F(e,c))||r.enumerable});return n};var Q=n=>J($({},"__esModule",{value:!0}),n);var Ie={};X(Ie,{$:()=>ae,B:()=>ge,C:()=>be,D:()=>ue,G:()=>de,H:()=>le,I:()=>me,L:()=>Ne,Li:()=>Me,M:()=>Ce,Ol:()=>Le,R:()=>Te,S:()=>he,Sv:()=>Re,T:()=>fe,Ta:()=>ye,Tb:()=>pe,Tbd:()=>Se,Tc:()=>ve,Td:()=>ke,Th:()=>Ee,Tr:()=>we,Ul:()=>He,V:()=>ce,async$:()=>Z,batch:()=>U,computed:()=>Y,createTooey:()=>se,effect:()=>k,render:()=>q,signal:()=>W});function P(n){return typeof n=="object"&&n!==null&&"boundary"in n&&n.boundary===!0}function j(n){let e=document.createElement("div");return e.style.cssText="padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px",e.textContent=`[tooey error] ${n.message}`,e}var T=null,L=0,I=new Set;function W(n){let e=n,i=new Set,r=(()=>(T&&i.add(T),e));return r.set=c=>{let d=typeof c=="function"?c(e):c;d!==e&&(e=d,L>0?i.forEach(t=>I.add(t)):i.forEach(t=>t()))},r.sub=c=>(i.add(c),()=>i.delete(c)),r}function U(n){L++;try{n()}finally{if(L--,L===0){let e=I;I=new Set,e.forEach(i=>i())}}}function k(n,e){let i=!0,r=()=>{if(i){T=r;try{n()}finally{T=null}}};r();let c=()=>{i=!1,T=null};return e&&e.cleanups.push(c),c}function Y(n){let e,i=!0,r=new Set,c=()=>{i=!0,L>0?r.forEach(t=>I.add(t)):r.forEach(t=>t())},d=(()=>{if(T&&r.add(T),i){let t=T;T=c;try{e=n()}finally{T=t}i=!1}return e});return d.sub=t=>(r.add(t),()=>r.delete(t)),d}function Z(n,e){return{s:{data:null,loading:!0,error:null},async init(i){try{let c=await(typeof n=="function"?n():n);i.set("data",c),i.set("loading",!1)}catch(r){let c=r instanceof Error?r.message:String(r);i.set("error",c),i.set("loading",!1),e?.onError&&r instanceof Error&&e.onError(r)}}}}function z(n,e,i){try{switch(e){case"+":n.set(r=>r+(typeof i=="number"?i:1));break;case"-":n.set(r=>r-(typeof i=="number"?i:1));break;case"!":n.set(i);break;case"~":n.set(r=>!r);break;case"<":n.set(r=>[...r,i]);break;case">":n.set(r=>[i,...r]);break;case"X":n.set(r=>{let c=r;return typeof i=="number"?c.filter((d,t)=>t!==i):typeof i=="function"?c.filter((d,t)=>!i(d,t)):c.filter(d=>d!==i)});break;case".":Array.isArray(i)&&i.length===2&&n.set(r=>({...r,[i[0]]:i[1]}));break}}catch(r){console.warn("[tooey] state operation error:",e,r)}}function R(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&"$"in n}function C(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("if"in n||"?"in n)}function N(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)&&("map"in n||"m"in n)}function H(n,e){if(R(n)){let i=e[n.$];if(!i){console.warn(`[tooey] unknown state key: "${n.$}"`);return}return i()}return n}function ee(n){if(n!==void 0)return typeof n=="number"?`${n}px`:n}function ne(n,e){if(!e)return;let i=["colors","spacing","radius","fonts"];for(let r of i){let c=e[r];if(c&&n in c)return c[n]}for(let[r,c]of Object.entries(e))if(c&&!i.includes(r)&&n in c)return c[n]}var te={c:"center",sb:"space-between",sa:"space-around",se:"space-evenly",fe:"flex-end",fs:"flex-start",st:"stretch",bl:"baseline"};function x(n){if(n!==void 0)return te[n]||n}function _(n){if(typeof n!="string"||n.length<2)return null;let e=n[n.length-1];if(e==="+"||e==="-"||e==="~")return[n.slice(0,-1),e];let i=n.indexOf("!");if(i>0){let r=n.slice(0,i),c=n.slice(i+1),d=c;return c==="true"?d=!0:c==="false"?d=!1:!isNaN(Number(c))&&c!==""&&(d=Number(c)),[r,"!",d]}return null}var re=["http:","https:","mailto:","tel:","ftp:"];function oe(n){if(!n||typeof n!="string")return!1;if(n.startsWith("/")||n.startsWith("#")||n.startsWith("."))return!0;try{let e=new URL(n,window.location.href);return re.includes(e.protocol)}catch{let e=n.toLowerCase().trim();return!["javascript:","data:","vbscript:"].some(r=>e.startsWith(r))}}function D(n,e){return n?oe(n)?n:(console.warn(`[tooey] blocked unsafe URL in ${e}: "${n.slice(0,50)}..."`),null):null}function S(n,e,i,r,c){if(typeof n=="function")return n;let d;if(typeof n=="string"){let a=_(n);a?d=a:c==="+"?d=[n,"+"]:c==="-"?d=[n,"-"]:d=[n,"~"]}else d=n;let[t,s,g]=d;return()=>{let a=e[t];if(!a){console.warn(`[tooey] click handler: unknown state key "${t}"`);return}let l=g;if(r&&typeof l=="string"){if(l==="$index")l=r.index;else if(l==="$item")l=r.item;else if(l.startsWith("$item.")){let m=l.substring(6);l=r.item?.[m]}}if(s==="!"&&g===void 0&&i){let m=i.target;l=m.type==="checkbox"?m.checked:m.value}z(a,s,l)}}function B(n,e){if(n!==void 0){if(typeof n=="string"&&n.startsWith("$")){let i=n.slice(1),r=ne(i,e);if(r!==void 0)return r;console.warn(`[tooey] unknown theme token: "${n}"`);return}return n}}function ie(n,e,i){let r=n.style,c=t=>{let s=B(t,i);return ee(s)},d=t=>{if(t===void 0)return;let s=B(t,i);return s!==void 0?String(s):void 0};if(e.g!==void 0){let t=c(e.g);t&&(r.gap=t)}if(e.p!==void 0){let t=c(e.p);t&&(r.padding=t)}if(e.m!==void 0){let t=c(e.m);t&&(r.margin=t)}if(e.w!==void 0){let t=c(e.w);t&&(r.width=t)}if(e.h!==void 0){let t=c(e.h);t&&(r.height=t)}if(e.mw!==void 0){let t=c(e.mw);t&&(r.maxWidth=t)}if(e.mh!==void 0){let t=c(e.mh);t&&(r.maxHeight=t)}if(e.bg!==void 0){let t=d(e.bg);t&&(r.background=t)}if(e.fg!==void 0){let t=d(e.fg);t&&(r.color=t)}if(e.o!==void 0&&(r.opacity=String(e.o)),e.r!==void 0){let t=c(e.r);t&&(r.borderRadius=t)}if(e.bw!==void 0){let t=c(e.bw);t&&(r.borderWidth=t)}if(e.bc!==void 0){let t=d(e.bc);t&&(r.borderColor=t)}if(e.bs!==void 0&&(r.borderStyle=e.bs),e.pos!==void 0){let t={rel:"relative",abs:"absolute",fix:"fixed",sticky:"sticky"};r.position=t[e.pos]||e.pos}if(e.z!==void 0&&(r.zIndex=String(e.z)),e.t!==void 0){let t=c(e.t);t&&(r.top=t)}if(e.l!==void 0){let t=c(e.l);t&&(r.left=t)}if(typeof e.b=="number"||typeof e.b=="string"&&!Array.isArray(e.b)){let t=c(e.b);t&&(r.bottom=t)}if(e.rt!==void 0){let t=c(e.rt);t&&(r.right=t)}if(e.fs!==void 0){let t=c(e.fs);t&&(r.fontSize=t)}if(e.fw!==void 0&&(r.fontWeight=String(e.fw)),e.ff!==void 0){let t=d(e.ff);t&&(r.fontFamily=t)}if(e.ta!==void 0&&(r.textAlign=e.ta),e.td!==void 0&&(r.textDecoration=e.td),e.lh!==void 0&&(r.lineHeight=typeof e.lh=="number"?String(e.lh):e.lh),e.ls!==void 0){let t=c(e.ls);t&&(r.letterSpacing=t)}if(e.ai!==void 0&&(r.alignItems=x(e.ai)),e.jc!==void 0&&(r.justifyContent=x(e.jc)),e.flw!==void 0&&(r.flexWrap=x(e.flw)),e.cur!==void 0&&(r.cursor=e.cur),e.ov!==void 0&&(r.overflow=e.ov),e.pe!==void 0&&(r.pointerEvents=e.pe),e.us!==void 0&&(r.userSelect=e.us),e.sh!==void 0){let t=d(e.sh);t&&(r.boxShadow=t)}e.tr!==void 0&&(r.transform=e.tr),e.s&&Object.entries(e.s).forEach(([t,s])=>{let g=B(s,i);g!==void 0&&(r[t]=String(g))})}function b(n,e,i){let{state:r}=e;if(P(n)){let o=document.createElement("div");o.style.display="contents";try{let u={cleanups:[],state:r,onError:n.onError||e.onError},f=b(n.child,u,i);f&&(o.appendChild(f),e.cleanups.push(...u.cleanups))}catch(u){let f={message:u instanceof Error?u.message:String(u),stack:u instanceof Error?u.stack:void 0};if(n.onError&&n.onError(f),n.fallback)try{let y=b(n.fallback,e,i);y&&o.appendChild(y)}catch{o.appendChild(j(f))}else o.appendChild(j(f))}return o}if(C(n)){let o=document.createElement("div");o.style.display="contents";let u=null,f=null,y=n.if??n["?"],p=n.then??n.t,h=n.else??n.e,E=n.eq??n.is;return k(()=>{f&&(f.cleanups.forEach(V=>V()),f.cleanups=[]),u&&(o.innerHTML="",u=null);let w=typeof y=="string"?r[y]?.():H(y,r),A;E!==void 0?A=w===E:A=!!w;let v=A?p:h;v&&(f={cleanups:[],state:r},Array.isArray(v)&&v.length>0&&Array.isArray(v[0])?v.forEach(V=>{let O=b(V,f,i);O&&o.appendChild(O)}):(u=b(v,f,i),u&&o.appendChild(u)))},e),o}if(N(n)){let o=document.createElement("div");o.style.display="contents";let u=null,f=n.map??n.m,y=n.as??n.a;return k(()=>{u&&(u.cleanups.forEach(E=>E()),u.cleanups=[]),o.innerHTML="";let h=typeof f=="string"?r[f]?.():H(f,r);!Array.isArray(h)||!y||(u={cleanups:[],state:r},h.forEach((E,M)=>{let w=b(y,u,{item:E,index:M});w&&o.appendChild(w)}))},e),o}if(!Array.isArray(n)||n.length===0)return console.warn("[tooey] invalid node spec:",n),null;let c=n;if(e.plugins)for(let o of e.plugins)o.beforeRender&&(c=o.beforeRender(c,e));if(!Array.isArray(c))return b(c,e,i);let[d,t,s={}]=c;if(typeof d=="function"){let o=Array.isArray(t)&&t.length>0&&(Array.isArray(t[0])||C(t[0])||N(t[0])||typeof t[0]=="function")?t:void 0,u=d(s,o);return b(u,e,i)}let g=d;if(s.show!==void 0){let o=s.show,u=document.createElement("div");u.style.display="contents";let f=null,y=null;return k(()=>{if(y&&(y.cleanups.forEach(w=>w()),y.cleanups=[]),f&&(u.innerHTML="",f=null),!r[o]?.())return;let{show:E,...M}=s;y={cleanups:[],state:r,theme:e.theme,plugins:e.plugins},f=b([g,t,M],y,i),f&&(u.appendChild(f),e.cleanups.push(...y.cleanups))},e),u}let a;switch(g){case"V":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="column";break;case"H":a=document.createElement("div"),a.style.display="flex",a.style.flexDirection="row";break;case"G":a=document.createElement("div"),a.style.display="grid",s.cols&&(a.style.gridTemplateColumns=typeof s.cols=="number"?`repeat(${s.cols}, 1fr)`:s.cols),s.rows&&(a.style.gridTemplateRows=typeof s.rows=="number"?`repeat(${s.rows}, 1fr)`:s.rows);break;case"D":a=document.createElement("div");break;case"T":a=document.createElement("span");break;case"B":a=document.createElement("button");break;case"I":a=document.createElement("input"),a.type=s.type||"text",s.ph&&(a.placeholder=s.ph),s.ro&&(a.readOnly=!0);break;case"Ta":a=document.createElement("textarea"),s.ph&&(a.placeholder=s.ph),s.rw&&(a.rows=s.rw),s.ro&&(a.readOnly=!0);break;case"S":a=document.createElement("select"),s.opts&&s.opts.forEach(o=>{let u=document.createElement("option");u.value=o.v,u.textContent=o.l,a.appendChild(u)});break;case"C":a=document.createElement("input"),a.type="checkbox";break;case"R":a=document.createElement("input"),a.type="radio";break;case"Tb":a=document.createElement("table");break;case"Th":a=document.createElement("thead");break;case"Tbd":a=document.createElement("tbody");break;case"Tr":a=document.createElement("tr");break;case"Td":a=document.createElement("td"),s.sp&&(a.colSpan=s.sp),s.rsp&&(a.rowSpan=s.rsp);break;case"Tc":a=document.createElement("th"),s.sp&&(a.colSpan=s.sp),s.rsp&&(a.rowSpan=s.rsp);break;case"Ul":a=document.createElement("ul");break;case"Ol":a=document.createElement("ol");break;case"Li":a=document.createElement("li");break;case"M":if(a=document.createElement("img"),s.src){let o=D(s.src,"src");o&&(a.src=o)}s.alt&&(a.alt=s.alt);break;case"L":if(a=document.createElement("a"),s.href){let o=D(s.href,"href");o&&(a.href=o)}break;case"Sv":a=document.createElementNS("http://www.w3.org/2000/svg","svg");break;default:console.warn(`[tooey] unknown component type: ${g}`),a=document.createElement("div")}if(s.cls&&(a.className=s.cls),s.id&&(a.id=s.id),s.dis&&(a.disabled=!0),ie(a,s,e.theme),t!==void 0){if(Array.isArray(t)&&t.length>0&&(Array.isArray(t[0])||C(t[0])||N(t[0])||P(t[0])))t.forEach(o=>{let u=b(o,e,i);u&&a.appendChild(u)});else if(C(t)||N(t)||P(t)){let o=b(t,e,i);o&&a.appendChild(o)}else if(R(t))k(()=>{let o=H(t,r);g==="I"||g==="Ta"?a.value=String(o??""):g==="C"||g==="R"?a.checked=!!o:a.textContent=String(o??"")},e);else if(typeof t=="string"||typeof t=="number"){let o=String(t);i&&(typeof i.item=="object"&&i.item!==null&&(o=o.replace(/\$item\.(\w+)/g,(u,f)=>String(i.item[f]??""))),o=o.replace(/\$item/g,String(i.item)),o=o.replace(/\$index/g,String(i.index))),g==="I"||g==="Ta"?a.value=o:g!=="S"&&(a.textContent=o)}}s.v!==void 0&&R(s.v)&&k(()=>{let o=H(s.v,r);g==="I"||g==="S"||g==="Ta"?a.value=String(o??""):(g==="C"||g==="R")&&(a.checked=!!o)},e),s.ch!==void 0&&(R(s.ch)?k(()=>{let o=H(s.ch,r);a.checked=!!o},e):a.checked=!!s.ch);let l=(o,u)=>{a.addEventListener(o,u),e.cleanups.push(()=>a.removeEventListener(o,u))},m=g==="B"&&(typeof t=="string"||typeof t=="number")?String(t):void 0;if(s.c&&l("click",o=>S(s.c,r,o,i,m)()),s.x){let o=s.x;l("input",u=>{if(typeof o=="function")o();else{let f,y;if(typeof o=="string"){let h=_(o);h?[f,y]=h:(f=o,y="!")}else[f,y]=o;let p=r[f];if(p){let h=u.target,E=g==="C"||g==="R"?h.checked:h.value;z(p,y,E)}}})}if(s.f&&l("focus",o=>S(s.f,r,o,i)()),s.bl&&l("blur",o=>S(s.bl,r,o,i)()),s.k&&l("keydown",o=>S(s.k,r,o,i)()),s.ku&&l("keyup",o=>S(s.ku,r,o,i)()),s.kp&&l("keypress",o=>S(s.kp,r,o,i)()),s.e&&l("mouseenter",o=>S(s.e,r,o,i)()),s.lv&&l("mouseleave",o=>S(s.lv,r,o,i)()),s.sub&&l("submit",o=>{o.preventDefault(),S(s.sub,r,o,i)()}),e.plugins)for(let o of e.plugins)o.afterRender&&o.afterRender(a,c);return a}function q(n,e,i){if(!n)throw new Error("[tooey] render requires a valid container element");if(!e||!e.r)throw new Error("[tooey] render requires a spec with a root node (r)");let r=i?.theme,c=i?.plugins||[],d=(l,m)=>{let o=W(m),u=o.set.bind(o);return o.set=f=>{let y=o();u(f);let p=o();y!==p&&c.forEach(h=>h.onStateChange?.(l,y,p))},o},t={};e.s&&Object.entries(e.s).forEach(([l,m])=>{t[l]=d(l,m)});let s={cleanups:[],state:t,theme:r,plugins:c};n.innerHTML="";let g=b(e.r,s);g&&n.appendChild(g);let a={state:t,el:g,destroy(){c.forEach(l=>l.onDestroy?.(a)),s.cleanups.forEach(l=>l()),s.cleanups=[],n.innerHTML=""},update(l){if(l.s&&U(()=>{Object.entries(l.s).forEach(([m,o])=>{t[m]?t[m].set(o):t[m]=d(m,o)})}),l.r){s.cleanups.forEach(o=>o()),s.cleanups=[],n.innerHTML="";let m=b(l.r,s);m&&n.appendChild(m),a.el=m}},get(l){return t[l]?.()},set(l,m){t[l]&&t[l].set(m)}};return c.forEach(l=>{l.extend&&Object.entries(l.extend).forEach(([m,o])=>{a[m]=o.bind(a)})}),c.forEach(l=>l.onInit?.(a)),a}function se(n){let e=n&&("theme"in n||"plugins"in n),i=e?n.theme:n,r=e?n.plugins:void 0;return{render:(c,d)=>q(c,d,{theme:i,plugins:r}),theme:i,plugins:r}}function ae(n){return{$:n}}var ce="V",le="H",ue="D",de="G",fe="T",ge="B",me="I",ye="Ta",he="S",be="C",Te="R",pe="Tb",Ee="Th",Se="Tbd",we="Tr",ke="Td",ve="Tc",He="Ul",Le="Ol",Me="Li",Ce="M",Ne="L",Re="Sv";return Q(Ie);})();
|
|
2
2
|
if(typeof module!=="undefined")module.exports=tooey;
|
|
3
3
|
//# sourceMappingURL=tooey.js.map
|
package/dist/tooey.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/tooey.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * tooey - token-efficient ui library for llms\n *\n * component types:\n * layout: V (vstack), H (hstack), D (div), G (grid)\n * text & buttons: T (text/span), B (button)\n * inputs: I (input), Ta (textarea), S (select), C (checkbox), R (radio)\n * tables: Tb (table), Th (thead), Tbd (tbody), Tr (tr), Td (td), Tc (th)\n * lists: Ul (ul), Ol (ol), Li (li)\n * media & links: M (image), L (link), Sv (svg)\n *\n * props (short keys):\n * spacing: g (gap), p (padding), m (margin), w (width), h (height), mw, mh\n * colors: bg (background), fg (color), o (opacity)\n * borders: r (border-radius), bw (border-width), bc (border-color), bs (border-style)\n * positioning: pos (position), z (z-index), t (top), l (left), rt (right)\n * typography: fs (font-size), fw (font-weight), ff (font-family), ta, td, lh, ls\n * layout: ai (align-items), jc (justify-content), flw (flex-wrap), cols, rows\n * shortcuts: c=center, sb=space-between, fe=flex-end, fs=flex-start, st=stretch\n * misc: cur (cursor), ov (overflow), pe (pointer-events), us (user-select), sh, tr\n * element-specific: v (value), ph (placeholder), type, href, src, alt, dis, ch, ro, opts\n *\n * events: c (click), x (input/change), f (focus), bl (blur), k (keydown), ku, kp, e, lv, sub\n * shorthand: \"state+\" (increment), \"state-\" (decrement), \"state~\" (toggle), \"state!val\" (set)\n *\n * state operations: + (increment), - (decrement), ! (set), ~ (toggle), < (append), > (prepend), X (remove), . (set prop)\n *\n * control flow (short form): {?: cond, t: [...], e: [...]} | {m: state, a: [...]}\n * control flow (long form): {if: state, then: [...], else: [...]} | {map: state, as: [...]}\n * equality check: {?: \"state\", is: 0, t: [...]} or {?: {$:\"state\"}, is: 0, t: [...]}\n */\n\n// ============ types ============\n\ntype StateValue = unknown;\ntype StateStore = Record<string, Signal<StateValue>>;\n\ninterface Signal<T> {\n (): T;\n set(v: T | ((prev: T) => T)): void;\n sub(fn: () => void): () => void;\n}\n\ntype Op = '+' | '-' | '!' | '~' | '<' | '>' | 'X' | '.';\ntype EventHandler = [string, Op, unknown?] | (() => void) | string;\n\ninterface Props {\n // spacing/sizing\n g?: number | string;\n p?: number | string;\n m?: number | string;\n w?: number | string;\n h?: number | string;\n mw?: number | string;\n mh?: number | string;\n // colors\n bg?: string;\n fg?: string;\n o?: number;\n // borders\n r?: number | string;\n bw?: number | string;\n bc?: string;\n bs?: string;\n // positioning\n pos?: 'rel' | 'abs' | 'fix' | 'sticky' | string;\n z?: number;\n t?: number | string;\n l?: number | string;\n b?: number | string;\n rt?: number | string;\n // typography\n fs?: number | string;\n fw?: number | string;\n ff?: string;\n ta?: string;\n td?: string;\n lh?: number | string;\n ls?: number | string;\n // layout\n ai?: string;\n jc?: string;\n flw?: string;\n cols?: number | string;\n rows?: number | string;\n // misc\n cur?: string;\n ov?: string;\n pe?: string;\n us?: string;\n sh?: string;\n tr?: string;\n // element-specific\n v?: unknown;\n ph?: string;\n type?: string;\n href?: string;\n src?: string;\n alt?: string;\n dis?: boolean;\n ch?: unknown;\n ro?: boolean;\n opts?: Array<{v: string, l: string}>;\n cls?: string;\n id?: string;\n rw?: number;\n sp?: number;\n rsp?: number;\n // events\n c?: EventHandler;\n x?: EventHandler;\n f?: EventHandler;\n bl?: EventHandler;\n k?: EventHandler;\n ku?: EventHandler;\n kp?: EventHandler;\n e?: EventHandler;\n lv?: EventHandler;\n sub?: EventHandler;\n // custom styles\n s?: Record<string, unknown>;\n}\n\ntype ComponentType =\n | 'V' | 'H' | 'D' | 'G'\n | 'T' | 'B'\n | 'I' | 'Ta' | 'S' | 'C' | 'R'\n | 'Tb' | 'Th' | 'Tbd' | 'Tr' | 'Td' | 'Tc'\n | 'Ul' | 'Ol' | 'Li'\n | 'M' | 'L' | 'Sv';\n\ntype StateRef = { $: string };\n\ninterface IfNode {\n // Long form\n if?: StateRef | string;\n then?: NodeSpec | NodeSpec[];\n else?: NodeSpec | NodeSpec[];\n // Short form\n '?'?: StateRef | string;\n t?: NodeSpec | NodeSpec[];\n e?: NodeSpec | NodeSpec[];\n // Equality check (works with both forms)\n eq?: unknown;\n is?: unknown;\n}\n\ninterface MapNode {\n // Long form\n map?: StateRef | string;\n as?: NodeSpec;\n // Short form\n m?: StateRef | string;\n a?: NodeSpec;\n key?: string;\n}\n\ntype Content = string | number | StateRef | NodeSpec[] | IfNode | MapNode;\ntype NodeSpec = [ComponentType, Content?, Props?] | IfNode | MapNode;\n\ninterface TooeySpec {\n s?: Record<string, StateValue>;\n r: NodeSpec;\n}\n\n// ============ render context for cleanup ============\n\ninterface ErrorInfo {\n message: string;\n componentType?: string;\n stack?: string;\n}\n\ntype ErrorHandler = (error: ErrorInfo) => void;\n\ninterface RenderContext {\n cleanups: Array<() => void>;\n state: StateStore;\n onError?: ErrorHandler;\n}\n\n// ============ error boundary ============\n\ninterface ErrorBoundaryNode {\n boundary: true;\n child: NodeSpec;\n fallback?: NodeSpec;\n onError?: ErrorHandler;\n}\n\nfunction isErrorBoundaryNode(v: unknown): v is ErrorBoundaryNode {\n return typeof v === 'object' && v !== null && 'boundary' in v && (v as ErrorBoundaryNode).boundary === true;\n}\n\nfunction createErrorFallback(error: ErrorInfo): HTMLElement {\n const el = document.createElement('div');\n el.style.cssText = 'padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px';\n el.textContent = `[tooey error] ${error.message}`;\n return el;\n}\n\n// ============ signals ============\n\nlet currentEffect: (() => void) | null = null;\nlet batchDepth = 0;\nlet pendingEffects = new Set<() => void>();\n\nfunction signal<T>(initial: T): Signal<T> {\n let value = initial;\n const subscribers = new Set<() => void>();\n\n const sig = (() => {\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n return value;\n }) as Signal<T>;\n\n sig.set = (v: T | ((prev: T) => T)) => {\n const newValue = typeof v === 'function' ? (v as (prev: T) => T)(value) : v;\n if (newValue !== value) {\n value = newValue;\n if (batchDepth > 0) {\n subscribers.forEach(fn => pendingEffects.add(fn));\n } else {\n subscribers.forEach(fn => fn());\n }\n }\n };\n\n sig.sub = (fn: () => void) => {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n };\n\n return sig;\n}\n\nfunction batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n const effects = pendingEffects;\n pendingEffects = new Set();\n effects.forEach(fn => fn());\n }\n }\n}\n\nfunction effect(fn: () => void, ctx?: RenderContext): () => void {\n let isActive = true;\n\n const execute = () => {\n if (!isActive) return;\n currentEffect = execute;\n try {\n fn();\n } finally {\n currentEffect = null;\n }\n };\n\n execute();\n\n const cleanup = () => {\n isActive = false;\n currentEffect = null;\n };\n\n if (ctx) {\n ctx.cleanups.push(cleanup);\n }\n\n return cleanup;\n}\n\n// ============ state operations ============\n\nfunction applyOp(state: Signal<StateValue>, op: Op, val?: unknown): void {\n try {\n switch (op) {\n case '+':\n state.set((v: StateValue) => (v as number) + (typeof val === 'number' ? val : 1));\n break;\n case '-':\n state.set((v: StateValue) => (v as number) - (typeof val === 'number' ? val : 1));\n break;\n case '!':\n state.set(val);\n break;\n case '~':\n state.set((v: StateValue) => !v);\n break;\n case '<':\n state.set((v: StateValue) => [...(v as unknown[]), val]);\n break;\n case '>':\n state.set((v: StateValue) => [val, ...(v as unknown[])]);\n break;\n case 'X':\n state.set((v: StateValue) => {\n const arr = v as unknown[];\n if (typeof val === 'number') {\n return arr.filter((_, i) => i !== val);\n } else if (typeof val === 'function') {\n return arr.filter((item, i) => !(val as (item: unknown, i: number) => boolean)(item, i));\n }\n return arr.filter(item => item !== val);\n });\n break;\n case '.':\n if (Array.isArray(val) && val.length === 2) {\n state.set((v: StateValue) => ({ ...(v as Record<string, unknown>), [val[0]]: val[1] }));\n }\n break;\n }\n } catch (err) {\n console.warn('[tooey] state operation error:', op, err);\n }\n}\n\n// ============ helpers ============\n\nfunction isStateRef(v: unknown): v is StateRef {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && '$' in v;\n}\n\nfunction isIfNode(v: unknown): v is IfNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('if' in v || '?' in v);\n}\n\nfunction isMapNode(v: unknown): v is MapNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('map' in v || 'm' in v);\n}\n\nfunction resolveValue(content: unknown, state: StateStore): unknown {\n if (isStateRef(content)) {\n const sig = state[content.$];\n if (!sig) {\n console.warn(`[tooey] unknown state key: \"${content.$}\"`);\n return undefined;\n }\n return sig();\n }\n return content;\n}\n\nfunction resolveCssValue(val: number | string | undefined): string | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'number') return `${val}px`;\n return val;\n}\n\n// Style value shortcuts for common layout values\nconst styleShortcuts: Record<string, string> = {\n 'c': 'center',\n 'sb': 'space-between',\n 'sa': 'space-around',\n 'se': 'space-evenly',\n 'fe': 'flex-end',\n 'fs': 'flex-start',\n 'st': 'stretch',\n 'bl': 'baseline',\n};\n\nfunction expandStyleValue(val: string | undefined): string | undefined {\n if (val === undefined) return undefined;\n return styleShortcuts[val] || val;\n}\n\n// Parse string-based event handler shorthand\n// Format: \"stateName+\" | \"stateName-\" | \"stateName~\" | \"stateName!value\"\nfunction parseEventShorthand(str: string): [string, Op, unknown?] | null {\n if (typeof str !== 'string' || str.length < 2) return null;\n\n const lastChar = str[str.length - 1];\n\n // Simple ops: +, -, ~\n if (lastChar === '+' || lastChar === '-' || lastChar === '~') {\n return [str.slice(0, -1), lastChar as Op];\n }\n\n // Set operation with value: \"state!value\"\n const bangIdx = str.indexOf('!');\n if (bangIdx > 0) {\n const stateKey = str.slice(0, bangIdx);\n const valStr = str.slice(bangIdx + 1);\n // Try to parse as number or boolean\n let val: unknown = valStr;\n if (valStr === 'true') val = true;\n else if (valStr === 'false') val = false;\n else if (!isNaN(Number(valStr)) && valStr !== '') val = Number(valStr);\n return [stateKey, '!', val];\n }\n\n return null;\n}\n\n// XSS protection - escape HTML entities (kept for future use, textContent provides protection now)\nfunction _escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n// URL validation - prevent dangerous protocols\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nfunction isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n\n // Allow relative URLs and anchors\n if (url.startsWith('/') || url.startsWith('#') || url.startsWith('.')) {\n return true;\n }\n\n try {\n const parsed = new URL(url, window.location.href);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n // If URL parsing fails, check for dangerous patterns directly\n const lowerUrl = url.toLowerCase().trim();\n const dangerousPatterns = ['javascript:', 'data:', 'vbscript:'];\n return !dangerousPatterns.some(pattern => lowerUrl.startsWith(pattern));\n }\n}\n\nfunction sanitizeUrl(url: string, propName: string): string | null {\n if (!url) return null;\n\n if (!isValidUrl(url)) {\n console.warn(`[tooey] blocked unsafe URL in ${propName}: \"${url.slice(0, 50)}...\"`);\n return null;\n }\n\n return url;\n}\n\nfunction createHandler(\n handler: EventHandler,\n state: StateStore,\n event?: Event,\n itemContext?: { item: unknown, index: number },\n buttonText?: string\n): () => void {\n if (typeof handler === 'function') {\n return handler;\n }\n\n // Handle string shorthand: \"state+\", \"state-\", \"state~\", \"state!value\"\n let normalizedHandler: [string, Op, unknown?];\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n normalizedHandler = parsed;\n } else {\n // Plain state key - infer operation from button text if available\n if (buttonText === '+') {\n normalizedHandler = [handler, '+'];\n } else if (buttonText === '-') {\n normalizedHandler = [handler, '-'];\n } else {\n // Default to toggle for plain state key\n normalizedHandler = [handler, '~'];\n }\n }\n } else {\n normalizedHandler = handler;\n }\n\n const [stateKey, op, val] = normalizedHandler;\n return () => {\n const sig = state[stateKey];\n if (!sig) {\n console.warn(`[tooey] click handler: unknown state key \"${stateKey}\"`);\n return;\n }\n let actualVal = val;\n // Resolve $item and $index in event handler values\n if (itemContext && typeof actualVal === 'string') {\n if (actualVal === '$index') {\n actualVal = itemContext.index;\n } else if (actualVal === '$item') {\n actualVal = itemContext.item;\n } else if (actualVal.startsWith('$item.')) {\n const key = actualVal.substring(6);\n actualVal = (itemContext.item as Record<string, unknown>)?.[key];\n }\n }\n if (op === '!' && val === undefined && event) {\n const target = event.target as HTMLInputElement;\n actualVal = target.type === 'checkbox' ? target.checked : target.value;\n }\n applyOp(sig, op, actualVal);\n };\n}\n\n// ============ styles ============\n\nfunction applyStyles(el: HTMLElement, props: Props): void {\n const style = el.style;\n\n if (props.g !== undefined) style.gap = resolveCssValue(props.g)!;\n if (props.p !== undefined) style.padding = resolveCssValue(props.p)!;\n if (props.m !== undefined) style.margin = resolveCssValue(props.m)!;\n if (props.w !== undefined) style.width = resolveCssValue(props.w)!;\n if (props.h !== undefined) style.height = resolveCssValue(props.h)!;\n if (props.mw !== undefined) style.maxWidth = resolveCssValue(props.mw)!;\n if (props.mh !== undefined) style.maxHeight = resolveCssValue(props.mh)!;\n\n if (props.bg !== undefined) style.background = props.bg;\n if (props.fg !== undefined) style.color = props.fg;\n if (props.o !== undefined) style.opacity = String(props.o);\n\n if (props.r !== undefined) style.borderRadius = resolveCssValue(props.r)!;\n if (props.bw !== undefined) style.borderWidth = resolveCssValue(props.bw)!;\n if (props.bc !== undefined) style.borderColor = props.bc;\n if (props.bs !== undefined) style.borderStyle = props.bs;\n\n if (props.pos !== undefined) {\n const posMap: Record<string, string> = {\n rel: 'relative', abs: 'absolute', fix: 'fixed', sticky: 'sticky'\n };\n style.position = posMap[props.pos] || props.pos;\n }\n if (props.z !== undefined) style.zIndex = String(props.z);\n if (props.t !== undefined) style.top = resolveCssValue(props.t)!;\n if (props.l !== undefined) style.left = resolveCssValue(props.l)!;\n if (typeof props.b === 'number' || (typeof props.b === 'string' && !Array.isArray(props.b))) {\n style.bottom = resolveCssValue(props.b as number | string)!;\n }\n if (props.rt !== undefined) style.right = resolveCssValue(props.rt)!;\n\n if (props.fs !== undefined) style.fontSize = resolveCssValue(props.fs)!;\n if (props.fw !== undefined) style.fontWeight = String(props.fw);\n if (props.ff !== undefined) style.fontFamily = props.ff;\n if (props.ta !== undefined) style.textAlign = props.ta;\n if (props.td !== undefined) style.textDecoration = props.td;\n if (props.lh !== undefined) style.lineHeight = typeof props.lh === 'number' ? String(props.lh) : props.lh;\n if (props.ls !== undefined) style.letterSpacing = resolveCssValue(props.ls)!;\n\n if (props.ai !== undefined) style.alignItems = expandStyleValue(props.ai)!;\n if (props.jc !== undefined) style.justifyContent = expandStyleValue(props.jc)!;\n if (props.flw !== undefined) style.flexWrap = expandStyleValue(props.flw)!\n\n if (props.cur !== undefined) style.cursor = props.cur;\n if (props.ov !== undefined) style.overflow = props.ov;\n if (props.pe !== undefined) style.pointerEvents = props.pe;\n if (props.us !== undefined) style.userSelect = props.us;\n if (props.sh !== undefined) style.boxShadow = props.sh;\n if (props.tr !== undefined) style.transform = props.tr;\n\n if (props.s) {\n Object.entries(props.s).forEach(([key, val]) => {\n (style as unknown as Record<string, string>)[key] = String(val);\n });\n }\n}\n\n// ============ renderer ============\n\nfunction createElement(\n spec: NodeSpec,\n ctx: RenderContext,\n itemContext?: { item: unknown, index: number }\n): HTMLElement | null {\n const { state } = ctx;\n\n // handle error boundary node\n if (isErrorBoundaryNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n try {\n const childCtx: RenderContext = {\n cleanups: [],\n state,\n onError: spec.onError || ctx.onError,\n };\n const child = createElement(spec.child, childCtx, itemContext);\n if (child) {\n placeholder.appendChild(child);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n } catch (err) {\n const errorInfo: ErrorInfo = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n\n if (spec.onError) {\n spec.onError(errorInfo);\n }\n\n if (spec.fallback) {\n try {\n const fallbackEl = createElement(spec.fallback, ctx, itemContext);\n if (fallbackEl) placeholder.appendChild(fallbackEl);\n } catch {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n } else {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n }\n\n return placeholder;\n }\n\n // handle reactive if node (supports both long and short form)\n if (isIfNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n // Normalize short form to long form\n const ifCond = spec.if ?? spec['?'];\n const thenBranch = spec.then ?? spec.t;\n const elseBranch = spec.else ?? spec.e;\n const eqValue = spec.eq ?? spec.is;\n\n const updateIf = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const rawValue = typeof ifCond === 'string'\n ? state[ifCond]?.()\n : resolveValue(ifCond, state);\n\n // Handle equality check (eq or is)\n let condition: boolean;\n if (eqValue !== undefined) {\n condition = rawValue === eqValue;\n } else {\n condition = Boolean(rawValue);\n }\n\n const branch = condition ? thenBranch : elseBranch;\n if (!branch) return;\n\n childCtx = { cleanups: [], state };\n\n if (Array.isArray(branch) && branch.length > 0 && Array.isArray(branch[0])) {\n (branch as NodeSpec[]).forEach(child => {\n const el = createElement(child, childCtx!, itemContext);\n if (el) placeholder.appendChild(el);\n });\n } else {\n currentEl = createElement(branch as NodeSpec, childCtx, itemContext);\n if (currentEl) placeholder.appendChild(currentEl);\n }\n };\n\n effect(updateIf, ctx);\n return placeholder;\n }\n\n // handle reactive map node (supports both long and short form)\n if (isMapNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let childCtx: RenderContext | null = null;\n\n // Normalize short form to long form\n const mapSource = spec.map ?? spec.m;\n const asTemplate = spec.as ?? spec.a;\n\n const updateMap = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n placeholder.innerHTML = '';\n\n const arr = (typeof mapSource === 'string'\n ? state[mapSource]?.()\n : resolveValue(mapSource, state)) as unknown[];\n\n if (!Array.isArray(arr) || !asTemplate) return;\n\n childCtx = { cleanups: [], state };\n\n arr.forEach((item, index) => {\n const el = createElement(asTemplate, childCtx!, { item, index });\n if (el) placeholder.appendChild(el);\n });\n };\n\n effect(updateMap, ctx);\n return placeholder;\n }\n\n // validate spec structure\n if (!Array.isArray(spec) || (spec as unknown[]).length === 0) {\n console.warn('[tooey] invalid node spec:', spec);\n return null;\n }\n\n const [type, content, props = {}] = spec as [ComponentType, Content?, Props?];\n let el: HTMLElement;\n\n switch (type) {\n case 'V':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'column';\n break;\n case 'H':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'row';\n break;\n case 'G':\n el = document.createElement('div');\n el.style.display = 'grid';\n if (props.cols) {\n el.style.gridTemplateColumns = typeof props.cols === 'number'\n ? `repeat(${props.cols}, 1fr)` : props.cols;\n }\n if (props.rows) {\n el.style.gridTemplateRows = typeof props.rows === 'number'\n ? `repeat(${props.rows}, 1fr)` : props.rows;\n }\n break;\n case 'D':\n el = document.createElement('div');\n break;\n case 'T':\n el = document.createElement('span');\n break;\n case 'B':\n el = document.createElement('button');\n break;\n case 'I':\n el = document.createElement('input');\n (el as HTMLInputElement).type = props.type || 'text';\n if (props.ph) (el as HTMLInputElement).placeholder = props.ph;\n if (props.ro) (el as HTMLInputElement).readOnly = true;\n break;\n case 'Ta':\n el = document.createElement('textarea');\n if (props.ph) (el as HTMLTextAreaElement).placeholder = props.ph;\n if (props.rw) (el as HTMLTextAreaElement).rows = props.rw;\n if (props.ro) (el as HTMLTextAreaElement).readOnly = true;\n break;\n case 'S':\n el = document.createElement('select');\n if (props.opts) {\n props.opts.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt.v;\n option.textContent = opt.l;\n el.appendChild(option);\n });\n }\n break;\n case 'C':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'checkbox';\n break;\n case 'R':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'radio';\n break;\n case 'Tb':\n el = document.createElement('table');\n break;\n case 'Th':\n el = document.createElement('thead');\n break;\n case 'Tbd':\n el = document.createElement('tbody');\n break;\n case 'Tr':\n el = document.createElement('tr');\n break;\n case 'Td':\n el = document.createElement('td');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Tc':\n el = document.createElement('th');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Ul':\n el = document.createElement('ul');\n break;\n case 'Ol':\n el = document.createElement('ol');\n break;\n case 'Li':\n el = document.createElement('li');\n break;\n case 'M':\n el = document.createElement('img');\n if (props.src) {\n const safeSrc = sanitizeUrl(props.src, 'src');\n if (safeSrc) (el as HTMLImageElement).src = safeSrc;\n }\n if (props.alt) (el as HTMLImageElement).alt = props.alt;\n break;\n case 'L':\n el = document.createElement('a');\n if (props.href) {\n const safeHref = sanitizeUrl(props.href, 'href');\n if (safeHref) (el as HTMLAnchorElement).href = safeHref;\n }\n break;\n case 'Sv':\n el = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as unknown as HTMLElement;\n break;\n default:\n console.warn(`[tooey] unknown component type: ${type}`);\n el = document.createElement('div');\n }\n\n if (props.cls) el.className = props.cls;\n if (props.id) el.id = props.id;\n if (props.dis) (el as HTMLButtonElement).disabled = true;\n\n applyStyles(el, props);\n\n // handle content\n if (content !== undefined) {\n if (Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]))) {\n (content as NodeSpec[]).forEach(childSpec => {\n const child = createElement(childSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n });\n } else if (isIfNode(content) || isMapNode(content)) {\n const child = createElement(content as NodeSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n } else if (isStateRef(content)) {\n effect(() => {\n const val = resolveValue(content, state);\n if (type === 'I') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n } else {\n // textContent provides XSS protection by not parsing HTML\n el.textContent = String(val ?? '');\n }\n }, ctx);\n } else if (typeof content === 'string' || typeof content === 'number') {\n let textContent = String(content);\n if (itemContext) {\n // handle object property access first (before $item replacement)\n if (typeof itemContext.item === 'object' && itemContext.item !== null) {\n textContent = textContent.replace(/\\$item\\.(\\w+)/g, (_, key) => {\n return String((itemContext.item as Record<string, unknown>)[key] ?? '');\n });\n }\n textContent = textContent.replace(/\\$item/g, String(itemContext.item));\n textContent = textContent.replace(/\\$index/g, String(itemContext.index));\n }\n // XSS protection for static content\n if (type === 'I') {\n (el as HTMLInputElement).value = textContent;\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = textContent;\n } else if (type !== 'S') {\n // don't set textContent for select (would clear options)\n el.textContent = textContent;\n }\n }\n }\n\n // handle value binding for inputs\n if (props.v !== undefined && isStateRef(props.v)) {\n effect(() => {\n const val = resolveValue(props.v!, state);\n if (type === 'I' || type === 'S' || type === 'Ta') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n }\n }, ctx);\n }\n\n // handle checked binding\n if (props.ch !== undefined) {\n if (isStateRef(props.ch as unknown)) {\n effect(() => {\n const val = resolveValue(props.ch as unknown as StateRef, state);\n (el as HTMLInputElement).checked = Boolean(val);\n }, ctx);\n } else {\n (el as HTMLInputElement).checked = Boolean(props.ch);\n }\n }\n\n // event handlers with cleanup tracking\n const addEventListener = (event: string, handler: (e: Event) => void) => {\n el.addEventListener(event, handler);\n ctx.cleanups.push(() => el.removeEventListener(event, handler));\n };\n\n // Get button text for implicit operation inference\n const buttonText = type === 'B' && (typeof content === 'string' || typeof content === 'number')\n ? String(content)\n : undefined;\n\n if (props.c) {\n addEventListener('click', (e) => createHandler(props.c!, state, e, itemContext, buttonText)());\n }\n if (props.x) {\n const handler = props.x;\n addEventListener('input', (e) => {\n if (typeof handler === 'function') {\n handler();\n } else {\n // Normalize string shorthand to array form\n let stateKey: string;\n let op: Op;\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n [stateKey, op] = parsed;\n } else {\n // Plain state key defaults to set (!) for input\n stateKey = handler;\n op = '!';\n }\n } else {\n [stateKey, op] = handler;\n }\n const sig = state[stateKey];\n if (sig) {\n const target = e.target as HTMLInputElement;\n const val = (type === 'C' || type === 'R') ? target.checked : target.value;\n applyOp(sig, op, val);\n }\n }\n });\n }\n if (props.f) {\n addEventListener('focus', (e) => createHandler(props.f!, state, e, itemContext)());\n }\n if (props.bl) {\n addEventListener('blur', (e) => createHandler(props.bl!, state, e, itemContext)());\n }\n if (props.k) {\n addEventListener('keydown', (e) => createHandler(props.k!, state, e, itemContext)());\n }\n if (props.ku) {\n addEventListener('keyup', (e) => createHandler(props.ku!, state, e, itemContext)());\n }\n if (props.kp) {\n addEventListener('keypress', (e) => createHandler(props.kp!, state, e, itemContext)());\n }\n if (props.e) {\n addEventListener('mouseenter', (e) => createHandler(props.e!, state, e, itemContext)());\n }\n if (props.lv) {\n addEventListener('mouseleave', (e) => createHandler(props.lv!, state, e, itemContext)());\n }\n if (props.sub) {\n addEventListener('submit', (e) => {\n e.preventDefault();\n createHandler(props.sub!, state, e, itemContext)();\n });\n }\n\n return el;\n}\n\n// ============ main api ============\n\ninterface TooeyInstance {\n state: StateStore;\n el: HTMLElement | null;\n destroy(): void;\n update(newSpec: TooeySpec): void;\n get(key: string): unknown;\n set(key: string, value: unknown): void;\n}\n\nfunction render(container: HTMLElement, spec: TooeySpec): TooeyInstance {\n if (!container) {\n throw new Error('[tooey] render requires a valid container element');\n }\n if (!spec || !spec.r) {\n throw new Error('[tooey] render requires a spec with a root node (r)');\n }\n\n const state: StateStore = {};\n if (spec.s) {\n Object.entries(spec.s).forEach(([key, val]) => {\n state[key] = signal(val);\n });\n }\n\n const ctx: RenderContext = { cleanups: [], state };\n\n container.innerHTML = '';\n const el = createElement(spec.r, ctx);\n if (el) container.appendChild(el);\n\n const instance: TooeyInstance = {\n state,\n el,\n destroy() {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n },\n update(newSpec: TooeySpec) {\n if (newSpec.s) {\n batch(() => {\n Object.entries(newSpec.s!).forEach(([key, val]) => {\n if (state[key]) {\n state[key].set(val);\n } else {\n state[key] = signal(val);\n }\n });\n });\n }\n if (newSpec.r) {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n const newEl = createElement(newSpec.r, ctx);\n if (newEl) container.appendChild(newEl);\n instance.el = newEl;\n }\n },\n get(key: string) {\n return state[key]?.();\n },\n set(key: string, value: unknown) {\n if (state[key]) {\n state[key].set(value);\n }\n }\n };\n\n return instance;\n}\n\n// ============ convenience helpers ============\n\nfunction $(name: string): StateRef {\n return { $: name };\n}\n\n// component type constants\nconst V = 'V' as const;\nconst H = 'H' as const;\nconst D = 'D' as const;\nconst G = 'G' as const;\nconst T = 'T' as const;\nconst B = 'B' as const;\nconst I = 'I' as const;\nconst Ta = 'Ta' as const;\nconst S = 'S' as const;\nconst C = 'C' as const;\nconst R = 'R' as const;\nconst Tb = 'Tb' as const;\nconst Th = 'Th' as const;\nconst Tbd = 'Tbd' as const;\nconst Tr = 'Tr' as const;\nconst Td = 'Td' as const;\nconst Tc = 'Tc' as const;\nconst Ul = 'Ul' as const;\nconst Ol = 'Ol' as const;\nconst Li = 'Li' as const;\nconst M = 'M' as const;\nconst L = 'L' as const;\nconst Sv = 'Sv' as const;\n\nexport {\n render,\n signal,\n effect,\n batch,\n $,\n V, H, D, G,\n T, B,\n I, Ta, S, C, R,\n Tb, Th, Tbd, Tr, Td, Tc,\n Ul, Ol, Li,\n M, L, Sv,\n TooeySpec,\n NodeSpec,\n Props,\n StateRef,\n TooeyInstance,\n IfNode,\n MapNode,\n ErrorBoundaryNode,\n ErrorInfo,\n ErrorHandler\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["tooey_exports", "__export", "$", "B", "C", "D", "G", "H", "I", "L", "Li", "M", "Ol", "R", "S", "Sv", "T", "Ta", "Tb", "Tbd", "Tc", "Td", "Th", "Tr", "Ul", "V", "batch", "effect", "render", "signal", "isErrorBoundaryNode", "v", "createErrorFallback", "error", "el", "currentEffect", "batchDepth", "pendingEffects", "initial", "value", "subscribers", "sig", "newValue", "fn", "effects", "ctx", "isActive", "execute", "cleanup", "applyOp", "state", "op", "val", "arr", "_", "i", "item", "
|
|
4
|
+
"sourcesContent": ["/**\n * tooey - token-efficient ui library for llms\n *\n * component types:\n * layout: V (vstack), H (hstack), D (div), G (grid)\n * text & buttons: T (text/span), B (button)\n * inputs: I (input), Ta (textarea), S (select), C (checkbox), R (radio)\n * tables: Tb (table), Th (thead), Tbd (tbody), Tr (tr), Td (td), Tc (th)\n * lists: Ul (ul), Ol (ol), Li (li)\n * media & links: M (image), L (link), Sv (svg)\n *\n * props (short keys):\n * spacing: g (gap), p (padding), m (margin), w (width), h (height), mw, mh\n * colors: bg (background), fg (color), o (opacity)\n * borders: r (border-radius), bw (border-width), bc (border-color), bs (border-style)\n * positioning: pos (position), z (z-index), t (top), l (left), rt (right)\n * typography: fs (font-size), fw (font-weight), ff (font-family), ta, td, lh, ls\n * layout: ai (align-items), jc (justify-content), flw (flex-wrap), cols, rows\n * shortcuts: c=center, sb=space-between, fe=flex-end, fs=flex-start, st=stretch\n * misc: cur (cursor), ov (overflow), pe (pointer-events), us (user-select), sh, tr\n * element-specific: v (value), ph (placeholder), type, href, src, alt, dis, ch, ro, opts\n *\n * events: c (click), x (input/change), f (focus), bl (blur), k (keydown), ku, kp, e, lv, sub\n * shorthand: \"state+\" (increment), \"state-\" (decrement), \"state~\" (toggle), \"state!val\" (set)\n *\n * state operations: + (increment), - (decrement), ! (set), ~ (toggle), < (append), > (prepend), X (remove), . (set prop)\n *\n * control flow (short form): {?: cond, t: [...], e: [...]} | {m: state, a: [...]}\n * control flow (long form): {if: state, then: [...], else: [...]} | {map: state, as: [...]}\n * equality check: {?: \"state\", is: 0, t: [...]} or {?: {$:\"state\"}, is: 0, t: [...]}\n */\n\n// ============ types ============\n\ntype StateValue = unknown;\ntype StateStore = Record<string, Signal<StateValue>>;\n\n// ============ theming ============\n\ntype ThemeValue = string | number;\ntype ThemeCategory = Record<string, ThemeValue>;\n\ninterface Theme {\n colors?: ThemeCategory;\n spacing?: ThemeCategory;\n radius?: ThemeCategory;\n fonts?: ThemeCategory;\n [key: string]: ThemeCategory | undefined;\n}\n\n// ============ plugins ============\n\ninterface TooeyPlugin {\n name: string;\n\n // lifecycle hooks\n onInit?(instance: TooeyInstance): void;\n onDestroy?(instance: TooeyInstance): void;\n\n // render hooks\n beforeRender?(spec: NodeSpec, ctx: RenderContext): NodeSpec;\n afterRender?(el: HTMLElement, spec: NodeSpec): void;\n\n // state hooks\n onStateChange?(key: string, oldVal: unknown, newVal: unknown): void;\n\n // extend instance with custom methods\n extend?: Record<string, (this: TooeyInstance, ...args: unknown[]) => unknown>;\n}\n\ninterface RenderOptions {\n theme?: Theme;\n plugins?: TooeyPlugin[];\n}\n\ninterface Signal<T> {\n (): T;\n set(v: T | ((prev: T) => T)): void;\n sub(fn: () => void): () => void;\n}\n\ntype Op = '+' | '-' | '!' | '~' | '<' | '>' | 'X' | '.';\ntype EventHandler = [string, Op, unknown?] | (() => void) | string;\n\ninterface Props {\n // conditional rendering\n show?: string; // state key - component only renders when state is truthy\n // spacing/sizing\n g?: number | string;\n p?: number | string;\n m?: number | string;\n w?: number | string;\n h?: number | string;\n mw?: number | string;\n mh?: number | string;\n // colors\n bg?: string;\n fg?: string;\n o?: number;\n // borders\n r?: number | string;\n bw?: number | string;\n bc?: string;\n bs?: string;\n // positioning\n pos?: 'rel' | 'abs' | 'fix' | 'sticky' | string;\n z?: number;\n t?: number | string;\n l?: number | string;\n b?: number | string;\n rt?: number | string;\n // typography\n fs?: number | string;\n fw?: number | string;\n ff?: string;\n ta?: string;\n td?: string;\n lh?: number | string;\n ls?: number | string;\n // layout\n ai?: string;\n jc?: string;\n flw?: string;\n cols?: number | string;\n rows?: number | string;\n // misc\n cur?: string;\n ov?: string;\n pe?: string;\n us?: string;\n sh?: string;\n tr?: string;\n // element-specific\n v?: unknown;\n ph?: string;\n type?: string;\n href?: string;\n src?: string;\n alt?: string;\n dis?: boolean;\n ch?: unknown;\n ro?: boolean;\n opts?: Array<{v: string, l: string}>;\n cls?: string;\n id?: string;\n rw?: number;\n sp?: number;\n rsp?: number;\n // events\n c?: EventHandler;\n x?: EventHandler;\n f?: EventHandler;\n bl?: EventHandler;\n k?: EventHandler;\n ku?: EventHandler;\n kp?: EventHandler;\n e?: EventHandler;\n lv?: EventHandler;\n sub?: EventHandler;\n // custom styles\n s?: Record<string, unknown>;\n}\n\ntype ComponentType =\n | 'V' | 'H' | 'D' | 'G'\n | 'T' | 'B'\n | 'I' | 'Ta' | 'S' | 'C' | 'R'\n | 'Tb' | 'Th' | 'Tbd' | 'Tr' | 'Td' | 'Tc'\n | 'Ul' | 'Ol' | 'Li'\n | 'M' | 'L' | 'Sv';\n\n// function component type - returns a NodeSpec\ntype Component<P extends Props = Props> = (props?: P, children?: NodeSpec[]) => NodeSpec;\n\ntype StateRef = { $: string };\n\ninterface IfNode {\n // long form\n if?: StateRef | string;\n then?: NodeSpec | NodeSpec[];\n else?: NodeSpec | NodeSpec[];\n // short form\n '?'?: StateRef | string;\n t?: NodeSpec | NodeSpec[];\n e?: NodeSpec | NodeSpec[];\n // equality check (works with both forms)\n eq?: unknown;\n is?: unknown;\n}\n\ninterface MapNode {\n // long form\n map?: StateRef | string;\n as?: NodeSpec;\n // short form\n m?: StateRef | string;\n a?: NodeSpec;\n key?: string;\n}\n\ntype Content = string | number | StateRef | NodeSpec[] | IfNode | MapNode;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype FunctionNodeSpec = [Component<any>, Content?, (Props & Record<string, unknown>)?];\ntype BuiltinNodeSpec = [ComponentType, Content?, Props?];\ntype NodeSpec = BuiltinNodeSpec | FunctionNodeSpec | IfNode | MapNode;\n\ninterface TooeySpec {\n s?: Record<string, StateValue>;\n r: NodeSpec;\n}\n\n// ============ render context for cleanup ============\n\ninterface ErrorInfo {\n message: string;\n componentType?: string;\n stack?: string;\n}\n\ntype ErrorHandler = (error: ErrorInfo) => void;\n\ninterface RenderContext {\n cleanups: Array<() => void>;\n state: StateStore;\n theme?: Theme;\n plugins?: TooeyPlugin[];\n onError?: ErrorHandler;\n}\n\n// ============ error boundary ============\n\ninterface ErrorBoundaryNode {\n boundary: true;\n child: NodeSpec;\n fallback?: NodeSpec;\n onError?: ErrorHandler;\n}\n\nfunction isErrorBoundaryNode(v: unknown): v is ErrorBoundaryNode {\n return typeof v === 'object' && v !== null && 'boundary' in v && (v as ErrorBoundaryNode).boundary === true;\n}\n\nfunction createErrorFallback(error: ErrorInfo): HTMLElement {\n const el = document.createElement('div');\n el.style.cssText = 'padding:12px;background:#fee;border:1px solid #fcc;border-radius:4px;color:#c00;font-family:monospace;font-size:12px';\n el.textContent = `[tooey error] ${error.message}`;\n return el;\n}\n\n// ============ signals ============\n\nlet currentEffect: (() => void) | null = null;\nlet batchDepth = 0;\nlet pendingEffects = new Set<() => void>();\n\nfunction signal<T>(initial: T): Signal<T> {\n let value = initial;\n const subscribers = new Set<() => void>();\n\n const sig = (() => {\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n return value;\n }) as Signal<T>;\n\n sig.set = (v: T | ((prev: T) => T)) => {\n const newValue = typeof v === 'function' ? (v as (prev: T) => T)(value) : v;\n if (newValue !== value) {\n value = newValue;\n if (batchDepth > 0) {\n subscribers.forEach(fn => pendingEffects.add(fn));\n } else {\n subscribers.forEach(fn => fn());\n }\n }\n };\n\n sig.sub = (fn: () => void) => {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n };\n\n return sig;\n}\n\nfunction batch(fn: () => void): void {\n batchDepth++;\n try {\n fn();\n } finally {\n batchDepth--;\n if (batchDepth === 0) {\n const effects = pendingEffects;\n pendingEffects = new Set();\n effects.forEach(fn => fn());\n }\n }\n}\n\nfunction effect(fn: () => void, ctx?: RenderContext): () => void {\n let isActive = true;\n\n const execute = () => {\n if (!isActive) return;\n currentEffect = execute;\n try {\n fn();\n } finally {\n currentEffect = null;\n }\n };\n\n execute();\n\n const cleanup = () => {\n isActive = false;\n currentEffect = null;\n };\n\n if (ctx) {\n ctx.cleanups.push(cleanup);\n }\n\n return cleanup;\n}\n\n// computed signal - derives value from other signals and auto-updates\ninterface ComputedSignal<T> {\n (): T;\n sub(fn: () => void): () => void;\n}\n\nfunction computed<T>(fn: () => T): ComputedSignal<T> {\n let cachedValue: T;\n let isDirty = true;\n const subscribers = new Set<() => void>();\n\n // re-compute and notify subscribers when dependencies change\n const recompute = () => {\n isDirty = true;\n // notify all subscribers that the value may have changed\n if (batchDepth > 0) {\n subscribers.forEach(sub => pendingEffects.add(sub));\n } else {\n subscribers.forEach(sub => sub());\n }\n };\n\n const sig = (() => {\n // track this computed as a dependency if inside an effect\n if (currentEffect) {\n subscribers.add(currentEffect);\n }\n\n // recompute if dirty\n if (isDirty) {\n // track dependencies by running the computation inside an effect context\n const prevEffect = currentEffect;\n currentEffect = recompute;\n try {\n cachedValue = fn();\n } finally {\n currentEffect = prevEffect;\n }\n isDirty = false;\n }\n\n return cachedValue;\n }) as ComputedSignal<T>;\n\n sig.sub = (subFn: () => void) => {\n subscribers.add(subFn);\n return () => subscribers.delete(subFn);\n };\n\n return sig;\n}\n\n// async$ helper - handle async data with loading states\ninterface AsyncState<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n [key: string]: unknown; // index signature for TooeySpec.s compatibility\n}\n\ninterface AsyncSpec<T> {\n s: AsyncState<T>;\n init(instance: TooeyInstance): Promise<void>;\n}\n\nfunction async$<T>(\n promiseOrFn: Promise<T> | (() => Promise<T>),\n options?: { onError?: (error: Error) => void }\n): AsyncSpec<T> {\n return {\n s: {\n data: null,\n loading: true,\n error: null\n },\n async init(instance: TooeyInstance) {\n try {\n const promise = typeof promiseOrFn === 'function' ? promiseOrFn() : promiseOrFn;\n const data = await promise;\n instance.set('data', data);\n instance.set('loading', false);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n instance.set('error', errorMessage);\n instance.set('loading', false);\n if (options?.onError && err instanceof Error) {\n options.onError(err);\n }\n }\n }\n };\n}\n\n// ============ state operations ============\n\nfunction applyOp(state: Signal<StateValue>, op: Op, val?: unknown): void {\n try {\n switch (op) {\n case '+':\n state.set((v: StateValue) => (v as number) + (typeof val === 'number' ? val : 1));\n break;\n case '-':\n state.set((v: StateValue) => (v as number) - (typeof val === 'number' ? val : 1));\n break;\n case '!':\n state.set(val);\n break;\n case '~':\n state.set((v: StateValue) => !v);\n break;\n case '<':\n state.set((v: StateValue) => [...(v as unknown[]), val]);\n break;\n case '>':\n state.set((v: StateValue) => [val, ...(v as unknown[])]);\n break;\n case 'X':\n state.set((v: StateValue) => {\n const arr = v as unknown[];\n if (typeof val === 'number') {\n return arr.filter((_, i) => i !== val);\n } else if (typeof val === 'function') {\n return arr.filter((item, i) => !(val as (item: unknown, i: number) => boolean)(item, i));\n }\n return arr.filter(item => item !== val);\n });\n break;\n case '.':\n if (Array.isArray(val) && val.length === 2) {\n state.set((v: StateValue) => ({ ...(v as Record<string, unknown>), [val[0]]: val[1] }));\n }\n break;\n }\n } catch (err) {\n console.warn('[tooey] state operation error:', op, err);\n }\n}\n\n// ============ helpers ============\n\nfunction isStateRef(v: unknown): v is StateRef {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && '$' in v;\n}\n\nfunction isIfNode(v: unknown): v is IfNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('if' in v || '?' in v);\n}\n\nfunction isMapNode(v: unknown): v is MapNode {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && ('map' in v || 'm' in v);\n}\n\nfunction resolveValue(content: unknown, state: StateStore): unknown {\n if (isStateRef(content)) {\n const sig = state[content.$];\n if (!sig) {\n console.warn(`[tooey] unknown state key: \"${content.$}\"`);\n return undefined;\n }\n return sig();\n }\n return content;\n}\n\nfunction resolveCssValue(val: number | string | undefined): string | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'number') return `${val}px`;\n return val;\n}\n\nfunction resolveThemeValue(token: string, theme: Theme | undefined): ThemeValue | undefined {\n if (!theme) return undefined;\n\n // try direct category lookup: $primary -> colors.primary, $md -> spacing.md, etc.\n // check in order of most common usage\n const categories: (keyof Theme)[] = ['colors', 'spacing', 'radius', 'fonts'];\n\n for (const category of categories) {\n const cat = theme[category];\n if (cat && token in cat) {\n return cat[token];\n }\n }\n\n // check any custom categories\n for (const [key, cat] of Object.entries(theme)) {\n if (cat && !categories.includes(key as keyof Theme) && token in cat) {\n return cat[token];\n }\n }\n\n return undefined;\n}\n\n// style value shortcuts for common layout values\nconst styleShortcuts: Record<string, string> = {\n 'c': 'center',\n 'sb': 'space-between',\n 'sa': 'space-around',\n 'se': 'space-evenly',\n 'fe': 'flex-end',\n 'fs': 'flex-start',\n 'st': 'stretch',\n 'bl': 'baseline',\n};\n\nfunction expandStyleValue(val: string | undefined): string | undefined {\n if (val === undefined) return undefined;\n return styleShortcuts[val] || val;\n}\n\n// parse string-based event handler shorthand\n// format: \"stateName+\" | \"stateName-\" | \"stateName~\" | \"stateName!value\"\nfunction parseEventShorthand(str: string): [string, Op, unknown?] | null {\n if (typeof str !== 'string' || str.length < 2) return null;\n\n const lastChar = str[str.length - 1];\n\n // simple ops: +, -, ~\n if (lastChar === '+' || lastChar === '-' || lastChar === '~') {\n return [str.slice(0, -1), lastChar as Op];\n }\n\n // set operation with value: \"state!value\"\n const bangIdx = str.indexOf('!');\n if (bangIdx > 0) {\n const stateKey = str.slice(0, bangIdx);\n const valStr = str.slice(bangIdx + 1);\n // try to parse as number or boolean\n let val: unknown = valStr;\n if (valStr === 'true') val = true;\n else if (valStr === 'false') val = false;\n else if (!isNaN(Number(valStr)) && valStr !== '') val = Number(valStr);\n return [stateKey, '!', val];\n }\n\n return null;\n}\n\n// xss protection - escape html entities (kept for future use, textContent provides protection now)\nfunction _escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n\n// url validation - prevent dangerous protocols\nconst SAFE_URL_PROTOCOLS = ['http:', 'https:', 'mailto:', 'tel:', 'ftp:'];\n\nfunction isValidUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n\n // allow relative urls and anchors\n if (url.startsWith('/') || url.startsWith('#') || url.startsWith('.')) {\n return true;\n }\n\n try {\n const parsed = new URL(url, window.location.href);\n return SAFE_URL_PROTOCOLS.includes(parsed.protocol);\n } catch {\n // if url parsing fails, check for dangerous patterns directly\n const lowerUrl = url.toLowerCase().trim();\n const dangerousPatterns = ['javascript:', 'data:', 'vbscript:'];\n return !dangerousPatterns.some(pattern => lowerUrl.startsWith(pattern));\n }\n}\n\nfunction sanitizeUrl(url: string, propName: string): string | null {\n if (!url) return null;\n\n if (!isValidUrl(url)) {\n console.warn(`[tooey] blocked unsafe URL in ${propName}: \"${url.slice(0, 50)}...\"`);\n return null;\n }\n\n return url;\n}\n\nfunction createHandler(\n handler: EventHandler,\n state: StateStore,\n event?: Event,\n itemContext?: { item: unknown, index: number },\n buttonText?: string\n): () => void {\n if (typeof handler === 'function') {\n return handler;\n }\n\n // handle string shorthand: \"state+\", \"state-\", \"state~\", \"state!value\"\n let normalizedHandler: [string, Op, unknown?];\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n normalizedHandler = parsed;\n } else {\n // plain state key - infer operation from button text if available\n if (buttonText === '+') {\n normalizedHandler = [handler, '+'];\n } else if (buttonText === '-') {\n normalizedHandler = [handler, '-'];\n } else {\n // default to toggle for plain state key\n normalizedHandler = [handler, '~'];\n }\n }\n } else {\n normalizedHandler = handler;\n }\n\n const [stateKey, op, val] = normalizedHandler;\n return () => {\n const sig = state[stateKey];\n if (!sig) {\n console.warn(`[tooey] click handler: unknown state key \"${stateKey}\"`);\n return;\n }\n let actualVal = val;\n // resolve $item and $index in event handler values\n if (itemContext && typeof actualVal === 'string') {\n if (actualVal === '$index') {\n actualVal = itemContext.index;\n } else if (actualVal === '$item') {\n actualVal = itemContext.item;\n } else if (actualVal.startsWith('$item.')) {\n const key = actualVal.substring(6);\n actualVal = (itemContext.item as Record<string, unknown>)?.[key];\n }\n }\n if (op === '!' && val === undefined && event) {\n const target = event.target as HTMLInputElement;\n actualVal = target.type === 'checkbox' ? target.checked : target.value;\n }\n applyOp(sig, op, actualVal);\n };\n}\n\n// ============ styles ============\n\nfunction resolveStyleValue(val: string | number | undefined, theme: Theme | undefined): string | number | undefined {\n if (val === undefined) return undefined;\n if (typeof val === 'string' && val.startsWith('$')) {\n const token = val.slice(1);\n const themeVal = resolveThemeValue(token, theme);\n if (themeVal !== undefined) return themeVal;\n console.warn(`[tooey] unknown theme token: \"${val}\"`);\n return undefined;\n }\n return val;\n}\n\nfunction applyStyles(el: HTMLElement, props: Props, theme?: Theme): void {\n const style = el.style;\n\n // helper to resolve and apply css value with theme token support\n const resolve = (val: string | number | undefined): string | undefined => {\n const resolved = resolveStyleValue(val, theme);\n return resolveCssValue(resolved as string | number | undefined);\n };\n\n // helper for string values that support theme tokens\n const resolveStr = (val: string | undefined): string | undefined => {\n if (val === undefined) return undefined;\n const resolved = resolveStyleValue(val, theme);\n return resolved !== undefined ? String(resolved) : undefined;\n };\n\n if (props.g !== undefined) { const v = resolve(props.g); if (v) style.gap = v; }\n if (props.p !== undefined) { const v = resolve(props.p); if (v) style.padding = v; }\n if (props.m !== undefined) { const v = resolve(props.m); if (v) style.margin = v; }\n if (props.w !== undefined) { const v = resolve(props.w); if (v) style.width = v; }\n if (props.h !== undefined) { const v = resolve(props.h); if (v) style.height = v; }\n if (props.mw !== undefined) { const v = resolve(props.mw); if (v) style.maxWidth = v; }\n if (props.mh !== undefined) { const v = resolve(props.mh); if (v) style.maxHeight = v; }\n\n if (props.bg !== undefined) { const v = resolveStr(props.bg); if (v) style.background = v; }\n if (props.fg !== undefined) { const v = resolveStr(props.fg); if (v) style.color = v; }\n if (props.o !== undefined) style.opacity = String(props.o);\n\n if (props.r !== undefined) { const v = resolve(props.r); if (v) style.borderRadius = v; }\n if (props.bw !== undefined) { const v = resolve(props.bw); if (v) style.borderWidth = v; }\n if (props.bc !== undefined) { const v = resolveStr(props.bc); if (v) style.borderColor = v; }\n if (props.bs !== undefined) style.borderStyle = props.bs;\n\n if (props.pos !== undefined) {\n const posMap: Record<string, string> = {\n rel: 'relative', abs: 'absolute', fix: 'fixed', sticky: 'sticky'\n };\n style.position = posMap[props.pos] || props.pos;\n }\n if (props.z !== undefined) style.zIndex = String(props.z);\n if (props.t !== undefined) { const v = resolve(props.t); if (v) style.top = v; }\n if (props.l !== undefined) { const v = resolve(props.l); if (v) style.left = v; }\n if (typeof props.b === 'number' || (typeof props.b === 'string' && !Array.isArray(props.b))) {\n const v = resolve(props.b as number | string);\n if (v) style.bottom = v;\n }\n if (props.rt !== undefined) { const v = resolve(props.rt); if (v) style.right = v; }\n\n if (props.fs !== undefined) { const v = resolve(props.fs); if (v) style.fontSize = v; }\n if (props.fw !== undefined) style.fontWeight = String(props.fw);\n if (props.ff !== undefined) { const v = resolveStr(props.ff); if (v) style.fontFamily = v; }\n if (props.ta !== undefined) style.textAlign = props.ta;\n if (props.td !== undefined) style.textDecoration = props.td;\n if (props.lh !== undefined) style.lineHeight = typeof props.lh === 'number' ? String(props.lh) : props.lh;\n if (props.ls !== undefined) { const v = resolve(props.ls); if (v) style.letterSpacing = v; }\n\n if (props.ai !== undefined) style.alignItems = expandStyleValue(props.ai)!;\n if (props.jc !== undefined) style.justifyContent = expandStyleValue(props.jc)!;\n if (props.flw !== undefined) style.flexWrap = expandStyleValue(props.flw)!\n\n if (props.cur !== undefined) style.cursor = props.cur;\n if (props.ov !== undefined) style.overflow = props.ov;\n if (props.pe !== undefined) style.pointerEvents = props.pe;\n if (props.us !== undefined) style.userSelect = props.us;\n if (props.sh !== undefined) { const v = resolveStr(props.sh); if (v) style.boxShadow = v; }\n if (props.tr !== undefined) style.transform = props.tr;\n\n if (props.s) {\n Object.entries(props.s).forEach(([key, val]) => {\n const resolved = resolveStyleValue(val as string | number | undefined, theme);\n if (resolved !== undefined) {\n (style as unknown as Record<string, string>)[key] = String(resolved);\n }\n });\n }\n}\n\n// ============ renderer ============\n\nfunction createElement(\n spec: NodeSpec,\n ctx: RenderContext,\n itemContext?: { item: unknown, index: number }\n): HTMLElement | null {\n const { state } = ctx;\n\n // handle error boundary node\n if (isErrorBoundaryNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n try {\n const childCtx: RenderContext = {\n cleanups: [],\n state,\n onError: spec.onError || ctx.onError,\n };\n const child = createElement(spec.child, childCtx, itemContext);\n if (child) {\n placeholder.appendChild(child);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n } catch (err) {\n const errorInfo: ErrorInfo = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n\n if (spec.onError) {\n spec.onError(errorInfo);\n }\n\n if (spec.fallback) {\n try {\n const fallbackEl = createElement(spec.fallback, ctx, itemContext);\n if (fallbackEl) placeholder.appendChild(fallbackEl);\n } catch {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n } else {\n placeholder.appendChild(createErrorFallback(errorInfo));\n }\n }\n\n return placeholder;\n }\n\n // handle reactive if node (supports both long and short form)\n if (isIfNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n // normalize short form to long form\n const ifCond = spec.if ?? spec['?'];\n const thenBranch = spec.then ?? spec.t;\n const elseBranch = spec.else ?? spec.e;\n const eqValue = spec.eq ?? spec.is;\n\n const updateIf = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const rawValue = typeof ifCond === 'string'\n ? state[ifCond]?.()\n : resolveValue(ifCond, state);\n\n // handle equality check (eq or is)\n let condition: boolean;\n if (eqValue !== undefined) {\n condition = rawValue === eqValue;\n } else {\n condition = Boolean(rawValue);\n }\n\n const branch = condition ? thenBranch : elseBranch;\n if (!branch) return;\n\n childCtx = { cleanups: [], state };\n\n if (Array.isArray(branch) && branch.length > 0 && Array.isArray(branch[0])) {\n (branch as NodeSpec[]).forEach(child => {\n const el = createElement(child, childCtx!, itemContext);\n if (el) placeholder.appendChild(el);\n });\n } else {\n currentEl = createElement(branch as NodeSpec, childCtx, itemContext);\n if (currentEl) placeholder.appendChild(currentEl);\n }\n };\n\n effect(updateIf, ctx);\n return placeholder;\n }\n\n // handle reactive map node (supports both long and short form)\n if (isMapNode(spec)) {\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let childCtx: RenderContext | null = null;\n\n // normalize short form to long form\n const mapSource = spec.map ?? spec.m;\n const asTemplate = spec.as ?? spec.a;\n\n const updateMap = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n placeholder.innerHTML = '';\n\n const arr = (typeof mapSource === 'string'\n ? state[mapSource]?.()\n : resolveValue(mapSource, state)) as unknown[];\n\n if (!Array.isArray(arr) || !asTemplate) return;\n\n childCtx = { cleanups: [], state };\n\n arr.forEach((item, index) => {\n const el = createElement(asTemplate, childCtx!, { item, index });\n if (el) placeholder.appendChild(el);\n });\n };\n\n effect(updateMap, ctx);\n return placeholder;\n }\n\n // validate spec structure\n if (!Array.isArray(spec) || (spec as unknown[]).length === 0) {\n console.warn('[tooey] invalid node spec:', spec);\n return null;\n }\n\n // apply beforeRender hooks from plugins\n let processedSpec: NodeSpec = spec;\n if (ctx.plugins) {\n for (const plugin of ctx.plugins) {\n if (plugin.beforeRender) {\n processedSpec = plugin.beforeRender(processedSpec, ctx);\n }\n }\n }\n\n // if beforeRender transformed spec to a non-array type, recurse\n if (!Array.isArray(processedSpec)) {\n return createElement(processedSpec, ctx, itemContext);\n }\n\n // handle function components\n const [first, content, props = {}] = processedSpec as [ComponentType | Component, Content?, Props?];\n if (typeof first === 'function') {\n // function component: call it with (props, children)\n const children = Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]) || typeof content[0] === 'function')\n ? content as NodeSpec[]\n : undefined;\n const resolved = (first as Component)(props, children);\n return createElement(resolved, ctx, itemContext);\n }\n\n const type = first as ComponentType;\n\n // handle show prop - conditional rendering based on state\n if (props.show !== undefined) {\n const showKey = props.show;\n const placeholder = document.createElement('div');\n placeholder.style.display = 'contents';\n\n let currentEl: HTMLElement | null = null;\n let childCtx: RenderContext | null = null;\n\n const updateShow = () => {\n // cleanup previous render\n if (childCtx) {\n childCtx.cleanups.forEach(fn => fn());\n childCtx.cleanups = [];\n }\n if (currentEl) {\n placeholder.innerHTML = '';\n currentEl = null;\n }\n\n const showValue = state[showKey]?.();\n if (!showValue) return;\n\n // create the element without the show prop to avoid infinite recursion\n const { show: _, ...propsWithoutShow } = props;\n childCtx = { cleanups: [], state, theme: ctx.theme, plugins: ctx.plugins };\n currentEl = createElement([type, content, propsWithoutShow as Props], childCtx, itemContext);\n if (currentEl) {\n placeholder.appendChild(currentEl);\n ctx.cleanups.push(...childCtx.cleanups);\n }\n };\n\n effect(updateShow, ctx);\n return placeholder;\n }\n\n let el: HTMLElement;\n\n switch (type) {\n case 'V':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'column';\n break;\n case 'H':\n el = document.createElement('div');\n el.style.display = 'flex';\n el.style.flexDirection = 'row';\n break;\n case 'G':\n el = document.createElement('div');\n el.style.display = 'grid';\n if (props.cols) {\n el.style.gridTemplateColumns = typeof props.cols === 'number'\n ? `repeat(${props.cols}, 1fr)` : props.cols;\n }\n if (props.rows) {\n el.style.gridTemplateRows = typeof props.rows === 'number'\n ? `repeat(${props.rows}, 1fr)` : props.rows;\n }\n break;\n case 'D':\n el = document.createElement('div');\n break;\n case 'T':\n el = document.createElement('span');\n break;\n case 'B':\n el = document.createElement('button');\n break;\n case 'I':\n el = document.createElement('input');\n (el as HTMLInputElement).type = props.type || 'text';\n if (props.ph) (el as HTMLInputElement).placeholder = props.ph;\n if (props.ro) (el as HTMLInputElement).readOnly = true;\n break;\n case 'Ta':\n el = document.createElement('textarea');\n if (props.ph) (el as HTMLTextAreaElement).placeholder = props.ph;\n if (props.rw) (el as HTMLTextAreaElement).rows = props.rw;\n if (props.ro) (el as HTMLTextAreaElement).readOnly = true;\n break;\n case 'S':\n el = document.createElement('select');\n if (props.opts) {\n props.opts.forEach(opt => {\n const option = document.createElement('option');\n option.value = opt.v;\n option.textContent = opt.l;\n el.appendChild(option);\n });\n }\n break;\n case 'C':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'checkbox';\n break;\n case 'R':\n el = document.createElement('input');\n (el as HTMLInputElement).type = 'radio';\n break;\n case 'Tb':\n el = document.createElement('table');\n break;\n case 'Th':\n el = document.createElement('thead');\n break;\n case 'Tbd':\n el = document.createElement('tbody');\n break;\n case 'Tr':\n el = document.createElement('tr');\n break;\n case 'Td':\n el = document.createElement('td');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Tc':\n el = document.createElement('th');\n if (props.sp) (el as HTMLTableCellElement).colSpan = props.sp;\n if (props.rsp) (el as HTMLTableCellElement).rowSpan = props.rsp;\n break;\n case 'Ul':\n el = document.createElement('ul');\n break;\n case 'Ol':\n el = document.createElement('ol');\n break;\n case 'Li':\n el = document.createElement('li');\n break;\n case 'M':\n el = document.createElement('img');\n if (props.src) {\n const safeSrc = sanitizeUrl(props.src, 'src');\n if (safeSrc) (el as HTMLImageElement).src = safeSrc;\n }\n if (props.alt) (el as HTMLImageElement).alt = props.alt;\n break;\n case 'L':\n el = document.createElement('a');\n if (props.href) {\n const safeHref = sanitizeUrl(props.href, 'href');\n if (safeHref) (el as HTMLAnchorElement).href = safeHref;\n }\n break;\n case 'Sv':\n el = document.createElementNS('http://www.w3.org/2000/svg', 'svg') as unknown as HTMLElement;\n break;\n default:\n console.warn(`[tooey] unknown component type: ${type}`);\n el = document.createElement('div');\n }\n\n if (props.cls) el.className = props.cls;\n if (props.id) el.id = props.id;\n if (props.dis) (el as HTMLButtonElement).disabled = true;\n\n applyStyles(el, props, ctx.theme);\n\n // handle content\n if (content !== undefined) {\n if (Array.isArray(content) && content.length > 0 && (Array.isArray(content[0]) || isIfNode(content[0]) || isMapNode(content[0]) || isErrorBoundaryNode(content[0]))) {\n (content as NodeSpec[]).forEach(childSpec => {\n const child = createElement(childSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n });\n } else if (isIfNode(content) || isMapNode(content) || isErrorBoundaryNode(content)) {\n const child = createElement(content as NodeSpec, ctx, itemContext);\n if (child) el.appendChild(child);\n } else if (isStateRef(content)) {\n effect(() => {\n const val = resolveValue(content, state);\n if (type === 'I') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n } else {\n // textContent provides XSS protection by not parsing HTML\n el.textContent = String(val ?? '');\n }\n }, ctx);\n } else if (typeof content === 'string' || typeof content === 'number') {\n let textContent = String(content);\n if (itemContext) {\n // handle object property access first (before $item replacement)\n if (typeof itemContext.item === 'object' && itemContext.item !== null) {\n textContent = textContent.replace(/\\$item\\.(\\w+)/g, (_, key) => {\n return String((itemContext.item as Record<string, unknown>)[key] ?? '');\n });\n }\n textContent = textContent.replace(/\\$item/g, String(itemContext.item));\n textContent = textContent.replace(/\\$index/g, String(itemContext.index));\n }\n // xss protection for static content\n if (type === 'I') {\n (el as HTMLInputElement).value = textContent;\n } else if (type === 'Ta') {\n (el as HTMLTextAreaElement).value = textContent;\n } else if (type !== 'S') {\n // don't set textContent for select (would clear options)\n el.textContent = textContent;\n }\n }\n }\n\n // handle value binding for inputs\n if (props.v !== undefined && isStateRef(props.v)) {\n effect(() => {\n const val = resolveValue(props.v!, state);\n if (type === 'I' || type === 'S' || type === 'Ta') {\n (el as HTMLInputElement).value = String(val ?? '');\n } else if (type === 'C' || type === 'R') {\n (el as HTMLInputElement).checked = Boolean(val);\n }\n }, ctx);\n }\n\n // handle checked binding\n if (props.ch !== undefined) {\n if (isStateRef(props.ch as unknown)) {\n effect(() => {\n const val = resolveValue(props.ch as unknown as StateRef, state);\n (el as HTMLInputElement).checked = Boolean(val);\n }, ctx);\n } else {\n (el as HTMLInputElement).checked = Boolean(props.ch);\n }\n }\n\n // event handlers with cleanup tracking\n const addEventListener = (event: string, handler: (e: Event) => void) => {\n el.addEventListener(event, handler);\n ctx.cleanups.push(() => el.removeEventListener(event, handler));\n };\n\n // get button text for implicit operation inference\n const buttonText = type === 'B' && (typeof content === 'string' || typeof content === 'number')\n ? String(content)\n : undefined;\n\n if (props.c) {\n addEventListener('click', (e) => createHandler(props.c!, state, e, itemContext, buttonText)());\n }\n if (props.x) {\n const handler = props.x;\n addEventListener('input', (e) => {\n if (typeof handler === 'function') {\n handler();\n } else {\n // normalize string shorthand to array form\n let stateKey: string;\n let op: Op;\n if (typeof handler === 'string') {\n const parsed = parseEventShorthand(handler);\n if (parsed) {\n [stateKey, op] = parsed;\n } else {\n // plain state key defaults to set (!) for input\n stateKey = handler;\n op = '!';\n }\n } else {\n [stateKey, op] = handler;\n }\n const sig = state[stateKey];\n if (sig) {\n const target = e.target as HTMLInputElement;\n const val = (type === 'C' || type === 'R') ? target.checked : target.value;\n applyOp(sig, op, val);\n }\n }\n });\n }\n if (props.f) {\n addEventListener('focus', (e) => createHandler(props.f!, state, e, itemContext)());\n }\n if (props.bl) {\n addEventListener('blur', (e) => createHandler(props.bl!, state, e, itemContext)());\n }\n if (props.k) {\n addEventListener('keydown', (e) => createHandler(props.k!, state, e, itemContext)());\n }\n if (props.ku) {\n addEventListener('keyup', (e) => createHandler(props.ku!, state, e, itemContext)());\n }\n if (props.kp) {\n addEventListener('keypress', (e) => createHandler(props.kp!, state, e, itemContext)());\n }\n if (props.e) {\n addEventListener('mouseenter', (e) => createHandler(props.e!, state, e, itemContext)());\n }\n if (props.lv) {\n addEventListener('mouseleave', (e) => createHandler(props.lv!, state, e, itemContext)());\n }\n if (props.sub) {\n addEventListener('submit', (e) => {\n e.preventDefault();\n createHandler(props.sub!, state, e, itemContext)();\n });\n }\n\n // apply afterRender hooks from plugins\n if (ctx.plugins) {\n for (const plugin of ctx.plugins) {\n if (plugin.afterRender) {\n plugin.afterRender(el, processedSpec);\n }\n }\n }\n\n return el;\n}\n\n// ============ main api ============\n\ninterface TooeyInstance {\n state: StateStore;\n el: HTMLElement | null;\n destroy(): void;\n update(newSpec: TooeySpec): void;\n get(key: string): unknown;\n set(key: string, value: unknown): void;\n // allow dynamic extension by plugins\n [key: string]: unknown;\n}\n\nfunction render(container: HTMLElement, spec: TooeySpec, options?: RenderOptions): TooeyInstance {\n if (!container) {\n throw new Error('[tooey] render requires a valid container element');\n }\n if (!spec || !spec.r) {\n throw new Error('[tooey] render requires a spec with a root node (r)');\n }\n\n const theme = options?.theme;\n const plugins = options?.plugins || [];\n\n // helper to create signals with plugin state change notification\n const createStateSignal = (key: string, initial: StateValue): Signal<StateValue> => {\n const sig = signal(initial);\n const originalSet = sig.set.bind(sig);\n sig.set = (v: StateValue | ((prev: StateValue) => StateValue)) => {\n const oldVal = sig();\n originalSet(v);\n const newVal = sig();\n if (oldVal !== newVal) {\n plugins.forEach(p => p.onStateChange?.(key, oldVal, newVal));\n }\n };\n return sig;\n };\n\n const state: StateStore = {};\n if (spec.s) {\n Object.entries(spec.s).forEach(([key, val]) => {\n state[key] = createStateSignal(key, val);\n });\n }\n\n const ctx: RenderContext = { cleanups: [], state, theme, plugins };\n\n container.innerHTML = '';\n const el = createElement(spec.r, ctx);\n if (el) container.appendChild(el);\n\n const instance: TooeyInstance = {\n state,\n el,\n destroy() {\n // call onDestroy hooks\n plugins.forEach(p => p.onDestroy?.(instance));\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n },\n update(newSpec: TooeySpec) {\n if (newSpec.s) {\n batch(() => {\n Object.entries(newSpec.s!).forEach(([key, val]) => {\n if (state[key]) {\n state[key].set(val);\n } else {\n state[key] = createStateSignal(key, val);\n }\n });\n });\n }\n if (newSpec.r) {\n ctx.cleanups.forEach(fn => fn());\n ctx.cleanups = [];\n container.innerHTML = '';\n const newEl = createElement(newSpec.r, ctx);\n if (newEl) container.appendChild(newEl);\n instance.el = newEl;\n }\n },\n get(key: string) {\n return state[key]?.();\n },\n set(key: string, value: unknown) {\n if (state[key]) {\n state[key].set(value);\n }\n }\n };\n\n // apply plugin extend methods\n plugins.forEach(plugin => {\n if (plugin.extend) {\n Object.entries(plugin.extend).forEach(([name, fn]) => {\n instance[name] = fn.bind(instance);\n });\n }\n });\n\n // call onInit hooks\n plugins.forEach(p => p.onInit?.(instance));\n\n return instance;\n}\n\n// ============ factory function ============\n\ninterface CreateTooeyOptions {\n theme?: Theme;\n plugins?: TooeyPlugin[];\n}\n\ninterface TooeyFactory {\n render: (container: HTMLElement, spec: TooeySpec) => TooeyInstance;\n theme: Theme;\n plugins?: TooeyPlugin[];\n}\n\n// createTooey supports both a Theme directly (backward compatible) or CreateTooeyOptions\nfunction createTooey(themeOrOptions: Theme | CreateTooeyOptions): TooeyFactory {\n // detect if it's a theme (has colors/spacing/radius/fonts) or options (has theme/plugins keys)\n const isOptions = themeOrOptions && ('theme' in themeOrOptions || 'plugins' in themeOrOptions);\n const theme = isOptions ? (themeOrOptions as CreateTooeyOptions).theme : (themeOrOptions as Theme);\n const plugins = isOptions ? (themeOrOptions as CreateTooeyOptions).plugins : undefined;\n return {\n render: (container: HTMLElement, spec: TooeySpec) => render(container, spec, { theme, plugins }),\n theme: theme!,\n plugins\n };\n}\n\n// ============ convenience helpers ============\n\nfunction $(name: string): StateRef {\n return { $: name };\n}\n\n// component type constants\nconst V = 'V' as const;\nconst H = 'H' as const;\nconst D = 'D' as const;\nconst G = 'G' as const;\nconst T = 'T' as const;\nconst B = 'B' as const;\nconst I = 'I' as const;\nconst Ta = 'Ta' as const;\nconst S = 'S' as const;\nconst C = 'C' as const;\nconst R = 'R' as const;\nconst Tb = 'Tb' as const;\nconst Th = 'Th' as const;\nconst Tbd = 'Tbd' as const;\nconst Tr = 'Tr' as const;\nconst Td = 'Td' as const;\nconst Tc = 'Tc' as const;\nconst Ul = 'Ul' as const;\nconst Ol = 'Ol' as const;\nconst Li = 'Li' as const;\nconst M = 'M' as const;\nconst L = 'L' as const;\nconst Sv = 'Sv' as const;\n\nexport {\n render,\n createTooey,\n signal,\n effect,\n batch,\n computed,\n async$,\n $,\n V, H, D, G,\n T, B,\n I, Ta, S, C, R,\n Tb, Th, Tbd, Tr, Td, Tc,\n Ul, Ol, Li,\n M, L, Sv,\n TooeySpec,\n NodeSpec,\n Props,\n StateRef,\n TooeyInstance,\n TooeyFactory,\n CreateTooeyOptions,\n IfNode,\n MapNode,\n ErrorBoundaryNode,\n ErrorInfo,\n ErrorHandler,\n Component,\n Theme,\n RenderOptions,\n TooeyPlugin,\n ComputedSignal,\n AsyncSpec\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["tooey_exports", "__export", "$", "B", "C", "D", "G", "H", "I", "L", "Li", "M", "Ol", "R", "S", "Sv", "T", "Ta", "Tb", "Tbd", "Tc", "Td", "Th", "Tr", "Ul", "V", "async$", "batch", "computed", "createTooey", "effect", "render", "signal", "isErrorBoundaryNode", "v", "createErrorFallback", "error", "el", "currentEffect", "batchDepth", "pendingEffects", "initial", "value", "subscribers", "sig", "newValue", "fn", "effects", "ctx", "isActive", "execute", "cleanup", "cachedValue", "isDirty", "recompute", "sub", "prevEffect", "subFn", "promiseOrFn", "options", "instance", "data", "err", "errorMessage", "applyOp", "state", "op", "val", "arr", "_", "i", "item", "isStateRef", "isIfNode", "isMapNode", "resolveValue", "content", "resolveCssValue", "resolveThemeValue", "token", "theme", "categories", "category", "cat", "key", "styleShortcuts", "expandStyleValue", "parseEventShorthand", "str", "lastChar", "bangIdx", "stateKey", "valStr", "SAFE_URL_PROTOCOLS", "isValidUrl", "url", "parsed", "lowerUrl", "pattern", "sanitizeUrl", "propName", "createHandler", "handler", "state", "event", "itemContext", "buttonText", "normalizedHandler", "parseEventShorthand", "stateKey", "op", "val", "sig", "actualVal", "key", "target", "applyOp", "resolveStyleValue", "theme", "token", "themeVal", "resolveThemeValue", "applyStyles", "el", "props", "style", "resolve", "resolved", "resolveCssValue", "resolveStr", "v", "posMap", "expandStyleValue", "createElement", "spec", "ctx", "isErrorBoundaryNode", "placeholder", "childCtx", "child", "err", "errorInfo", "fallbackEl", "createErrorFallback", "isIfNode", "currentEl", "ifCond", "thenBranch", "elseBranch", "eqValue", "effect", "fn", "rawValue", "resolveValue", "condition", "branch", "isMapNode", "mapSource", "asTemplate", "arr", "item", "index", "processedSpec", "plugin", "first", "content", "children", "type", "showKey", "_", "propsWithoutShow", "opt", "option", "safeSrc", "safeHref", "childSpec", "isStateRef", "textContent", "addEventListener", "e", "render", "container", "options", "plugins", "createStateSignal", "initial", "signal", "originalSet", "oldVal", "newVal", "p", "instance", "newSpec", "batch", "newEl", "value", "name", "createTooey", "themeOrOptions", "isOptions", "$", "V", "H", "D", "G", "T", "B", "I", "Ta", "S", "C", "R", "Tb", "Th", "Tbd", "Tr", "Td", "Tc", "Ul", "Ol", "Li", "M", "L", "Sv"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tooey/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Token-efficient UI library for LLMs",
|
|
5
5
|
"main": "dist/tooey.js",
|
|
6
6
|
"module": "dist/tooey.esm.js",
|
|
@@ -21,14 +21,16 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "node build.js",
|
|
23
23
|
"dev": "node build.js --watch",
|
|
24
|
-
"serve": "npx serve .",
|
|
25
24
|
"test": "vitest run",
|
|
26
25
|
"test:watch": "vitest",
|
|
27
26
|
"test:coverage": "vitest run --coverage",
|
|
28
27
|
"lint": "eslint src tests",
|
|
29
28
|
"lint:fix": "eslint src tests --fix",
|
|
30
29
|
"typecheck": "tsc --noEmit",
|
|
31
|
-
"
|
|
30
|
+
"benchmark": "node benchmarks/run-benchmark.js",
|
|
31
|
+
"benchmark:test": "vitest run benchmarks/benchmark.test.ts",
|
|
32
|
+
"validate": "npx ts-node --esm benchmarks/validation/run-validation.ts",
|
|
33
|
+
"validate:report": "npx ts-node --esm benchmarks/validation/run-validation.ts && cat benchmarks/validation/VALIDATION_RESULTS.md"
|
|
32
34
|
},
|
|
33
35
|
"keywords": [
|
|
34
36
|
"ui",
|
|
@@ -42,12 +44,13 @@
|
|
|
42
44
|
"license": "MIT",
|
|
43
45
|
"repository": {
|
|
44
46
|
"type": "git",
|
|
45
|
-
"url": "git+https://github.com/vijaypemmaraju/tooey.git"
|
|
47
|
+
"url": "git+https://github.com/vijaypemmaraju/tooey.git",
|
|
48
|
+
"directory": "packages/ui"
|
|
46
49
|
},
|
|
47
50
|
"bugs": {
|
|
48
51
|
"url": "https://github.com/vijaypemmaraju/tooey/issues"
|
|
49
52
|
},
|
|
50
|
-
"homepage": "https://github.com/vijaypemmaraju/tooey#readme",
|
|
53
|
+
"homepage": "https://github.com/vijaypemmaraju/tooey/tree/main/packages/ui#readme",
|
|
51
54
|
"publishConfig": {
|
|
52
55
|
"access": "public"
|
|
53
56
|
},
|
|
@@ -59,6 +62,7 @@
|
|
|
59
62
|
"eslint": "^9.0.0",
|
|
60
63
|
"gpt-tokenizer": "^3.4.0",
|
|
61
64
|
"jsdom": "^24.0.0",
|
|
65
|
+
"tsx": "^4.7.0",
|
|
62
66
|
"typescript": "^5.3.0",
|
|
63
67
|
"typescript-eslint": "^8.0.0",
|
|
64
68
|
"vitest": "^3.0.0"
|
package/readme.md
CHANGED
|
@@ -106,6 +106,32 @@ sub submit
|
|
|
106
106
|
{?: "step", is: 0, t: [T, "step 1"]}
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
## function components
|
|
110
|
+
|
|
111
|
+
create reusable components with functions:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import { Component, V, T, H, B } from '@tooey/ui';
|
|
115
|
+
|
|
116
|
+
// simple component
|
|
117
|
+
const Card = (props, children) => [V, children, { bg: '#fff', p: 16, r: 8, ...props }];
|
|
118
|
+
|
|
119
|
+
// component with props
|
|
120
|
+
const Alert = ({ type = 'info', message }) =>
|
|
121
|
+
[V, [[T, message]], { bg: type === 'error' ? '#fee' : '#eef', p: 12 }];
|
|
122
|
+
|
|
123
|
+
// usage
|
|
124
|
+
render(container, {
|
|
125
|
+
s: {},
|
|
126
|
+
r: [V, [
|
|
127
|
+
[Card, [[T, 'Hello']]],
|
|
128
|
+
[Alert, '', { type: 'error', message: 'Error!' }]
|
|
129
|
+
]]
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
components receive `(props, children)` and return a `NodeSpec`.
|
|
134
|
+
|
|
109
135
|
## api
|
|
110
136
|
|
|
111
137
|
```javascript
|
|
@@ -160,6 +186,7 @@ events: c(click) x(input) f(focus) bl(blur) k(keydown) e(mouseenter) lv(mouselea
|
|
|
160
186
|
state ops: "key+"(inc) "key-"(dec) "key~"(toggle) "key!val"(set) or ["key","op",val?] where op=+/-/!/~/</>/X/.
|
|
161
187
|
control: {?:"key",t:[...],e:[...]} {?:"key",is:val,t:[...]} {m:"arr",a:[...]}
|
|
162
188
|
state ref: {$:"key"} | in map: $item $index $item.prop
|
|
189
|
+
function components: const Comp=(props,children)=>[V,children,{...props}] | use: [Comp,content,props]
|
|
163
190
|
example: {s:{n:0},r:[V,[[T,{$:"n"}],[H,[[B,"-",{c:"n"}],[B,"+",{c:"n"}]],{g:8}]],{g:8}]}
|
|
164
191
|
```
|
|
165
192
|
|