rip-lang 3.13.71 → 3.13.73

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/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.71-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.13.73-blue.svg" alt="Version"></a>
13
13
  <a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
14
14
  <a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
package/docs/dist/rip.js CHANGED
@@ -8751,8 +8751,8 @@ globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));
8751
8751
  return new CodeGenerator({}).getComponentRuntime();
8752
8752
  }
8753
8753
  // src/browser.js
8754
- var VERSION = "3.13.70";
8755
- var BUILD_DATE = "2026-03-02@08:04:50GMT";
8754
+ var VERSION = "3.13.72";
8755
+ var BUILD_DATE = "2026-03-02@17:47:10GMT";
8756
8756
  if (typeof globalThis !== "undefined") {
8757
8757
  if (!globalThis.__rip)
8758
8758
  new Function(getReactiveRuntime())();
@@ -8856,6 +8856,29 @@ ${c.js}
8856
8856
  await ui.launch("", opts);
8857
8857
  }
8858
8858
  }
8859
+ if (runtimeTag?.hasAttribute("data-reload")) {
8860
+ let ready = false;
8861
+ const es = new EventSource("/watch");
8862
+ es.addEventListener("connected", () => {
8863
+ if (ready)
8864
+ location.reload();
8865
+ ready = true;
8866
+ });
8867
+ es.addEventListener("reload", (e) => {
8868
+ if (e.data === "styles") {
8869
+ const t = Date.now();
8870
+ document.querySelectorAll('link[rel="stylesheet"]').forEach((l) => {
8871
+ if (new URL(l.href).origin !== location.origin)
8872
+ return;
8873
+ const url = new URL(l.href);
8874
+ url.searchParams.set("_r", t);
8875
+ l.href = url.toString();
8876
+ });
8877
+ } else {
8878
+ location.reload();
8879
+ }
8880
+ });
8881
+ }
8859
8882
  }
