velyx 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # Velar CLI
1
+ # Velyx CLI
2
2
 
3
- Velar CLI is a command-line tool for adding UI components to Laravel projects.
3
+ Velyx CLI is a command-line tool for adding UI components to Laravel projects.
4
4
 
5
5
  It delivers composable UI components built with **Blade**, **Alpine.js**, and **Tailwind CSS v4**.
6
- Inspired by shadcn, Velar gives you the code, not a dependency.
6
+ Inspired by shadcn, Velyx gives you the code, not a dependency.
7
7
 
8
8
  ---
9
9
 
10
- ## What Velar is
10
+ ## What Velyx is
11
11
 
12
12
  - A **code delivery tool** for Laravel UI components
13
13
  - A way to **copy components into your project**
14
14
  - A workflow that keeps **you in control of your code**
15
15
 
16
- ## What Velar is not
16
+ ## What Velyx is not
17
17
 
18
18
  - Not a UI framework
19
19
  - Not a runtime dependency
@@ -26,7 +26,7 @@ Once components are added, they belong to your project.
26
26
 
27
27
  ## Requirements
28
28
 
29
- Velar assumes a modern Laravel setup:
29
+ Velyx assumes a modern Laravel setup:
30
30
 
31
31
  - Laravel
32
32
  - Blade
@@ -39,12 +39,12 @@ Tailwind v3 is not supported.
39
39
 
40
40
  ## Usage
41
41
 
42
- Velar can be executed without installation.
42
+ Velyx can be executed without installation.
43
43
 
44
- ### Initialize Velar in a project
44
+ ### Initialize Velyx in a project
45
45
 
46
46
  ```bash
47
- npx velar init
47
+ npx velyx init
48
48
  ```
49
49
 
50
50
  This command:
@@ -57,10 +57,10 @@ This command:
57
57
  ### Add a component
58
58
 
59
59
  ```bash
60
- npx velar add button
60
+ npx velyx add button
61
61
  ```
62
62
 
63
- Velar will:
63
+ Velyx will:
64
64
 
65
65
  - fetch the component from the registry
66
66
  - resolve its dependencies
@@ -77,18 +77,18 @@ resources/views/components/ui
77
77
  ### List available components
78
78
 
79
79
  ```bash
80
- npx velar list
80
+ npx velyx list
81
81
  ```
82
82
 
83
83
  ---
84
84
 
85
85
  ## How updates work
86
86
 
87
- Velar does **not** update your code automatically.
87
+ Velyx does **not** update your code automatically.
88
88
 
89
89
  If a component changes in the registry and you want the new version:
90
90
 
91
- - run `velar add <component>` again
91
+ - run `velyx add <component>` again
92
92
  - review the changes
93
93
  - decide what to keep
94
94
 
@@ -98,12 +98,12 @@ This is intentional.
98
98
 
99
99
  ## Philosophy
100
100
 
101
- Velar follows a simple principle:
101
+ Velyx follows a simple principle:
102
102
 
103
103
  > You own your UI code.
104
104
 
105
105
  There are no hidden abstractions and no vendor lock-in.
106
- Velar exists to help you move faster, not to take control away from you.
106
+ Velyx exists to help you move faster, not to take control away from you.
107
107
 
108
108
  ---
