cascivo 1.2.0 → 1.3.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/index.mjs CHANGED
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,l as t,n,o as r,r as i,s as a,t as o,u as s}from"./config-DT-Cs7bC.mjs";import{i as c,n as l,r as u,t as d}from"./fs-B7O-fNID.mjs";import{r as f,t as p}from"./http-Dx1cFJ5S.mjs";import{a as m,c as h,i as g,l as _,n as v,o as y,r as b,s as x,t as ee}from"./lock-BwLjTQmQ.mjs";import{n as S,r as C,t as te}from"./peer-versions-DIPdOfWj.mjs";import{n as w,r as T,t as E}from"./args-CtmltI1S.mjs";import{createRequire as D}from"node:module";import{argv as O,stdin as k,stdout as A}from"node:process";import{pathToFileURL as ne}from"node:url";import{existsSync as j,readFileSync as M,readdirSync as N,writeFileSync as P}from"node:fs";import{basename as re,dirname as ie,join as F,resolve as I}from"node:path";import{spawnSync as ae}from"node:child_process";import{readFile as oe}from"node:fs/promises";import{asTemplateMeta as se,buildRegistry as ce,isTemplateItem as L,parseItem as R,parseLegacyRegistry as le,validateIndex as ue,validateItem as de,validateTemplate as fe}from"@cascivo/registry";import{createInterface as z}from"node:readline/promises";function B(t,n=process.cwd(),i={}){if(t.length===0)return!0;let o=i.pm??e(n),[s,c]=r(o,t,{dev:i.dev??!1,...i.floors?{floors:i.floors}:{},...i.pin?{pin:i.pin}:{}});return console.log(`Installing ${t.join(`, `)} with ${s}…`),ae(s,c,{cwd:n,stdio:`inherit`,shell:process.platform===`win32`}).status===0?!0:(console.error(`Failed to install: ${t.join(`, `)}`),console.error(`Install them yourself with: ${a(o,t,{dev:i.dev??!1})}`),!1)}const pe=/^([^/]+)\/([^/]+)\/([^#]+)(?:#(.+))?$/;function V(e,t=process.env){return e.replace(/\$\{([^}]+)\}/g,(e,n)=>{let r=t[n];if(r===void 0)throw Error(`Environment variable ${n} is not set`);return r})}function H(e,t=process.env){if(e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`./`)||e.startsWith(`/`))return{kind:`url`,name:e,raw:e};if(e.startsWith(`@`)){let t=e.indexOf(`/`,1);if(t===-1)throw Error(`Invalid namespace address: ${e} (expected @ns/name)`);return{kind:`namespace`,namespace:e.slice(0,t),name:e.slice(t+1),raw:e}}let n=e.includes(`#`)?e.slice(0,e.indexOf(`#`)):e,r=pe.exec(e);if(r&&!n.includes(`.`)&&n.split(`/`).length>=3){let[,t,n,i,a]=r;return{kind:`github`,name:`${t}/${n}/${i}`,ref:a??`main`,raw:e}}return{kind:`bare`,name:e,raw:e}}function U(e,t,n,r){let i=typeof n==`string`?n:n.url;if(!i.includes(`{name}`))throw Error(`Registry namespace "${e}" URL template must contain {name}: ${i}`);return V(i.replace(`{name}`,t),r)}async function W(e,t,n=process.env,r){switch(e.kind){case`url`:return{url:e.name};case`bare`:return{url:`${t.registry.replace(/\/registry\.json$/,``).replace(/\/r$/,``)}/r/${e.name}.json`};case`github`:{let t=e.name.split(`/`),n=t[0],r=t[1],i=t.slice(2).join(`/`);return{url:`https://raw.githubusercontent.com/${n}/${r}/${e.ref??`main`}/r/${i}.json`}}case`namespace`:{let i=e.namespace,a=e.name;if(t.registries?.[i]){let e=t.registries[i],r=U(i,a,e,n),o=typeof e==`string`?void 0:e.headers,s=typeof e==`string`?void 0:e.params,c=o?Object.fromEntries(Object.entries(o).map(([e,t])=>[e,V(t,n)])):void 0,l=s?Object.fromEntries(Object.entries(s).map(([e,t])=>[e,V(t,n)])):void 0,u={url:r};return c&&(u.headers=c),l&&(u.params=l),u}if(r){let e=await r(i);if(e)return{url:U(i,a,e,n)}}if(i===`@cascivo`||i===`@cascade`)return{url:`${o}/r/${a}.json`};throw Error(`Unknown namespace "${i}". Add it to registries in cascivo.config.ts or check the directory at cascivo.com`)}}}async function me(e,t,n=process.env,r){let i=new Set,a=[...e],o=[];for(;a.length>0;){let e=a.shift(),s=H(e,n),c=s.raw;if(i.has(c))continue;i.add(c);let{url:l,headers:u,params:d}=await W(s,t,n,r),f={};u&&(f.headers=u),d&&(f.params=d);let m=R(await p(l,f),l),h={spec:e,addr:s,itemUrl:l,item:m,registryBase:l.replace(/\/[^/]+\.json$/,``)};u&&(h.headers=u),d&&(h.params=d),o.push(h);for(let e of m.registryDependencies??[])a.push(e)}return{items:o}}const he=`${o}/r/registries.json`;function ge(e,t){if(typeof e!=`object`||!e)return null;let n=e.registries;if(!Array.isArray(n))return null;for(let e of n){if(typeof e!=`object`||!e)continue;let n=e;if(n.namespace!==t)continue;let r=n.registryUrl;return typeof r!=`string`||!/^https?:\/\//.test(r)?null:r}return null}async function _e(e,t){try{let n;if(t){let e=await t(he,{headers:{Accept:`application/json`}});if(!e.ok)throw Error(`HTTP ${e.status}`);n=await e.json()}else n=await p(he);return ge(n,e)}catch(e){let t=e instanceof Error?e.message:String(e);return console.warn(`Could not reach cascivo.com directory: ${t}`),null}}var ve=s({LAYOUT_ALIASES:()=>G,NAME_NOTES:()=>Ce,add:()=>Oe,isThirdParty:()=>Ee,resolveBareClosure:()=>we,resolveTemplateTarget:()=>Se});const ye=new Set([`react`,`react-dom`]);function be(e){try{let t=JSON.parse(M(F(e,`package.json`),`utf8`));return{...t.dependencies,...t.devDependencies}}catch{return{}}}function xe(e,t){let n=be(e);n[`@cascivo/themes`]!==void 0||n[`@cascivo/tokens`]!==void 0||(console.log(`
3
- Styling: cascivo components read --cascivo-* tokens, which this project does not import yet.`),console.log(` ${a(t,[`@cascivo/themes`])}`),console.log(` import '@cascivo/themes/all' // once, in your entry file`),console.log(` <html data-theme="light"> // or any container`))}function Se(e,t){return d(e,I(e,t))}const G={box:`layout/flex`,hstack:`layout/flex`,vstack:`layout/flex`,gap:`spacer`},Ce={stack:`Note: cascivo's Stack overlaps children into a card-pile (z-axis), not a vertical spacing layout. For vertical spacing use Flex direction="vertical" (cascivo add flex; aliases: vstack, hstack).`};function we(e,t){let n=t.map(e=>({name:e,requested:!0})),r=new Set,i=[],a=[];for(;n.length>0;){let{name:t,requested:o}=n.shift(),s=h(e,G[t.toLowerCase()]??t);if(!s){a.push(t);continue}if(r.has(s.name))continue;r.add(s.name);let c=_(s,t);i.push({entry:s,requested:o,...c?{viaAlias:c}:{}});for(let e of s.registryDependencies??[])n.push({name:e,requested:!1})}return{resolved:i,missing:a}}const Te=/^https:\/\/(cascivo\.com|raw\.githubusercontent\.com\/cascivo\/cascivo)\//;function Ee(e){return!Te.test(e)}function De(e){return e.startsWith(`@`)||e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`./`)||e.startsWith(`/`)||e.split(`/`).length>=3}async function Oe(t,n,r={}){if(t.length===0){console.error(`Usage: cascivo add <component...>`);return}let i=r.cwd??process.cwd(),o=r.pm??e(i),s=t.filter(De),l=t.filter(e=>!De(e)),d=null;if(l.length>0){d=await y(n.registry);let e=new Set(d.templates.map(e=>e.toLowerCase())),t=l.filter(t=>e.has(t.toLowerCase()));t.length>0&&(l=l.filter(t=>!e.has(t.toLowerCase())),s.push(...t.map(e=>`@cascivo/${e.toLowerCase()}`)))}let p=await v(i)??ee();if(s.length>0){let e=await me(s,n,process.env,_e);if(r.dryRun){console.log(`Dry run — would install:`);for(let t of e.items){let e=L(t.item)?` [template]`:``;console.log(` ${t.spec} (${t.item.name}@${t.item.version})${e} from ${t.itemUrl}`);for(let e of t.item.files){let n=L(t.item)&&e.target?` → ${e.target}`:``;console.log(` ${e.url}${n}`)}t.item.registryDependencies?.length&&console.log(` components: ${t.item.registryDependencies.join(`, `)}`)}return}for(let{item:t,itemUrl:a,registryBase:s}of e.items){Ee(a)&&console.log(`\nReview before use — files from non-directory registry: ${s}\n`+(t.files??[]).map(e=>` ${e.url}`).join(`
4
- `));let e;try{e=await ke(t,n,i,{pm:o,...r.noInstall?{noInstall:!0}:{}})}catch(e){console.error(`Failed to install ${t.name}: ${e instanceof Error?e.message:e}`),process.exitCode=1;continue}p=g(p,t.name,{registry:s,version:t.version,installedAt:new Date().toISOString().slice(0,10),files:e})}if(await m(p,i),l.length===0){xe(i,o);return}}if(l.length===0)return;d??=await y(n.registry);let _=new Set,S=n.registry.replace(/\/registry\.json$/,``).replace(/\/r$/,``);for(let e of l){let t=Ce[e.toLowerCase()];t&&console.log(t);let n=G[e.toLowerCase()];if(!n)continue;let r=h(d,n);r&&console.log(`"${e}" is not a cascivo component — installing ${r.name} (its ${e} primitive).`)}let{resolved:C,missing:w}=we(d,l);for(let e of w)console.error(`Component "${e}" not found in registry. Run "cascivo list".`);for(let{entry:e,requested:t,viaAlias:n}of C)!t||!n||console.log(`\n"${n}" is cascivo's "${e.name}" — installing that.`);let T=new Set;for(let{entry:e,requested:t}of C)!t||!e.install||T.has(e.install)||(T.add(e.install),console.log(`\n"${e.name}" ships in the ${e.install} npm package — no source is copied into your project. Updates come from your package manager, not \`cascivo update\`.`));for(let{entry:e,requested:t}of C){if(!t||!e.deprecated)continue;let{replacement:n,since:r,note:i}=e.deprecated;console.warn(`\n⚠ "${e.name}" is deprecated since ${r}. Use "${n}" instead:\n cascivo add ${n}\n`+(i?` ${i}\n`:``)+` Adding "${e.name}" anyway — it still works.\n`)}let E={};for(let{entry:e}of C)for(let[t,n]of Object.entries(e.peerVersions??{}))E[t]=n;let D=new Set,O=[];for(let{entry:e,requested:t}of C){if(e.install){let t=e.install;D.add(t),console.log(`"${e.name}" is distributed as the npm package ${t} — a runtime dependency, not copied source (updates come via your package manager).`),O.push(` import { ${e.meta.name} } from '${t}'`),e.styles&&O.push(` import '${e.styles}' // once, in your entry file`);continue}let r=e.name.includes(`/`)?e.name.split(`/`).pop():e.name,a={},o;try{o=await Promise.all(e.files.map(async e=>({url:e,content:await f(e)})))}catch(t){console.error(`Failed to install ${e.name}: ${t instanceof Error?t.message:t}`),process.exitCode=1;continue}for(let{url:e,content:t}of o){let o=u(n.outputDir,r,x(e),i);await c(o,t),a[o]=b(t)}for(let t of e.dependencies)ye.has(t)||_.add(t);p=g(p,e.name,{registry:S,version:e.version,installedAt:new Date().toISOString().slice(0,10),files:a});let s=t?``:` (dependency)`;console.log(`Added ${e.name} to ${n.outputDir}/${r}/${s}`)}if(D.size>0){let e=be(i),t=[...D].filter(t=>e[t]===void 0);r.dryRun?console.log(`Dry run — would install npm package(s): ${[...D].join(`, `)}`):t.length>0&&(r.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(o,t)}`):B(t,i,{pm:o})||(process.exitCode=1)),O.length>0&&console.log(`\nImport it:\n${O.join(`
5
- `)}`)}if(_.size>0&&!r.dryRun&&(r.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(o,[..._])}`):B([..._],i,{pm:o})),Object.keys(E).length>0){let e=await te(i,E);for(let t of e)console.error(`\nWarning: ${t.pkg} ${t.installed?`${t.installed} is`:`is not`} installed, but the copied component source needs ${t.pkg} ${t.required}. Run: ${a(o,[`${t.pkg}@latest`])}`),process.exitCode=1}await m(p,i),xe(i,o)}async function ke(t,n,r,i={}){let o={},s=new Set,l=L(t),d=t.name.includes(`/`)?t.name.split(`/`).pop():t.name,p=await Promise.all((t.files??[]).map(async e=>({file:e,content:await f(e.url)})));for(let{file:e,content:t}of p){let i=l&&e.target?Se(r,e.target):u(n.outputDir,d,x(e.url),r);await c(i,t),o[i]=b(t)}for(let e of t.dependencies??[])ye.has(e)||s.add(e);if(s.size>0&&(i.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(i.pm??e(r),[...s])}`):B([...s],r,i.pm?{pm:i.pm}:{})),l){let e=t.files?.filter(e=>e.target).map(e=>e.target)??[];console.log(`Installed template ${t.name} (${e.length} files)`)}else console.log(`Added ${t.name} to ${n.outputDir}/${d}/`);return o}const K={"@cascivo/react":`1.2.0`,"@cascivo/themes":`1.0.0`,"@cascivo/charts":`1.2.0`,"@cascivo/icons":`1.1.0`,"@cascivo/eslint-config":`0.4.0`};function Ae(e){return e===`yarn`?`yarn`:`${e} install`}function je(e,t){return e===`npm`?`npm run ${t}`:`${e} ${t}`}function Me(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`section`}function Ne(e){let t=e.trim().split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)||`Section`;return/^[0-9]/.test(t)?`Section${t}`:t}function Pe(e){let t=e.trim().split(/[^a-zA-Z0-9]+/).filter(e=>e!==``&&!/^\d+$/.test(e)&&!/^v\d+$/i.test(e)),n=[];for(let e of t){if(n.length>=3||n.length>0&&n.join(` `).length+1+e.length>24)break;n.push(e.charAt(0).toUpperCase()+e.slice(1))}return n.join(` `)||`App`}function Fe(e){return e.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^-+|-+$/g,``)||`cascivo-app`}function Ie(e){let t=new Set,n=new Set,r=[];for(let i of e){let e=i.trim();if(!e)continue;let a=Me(e),o=Ne(e),s=2;for(;t.has(a)||n.has(o);)a=`${Me(e)}-${s}`,o=`${Ne(e)}${s}`,s++;t.add(a),n.add(o),r.push({key:a,label:e,component:o})}return r.length>0?r:[{key:`home`,label:`Home`,component:`Home`}]}function Le(e){let t={name:Fe(e.name),private:!0,version:`0.0.0`,type:`module`,scripts:{dev:`vite`,build:`tsc && vite build`,preview:`vite preview`,typecheck:`tsc --noEmit`,lint:`eslint .`,format:`prettier --write .`,"format:check":`prettier --check .`},dependencies:{"@cascivo/react":K[`@cascivo/react`],"@cascivo/themes":K[`@cascivo/themes`],"@preact/signals-react":`>=3.0.0`,react:`^19.0.0`,"react-dom":`^19.0.0`},devDependencies:{"@cascivo/eslint-config":K[`@cascivo/eslint-config`],"@eslint/js":`^9.0.0`,"@types/react":`^19.0.0`,"@types/react-dom":`^19.0.0`,"@vitejs/plugin-react":`^5.0.0`,eslint:`^9.0.0`,"eslint-plugin-react-hooks":`^7.0.0`,prettier:`^3.0.0`,typescript:`^5.7.0`,"typescript-eslint":`^8.0.0`,vite:`^7.0.0`}};return JSON.stringify(t,null,2)+`
6
- `}function Re(){return JSON.stringify({compilerOptions:{target:`ES2022`,useDefineForClassFields:!0,lib:[`ES2022`,`DOM`,`DOM.Iterable`],module:`ESNext`,skipLibCheck:!0,moduleResolution:`bundler`,allowImportingTsExtensions:!0,resolveJsonModule:!0,isolatedModules:!0,moduleDetection:`force`,noEmit:!0,jsx:`react-jsx`,strict:!0,noUnusedLocals:!0,noUnusedParameters:!0,noFallthroughCasesInSwitch:!0},include:[`src`]},null,2)+`
7
- `}function ze(){return`import react from '@vitejs/plugin-react'
2
+ import{a as e,l as t,n,o as r,r as i,s as a,t as o,u as s}from"./config-DT-Cs7bC.mjs";import{i as c,n as l,r as u,t as d}from"./fs-B7O-fNID.mjs";import{r as f,t as p}from"./http-Dx1cFJ5S.mjs";import{a as m,c as h,i as g,l as _,n as v,o as y,r as b,s as x,t as ee}from"./lock-BwLjTQmQ.mjs";import{n as S,r as C,t as te}from"./peer-versions-DIPdOfWj.mjs";import{n as w,r as T,t as E}from"./args-CtmltI1S.mjs";import{createRequire as D}from"node:module";import{argv as O,stdin as k,stdout as A}from"node:process";import{pathToFileURL as ne}from"node:url";import{existsSync as j,readFileSync as M,readdirSync as N,writeFileSync as P}from"node:fs";import{basename as re,dirname as ie,join as F,resolve as I}from"node:path";import{spawnSync as ae}from"node:child_process";import{readFile as oe}from"node:fs/promises";import{asTemplateMeta as se,buildRegistry as ce,isTemplateItem as L,parseItem as R,parseLegacyRegistry as le,validateIndex as ue,validateItem as de,validateTemplate as fe}from"@cascivo/registry";import{createInterface as z}from"node:readline/promises";function B(t,n=process.cwd(),i={}){if(t.length===0)return!0;let o=i.pm??e(n),[s,c]=r(o,t,{dev:i.dev??!1,...i.floors?{floors:i.floors}:{},...i.pin?{pin:i.pin}:{}});return console.log(`Installing ${t.join(`, `)} with ${s}…`),ae(s,c,{cwd:n,stdio:`inherit`,shell:process.platform===`win32`}).status===0?!0:(console.error(`Failed to install: ${t.join(`, `)}`),console.error(`Install them yourself with: ${a(o,t,{dev:i.dev??!1})}`),!1)}const pe=/^([^/]+)\/([^/]+)\/([^#]+)(?:#(.+))?$/;function V(e,t=process.env){return e.replace(/\$\{([^}]+)\}/g,(e,n)=>{let r=t[n];if(r===void 0)throw Error(`Environment variable ${n} is not set`);return r})}function me(e,t=process.env){if(e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`./`)||e.startsWith(`/`))return{kind:`url`,name:e,raw:e};if(e.startsWith(`@`)){let t=e.indexOf(`/`,1);if(t===-1)throw Error(`Invalid namespace address: ${e} (expected @ns/name)`);return{kind:`namespace`,namespace:e.slice(0,t),name:e.slice(t+1),raw:e}}let n=e.includes(`#`)?e.slice(0,e.indexOf(`#`)):e,r=pe.exec(e);if(r&&!n.includes(`.`)&&n.split(`/`).length>=3){let[,t,n,i,a]=r;return{kind:`github`,name:`${t}/${n}/${i}`,ref:a??`main`,raw:e}}return{kind:`bare`,name:e,raw:e}}function he(e,t,n,r){let i=typeof n==`string`?n:n.url;if(!i.includes(`{name}`))throw Error(`Registry namespace "${e}" URL template must contain {name}: ${i}`);return V(i.replace(`{name}`,t),r)}async function ge(e,t,n=process.env,r){switch(e.kind){case`url`:return{url:e.name};case`bare`:return{url:`${t.registry.replace(/\/registry\.json$/,``).replace(/\/r$/,``)}/r/${e.name}.json`};case`github`:{let t=e.name.split(`/`),n=t[0],r=t[1],i=t.slice(2).join(`/`);return{url:`https://raw.githubusercontent.com/${n}/${r}/${e.ref??`main`}/r/${i}.json`}}case`namespace`:{let i=e.namespace,a=e.name;if(t.registries?.[i]){let e=t.registries[i],r=he(i,a,e,n),o=typeof e==`string`?void 0:e.headers,s=typeof e==`string`?void 0:e.params,c=o?Object.fromEntries(Object.entries(o).map(([e,t])=>[e,V(t,n)])):void 0,l=s?Object.fromEntries(Object.entries(s).map(([e,t])=>[e,V(t,n)])):void 0,u={url:r};return c&&(u.headers=c),l&&(u.params=l),u}if(r){let e=await r(i);if(e)return{url:he(i,a,e,n)}}if(i===`@cascivo`||i===`@cascade`)return{url:`${o}/r/${a}.json`};throw Error(`Unknown namespace "${i}". Add it to registries in cascivo.config.ts or check the directory at cascivo.com`)}}}async function _e(e,t,n=process.env,r){let i=new Set,a=[...e],o=[];for(;a.length>0;){let e=a.shift(),s=me(e,n),c=s.raw;if(i.has(c))continue;i.add(c);let{url:l,headers:u,params:d}=await ge(s,t,n,r),f={};u&&(f.headers=u),d&&(f.params=d);let m=R(await p(l,f),l),h={spec:e,addr:s,itemUrl:l,item:m,registryBase:l.replace(/\/[^/]+\.json$/,``)};u&&(h.headers=u),d&&(h.params=d),o.push(h);for(let e of m.registryDependencies??[])a.push(e)}return{items:o}}const ve=`${o}/r/registries.json`;function ye(e,t){if(typeof e!=`object`||!e)return null;let n=e.registries;if(!Array.isArray(n))return null;for(let e of n){if(typeof e!=`object`||!e)continue;let n=e;if(n.namespace!==t)continue;let r=n.registryUrl;return typeof r!=`string`||!/^https?:\/\//.test(r)?null:r}return null}async function be(e,t){try{let n;if(t){let e=await t(ve,{headers:{Accept:`application/json`}});if(!e.ok)throw Error(`HTTP ${e.status}`);n=await e.json()}else n=await p(ve);return ye(n,e)}catch(e){let t=e instanceof Error?e.message:String(e);return console.warn(`Could not reach cascivo.com directory: ${t}`),null}}var xe=s({LAYOUT_ALIASES:()=>H,NAME_NOTES:()=>Ee,add:()=>je,isThirdParty:()=>ke,resolveBareClosure:()=>De,resolveTemplateTarget:()=>Te});const Se=new Set([`react`,`react-dom`]);function Ce(e){try{let t=JSON.parse(M(F(e,`package.json`),`utf8`));return{...t.dependencies,...t.devDependencies}}catch{return{}}}function we(e,t){let n=Ce(e);n[`@cascivo/themes`]!==void 0||n[`@cascivo/tokens`]!==void 0||(console.log(`
3
+ Styling: cascivo components read --cascivo-* tokens, which this project does not import yet.`),console.log(` ${a(t,[`@cascivo/themes`])}`),console.log(` import '@cascivo/themes/all' // once, in your entry file`),console.log(` <html data-theme="light"> // or any container`))}function Te(e,t){return d(e,I(e,t))}const H={box:`layout/flex`,hstack:`layout/flex`,vstack:`layout/flex`,gap:`spacer`},Ee={stack:`Note: cascivo's Stack overlaps children into a card-pile (z-axis), not a vertical spacing layout. For vertical spacing use Flex direction="vertical" (cascivo add flex; aliases: vstack, hstack).`};function De(e,t){let n=t.map(e=>({name:e,requested:!0})),r=new Set,i=[],a=[];for(;n.length>0;){let{name:t,requested:o}=n.shift(),s=h(e,H[t.toLowerCase()]??t);if(!s){a.push(t);continue}if(r.has(s.name))continue;r.add(s.name);let c=_(s,t);i.push({entry:s,requested:o,...c?{viaAlias:c}:{}});for(let e of s.registryDependencies??[])n.push({name:e,requested:!1})}return{resolved:i,missing:a}}const Oe=/^https:\/\/(cascivo\.com|raw\.githubusercontent\.com\/cascivo\/cascivo)\//;function ke(e){return!Oe.test(e)}function Ae(e){return e.startsWith(`@`)||e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`./`)||e.startsWith(`/`)||e.split(`/`).length>=3}async function je(t,n,r={}){if(t.length===0){console.error(`Usage: cascivo add <component...>`);return}let i=r.cwd??process.cwd(),o=r.pm??e(i),s=t.filter(Ae),l=t.filter(e=>!Ae(e)),d=null;if(l.length>0){d=await y(n.registry);let e=new Set(d.templates.map(e=>e.toLowerCase())),t=l.filter(t=>e.has(t.toLowerCase()));t.length>0&&(l=l.filter(t=>!e.has(t.toLowerCase())),s.push(...t.map(e=>`@cascivo/${e.toLowerCase()}`)))}let p=await v(i)??ee();if(s.length>0){let e=await _e(s,n,process.env,be);if(r.dryRun){console.log(`Dry run — would install:`);for(let t of e.items){let e=L(t.item)?` [template]`:``;console.log(` ${t.spec} (${t.item.name}@${t.item.version})${e} from ${t.itemUrl}`);for(let e of t.item.files){let n=L(t.item)&&e.target?` → ${e.target}`:``;console.log(` ${e.url}${n}`)}t.item.registryDependencies?.length&&console.log(` components: ${t.item.registryDependencies.join(`, `)}`)}return}for(let{item:t,itemUrl:a,registryBase:s}of e.items){ke(a)&&console.log(`\nReview before use — files from non-directory registry: ${s}\n`+(t.files??[]).map(e=>` ${e.url}`).join(`
4
+ `));let e;try{e=await Me(t,n,i,{pm:o,...r.noInstall?{noInstall:!0}:{}})}catch(e){console.error(`Failed to install ${t.name}: ${e instanceof Error?e.message:e}`),process.exitCode=1;continue}p=g(p,t.name,{registry:s,version:t.version,installedAt:new Date().toISOString().slice(0,10),files:e})}if(await m(p,i),l.length===0){we(i,o);return}}if(l.length===0)return;d??=await y(n.registry);let _=new Set,S=n.registry.replace(/\/registry\.json$/,``).replace(/\/r$/,``);for(let e of l){let t=Ee[e.toLowerCase()];t&&console.log(t);let n=H[e.toLowerCase()];if(!n)continue;let r=h(d,n);r&&console.log(`"${e}" is not a cascivo component — installing ${r.name} (its ${e} primitive).`)}let{resolved:C,missing:w}=De(d,l);for(let e of w)console.error(`Component "${e}" not found in registry. Run "cascivo list".`);for(let{entry:e,requested:t,viaAlias:n}of C)!t||!n||console.log(`\n"${n}" is cascivo's "${e.name}" — installing that.`);let T=new Set;for(let{entry:e,requested:t}of C)!t||!e.install||T.has(e.install)||(T.add(e.install),console.log(`\n"${e.name}" ships in the ${e.install} npm package — no source is copied into your project. Updates come from your package manager, not \`cascivo update\`.`));for(let{entry:e,requested:t}of C){if(!t||!e.deprecated)continue;let{replacement:n,since:r,note:i}=e.deprecated;console.warn(`\n⚠ "${e.name}" is deprecated since ${r}. Use "${n}" instead:\n cascivo add ${n}\n`+(i?` ${i}\n`:``)+` Adding "${e.name}" anyway — it still works.\n`)}let E={};for(let{entry:e}of C)for(let[t,n]of Object.entries(e.peerVersions??{}))E[t]=n;let D=new Set,O=[];for(let{entry:e,requested:t}of C){if(e.install){let t=e.install;D.add(t),console.log(`"${e.name}" is distributed as the npm package ${t} — a runtime dependency, not copied source (updates come via your package manager).`),O.push(` import { ${e.meta.name} } from '${t}'`),e.styles&&O.push(` import '${e.styles}' // once, in your entry file`);continue}let r=e.name.includes(`/`)?e.name.split(`/`).pop():e.name,a={},o;try{o=await Promise.all(e.files.map(async e=>({url:e,content:await f(e)})))}catch(t){console.error(`Failed to install ${e.name}: ${t instanceof Error?t.message:t}`),process.exitCode=1;continue}for(let{url:e,content:t}of o){let o=u(n.outputDir,r,x(e),i);await c(o,t),a[o]=b(t)}for(let t of e.dependencies)Se.has(t)||_.add(t);p=g(p,e.name,{registry:S,version:e.version,installedAt:new Date().toISOString().slice(0,10),files:a});let s=t?``:` (dependency)`;console.log(`Added ${e.name} to ${n.outputDir}/${r}/${s}`)}if(D.size>0){let e=Ce(i),t=[...D].filter(t=>e[t]===void 0);r.dryRun?console.log(`Dry run — would install npm package(s): ${[...D].join(`, `)}`):t.length>0&&(r.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(o,t)}`):B(t,i,{pm:o})||(process.exitCode=1)),O.length>0&&console.log(`\nImport it:\n${O.join(`
5
+ `)}`)}if(_.size>0&&!r.dryRun&&(r.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(o,[..._])}`):B([..._],i,{pm:o})),Object.keys(E).length>0){let e=await te(i,E);for(let t of e)console.error(`\nWarning: ${t.pkg} ${t.installed?`${t.installed} is`:`is not`} installed, but the copied component source needs ${t.pkg} ${t.required}. Run: ${a(o,[`${t.pkg}@latest`])}`),process.exitCode=1}await m(p,i),we(i,o)}async function Me(t,n,r,i={}){let o={},s=new Set,l=L(t),d=t.name.includes(`/`)?t.name.split(`/`).pop():t.name,p=await Promise.all((t.files??[]).map(async e=>({file:e,content:await f(e.url)})));for(let{file:e,content:t}of p){let i=l&&e.target?Te(r,e.target):u(n.outputDir,d,x(e.url),r);await c(i,t),o[i]=b(t)}for(let e of t.dependencies??[])Se.has(e)||s.add(e);if(s.size>0&&(i.noInstall?console.log(`\nSkipped install (--no-install). Install with:\n ${a(i.pm??e(r),[...s])}`):B([...s],r,i.pm?{pm:i.pm}:{})),l){let e=t.files?.filter(e=>e.target).map(e=>e.target)??[];console.log(`Installed template ${t.name} (${e.length} files)`)}else console.log(`Added ${t.name} to ${n.outputDir}/${d}/`);return o}const Ne={"@cascivo/react":`1.3.1`,"@cascivo/themes":`1.0.0`,"@cascivo/charts":`1.3.1`,"@cascivo/icons":`1.1.0`,"@cascivo/eslint-config":`0.4.1`},Pe=`>=3.0.0`,U=Ne;function W(e){return e===`yarn`?`yarn`:`${e} install`}function G(e,t){return e===`npm`?`npm run ${t}`:`${e} ${t}`}const K=[`react-vite`,`astro`];function Fe(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`section`}function Ie(e){let t=e.trim().split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)||`Section`;return/^[0-9]/.test(t)?`Section${t}`:t}function q(e){let t=e.trim().split(/[^a-zA-Z0-9]+/).filter(e=>e!==``&&!/^\d+$/.test(e)&&!/^v\d+$/i.test(e)),n=[];for(let e of t){if(n.length>=3||n.length>0&&n.join(` `).length+1+e.length>24)break;n.push(e.charAt(0).toUpperCase()+e.slice(1))}return n.join(` `)||`App`}function Le(e){return e.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,`-`).replace(/^-+|-+$/g,``)||`cascivo-app`}function Re(e){let t=new Set,n=new Set,r=[];for(let i of e){let e=i.trim();if(!e)continue;let a=Fe(e),o=Ie(e),s=2;for(;t.has(a)||n.has(o);)a=`${Fe(e)}-${s}`,o=`${Ie(e)}${s}`,s++;t.add(a),n.add(o),r.push({key:a,label:e,component:o})}return r.length>0?r:[{key:`home`,label:`Home`,component:`Home`}]}function ze(e){let t={name:Le(e.name),private:!0,version:`0.0.0`,type:`module`,scripts:{dev:`vite`,build:`tsc && vite build`,preview:`vite preview`,typecheck:`tsc --noEmit`,lint:`eslint .`,format:`prettier --write .`,"format:check":`prettier --check .`},dependencies:{"@cascivo/react":U[`@cascivo/react`],"@cascivo/themes":U[`@cascivo/themes`],"@preact/signals-react":Pe,react:`^19.0.0`,"react-dom":`^19.0.0`},devDependencies:{"@cascivo/eslint-config":U[`@cascivo/eslint-config`],"@eslint/js":`^9.0.0`,"@types/react":`^19.0.0`,"@types/react-dom":`^19.0.0`,"@vitejs/plugin-react":`^5.0.0`,eslint:`^9.0.0`,"eslint-plugin-react-hooks":`^7.0.0`,prettier:`^3.0.0`,typescript:`^5.7.0`,"typescript-eslint":`^8.0.0`,vite:`^7.0.0`}};return JSON.stringify(t,null,2)+`
6
+ `}function Be(){return JSON.stringify({compilerOptions:{target:`ES2022`,useDefineForClassFields:!0,lib:[`ES2022`,`DOM`,`DOM.Iterable`],module:`ESNext`,skipLibCheck:!0,moduleResolution:`bundler`,allowImportingTsExtensions:!0,resolveJsonModule:!0,isolatedModules:!0,moduleDetection:`force`,noEmit:!0,jsx:`react-jsx`,strict:!0,noUnusedLocals:!0,noUnusedParameters:!0,noFallthroughCasesInSwitch:!0},include:[`src`]},null,2)+`
7
+ `}function Ve(){return`import react from '@vitejs/plugin-react'
8
8
  import { defineConfig } from 'vite'
9
9
 
10
10
  export default defineConfig({
11
11
  plugins: [react()],
12
12
  })
13
- `}function Be(e){return`<!doctype html>
13
+ `}function He(e){return`<!doctype html>
14
14
  <html lang="en" data-theme="${e.theme}">
15
15
  <head>
16
16
  <meta charset="UTF-8" />
17
17
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
18
- <title>${Pe(e.name)}</title>
18
+ <title>${q(e.name)}</title>
19
19
  <style>
20
20
  @layer vendor, cascivo.reset, cascivo.base, cascivo.tokens, cascivo.component,
21
21
  cascivo.platform, cascivo.theme, cascivo.blocks, cascivo.example, cascivo.override;
@@ -49,7 +49,7 @@ export default defineConfig({
49
49
  <script type="module" src="/src/main.tsx"><\/script>
50
50
  </body>
51
51
  </html>
52
- `}function Ve(){return`import React from 'react'
52
+ `}function Ue(){return`import React from 'react'
53
53
  import ReactDOM from 'react-dom/client'
54
54
  import App from './App'
55
55
 
@@ -61,8 +61,8 @@ if (root) {
61
61
  </React.StrictMode>,
62
62
  )
63
63
  }
64
- `}function He(){return`/// <reference types="vite/client" />
65
- `}function Ue(e){let t=e.map(e=>`import { ${e.component} } from './sections/${e.component}'`).join(`
64
+ `}function We(){return`/// <reference types="vite/client" />
65
+ `}function Ge(e){let t=e.map(e=>`import { ${e.component} } from './sections/${e.component}'`).join(`
66
66
  `),n=e.map(e=>`'${e.key}'`).join(` | `),r=e.map(e=>` {
67
67
  label: '${e.label.replace(/'/g,`\\'`)}',
68
68
  active: section.value === '${e.key}',
@@ -94,7 +94,7 @@ ${i}
94
94
  </Shell>
95
95
  )