8860
8883
  async function importRip(url) {
8861
8884
  for (const [key, mod] of Object.entries(importRip.modules)) {
@@ -718,13 +718,13 @@ globalThis.sleep ??= (ms) => new Promise(r => setTimeout(r, ms));
718
718
  globalThis.todo ??= (msg) => { throw new Error(msg || "Not implemented"); };
719
719
  globalThis.warn ??= console.warn;
720
720
  globalThis.zip ??= (...a) => a[0].map((_, i) => a.map(b => b[i]));
721
- `}function z1(){return new l({}).getReactiveRuntime()}function K1(){return new l({}).getComponentRuntime()}var D2="3.13.70",M2="2026-03-02@08:04:50GMT";if(typeof globalThis<"u"){if(!globalThis.__rip)Function(z1())();if(!globalThis.__ripComponent)Function(K1())()}var x3=($)=>{let U=$.match(/^[ \t]*(?=\S)/gm),F=Math.min(...(U||[]).map((W)=>W.length));return $.replace(RegExp(`^[ ]{${F}}`,"gm"),"").trim()};async function H2(){let $=[],U=document.querySelector('script[src$="rip.min.js"], script[src$="rip.js"]'),F=U?.getAttribute("data-src");if(F){for(let u of F.trim().split(/\s+/))if(u)$.push({url:u})}for(let u of document.querySelectorAll('script[type="text/rip"]'))if(u.src)$.push({url:u.src});else{let f=x3(u.textContent);if(f)$.push({code:f})}if($.length>0){await Promise.all($.map(async(Y)=>{if(!Y.url)return;try{let A=await fetch(Y.url);if(!A.ok){console.error(`Rip: failed to fetch ${Y.url} (${A.status})`);return}Y.code=await A.text()}catch(A){console.error(`Rip: failed to fetch ${Y.url}:`,A.message)}}));let u={skipRuntimes:!0,skipExports:!0},f=[];for(let Y of $){if(!Y.code)continue;try{let A=t(Y.code,u);f.push({js:A,url:Y.url||"inline"})}catch(A){console.error(`Rip compile error in ${Y.url||"inline"}:`,A.message)}}if(f.length>0){let Y=f.map((_)=>_.js).join(`
721
+ `}function z1(){return new l({}).getReactiveRuntime()}function K1(){return new l({}).getComponentRuntime()}var D2="3.13.72",M2="2026-03-02@17:47:10GMT";if(typeof globalThis<"u"){if(!globalThis.__rip)Function(z1())();if(!globalThis.__ripComponent)Function(K1())()}var x3=($)=>{let U=$.match(/^[ \t]*(?=\S)/gm),F=Math.min(...(U||[]).map((W)=>W.length));return $.replace(RegExp(`^[ ]{${F}}`,"gm"),"").trim()};async function H2(){let $=[],U=document.querySelector('script[src$="rip.min.js"], script[src$="rip.js"]'),F=U?.getAttribute("data-src");if(F){for(let u of F.trim().split(/\s+/))if(u)$.push({url:u})}for(let u of document.querySelectorAll('script[type="text/rip"]'))if(u.src)$.push({url:u.src});else{let f=x3(u.textContent);if(f)$.push({code:f})}if($.length>0){await Promise.all($.map(async(Y)=>{if(!Y.url)return;try{let A=await fetch(Y.url);if(!A.ok){console.error(`Rip: failed to fetch ${Y.url} (${A.status})`);return}Y.code=await A.text()}catch(A){console.error(`Rip: failed to fetch ${Y.url}:`,A.message)}}));let u={skipRuntimes:!0,skipExports:!0},f=[];for(let Y of $){if(!Y.code)continue;try{let A=t(Y.code,u);f.push({js:A,url:Y.url||"inline"})}catch(A){console.error(`Rip compile error in ${Y.url||"inline"}:`,A.message)}}if(f.length>0){let Y=f.map((_)=>_.js).join(`
722
722
  `),A=U?.getAttribute("data-mount");if(A){let _=U.getAttribute("data-target")||"body";Y+=`
723
723
  ${A}.mount(${JSON.stringify(_)});`}try{await(0,eval)(`(async()=>{
724
724
  ${Y}
725
725
  })()`)}catch(_){if(_ instanceof SyntaxError){console.error(`Rip syntax error in combined output: ${_.message}`);for(let Z of f)try{Function(`(async()=>{
726
726
  ${Z.js}
727
- })()`)}catch(R){console.error(` → source: ${Z.url}`,R.message)}}else console.error("Rip runtime error:",_)}}}let W=document.querySelector("script[data-launch]");if(W&&!globalThis.__ripLaunched){let u=$1.modules?.["ui.rip"];if(u?.launch){let f=W.getAttribute("data-launch")||"",Y=W.getAttribute("data-hash"),A=W.getAttribute("data-persist"),_={hash:Y!=="false"};if(f)_.bundleUrl=f;if(A!=null)_.persist=A==="local"?"local":!0;await u.launch("",_)}}}async function $1($){for(let[Y,A]of Object.entries($1.modules))if($.includes(Y))return A;let U=await fetch($).then((Y)=>{if(!Y.ok)throw Error(`importRip: ${$} (${Y.status})`);return Y.text()}),F=t(U),W=`// ${$}
727
+ })()`)}catch(R){console.error(` → source: ${Z.url}`,R.message)}}else console.error("Rip runtime error:",_)}}}let W=document.querySelector("script[data-launch]");if(W&&!globalThis.__ripLaunched){let u=$1.modules?.["ui.rip"];if(u?.launch){let f=W.getAttribute("data-launch")||"",Y=W.getAttribute("data-hash"),A=W.getAttribute("data-persist"),_={hash:Y!=="false"};if(f)_.bundleUrl=f;if(A!=null)_.persist=A==="local"?"local":!0;await u.launch("",_)}}if(U?.hasAttribute("data-reload")){let u=!1,f=new EventSource("/watch");f.addEventListener("connected",()=>{if(u)location.reload();u=!0}),f.addEventListener("reload",(Y)=>{if(Y.data==="styles"){let A=Date.now();document.querySelectorAll('link[rel="stylesheet"]').forEach((_)=>{if(new URL(_.href).origin!==location.origin)return;let Z=new URL(_.href);Z.searchParams.set("_r",A),_.href=Z.toString()})}else location.reload()})}}async function $1($){for(let[Y,A]of Object.entries($1.modules))if($.includes(Y))return A;let U=await fetch($).then((Y)=>{if(!Y.ok)throw Error(`importRip: ${$} (${Y.status})`);return Y.text()}),F=t(U),W=`// ${$}
728
728
  `,u=new Blob([W+F],{type:"application/javascript"});return await import(URL.createObjectURL(u))}$1.modules={};function q2($){try{let U=$.replace(/^/gm," "),W=t(`do ->