109
109
 
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
- import b from'chalk';import {Command}from'commander';import x from'path';import y from'fs-extra';import Ce from'prompts';import R,{promises}from'fs';import {cyan,green,yellow,red}from'kleur/colors';import {exec}from'child_process';import {promisify}from'util';import rt from'ora';import {z as z$1}from'zod';import kt from'cli-table3';var Y=".bak";function ce(r){if(!y.existsSync(r))return null;let e=`${r}${Y}`;try{return y.renameSync(r,e),e}catch(t){return console.error(`Failed to create backup of ${r}: ${t}`),null}}function D(r){let e=`${r}${Y}`;if(!y.existsSync(e))return false;try{return y.renameSync(e,r),!0}catch(t){return console.error(`Warning: Could not restore backup file ${e}: ${t}`),false}}function M(r){let e=`${r}${Y}`;if(!y.existsSync(e))return false;try{return y.unlinkSync(e),!0}catch{return false}}var g=class{async fileExists(e){try{return await promises.access(e),!0}catch{return false}}async writeFile(e,t){await promises.mkdir(x.dirname(e),{recursive:true}),await promises.writeFile(e,t,"utf-8");}async readFile(e){return await promises.readFile(e,"utf-8")}async ensureDir(e){await promises.mkdir(e,{recursive:true});}};function pe(){return R.existsSync("composer.json")&&R.existsSync("artisan")}function me(){try{return JSON.parse(R.readFileSync("package.json","utf8"))}catch{return null}}function de(r){let e={...r.dependencies,...r.devDependencies};if(e["@tailwindcss/vite"]||e["@tailwindcss/postcss"])return true;if(e.tailwindcss){let o=String(e.tailwindcss).match(/(\d+)/);return o?Number(o[1])>=4:false}return false}function Ge(){try{let r=JSON.parse(R.readFileSync("package.json","utf8")),e=r.dependencies&&Object.keys(r.dependencies).some(o=>o.toLowerCase().includes("alpine")),t=r.devDependencies&&Object.keys(r.devDependencies).some(o=>o.toLowerCase().includes("alpine"));return !!(e||t)}catch{return false}}function Be(){let r="resources/views/layouts";if(!R.existsSync(r))return false;try{let e=R.readdirSync(r,{recursive:!0});for(let t of e)if(t.endsWith(".blade.php")&&R.readFileSync(x.join(r,t),"utf8").toLowerCase().includes("alpine"))return !0}catch{return false}return false}function fe(){return Ge()||Be()}function A(){return R.existsSync("pnpm-lock.yaml")||R.existsSync("pnpm-lock.yml")?"pnpm":R.existsSync("yarn.lock")?"yarn":R.existsSync("package-lock.json")?"npm":R.existsSync("bun.lock")?"bun":"npm"}var He=["resources/css/app.css","resources/css/app.scss","resources/css/main.css","resources/css/style.css","resources/css/styles.css"];function ue(){for(let r of He)if(R.existsSync(r))return {path:r,content:R.readFileSync(r,"utf8")};return null}function X(r){return /@import\s+["']tailwindcss["']/.test(r)}function ge(r){let e=R.readFileSync(r,"utf8");e.includes('@import "./velar.css"')||(X(e)?e=e.replace(/@import\s+["']tailwindcss["'];?/,t=>`${t}
2
- @import "./velar.css";`):e+=`
3
- @import "./velar.css";
4
- `,R.writeFileSync(r,e,"utf8"));}var qe=["resources/js/app.js","resources/js/main.js","resources/js/index.js"];function he(){for(let r of qe)if(R.existsSync(r))return {path:r,content:R.readFileSync(r,"utf8")};return null}function ye(r,e,t){let o=R.readFileSync(r,"utf8"),n=`import ${e} from '${t}'`;if(o.includes(n)||o.includes(`import ${e} from "${t}"`))return;let i=o.split(`
5
- `),a=-1;for(let c=0;c<i.length;c++)i[c]?.startsWith("import ")&&(a=c);i.splice(a+1,0,n),o=i.join(`
6
- `);let l=`Alpine.data('${e}', ${e});`;o.includes("document.addEventListener('alpine:init'")?o.includes(l)||(o=o.replace(/document\.addEventListener\('alpine:init',\s*\(\)\s*=>\s*\{/,c=>`${c}
7
- ${l}`)):o+=`
1
+ import v from'chalk';import {Command}from'commander';import b from'path';import w from'fs-extra';import Se from'prompts';import R,{promises}from'fs';import {cyan,green,yellow,red}from'kleur/colors';import {exec}from'child_process';import {promisify}from'util';import Ze from'ora';import {z as z$1}from'zod';import bt from'cli-table3';var H=".bak";function ae(r){if(!w.existsSync(r))return null;let e=`${r}${H}`;try{return w.renameSync(r,e),e}catch(t){return console.error(`Failed to create backup of ${r}: ${t}`),null}}function N(r){let e=`${r}${H}`;if(!w.existsSync(e))return false;try{return w.renameSync(e,r),!0}catch(t){return console.error(`Warning: Could not restore backup file ${e}: ${t}`),false}}function T(r){let e=`${r}${H}`;if(!w.existsSync(e))return false;try{return w.unlinkSync(e),!0}catch{return false}}var u=class{async fileExists(e){try{return await promises.access(e),!0}catch{return false}}async writeFile(e,t){await promises.mkdir(b.dirname(e),{recursive:true}),await promises.writeFile(e,t,"utf-8");}async readFile(e){return await promises.readFile(e,"utf-8")}async ensureDir(e){await promises.mkdir(e,{recursive:true});}};function le(){return R.existsSync("composer.json")&&R.existsSync("artisan")}function pe(){try{return JSON.parse(R.readFileSync("package.json","utf8"))}catch{return null}}function me(r){let e={...r.dependencies,...r.devDependencies};if(e["@tailwindcss/vite"]||e["@tailwindcss/postcss"])return true;if(e.tailwindcss){let n=String(e.tailwindcss).match(/(\d+)/);return n?Number(n[1])>=4:false}return false}function Ae(){try{let r=JSON.parse(R.readFileSync("package.json","utf8")),e=r.dependencies&&Object.keys(r.dependencies).some(n=>n.toLowerCase().includes("alpine")),t=r.devDependencies&&Object.keys(r.devDependencies).some(n=>n.toLowerCase().includes("alpine"));return !!(e||t)}catch{return false}}function Le(){let r="resources/views/layouts";if(!R.existsSync(r))return false;try{let e=R.readdirSync(r,{recursive:!0});for(let t of e)if(t.endsWith(".blade.php")&&R.readFileSync(b.join(r,t),"utf8").toLowerCase().includes("alpine"))return !0}catch{return false}return false}function de(){return Ae()||Le()}function D(){return R.existsSync("pnpm-lock.yaml")||R.existsSync("pnpm-lock.yml")?"pnpm":R.existsSync("yarn.lock")?"yarn":R.existsSync("package-lock.json")?"npm":R.existsSync("bun.lock")?"bun":"npm"}var Ue=["resources/css/app.css","resources/css/app.scss","resources/css/main.css","resources/css/style.css","resources/css/styles.css"];function fe(){for(let r of Ue)if(R.existsSync(r))return {path:r,content:R.readFileSync(r,"utf8")};return null}function K(r){return /@import\s+["']tailwindcss["']/.test(r)}function ue(r){let e=R.readFileSync(r,"utf8");e.includes('@import "./velyx.css"')||(K(e)?e=e.replace(/@import\s+["']tailwindcss["'];?/,t=>`${t}
2
+ @import "./velyx.css";`):e+=`
3
+ @import "./velyx.css";
4
+ `,R.writeFileSync(r,e,"utf8"));}var Je=["resources/js/app.js","resources/js/main.js","resources/js/index.js"];function ge(){for(let r of Je)if(R.existsSync(r))return {path:r,content:R.readFileSync(r,"utf8")};return null}function ye(r,e,t){let n=R.readFileSync(r,"utf8"),o=`import ${e} from '${t}'`;if(n.includes(o)||n.includes(`import ${e} from "${t}"`))return;let i=n.split(`
5
+ `),a=-1;for(let c=0;c<i.length;c++)i[c]?.startsWith("import ")&&(a=c);i.splice(a+1,0,o),n=i.join(`
6
+ `);let l=`Alpine.data('${e}', ${e});`;n.includes("document.addEventListener('alpine:init'")?n.includes(l)||(n=n.replace(/document\.addEventListener\('alpine:init',\s*\(\)\s*=>\s*\{/,c=>`${c}
7
+ ${l}`)):n+=`
8
8
 
9
9
  document.addEventListener('alpine:init', () => {
10
10
  ${l}
11
11
  });
12
- `,R.writeFileSync(r,o,"utf8");}function We(r){let e=r;for(let t=0;t<4;t+=1){let o=x.join(e,"colors");if(R.existsSync(o))return o;let n=x.join(e,"src/colors");if(R.existsSync(n))return n;let i=x.dirname(e);if(i===e)break;e=i;}return x.join(r,"colors")}var ze=process.argv[1]?x.dirname(x.resolve(process.argv[1])):process.cwd(),Q=We(ze);function ve(){return R.existsSync(Q)?R.readdirSync(Q).filter(e=>e.endsWith(".json")).map(e=>{let t=x.join(Q,e),o=R.readFileSync(t,"utf-8");return JSON.parse(o)}).filter(e=>!!e?.name).sort((e,t)=>e.name.localeCompare(t.name)):[]}function U(){return ve()}function Ke(r){return ve().find(e=>e.name===r)}function we(r){return Object.entries(r).map(([e,t])=>` --${e}: ${t};`)}function be(r,e){let t=Ke(r);if(!t)throw new Error(`Theme "${r}" not found in colors registry.`);let o=we(t.cssVars.light),n=we(t.cssVars.dark),i=[":root {",...o,"}","",".dark {",...n,"}",""].join(`
13
- `);R.writeFileSync(e,i,{encoding:"utf-8",flag:"wx"});}function xe(r){R.writeFileSync("velar.json",JSON.stringify(r,null,2)+`
14
- `,"utf8");}function Se(){if(!R.existsSync("velar.json"))throw new Error("Velar configuration not found.");return JSON.parse(R.readFileSync("velar.json","utf8"))}var m={error:red,warn:yellow,info:cyan,success:green};var s={error(...r){console.log(m.error(r.join(" ")));},warn(...r){console.log(m.warn(r.join(" ")));},info(...r){console.log(m.info(r.join(" ")));},success(...r){console.log(m.success(r.join(" ")));},log(...r){console.log(r.join(" "));},break(){console.log("");}};var N={version:"1.0.0"};var J=class{constructor(e){this.fileSystem=e;}validateEnvironment(){if(!pe())throw new Error("No Laravel project detected");let e=me();if(!e||!de(e))throw new Error("Tailwind CSS v4 was not detected");let t=fe(),o=A(),n=ue(),i=he(),a=n?X(n.content):false;return {isLaravel:true,hasTailwindV4:true,hasAlpine:t,detectedPackageManager:o,cssFile:n,jsFile:i,canInjectCss:a}}displayEnvironmentInfo(e){e.hasAlpine?s.success("Alpine.js detected - components will be fully interactive"):(s.warn("Alpine.js not detected"),s.log(`Install Alpine.js: ${e.detectedPackageManager} install alpinejs`)),e.cssFile?e.canInjectCss||(s.warn("Tailwind import not found in CSS"),s.log("Velar styles will not be auto-imported")):(s.warn("No main CSS file found"),s.log("Styles will be created but not auto-imported")),e.jsFile||(s.warn("No main JS file found"),s.log("Component scripts will not be auto-imported"));}async createComponentsDirectory(e="resources/views/components/ui"){await this.fileSystem.ensureDir(e);}async createThemeFile(e,t="resources/css/velar.css"){let o=t.split("/").slice(0,-1).join("/");if(await this.fileSystem.ensureDir(o),R.existsSync(t))s.info("velar.css already exists");else try{be(e,t),s.success("Velar theme created"),s.info(t);}catch(n){throw new Error(`Failed to create theme file: ${n.message}`)}}async injectStylesImport(e){ge(e),s.success("Velar styles imported"),s.info(e);}async generateConfig(e,t){let o={version:N.version,theme:e.theme,packageManager:e.packageManager,css:{entry:t.cssFile?.path??"",velar:"resources/css/velar.css"},js:{entry:t.jsFile?.path??""},components:{path:"resources/views/components/ui"}};xe(o),s.success("velar.json config generated");}displaySummary(e,t,o){console.log(`
15
- ---`),s.success("Laravel project detected"),s.success("Tailwind CSS v4 detected"),s.success(`Theme selected: ${e.theme}`),s.success(`Package manager: ${e.packageManager}`),s.success("UI components directory ready"),t.jsFile&&s.success("Main JS file detected"),s.success(o?"Styles import complete":"Styles import pending"),s.success("velar.json created"),console.log(`
16
- Next steps:`),console.log(" velar add button"),console.log(`
17
- \u{1F4A1} Want to customize your Tailwind palette? Try https://tweakcn.com/ \u2014 a visual generator for Tailwind-compatible color scales.`);}};var h={start(r){return rt(r).start()},async withTask(r,e,t,o){let n=this.start(r);try{let i=await e();return t?n.succeed(t):n.stop(),i}catch(i){throw n.fail(o||"Operation failed"),i}}};var st=promisify(exec);async function it(r){try{let e=x.resolve(r,"composer.json"),t=x.resolve(r,"package.json");if(!y.existsSync(e))return null;let o=await y.readJson(e);if(!(o.require?.["laravel/framework"]||o.require?.["illuminate/foundation"]))return null;let i=process.cwd();process.chdir(r);let a=A();console.log(`Detected package manager: ${a}`),process.chdir(i);let l={name:o.name||x.basename(r),framework:{name:"laravel",label:"Laravel",version:o.require?.["laravel/framework"]||"unknown"},hasAlpine:!1,hasVite:!1,packageManager:a,paths:{views:"resources/views",assets:"resources/js",public:"public",config:"config"}};if(y.existsSync(t)){let u=await y.readJson(t);l.hasAlpine=!!(u.dependencies?.alpinejs||u.devDependencies?.alpinejs),l.hasVite=!!u.devDependencies?.vite;}let c=x.resolve(r,"resources/views"),d=x.resolve(r,"resources/js");return y.existsSync(c)&&(l.paths.views="resources/views"),y.existsSync(d)&&(l.paths.assets="resources/js"),l}catch{return null}}async function ke(r){let e={};if(!y.existsSync(r.cwd))return e.MISSING_DIR=true,{errors:e,projectInfo:null};let t=h.start("Checking project environment..."),o=x.resolve(r.cwd,"velar.json");if(y.existsSync(o)&&!r.force){t.fail(),s.break();let{action:l}=await Ce({type:"select",name:"action",message:`A ${m.info("velar.json")} file already exists. What would you like to do?`,choices:[{title:"Re-initialize Velar configuration",value:"reinit"},{title:"Keep existing configuration",value:"keep"},{title:"Exit",value:"exit"}],initial:0});l==="exit"&&(s.log("Operation cancelled."),process.exit(0)),l==="keep"&&(s.log("Keeping existing configuration."),process.exit(0)),s.log("Re-initializing Velar configuration...");}let n=await it(r.cwd);(!n||n.framework.name!=="laravel")&&(e.UNSUPPORTED_PROJECT=true,t.fail(),s.break(),s.error(`We could not detect a supported Laravel project at ${m.info(r.cwd)}.
18
- Velar is designed to work with Laravel projects.`),s.break(),process.exit(1)),t.succeed(`Found ${m.info(n.framework.label)} project`);let i=h.start("Checking Alpine.js...");if(n.hasAlpine)i.succeed("Alpine.js found");else {i.fail(),s.break(),s.warn("Alpine.js is required but not found in your project.");let{installAlpine:l}=await Ce({type:"confirm",name:"installAlpine",message:"Would you like to install Alpine.js now?",initial:true});if(l){let c=n.packageManager,d=h.start(`Installing Alpine.js with ${c}...`);try{await st(`${c} install alpinejs`,{cwd:r.cwd}),d.succeed("Alpine.js installed successfully"),n.hasAlpine=!0;}catch(u){d.fail(`Failed to install Alpine.js: ${u.message}`),s.error(`Please install Alpine.js manually: ${m.info(`${c} install alpinejs`)}`),s.break(),process.exit(1);}}else {let c=n.packageManager;s.error(`Alpine.js is required. Install it with: ${m.info(`${c} install alpinejs`)}`),s.break(),process.exit(1);}}let a=h.start("Checking build tools...");return n.hasVite?a.succeed("Vite found"):(s.warn("Vite not found. Using Vite is recommended for better development experience."),a.warn("Vite not found (but optional)")),Object.keys(e).length>0&&(s.break(),process.exit(1)),{errors:e,projectInfo:n}}var Ee=z$1.object({baseColor:z$1.string().optional(),yes:z$1.boolean(),defaults:z$1.boolean(),force:z$1.boolean(),cwd:z$1.string(),silent:z$1.boolean()});async function at(){let r=U();r.length===0&&(s.error("No base colors available."),process.exit(1));let{theme:e}=await Ce({type:"select",name:"theme",message:"Choose a base color theme",choices:r.map(t=>({title:t.label,value:t.name}))},{onCancel:()=>{s.error("Theme selection aborted"),process.exit(1);}});return e}async function ct(){let{shouldImport:r}=await Ce({type:"confirm",name:"shouldImport",message:"Import Velar styles into your main CSS file?",initial:true},{onCancel:()=>false});return !!r}function lt(r){if(!r.baseColor)return;let t=U().find(o=>o.name===r.baseColor);if(t)return t.name;s.warn(`Unknown base color "${r.baseColor}".`);}async function Ie(r,e){e||(e=(await ke(r)).projectInfo),process.chdir(r.cwd);let t=new g,o=new J(t);try{let n=o.validateEnvironment();o.displayEnvironmentInfo(n);let i=e.packageManager,a=U(),l=a.find(u=>u.name==="neutral")?.name??a[0]?.name,c=lt(r);c||(c=r.defaults&&l?l:await at()),c||(s.error("No base color available."),process.exit(1)),await o.createComponentsDirectory(),await o.createThemeFile(c);let d=!1;n.cssFile&&n.canInjectCss&&(r.defaults||await ct())&&(await o.injectStylesImport(n.cssFile.path),d=!0),await o.generateConfig({packageManager:i,theme:c,importStyles:d},n),o.displaySummary({packageManager:i,theme:c,importStyles:d},n,d);}catch(n){s.error(n.message),n instanceof Error&&(n.message.includes("Laravel project")?s.log("Run velar init at the root of a Laravel project"):n.message.includes("Tailwind")&&s.log(`Velar requires ${m.info("Tailwind CSS v4+")}`)),process.exit(1);}}process.on("exit",r=>{let e=x.resolve(process.cwd(),"velar.json");return r===0?M(e):D(e)});var Fe=new Command().name("init").description("initialize your project and install dependencies").option("-b, --base-color <base-color>","the base color to use. (neutral, gray, zinc, stone, slate)",void 0).option("-y, --yes","skip confirmation prompt.",true).option("-d, --defaults","use default configuration.",false).option("-f, --force","force overwrite of existing configuration.",false).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-s, --silent","mute output.",false).action(async r=>{let e=Ee.parse({baseColor:r.baseColor,yes:!!r.yes,defaults:!!r.defaults,force:!!r.force,cwd:x.resolve(r.cwd),silent:!!r.silent});await Ie(e);});var te=class extends Error{constructor(t,o,n){super(t);this.code=o;this.context=n;this.name="VelarError";}},I=class{handle(e,t){e instanceof te?(console.error(`[${e.code}] ${e.message}`),e.context&&console.error("Context:",e.context)):console.error(`Unexpected error in ${t}: ${e.message}`);}};var mt={UNKNOWN_ERROR:"UNKNOWN_ERROR"},G=class extends Error{code;statusCode;context;suggestion;timestamp;cause;constructor(e,t={}){super(e),this.name="RegistryError",this.code=t.code||mt.UNKNOWN_ERROR,this.statusCode=t.statusCode,this.cause=t.cause,this.context=t.context,this.suggestion=t.suggestion,this.timestamp=new Date,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}toJSON(){return {name:this.name,message:this.message,code:this.code,statusCode:this.statusCode,context:this.context,suggestion:this.suggestion,timestamp:this.timestamp,stack:this.stack}}};function re(r){if(s.break(),s.error("Something went wrong. Please check the error below for more details."),s.error("If the problem persists, please open an issue on GitHub."),s.error(""),typeof r=="string"&&(s.error(r),s.break(),process.exit(1)),r instanceof G&&(r.message&&(s.error(r.cause?"Error:":"Message:"),s.error(r.message)),r.cause&&(s.error(`
12
+ `,R.writeFileSync(r,n,"utf8");}function qe(r){let e=r;for(let t=0;t<4;t+=1){let n=b.join(e,"colors");if(R.existsSync(n))return n;let o=b.join(e,"src/colors");if(R.existsSync(o))return o;let i=b.dirname(e);if(i===e)break;e=i;}return b.join(r,"colors")}var Be=process.argv[1]?b.dirname(b.resolve(process.argv[1])):process.cwd(),X=qe(Be);function we(){return R.existsSync(X)?R.readdirSync(X).filter(e=>e.endsWith(".json")).map(e=>{let t=b.join(X,e),n=R.readFileSync(t,"utf-8");return JSON.parse(n)}).filter(e=>!!e?.name).sort((e,t)=>e.name.localeCompare(t.name)):[]}function A(){return we()}function We(r){return we().find(e=>e.name===r)}function he(r){return Object.entries(r).map(([e,t])=>` --${e}: ${t};`)}function xe(r,e){let t=We(r);if(!t)throw new Error(`Theme "${r}" not found in colors registry.`);let n=he(t.cssVars.light),o=he(t.cssVars.dark),i=[":root {",...n,"}","",".dark {",...o,"}",""].join(`
13
+ `);R.writeFileSync(e,i,{encoding:"utf-8",flag:"wx"});}var m={error:red,warn:yellow,info:cyan,success:green};var s={error(...r){console.log(m.error(r.join(" ")));},warn(...r){console.log(m.warn(r.join(" ")));},info(...r){console.log(m.info(r.join(" ")));},success(...r){console.log(m.success(r.join(" ")));},log(...r){console.log(r.join(" "));},break(){console.log("");}};function ve(r){R.writeFileSync("velyx.json",JSON.stringify(r,null,2)+`
14
+ `,"utf8");}function be(){return R.existsSync("velyx.json")||(s.error("Velyx configuration not found."),process.exit(1)),JSON.parse(R.readFileSync("velyx.json","utf8"))}var P={version:"1.0.3"};var L=class{constructor(e){this.fileSystem=e;}validateEnvironment(){if(!le())throw new Error("No Laravel project detected");let e=pe();if(!e||!me(e))throw new Error("Tailwind CSS v4 was not detected");let t=de(),n=D(),o=fe(),i=ge(),a=o?K(o.content):false;return {isLaravel:true,hasTailwindV4:true,hasAlpine:t,detectedPackageManager:n,cssFile:o,jsFile:i,canInjectCss:a}}displayEnvironmentInfo(e){e.hasAlpine?s.success("Alpine.js detected - components will be fully interactive"):(s.warn("Alpine.js not detected"),s.log(`Install Alpine.js: ${e.detectedPackageManager} install alpinejs`)),e.cssFile?e.canInjectCss||(s.warn("Tailwind import not found in CSS"),s.log("Velyx styles will not be auto-imported")):(s.warn("No main CSS file found"),s.log("Styles will be created but not auto-imported")),e.jsFile||(s.warn("No main JS file found"),s.log("Component scripts will not be auto-imported"));}async createComponentsDirectory(e="resources/views/components/ui"){await this.fileSystem.ensureDir(e);}async createThemeFile(e,t="resources/css/velyx.css"){let n=t.split("/").slice(0,-1).join("/");if(await this.fileSystem.ensureDir(n),R.existsSync(t))s.info("velyx.css already exists");else try{xe(e,t),s.success("Velyx theme created"),s.info(t);}catch(o){throw new Error(`Failed to create theme file: ${o.message}`)}}async injectStylesImport(e){ue(e),s.success("Velyx styles imported"),s.info(e);}async generateConfig(e,t){let n={version:P.version,theme:e.theme,packageManager:e.packageManager,css:{entry:t.cssFile?.path??"",velyx:"resources/css/velyx.css"},js:{entry:t.jsFile?.path??""},components:{path:"resources/views/components/ui"}};ve(n),s.success("velyx.json config generated");}displaySummary(e,t,n){console.log(`
15
+ ---`),s.success("Laravel project detected"),s.success("Tailwind CSS v4 detected"),s.success(`Theme selected: ${e.theme}`),s.success(`Package manager: ${e.packageManager}`),s.success("UI components directory ready"),t.jsFile&&s.success("Main JS file detected"),s.success(n?"Styles import complete":"Styles import pending"),s.success("velyx.json created"),console.log(`
16
+ Next steps:`),console.log(" velyx add button"),console.log(`
17
+ \u{1F4A1} Want to customize your Tailwind palette? Try https://tweakcn.com/ \u2014 a visual generator for Tailwind-compatible color scales.`);}};var y={start(r){return Ze(r).start()},async withTask(r,e,t,n){let o=this.start(r);try{let i=await e();return t?o.succeed(t):o.stop(),i}catch(i){throw o.fail(n||"Operation failed"),i}}};var tt=promisify(exec);async function rt(r){try{let e=b.resolve(r,"composer.json"),t=b.resolve(r,"package.json");if(!w.existsSync(e))return null;let n=await w.readJson(e);if(!(n.require?.["laravel/framework"]||n.require?.["illuminate/foundation"]))return null;let i=process.cwd();process.chdir(r);let a=D();console.log(`Detected package manager: ${a}`),process.chdir(i);let l={name:n.name||b.basename(r),framework:{name:"laravel",label:"Laravel",version:n.require?.["laravel/framework"]||"unknown"},hasAlpine:!1,hasVite:!1,packageManager:a,paths:{views:"resources/views",assets:"resources/js",public:"public",config:"config"}};if(w.existsSync(t)){let g=await w.readJson(t);l.hasAlpine=!!(g.dependencies?.alpinejs||g.devDependencies?.alpinejs),l.hasVite=!!g.devDependencies?.vite;}let c=b.resolve(r,"resources/views"),d=b.resolve(r,"resources/js");return w.existsSync(c)&&(l.paths.views="resources/views"),w.existsSync(d)&&(l.paths.assets="resources/js"),l}catch{return null}}async function Ce(r){let e={};if(!w.existsSync(r.cwd))return e.MISSING_DIR=true,{errors:e,projectInfo:null};let t=y.start("Checking project environment..."),n=b.resolve(r.cwd,"velyx.json");if(w.existsSync(n)&&!r.force){t.fail(),s.break();let{action:l}=await Se({type:"select",name:"action",message:`A ${m.info("velyx.json")} file already exists. What would you like to do?`,choices:[{title:"Re-initialize Velyx configuration",value:"reinit"},{title:"Keep existing configuration",value:"keep"},{title:"Exit",value:"exit"}],initial:0});l==="exit"&&(s.log("Operation cancelled."),process.exit(0)),l==="keep"&&(s.log("Keeping existing configuration."),process.exit(0)),s.log("Re-initializing Velyx configuration...");}let o=await rt(r.cwd);(!o||o.framework.name!=="laravel")&&(e.UNSUPPORTED_PROJECT=true,t.fail(),s.break(),s.error(`We could not detect a supported Laravel project at ${m.info(r.cwd)}.
18
+ Velyx is designed to work with Laravel projects.`),s.break(),process.exit(1)),t.succeed(`Found ${m.info(o.framework.label)} project`);let i=y.start("Checking Alpine.js...");if(o.hasAlpine)i.succeed("Alpine.js found");else {i.fail(),s.break(),s.warn("Alpine.js is required but not found in your project.");let{installAlpine:l}=await Se({type:"confirm",name:"installAlpine",message:"Would you like to install Alpine.js now?",initial:true});if(l){let c=o.packageManager,d=y.start(`Installing Alpine.js with ${c}...`);try{await tt(`${c} install alpinejs`,{cwd:r.cwd}),d.succeed("Alpine.js installed successfully"),o.hasAlpine=!0;}catch(g){d.fail(`Failed to install Alpine.js: ${g.message}`),s.error(`Please install Alpine.js manually: ${m.info(`${c} install alpinejs`)}`),s.break(),process.exit(1);}}else {let c=o.packageManager;s.error(`Alpine.js is required. Install it with: ${m.info(`${c} install alpinejs`)}`),s.break(),process.exit(1);}}let a=y.start("Checking build tools...");return o.hasVite?a.succeed("Vite found"):(s.warn("Vite not found. Using Vite is recommended for better development experience."),a.warn("Vite not found (but optional)")),Object.keys(e).length>0&&(s.break(),process.exit(1)),{errors:e,projectInfo:o}}var ke=z$1.object({baseColor:z$1.string().optional(),yes:z$1.boolean(),defaults:z$1.boolean(),force:z$1.boolean(),cwd:z$1.string(),silent:z$1.boolean()});async function nt(){let r=A();r.length===0&&(s.error("No base colors available."),process.exit(1));let{theme:e}=await Se({type:"select",name:"theme",message:"Choose a base color theme",choices:r.map(t=>({title:t.label,value:t.name}))},{onCancel:()=>{s.error("Theme selection aborted"),process.exit(1);}});return e}async function ot(){let{shouldImport:r}=await Se({type:"confirm",name:"shouldImport",message:"Import Velyx styles into your main CSS file?",initial:true},{onCancel:()=>false});return !!r}function st(r){if(!r.baseColor)return;let t=A().find(n=>n.name===r.baseColor);if(t)return t.name;s.warn(`Unknown base color "${r.baseColor}".`);}async function Ee(r,e){e||(e=(await Ce(r)).projectInfo),process.chdir(r.cwd);let t=new u,n=new L(t);try{let o=n.validateEnvironment();n.displayEnvironmentInfo(o);let i=e.packageManager,a=A(),l=a.find(g=>g.name==="neutral")?.name??a[0]?.name,c=st(r);c||(c=r.defaults&&l?l:await nt()),c||(s.error("No base color available."),process.exit(1)),await n.createComponentsDirectory(),await n.createThemeFile(c);let d=!1;o.cssFile&&o.canInjectCss&&(r.defaults||await ot())&&(await n.injectStylesImport(o.cssFile.path),d=!0),await n.generateConfig({packageManager:i,theme:c,importStyles:d},o),n.displaySummary({packageManager:i,theme:c,importStyles:d},o,d);}catch(o){s.error(o.message),o instanceof Error&&(o.message.includes("Laravel project")?s.log("Run velyx init at the root of a Laravel project"):o.message.includes("Tailwind")&&s.log(`Velyx requires ${m.info("Tailwind CSS v4+")}`)),process.exit(1);}}process.on("exit",r=>{let e=b.resolve(process.cwd(),"velyx.json");return r===0?T(e):N(e)});var Fe=new Command().name("init").description("initialize your project and install dependencies").option("-b, --base-color <base-color>","the base color to use. (neutral, gray, zinc, stone, slate)",void 0).option("-y, --yes","skip confirmation prompt.",true).option("-d, --defaults","use default configuration.",false).option("-f, --force","force overwrite of existing configuration.",false).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-s, --silent","mute output.",false).action(async r=>{let e=ke.parse({baseColor:r.baseColor,yes:!!r.yes,defaults:!!r.defaults,force:!!r.force,cwd:b.resolve(r.cwd),silent:!!r.silent});await Ee(e);});var Q=class extends Error{constructor(t,n,o){super(t);this.code=n;this.context=o;this.name="VelyxError";}},E=class{handle(e,t){e instanceof Q?(console.error(`[${e.code}] ${e.message}`),e.context&&console.error("Context:",e.context)):console.error(`Unexpected error in ${t}: ${e.message}`);}};var at={UNKNOWN_ERROR:"UNKNOWN_ERROR"},U=class extends Error{code;statusCode;context;suggestion;timestamp;cause;constructor(e,t={}){super(e),this.name="RegistryError",this.code=t.code||at.UNKNOWN_ERROR,this.statusCode=t.statusCode,this.cause=t.cause,this.context=t.context,this.suggestion=t.suggestion,this.timestamp=new Date,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}toJSON(){return {name:this.name,message:this.message,code:this.code,statusCode:this.statusCode,context:this.context,suggestion:this.suggestion,timestamp:this.timestamp,stack:this.stack}}};function ee(r){if(s.break(),s.error("Something went wrong. Please check the error below for more details."),s.error("If the problem persists, please open an issue on GitHub."),s.error(""),typeof r=="string"&&(s.error(r),s.break(),process.exit(1)),r instanceof U&&(r.message&&(s.error(r.cause?"Error:":"Message:"),s.error(r.message)),r.cause&&(s.error(`
19
19
  Message:`),s.error(r.cause)),r.suggestion&&(s.error(`
20
- Suggestion:`),s.error(r.suggestion)),s.break(),process.exit(1)),r instanceof z$1.ZodError){s.error("Validation failed:");for(let[e,t]of Object.entries(r.flatten().fieldErrors))s.error(`- ${m.info(e)}: ${t}`);s.break(),process.exit(1);}r instanceof Error&&(s.error(r.message),s.break(),process.exit(1)),s.break(),process.exit(1);}var B=class{config;async load(){try{return this.config=Se(),this.config||(s.error(""),re(new Error("Configuration not found")),process.exit(1)),this.config}catch{s.error(""),re(new Error("Something went wrong. Please try again.")),process.exit(1);}}getPackageManager(){if(!this.config)throw new Error("Configuration not loaded");return this.config.packageManager||"npm"}validate(){return !!this.config}getComponentsPath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.components.path}getThemePath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.css.velar}getJsEntryPath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.js?.entry??""}getTheme(){if(!this.config)throw new Error("Configuration not loaded");return this.config.theme}};var H=promisify(exec);function gt(r){return r.startsWith("@")?r:r.replace("@",":")}var q=class{fileSystem;constructor(e){this.fileSystem=e??new g;}async installDependencies(e,t){let o=[],n=[];e.npm&&e.npm.length>0&&o.push(this.installNpmDependencies(e.npm,t)),e.composer&&e.composer.length>0&&n.push(this.installComposerDependencies(e.composer)),await Promise.allSettled([...o,...n]);}async installNpmDependencies(e,t){if(!this.fileSystem.fileExists("package.json")){s.warn("No package.json found, skipping npm dependencies");return}let o=await this.filterMissingNpmDependencies(e);if(o.length===0){s.info("All npm dependencies already installed");return}let n=this.getNpmInstallCommand(t,o);try{s.info(`Installing npm dependencies: ${o.join(", ")}`);let{stdout:i,stderr:a}=await H(n,{cwd:process.cwd(),timeout:12e4});i&&process.env.NODE_ENV!=="test"&&console.log(i),a&&!a.includes("WARN")&&s.warn(`npm install warnings: ${a}`),s.success(`Installed ${o.length} npm dependencies`);}catch(i){throw s.error(`Failed to install npm dependencies: ${i.message}`),i}}async installComposerDependencies(e){if(!this.fileSystem.fileExists("composer.json")){s.warn("No composer.json found, skipping composer dependencies");return}let t=e.map(gt),o=await this.filterMissingComposerDependencies(t);if(o.length===0){s.info("All composer dependencies already installed");return}try{s.info(`Installing composer dependencies: ${o.join(", ")}`);let{stdout:n,stderr:i}=await H(`composer require ${o.join(" ")}`,{cwd:process.cwd(),timeout:3e5});n&&process.env.NODE_ENV!=="test"&&console.log(n),i&&s.warn(`composer require warnings: ${i}`),s.success(`Installed ${o.length} composer dependencies`);}catch(n){throw s.error(`Failed to install composer dependencies: ${n.message}`),n}}getNpmInstallCommand(e,t){switch(e){case "pnpm":return `pnpm add ${t.join(" ")}`;case "yarn":return `yarn add ${t.join(" ")}`;case "bun":return `bun add ${t.join(" ")}`;default:return `npm install ${t.join(" ")}`}}async filterMissingNpmDependencies(e){try{let{stdout:t}=await H("npm list --json --depth=0",{cwd:process.cwd(),timeout:3e4}),o=JSON.parse(t),n=Object.keys({...o.dependencies,...o.devDependencies});return e.filter(i=>{let a=i.split("@")[0];return !n.includes(a)})}catch{return e}}async filterMissingComposerDependencies(e){try{let{stdout:t}=await H("composer show --installed --format=json",{cwd:process.cwd(),timeout:3e4}),n=JSON.parse(t).installed.map(i=>i.name);return e.filter(i=>{let a=i.split(":")[0];return !n.includes(a)})}catch{return e}}};var z=class{constructor(e,t,o){this.registryService=e;this.configManager=o;if(this.fileSystem=t??new g,this.dependencyService=new q(this.fileSystem),!this.configManager)throw new Error("ConfigManager is required")}fileSystem;dependencyService;async addComponents(e){let t={added:[],skipped:[],failed:[]};for(let o of e)try{let n=await this.addComponent(o);t.added.push(...n.added),t.skipped.push(...n.skipped),t.failed.push(...n.failed);}catch(n){t.failed.push({name:o,error:n.message});}return t}async addComponent(e){let t={added:[],skipped:[],failed:[]},o=await this.registryService.fetchComponent(e),n=await this.registryService.resolveDependencies(o);if(o.dependencies){let l=this.configManager.getPackageManager();try{await this.dependencyService.installDependencies(o.dependencies,l);}catch(c){s.warn(`Failed to install dependencies for ${e}: ${c.message}`);}}let i=this.configManager.getComponentsPath(),a=[];for(let l of n)for(let c of l.files){let d=this.getDestinationPath(l,c,i),u=await this.fileSystem.fileExists(d);if(u){let ae=await this.handleFileConflict(c.path);if(ae==="skip"){t.skipped.push(`${l.name}/${c.path}`);continue}else ae==="cancel"&&(s.error("Cancelled."),process.exit(0));}let _e=await this.registryService.fetchFile(l.name,c.path);a.push({componentName:l.name,filePath:c.path,fileType:c.type,destPath:d,content:_e,existedBefore:u});}if(a.length>0)try{await this.applyFileBatch(a),a.forEach(c=>t.added.push(`${c.componentName}/${c.filePath}`));let l=new Set(a.filter(c=>c.fileType==="js").map(c=>c.componentName));for(let c of Array.from(l))await this.autoImportJs(c);}catch(l){a.forEach(c=>t.failed.push({name:`${c.componentName}/${c.filePath}`,error:l.message}));}return t}async autoImportJs(e){try{let t=this.configManager?.getJsEntryPath();if(!t||!await this.fileSystem.fileExists(t))return;let o=`./ui/${e}`;ye(t,e,o),s.success(`Auto-imported ${e} into ${t}`);}catch(t){s.warn(`Failed to auto-import JS for ${e}: ${t.message}`);}}getDestinationPath(e,t,o){switch(t.type){case "blade":return x.join(o,`${e.name}.blade.php`);case "js":return x.join("resources/js/ui",`${e.name}.js`);case "css":return x.join("resources/css/components",`${e.name}.css`);default:return x.join(o,t.path)}}async handleFileConflict(e){let{action:t}=await Ce({type:"select",name:"action",message:`File "${e}" already exists. What do you want to do?`,choices:[{title:"Skip",value:"skip"},{title:"Overwrite",value:"overwrite"},{title:"Cancel",value:"cancel"}],initial:0},{onCancel:()=>{s.error("Cancelled."),process.exit(0);}});return t}async applyFileBatch(e){let t=[],o=[];try{for(let n of e){let i=`${n.destPath}.velar-tmp`;await this.fileSystem.writeFile(i,n.content),t.push(i);}for(let n of e){if(!n.existedBefore)continue;if(!ce(n.destPath))throw new Error(`Failed to create backup for ${n.destPath}`);o.push(n.destPath);}for(let n of e){let i=`${n.destPath}.velar-tmp`;await y.move(i,n.destPath,{overwrite:!0});}o.forEach(n=>M(n));}catch(n){for(let i of e)await this.fileSystem.fileExists(i.destPath)&&await y.remove(i.destPath),i.existedBefore&&D(i.destPath);for(let i of t)await this.fileSystem.fileExists(i)&&await y.remove(i);throw n}}};var K=class{constructor(e,t,o){this.registryService=e;this.configManager=t;this.componentService=o??new z(e,new g,t);}componentService;validateInitialization(){if(!this.configManager.validate())throw new Error("Velar is not initialized")}validateComponents(e,t){for(let o of e)if(!t.components.find(i=>i.name===o))throw new Error(`Component "${o}" not found`)}async getAvailableComponents(){return await this.registryService.fetchRegistry()}async addComponents(e){return await this.componentService.addComponents(e)}displayResults(e){e.added.forEach(t=>s.success(`Added ${t}`)),e.skipped.forEach(t=>s.warn(`Skipped ${t}`)),e.failed.forEach(({name:t,error:o})=>s.error(`Failed to add ${t}: ${o}`));}displayNextSteps(e){if(e.added.length===0)return;console.log(`
21
- \u{1F389} Happy coding! Enjoy building beautiful components!`);let t=e.added.filter(n=>n.endsWith(".js")),o=this.configManager.validate()&&this.configManager.getJsEntryPath();t.length>0&&!o&&(console.log(" Import JS files in your app.js:"),t.forEach(n=>{let i=n.split("/")[1];i&&console.log(` import './ui/${i}'`);}));}};var T=()=>"https://api.github.com/repos/velar-ui/registry/contents";var Z=class extends Error{constructor(t,o){super(t);this.cause=o;this.name="RegistryError";}},p=class extends Z{constructor(e,t){super(e,t),this.name="NetworkError";}},C=class extends Z{constructor(e,t){super(`Component "${e}" not found`,t),this.name="ComponentNotFoundError";}};var w={maxRetries:3,initialDelay:1e3,backoffFactor:2,maxDelay:1e4,retryableStatusCodes:[408,429,500,502,503,504],timeout:3e4,headers:{}};function ne(r){return new Promise(e=>setTimeout(e,r))}function se(r,e,t,o){let n=e*Math.pow(t,r);return Math.min(n,o)}function yt(r,e){return e.includes(r)}async function wt(r,e){let{timeout:t=w.timeout,headers:o={}}=e,n=new AbortController,i=setTimeout(()=>n.abort(),t);try{return await fetch(r,{signal:n.signal,headers:{"User-Agent":"Velar-CLI",...o}})}catch(a){throw a instanceof Error&&a.name==="AbortError"?new p(`Request timeout after ${t}ms for ${r}`,a):a}finally{clearTimeout(i);}}var j=class{async fetch(e,t={}){let o={maxRetries:t.maxRetries??w.maxRetries,initialDelay:t.initialDelay??w.initialDelay,backoffFactor:t.backoffFactor??w.backoffFactor,maxDelay:t.maxDelay??w.maxDelay,retryableStatusCodes:t.retryableStatusCodes??w.retryableStatusCodes,timeout:t.timeout??w.timeout,headers:t.headers??w.headers},n=null;for(let i=0;i<=o.maxRetries;i++)try{let a=await wt(e,{...t,timeout:o.timeout,headers:o.headers});if(a.ok||!yt(a.status,o.retryableStatusCodes))return a;if(console.log("Attempt: ",i),i===o.maxRetries)throw new p(`Request failed after ${o.maxRetries+1} attempts: ${a.status} ${a.statusText}`);let l=se(i,o.initialDelay,o.backoffFactor,o.maxDelay);await ne(l);}catch(a){if(n=a,a instanceof p&&a.message.includes("timeout")){if(i===o.maxRetries)throw a;let c=se(i,o.initialDelay,o.backoffFactor,o.maxDelay);await ne(c);continue}if(i===o.maxRetries)throw n instanceof p?n:new p(`Request failed after ${o.maxRetries+1} attempts: ${n.message}`,n);let l=se(i,o.initialDelay,o.backoffFactor,o.maxDelay);await ne(l);}throw new p(`Request failed after ${o.maxRetries+1} attempts: ${n?.message??"Unknown error"}`,n??void 0)}async fetchJson(e,t){let o=await this.fetch(e,t);if(!o.ok)throw new p(`Failed to fetch JSON from ${e}: ${o.status} ${o.statusText}`);try{return await o.json()}catch(n){throw new p(`Failed to parse JSON from ${e}: ${n.message}`,n)}}async fetchText(e,t){let o=await this.fetch(e,t);if(!o.ok)throw new p(`Failed to fetch text from ${e}: ${o.status} ${o.statusText}`);try{return await o.text()}catch(n){throw new p(`Failed to read text from ${e}: ${n.message}`,n)}}};var v=new j;async function $e(r="main"){try{let e=`https://raw.githubusercontent.com/velar-ui/registry/${r}/registry.json`;try{return await v.fetchJson(e)}catch{}let t=await v.fetchJson(`${T()}/components`),o=[];for(let n of t)if(n.type==="dir")try{let i=await v.fetchJson(`${T()}/components/${n.name}/meta.json`);o.push({...i,name:n.name,path:n.path});}catch{o.push({name:n.name,path:n.path,files:[]});}return {components:o}}catch(e){throw e instanceof p?e:new p(`Failed to fetch remote registry: ${e.message}`,e)}}async function Pe(r){try{let e=`${T()}/components/${r}/meta.json`,t=await v.fetch(e);if(t.status===404)throw new C(r);if(!t.ok)throw new p(`Component meta not found: ${t.status} ${t.statusText}`);return await v.fetchJson(e)}catch(e){throw e instanceof C||e instanceof p?e:new p(`Failed to fetch component meta for "${r}": ${e.message}`,e)}}async function Oe(r,e){try{let t=`${T()}/components/${r}/${e}`,o=await v.fetch(t);if(o.status===404)throw new C(r);if(!o.ok)throw new p(`File not found: ${o.status} ${o.statusText}`);let n=await v.fetchJson(t);if(!n.download_url)throw new p("File has no download URL");return await v.fetchText(n.download_url)}catch(t){throw t instanceof C||t instanceof p?t:new p(`Failed to fetch file "${e}" for component "${r}": ${t.message}`,t)}}var F=class{httpService;constructor(e){this.httpService=e??new j;}async fetchRegistry(){return await h.withTask("Fetching registry...",()=>$e(),void 0,"Failed to fetch registry")}async fetchComponent(e){let t=await h.withTask(`Fetching component "${e}" metadata...`,()=>Pe(e),void 0,`Failed to fetch component "${e}"`);return await this.parseComponentMeta(t)}async fetchFile(e,t){let o=e.split("/").pop()||e;return await h.withTask(`Downloading ${t}...`,()=>Oe(o,t),void 0,`Failed to fetch file "${t}"`)}async resolveDependencies(e){let t=new Set,o=[];return await(async i=>{t.has(i.name)||(t.add(i.name),o.push(i));})(e),o}async parseComponentMeta(e){if(!e.download_url)throw new Error("GitHub file has no download URL");try{let t=await this.httpService.fetchText(e.download_url);return JSON.parse(t)}catch(t){throw new Error(`Failed to parse component meta: ${t.message}`)}}};async function bt(r,e){if(r.all)return [...e];if(r.components?.length)return r.components;s.info("Use arrow keys and space to select, then press enter.");let{components:t}=await Ce({type:"multiselect",name:"components",message:"Which components would you like to add?",hint:"Space to select. A to toggle all. Enter to submit.",instructions:false,choices:e.map(n=>({title:n,value:n,selected:r.all?true:r.components?.includes(n)}))});t?.length||(s.warn("No components selected. Exiting."),s.info(""),process.exit(1));let o=z$1.array(z$1.string()).safeParse(t);return o.success||(s.error("Something went wrong. Please try again."),process.exit(1)),o.data}async function Te(r){let e=new B;await e.load();let t=new F,o=new K(t,e);try{o.validateInitialization();}catch{s.error("Velar is not initialized"),s.log("Run velar init first"),process.exit(1);}let n=await o.getAvailableComponents(),i=n.components.map(c=>c.name).sort((c,d)=>c.localeCompare(d)),a=await bt(r,i);try{o.validateComponents(a,n);}catch(c){s.error(c.message),s.log("Run velar list to see available components"),process.exit(1);}let l=await o.addComponents(a);o.displayResults(l),o.displayNextSteps(l);}var Ct=z$1.object({components:z$1.array(z$1.string()).optional(),yes:z$1.boolean(),overwrite:z$1.boolean(),cwd:z$1.string(),all:z$1.boolean(),path:z$1.string().optional(),silent:z$1.boolean(),srcDir:z$1.boolean().optional(),cssVariables:z$1.boolean().optional()}),De=new Command().name("add").argument("[components...]","Names of components to add").option("-y, --yes","skip confirmation prompt.",false).option("-o, --overwrite","overwrite existing files.",false).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-a, --all","add all available components",false).option("-p, --path <path>","the path to add the component to.").option("-s, --silent","mute output.",false).option("--src-dir","use the src directory when creating a new project.",false).option("--no-src-dir","do not use the src directory when creating a new project.").option("--css-variables","use CSS variables for theming.",true).option("--no-css-variables","do not use CSS variables for theming.").description("Add one or more UI components to your Laravel project").action(async(r,e)=>{let t=new I;try{let o={components:r,cwd:x.resolve(e.cwd),...e,cssVariables:e.cssVariables??!0},n=Ct.parse(o);await Te(n);}catch(o){t.handle(o,"add command"),process.exit(1);}});function Rt(r,e){if(!e)return [...r];let t=e.toLowerCase();return r.filter(o=>{let n=o.name.toLowerCase().includes(t),i=o.description?o.description.toLowerCase().includes(t):false,a=o.categories?o.categories.some(l=>l.toLowerCase().includes(t)):false;return n||i||a})}function Et(r,e,t){let o=Math.max(0,e??0);return t===void 0?r.slice(o):r.slice(o,o+Math.max(0,t))}async function Me(r){let o=[...(await new F().fetchRegistry()).components].sort((l,c)=>l.name.localeCompare(c.name)),n=Rt(o,r.query),i=Et(n,r.offset,r.limit);if(r.json){console.log(JSON.stringify({total:n.length,count:i.length,offset:r.offset??0,limit:r.limit??null,components:i},null,2));return}if(i.length===0){s.warn("No components found.");return}console.log(b.bold(`
22
- Available components:`)),console.log("");let a=new kt({head:[b.bold("Component"),b.bold("Description"),b.bold("Categories")],colWidths:[24,50,24],wordWrap:true,style:{head:[],border:[]}});for(let l of i)a.push([b.cyan(l.name),b.white(l.description||"No description"),b.gray(l.categories?.join(", ")||"-")]);console.log(a.toString()),console.log(""),s.info(`Run ${b.green("velar add <component>")} to add one.`);}var Ft=z$1.object({cwd:z$1.string(),query:z$1.string().optional(),limit:z$1.number().optional(),offset:z$1.number().optional(),json:z$1.boolean()}),Ve=new Command().name("list").alias("search").description("List or search components from the registry").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-q, --query <query>","query string").option("-l, --limit <number>","maximum number of items to display",void 0).option("-o, --offset <number>","number of items to skip",void 0).option("--json","output JSON",false).action(async r=>{let e=new I;try{let t=Ft.parse({cwd:x.resolve(r.cwd),query:r.query,limit:r.limit?Number.parseInt(r.limit,10):void 0,offset:r.offset?Number.parseInt(r.offset,10):void 0,json:!!r.json});process.chdir(t.cwd),await Me(t);}catch(t){e.handle(t,"list command"),process.exit(1);}});function Pt(){console.log(""),console.log(b.bold.cyan(` \u25BC VELAR CLI v${N.version}`)),console.log(b.gray(" Tailwind CSS v4+ components for Laravel")),console.log("");}var ie=new Command;ie.name("velar").description("Velar CLI: Copy UI components into your Laravel project").version(N.version,"-v, --version","display the version number").hook("preAction",()=>{Pt();});ie.addCommand(De).addCommand(Fe).addCommand(Ve);ie.parse(process.argv);//# sourceMappingURL=index.js.map
20
+ Suggestion:`),s.error(r.suggestion)),s.break(),process.exit(1)),r instanceof z$1.ZodError){s.error("Validation failed:");for(let[e,t]of Object.entries(r.flatten().fieldErrors))s.error(`- ${m.info(e)}: ${t}`);s.break(),process.exit(1);}r instanceof Error&&(s.error(r.message),s.break(),process.exit(1)),s.break(),process.exit(1);}var I=class{config;async load(){try{return this.config=be(),this.config||(s.error(""),ee(new Error("Configuration not found")),process.exit(1)),this.config}catch{s.error(""),ee(new Error("Something went wrong. Please try again.")),process.exit(1);}}getPackageManager(){if(!this.config)throw new Error("Configuration not loaded");return this.config.packageManager||"npm"}validate(){return !!this.config}getComponentsPath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.components.path}getThemePath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.css.velyx}getJsEntryPath(){if(!this.config)throw new Error("Configuration not loaded");return this.config.js?.entry??""}getTheme(){if(!this.config)throw new Error("Configuration not loaded");return this.config.theme}};var J=promisify(exec);function mt(r){return r.startsWith("@")?r:r.replace("@",":")}var q=class{fileSystem;constructor(e){this.fileSystem=e??new u;}async installDependencies(e,t){let n=[],o=[];e.npm&&e.npm.length>0&&n.push(this.installNpmDependencies(e.npm,t)),e.composer&&e.composer.length>0&&o.push(this.installComposerDependencies(e.composer)),await Promise.allSettled([...n,...o]);}async installNpmDependencies(e,t){if(!this.fileSystem.fileExists("package.json")){s.warn("No package.json found, skipping npm dependencies");return}let n=await this.filterMissingNpmDependencies(e);if(n.length===0){s.info("All npm dependencies already installed");return}let o=this.getNpmInstallCommand(t,n);try{s.info(`Installing npm dependencies: ${n.join(", ")}`);let{stdout:i,stderr:a}=await J(o,{cwd:process.cwd(),timeout:12e4});i&&process.env.NODE_ENV!=="test"&&console.log(i),a&&!a.includes("WARN")&&s.warn(`npm install warnings: ${a}`),s.success(`Installed ${n.length} npm dependencies`);}catch(i){throw s.error(`Failed to install npm dependencies: ${i.message}`),i}}async installComposerDependencies(e){if(!this.fileSystem.fileExists("composer.json")){s.warn("No composer.json found, skipping composer dependencies");return}let t=e.map(mt),n=await this.filterMissingComposerDependencies(t);if(n.length===0){s.info("All composer dependencies already installed");return}try{s.info(`Installing composer dependencies: ${n.join(", ")}`);let{stdout:o,stderr:i}=await J(`composer require ${n.join(" ")}`,{cwd:process.cwd(),timeout:3e5});o&&process.env.NODE_ENV!=="test"&&console.log(o),i&&s.warn(`composer require warnings: ${i}`),s.success(`Installed ${n.length} composer dependencies`);}catch(o){throw s.error(`Failed to install composer dependencies: ${o.message}`),o}}getNpmInstallCommand(e,t){switch(e){case "pnpm":return `pnpm add ${t.join(" ")}`;case "yarn":return `yarn add ${t.join(" ")}`;case "bun":return `bun add ${t.join(" ")}`;default:return `npm install ${t.join(" ")}`}}async filterMissingNpmDependencies(e){try{let{stdout:t}=await J("npm list --json --depth=0",{cwd:process.cwd(),timeout:3e4}),n=JSON.parse(t),o=Object.keys({...n.dependencies,...n.devDependencies});return e.filter(i=>{let a=i.split("@")[0];return !o.includes(a)})}catch{return e}}async filterMissingComposerDependencies(e){try{let{stdout:t}=await J("composer show --installed --format=json",{cwd:process.cwd(),timeout:3e4}),o=JSON.parse(t).installed.map(i=>i.name);return e.filter(i=>{let a=i.split(":")[0];return !o.includes(a)})}catch{return e}}};function ft(r){return r.endsWith(".blade.php")?"blade":r.endsWith(".js")?"js":r.endsWith(".css")?"css":null}var B=class{constructor(e,t,n){this.registryService=e;this.configManager=n;if(this.fileSystem=t??new u,this.dependencyService=new q(this.fileSystem),!this.configManager)throw new Error("ConfigManager is required")}fileSystem;dependencyService;async addComponents(e){let t={added:[],skipped:[],failed:[]};for(let n of e)try{let o=await this.addComponent(n);t.added.push(...o.added),t.skipped.push(...o.skipped),t.failed.push(...o.failed);}catch(o){t.failed.push({name:n,error:o.message});}return t}async addComponent(e){let t={added:[],skipped:[],failed:[]},n=await this.registryService.fetchComponent(e,{includeFiles:true});await this.registryService.resolveDependencies(n);let o=this.buildDependencies(n);if(o){let l=this.configManager.getPackageManager();try{await this.dependencyService.installDependencies(o,l);}catch(c){s.warn(`Failed to install dependencies for ${e}: ${c.message}`);}}let i=[],a=await this.fetchComponentWithFiles(e);for(let[l,c]of Object.entries(a.files)){let d=this.getDestinationPath(l),g=ft(l),se=await this.fileSystem.fileExists(d);if(se){let ie=await this.handleFileConflict(l);if(ie==="skip"){t.skipped.push(`${e}/${l}`);continue}else ie==="cancel"&&(s.error("Cancelled."),process.exit(0));}i.push({componentName:e,filePath:l,fileType:g,destPath:d,content:c,existedBefore:se});}if(i.length>0)try{await this.applyFileBatch(i),i.forEach(c=>t.added.push(`${c.componentName}/${c.filePath}`));let l=new Set(i.filter(c=>c.fileType==="js").map(c=>c.componentName));for(let c of Array.from(l))await this.autoImportJs(c);}catch(l){i.forEach(c=>t.failed.push({name:`${c.componentName}/${c.filePath}`,error:l.message}));}return t}buildDependencies(e){let t={};return e.requires&&e.requires.length>0&&(t.composer=[...e.requires]),e.requires_alpine&&(t.npm=["alpinejs"]),Object.keys(t).length>0?t:null}async fetchComponentWithFiles(e){let t=await this.registryService.fetchComponent(e,{includeFiles:true});return "files"in t?t:{files:{}}}async autoImportJs(e){try{let t=this.configManager?.getJsEntryPath();if(!t||!await this.fileSystem.fileExists(t))return;let n=`./ui/${e}`;ye(t,e,n),s.success(`Auto-imported ${e} into ${t}`);}catch(t){s.warn(`Failed to auto-import JS for ${e}: ${t.message}`);}}getDestinationPath(e){return e}async handleFileConflict(e){let{action:t}=await Se({type:"select",name:"action",message:`File "${e}" already exists. What do you want to do?`,choices:[{title:"Skip",value:"skip"},{title:"Overwrite",value:"overwrite"},{title:"Cancel",value:"cancel"}],initial:0},{onCancel:()=>{s.error("Cancelled."),process.exit(0);}});return t}async applyFileBatch(e){let t=[],n=[];try{for(let o of e){let i=`${o.destPath}.velyx-tmp`;await this.fileSystem.writeFile(i,o.content),t.push(i);}for(let o of e){if(!o.existedBefore)continue;if(!ae(o.destPath))throw new Error(`Failed to create backup for ${o.destPath}`);n.push(o.destPath);}for(let o of e){let i=`${o.destPath}.velyx-tmp`;await w.move(i,o.destPath,{overwrite:!0});}n.forEach(o=>T(o));}catch(o){for(let i of e)await this.fileSystem.fileExists(i.destPath)&&await w.remove(i.destPath),i.existedBefore&&N(i.destPath);for(let i of t)await this.fileSystem.fileExists(i)&&await w.remove(i);throw o}}};var W=class{constructor(e,t,n){this.registryService=e;this.configManager=t;this.componentService=n??new B(e,new u,t);}componentService;validateInitialization(){if(!this.configManager.validate())throw new Error("Velyx is not initialized")}validateComponents(e,t){for(let n of e)if(!t.components.find(i=>i.name===n))throw new Error(`Component "${n}" not found`)}async getAvailableComponents(){return await this.registryService.fetchRegistry()}async addComponents(e){return await this.componentService.addComponents(e)}displayResults(e){e.added.forEach(t=>s.success(`Added ${t}`)),e.skipped.forEach(t=>s.warn(`Skipped ${t}`)),e.failed.forEach(({name:t,error:n})=>s.error(`Failed to add ${t}: ${n}`));}displayNextSteps(e){e.added.length!==0&&console.log(`
21
+ \u{1F389} Happy coding! Enjoy building beautiful components!`);}};var G=class extends Error{constructor(t,n){super(t);this.cause=n;this.name="RegistryError";}},p=class extends G{constructor(e,t){super(e,t),this.name="NetworkError";}},h=class extends G{constructor(e,t){super(`Component "${e}" not found`,t),this.name="ComponentNotFoundError";}};var x={maxRetries:3,initialDelay:1e3,backoffFactor:2,maxDelay:1e4,retryableStatusCodes:[408,429,500,502,503,504],timeout:3e4,headers:{}};function re(r){return new Promise(e=>setTimeout(e,r))}function ne(r,e,t,n){let o=e*Math.pow(t,r);return Math.min(o,n)}function ut(r,e){return e.includes(r)}async function gt(r,e){let{timeout:t=x.timeout,headers:n={}}=e,o=new AbortController,i=setTimeout(()=>o.abort(),t);try{return await fetch(r,{signal:o.signal,headers:{"User-Agent":"Velyx-CLI",...n}})}catch(a){throw a instanceof Error&&a.name==="AbortError"?new p(`Request timeout after ${t}ms for ${r}`,a):a}finally{clearTimeout(i);}}var z=class{async fetch(e,t={}){let n={maxRetries:t.maxRetries??x.maxRetries,initialDelay:t.initialDelay??x.initialDelay,backoffFactor:t.backoffFactor??x.backoffFactor,maxDelay:t.maxDelay??x.maxDelay,retryableStatusCodes:t.retryableStatusCodes??x.retryableStatusCodes,timeout:t.timeout??x.timeout,headers:t.headers??x.headers},o=null;for(let i=0;i<=n.maxRetries;i++)try{let a=await gt(e,{...t,timeout:n.timeout,headers:n.headers});if(a.ok||!ut(a.status,n.retryableStatusCodes))return a;if(console.log("Attempt: ",i),i===n.maxRetries)throw new p(`Request failed after ${n.maxRetries+1} attempts: ${a.status} ${a.statusText}`);let l=ne(i,n.initialDelay,n.backoffFactor,n.maxDelay);await re(l);}catch(a){if(o=a,a instanceof p&&a.message.includes("timeout")){if(i===n.maxRetries)throw a;let c=ne(i,n.initialDelay,n.backoffFactor,n.maxDelay);await re(c);continue}if(i===n.maxRetries)throw o instanceof p?o:new p(`Request failed after ${n.maxRetries+1} attempts: ${o.message}`,o);let l=ne(i,n.initialDelay,n.backoffFactor,n.maxDelay);await re(l);}throw new p(`Request failed after ${n.maxRetries+1} attempts: ${o?.message??"Unknown error"}`,o??void 0)}async fetchJson(e,t){let n=await this.fetch(e,t);if(!n.ok)throw new p(`Failed to fetch JSON from ${e}: ${n.status} ${n.statusText}`);try{return await n.json()}catch(o){throw new p(`Failed to parse JSON from ${e}: ${o.message}`,o)}}async fetchText(e,t){let n=await this.fetch(e,t);if(!n.ok)throw new p(`Failed to fetch text from ${e}: ${n.status} ${n.statusText}`);try{return await n.text()}catch(o){throw new p(`Failed to read text from ${e}: ${o.message}`,o)}}};var je=()=>process.env.VELYX_REGISTRY_URL?process.env.VELYX_REGISTRY_URL.replace(/\/$/,""):"http://velyx.test/api/v1";var Y=class{httpService;baseUrl;constructor(e){this.httpService=e??new z,this.baseUrl=je();}async fetchRegistry(){try{let e=await this.httpService.fetch(`${this.baseUrl}/components`);if(!e.ok)throw new p(`Failed to fetch registry: ${e.status} ${e.statusText}`);let t=await this.httpService.fetchJson(`${this.baseUrl}/components`);return {components:Object.values(t.data),count:t.count}}catch(e){throw e instanceof p?e:new p(`Failed to fetch registry: ${e.message}`)}}async fetchComponent(e,t){try{let n=this.buildComponentUrl(e,t),o=await this.httpService.fetch(n);if(o.status===404)throw new h(e);if(!o.ok)throw new p(`Failed to fetch component: ${o.status} ${o.statusText}`);let i=await this.httpService.fetchJson(n);return t?.includeFiles?i.data:this.convertRegistryComponentToMeta(i.data)}catch(n){throw n instanceof h||n instanceof p?n:new p(`Failed to fetch component "${e}": ${n.message}`)}}async fetchFile(e,t){try{let n=e.split("/").pop()||e,o=await this.httpService.fetch(`${this.baseUrl}/components/${n}`);if(o.status===404)throw new h(n);if(!o.ok)throw new p(`Failed to fetch component: ${o.status} ${o.statusText}`);let a=(await this.httpService.fetchJson(`${this.baseUrl}/components/${n}`)).files[t];if(a===void 0)throw new p(`File "${t}" not found in component "${n}"`);return a}catch(n){throw n instanceof h||n instanceof p?n:new p(`Failed to fetch file "${t}": ${n.message}`)}}async resolveDependencies(e){let t=new Set,n=[],o=async i=>{if(!t.has(i.name)&&(t.add(i.name),n.push(i),i.requires&&i.requires.length>0))for(let a of i.requires)try{let l=await this.fetchComponent(a);await o(l);}catch{}};return await o(e),n}convertRegistryComponentToMeta(e){return {name:e.name,description:e.description,latest:e.latest,versions:e.versions,requires_alpine:e.requires_alpine,requires:e.requires,categories:e.categories,laravel:e.laravel}}buildComponentUrl(e,t){let n=new URLSearchParams;t?.version&&n.append("version",t.version),t?.includeFiles&&n.append("include","files");let o=n.toString();return `${this.baseUrl}/components/${e}${o?`?${o}`:""}`}async getComponentVersions(e){try{let t=await this.httpService.fetch(`${this.baseUrl}/components/${e}/versions`);if(t.status===404)throw new h(e);if(!t.ok)throw new p(`Failed to fetch component versions: ${t.status} ${t.statusText}`);return await this.httpService.fetchJson(`${this.baseUrl}/components/${e}/versions`)}catch(t){throw t instanceof h||t instanceof p?t:new p(`Failed to fetch versions for "${e}": ${t.message}`)}}};var F=class{velyxService;constructor(){this.velyxService=new Y;}async fetchRegistry(){return await y.withTask("Fetching registry...",()=>this.velyxService.fetchRegistry(),void 0,"Failed to fetch registry")}async fetchComponent(e,t){let n=t?.includeFiles?`Fetching component "${e}" with files...`:`Fetching component "${e}" metadata...`;return await y.withTask(n,()=>this.velyxService.fetchComponent(e,t),void 0,`Failed to fetch component "${e}"`)}async resolveDependencies(e){return await y.withTask("Resolving dependencies...",()=>this.velyxService.resolveDependencies(e),void 0,"Failed to resolve dependencies")}};async function ht(r,e){if(r.all)return [...e];if(r.components?.length)return r.components;s.info("Use arrow keys and space to select, then press enter.");let{components:t}=await Se({type:"multiselect",name:"components",message:"Which components would you like to add?",hint:"Space to select. A to toggle all. Enter to submit.",instructions:false,choices:e.map(o=>({title:o,value:o,selected:r.all?true:r.components?.includes(o)}))});t?.length||(s.warn("No components selected. Exiting."),s.info(""),process.exit(1));let n=z$1.array(z$1.string()).safeParse(t);return n.success||(s.error("Something went wrong. Please try again."),process.exit(1)),n.data}async function Oe(r){let e=new I;await e.load();let t=new F,n=new W(t,e);try{n.validateInitialization();}catch{s.error("Velyx is not initialized"),s.log("Run velyx init first"),process.exit(1);}let o=await n.getAvailableComponents(),i=o.components.map(c=>c.name).sort((c,d)=>c.localeCompare(d)),a=await ht(r,i);try{n.validateComponents(a,o);}catch(c){s.error(c.message),s.log("Run velyx list to see available components"),process.exit(1);}let l=await n.addComponents(a);n.displayResults(l),n.displayNextSteps(l);}var vt=z$1.object({components:z$1.array(z$1.string()).optional(),yes:z$1.boolean(),overwrite:z$1.boolean(),cwd:z$1.string(),all:z$1.boolean(),path:z$1.string().optional(),silent:z$1.boolean(),srcDir:z$1.boolean().optional(),cssVariables:z$1.boolean().optional()}),Pe=new Command().name("add").argument("[components...]","Names of components to add").option("-y, --yes","skip confirmation prompt.",false).option("-o, --overwrite","overwrite existing files.",false).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-a, --all","add all available components",false).option("-p, --path <path>","the path to add the component to.").option("-s, --silent","mute output.",false).option("--src-dir","use the src directory when creating a new project.",false).option("--no-src-dir","do not use the src directory when creating a new project.").option("--css-variables","use CSS variables for theming.",true).option("--no-css-variables","do not use CSS variables for theming.").description("Add one or more UI components to your Laravel project").action(async(r,e)=>{let t=new E;try{let n={components:r,cwd:b.resolve(e.cwd),...e,cssVariables:e.cssVariables??!0},o=vt.parse(n);await Oe(o);}catch(n){t.handle(n,"add command"),process.exit(1);}});function St(r,e){if(!e)return [...r];let t=e.toLowerCase();return r.filter(n=>{let o=n.name.toLowerCase().includes(t),i=n.description?n.description.toLowerCase().includes(t):false,a=n.categories?n.categories.some(l=>l.toLowerCase().includes(t)):false;return o||i||a})}function Ct(r,e,t){let n=Math.max(0,e??0);return t===void 0?r.slice(n):r.slice(n,n+Math.max(0,t))}async function Ne(r){let n=[...(await new F().fetchRegistry()).components].sort((l,c)=>l.name.localeCompare(c.name)),o=St(n,r.query),i=Ct(o,r.offset,r.limit);if(r.json){console.log(JSON.stringify({total:o.length,count:i.length,offset:r.offset??0,limit:r.limit??null,components:i},null,2));return}if(i.length===0){s.warn("No components found.");return}console.log(v.bold(`
22
+ Available components:`)),console.log("");let a=new bt({head:[v.bold("Component"),v.bold("Description"),v.bold("Categories")],colWidths:[24,50,24],wordWrap:true,style:{head:[],border:[]}});for(let l of i)a.push([v.cyan(l.name),v.white(l.description||"No description"),v.gray(l.categories?.join(", ")||"-")]);console.log(a.toString()),console.log(""),s.info(`Run ${v.green("velyx add <component>")} to add one.`);}var Et=z$1.object({cwd:z$1.string(),query:z$1.string().optional(),limit:z$1.number().optional(),offset:z$1.number().optional(),json:z$1.boolean()}),Te=new Command().name("list").alias("search").description("List or search components from the registry").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("-q, --query <query>","query string").option("-l, --limit <number>","maximum number of items to display",void 0).option("-o, --offset <number>","number of items to skip",void 0).option("--json","output JSON",false).action(async r=>{let e=new E;try{let t=Et.parse({cwd:b.resolve(r.cwd),query:r.query,limit:r.limit?Number.parseInt(r.limit,10):void 0,offset:r.offset?Number.parseInt(r.offset,10):void 0,json:!!r.json});process.chdir(t.cwd);let n=new I;try{await n.load();}catch{s.error("Velyx is not initialized"),s.log("Run velyx init first"),process.exit(1);}await Ne(t);}catch(t){e.handle(t,"list command"),process.exit(1);}});function Ft(){console.log(""),console.log(v.bold.cyan(` \u25BC VELYX CLI v${P.version}`)),console.log(v.gray(" Tailwind CSS v4+ components for Laravel")),console.log("");}var oe=new Command;oe.name("velyx").description("Velyx CLI: Copy UI components into your Laravel project").version(P.version,"-v, --version","display the version number").hook("preAction",()=>{Ft();});oe.addCommand(Pe).addCommand(Fe).addCommand(Te);oe.parse(process.argv);//# sourceMappingURL=index.js.map
23
23
  //# sourceMappingURL=index.js.map