96
96
  }
97
- `}function We(e){return`'use client'
97
+ `}function Ke(e){return`'use client'
98
98
  import { AppShell, ShellHeader, SideNav, type SideNavItem } from '@cascivo/react'
99
99
  import type { ReactNode } from 'react'
100
100
 
@@ -125,14 +125,14 @@ export interface ShellProps {
125
125
  export function Shell({ navItems, children }: ShellProps) {
126
126
  return (
127
127
  <AppShell
128
- header={<ShellHeader brand={{ name: '${Pe(e.name).replace(/'/g,`\\'`)}' }} />}
128
+ header={<ShellHeader brand={{ name: '${q(e.name).replace(/'/g,`\\'`)}' }} />}
129
129
  nav={<SideNav items={navItems} />}
130
130
  >
131
131
  {children}
132
132
  </AppShell>
133
133
  )
134
134
  }
135
- `}function Ge(e){return`import { Card, CardContent, CardHeader, CardTitle, Flex, Heading, Text } from '@cascivo/react'
135
+ `}function qe(e){return`import { Card, CardContent, CardHeader, CardTitle, Flex, Heading, Text } from '@cascivo/react'
136
136
 
137
137
  export function ${e.component}() {
138
138
  return (
@@ -158,7 +158,7 @@ export function ${e.component}() {
158
158
  </Flex>
159
159
  )
160
160
  }
161
- `}function Ke(){return`import js from '@eslint/js'
161
+ `}function Je(){return`import js from '@eslint/js'
162
162
  import tseslint from 'typescript-eslint'
163
163
  import reactHooks from 'eslint-plugin-react-hooks'
164
164
  import cascivo from '@cascivo/eslint-config'
@@ -180,17 +180,17 @@ export default [
180
180
  // see https://cascivo.com/docs/using-with-strict-eslint.md
181
181
  ...cascivo,
182
182
  ]
183
- `}function qe(){return JSON.stringify({semi:!1,singleQuote:!0,printWidth:100},null,2)+`
184
- `}function Je(){return`dist
183
+ `}function Ye(){return JSON.stringify({semi:!1,singleQuote:!0,printWidth:100},null,2)+`
184
+ `}function Xe(){return`dist
185
185
  node_modules
186
186
  # Vendored cascivo source is formatted upstream — reformatting it makes every
187
187
  # \`cascivo add\` update a merge conflict.
188
188
  src/components/ui/
189
- `}function Ye(){return`node_modules
189
+ `}function Ze(){return`node_modules
190
190
  dist
191
191
  *.local
192
192
  .DS_Store
193
- `}function Xe(e){let t=e.pm??`npm`;return`# ${e.name}
193
+ `}function Qe(e){let t=e.pm??`npm`;return`# ${e.name}
194
194
 
195
195
  A [cascivo](https://cascivo.com) app — Vite + React + TypeScript, pre-wired with
196
196
  the cascivo app shell, side navigation, and the \`${e.theme}\` theme.
@@ -198,8 +198,8 @@ the cascivo app shell, side navigation, and the \`${e.theme}\` theme.
198
198
  ## Develop
199
199
 
200
200
  \`\`\`sh
201
- ${Ae(t)}
202
- ${je(t,`dev`)}
201
+ ${W(t)}
202
+ ${G(t,`dev`)}
203
203
  \`\`\`
204
204
 
205
205
  ## Structure
@@ -232,7 +232,7 @@ setLinkComponent(({ href, ...rest }: LinkComponentProps) => <Link to={href ?? '#
232
232
  That one call makes \`SideNav\`, \`ShellHeader\` and \`Breadcrumb\` render real router links.
233
233
  Links you write in page content use \`<Link asChild>\` instead — two kinds of link, two
234
234
  mechanisms. Full recipe: https://cascivo.com/docs/using-with-a-router.md
235
- `}function Ze(e){return`# Agent instructions — ${e.name}
235
+ `}function $e(e){return`# Agent instructions — ${e.name}
236
236
 
237
237
  This is a [cascivo](https://cascivo.com) app. When generating or editing CSS, follow
238
238
  the **layer contract** — cascivo styles live in cascade layers, and layer order beats
@@ -299,13 +299,215 @@ The vocabulary types are on a subpath: \`import type { Tone } from '@cascivo/rea
299
299
  add \`@cascivo/core\` to this app's dependencies — it is transitive here.
300
300
 
301
301
  More: cascivo's machine-readable guide is at https://cascivo.com/llms.txt.
302
- `}function Qe(e){let t=Ie(e.sections);return[{path:`package.json`,contents:Le(e)},{path:`tsconfig.json`,contents:Re()},{path:`vite.config.ts`,contents:ze()},{path:`index.html`,contents:Be(e)},{path:`eslint.config.js`,contents:Ke()},{path:`.prettierrc`,contents:qe()},{path:`.prettierignore`,contents:Je()},{path:`.gitignore`,contents:Ye()},{path:`README.md`,contents:Xe(e)},{path:`AGENTS.md`,contents:Ze(e)},{path:`src/main.tsx`,contents:Ve()},{path:`src/vite-env.d.ts`,contents:He()},{path:`src/App.tsx`,contents:Ue(t)},{path:`src/Shell.tsx`,contents:We(e)},...t.map(e=>({path:`src/sections/${e.component}.tsx`,contents:Ge(e)}))]}const $e=[`Dashboard`,`Reports`,`Settings`];async function et(t,n=process.cwd()){let r=t.includes(`--yes`)||t.includes(`-y`),a=w(t,[`pm`,`package-manager`,`theme`,`sections`,`template`])[0],o=E(t,`theme`),s=E(t,`sections`),l=T(t);if(`error`in l){console.error(l.error),process.exitCode=1;return}let u=e(n,{preferLockfileOverUserAgent:!0,...l.pm?{override:l.pm}:{}}),d=!r&&k.isTTY?z({input:k,output:A}):null;try{let e=a;!e&&d&&(e=(await d.question(`Project name? [my-cascivo-app]: `)).trim()),e||=`my-cascivo-app`;let r=(o??``).toLowerCase();!i.includes(r)&&d&&(r=(await d.question(`Theme? (${i.join(`/`)}) [light]: `)).trim().toLowerCase());let l=i.includes(r)?r:`light`,f=s;!f&&d&&(f=(await d.question(`Nav sections? (comma-separated) [${$e.join(`, `)}]: `)).trim());let p=(f??``).split(`,`).map(e=>e.trim()).filter(Boolean),m={name:e,theme:l,sections:p.length>0?p:$e,pm:u},h=F(n,e);if(j(h)&&N(h).length>0){console.error(`Target directory "${e}" already exists and is not empty.`),process.exitCode=1;return}let g=Qe(m);for(let e of g)await c(F(h,e.path),e.contents);console.log(`\nCreated ${e} with the ${l} theme (${g.length} files).`);let _=E(t,`template`);if(_){let{add:e}=await Promise.resolve().then(()=>ve),{loadConfig:t}=await import(`./config-DT-Cs7bC.mjs`).then(e=>e.i);console.log(`\nInstalling template "${_}"…`),await e([_],await t(),{cwd:h,pm:u})}console.log(`
303
- Next steps:`),console.log(` cd ${e}`),console.log(` ${Ae(u)}`),console.log(` ${je(u,`dev`)}`),console.log(`
304
- Good to know:`),console.log(` No cascivo.config.ts is written — this app uses the prebuilt @cascivo/react`),console.log(" packages and never copies source. `cascivo add <component>` writes the"),console.log(` config itself the first time you vendor a component.`),console.log(`
305
- Adding a router? Keep src/Shell.tsx, delete src/App.tsx + src/sections/,`),console.log(` and register your Link once with setLinkComponent — see`),console.log(` https://cascivo.com/docs/using-with-a-router.md`)}finally{d?.close()}}var tt=s({checkDuplicateCore:()=>ft,checkFormatterIgnore:()=>gt,checkProjectDependencies:()=>ut,checkSignalsCompat:()=>pt,checkSsrConfig:()=>_t,detectInstallPath:()=>st,runDoctor:()=>bt,stripCommentsAndStrings:()=>yt});const nt=[`@cascivo/core`,`@cascivo/tokens`,`@cascivo/themes`,`@preact/signals-react`],rt=[`@cascivo/react`,`@cascivo/themes`,`@preact/signals-react`],it={"@cascivo/core":`AI-RULES.md: never add @cascivo/core to a prebuilt-path app — it is transitive, and everything is re-exported from @cascivo/react`,"@cascivo/tokens":`GETTING-STARTED.md: @cascivo/tokens comes with @cascivo/themes as a direct dependency — never install it by hand`},at=[`@cascivo/i18n`,`@cascivo/charts`],ot=[`cascivo.config.ts`,`cascivo.config.js`,`cascivo.config.mjs`];function st(e){let t={},n=!0;try{let n=JSON.parse(M(F(e,`package.json`),`utf8`));t={...n.dependencies,...n.devDependencies}}catch{n=!1}if(!n)return`unknown`;let r=t[`@cascivo/react`]!==void 0,i=ct(e);return r&&i?`hybrid`:r?`prebuilt`:i?`copied`:`unknown`}function ct(e){for(let t of lt(e)){let n=F(e,t);if(j(n))try{if(N(n).some(e=>e.endsWith(`.tsx`)))return!0}catch{}}return!1}function lt(e){let t=new Set([`src/components/ui`]);for(let n of ot){let r=F(e,n);if(j(r))try{let e=/outputDir\s*:\s*['"]([^'"]+)['"]/.exec(M(r,`utf8`))?.[1];e!==void 0&&t.add(e)}catch{}}return[...t]}function ut(t){let n={};try{let e=JSON.parse(M(F(t,`package.json`),`utf8`));n={...e.dependencies,...e.devDependencies}}catch{return[]}let r=st(t);if(r===`unknown`)return[];let i=e(t),o=[],s=r===`prebuilt`?rt:nt;for(let e of s)n[e]===void 0&&o.push({package:e,required:!0,hint:`detected ${r} install path — ${a(i,[e])}`});if(r===`prebuilt`)for(let[e,t]of Object.entries(it))n[e]!==void 0&&o.push({package:e,required:!0,kind:`forbidden`,hint:t});for(let e of at)n[e]===void 0&&o.push({package:e,required:!1,hint:a(i,[e])});return o}const dt=[`@cascivo/react`,`@cascivo/charts`,`@cascivo/flow`,`@cascivo/editor`];async function ft(e){let t=await S(e,`@cascivo/core`),n=[];for(let r of dt){let i=F(e,`node_modules`,r);if(!j(i))continue;let a=await S(i,`@cascivo/core`);a!==null&&a!==t&&n.push(`${r} → ${a}`)}return n.length===0?null:{root:t,nested:n,hint:`Align the @cascivo/* versions (they are released together — see breaking-changes.json) and reinstall. Two copies of @cascivo/core means two signal registries: writes through one are invisible to components subscribed through the other, with no error.`}}async function pt(t){let[n,r]=await Promise.all([S(t,`@preact/signals-react`),S(t,`react`)]);if(n===null)return null;let i;try{i=C(n,`3.0.0`)<0}catch{return null}if(!i)return null;let o=a(e(t),[`@preact/signals-react@^3`]),s=null;if(r!==null){let e=/^(\d+)\./.exec(r.trim());s=e?Number(e[1]):null}return s!==null&&s>=19?{severity:`error`,detail:`@preact/signals-react ${n} cannot run on React ${r} — React 19 removed an internal signals 2.x imports, so it fails at module load. Upgrade to signals-react 3.x.`,hint:o}:{severity:`warning`,detail:`@preact/signals-react ${n} is below the required 3.x floor. It works on React 18 today but breaks the moment you move to React 19; upgrade now.`,hint:o}}const mt=[`@tanstack/react-start`,`vite-ssr`,`@remix-run/dev`],ht=[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.mts`];function gt(e,t){let n=[{configs:[`.prettierrc`,`.prettierrc.json`,`.prettierrc.js`,`prettier.config.js`],ignore:`.prettierignore`},{configs:[`.oxfmtrc`,`.oxfmtrc.json`],ignore:`.oxfmtignore`}],r=t.replace(/\/+$/,``);for(let{configs:t,ignore:i}of n){if(!t.some(t=>j(F(e,t))))continue;let n=``;try{n=M(F(e,i),`utf8`)}catch{}if(!n.split(`
306
- `).some(e=>e.trim().replace(/\/+$/,``)===r))return`"${r}/" is not excluded from your formatter. Running it will rewrite code you own, and \`cascivo update\` will then report drift on files you never edited. Add "${r}/" to ${i}.`}return null}function _t(e){let t={};try{let n=JSON.parse(M(F(e,`package.json`),`utf8`));t={...n.dependencies,...n.devDependencies}}catch{return null}let n=mt.find(e=>t[e]!==void 0);if(n===void 0)return null;for(let t of ht){let n=F(e,t);if(!j(n))continue;let r=M(n,`utf8`);if(/noExternal/.test(r)&&/@cascivo/.test(r)||/cascivoSsr/.test(r))return null}return`${n} is a Vite SSR framework, but no vite config marks the cascivo packages ssr.noExternal — an unconfigured SSR build crashes with \`Unknown file extension ".css"\`. Add \`ssr: { noExternal: [/^@cascivo\\//] }\` (or the cascivoSsr() plugin from @cascivo/vite-plugin). Recipe: https://cascivo.com/docs/using-with-vite-ssr.md`}const vt=[`useState`,`useEffect`,`useLayoutEffect`,`useContext`,`useReducer`];function yt(e){let t=``,n=0,r=e.length;for(;n<r;){let i=e[n],a=e[n+1];if(i===`/`&&a===`/`)for(;n<r&&e[n]!==`
307
- `;)n++;else if(i===`/`&&a===`*`){for(n+=2;n<r&&!(e[n]===`*`&&e[n+1]===`/`);)n++;n+=2}else if(i===`'`||i===`"`){for(n++;n<r&&e[n]!==i;)e[n]===`\\`&&n++,n++;n++,t+=i+i}else if(i==="`"){for(n++;n<r&&e[n]!=="`";)e[n]===`\\`&&n++,n++;n++,t+="``"}else t+=i,n++}return t}async function bt(e){let t=[],n=F(e,`packages`,`components`,`src`);if(!j(n))return{violations:[],passed:!0};let r=N(n,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name),i=F(e,`packages`,`react`,`src`,`index.ts`),a=j(i)?M(i,`utf8`):``;for(let e of r){let r=F(n,e,`${e}.tsx`);if(!j(r))continue;let i=M(r,`utf8`),o=yt(i);for(let n of vt)RegExp(`\\b${n}\\b`).test(o)&&t.push({file:r,rule:`no-react-hooks`,detail:`Banned hook '${n}' in ${e}.tsx`});/aria-label="[A-Z]/.test(i)&&t.push({file:r,rule:`no-hardcoded-strings`,detail:`Hardcoded aria-label in ${e}.tsx — use t(builtin.*)`}),RegExp(`from.*components/src/${e}`).test(a)||t.push({file:r,rule:`missing-react-export`,detail:`${e} not exported from @cascivo/react`})}return{violations:t,passed:t.length===0}}function xt(e){return typeof e==`object`&&!!e&&`$t`in e}function St(e){return typeof e==`string`?`'${e.replace(/'/g,`\\'`)}'`:String(e)}function Ct(e){return typeof e==`string`?`"${e.replace(/"/g,`\\"`)}"`:typeof e==`number`||typeof e==`boolean`?`{${e}}`:e===null?`{null}`:xt(e)?`{"${e.$t}"} {/* i18n: ${e.$t} */}`:`{${JSON.stringify(e)}}`}function wt(e,t,n,r){return e===void 0?``:typeof e==`string`?e:xt(e)?`{/* i18n: ${e.$t} */}`:Array.isArray(e)?e.map(e=>Tt(e,t+` `,n,r)).join(`
308
- `):``}function Tt(e,t,n,r){let i=e.component;r.add(i);let a=[];if(e.props)for(let[t,n]of Object.entries(e.props))a.push(`${t}=${Ct(n)}`);if(e.bind)for(let[t,n]of Object.entries(e.bind))n.startsWith(`$state.`)?a.push(`${t}={${n.slice(7)}.value}`):a.push(`${t}={data.${n.replace(/^\$data\./,``)}}`);if(e.events)for(let[t,n]of Object.entries(e.events))if(n.startsWith(`$state.set.`)){let e=n.slice(11);a.push(`${t}={(e) => (${e}.value = coerceValue(e))}`)}else if(n.startsWith(`$state.toggle.`)){let e=n.slice(14);a.push(`${t}={() => (${e}.value = !${e}.value)}`)}else a.push(`${t}={actions.${n.replace(/^\$actions\./,``)}}`);let o=a.length>0?` `+a.join(` `):``,s=e.children===void 0?void 0:wt(e.children,t,[],r);return s!==void 0&&s!==``?`${t}<${i}${o}>\n${t} ${s}\n${t}</${i}>`:`${t}<${i}${o} />`}function Et(e){let t=[],n=[];function r(e){if(e.bind)for(let n of Object.values(e.bind)){if(n.startsWith(`$state.`))continue;let e=n.replace(/^\$data\./,``);t.includes(e)||t.push(e)}if(e.events)for(let t of Object.values(e.events)){if(t.startsWith(`$state.`))continue;let e=t.replace(/^\$actions\./,``);n.includes(e)||n.push(e)}Array.isArray(e.children)&&e.children.forEach(r)}return e.forEach(r),{boundProps:t,actionProps:n}}function Dt(e){let t=e=>e.events&&Object.values(e.events).some(e=>e.startsWith(`$state.set.`))?!0:Array.isArray(e.children)?e.children.some(t):!1;return e.some(t)}function Ot(e,t,n){let r=new Set,i=Object.values(e.view.regions).flat(),{boundProps:a,actionProps:o}=Et(i),s=Object.entries(e.state??{}),c=s.length>0,l=Dt(i),u=Object.entries(e.view.regions).map(([e,t])=>` <div className="region-${e}">\n${t.map(e=>Tt(e,` `,[],r)).join(`
302
+ `}function J(e,t){return t===0?`/`:`/${e.key}`}function et(e,t){return t===0?`index.astro`:`${e.key}.astro`}function tt(e){let t={name:Le(e.name),private:!0,version:`0.0.0`,type:`module`,scripts:{dev:`astro dev`,build:`astro build`,preview:`astro preview`,typecheck:`astro check`,lint:`eslint .`,format:`prettier --write .`,"format:check":`prettier --check .`},dependencies:{"@astrojs/react":`^5.0.0`,"@cascivo/react":U[`@cascivo/react`],"@cascivo/themes":U[`@cascivo/themes`],"@preact/signals-react":Pe,astro:`^7.0.0`,react:`^19.0.0`,"react-dom":`^19.0.0`},devDependencies:{"@astrojs/check":`^0.9.0`,"@cascivo/eslint-config":U[`@cascivo/eslint-config`],"@eslint/js":`^9.0.0`,"@types/react":`^19.0.0`,"@types/react-dom":`^19.0.0`,eslint:`^9.0.0`,"eslint-plugin-react-hooks":`^7.0.0`,prettier:`^3.0.0`,typescript:`^5.7.0`,"typescript-eslint":`^8.0.0`}};return JSON.stringify(t,null,2)+`
303
+ `}function nt(){return`// @ts-check
304
+ import { defineConfig } from 'astro/config'
305
+ import react from '@astrojs/react'
306
+
307
+ export default defineConfig({
308
+ integrations: [react()],
309
+ vite: {
310
+ resolve: {
311
+ // REQUIRED, and the single least obvious line in this app.
312
+ //
313
+ // Vite externalizes node_modules packages in its server build, so an externalized
314
+ // @cascivo/react is imported by Node at runtime and its module graph is never walked
315
+ // — and Astro collects a page's CSS by walking that graph. Without this, SSR'd
316
+ // islands (client:load, client:visible) render with correct class names and no rules
317
+ // anywhere in the output. Nothing warns; it reads as a theming problem.
318
+ //
319
+ // It must be \`resolve.noExternal\`, NOT \`ssr.noExternal\`: Astro prerenders static
320
+ // routes in its own Vite environment, which \`ssr.*\` does not reach.
321
+ // https://cascivo.com/docs/using-with-astro.md
322
+ noExternal: [/^@cascivo\\//],
323
+ },
324
+ },
325
+ })
326
+ `}function rt(){return JSON.stringify({extends:`astro/tsconfigs/strict`,include:[`.astro/types.d.ts`,`**/*`],exclude:[`dist`],compilerOptions:{jsx:`react-jsx`}},null,2)+`
327
+ `}function it(){return`/* Cascade layer order. Must load before any cascivo CSS — see the note in
328
+ src/layouts/Layout.astro. Later layers beat earlier ones regardless of specificity.
329
+
330
+ cascivo.example is this app's own slot: above the component and blocks layers so your
331
+ page styles win, below cascivo.override which stays free for one-off hotfixes.
332
+ Third-party CSS goes in vendor so it cannot beat cascivo:
333
+ @import url('some-lib/styles.css') layer(vendor);
334
+ See https://cascivo.com/docs/third-party-css.md */
335
+ @layer vendor, cascivo.reset, cascivo.base, cascivo.tokens, cascivo.component,
336
+ cascivo.platform, cascivo.theme, cascivo.blocks, cascivo.example, cascivo.override;
337
+
338
+ @layer cascivo.reset {
339
+ *,
340
+ *::before,
341
+ *::after {
342
+ box-sizing: border-box;
343
+ margin: 0;
344
+ padding: 0;
345
+ }
346
+ }
347
+
348
+ @layer cascivo.base {
349
+ html,
350
+ body {
351
+ block-size: 100%;
352
+ }
353
+ }
354
+ `}function at(e){return`---
355
+ // Import order matters: the layer statement must be established before any cascivo CSS.
356
+ import '../styles/layers.css'
357
+ import '@cascivo/themes/${e.theme}.css'
358
+
359
+ // No '@cascivo/react/styles.css'. Each component brings its own CSS through the module
360
+ // graph, so you ship only what your pages use. Import the aggregate ONLY if you drop the
361
+ // bundler entirely. The theme import above is always required — themes are never automatic.
362
+
363
+ interface Props {
364
+ title: string
365
+ }
366
+
367
+ const { title } = Astro.props
368
+ ---
369
+
370
+ <!doctype html>
371
+ <html lang="en" data-theme="${e.theme}">
372
+ <head>
373
+ <meta charset="UTF-8" />
374
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
375
+ <title>{title} · ${q(e.name)}</title>
376
+ </head>
377
+ <body>
378
+ <slot />
379
+ </body>
380
+ </html>
381
+ `}function ot(e,t){return`import { AppShell, ShellHeader, SideNav, type SideNavItem } from '@cascivo/react'
382
+ import type { ReactNode } from 'react'
383
+
384
+ const NAV: { label: string; href: string }[] = [
385
+ ${t.map((e,t)=>` { label: '${e.label.replace(/'/g,`\\'`)}', href: '${J(e,t)}' },`).join(`
386
+ `)}
387
+ ]
388
+
389
+ export interface ShellProps {
390
+ /** Current route, e.g. \`Astro.url.pathname\`. Marks the matching nav item active. */
391
+ activePath: string
392
+ children: ReactNode
393
+ }
394
+
395
+ /**
396
+ * Header + side nav + a content slot.
397
+ *
398
+ * Nav items carry \`href\`, so navigation is a real page load and Astro's router handles
399
+ * it — there is no client router to register and no \`setLinkComponent\` call to make.
400
+ */
401
+ export function Shell({ activePath, children }: ShellProps) {
402
+ const items: SideNavItem[] = NAV.map((item) => ({
403
+ ...item,
404
+ active: item.href === activePath,
405
+ }))
406
+
407
+ return (
408
+ <AppShell
409
+ header={<ShellHeader brand={{ name: '${q(e.name).replace(/'/g,`\\'`)}' }} />}
410
+ nav={<SideNav items={items} />}
411
+ >
412
+ {children}
413
+ </AppShell>
414
+ )
415
+ }
416
+ `}function st(e){return`import { Card, CardContent, CardHeader, CardTitle, Flex, Heading, Text } from '@cascivo/react'
417
+
418
+ export function ${e.component}() {
419
+ return (
420
+ <Flex gap={6}>
421
+ <Flex gap={2}>
422
+ <Heading level={1}>${e.label}</Heading>
423
+ <Text muted>
424
+ Edit <code>src/components/${e.component}.tsx</code> to build out this page.
425
+ </Text>
426
+ </Flex>
427
+
428
+ <Card>
429
+ <CardHeader>
430
+ <CardTitle>Get started</CardTitle>
431
+ </CardHeader>
432
+ <CardContent>
433
+ <Text>
434
+ This page is server-rendered — no JavaScript ships for it. Add components with{' '}
435
+ <code>npx cascivo add &lt;component&gt;</code>.
436
+ </Text>
437
+ </CardContent>
438
+ </Card>
439
+ </Flex>
440
+ )
441
+ }
442
+ `}function ct(e,t){return`---
443
+ import Layout from '../layouts/Layout.astro'
444
+ import { Shell } from '../components/Shell'
445
+ import { ${e.component} } from '../components/${e.component}'
446
+ ---
447
+
448
+ <Layout title="${e.label}">
449
+ {/* client:load hydrates the shell for its mobile nav drawer. The section below stays
450
+ server-rendered HTML — it is slotted in as children and ships no JS. */}
451
+ <Shell client:load activePath="${J(e,t)}">
452
+ <${e.component} />
453
+ </Shell>
454
+ </Layout>
455
+ `}function lt(){return`node_modules
456
+ dist
457
+ .astro
458
+ *.local
459
+ .DS_Store
460
+ `}function ut(e,t){let n=e.pm??`npm`,r=t.map((e,t)=>`- \`${J(e,t)}\` — \`src/pages/${et(e,t)}\``).join(`
461
+ `);return`# ${e.name}
462
+
463
+ A [cascivo](https://cascivo.com) app — Astro + React islands + TypeScript, pre-wired with
464
+ the cascivo app shell, side navigation, and the \`${e.theme}\` theme.
465
+
466
+ ## Develop
467
+
468
+ \`\`\`sh
469
+ ${W(n)}
470
+ ${G(n,`dev`)}
471
+ \`\`\`
472
+
473
+ ## Routes
474
+
475
+ ${r}
476
+
477
+ Add a page by dropping a new \`.astro\` file in \`src/pages/\` — Astro routes it by filename.
478
+ Add it to \`NAV\` in \`src/components/Shell.tsx\` to get a nav entry.
479
+
480
+ ## What hydrates, and what doesn't
481
+
482
+ Only \`Shell\` carries a client directive (\`client:load\`), because its nav drawer is
483
+ interactive on small screens. Everything inside it is slotted in as children and stays
484
+ server-rendered HTML, so a page ships the shell's JavaScript and nothing else.
485
+
486
+ Need a section to be interactive? Give it a directive at the call site in the page:
487
+
488
+ \`\`\`astro
489
+ <${t[0].component} client:visible />
490
+ \`\`\`
491
+
492
+ A component that reads \`signal.value\` during render must also call \`useSignals()\` from
493
+ \`@cascivo/react\` as its first statement — Astro applies no signals transform.
494
+
495
+ ## Styling
496
+
497
+ \`src/styles/layers.css\` declares the cascade layer order and this app's own
498
+ \`cascivo.example\` slot. It is imported **before** the theme in \`src/layouts/Layout.astro\`,
499
+ and that order matters: layers take their position from first appearance, so a statement
500
+ loaded after the theme cannot reorder anything.
501
+
502
+ Add more components with \`npx cascivo add <component>\`.
503
+ `}function dt(e){let t=Re(e.sections);return e.framework===`astro`?ft(e,t):[{path:`package.json`,contents:ze(e)},{path:`tsconfig.json`,contents:Be()},{path:`vite.config.ts`,contents:Ve()},{path:`index.html`,contents:He(e)},{path:`eslint.config.js`,contents:Je()},{path:`.prettierrc`,contents:Ye()},{path:`.prettierignore`,contents:Xe()},{path:`.gitignore`,contents:Ze()},{path:`README.md`,contents:Qe(e)},{path:`AGENTS.md`,contents:$e(e)},{path:`src/main.tsx`,contents:Ue()},{path:`src/vite-env.d.ts`,contents:We()},{path:`src/App.tsx`,contents:Ge(t)},{path:`src/Shell.tsx`,contents:Ke(e)},...t.map(e=>({path:`src/sections/${e.component}.tsx`,contents:qe(e)}))]}function ft(e,t){return[{path:`package.json`,contents:tt(e)},{path:`tsconfig.json`,contents:rt()},{path:`astro.config.mjs`,contents:nt()},{path:`eslint.config.js`,contents:Je()},{path:`.prettierrc`,contents:Ye()},{path:`.prettierignore`,contents:Xe()},{path:`.gitignore`,contents:lt()},{path:`README.md`,contents:ut(e,t)},{path:`AGENTS.md`,contents:$e(e)},{path:`src/styles/layers.css`,contents:it()},{path:`src/layouts/Layout.astro`,contents:at(e)},{path:`src/components/Shell.tsx`,contents:ot(e,t)},...t.map((e,t)=>({path:`src/pages/${et(e,t)}`,contents:ct(e,t)})),...t.map(e=>({path:`src/components/${e.component}.tsx`,contents:st(e)}))]}const pt=[`Dashboard`,`Reports`,`Settings`];async function mt(t,n=process.cwd()){let r=t.includes(`--yes`)||t.includes(`-y`),a=w(t,[`pm`,`package-manager`,`theme`,`sections`,`template`,`framework`])[0],o=E(t,`theme`),s=E(t,`sections`),l=(E(t,`framework`)??``).toLowerCase();if(l&&!K.includes(l)){console.error(`Unknown framework "${l}". Expected one of: ${K.join(`, `)}.`),process.exitCode=1;return}let u=T(t);if(`error`in u){console.error(u.error),process.exitCode=1;return}let d=e(n,{preferLockfileOverUserAgent:!0,...u.pm?{override:u.pm}:{}}),f=!r&&k.isTTY?z({input:k,output:A}):null;try{let e=a;!e&&f&&(e=(await f.question(`Project name? [my-cascivo-app]: `)).trim()),e||=`my-cascivo-app`;let r=(o??``).toLowerCase();!i.includes(r)&&f&&(r=(await f.question(`Theme? (${i.join(`/`)}) [light]: `)).trim().toLowerCase());let u=i.includes(r)?r:`light`,p=s;!p&&f&&(p=(await f.question(`Nav sections? (comma-separated) [${pt.join(`, `)}]: `)).trim());let m=(p??``).split(`,`).map(e=>e.trim()).filter(Boolean),h=l;!h&&f&&(h=(await f.question(`Framework? (${K.join(`/`)}) [react-vite]: `)).trim().toLowerCase());let g=K.includes(h)?h:`react-vite`,_={name:e,framework:g,theme:u,sections:m.length>0?m:pt,pm:d},v=F(n,e);if(j(v)&&N(v).length>0){console.error(`Target directory "${e}" already exists and is not empty.`),process.exitCode=1;return}let y=dt(_);for(let e of y)await c(F(v,e.path),e.contents);console.log(`\nCreated ${e} (${g}) with the ${u} theme (${y.length} files).`);let b=E(t,`template`);if(b){let{add:e}=await Promise.resolve().then(()=>xe),{loadConfig:t}=await import(`./config-DT-Cs7bC.mjs`).then(e=>e.i);console.log(`\nInstalling template "${b}"…`),await e([b],await t(),{cwd:v,pm:d})}console.log(`
504
+ Next steps:`),console.log(` cd ${e}`),console.log(` ${W(d)}`),console.log(` ${G(d,`dev`)}`),console.log(`
505
+ Good to know:`),console.log(` No cascivo.config.ts is written — this app uses the prebuilt @cascivo/react`),console.log(" packages and never copies source. `cascivo add <component>` writes the"),console.log(` config itself the first time you vendor a component.`),g===`astro`?(console.log(`
506
+ Pages are real Astro routes — no client router to add. Only src/`),console.log(` components/Shell.tsx hydrates (client:load, for the mobile nav drawer);`),console.log(` page content is server-rendered and ships no JS. See`),console.log(` https://cascivo.com/docs/using-with-astro.md`)):(console.log(`
507
+ Adding a router? Keep src/Shell.tsx, delete src/App.tsx + src/sections/,`),console.log(` and register your Link once with setLinkComponent — see`),console.log(` https://cascivo.com/docs/using-with-a-router.md`))}finally{f?.close()}}var ht=s({checkDuplicateCore:()=>Et,checkFormatterIgnore:()=>At,checkProjectDependencies:()=>wt,checkSignalsCompat:()=>Dt,checkSsrConfig:()=>jt,detectInstallPath:()=>xt,runDoctor:()=>Pt,stripCommentsAndStrings:()=>Nt});const gt=[`@cascivo/core`,`@cascivo/tokens`,`@cascivo/themes`,`@preact/signals-react`],_t=[`@cascivo/react`,`@cascivo/themes`,`@preact/signals-react`],vt={"@cascivo/core":`AI-RULES.md: never add @cascivo/core to a prebuilt-path app — it is transitive, and everything is re-exported from @cascivo/react`,"@cascivo/tokens":`GETTING-STARTED.md: @cascivo/tokens comes with @cascivo/themes as a direct dependency — never install it by hand`},yt=[`@cascivo/i18n`,`@cascivo/charts`],bt=[`cascivo.config.ts`,`cascivo.config.js`,`cascivo.config.mjs`];function xt(e){let t={},n=!0;try{let n=JSON.parse(M(F(e,`package.json`),`utf8`));t={...n.dependencies,...n.devDependencies}}catch{n=!1}if(!n)return`unknown`;let r=t[`@cascivo/react`]!==void 0,i=St(e);return r&&i?`hybrid`:r?`prebuilt`:i?`copied`:`unknown`}function St(e){for(let t of Ct(e)){let n=F(e,t);if(j(n))try{if(N(n).some(e=>e.endsWith(`.tsx`)))return!0}catch{}}return!1}function Ct(e){let t=new Set([`src/components/ui`]);for(let n of bt){let r=F(e,n);if(j(r))try{let e=/outputDir\s*:\s*['"]([^'"]+)['"]/.exec(M(r,`utf8`))?.[1];e!==void 0&&t.add(e)}catch{}}return[...t]}function wt(t){let n={};try{let e=JSON.parse(M(F(t,`package.json`),`utf8`));n={...e.dependencies,...e.devDependencies}}catch{return[]}let r=xt(t);if(r===`unknown`)return[];let i=e(t),o=[],s=r===`prebuilt`?_t:gt;for(let e of s)n[e]===void 0&&o.push({package:e,required:!0,hint:`detected ${r} install path — ${a(i,[e])}`});if(r===`prebuilt`)for(let[e,t]of Object.entries(vt))n[e]!==void 0&&o.push({package:e,required:!0,kind:`forbidden`,hint:t});for(let e of yt)n[e]===void 0&&o.push({package:e,required:!1,hint:a(i,[e])});return o}const Tt=[`@cascivo/react`,`@cascivo/charts`,`@cascivo/flow`,`@cascivo/editor`];async function Et(e){let t=await S(e,`@cascivo/core`),n=[];for(let r of Tt){let i=F(e,`node_modules`,r);if(!j(i))continue;let a=await S(i,`@cascivo/core`);a!==null&&a!==t&&n.push(`${r} → ${a}`)}return n.length===0?null:{root:t,nested:n,hint:`Align the @cascivo/* versions (they are released together — see breaking-changes.json) and reinstall. Two copies of @cascivo/core means two signal registries: writes through one are invisible to components subscribed through the other, with no error.`}}async function Dt(t){let[n,r]=await Promise.all([S(t,`@preact/signals-react`),S(t,`react`)]);if(n===null)return null;let i;try{i=C(n,`3.0.0`)<0}catch{return null}if(!i)return null;let o=a(e(t),[`@preact/signals-react@^3`]),s=null;if(r!==null){let e=/^(\d+)\./.exec(r.trim());s=e?Number(e[1]):null}return s!==null&&s>=19?{severity:`error`,detail:`@preact/signals-react ${n} cannot run on React ${r} — React 19 removed an internal signals 2.x imports, so it fails at module load. Upgrade to signals-react 3.x.`,hint:o}:{severity:`warning`,detail:`@preact/signals-react ${n} is below the required 3.x floor. It works on React 18 today but breaks the moment you move to React 19; upgrade now.`,hint:o}}const Ot=[`@tanstack/react-start`,`vite-ssr`,`@remix-run/dev`],kt=[`vite.config.ts`,`vite.config.js`,`vite.config.mjs`,`vite.config.mts`];function At(e,t){let n=[{configs:[`.prettierrc`,`.prettierrc.json`,`.prettierrc.js`,`prettier.config.js`],ignore:`.prettierignore`},{configs:[`.oxfmtrc`,`.oxfmtrc.json`],ignore:`.oxfmtignore`}],r=t.replace(/\/+$/,``);for(let{configs:t,ignore:i}of n){if(!t.some(t=>j(F(e,t))))continue;let n=``;try{n=M(F(e,i),`utf8`)}catch{}if(!n.split(`
508
+ `).some(e=>e.trim().replace(/\/+$/,``)===r))return`"${r}/" is not excluded from your formatter. Running it will rewrite code you own, and \`cascivo update\` will then report drift on files you never edited. Add "${r}/" to ${i}.`}return null}function jt(e){let t={};try{let n=JSON.parse(M(F(e,`package.json`),`utf8`));t={...n.dependencies,...n.devDependencies}}catch{return null}let n=Ot.find(e=>t[e]!==void 0);if(n===void 0)return null;for(let t of kt){let n=F(e,t);if(!j(n))continue;let r=M(n,`utf8`);if(/noExternal/.test(r)&&/@cascivo/.test(r)||/cascivoSsr/.test(r))return null}return`${n} is a Vite SSR framework, but no vite config marks the cascivo packages ssr.noExternal — an unconfigured SSR build crashes with \`Unknown file extension ".css"\`. Add \`ssr: { noExternal: [/^@cascivo\\//] }\` (or the cascivoSsr() plugin from @cascivo/vite-plugin). Recipe: https://cascivo.com/docs/using-with-vite-ssr.md`}const Mt=[`useState`,`useEffect`,`useLayoutEffect`,`useContext`,`useReducer`];function Nt(e){let t=``,n=0,r=e.length;for(;n<r;){let i=e[n],a=e[n+1];if(i===`/`&&a===`/`)for(;n<r&&e[n]!==`
509
+ `;)n++;else if(i===`/`&&a===`*`){for(n+=2;n<r&&!(e[n]===`*`&&e[n+1]===`/`);)n++;n+=2}else if(i===`'`||i===`"`){for(n++;n<r&&e[n]!==i;)e[n]===`\\`&&n++,n++;n++,t+=i+i}else if(i==="`"){for(n++;n<r&&e[n]!=="`";)e[n]===`\\`&&n++,n++;n++,t+="``"}else t+=i,n++}return t}async function Pt(e){let t=[],n=F(e,`packages`,`components`,`src`);if(!j(n))return{violations:[],passed:!0};let r=N(n,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name),i=F(e,`packages`,`react`,`src`,`index.ts`),a=j(i)?M(i,`utf8`):``;for(let e of r){let r=F(n,e,`${e}.tsx`);if(!j(r))continue;let i=M(r,`utf8`),o=Nt(i);for(let n of Mt)RegExp(`\\b${n}\\b`).test(o)&&t.push({file:r,rule:`no-react-hooks`,detail:`Banned hook '${n}' in ${e}.tsx`});/aria-label="[A-Z]/.test(i)&&t.push({file:r,rule:`no-hardcoded-strings`,detail:`Hardcoded aria-label in ${e}.tsx — use t(builtin.*)`}),RegExp(`from.*components/src/${e}`).test(a)||t.push({file:r,rule:`missing-react-export`,detail:`${e} not exported from @cascivo/react`})}return{violations:t,passed:t.length===0}}function Ft(e){return typeof e==`object`&&!!e&&`$t`in e}function It(e){return typeof e==`string`?`'${e.replace(/'/g,`\\'`)}'`:String(e)}function Lt(e){return typeof e==`string`?`"${e.replace(/"/g,`\\"`)}"`:typeof e==`number`||typeof e==`boolean`?`{${e}}`:e===null?`{null}`:Ft(e)?`{"${e.$t}"} {/* i18n: ${e.$t} */}`:`{${JSON.stringify(e)}}`}function Rt(e,t,n,r){return e===void 0?``:typeof e==`string`?e:Ft(e)?`{/* i18n: ${e.$t} */}`:Array.isArray(e)?e.map(e=>zt(e,t+` `,n,r)).join(`
510
+ `):``}function zt(e,t,n,r){let i=e.component;r.add(i);let a=[];if(e.props)for(let[t,n]of Object.entries(e.props))a.push(`${t}=${Lt(n)}`);if(e.bind)for(let[t,n]of Object.entries(e.bind))n.startsWith(`$state.`)?a.push(`${t}={${n.slice(7)}.value}`):a.push(`${t}={data.${n.replace(/^\$data\./,``)}}`);if(e.events)for(let[t,n]of Object.entries(e.events))if(n.startsWith(`$state.set.`)){let e=n.slice(11);a.push(`${t}={(e) => (${e}.value = coerceValue(e))}`)}else if(n.startsWith(`$state.toggle.`)){let e=n.slice(14);a.push(`${t}={() => (${e}.value = !${e}.value)}`)}else a.push(`${t}={actions.${n.replace(/^\$actions\./,``)}}`);let o=a.length>0?` `+a.join(` `):``,s=e.children===void 0?void 0:Rt(e.children,t,[],r);return s!==void 0&&s!==``?`${t}<${i}${o}>\n${t} ${s}\n${t}</${i}>`:`${t}<${i}${o} />`}function Bt(e){let t=[],n=[];function r(e){if(e.bind)for(let n of Object.values(e.bind)){if(n.startsWith(`$state.`))continue;let e=n.replace(/^\$data\./,``);t.includes(e)||t.push(e)}if(e.events)for(let t of Object.values(e.events)){if(t.startsWith(`$state.`))continue;let e=t.replace(/^\$actions\./,``);n.includes(e)||n.push(e)}Array.isArray(e.children)&&e.children.forEach(r)}return e.forEach(r),{boundProps:t,actionProps:n}}function Vt(e){let t=e=>e.events&&Object.values(e.events).some(e=>e.startsWith(`$state.set.`))?!0:Array.isArray(e.children)?e.children.some(t):!1;return e.some(t)}function Ht(e,t,n){let r=new Set,i=Object.values(e.view.regions).flat(),{boundProps:a,actionProps:o}=Bt(i),s=Object.entries(e.state??{}),c=s.length>0,l=Vt(i),u=Object.entries(e.view.regions).map(([e,t])=>` <div className="region-${e}">\n${t.map(e=>zt(e,` `,[],r)).join(`
309
511
  `)}\n </div>`).join(`
310
512
  `),d=[...r].sort().map(e=>`import { ${e} } from '${n}/${e.toLowerCase()}/${e.toLowerCase()}'`).join(`
311
513
  `),f=a.length>0,p=o.length>0,m=[f?`data: {\n${a.map(e=>` ${e.replace(/\./g,`_`)}: unknown // TODO: type your data`).join(`
@@ -320,7 +522,7 @@ function coerceValue(e: unknown) {
320
522
  return e
321
523
  }
322
524
  `:``,v=c?` useSignals()
323
- `+s.map(([e,t])=>` const ${e} = useSignal(${St(t)})`).join(`
525
+ `+s.map(([e,t])=>` const ${e} = useSignal(${It(t)})`).join(`
324
526
  `)+`
325
527
  `:``;return`import React from 'react'${g}
326
528
  ${d}
@@ -334,7 +536,7 @@ ${u}
334
536
  </div>
335
537
  )
336
538
  }
337
- `}async function kt(e,t){let n=e.find((t,n)=>e[n-1]===`--out`),r=e.find(e=>!e.startsWith(`--`)),i=e.find((t,n)=>e[n-1]===`--components-dir`);if(!r){console.error(`Usage: cascivo generate <config.json> [--out output.tsx] [--components-dir ./src/components/ui]`),process.exitCode=1;return}let{readFileSync:a}=await import(`node:fs`),o=a(r,`utf-8`),s=Ot(JSON.parse(o),new Map,i??t.outputDir??`./src/components/ui`),c=n??F(ie(r),`${re(r,`.json`)}.tsx`);P(c,s,`utf-8`),console.log(`Generated ${c}`);try{let{spawnSync:e}=await import(`node:child_process`);e(`pnpm`,[`exec`,`vp`,`fmt`,c],{encoding:`utf8`,stdio:`inherit`}).status!==0&&e(`npx`,[`--yes`,`prettier`,`--write`,c],{encoding:`utf8`,stdio:`inherit`}).status!==0&&console.log(`(Note: formatter not found — output may need manual formatting)`)}catch{}}const q=[`@cascivo/core`,`@cascivo/tokens`,`@cascivo/themes`,`@preact/signals-react`],J=[`cascivo`];async function At(){let e=z({input:k,output:A});try{let t=(await e.question(`Theme? (${i.join(`/`)}) [light]: `)).trim().toLowerCase();return i.includes(t)?t:`light`}finally{e.close()}}function jt(e){return`import type { CascadeConfig } from 'cascivo'
539
+ `}async function Ut(e,t){let n=e.find((t,n)=>e[n-1]===`--out`),r=e.find(e=>!e.startsWith(`--`)),i=e.find((t,n)=>e[n-1]===`--components-dir`);if(!r){console.error(`Usage: cascivo generate <config.json> [--out output.tsx] [--components-dir ./src/components/ui]`),process.exitCode=1;return}let{readFileSync:a}=await import(`node:fs`),o=a(r,`utf-8`),s=Ht(JSON.parse(o),new Map,i??t.outputDir??`./src/components/ui`),c=n??F(ie(r),`${re(r,`.json`)}.tsx`);P(c,s,`utf-8`),console.log(`Generated ${c}`);try{let{spawnSync:e}=await import(`node:child_process`);e(`pnpm`,[`exec`,`vp`,`fmt`,c],{encoding:`utf8`,stdio:`inherit`}).status!==0&&e(`npx`,[`--yes`,`prettier`,`--write`,c],{encoding:`utf8`,stdio:`inherit`}).status!==0&&console.log(`(Note: formatter not found — output may need manual formatting)`)}catch{}}const Y=[`@cascivo/core`,`@cascivo/tokens`,`@cascivo/themes`,`@preact/signals-react`],X=[`cascivo`];async function Wt(){let e=z({input:k,output:A});try{let t=(await e.question(`Theme? (${i.join(`/`)}) [light]: `)).trim().toLowerCase();return i.includes(t)?t:`light`}finally{e.close()}}function Gt(e){return`import type { CascadeConfig } from 'cascivo'
338
540
 
339
541
  const config: CascadeConfig = {
340
542
  registry: '${n.registry}',
@@ -343,25 +545,25 @@ const config: CascadeConfig = {
343
545
  }
344
546
 
345
547
  export default config
346
- `}const Mt=[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yml`,`.eslintrc.yaml`];function Nt(e){Mt.some(t=>j(F(e,t)))&&(console.log(`
347
- ESLint: copied cascivo source may trip a strict host config on stylistic rules.`),console.log(` Scope them off your components dir — see docs/USING-WITH-STRICT-ESLINT.md`))}function Pt(e,t,n){let r=F(e,`package.json`);if(!j(r))return[];let i;try{i=JSON.parse(M(r,`utf8`))}catch{return[]}let a=n.dev?`devDependencies`:`dependencies`,o=i[a]??={},s=[];for(let e of t)o[e]===void 0&&(o[e]=`latest`,s.push(e));return s.length===0?[]:(P(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),s)}const Ft=[{config:[`.prettierrc`,`.prettierrc.json`,`.prettierrc.js`,`prettier.config.js`],ignore:`.prettierignore`},{config:[`.oxfmtrc`,`.oxfmtrc.json`],ignore:`.oxfmtignore`}];function It(e,t){let n=`${t.replace(/\/+$/,``)}/`;for(let{config:t,ignore:r}of Ft){if(!(t.some(t=>j(F(e,t)))||Lt(e,r)))continue;let i=F(e,r),a=j(i)?M(i,`utf8`):``;if(a.split(`
548
+ `}const Kt=[`eslint.config.js`,`eslint.config.mjs`,`eslint.config.cjs`,`eslint.config.ts`,`.eslintrc`,`.eslintrc.js`,`.eslintrc.cjs`,`.eslintrc.json`,`.eslintrc.yml`,`.eslintrc.yaml`];function qt(e){Kt.some(t=>j(F(e,t)))&&(console.log(`
549
+ ESLint: copied cascivo source may trip a strict host config on stylistic rules.`),console.log(` Scope them off your components dir — see docs/USING-WITH-STRICT-ESLINT.md`))}function Jt(e,t,n){let r=F(e,`package.json`);if(!j(r))return[];let i;try{i=JSON.parse(M(r,`utf8`))}catch{return[]}let a=n.dev?`devDependencies`:`dependencies`,o=i[a]??={},s=[];for(let e of t)o[e]===void 0&&(o[e]=`latest`,s.push(e));return s.length===0?[]:(P(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),s)}const Yt=[{config:[`.prettierrc`,`.prettierrc.json`,`.prettierrc.js`,`prettier.config.js`],ignore:`.prettierignore`},{config:[`.oxfmtrc`,`.oxfmtrc.json`],ignore:`.oxfmtignore`}];function Xt(e,t){let n=`${t.replace(/\/+$/,``)}/`;for(let{config:t,ignore:r}of Yt){if(!(t.some(t=>j(F(e,t)))||Zt(e,r)))continue;let i=F(e,r),a=j(i)?M(i,`utf8`):``;if(a.split(`
348
550
  `).some(e=>e.trim()===n))continue;let o=`# cascivo: vendored component source — you own it, so do not reformat it
349
551
  `;P(i,a===``?o+n+`
350
552
  `:`${a.replace(/\n*$/,`
351
- `)}\n${o}${n}\n`,`utf8`),console.log(`\nAdded "${n}" to ${r} (so your formatter does not rewrite copied source).`)}}function Lt(e,t){if(t!==`.prettierignore`)return!1;let n=F(e,`package.json`);if(!j(n))return!1;try{return`prettier`in JSON.parse(M(n,`utf8`))}catch{return!1}}function Rt(){console.log(`
352
- Dependencies`),console.log(` runtime: ${q.join(` `)}`),console.log(` dev: ${J.join(` `)} (types for cascivo.config.ts)`),console.log(" on demand: @cascivo/i18n, @cascivo/charts — added by `cascivo add` when a component or chart needs them")}async function zt(t=[],r=process.cwd()){let o=t.includes(`--yes`)||t.includes(`-y`),s=t.includes(`--no-install`),l=E(t,`theme`)?.toLowerCase();if(l!==void 0&&!i.includes(l)){console.error(`Unknown theme "${l}". Available: ${i.join(`, `)}`),process.exitCode=1;return}let u=T(t);if(`error`in u){console.error(u.error),process.exitCode=1;return}let d=e(r,u.pm?{override:u.pm}:{}),f=l===void 0&&!o&&k.isTTY,p=l??(f?await At():`light`);if(await c(F(r,`cascivo.config.ts`),jt(p)),console.log(`\nCreated cascivo.config.ts (theme: ${p})`),s)console.log(`
353
- Skipped install (--no-install). Install the dependencies yourself:`),console.log(` ${a(d,q)}`),console.log(` ${a(d,J,{dev:!0})}`);else{let e=B(q,r,{pm:d}),t=B(J,r,{pm:d,dev:!0});if(!e||!t){let n=[...e?[]:Pt(r,q,{dev:!1}),...t?[]:Pt(r,J,{dev:!0})];console.error(`
354
- Install failed — cascivo.config.ts was written but the packages are not installed.`),n.length>0?(console.error(`Wrote ${n.length} dependency entries to package.json: ${n.join(`, `)}`),console.error(`Recover with:\n ${d} install`)):console.error(`Recover with:\n ${a(d,q)}\n ${a(d,J,{dev:!0})}`),process.exitCode=1}}console.log(`
553
+ `)}\n${o}${n}\n`,`utf8`),console.log(`\nAdded "${n}" to ${r} (so your formatter does not rewrite copied source).`)}}function Zt(e,t){if(t!==`.prettierignore`)return!1;let n=F(e,`package.json`);if(!j(n))return!1;try{return`prettier`in JSON.parse(M(n,`utf8`))}catch{return!1}}function Qt(){console.log(`
554
+ Dependencies`),console.log(` runtime: ${Y.join(` `)}`),console.log(` dev: ${X.join(` `)} (types for cascivo.config.ts)`),console.log(" on demand: @cascivo/i18n, @cascivo/charts — added by `cascivo add` when a component or chart needs them")}async function $t(t=[],r=process.cwd()){let o=t.includes(`--yes`)||t.includes(`-y`),s=t.includes(`--no-install`),l=E(t,`theme`)?.toLowerCase();if(l!==void 0&&!i.includes(l)){console.error(`Unknown theme "${l}". Available: ${i.join(`, `)}`),process.exitCode=1;return}let u=T(t);if(`error`in u){console.error(u.error),process.exitCode=1;return}let d=e(r,u.pm?{override:u.pm}:{}),f=l===void 0&&!o&&k.isTTY,p=l??(f?await Wt():`light`);if(await c(F(r,`cascivo.config.ts`),Gt(p)),console.log(`\nCreated cascivo.config.ts (theme: ${p})`),s)console.log(`
555
+ Skipped install (--no-install). Install the dependencies yourself:`),console.log(` ${a(d,Y)}`),console.log(` ${a(d,X,{dev:!0})}`);else{let e=B(Y,r,{pm:d}),t=B(X,r,{pm:d,dev:!0});if(!e||!t){let n=[...e?[]:Jt(r,Y,{dev:!1}),...t?[]:Jt(r,X,{dev:!0})];console.error(`
556
+ Install failed — cascivo.config.ts was written but the packages are not installed.`),n.length>0?(console.error(`Wrote ${n.length} dependency entries to package.json: ${n.join(`, `)}`),console.error(`Recover with:\n ${d} install`)):console.error(`Recover with:\n ${a(d,Y)}\n ${a(d,X,{dev:!0})}`),process.exitCode=1}}console.log(`
355
557
  Stylesheets — import these once, in this order, in your entry file:`),console.log(` import '@cascivo/tokens' // primitive tokens — every --cascivo-* value`),console.log(` import '@cascivo/themes/${p}.css'${` `.repeat(Math.max(1,16-p.length))}// the ${p} theme's semantic values`),console.log(" // …then your component CSS (`cascivo add` writes .module.css beside each component)"),console.log(`
356
558
  Then set the theme on your root element:`),console.log(` <html data-theme="${p}">`),console.log(`
357
559
  Switching themes at runtime? Use a bundle instead of the single theme:`),console.log(` import '@cascivo/themes/light-dark.css' // light + dark — the common case`),console.log(` import '@cascivo/themes/all.css' // all twelve themes`),console.log(` import { ThemeProvider } from '@cascivo/core'`),console.log(`
358
560
  In YOUR components, when you read a signal during render:`),console.log(` import { useSignals } from '@cascivo/core'`),console.log(` function MyComponent() {`),console.log(` useSignals() // ← first statement, or the component never re-renders`),console.log(` return <span>{count.value}</span>`),console.log(` }`),console.log(`
359
- Adding a chart later? Charts ship as an npm package with their own stylesheet:`),console.log(" import '@cascivo/charts/styles.css' // `cascivo add <chart>` reminds you"),Rt(),It(r,n.outputDir),Nt(r),console.log(`
561
+ Adding a chart later? Charts ship as an npm package with their own stylesheet:`),console.log(" import '@cascivo/charts/styles.css' // `cascivo add <chart>` reminds you"),Qt(),Xt(r,n.outputDir),qt(r),console.log(`
360
562
  Packages version independently (changesets), so a low number means fewer`),console.log(`releases, not less finished. Pin exact versions, and before upgrading run:`),console.log(` cascivo doctor --drift # reads breaking-changes.json, reports API drift`),console.log(`
361
- Add components with: cascivo add <name>`)}const Bt={component:`Components`,layout:`Layouts (copy-paste)`,block:`Blocks (copy-paste)`,section:`Sections (copy-paste)`,chart:`Charts (npm: @cascivo/charts)`,flow:`Flow (npm: @cascivo/flow)`,editor:`Editor (npm: @cascivo/editor)`};function Vt(e){return e.deprecated?` ⚠ deprecated → ${e.deprecated.replacement}`:``}function Ht(e){let t=e.map(e=>[e.name,e.category,e.description+Vt(e)]),n=[`Name`,`Category`,`Description`],r=n.map((e,n)=>Math.max(e.length,...t.map(e=>(e[n]??``).length))),i=e=>e.map((e,t)=>e.padEnd(r[t]??e.length)).join(` `).trimEnd(),a=r.map(e=>`-`.repeat(e)).join(` `);return[i(n),a,...t.map(i)].join(`
362
- `)}function Ut(e){if(e.length===0)return`No components found.`;if(!e.some(e=>e.type!==void 0))return Ht(e);let t=new Map;for(let n of e){let e=n.type??`component`;t.has(e)||t.set(e,[]),t.get(e).push(n)}let n=[];for(let[e,r]of t){let t=Bt[e]??e;n.push(`${t}\n${Ht(r)}`)}return n.join(`
563
+ Add components with: cascivo add <name>`)}const en={component:`Components`,layout:`Layouts (copy-paste)`,block:`Blocks (copy-paste)`,section:`Sections (copy-paste)`,chart:`Charts (npm: @cascivo/charts)`,flow:`Flow (npm: @cascivo/flow)`,editor:`Editor (npm: @cascivo/editor)`};function tn(e){return e.deprecated?` ⚠ deprecated → ${e.deprecated.replacement}`:``}function nn(e){let t=e.map(e=>[e.name,e.category,e.description+tn(e)]),n=[`Name`,`Category`,`Description`],r=n.map((e,n)=>Math.max(e.length,...t.map(e=>(e[n]??``).length))),i=e=>e.map((e,t)=>e.padEnd(r[t]??e.length)).join(` `).trimEnd(),a=r.map(e=>`-`.repeat(e)).join(` `);return[i(n),a,...t.map(i)].join(`
564
+ `)}function rn(e){if(e.length===0)return`No components found.`;if(!e.some(e=>e.type!==void 0))return nn(e);let t=new Map;for(let n of e){let e=n.type??`component`;t.has(e)||t.set(e,[]),t.get(e).push(n)}let n=[];for(let[e,r]of t){let t=en[e]??e;n.push(`${t}\n${nn(r)}`)}return n.join(`
363
565
 
364
- `)}async function Wt(e,t={}){let n=(await y(e.registry)).components;t.installed&&(n=n.filter(t=>{let n=t.name.includes(`/`)?t.name.split(`/`).pop():t.name;return j(F(process.cwd(),e.outputDir,n))})),console.log(Ut(n)),console.log("\nTip: install any entry by its bare name — `cascivo add flex` resolves to `layout/flex`. Layout primitives (Flex, Grid, AutoGrid, Columns, Spacer, Center) replace inline-style layout; see docs/cookbooks/layout-and-spacing.md.")}function Gt(e){let t=[],n=[],r=new Set(e.items.map(e=>e.name));for(let i of e.items)if(L(i)){for(let e of fe(i))t.push(`template "${i.name}": ${e}`);for(let e of i.registryDependencies??[])!(e.includes(`/`)||e.startsWith(`@`)||e.startsWith(`http`))&&!r.has(e)&&n.push(`template "${i.name}": component "${e}" is not in this index — it must resolve from another registry at install time`)}return{errors:t,warnings:n}}async function Kt(e){let t=`cascade-registry.json`,n=`public/r`;for(let r=0;r<e.length;r++)e[r]===`--in`&&e[r+1]?(t=e[r+1],r++):e[r]===`--out`&&e[r+1]&&(n=e[r+1],r++);let r=I(t);if(!j(r)){console.error(`cascade registry build: file not found: ${r}`),process.exitCode=1;return}let i=JSON.parse(await oe(r,`utf8`));ie(r);let a=typeof i==`object`&&i&&i.schemaVersion===2?i:le(i),o=ue(a);if(o.warnings.length>0)for(let e of o.warnings)console.warn(`warn: ${e}`);if(!o.ok){for(let e of o.errors)console.error(`error: ${e}`);process.exitCode=1;return}let s=Gt(a);for(let e of s.warnings)console.warn(`warn: ${e}`);if(s.errors.length>0){for(let e of s.errors)console.error(`error: ${e}`);process.exitCode=1;return}let c=I(n);await ce(a,c),console.log(`cascade registry build: wrote static output to ${c}`)}function qt(e,t){let n=t.toLowerCase();return e.name.toLowerCase().includes(n)||e.description.toLowerCase().includes(n)||e.tags.some(e=>e.toLowerCase().includes(n))}async function Jt(e,t){let n=e.indexOf(`--registry`),r=n===-1?void 0:e[n+1],i=e.filter((t,n)=>t!==`--registry`&&e[n-1]!==`--registry`).join(` `).trim();if(!i){console.error(`Usage: cascivo search <query> [--registry @ns]`);return}let a=[];if(!r){let e=await y(t.registry);for(let t of e.components)qt(t,i)&&a.push({name:t.name,version:t.version,description:t.description})}let o=t.registries??{};for(let[e,t]of Object.entries(o))if(!(r&&e!==r))try{let n=await p((typeof t==`string`?t:t.url).replace(/{name}[^$]*$/,``).replace(/\/$/,``)+`/registry.json`),r=typeof n==`object`&&n&&Array.isArray(n.items)?n.items??[]:[];for(let t of r){if(!de(t).ok)continue;let n=t;qt(n,i)&&a.push({name:`${e}/${n.name}`,version:n.version,description:n.description,registry:e})}}catch{console.warn(` [warn] Could not search ${e} registry`)}if(a.length===0){console.log(`No results found.`);return}for(let e of a){let t=e.registry?` (${e.registry})`:``;console.log(`${e.name}@${e.version}${t} — ${e.description}`)}}const Y={baseMode:`light`,accentHue:250,accentChroma:.2,radiusBase:.375,fontFamily:`system`,presetId:`light`};function Yt(e){if(!e)return null;try{let t=e.replace(/-/g,`+`).replace(/_/g,`/`),n=atob(t),r=JSON.parse(n);return{baseMode:r.baseMode===`dark`?`dark`:`light`,accentHue:typeof r.accentHue==`number`?r.accentHue:Y.accentHue,accentChroma:typeof r.accentChroma==`number`?r.accentChroma:Y.accentChroma,radiusBase:typeof r.radiusBase==`number`?r.radiusBase:Y.radiusBase,fontFamily:r.fontFamily??Y.fontFamily,presetId:r.presetId??null}}catch{return null}}const X={geometric:`'Futura', 'Century Gothic', 'Trebuchet MS', ui-sans-serif, sans-serif`,humanist:`'Gill Sans', 'Trebuchet MS', 'Calibri', ui-sans-serif, sans-serif`,transitional:`'Optima', 'Candara', 'Palatino Linotype', ui-sans-serif, sans-serif`,mono:`ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace`};function Xt(e,t={}){let{previewMode:n=!1,themeName:r=`create-custom`}=t,i=e.baseMode===`light`,a=e.accentHue,o=e.accentChroma,s=(e,t=o)=>`oklch(${e} ${t.toFixed(3)} ${a})`,c=[`/* Add to your project CSS after importing the base theme: */`,`/* @import '@cascivo/themes/${e.baseMode}.css'; */`,`/* @import './theme.css'; */`,``,`@layer cascivo.theme {`,` [data-theme="${r}"] {`];return n&&(c.push(i?`
566
+ `)}async function an(e,t={}){let n=(await y(e.registry)).components;t.installed&&(n=n.filter(t=>{let n=t.name.includes(`/`)?t.name.split(`/`).pop():t.name;return j(F(process.cwd(),e.outputDir,n))})),console.log(rn(n)),console.log("\nTip: install any entry by its bare name — `cascivo add flex` resolves to `layout/flex`. Layout primitives (Flex, Grid, AutoGrid, Columns, Spacer, Center) replace inline-style layout; see docs/cookbooks/layout-and-spacing.md.")}function on(e){let t=[],n=[],r=new Set(e.items.map(e=>e.name));for(let i of e.items)if(L(i)){for(let e of fe(i))t.push(`template "${i.name}": ${e}`);for(let e of i.registryDependencies??[])!(e.includes(`/`)||e.startsWith(`@`)||e.startsWith(`http`))&&!r.has(e)&&n.push(`template "${i.name}": component "${e}" is not in this index — it must resolve from another registry at install time`)}return{errors:t,warnings:n}}async function sn(e){let t=`cascade-registry.json`,n=`public/r`;for(let r=0;r<e.length;r++)e[r]===`--in`&&e[r+1]?(t=e[r+1],r++):e[r]===`--out`&&e[r+1]&&(n=e[r+1],r++);let r=I(t);if(!j(r)){console.error(`cascade registry build: file not found: ${r}`),process.exitCode=1;return}let i=JSON.parse(await oe(r,`utf8`));ie(r);let a=typeof i==`object`&&i&&i.schemaVersion===2?i:le(i),o=ue(a);if(o.warnings.length>0)for(let e of o.warnings)console.warn(`warn: ${e}`);if(!o.ok){for(let e of o.errors)console.error(`error: ${e}`);process.exitCode=1;return}let s=on(a);for(let e of s.warnings)console.warn(`warn: ${e}`);if(s.errors.length>0){for(let e of s.errors)console.error(`error: ${e}`);process.exitCode=1;return}let c=I(n);await ce(a,c),console.log(`cascade registry build: wrote static output to ${c}`)}function cn(e,t){let n=t.toLowerCase();return e.name.toLowerCase().includes(n)||e.description.toLowerCase().includes(n)||e.tags.some(e=>e.toLowerCase().includes(n))}async function ln(e,t){let n=e.indexOf(`--registry`),r=n===-1?void 0:e[n+1],i=e.filter((t,n)=>t!==`--registry`&&e[n-1]!==`--registry`).join(` `).trim();if(!i){console.error(`Usage: cascivo search <query> [--registry @ns]`);return}let a=[];if(!r){let e=await y(t.registry);for(let t of e.components)cn(t,i)&&a.push({name:t.name,version:t.version,description:t.description})}let o=t.registries??{};for(let[e,t]of Object.entries(o))if(!(r&&e!==r))try{let n=await p((typeof t==`string`?t:t.url).replace(/{name}[^$]*$/,``).replace(/\/$/,``)+`/registry.json`),r=typeof n==`object`&&n&&Array.isArray(n.items)?n.items??[]:[];for(let t of r){if(!de(t).ok)continue;let n=t;cn(n,i)&&a.push({name:`${e}/${n.name}`,version:n.version,description:n.description,registry:e})}}catch{console.warn(` [warn] Could not search ${e} registry`)}if(a.length===0){console.log(`No results found.`);return}for(let e of a){let t=e.registry?` (${e.registry})`:``;console.log(`${e.name}@${e.version}${t} — ${e.description}`)}}const Z={baseMode:`light`,accentHue:250,accentChroma:.2,radiusBase:.375,fontFamily:`system`,presetId:`light`};function un(e){if(!e)return null;try{let t=e.replace(/-/g,`+`).replace(/_/g,`/`),n=atob(t),r=JSON.parse(n);return{baseMode:r.baseMode===`dark`?`dark`:`light`,accentHue:typeof r.accentHue==`number`?r.accentHue:Z.accentHue,accentChroma:typeof r.accentChroma==`number`?r.accentChroma:Z.accentChroma,radiusBase:typeof r.radiusBase==`number`?r.radiusBase:Z.radiusBase,fontFamily:r.fontFamily??Z.fontFamily,presetId:r.presetId??null}}catch{return null}}const dn={geometric:`'Futura', 'Century Gothic', 'Trebuchet MS', ui-sans-serif, sans-serif`,humanist:`'Gill Sans', 'Trebuchet MS', 'Calibri', ui-sans-serif, sans-serif`,transitional:`'Optima', 'Candara', 'Palatino Linotype', ui-sans-serif, sans-serif`,mono:`ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace`};function fn(e,t={}){let{previewMode:n=!1,themeName:r=`create-custom`}=t,i=e.baseMode===`light`,a=e.accentHue,o=e.accentChroma,s=(e,t=o)=>`oklch(${e} ${t.toFixed(3)} ${a})`,c=[`/* Add to your project CSS after importing the base theme: */`,`/* @import '@cascivo/themes/${e.baseMode}.css'; */`,`/* @import './theme.css'; */`,``,`@layer cascivo.theme {`,` [data-theme="${r}"] {`];return n&&(c.push(i?`
365
567
  color-scheme: light;
366
568
  --cascivo-color-background: oklch(1 0 0);
367
569
  --cascivo-color-surface: oklch(0.985 0.002 264);
@@ -457,20 +659,20 @@ Add components with: cascivo add <name>`)}const Bt={component:`Components`,layou
457
659
  --cascivo-ring-width: 2px;
458
660
  --cascivo-ring-offset: 0px;
459
661
  --cascivo-ring-color: color-mix(in oklch, var(--cascivo-color-accent) 65%, transparent);
460
- --cascivo-focus-ring: 0 0 0 var(--cascivo-ring-width) var(--cascivo-ring-color);`),c.push(``)),c.push(` /* ── Accent ─────────────────────────────────── */`,` --cascivo-color-accent: ${s(i?.52:.65)};`,` --cascivo-color-accent-foreground: ${i?`oklch(1 0 0)`:`oklch(0.145 0.005 ${a})`};`,` --cascivo-color-accent-hover: ${s(i?.45:.707)};`,` --cascivo-color-accent-active: ${s(i?.373:.808,Math.min(o,.155))};`,` --cascivo-color-accent-subtle: ${s(i?.97:.623,.025)};`,` --cascivo-color-accent-muted: ${s(i?.932:.623,i?.055:o*.2)};`,``,` /* ── Radius ─────────────────────────────────── */`,` --cascivo-radius-base: ${e.radiusBase}rem;`,` --cascivo-radius-control: var(--cascivo-radius-base);`,` --cascivo-radius-surface: calc(var(--cascivo-radius-base) * 1.66);`,` --cascivo-radius-indicator: calc(var(--cascivo-radius-base) / 2);`,` --cascivo-radius-full: 9999px;`,` --cascivo-radius-component: var(--cascivo-radius-base);`,` --cascivo-radius-button: var(--cascivo-radius-base);`,` --cascivo-radius-input: var(--cascivo-radius-base);`,` --cascivo-radius-card: calc(var(--cascivo-radius-base) * 1.66);`,` --cascivo-radius-badge: var(--cascivo-radius-full);`,` --cascivo-radius-modal: calc(var(--cascivo-radius-base) * 2);`),e.fontFamily!==`system`&&(c.push(``),c.push(` /* ── Font ───────────────────────────────────── */`),c.push(` --cascivo-font-sans: ${X[e.fontFamily]??X.humanist};`)),c.push(` }`),c.push(`}`),c.join(`
461
- `)}const Zt=/^[a-z][a-z0-9-]*$/;function Qt(e,t){let n=e.find(e=>e.startsWith(`--${t}=`));if(n)return n.slice(t.length+3);let r=e.indexOf(`--${t}`),i=r===-1?void 0:e[r+1];return i&&!i.startsWith(`--`)?i:void 0}async function $t(e,t){let n=e.find(e=>!e.startsWith(`--`)),r=Qt(e,`from`),i=e.includes(`--dry-run`);if(!n||!r){console.error(`Usage: cascivo theme create <name> --from <hash> [--out <path>]`),console.error(`Get <hash> from the theme builder at https://cascivo.com/create (Copy CLI command).`);return}if(!Zt.test(n)){console.error(`Invalid theme name "${n}". Use lowercase letters, digits, and dashes.`);return}let a=Yt(r);if(!a){console.error(`Could not decode --from. Copy the command again from the theme builder.`);return}let o=Xt(a,{themeName:n});if(i){console.log(o);return}await c(I(t,Qt(e,`out`)??`${n}.theme.css`),o),console.log(`\n✓ Wrote ${n}.theme.css`),console.log(`
462
- Import the base theme and your overlay in your entry CSS:`),console.log(` @import '@cascivo/themes/${a.baseMode}.css';`),console.log(` @import './${n}.theme.css';`),console.log(`Then set it on a container:`),console.log(` <div data-theme="${n}">…</div>`)}async function en(e){let[t,n]=e;if(t===`create`){await $t(e.slice(1),process.cwd());return}if(t!==`add`||!n){console.error(`Usage: cascivo theme add <${i.join(`|`)}>`),console.error(` cascivo theme create <name> --from <hash>`);return}if(!i.includes(n)){console.error(`Unknown theme "${n}". Available: ${i.join(`, `)}`);return}B([`@cascivo/themes`]),console.log(`
463
- Import the theme in your root CSS or entry file:`),console.log(` import '@cascivo/themes/${n}.css'`),console.log(`Then set it on a container:`),console.log(` <div data-theme="${n}">…</div>`)}function tn(e,t){let n=e.split(`
662
+ --cascivo-focus-ring: 0 0 0 var(--cascivo-ring-width) var(--cascivo-ring-color);`),c.push(``)),c.push(` /* ── Accent ─────────────────────────────────── */`,` --cascivo-color-accent: ${s(i?.52:.65)};`,` --cascivo-color-accent-foreground: ${i?`oklch(1 0 0)`:`oklch(0.145 0.005 ${a})`};`,` --cascivo-color-accent-hover: ${s(i?.45:.707)};`,` --cascivo-color-accent-active: ${s(i?.373:.808,Math.min(o,.155))};`,` --cascivo-color-accent-subtle: ${s(i?.97:.623,.025)};`,` --cascivo-color-accent-muted: ${s(i?.932:.623,i?.055:o*.2)};`,``,` /* ── Radius ─────────────────────────────────── */`,` --cascivo-radius-base: ${e.radiusBase}rem;`,` --cascivo-radius-control: var(--cascivo-radius-base);`,` --cascivo-radius-surface: calc(var(--cascivo-radius-base) * 1.66);`,` --cascivo-radius-indicator: calc(var(--cascivo-radius-base) / 2);`,` --cascivo-radius-full: 9999px;`,` --cascivo-radius-component: var(--cascivo-radius-base);`,` --cascivo-radius-button: var(--cascivo-radius-base);`,` --cascivo-radius-input: var(--cascivo-radius-base);`,` --cascivo-radius-card: calc(var(--cascivo-radius-base) * 1.66);`,` --cascivo-radius-badge: var(--cascivo-radius-full);`,` --cascivo-radius-modal: calc(var(--cascivo-radius-base) * 2);`),e.fontFamily!==`system`&&(c.push(``),c.push(` /* ── Font ───────────────────────────────────── */`),c.push(` --cascivo-font-sans: ${dn[e.fontFamily]??dn.humanist};`)),c.push(` }`),c.push(`}`),c.join(`
663
+ `)}const pn=/^[a-z][a-z0-9-]*$/;function mn(e,t){let n=e.find(e=>e.startsWith(`--${t}=`));if(n)return n.slice(t.length+3);let r=e.indexOf(`--${t}`),i=r===-1?void 0:e[r+1];return i&&!i.startsWith(`--`)?i:void 0}async function hn(e,t){let n=e.find(e=>!e.startsWith(`--`)),r=mn(e,`from`),i=e.includes(`--dry-run`);if(!n||!r){console.error(`Usage: cascivo theme create <name> --from <hash> [--out <path>]`),console.error(`Get <hash> from the theme builder at https://cascivo.com/create (Copy CLI command).`);return}if(!pn.test(n)){console.error(`Invalid theme name "${n}". Use lowercase letters, digits, and dashes.`);return}let a=un(r);if(!a){console.error(`Could not decode --from. Copy the command again from the theme builder.`);return}let o=fn(a,{themeName:n});if(i){console.log(o);return}await c(I(t,mn(e,`out`)??`${n}.theme.css`),o),console.log(`\n✓ Wrote ${n}.theme.css`),console.log(`
664
+ Import the base theme and your overlay in your entry CSS:`),console.log(` @import '@cascivo/themes/${a.baseMode}.css';`),console.log(` @import './${n}.theme.css';`),console.log(`Then set it on a container:`),console.log(` <div data-theme="${n}">…</div>`)}async function gn(e){let[t,n]=e;if(t===`create`){await hn(e.slice(1),process.cwd());return}if(t!==`add`||!n){console.error(`Usage: cascivo theme add <${i.join(`|`)}>`),console.error(` cascivo theme create <name> --from <hash>`);return}if(!i.includes(n)){console.error(`Unknown theme "${n}". Available: ${i.join(`, `)}`);return}B([`@cascivo/themes`]),console.log(`
665
+ Import the theme in your root CSS or entry file:`),console.log(` import '@cascivo/themes/${n}.css'`),console.log(`Then set it on a container:`),console.log(` <div data-theme="${n}">…</div>`)}function _n(e,t){let n=e.split(`
464
666
  `),r=t.split(`
465
- `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array.from({length:a+1},()=>0));for(let e=i-1;e>=0;e--)for(let t=a-1;t>=0;t--)o[e][t]=n[e]===r[t]?o[e+1][t+1]+1:Math.max(o[e+1][t],o[e][t+1]);let s=[],c=0,l=0;for(;c<i&&l<a;)n[c]===r[l]?(s.push(` ${n[c]}`),c++,l++):o[c+1][l]>=o[c][l+1]?(s.push(`- ${n[c]}`),c++):(s.push(`+ ${r[l]}`),l++);for(;c<i;)s.push(`- ${n[c++]}`);for(;l<a;)s.push(`+ ${r[l++]}`);return s}function nn(e,t){return e!==t}function rn(e,t){let n=e.length,r=t.length,i=Array.from({length:n+1},()=>Array.from({length:r+1},()=>0));for(let a=1;a<=n;a++)for(let n=1;n<=r;n++)i[a][n]=e[a-1]===t[n-1]?i[a-1][n-1]+1:Math.max(i[a-1][n],i[a][n-1]);return i}function Z(e,t){let n=rn(e,t),r=[],i=e.length,a=t.length,o=[],s=[],c=[];function l(){o.length>0||s.length>0?(c.length>0&&(r.unshift({type:`common`,lines:[...c]}),c.length=0),r.unshift({type:o.length>0?`left`:`right`,lines:o.length>0?[...o]:[...s]}),o.length=0,s.length=0):c.length>0&&(r.unshift({type:`common`,lines:[...c]}),c.length=0)}for(;i>0||a>0;)i>0&&a>0&&e[i-1]===t[a-1]?((o.length>0||s.length>0)&&l(),c.unshift(e[i-1]),i--,a--):a>0&&(i===0||n[i][a-1]>=n[i-1][a])?(l(),s.unshift(t[a-1]),a--):(l(),o.unshift(e[i-1]),i--);return l(),r}function an(e,t,n){let r=e.split(`
667
+ `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array.from({length:a+1},()=>0));for(let e=i-1;e>=0;e--)for(let t=a-1;t>=0;t--)o[e][t]=n[e]===r[t]?o[e+1][t+1]+1:Math.max(o[e+1][t],o[e][t+1]);let s=[],c=0,l=0;for(;c<i&&l<a;)n[c]===r[l]?(s.push(` ${n[c]}`),c++,l++):o[c+1][l]>=o[c][l+1]?(s.push(`- ${n[c]}`),c++):(s.push(`+ ${r[l]}`),l++);for(;c<i;)s.push(`- ${n[c++]}`);for(;l<a;)s.push(`+ ${r[l++]}`);return s}function vn(e,t){return e!==t}function yn(e,t){let n=e.length,r=t.length,i=Array.from({length:n+1},()=>Array.from({length:r+1},()=>0));for(let a=1;a<=n;a++)for(let n=1;n<=r;n++)i[a][n]=e[a-1]===t[n-1]?i[a-1][n-1]+1:Math.max(i[a-1][n],i[a][n-1]);return i}function Q(e,t){let n=yn(e,t),r=[],i=e.length,a=t.length,o=[],s=[],c=[];function l(){o.length>0||s.length>0?(c.length>0&&(r.unshift({type:`common`,lines:[...c]}),c.length=0),r.unshift({type:o.length>0?`left`:`right`,lines:o.length>0?[...o]:[...s]}),o.length=0,s.length=0):c.length>0&&(r.unshift({type:`common`,lines:[...c]}),c.length=0)}for(;i>0||a>0;)i>0&&a>0&&e[i-1]===t[a-1]?((o.length>0||s.length>0)&&l(),c.unshift(e[i-1]),i--,a--):a>0&&(i===0||n[i][a-1]>=n[i-1][a])?(l(),s.unshift(t[a-1]),a--):(l(),o.unshift(e[i-1]),i--);return l(),r}function bn(e,t,n){let r=e.split(`
466
668
  `),i=t.split(`
467
669
  `),a=n.split(`
468
- `),o=Z(r,i),s=new Map,c=0;for(let e of o)e.type===`left`?s.set(`del:${c}`,e.lines):(e.type===`right`&&s.set(`ins:${c}`,e.lines),c+=e.lines.length);let l=[],u=0;if(r.length,i.length,a.length,t===e)return{text:n,conflicts:0};if(n===e)return{text:t,conflicts:0};let d=Z(r,i),f=Z(r,a),p=0,m=0,h=0,g=[],_=[];for(let e of d)e.type===`common`?(m+=e.lines.length,p+=e.lines.length):e.type===`right`?(g.push({baseStart:p,baseEnd:p,lines:e.lines}),m+=e.lines.length):(g.push({baseStart:p,baseEnd:p+e.lines.length,lines:[]}),p+=e.lines.length);p=0;for(let e of f)e.type===`common`?(h+=e.lines.length,p+=e.lines.length):e.type===`right`?(_.push({baseStart:p,baseEnd:p,lines:e.lines}),h+=e.lines.length):(_.push({baseStart:p,baseEnd:p+e.lines.length,lines:[]}),p+=e.lines.length);let v=new Map;for(let e of g)v.set(e.baseStart,{end:e.baseEnd,lines:e.lines});let y=new Map;for(let e of _)y.set(e.baseStart,{end:e.baseEnd,lines:e.lines});let b=0;for(;b<=r.length;){let e=v.get(b),t=y.get(b);if(e&&t){let n=Math.max(e.end,b),r=Math.max(t.end,b),i=e.lines,a=t.lines;JSON.stringify(i)===JSON.stringify(a)?l.push(...i):(l.push(`<<<<<<< local`),l.push(...i),l.push(`=======`),l.push(...a),l.push(`>>>>>>> upstream`),u++),b=Math.max(n,r,b+1)}else e?(l.push(...e.lines),b=Math.max(e.end,b+1)):t?(l.push(...t.lines),b=Math.max(t.end,b+1)):(b<r.length&&l.push(r[b]),b++)}return{text:l.join(`
469
- `),conflicts:u}}async function on(e){let t=z({input:k,output:A});try{let n=(await t.question(`${e} (y/N): `)).trim().toLowerCase();return n===`y`||n===`yes`}finally{t.close()}}async function sn(e,t,n={}){if(n.check)return un(t);if(!e){console.error(`Usage: cascivo update <component>`);return}let r=(await v())?.items[e],i=h(await y(t.registry),e);if(!i){console.error(`Component "${e}" not found in registry. Run "cascivo list".`);return}if(r){let a=r.version,o=`${r.registry}/r/${e}@${a}.json`,s=null;try{s=R(await p(o),o)}catch{console.warn(`Warning: could not fetch base version ${a} from ${o}. Falling back to two-way diff.`)}s?await cn(e,i,s,t,n):await ln(e,i,t,n)}else console.warn(`Warning: "${e}" has no lock entry. Falling back to two-way diff update (pre-v11 install).`),await ln(e,i,t,n)}async function cn(e,t,n,r,i){if(!t)return;let a=e.includes(`/`)?e.split(`/`).pop():e,o=[],s=[];for(let e of t.files){let t=x(e),i=n.files.find(e=>x(e.url)===t),c=u(r.outputDir,a,t),l=await f(e),d=j(c)?await oe(c,`utf8`):``,p=i?await f(i.url):``;if(p===``&&d===``){o.push({file:t,result:`clean`}),s.push({dest:c,content:l,conflicts:0});continue}let{text:m,conflicts:h}=an(p,d,l);if(h>0)o.push({file:t,result:`conflict`});else if(m===d){o.push({file:t,result:`unchanged`});continue}else o.push({file:t,result:`clean`});s.push({dest:c,content:m,conflicts:h})}if(s.length===0){console.log(`${e} is already up to date.`);return}for(let e of o){let t=e.result===`conflict`?`⚠`:e.result===`clean`?`✓`:`·`;console.log(` ${t} ${e.file} (${e.result})`)}let l=s.filter(e=>e.conflicts>0);if((i.yes?l.length===0:await on(`\nApply ${s.length} change(s) to ${e}?`))||i.yes){let n=await v(),r=n;for(let{dest:e,content:t,conflicts:n}of s){if(i.yes&&n>0){console.log(` skipped (conflicts): ${e}`);continue}await c(e,t)}if(n&&r){let i=l.length>0;r=g(r,e,{...n.items[e],version:t.version,...i?{conflicted:!0}:{}}),await m(r)}console.log(`Updated ${e}.`),l.length>0&&console.log(`${l.length} file(s) have conflict markers — resolve them manually.`)}else console.log(`Aborted. No files changed.`)}async function ln(e,t,n,r){if(!t)return;let i=[];for(let e of t.files){let r;try{r=await f(e)}catch(e){console.error(e instanceof Error?e.message:String(e));return}let a=u(n.outputDir,t.name,x(e)),o=await l(a);o===null?(console.log(`New file: ${a}`),i.push({path:a,content:r})):nn(o,r)&&(console.log(`\n--- ${a}`),console.log(tn(o,r).join(`
470
- `)),i.push({path:a,content:r}))}if(i.length===0){console.log(`${e} is already up to date.`);return}if(r.yes||await on(`\nApply ${i.length} change(s) to ${e}?`)){for(let{path:e,content:t}of i)await c(e,t);console.log(`Updated ${e}.`)}else console.log(`Aborted. No files changed.`)}async function un(e){let t=await v();if(!t||Object.keys(t.items).length===0){console.log(`No installed components found in cascivo.lock.`);return}let n=await y(e.registry),r=0;for(let[e,i]of Object.entries(t.items)){let t=h(n,e);if(t)if(t.fileHashes&&Object.keys(t.fileHashes).length>0){let n=new Map(Object.entries(i.files).map(([e,t])=>[e.split(`/`).pop(),t])),a=Object.entries(t.fileHashes).filter(([e,t])=>n.get(e)!==t);a.length>0&&(console.log(`${e}: ${a.length} file(s) changed upstream (${i.version} → ${t.version})`),r++)}else t.version!==i.version&&(console.log(`${e}: ${i.version} → ${t.version}`),r++)}r>0?(console.log(`${r} component(s) outdated.`),process.exitCode=1):console.log(`All components up to date.`)}function dn(e){let t=[];if(t.push(`\n${e.name} v${e.version}`),t.push(`Type: ${e.type}${e.category?` / ${e.category}`:``}`),t.push(e.description),e.author&&t.push(`Author: ${e.author}`),e.license&&t.push(`License: ${e.license}`),e.homepage&&t.push(`Homepage: ${e.homepage}`),e.install?(t.push(`Distribution: npm package — pnpm add ${e.install}`),e.styles&&t.push(`Stylesheet: import '${e.styles}' (required)`)):L(e)||t.push(`Distribution: copy-paste — npx cascivo add ${e.name}`),L(e))try{let n=se(e.meta);if(t.push(`\nTemplate: ${n.intent}`),t.push(`Framework: ${n.framework}`),n.demoUrl&&t.push(`Demo: ${n.demoUrl}`),n.pages?.length){t.push(`Pages:`);for(let e of n.pages)t.push(` ${e.name} → ${e.target}`)}}catch{}if(e.changelog?.length){t.push(`
670
+ `),o=Q(r,i),s=new Map,c=0;for(let e of o)e.type===`left`?s.set(`del:${c}`,e.lines):(e.type===`right`&&s.set(`ins:${c}`,e.lines),c+=e.lines.length);let l=[],u=0;if(r.length,i.length,a.length,t===e)return{text:n,conflicts:0};if(n===e)return{text:t,conflicts:0};let d=Q(r,i),f=Q(r,a),p=0,m=0,h=0,g=[],_=[];for(let e of d)e.type===`common`?(m+=e.lines.length,p+=e.lines.length):e.type===`right`?(g.push({baseStart:p,baseEnd:p,lines:e.lines}),m+=e.lines.length):(g.push({baseStart:p,baseEnd:p+e.lines.length,lines:[]}),p+=e.lines.length);p=0;for(let e of f)e.type===`common`?(h+=e.lines.length,p+=e.lines.length):e.type===`right`?(_.push({baseStart:p,baseEnd:p,lines:e.lines}),h+=e.lines.length):(_.push({baseStart:p,baseEnd:p+e.lines.length,lines:[]}),p+=e.lines.length);let v=new Map;for(let e of g)v.set(e.baseStart,{end:e.baseEnd,lines:e.lines});let y=new Map;for(let e of _)y.set(e.baseStart,{end:e.baseEnd,lines:e.lines});let b=0;for(;b<=r.length;){let e=v.get(b),t=y.get(b);if(e&&t){let n=Math.max(e.end,b),r=Math.max(t.end,b),i=e.lines,a=t.lines;JSON.stringify(i)===JSON.stringify(a)?l.push(...i):(l.push(`<<<<<<< local`),l.push(...i),l.push(`=======`),l.push(...a),l.push(`>>>>>>> upstream`),u++),b=Math.max(n,r,b+1)}else e?(l.push(...e.lines),b=Math.max(e.end,b+1)):t?(l.push(...t.lines),b=Math.max(t.end,b+1)):(b<r.length&&l.push(r[b]),b++)}return{text:l.join(`
671
+ `),conflicts:u}}async function xn(e){let t=z({input:k,output:A});try{let n=(await t.question(`${e} (y/N): `)).trim().toLowerCase();return n===`y`||n===`yes`}finally{t.close()}}async function Sn(e,t,n={}){if(n.check)return Tn(t);if(!e){console.error(`Usage: cascivo update <component>`);return}let r=(await v())?.items[e],i=h(await y(t.registry),e);if(!i){console.error(`Component "${e}" not found in registry. Run "cascivo list".`);return}if(r){let a=r.version,o=`${r.registry}/r/${e}@${a}.json`,s=null;try{s=R(await p(o),o)}catch{console.warn(`Warning: could not fetch base version ${a} from ${o}. Falling back to two-way diff.`)}s?await Cn(e,i,s,t,n):await wn(e,i,t,n)}else console.warn(`Warning: "${e}" has no lock entry. Falling back to two-way diff update (pre-v11 install).`),await wn(e,i,t,n)}async function Cn(e,t,n,r,i){if(!t)return;let a=e.includes(`/`)?e.split(`/`).pop():e,o=[],s=[];for(let e of t.files){let t=x(e),i=n.files.find(e=>x(e.url)===t),c=u(r.outputDir,a,t),l=await f(e),d=j(c)?await oe(c,`utf8`):``,p=i?await f(i.url):``;if(p===``&&d===``){o.push({file:t,result:`clean`}),s.push({dest:c,content:l,conflicts:0});continue}let{text:m,conflicts:h}=bn(p,d,l);if(h>0)o.push({file:t,result:`conflict`});else if(m===d){o.push({file:t,result:`unchanged`});continue}else o.push({file:t,result:`clean`});s.push({dest:c,content:m,conflicts:h})}if(s.length===0){console.log(`${e} is already up to date.`);return}for(let e of o){let t=e.result===`conflict`?`⚠`:e.result===`clean`?`✓`:`·`;console.log(` ${t} ${e.file} (${e.result})`)}let l=s.filter(e=>e.conflicts>0);if((i.yes?l.length===0:await xn(`\nApply ${s.length} change(s) to ${e}?`))||i.yes){let n=await v(),r=n;for(let{dest:e,content:t,conflicts:n}of s){if(i.yes&&n>0){console.log(` skipped (conflicts): ${e}`);continue}await c(e,t)}if(n&&r){let i=l.length>0;r=g(r,e,{...n.items[e],version:t.version,...i?{conflicted:!0}:{}}),await m(r)}console.log(`Updated ${e}.`),l.length>0&&console.log(`${l.length} file(s) have conflict markers — resolve them manually.`)}else console.log(`Aborted. No files changed.`)}async function wn(e,t,n,r){if(!t)return;let i=[];for(let e of t.files){let r;try{r=await f(e)}catch(e){console.error(e instanceof Error?e.message:String(e));return}let a=u(n.outputDir,t.name,x(e)),o=await l(a);o===null?(console.log(`New file: ${a}`),i.push({path:a,content:r})):vn(o,r)&&(console.log(`\n--- ${a}`),console.log(_n(o,r).join(`
672
+ `)),i.push({path:a,content:r}))}if(i.length===0){console.log(`${e} is already up to date.`);return}if(r.yes||await xn(`\nApply ${i.length} change(s) to ${e}?`)){for(let{path:e,content:t}of i)await c(e,t);console.log(`Updated ${e}.`)}else console.log(`Aborted. No files changed.`)}async function Tn(e){let t=await v();if(!t||Object.keys(t.items).length===0){console.log(`No installed components found in cascivo.lock.`);return}let n=await y(e.registry),r=0;for(let[e,i]of Object.entries(t.items)){let t=h(n,e);if(t)if(t.fileHashes&&Object.keys(t.fileHashes).length>0){let n=new Map(Object.entries(i.files).map(([e,t])=>[e.split(`/`).pop(),t])),a=Object.entries(t.fileHashes).filter(([e,t])=>n.get(e)!==t);a.length>0&&(console.log(`${e}: ${a.length} file(s) changed upstream (${i.version} → ${t.version})`),r++)}else t.version!==i.version&&(console.log(`${e}: ${i.version} → ${t.version}`),r++)}r>0?(console.log(`${r} component(s) outdated.`),process.exitCode=1):console.log(`All components up to date.`)}function En(e){let t=[];if(t.push(`\n${e.name} v${e.version}`),t.push(`Type: ${e.type}${e.category?` / ${e.category}`:``}`),t.push(e.description),e.author&&t.push(`Author: ${e.author}`),e.license&&t.push(`License: ${e.license}`),e.homepage&&t.push(`Homepage: ${e.homepage}`),e.install?(t.push(`Distribution: npm package — pnpm add ${e.install}`),e.styles&&t.push(`Stylesheet: import '${e.styles}' (required)`)):L(e)||t.push(`Distribution: copy-paste — npx cascivo add ${e.name}`),L(e))try{let n=se(e.meta);if(t.push(`\nTemplate: ${n.intent}`),t.push(`Framework: ${n.framework}`),n.demoUrl&&t.push(`Demo: ${n.demoUrl}`),n.pages?.length){t.push(`Pages:`);for(let e of n.pages)t.push(` ${e.name} → ${e.target}`)}}catch{}if(e.changelog?.length){t.push(`
471
673
  Changelog:`);for(let n of e.changelog.slice(0,5))t.push(` ${n.version}: ${n.note}`)}if(e.files?.length){t.push(`
472
674
  Files:`);for(let n of e.files)t.push(` ${n.url}${n.target?` → ${n.target}`:``}`)}if(e.dependencies?.length&&t.push(`\nDependencies: ${e.dependencies.join(`, `)}`),e.registryDependencies?.length){let n=L(e)?`Components`:`Registry dependencies`;t.push(`${n}: ${e.registryDependencies.join(`, `)}`)}return t.join(`
473
- `)}async function fn(e,t){let n=e[0];if(!n){console.error(`Usage: cascivo view <component-spec>`);return}let{url:r,headers:i,params:a}=await W(H(n),t),o={};i&&(o.headers=i),a&&(o.params=a);let s=R(await p(r,o),r);console.log(dn(s))}const Q=D(import.meta.url)(`../package.json`).version,pn=`cascivo ${Q} — the CSS-native, signal-driven, AI-first design system
675
+ `)}async function Dn(e,t){let n=e[0];if(!n){console.error(`Usage: cascivo view <component-spec>`);return}let{url:r,headers:i,params:a}=await ge(me(n),t),o={};i&&(o.headers=i),a&&(o.params=a);let s=R(await p(r,o),r);console.log(En(s))}const $=D(import.meta.url)(`../package.json`).version,On=`cascivo ${$} — the CSS-native, signal-driven, AI-first design system
474
676
 
475
677
  Usage: cascivo <command> [options]
476
678
 
@@ -493,7 +695,7 @@ Commands:
493
695
  tokens import <file> Import external design tokens as cascivo overrides
494
696
  email lint <file...> Check rendered email HTML against the Can I email matrix
495
697
 
496
- Run "cascivo <command> --help" for details.`,$=i.join(` | `),mn={email:`Usage: cascivo email lint <file...> [options]
698
+ Run "cascivo <command> --help" for details.`,kn=i.join(` | `),An={email:`Usage: cascivo email lint <file...> [options]
497
699
 
498
700
  Check rendered email HTML against the Can I email support matrix — the same
499
701
  conformance lint @cascivo/email exposes as \`lint()\`, with the setup done for you.
@@ -525,7 +727,7 @@ cascivo app shell, side navigation, header, and a theme.
525
727
 
526
728
  Options:
527
729
  --template <spec> Start from a marketplace template (@ns/name or owner/repo/name)
528
- --theme <name> Theme to install (${$})
730
+ --theme <name> Theme to install (${kn})
529
731
  --sections "<a, b>" Comma-separated nav section labels (one component each)
530
732
  --package-manager <pm> Package manager for README/next-steps (alias --pm; default: auto-detect)
531
733
  --yes, -y Accept defaults, never prompt`,init:`Usage: cascivo init [options]
@@ -535,7 +737,7 @@ runtime dependencies (@cascivo/core, @cascivo/tokens, @cascivo/themes, the
535
737
  @preact/signals-react peer) plus cascivo as a dev dependency for the config's types.
536
738
 
537
739
  Options:
538
- --theme <name> Theme to configure (${$})
740
+ --theme <name> Theme to configure (${kn})
539
741
  --package-manager <pm> Force pnpm | yarn | npm | bun (alias --pm; default: auto-detect)
540
742
  --no-install Write files only; print the install commands to run yourself
541
743
  --yes, -y Accept defaults, never prompt (implied when stdin is not a TTY)`,add:`Usage: cascivo add <component...> [options]
@@ -576,7 +778,7 @@ create Turn a theme-builder config into an owned <name>.theme.css. Get <hash>
576
778
  from https://cascivo.com/create ("Copy CLI command"). --dry-run prints
577
779
  the CSS without writing.
578
780
 
579
- Themes: ${$}`,eject:`Usage: cascivo eject <component> [options]
781
+ Themes: ${kn}`,eject:`Usage: cascivo eject <component> [options]
580
782
 
581
783
  Eject specific tokens into a scoped local override file so you can restyle a
582
784
  component without forking it.
@@ -624,5 +826,5 @@ Options:
624
826
  --repo <owner/repo> Repository the template will be hosted in`,tokens:`Usage: cascivo tokens import <file>
625
827
 
626
828
  Import external design tokens (W3C design-tokens JSON) as cascivo token
627
- overrides.`};async function hn(e){let[n,...r]=e;if(n!==void 0&&(r.includes(`--help`)||r.includes(`-h`))){let e=mn[n];if(e!==void 0){console.log(e);return}}switch(n){case`create`:await et(r);break;case`init`:await zt(r);break;case`add`:{let e=T(r);if(`error`in e){console.error(e.error),process.exitCode=1;break}await Oe(w(r,[`pm`,`package-manager`]),await t(),{dryRun:r.includes(`--dry-run`),yes:r.includes(`--yes`),noInstall:r.includes(`--no-install`),...e.pm?{pm:e.pm}:{}});break}case`list`:await Wt(await t(),{installed:r.includes(`--installed`)});break;case`update`:await sn(r.filter(e=>!e.startsWith(`--`))[0],await t(),{check:r.includes(`--check`),yes:r.includes(`--yes`)});break;case`search`:await Jt(r,await t());break;case`view`:await fn(r,await t());break;case`theme`:await en(r);break;case`eject`:{let{eject:e}=await import(`./eject-B94ujtUo.mjs`),n=e=>{let t=r.find(t=>t.startsWith(`--${e}=`));if(t)return t.slice(e.length+3);let n=r.indexOf(`--${e}`),i=n===-1?void 0:r[n+1];return i&&!i.startsWith(`--`)?i:void 0},i=n(`tokens`);await e(r,await t(),{...i?{tokens:i.split(`,`).map(e=>e.trim()).filter(Boolean)}:{},...n(`scope`)?{scope:n(`scope`)}:{},...n(`out`)?{out:n(`out`)}:{},dryRun:r.includes(`--dry-run`)});break}case`generate`:await kt(r,await t());break;case`registry`:r[0]===`build`?await Kt(r.slice(1)):(console.error(`Unknown registry subcommand: ${r[0]}`),process.exitCode=1);break;case`template`:if(r[0]===`init`){let{templateInit:e}=await import(`./template-init-BFlRHOxK.mjs`);await e(r.slice(1))}else console.error(`Unknown template subcommand: ${r[0]}`),process.exitCode=1;break;case`doctor`:{let e=r.includes(`--ci`);if(r.includes(`--drift`)){let{runDoctorDrift:e}=await import(`./drift-BCtn9Ua_.mjs`);await e(await t())}else{let n=process.cwd(),r=await bt(n),{checkDuplicateCore:i,checkFormatterIgnore:a,checkProjectDependencies:o,checkSignalsCompat:s,checkSsrConfig:c,detectInstallPath:l}=await Promise.resolve().then(()=>tt),u=l(n)!==`unknown`,d=u?o(n):[],f=d.filter(e=>e.required),p=u?await s(n):null,m=p?.severity===`error`,h=u?c(n):null,g=u?await i(n):null,_=u?a(n,(await t()).outputDir):null,{runDoctorDrift:v}=await import(`./drift-BCtn9Ua_.mjs`),y=u?await v(await t(),n):{ran:!1,reason:`no cascivo install detected`,issues:0};if(r.passed&&d.length===0&&p===null&&h===null&&g===null&&_===null&&y.issues===0)console.log(y.ran?`No violations found.`:`No violations found (drift: not checked — ${y.reason}).`);else{for(let e of r.violations)console.error(`[${e.rule}] ${e.detail}\n ${e.file}`);for(let e of f)console.error(e.kind===`forbidden`?`[forbidden-dependency] ${e.package} must not be a direct dependency here. Remove it — ${e.hint}`:`[missing-dependency] ${e.package} is not in package.json. Install: ${e.hint}`);p&&(m?console.error:console.log)(`[${m?`signals-incompatible`:`signals-outdated`}] ${p.detail} Upgrade: ${p.hint}`),h&&console.log(`[ssr-config] ${h}`),_&&console.log(`[formatter-drift] ${_}`),g&&console.error(`[duplicate-core] More than one @cascivo/core is installed (root: ${g.root??`none`}; ${g.nested.join(`; `)}). `+g.hint);for(let e of d.filter(e=>!e.required))console.log(`[optional] ${e.package} is not installed; add it when a component or chart needs it: ${e.hint}`);e&&(r.violations.length>0||f.length>0||m||g!==null||y.issues>0)&&(process.exitCode=1)}}break}case`audit`:{let{audit:e}=await import(`./audit-DqWSsQGC.mjs`);await e(r,await t());break}case`email`:{let{email:e}=await import(`./email-CwQcZ-mB.mjs`);await e(r);break}case`tokens`:if(r[0]===`import`){let{tokensImport:e}=await import(`./tokens-VSJC9GgT.mjs`);await e(r.slice(1))}else console.error(`Unknown tokens subcommand: ${r[0]}`),process.exitCode=1;break;case void 0:case`--help`:case`-h`:case`help`:console.log(pn);break;case`--version`:case`-v`:console.log(Q);break;default:console.error(`Unknown command: ${n}\n`),console.log(pn),process.exitCode=1}}O[1]!==void 0&&import.meta.url===ne(O[1]).href&&hn(O.slice(2)).catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});export{Q as VERSION,hn as run};
829
+ overrides.`};async function jn(e){let[n,...r]=e;if(n!==void 0&&(r.includes(`--help`)||r.includes(`-h`))){let e=An[n];if(e!==void 0){console.log(e);return}}switch(n){case`create`:await mt(r);break;case`init`:await $t(r);break;case`add`:{let e=T(r);if(`error`in e){console.error(e.error),process.exitCode=1;break}await je(w(r,[`pm`,`package-manager`]),await t(),{dryRun:r.includes(`--dry-run`),yes:r.includes(`--yes`),noInstall:r.includes(`--no-install`),...e.pm?{pm:e.pm}:{}});break}case`list`:await an(await t(),{installed:r.includes(`--installed`)});break;case`update`:await Sn(r.filter(e=>!e.startsWith(`--`))[0],await t(),{check:r.includes(`--check`),yes:r.includes(`--yes`)});break;case`search`:await ln(r,await t());break;case`view`:await Dn(r,await t());break;case`theme`:await gn(r);break;case`eject`:{let{eject:e}=await import(`./eject-B94ujtUo.mjs`),n=e=>{let t=r.find(t=>t.startsWith(`--${e}=`));if(t)return t.slice(e.length+3);let n=r.indexOf(`--${e}`),i=n===-1?void 0:r[n+1];return i&&!i.startsWith(`--`)?i:void 0},i=n(`tokens`);await e(r,await t(),{...i?{tokens:i.split(`,`).map(e=>e.trim()).filter(Boolean)}:{},...n(`scope`)?{scope:n(`scope`)}:{},...n(`out`)?{out:n(`out`)}:{},dryRun:r.includes(`--dry-run`)});break}case`generate`:await Ut(r,await t());break;case`registry`:r[0]===`build`?await sn(r.slice(1)):(console.error(`Unknown registry subcommand: ${r[0]}`),process.exitCode=1);break;case`template`:if(r[0]===`init`){let{templateInit:e}=await import(`./template-init-BFlRHOxK.mjs`);await e(r.slice(1))}else console.error(`Unknown template subcommand: ${r[0]}`),process.exitCode=1;break;case`doctor`:{let e=r.includes(`--ci`);if(r.includes(`--drift`)){let{runDoctorDrift:e}=await import(`./drift-BCtn9Ua_.mjs`);await e(await t())}else{let n=process.cwd(),r=await Pt(n),{checkDuplicateCore:i,checkFormatterIgnore:a,checkProjectDependencies:o,checkSignalsCompat:s,checkSsrConfig:c,detectInstallPath:l}=await Promise.resolve().then(()=>ht),u=l(n)!==`unknown`,d=u?o(n):[],f=d.filter(e=>e.required),p=u?await s(n):null,m=p?.severity===`error`,h=u?c(n):null,g=u?await i(n):null,_=u?a(n,(await t()).outputDir):null,{runDoctorDrift:v}=await import(`./drift-BCtn9Ua_.mjs`),y=u?await v(await t(),n):{ran:!1,reason:`no cascivo install detected`,issues:0};if(r.passed&&d.length===0&&p===null&&h===null&&g===null&&_===null&&y.issues===0)console.log(y.ran?`No violations found.`:`No violations found (drift: not checked — ${y.reason}).`);else{for(let e of r.violations)console.error(`[${e.rule}] ${e.detail}\n ${e.file}`);for(let e of f)console.error(e.kind===`forbidden`?`[forbidden-dependency] ${e.package} must not be a direct dependency here. Remove it — ${e.hint}`:`[missing-dependency] ${e.package} is not in package.json. Install: ${e.hint}`);p&&(m?console.error:console.log)(`[${m?`signals-incompatible`:`signals-outdated`}] ${p.detail} Upgrade: ${p.hint}`),h&&console.log(`[ssr-config] ${h}`),_&&console.log(`[formatter-drift] ${_}`),g&&console.error(`[duplicate-core] More than one @cascivo/core is installed (root: ${g.root??`none`}; ${g.nested.join(`; `)}). `+g.hint);for(let e of d.filter(e=>!e.required))console.log(`[optional] ${e.package} is not installed; add it when a component or chart needs it: ${e.hint}`);e&&(r.violations.length>0||f.length>0||m||g!==null||y.issues>0)&&(process.exitCode=1)}}break}case`audit`:{let{audit:e}=await import(`./audit-DqWSsQGC.mjs`);await e(r,await t());break}case`email`:{let{email:e}=await import(`./email-CwQcZ-mB.mjs`);await e(r);break}case`tokens`:if(r[0]===`import`){let{tokensImport:e}=await import(`./tokens-VSJC9GgT.mjs`);await e(r.slice(1))}else console.error(`Unknown tokens subcommand: ${r[0]}`),process.exitCode=1;break;case void 0:case`--help`:case`-h`:case`help`:console.log(On);break;case`--version`:case`-v`:console.log($);break;default:console.error(`Unknown command: ${n}\n`),console.log(On),process.exitCode=1}}O[1]!==void 0&&import.meta.url===ne(O[1]).href&&jn(O.slice(2)).catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exitCode=1});export{$ as VERSION,jn as run};
628
830
  //# sourceMappingURL=index.mjs.map