729
729
  ${U}`).replace(/^let\s+[^;]+;\s*\n\s*/m,"");W=W.replace(/^const\s+(\w+)\s*=/gm,"globalThis.$1 =");let u=(0,eval)(W);if(u&&typeof u.then==="function")return u.then((f)=>{if(f!==void 0)globalThis._=f;return f});if(u!==void 0)globalThis._=u;return u}catch(U){console.error("Rip compilation error:",U.message);return}}if(typeof globalThis<"u")globalThis.rip=q2,globalThis.importRip=$1,globalThis.compileToJS=t,globalThis.__ripExports={compile:I1,compileToJS:t,formatSExpr:d,getStdlibCode:X1,VERSION:D2,BUILD_DATE:M2,getReactiveRuntime:z1,getComponentRuntime:K1};if(typeof document<"u")globalThis.__ripScriptsReady=new Promise(($)=>{let U=()=>H2().then($);if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",()=>queueMicrotask(U));else queueMicrotask(U)});var T1={};t1(T1,{throttle:()=>n3,stash:()=>c2,setContext:()=>j2,raw:()=>g2,launch:()=>d3,isStash:()=>k3,hold:()=>p3,hasContext:()=>S2,getContext:()=>T2,delay:()=>v2,debounce:()=>i3,createRouter:()=>x2,createResource:()=>m3,createRenderer:()=>k2,createComponents:()=>l2});var O2,i1,_1,e,N1,G2,U1,g,x1,M1,H1,n1,P2,I2,E1,B1,E2,B2,N2,k1,m1,T2,L2,p1,S2,D1,d1,h2,V2,j2,C2,y2,r1,b2;globalThis.abort??=($)=>{if($)console.error($);process.exit(1)};globalThis.assert??=($,U)=>{if(!$)throw Error(U||"Assertion failed")};globalThis.exit??=($)=>process.exit($||0);globalThis.kind??=($)=>$!=null?($.constructor?.name||Object.prototype.toString.call($).slice(8,-1)).toLowerCase():String($);globalThis.noop??=()=>{};globalThis.p??=console.log;globalThis.pp??=($)=>{return console.log(JSON.stringify($,null,2)),$};globalThis.raise??=($,U)=>{throw U!==void 0?new $(U):Error($)};globalThis.rand??=($,U)=>U!==void 0?($>U&&([$,U]=[U,$]),Math.floor(Math.random()*(U-$+1)+$)):$?Math.floor(Math.random()*$):Math.random();globalThis.sleep??=($)=>new Promise((U)=>setTimeout(U,$));globalThis.todo??=($)=>{throw Error($||"Not implemented")};globalThis.warn??=console.warn;globalThis.zip??=(...$)=>$[0].map((U,F)=>$.map((W)=>W[F]));({__state:g,__effect:U1,__batch:G2}=globalThis.__rip);({setContext:j2,getContext:T2,hasContext:S2}=globalThis.__ripComponent||{});N1=Symbol("stash");e=Symbol("signals");_1=Symbol("raw");i1=new WeakMap;x1=0;n1=g(0);p1=function($,U){let F;if(!$[e])Object.defineProperty($,e,{value:new Map,enumerable:!1});if(F=$[e].get(U),!F)F=g($[U]),$[e].set(U,F);return F};D1=function($){return p1($,Symbol.for("keys"))};b2=function($){let U;if(!($!=null&&typeof $==="object"))return $;if($[N1])return $;if($ instanceof Date||$ instanceof RegExp||$ instanceof Map||$ instanceof Set||$ instanceof Promise)return $;if(U=i1.get($),U)return U;return d1($)};d1=function($){let U,F;return F=null,U={get:function(W,u){let f,Y;if(u===N1)return!0;if(u===_1)return W;if(typeof u==="symbol")return Reflect.get(W,u);if(u==="length"&&Array.isArray(W))return D1(W).value,W.length;if(u==="get")return function(A){return C2(F,A)};if(u==="set")return function(A,_){return y2(F,A,_)};if(f=p1(W,u),Y=f.value,Y!=null&&typeof Y==="object")return b2(Y);return Y},set:function(W,u,f){let Y,A;if(Y=W[u],A=f?.[_1]?f[_1]:f,A===Y)return!0;if(W[u]=A,W[e]?.has(u))W[e].get(u).value=A;if(Y===void 0&&A!==void 0)D1(W).value=++x1;return n1.value++,!0},deleteProperty:function(W,u){let f;if(delete W[u],f=W[e]?.get(u),f!=null)f.value=void 0;return D1(W).value=++x1,!0},ownKeys:function(W){return D1(W).value,Reflect.ownKeys(W)}},F=new Proxy($,U),i1.set($,F),F};O2=/([./][^./\[\s]+|\[[-+]?\d+\]|\[(?:"[^"]+"|'[^']+')\])/;r1=function($){let U,F,W,u,f;W=("."+$).split(O2),W.shift(),f=[],F=0;while(F<W.length){if(u=W[F],U=u[0],U==="."||U==="/")f.push(u.slice(1));else if(U==="[")if(u[1]==='"'||u[1]==="'")f.push(u.slice(2,-2));else f.push(+u.slice(1,-1));F+=2}return f};C2=function($,U){let F,W;W=r1(U),F=$;for(let u of W){if(F==null)return;F=F[u]}return F};y2=function($,U,F){let W,u;u=r1(U),W=$;for(let f=0;f<u.length;f++){let Y=u[f];if(f===u.length-1)W[Y]=F;else{if(W[Y]==null)W[Y]={};W=W[Y]}}return F};var c2=function($={}){return d1($)},g2=function($){return $?.[_1]?$[_1]:$},k3=function($){return $?.[N1]===!0},m3=function($,U={}){let F,W,u,f,Y;if(F=g(U.initial||null),u=g(!1),W=g(null),f=async function(){let A;return u.value=!0,W.value=null,(async()=>{try{return A=await $(),F.value=A}catch(_){return W.value=_}finally{u.value=!1}})()},Y={data:void 0,loading:void 0,error:void 0,refetch:f},Object.defineProperty(Y,"data",{get:function(){return F.value}}),Object.defineProperty(Y,"loading",{get:function(){return u.value}}),Object.defineProperty(Y,"error",{get:function(){return W.value}}),!U.lazy)f();return Y};H1=function($){return typeof $==="function"?$:function(){return $.value}};M1=function($,U){let F;return F={read:function(){return $.read()}},Object.defineProperty(F,"value",{get:function(){return $.value},set:function(W){return U.value=W}}),F};var v2=function($,U){let F,W;return F=H1(U),W=g(!!F()),U1(function(){let u;if(F())return u=setTimeout(function(){return W.value=!0},$),function(){return clearTimeout(u)};else return W.value=!1}),typeof U!=="function"?M1(W,U):W},i3=function($,U){let F,W;return F=H1(U),W=g(F()),U1(function(){let u,f;return f=F(),u=setTimeout(function(){return W.value=f},$),function(){return clearTimeout(u)}}),typeof U!=="function"?M1(W,U):W},n3=function($,U){let F,W,u;return F=H1(U),u=g(F()),W=0,U1(function(){let f,Y,A,_;if(_=F(),f=Date.now(),Y=$-(f-W),Y<=0)return u.value=_,W=f;else return A=setTimeout(function(){return u.value=F(),W=Date.now()},Y),function(){return clearTimeout(A)}}),typeof U!=="function"?M1(u,U):u},p3=function($,U){let F,W;return F=H1(U),W=g(!!F()),U1(function(){let u;if(F())return W.value=!0;else return u=setTimeout(function(){return W.value=!1},$),function(){return clearTimeout(u)}}),typeof U!=="function"?M1(W,U):W},l2=function(){let $,U,F,W;return U=new Map,W=[],$=new Map,F=function(u,f){for(let Y of W)Y(u,f)},{read:function(u){return U.get(u)},write:function(u,f){let Y;return Y=!U.has(u),U.set(u,f),$.delete(u),F(Y?"create":"change",u)},del:function(u){return U.delete(u),$.delete(u),F("delete",u)},exists:function(u){return U.has(u)},size:function(){return U.size},list:function(u=""){let f,Y,A;A=[],f=u?u+"/":"";for(let[_]of U)if(_.startsWith(f)){if(Y=_.slice(f.length),Y.includes("/"))continue;A.push(_)}return A},listAll:function(u=""){let f,Y;Y=[],f=u?u+"/":"";for(let[A]of U)if(A.startsWith(f))Y.push(A);return Y},load:function(u){for(let f in u){let Y=u[f];U.set(f,Y)}},watch:function(u){return W.push(u),function(){return W.splice(W.indexOf(u),1)}},getCompiled:function(u){return $.get(u)},setCompiled:function(u,f){return $.set(u,f)}}};N2=function($){let U;if(U=$.replace(/\.rip$/,""),U=U.replace(/\[\.\.\.(\w+)\]/g,"*$1"),U=U.replace(/\[(\w+)\]/g,":$1"),U==="index")return"/";return U=U.replace(/\/index$/,""),"/"+U};V2=function($){let U,F;return U=[],F=$.replace(/\*(\w+)/g,function(W,u){return U.push(u),"(.+)"}).replace(/:(\w+)/g,function(W,u){return U.push(u),"([^/]+)"}),{regex:new RegExp("^"+F+"$"),names:U}};h2=function($,U){let F,W;for(let u of U)if(F=$.match(u.regex.regex),F){W={};for(let f=0;f<u.regex.names.length;f++){let Y=u.regex.names[f];W[Y]=decodeURIComponent(F[f+1])}return{route:u,params:W}}return null};E1=function($,U="components"){let F,W,u,f,Y,A,_,Z,R;_=[],u=new Map,F=$.listAll(U);for(let Q of F){if(A=Q.slice(U.length+1),!A.endsWith(".rip"))continue;if(f=A.split("/").pop(),f==="_layout.rip"){W=A==="_layout.rip"?"":A.slice(0,-12),u.set(W,Q);continue}if(f.startsWith("_"))continue;if(Z=A.split("/"),Z.length>1&&Z.some(function(z,J){return J<Z.length-1&&z.startsWith("_")}))continue;R=N2(A),Y=V2(R),_.push({pattern:R,regex:Y,file:Q,rel:A})}return _.sort(function(Q,z){let J,D,M,X;if(D=(Q.pattern.match(/:/g)||[]).length,X=(z.pattern.match(/:/g)||[]).length,J=Q.pattern.includes("*")?1:0,M=z.pattern.includes("*")?1:0,J!==M)return J-M;if(D!==X)return D-X;return Q.pattern.localeCompare(z.pattern)}),{routes:_,layouts:u}};L2=function($,U,F){let W,u,f,Y;if(W=[],f=$.slice(U.length+1),Y=f.split("/"),u="",F.has(""))W.push(F.get(""));for(let A=0;A<Y.length;A++){let _=Y[A];if(A===Y.length-1)break;if(u=u?u+"/"+_:_,F.has(u))W.push(F.get(u))}return W};var x2=function($,U={}){let F,W,u,f,Y,A,_,Z,R,Q,z,J,D,M,X,w,K,q,O,P,G;if(K=U.root||"components",R=U.base||"",Q=U.hash||!1,D=U.onError||null,O=function(H){return R&&H.startsWith(R)?H.slice(R.length)||"/":H},Z=function(H){return R?R+H:H},X=function(){let H;if(Q){if(H=location.hash.slice(1),!H)return"/";return H[0]==="/"?H:"/"+H}else return location.pathname+location.search+location.hash},G=function(H){return Q?H==="/"?location.pathname:"#"+H.slice(1):Z(H)},Y=g(O(Q?X():location.pathname)),f=g({}),_=g(null),W=g([]),A=g({}),F=g(""),u=v2(100,g(!1)),P=E1($,K),z=new Set,$.watch(function(H,I){if(!I.startsWith(K+"/"))return;return P=E1($,K)}),w=function(H){let I,E,N,B,T;if(B=H.split("?")[0].split("#")[0],E=O(B),E=E[0]==="/"?E:"/"+E,N=H.split("?")[1]?.split("#")[0]||"",I=H.includes("#")?H.split("#")[1]:"",T=h2(E,P.routes),T){G2(function(){return Y.value=E,f.value=T.params,_.value=T.route,W.value=L2(T.route.file,K,P.layouts),A.value=Object.fromEntries(new URLSearchParams(N)),F.value=I});for(let C of z)C(q.current);return!0}if(D)D({status:404,path:E});return!1},M=function(){return w(X())},typeof window<"u")window.addEventListener("popstate",M);if(J=function(H){let I,E,N;if(H.button!==0||H.metaKey||H.ctrlKey||H.shiftKey||H.altKey)return;E=H.target;while(E&&E.tagName!=="A")E=E.parentElement;if(!E?.href)return;if(N=new URL(E.href,location.origin),N.origin!==location.origin)return;if(E.target==="_blank"||E.hasAttribute("data-external"))return;return H.preventDefault(),I=Q&&N.hash?N.hash.slice(1)||"/":N.pathname+N.search+N.hash,q.push(I)},typeof document<"u")document.addEventListener("click",J);return q={push:function(H){return w(H)?history.pushState(null,"",G(Y.read())):void 0},replace:function(H){return w(H)?history.replaceState(null,"",G(Y.read())):void 0},back:function(){return history.back()},forward:function(){return history.forward()},current:void 0,path:void 0,params:void 0,route:void 0,layouts:void 0,query:void 0,hash:void 0,navigating:void 0,onNavigate:function(H){return z.add(H),function(){return z.delete(H)}},rebuild:function(){return P=E1($,K)},routes:void 0,init:function(){return w(X()),q},destroy:function(){if(typeof window<"u")window.removeEventListener("popstate",M);if(typeof document<"u")document.removeEventListener("click",J);return z.clear()}},Object.defineProperty(q,"current",{get:function(){return{path:Y.value,params:f.value,route:_.value,layouts:W.value,query:A.value,hash:F.value}}}),Object.defineProperty(q,"path",{get:function(){return Y.value}}),Object.defineProperty(q,"params",{get:function(){return f.value}}),Object.defineProperty(q,"route",{get:function(){return _.value}}),Object.defineProperty(q,"layouts",{get:function(){return W.value}}),Object.defineProperty(q,"query",{get:function(){return A.value}}),Object.defineProperty(q,"hash",{get:function(){return F.value}}),Object.defineProperty(q,"navigating",{get:function(){return u.value},set:function(H){return u.value=H}}),Object.defineProperty(q,"routes",{get:function(){return P.routes}}),q};P2=function($,U){if($.length!==U.length)return!1;for(let F=0;F<$.length;F++)if($[F]!==U[F])return!1;return!0};m1=function($){for(let U in $){let F=$[U];if(typeof F==="function"&&(F.prototype?.mount||F.prototype?._create))return F}return typeof $.default==="function"?$.default:void 0};k1=function($){let U;U={};for(let F in $){let W=$[F];if(typeof W==="function"&&(W.prototype?.mount||W.prototype?._create))U[F]=W}return U};B2=function($){let U;return U=$.split("/").pop().replace(/\.rip$/,""),U.replace(/(^|[-_])([a-z])/g,function(F,W,u){return u.toUpperCase()})};I2=function($,U="components"){let F,W,u;W={};for(let f of $.listAll(U)){if(!f.endsWith(".rip"))continue;if(F=f.split("/").pop(),F.startsWith("_"))continue;if(u=B2(f),W[u])console.warn(`[Rip] Component name collision: ${u} (${W[u]} vs ${f})`);W[u]=f}return W};B1=async function($,U,F=null,W=null,u=null){let f,Y,A,_,Z,R,Q,z,J,D,M,X;if(F&&W){if(Y=F.getCompiled(W),Y)return Y}if(Q=U($),u){D={};for(let w in u.map){let K=u.map[w];if(K!==W&&Q.includes(`new ${w}(`)){if(!u.classes[w]){if(_=F.read(K),_){A=await B1(_,U,F,K,u),Z=k1(A);for(let q in Z){let O=Z[q];u.classes[q]=O}}}if(u.classes[w])D[w]=!0}}if(J=Object.keys(D),J.length>0)M=`const {${J.join(", ")}} = globalThis['${u.key}'];
730
730
  `,Q=M+Q}if(R=W?`// ${W}
Binary file
@@ -0,0 +1,96 @@
1
+ # AlertDialog — accessible headless non-dismissable modal
2
+ #
3
+ # A Dialog variant that requires explicit user action to close.
4
+ # Cannot be dismissed by clicking outside or pressing Escape.
5
+ # Use for destructive confirmations, unsaved changes, etc.
6
+ # Ships zero CSS.
7
+ #
8
+ # Usage:
9
+ # AlertDialog open <=> showConfirm
10
+ # h2 "Delete account?"
11
+ # p "This action cannot be undone."
12
+ # button @click: (=> showConfirm = false), "Cancel"
13
+ # button @click: handleDelete, "Delete"
14
+
15
+ alertDialogStack = []
16
+
17
+ export AlertDialog = component
18
+ @open := false
19
+ @initialFocus := null
20
+
21
+ _prevFocus = null
22
+ _cleanupTrap = null
23
+ _scrollY = 0
24
+ _id =! "adlg-#{Math.random().toString(36).slice(2, 8)}"
25
+
26
+ _wireAria: ->
27
+ panel = @_panel
28
+ return unless panel
29
+ heading = panel.querySelector('h1,h2,h3,h4,h5,h6')
30
+ if heading
31
+ heading.id ?= "#{_id}-title"
32
+ panel.setAttribute 'aria-labelledby', heading.id
33
+ desc = panel.querySelector('p')
34
+ if desc
35
+ desc.id ?= "#{_id}-desc"
36
+ panel.setAttribute 'aria-describedby', desc.id
37
+
38
+ ~>
39
+ if @open
40
+ _prevFocus = document.activeElement
41
+ _scrollY = window.scrollY
42
+ alertDialogStack.push this
43
+ document.body.style.position = 'fixed'
44
+ document.body.style.top = "-#{_scrollY}px"
45
+ document.body.style.width = '100%'
46
+
47
+ setTimeout =>
48
+ panel = @_panel
49
+ if panel
50
+ @_wireAria()
51
+ if @initialFocus
52
+ target = if typeof @initialFocus is 'string' then panel.querySelector(@initialFocus) else @initialFocus
53
+ target?.focus()
54
+ else
55
+ focusable = panel.querySelectorAll 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])'
56
+ focusable[0]?.focus()
57
+ _cleanupTrap = (e) ->
58
+ return unless e.key is 'Tab'
59
+ list = Array.from(panel.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')).filter (f) -> f.offsetParent isnt null
60
+ return unless list.length
61
+ first = list[0]
62
+ last = list[list.length - 1]
63
+ if e.shiftKey
64
+ if document.activeElement is first then (e.preventDefault(); last.focus())
65
+ else
66
+ if document.activeElement is last then (e.preventDefault(); first.focus())
67
+ panel.addEventListener 'keydown', _cleanupTrap
68
+ , 0
69
+
70
+ return ->
71
+ idx = alertDialogStack.indexOf this
72
+ alertDialogStack.splice(idx, 1) if idx >= 0
73
+ document.body.style.position = '' unless alertDialogStack.length
74
+ document.body.style.top = '' unless alertDialogStack.length
75
+ document.body.style.width = '' unless alertDialogStack.length
76
+ window.scrollTo 0, _scrollY unless alertDialogStack.length
77
+ _prevFocus?.focus()
78
+ else
79
+ idx = alertDialogStack.indexOf this
80
+ alertDialogStack.splice(idx, 1) if idx >= 0
81
+ unless alertDialogStack.length
82
+ document.body.style.position = ''
83
+ document.body.style.top = ''
84
+ document.body.style.width = ''
85
+ window.scrollTo 0, _scrollY
86
+ _prevFocus?.focus()
87
+
88
+ close: ->
89
+ @open = false
90
+ @emit 'close'
91
+
92
+ render
93
+ if @open
94
+ div ref: "_backdrop", $open: true
95
+ div ref: "_panel", role: "alertdialog", aria-modal: "true", tabindex: "-1"
96
+ slot
@@ -0,0 +1,15 @@
1
+ # Badge — accessible headless inline label
2
+ #
3
+ # Decorative label for status, counts, or categories.
4
+ # Ships zero CSS.
5
+ #
6
+ # Usage:
7
+ # Badge "New"
8
+ # Badge variant: "outline", "Beta"
9
+
10
+ export Badge = component
11
+ @variant := 'solid'
12
+
13
+ render
14
+ span $variant: @variant
15
+ slot
@@ -0,0 +1,46 @@
1
+ # Breadcrumb — accessible headless navigation breadcrumb
2
+ #
3
+ # Renders a navigation trail with separator between items.
4
+ # The last item is automatically marked as the current page.
5
+ # Ships zero CSS.
6
+ #
7
+ # Usage:
8
+ # Breadcrumb
9
+ # a $item: true, href: "/", "Home"
10
+ # a $item: true, href: "/products", "Products"
11
+ # span $item: true, "Widget Pro"
12
+ #
13
+ # Breadcrumb separator: ">"
14
+ # a $item: true, href: "/", "Home"
15
+ # span $item: true, "Settings"
16
+
17
+ export Breadcrumb = component
18
+ @separator := '/'
19
+ @label := 'Breadcrumb'
20
+
21
+ _ready := false
22
+
23
+ mounted: -> _ready = true
24
+
25
+ _items ~=
26
+ return [] unless _ready
27
+ return [] unless @_content
28
+ Array.from(@_content.querySelectorAll('[data-item]') or [])
29
+
30
+ ~>
31
+ return unless _ready
32
+ items = _items
33
+ return unless items.length
34
+ items.forEach (el, idx) =>
35
+ isLast = idx is items.length - 1
36
+ if isLast
37
+ el.setAttribute 'aria-current', 'page'
38
+ el.toggleAttribute 'data-current', true
39
+ else
40
+ el.removeAttribute 'aria-current'
41
+ el.removeAttribute 'data-current'
42
+
43
+ render
44
+ nav aria-label: @label
45
+ ol ref: "_content"
46
+ slot
@@ -0,0 +1,26 @@
1
+ # ButtonGroup — accessible headless button group
2
+ #
3
+ # Groups related buttons with proper ARIA semantics.
4
+ # Ships zero CSS.
5
+ #
6
+ # Usage:
7
+ # ButtonGroup
8
+ # Button "Cut"
9
+ # Button "Copy"
10
+ # Button "Paste"
11
+ # ButtonGroup orientation: "vertical", label: "Text formatting"
12
+ # Toggle pressed <=> isBold, "Bold"
13
+ # Toggle pressed <=> isItalic, "Italic"
14
+
15
+ export ButtonGroup = component
16
+ @orientation := 'horizontal'
17
+ @disabled := false
18
+ @label := ''
19
+
20
+ render
21
+ div role: "group"
22
+ aria-label: @label?!
23
+ aria-orientation: @orientation
24
+ $orientation: @orientation
25
+ $disabled: @disabled?!
26
+ slot
@@ -0,0 +1,25 @@
1
+ # Card — accessible headless content container
2
+ #
3
+ # Structured container with optional header, content, and footer sections.
4
+ # Use $header, $content, $footer on children to mark sections.
5
+ # Ships zero CSS.
6
+ #
7
+ # Usage:
8
+ # Card
9
+ # div $header: true
10
+ # h3 "Title"
11
+ # div $content: true
12
+ # p "Body text"
13
+ # div $footer: true
14
+ # Button "Action"
15
+ #
16
+ # Card interactive: true, @click: handleClick
17
+ # p "Clickable card"
18
+
19
+ export Card = component
20
+ @interactive := false
21
+
22
+ render
23
+ div tabindex: (if @interactive then "0" else undefined)
24
+ $interactive: @interactive?!
25
+ slot
@@ -0,0 +1,110 @@
1
+ # Carousel — accessible headless slide carousel
2
+ #
3
+ # Displays one slide at a time with arrow key navigation, optional
4
+ # autoplay, and loop mode. Discovers slides from [data-slide] children.
5
+ # Ships zero CSS.
6
+ #
7
+ # Usage:
8
+ # Carousel loop: true
9
+ # div $slide: true
10
+ # img src: "slide1.jpg"
11
+ # div $slide: true
12
+ # img src: "slide2.jpg"
13
+ # div $slide: true
14
+ # img src: "slide3.jpg"
15
+ #
16
+ # Carousel autoplay: true, interval: 5000, @change: handleSlide
17
+ # div $slide: true, "Slide A"
18
+ # div $slide: true, "Slide B"
19
+
20
+ export Carousel = component
21
+ @orientation := 'horizontal'
22
+ @loop := false
23
+ @autoplay := false
24
+ @interval := 4000
25
+ @label := 'Carousel'
26
+
27
+ activeIndex := 0
28
+ _ready := false
29
+ _timer = null
30
+
31
+ _slides ~=
32
+ return [] unless _ready
33
+ return [] unless @_content
34
+ Array.from(@_content.querySelectorAll('[data-slide]') or [])
35
+
36
+ totalSlides ~= _slides.length
37
+
38
+ mounted: ->
39
+ _ready = true
40
+ @_startAutoplay() if @autoplay
41
+
42
+ beforeUnmount: ->
43
+ @_stopAutoplay()
44
+
45
+ _startAutoplay: ->
46
+ @_stopAutoplay()
47
+ _timer = setInterval (=> @next()), @interval
48
+
49
+ _stopAutoplay: ->
50
+ clearInterval _timer if _timer
51
+ _timer = null
52
+
53
+ goto: (idx) ->
54
+ count = totalSlides
55
+ return unless count
56
+ if @loop
57
+ idx = idx %% count
58
+ else
59
+ idx = Math.max(0, Math.min(idx, count - 1))
60
+ activeIndex = idx
61
+ @emit 'change', activeIndex
62
+
63
+ next: -> @goto(activeIndex + 1)
64
+ prev: -> @goto(activeIndex - 1)
65
+
66
+ onKeydown: (e) ->
67
+ horiz = @orientation is 'horizontal'
68
+ switch e.key
69
+ when (if horiz then 'ArrowRight' else 'ArrowDown')
70
+ e.preventDefault()
71
+ @next()
72
+ when (if horiz then 'ArrowLeft' else 'ArrowUp')
73
+ e.preventDefault()
74
+ @prev()
75
+ when 'Home'
76
+ e.preventDefault()
77
+ @goto(0)
78
+ when 'End'
79
+ e.preventDefault()
80
+ @goto(totalSlides - 1)
81
+
82
+ ~>
83
+ return unless _ready
84
+ _slides.forEach (el, idx) =>
85
+ isActive = idx is activeIndex
86
+ el.hidden = not isActive
87
+ el.toggleAttribute 'data-active', isActive
88
+ el.setAttribute 'role', 'tabpanel'
89
+ el.setAttribute 'aria-roledescription', 'slide'
90
+ el.setAttribute 'aria-label', "Slide #{idx + 1} of #{totalSlides}"
91
+
92
+ onMouseenter: -> @_stopAutoplay() if @autoplay
93
+ onMouseleave: -> @_startAutoplay() if @autoplay
94
+
95
+ render
96
+ div role: "region", aria-roledescription: "carousel", aria-label: @label, tabindex: "0"
97
+ $orientation: @orientation
98
+ @keydown: @onKeydown
99
+ @mouseenter: @onMouseenter
100
+ @mouseleave: @onMouseleave
101
+ button $prev: true, aria-label: "Previous slide"
102
+ disabled: not @loop and activeIndex <= 0
103
+ $disabled: (not @loop and activeIndex <= 0)?!
104
+ @click: (=> @prev())
105
+ div ref: "_content"
106
+ slot
107
+ button $next: true, aria-label: "Next slide"
108
+ disabled: not @loop and activeIndex >= totalSlides - 1
109
+ $disabled: (not @loop and activeIndex >= totalSlides - 1)?!
110
+ @click: (=> @next())
@@ -0,0 +1,50 @@
1
+ # Collapsible — accessible headless expand/collapse section
2
+ #
3
+ # Single open/close section. Simpler than Accordion (no item IDs,
4
+ # no single/multiple mode). Exposes content dimensions as CSS
5
+ # custom properties for animated expand/collapse. Ships zero CSS.
6
+ #
7
+ # Usage:
8
+ # Collapsible open <=> isOpen
9
+ # button $trigger: true, "Show details"
10
+ # div $content: true
11
+ # p "Hidden content here"
12
+
13
+ export Collapsible = component
14
+ @open := false
15
+ @disabled := false
16
+
17
+ _ready := false
18
+
19
+ mounted: ->
20
+ _ready = true
21
+ trigger = @_root?.querySelector('[data-trigger]')
22
+ return unless trigger
23
+ trigger.addEventListener 'click', => @toggle() unless @disabled
24
+ trigger.addEventListener 'keydown', (e) =>
25
+ if e.key in ['Enter', ' '] and not @disabled
26
+ e.preventDefault()
27
+ @toggle()
28
+
29
+ toggle: ->
30
+ @open = not @open
31
+ @emit 'change', @open
32
+
33
+ ~>
34
+ return unless _ready
35
+ trigger = @_root?.querySelector('[data-trigger]')
36
+ content = @_root?.querySelector('[data-content]')
37
+ if trigger
38
+ trigger.setAttribute 'aria-expanded', !!@open
39
+ trigger.setAttribute 'aria-disabled', true if @disabled
40
+ trigger.tabIndex = if @disabled then -1 else 0
41
+ if content
42
+ content.hidden = not @open
43
+ if @open
44
+ rect = content.getBoundingClientRect()
45
+ content.style.setProperty '--collapsible-height', "#{rect.height}px"
46
+ content.style.setProperty '--collapsible-width', "#{rect.width}px"
47
+
48
+ render
49
+ div ref: "_root", $open: @open?!, $disabled: @disabled?!
50
+ slot