@nexa-ui-kit/cli 1.0.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/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @nexa-ui-kit/cli
2
+
3
+ CLI for adding Nexa UI components to your project.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @nexa-ui-kit/cli
9
+ # or use npx
10
+ npx @nexa-ui-kit/cli
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Initialize
16
+
17
+ ```bash
18
+ npx @nexa-ui-kit/cli init
19
+ # or with global install
20
+ nexa init
21
+ ```
22
+
23
+ ### Add Components
24
+
25
+ ```bash
26
+ nexa add button card dialog
27
+ ```
28
+
29
+ ### List Components
30
+
31
+ ```bash
32
+ nexa list
33
+ ```
34
+
35
+ ## Options
36
+
37
+ - `-y, --yes`: Skip prompts and use defaults
38
+ - `-o, --overwrite`: Overwrite existing files
39
+ - `-c, --cwd <path>`: Specify working directory
40
+
41
+ ## License
42
+
43
+ MIT
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,624 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import fs2 from 'fs';
4
+ import path2 from 'path';
5
+ import { execSync } from 'child_process';
6
+ import prompts from 'prompts';
7
+ import pc from 'picocolors';
8
+ import { z } from 'zod';
9
+
10
+ var logger = {
11
+ info: (message) => {
12
+ console.log(pc.blue("info"), message);
13
+ },
14
+ success: (message) => {
15
+ console.log(pc.green("success"), message);
16
+ },
17
+ warn: (message) => {
18
+ console.log(pc.yellow("warn"), message);
19
+ },
20
+ error: (message) => {
21
+ console.log(pc.red("error"), message);
22
+ },
23
+ log: (message) => {
24
+ console.log(message);
25
+ },
26
+ break: () => {
27
+ console.log("");
28
+ }
29
+ };
30
+ function highlight(text) {
31
+ return pc.cyan(text);
32
+ }
33
+ function dim(text) {
34
+ return pc.dim(text);
35
+ }
36
+ var configSchema = z.object({
37
+ $schema: z.string().optional(),
38
+ style: z.string().default("default"),
39
+ // Tailwind v4 uses CSS-first configuration via @theme directive
40
+ css: z.string().default("src/index.css"),
41
+ aliases: z.object({
42
+ components: z.string().default("@/components"),
43
+ utils: z.string().default("@/lib/utils")
44
+ }).default({})
45
+ });
46
+ var CONFIG_FILE = "nexa-ui.json";
47
+ function getConfigPath(cwd) {
48
+ return path2.join(cwd, CONFIG_FILE);
49
+ }
50
+ function configExists(cwd) {
51
+ return fs2.existsSync(getConfigPath(cwd));
52
+ }
53
+ async function loadConfig(cwd) {
54
+ const configPath = getConfigPath(cwd);
55
+ if (!fs2.existsSync(configPath)) {
56
+ return null;
57
+ }
58
+ try {
59
+ const content = fs2.readFileSync(configPath, "utf-8");
60
+ const parsed = JSON.parse(content);
61
+ return configSchema.parse(parsed);
62
+ } catch {
63
+ return null;
64
+ }
65
+ }
66
+ async function saveConfig(cwd, config) {
67
+ const configPath = getConfigPath(cwd);
68
+ const content = JSON.stringify(config, null, 2);
69
+ fs2.writeFileSync(configPath, content, "utf-8");
70
+ }
71
+
72
+ // src/commands/init.ts
73
+ function detectProject(cwd) {
74
+ const packageJsonPath = path2.join(cwd, "package.json");
75
+ let packageJson = {};
76
+ if (fs2.existsSync(packageJsonPath)) {
77
+ packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
78
+ }
79
+ const deps = {
80
+ ...packageJson.dependencies || {},
81
+ ...packageJson.devDependencies || {}
82
+ };
83
+ let framework = "unknown";
84
+ if (deps.next) {
85
+ framework = "next";
86
+ } else if (deps.vite) {
87
+ framework = "vite";
88
+ } else if (deps["@remix-run/react"]) {
89
+ framework = "remix";
90
+ } else if (deps.astro) {
91
+ framework = "astro";
92
+ }
93
+ let packageManager = "npm";
94
+ if (fs2.existsSync(path2.join(cwd, "bun.lockb")) || fs2.existsSync(path2.join(cwd, "bun.lock"))) {
95
+ packageManager = "bun";
96
+ } else if (fs2.existsSync(path2.join(cwd, "pnpm-lock.yaml"))) {
97
+ packageManager = "pnpm";
98
+ } else if (fs2.existsSync(path2.join(cwd, "yarn.lock"))) {
99
+ packageManager = "yarn";
100
+ }
101
+ const typescript = fs2.existsSync(path2.join(cwd, "tsconfig.json"));
102
+ const srcDir = fs2.existsSync(path2.join(cwd, "src"));
103
+ let tailwindConfigPath = null;
104
+ const tailwindConfigFiles = [
105
+ "tailwind.config.js",
106
+ "tailwind.config.ts",
107
+ "tailwind.config.mjs",
108
+ "tailwind.config.cjs"
109
+ ];
110
+ for (const configFile of tailwindConfigFiles) {
111
+ if (fs2.existsSync(path2.join(cwd, configFile))) {
112
+ tailwindConfigPath = configFile;
113
+ break;
114
+ }
115
+ }
116
+ let cssPath = srcDir ? "src/index.css" : "index.css";
117
+ if (framework === "next") {
118
+ cssPath = srcDir ? "src/app/globals.css" : "app/globals.css";
119
+ } else if (framework === "remix") {
120
+ cssPath = "app/tailwind.css";
121
+ } else if (framework === "astro") {
122
+ cssPath = "src/styles/global.css";
123
+ }
124
+ return {
125
+ framework,
126
+ packageManager,
127
+ typescript,
128
+ srcDir,
129
+ tailwindConfigPath,
130
+ cssPath
131
+ };
132
+ }
133
+ function getInstallCommand(packageManager, packages) {
134
+ const pkgList = packages.join(" ");
135
+ switch (packageManager) {
136
+ case "bun":
137
+ return `bun add ${pkgList}`;
138
+ case "pnpm":
139
+ return `pnpm add ${pkgList}`;
140
+ case "yarn":
141
+ return `yarn add ${pkgList}`;
142
+ default:
143
+ return `npm install ${pkgList}`;
144
+ }
145
+ }
146
+ function createCnUtility(cwd, utilsPath, typescript) {
147
+ const ext = typescript ? "ts" : "js";
148
+ const utilsDir = resolveAliasPath(utilsPath, cwd);
149
+ const cnFilePath = path2.join(utilsDir, `cn.${ext}`);
150
+ if (!fs2.existsSync(utilsDir)) {
151
+ fs2.mkdirSync(utilsDir, { recursive: true });
152
+ }
153
+ const cnContent = typescript ? `import { type ClassValue, clsx } from "clsx"
154
+ import { twMerge } from "tailwind-merge"
155
+
156
+ export function cn(...inputs: ClassValue[]) {
157
+ return twMerge(clsx(inputs))
158
+ }
159
+ ` : `import { clsx } from "clsx"
160
+ import { twMerge } from "tailwind-merge"
161
+
162
+ export function cn(...inputs) {
163
+ return twMerge(clsx(inputs))
164
+ }
165
+ `;
166
+ fs2.writeFileSync(cnFilePath, cnContent, "utf-8");
167
+ logger.log(` ${dim("\u2713")} Created ${highlight(`cn.${ext}`)} utility`);
168
+ }
169
+ function updateCssFile(cwd, cssPath) {
170
+ const fullCssPath = path2.join(cwd, cssPath);
171
+ const cssDir = path2.dirname(fullCssPath);
172
+ if (!fs2.existsSync(cssDir)) {
173
+ fs2.mkdirSync(cssDir, { recursive: true });
174
+ }
175
+ const nexaImports = `/* Nexa UI Theme */
176
+ @import "@nexa-ui-kit/theme-default/components";
177
+ `;
178
+ if (fs2.existsSync(fullCssPath)) {
179
+ let content = fs2.readFileSync(fullCssPath, "utf-8");
180
+ if (content.includes("@nexa-ui-kit/theme-default")) {
181
+ logger.log(` ${dim("\u2713")} CSS already configured`);
182
+ return;
183
+ }
184
+ const tailwindImportMatch = content.match(/@import\s+["']tailwindcss["'];?\n?/);
185
+ if (tailwindImportMatch) {
186
+ const insertIndex = (tailwindImportMatch.index ?? 0) + tailwindImportMatch[0].length;
187
+ content = content.slice(0, insertIndex) + "\n" + nexaImports + content.slice(insertIndex);
188
+ } else {
189
+ content = nexaImports + "\n" + content;
190
+ }
191
+ fs2.writeFileSync(fullCssPath, content, "utf-8");
192
+ } else {
193
+ const newCssContent = `@import "tailwindcss";
194
+
195
+ ${nexaImports}
196
+ `;
197
+ fs2.writeFileSync(fullCssPath, newCssContent, "utf-8");
198
+ }
199
+ logger.log(` ${dim("\u2713")} Updated ${highlight(cssPath)}`);
200
+ }
201
+ function updateTsConfig(cwd, aliases) {
202
+ const tsconfigPath = path2.join(cwd, "tsconfig.json");
203
+ if (!fs2.existsSync(tsconfigPath)) {
204
+ return;
205
+ }
206
+ try {
207
+ const content = fs2.readFileSync(tsconfigPath, "utf-8");
208
+ const tsconfig = JSON.parse(content);
209
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
210
+ tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
211
+ const baseUrl = tsconfig.compilerOptions.baseUrl || ".";
212
+ const componentsAlias = aliases.components.replace(/\/\*?$/, "");
213
+ const utilsAlias = aliases.utils.replace(/\/\*?$/, "");
214
+ if (componentsAlias.startsWith("@/")) {
215
+ const aliasKey = componentsAlias.endsWith("*") ? componentsAlias : `${componentsAlias}/*`;
216
+ if (!tsconfig.compilerOptions.paths[aliasKey]) {
217
+ const relativePath = `./src/${componentsAlias.slice(2)}/*`;
218
+ tsconfig.compilerOptions.paths[aliasKey] = [relativePath];
219
+ tsconfig.compilerOptions.paths[componentsAlias] = [`./src/${componentsAlias.slice(2)}`];
220
+ }
221
+ }
222
+ if (utilsAlias.startsWith("@/")) {
223
+ const aliasKey = utilsAlias.endsWith("*") ? utilsAlias : `${utilsAlias}/*`;
224
+ if (!tsconfig.compilerOptions.paths[aliasKey]) {
225
+ const relativePath = `./src/${utilsAlias.slice(2)}/*`;
226
+ tsconfig.compilerOptions.paths[aliasKey] = [relativePath];
227
+ tsconfig.compilerOptions.paths[utilsAlias] = [`./src/${utilsAlias.slice(2)}`];
228
+ }
229
+ }
230
+ if (!tsconfig.compilerOptions.baseUrl) {
231
+ tsconfig.compilerOptions.baseUrl = ".";
232
+ }
233
+ fs2.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n", "utf-8");
234
+ logger.log(` ${dim("\u2713")} Updated ${highlight("tsconfig.json")} with path aliases`);
235
+ } catch (error) {
236
+ logger.warn(` Could not update tsconfig.json: ${error}`);
237
+ }
238
+ }
239
+ function resolveAliasPath(alias, cwd) {
240
+ if (alias.startsWith("@/")) {
241
+ return path2.join(cwd, "src", alias.slice(2));
242
+ }
243
+ if (alias.startsWith("./") || alias.startsWith("../")) {
244
+ return path2.resolve(cwd, alias);
245
+ }
246
+ return path2.join(cwd, alias);
247
+ }
248
+ function ensureComponentsDir(cwd, componentsAlias) {
249
+ const componentsDir = resolveAliasPath(componentsAlias, cwd);
250
+ if (!fs2.existsSync(componentsDir)) {
251
+ fs2.mkdirSync(componentsDir, { recursive: true });
252
+ logger.log(` ${dim("\u2713")} Created ${highlight(componentsAlias.replace("@/", "src/"))} directory`);
253
+ }
254
+ }
255
+ async function init(options) {
256
+ const { cwd, yes } = options;
257
+ logger.break();
258
+ logger.info("Initializing Nexa UI in your project...");
259
+ logger.break();
260
+ if (configExists(cwd)) {
261
+ logger.warn("Nexa UI is already initialized in this project.");
262
+ logger.info(`Config file exists at ${highlight("nexa-ui.json")}`);
263
+ return;
264
+ }
265
+ const projectInfo = detectProject(cwd);
266
+ logger.log(` ${dim("Detected:")} ${highlight(projectInfo.framework)} with ${highlight(projectInfo.packageManager)}`);
267
+ if (projectInfo.typescript) {
268
+ logger.log(` ${dim("TypeScript:")} ${highlight("yes")}`);
269
+ }
270
+ logger.break();
271
+ let config;
272
+ if (yes) {
273
+ config = {
274
+ style: "default",
275
+ css: projectInfo.cssPath,
276
+ aliases: {
277
+ components: "@/components",
278
+ utils: "@/lib/utils"
279
+ }
280
+ };
281
+ } else {
282
+ const response = await prompts([
283
+ {
284
+ type: "select",
285
+ name: "style",
286
+ message: "Which style would you like to use?",
287
+ choices: [
288
+ { title: "Default", value: "default" },
289
+ { title: "New York", value: "new-york" }
290
+ ],
291
+ initial: 0
292
+ },
293
+ {
294
+ type: "text",
295
+ name: "css",
296
+ message: "Where is your global CSS file?",
297
+ initial: projectInfo.cssPath
298
+ },
299
+ {
300
+ type: "text",
301
+ name: "componentsAlias",
302
+ message: "Configure the import alias for components:",
303
+ initial: "@/components"
304
+ },
305
+ {
306
+ type: "text",
307
+ name: "utilsAlias",
308
+ message: "Configure the import alias for utils:",
309
+ initial: "@/lib/utils"
310
+ }
311
+ ]);
312
+ if (!response.style) {
313
+ logger.break();
314
+ logger.warn("Initialization cancelled.");
315
+ return;
316
+ }
317
+ config = {
318
+ style: response.style,
319
+ css: response.css,
320
+ aliases: {
321
+ components: response.componentsAlias,
322
+ utils: response.utilsAlias
323
+ }
324
+ };
325
+ }
326
+ logger.break();
327
+ logger.info("Installing dependencies...");
328
+ logger.break();
329
+ const packages = [
330
+ "@nexa-ui-kit/core",
331
+ "@nexa-ui-kit/theme-default",
332
+ "clsx",
333
+ "tailwind-merge",
334
+ "class-variance-authority"
335
+ ];
336
+ const installCmd = getInstallCommand(projectInfo.packageManager, packages);
337
+ logger.log(` ${dim("$")} ${installCmd}`);
338
+ try {
339
+ execSync(installCmd, { cwd, stdio: "inherit" });
340
+ } catch (error) {
341
+ logger.error("Failed to install dependencies.");
342
+ logger.info("Please install manually:");
343
+ logger.log(` ${installCmd}`);
344
+ logger.break();
345
+ }
346
+ logger.break();
347
+ logger.info("Configuring project...");
348
+ logger.break();
349
+ createCnUtility(cwd, config.aliases.utils, projectInfo.typescript);
350
+ updateCssFile(cwd, config.css);
351
+ if (projectInfo.typescript) {
352
+ updateTsConfig(cwd, config.aliases);
353
+ }
354
+ ensureComponentsDir(cwd, config.aliases.components);
355
+ await saveConfig(cwd, config);
356
+ logger.break();
357
+ logger.success("Nexa UI initialized successfully!");
358
+ logger.break();
359
+ logger.info(`Configuration saved to ${highlight("nexa-ui.json")}`);
360
+ logger.break();
361
+ logger.info("Next steps:");
362
+ logger.log(` 1. Add components: ${highlight("npx @nexa-ui-kit/cli add button")}`);
363
+ logger.log(` 2. Import in your code: ${highlight("import { Button } from '@/components/button'")}`);
364
+ logger.break();
365
+ }
366
+
367
+ // src/constants/available-components.ts
368
+ var AVAILABLE_COMPONENTS = [
369
+ "accordion",
370
+ "aspect-ratio",
371
+ "avatar",
372
+ "badge",
373
+ "button",
374
+ "calendar",
375
+ "card",
376
+ "carousel",
377
+ "chart",
378
+ "checkbox",
379
+ "collapsible",
380
+ "command",
381
+ "context-menu",
382
+ "dropdown-menu",
383
+ "field",
384
+ "form",
385
+ "hover-card",
386
+ "input",
387
+ "input-group",
388
+ "item",
389
+ "kbd",
390
+ "label",
391
+ "menubar",
392
+ "navigation-menu",
393
+ "popover",
394
+ "progress",
395
+ "radio-group",
396
+ "select",
397
+ "separator",
398
+ "sidebar",
399
+ "skeleton",
400
+ "slider",
401
+ "sonner",
402
+ "spinner",
403
+ "switch",
404
+ "tabs",
405
+ "textarea",
406
+ "toggle",
407
+ "tooltip"
408
+ ];
409
+
410
+ // src/commands/add.ts
411
+ var REGISTRY_PATH = path2.resolve(
412
+ import.meta.dirname,
413
+ "../../../registry/dist/registry.json"
414
+ );
415
+ async function add(options) {
416
+ const { cwd, components, overwrite } = options;
417
+ logger.break();
418
+ if (!configExists(cwd)) {
419
+ logger.error("Nexa UI is not initialized in this project.");
420
+ logger.info(`Run ${highlight("npx @nexa-ui-kit/cli init")} first.`);
421
+ return;
422
+ }
423
+ const config = await loadConfig(cwd);
424
+ if (!config) {
425
+ logger.error("Failed to load Nexa UI configuration.");
426
+ return;
427
+ }
428
+ const invalidComponents = components.filter(
429
+ (c) => !AVAILABLE_COMPONENTS.includes(c)
430
+ );
431
+ if (invalidComponents.length > 0) {
432
+ logger.error(`Unknown components: ${invalidComponents.join(", ")}`);
433
+ logger.info(
434
+ `Run ${highlight(
435
+ "npx @nexa-ui-kit/cli list"
436
+ )} to see available components.`
437
+ );
438
+ return;
439
+ }
440
+ let registry;
441
+ try {
442
+ const registryContent = fs2.readFileSync(REGISTRY_PATH, "utf-8");
443
+ registry = JSON.parse(registryContent);
444
+ } catch {
445
+ logger.error("Failed to load component registry.");
446
+ logger.info("Please ensure the registry is built: npm run build:registry");
447
+ return;
448
+ }
449
+ const componentsDir = resolveAliasPath2(config.aliases.components, cwd);
450
+ const installedComponents = /* @__PURE__ */ new Set();
451
+ const componentsToInstall = [...components];
452
+ const dependencies = /* @__PURE__ */ new Set();
453
+ const devDependencies = /* @__PURE__ */ new Set();
454
+ let index = 0;
455
+ while (index < componentsToInstall.length) {
456
+ const componentName = componentsToInstall[index];
457
+ index++;
458
+ if (installedComponents.has(componentName)) {
459
+ continue;
460
+ }
461
+ const registryComponent = registry.components.find(
462
+ (c) => c.name === componentName
463
+ );
464
+ if (!registryComponent) {
465
+ logger.error(`Component "${componentName}" not found in registry.`);
466
+ continue;
467
+ }
468
+ for (const dep of registryComponent.registryDependencies) {
469
+ if (!componentsToInstall.includes(dep)) {
470
+ componentsToInstall.push(dep);
471
+ }
472
+ }
473
+ registryComponent.dependencies.forEach((d) => dependencies.add(d));
474
+ registryComponent.devDependencies.forEach((d) => devDependencies.add(d));
475
+ installedComponents.add(componentName);
476
+ }
477
+ logger.info(`Adding ${installedComponents.size} component(s)...`);
478
+ logger.break();
479
+ if (!fs2.existsSync(componentsDir)) {
480
+ fs2.mkdirSync(componentsDir, { recursive: true });
481
+ }
482
+ for (const componentName of componentsToInstall) {
483
+ const registryComponent = registry.components.find(
484
+ (c) => c.name === componentName
485
+ );
486
+ if (!registryComponent) continue;
487
+ const success = await writeComponentFile(
488
+ registryComponent,
489
+ componentsDir,
490
+ overwrite
491
+ );
492
+ if (success) {
493
+ logger.log(` ${dim("\u2713")} ${highlight(componentName)}`);
494
+ }
495
+ }
496
+ logger.break();
497
+ logger.success("Components added successfully!");
498
+ logger.break();
499
+ if (dependencies.size > 0 || devDependencies.size > 0) {
500
+ logger.info("The following dependencies are required:");
501
+ if (dependencies.size > 0) {
502
+ logger.log(
503
+ ` ${dim("npm install")} ${Array.from(dependencies).join(" ")}`
504
+ );
505
+ }
506
+ if (devDependencies.size > 0) {
507
+ logger.log(
508
+ ` ${dim("npm install -D")} ${Array.from(devDependencies).join(" ")}`
509
+ );
510
+ }
511
+ logger.break();
512
+ }
513
+ if (overwrite) {
514
+ logger.info(dim("Existing files were overwritten."));
515
+ }
516
+ }
517
+ function resolveAliasPath2(alias, cwd) {
518
+ if (alias.startsWith("@/")) {
519
+ return path2.join(cwd, "src", alias.slice(2));
520
+ }
521
+ if (alias.startsWith("./") || alias.startsWith("../")) {
522
+ return path2.resolve(cwd, alias);
523
+ }
524
+ return path2.join(cwd, alias);
525
+ }
526
+ async function writeComponentFile(component, componentsDir, overwrite) {
527
+ for (const file of component.files) {
528
+ const filePath = path2.join(componentsDir, file.name);
529
+ if (fs2.existsSync(filePath) && !overwrite) {
530
+ logger.warn(
531
+ ` File already exists: ${file.name} (use --overwrite to replace)`
532
+ );
533
+ continue;
534
+ }
535
+ try {
536
+ fs2.writeFileSync(filePath, file.content, "utf-8");
537
+ } catch (error) {
538
+ logger.error(` Failed to write ${file.name}`);
539
+ return false;
540
+ }
541
+ }
542
+ return true;
543
+ }
544
+
545
+ // src/constants/component-descriptions.ts
546
+ var COMPONENT_DESCRIPTIONS = {
547
+ "accordion": "Vertically stacked collapsible sections",
548
+ "aspect-ratio": "Maintains consistent width-to-height ratio",
549
+ "avatar": "User avatar with image and fallback",
550
+ "badge": "Small status indicator or label",
551
+ "button": "Interactive button with variants",
552
+ "calendar": "Date picker calendar (react-day-picker)",
553
+ "card": "Container for grouping content",
554
+ "carousel": "Slideshow component (embla-carousel)",
555
+ "chart": "Data visualization charts (recharts)",
556
+ "checkbox": "Checkbox input with label",
557
+ "collapsible": "Expandable/collapsible content area",
558
+ "command": "Command palette/search (cmdk)",
559
+ "context-menu": "Right-click context menu",
560
+ "dropdown-menu": "Dropdown menu with items",
561
+ "field": "Form field layout with label/description",
562
+ "form": "Form handling (react-hook-form)",
563
+ "hover-card": "Card shown on hover",
564
+ "input": "Text input field",
565
+ "input-group": "Input with addons and buttons",
566
+ "item": "List item with media and actions",
567
+ "kbd": "Keyboard key indicator",
568
+ "label": "Form label component",
569
+ "menubar": "Horizontal menu bar",
570
+ "navigation-menu": "Site navigation component",
571
+ "popover": "Floating content popover",
572
+ "progress": "Progress bar indicator",
573
+ "radio-group": "Radio button group",
574
+ "select": "Dropdown select input (Radix)",
575
+ "separator": "Visual divider line",
576
+ "sidebar": "Side navigation panel",
577
+ "skeleton": "Loading placeholder skeleton",
578
+ "slider": "Range slider input",
579
+ "sonner": "Toast notifications (sonner)",
580
+ "spinner": "Loading spinner indicator",
581
+ "switch": "Toggle switch input",
582
+ "tabs": "Tabbed content panels",
583
+ "textarea": "Multi-line text input",
584
+ "toggle": "Toggle button",
585
+ "tooltip": "Hover tooltip"
586
+ };
587
+
588
+ // src/commands/list.ts
589
+ async function list() {
590
+ logger.break();
591
+ logger.info(`Available Nexa UI components (${AVAILABLE_COMPONENTS.length}):`);
592
+ logger.break();
593
+ for (const name of AVAILABLE_COMPONENTS) {
594
+ const description = COMPONENT_DESCRIPTIONS[name] || "";
595
+ logger.log(` ${highlight(name.padEnd(20))} ${dim(description)}`);
596
+ }
597
+ logger.break();
598
+ logger.info(`Add components with: ${highlight("npx @nexa-ui-kit/cli add <component>")}`);
599
+ logger.info(`Add multiple: ${highlight("npx @nexa-ui-kit/cli add button card input")}`);
600
+ logger.break();
601
+ }
602
+
603
+ // src/index.ts
604
+ var program = new Command();
605
+ program.name("nexa").description("CLI for adding Nexa UI components to your project").version("0.0.0");
606
+ program.command("init").description("Initialize Nexa UI in your project").option("-y, --yes", "Skip prompts and use defaults").option("-c, --cwd <path>", "Working directory", process.cwd()).action(async (options) => {
607
+ await init({
608
+ cwd: options.cwd,
609
+ yes: options.yes
610
+ });
611
+ });
612
+ program.command("add").description("Add components to your project").argument("<components...>", "Components to add").option("-o, --overwrite", "Overwrite existing files").option("-c, --cwd <path>", "Working directory", process.cwd()).action(async (components, options) => {
613
+ await add({
614
+ cwd: options.cwd,
615
+ components,
616
+ overwrite: options.overwrite
617
+ });
618
+ });
619
+ program.command("list").description("List available components").action(async () => {
620
+ await list();
621
+ });
622
+ program.parse();
623
+ //# sourceMappingURL=index.js.map
624
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/utils/config.ts","../src/commands/init.ts","../src/constants/available-components.ts","../src/commands/add.ts","../src/constants/component-descriptions.ts","../src/commands/list.ts","../src/index.ts"],"names":["path","fs","resolveAliasPath"],"mappings":"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","file":"index.js","sourcesContent":["import pc from 'picocolors'\n\nexport const logger = {\n info: (message: string) => {\n console.log(pc.blue('info'), message)\n },\n\n success: (message: string) => {\n console.log(pc.green('success'), message)\n },\n\n warn: (message: string) => {\n console.log(pc.yellow('warn'), message)\n },\n\n error: (message: string) => {\n console.log(pc.red('error'), message)\n },\n\n log: (message: string) => {\n console.log(message)\n },\n\n break: () => {\n console.log('')\n },\n}\n\nexport function highlight(text: string): string {\n return pc.cyan(text)\n}\n\nexport function dim(text: string): string {\n return pc.dim(text)\n}\n","import { z } from 'zod'\r\nimport fs from 'node:fs'\r\nimport path from 'node:path'\r\n\r\nconst configSchema = z.object({\r\n $schema: z.string().optional(),\r\n style: z.string().default('default'),\r\n // Tailwind v4 uses CSS-first configuration via @theme directive\r\n css: z.string().default('src/index.css'),\r\n aliases: z.object({\r\n components: z.string().default('@/components'),\r\n utils: z.string().default('@/lib/utils'),\r\n }).default({}),\r\n})\r\n\r\nexport type Config = z.infer<typeof configSchema>\r\n\r\nconst CONFIG_FILE = 'nexa-ui.json'\r\n\r\nexport function getConfigPath(cwd: string): string {\r\n return path.join(cwd, CONFIG_FILE)\r\n}\r\n\r\nexport function configExists(cwd: string): boolean {\r\n return fs.existsSync(getConfigPath(cwd))\r\n}\r\n\r\nexport async function loadConfig(cwd: string): Promise<Config | null> {\r\n const configPath = getConfigPath(cwd)\r\n\r\n if (!fs.existsSync(configPath)) {\r\n return null\r\n }\r\n\r\n try {\r\n const content = fs.readFileSync(configPath, 'utf-8')\r\n const parsed = JSON.parse(content)\r\n return configSchema.parse(parsed)\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nexport async function saveConfig(cwd: string, config: Config): Promise<void> {\r\n const configPath = getConfigPath(cwd)\r\n const content = JSON.stringify(config, null, 2)\r\n fs.writeFileSync(configPath, content, 'utf-8')\r\n}\r\n","import fs from 'node:fs'\r\nimport path from 'node:path'\r\nimport { execSync } from 'node:child_process'\r\nimport prompts from 'prompts'\r\nimport { logger, highlight, dim } from '../utils/logger'\r\nimport { configExists, saveConfig, type Config } from '../utils/config'\r\n\r\nexport interface InitOptions {\r\n cwd: string\r\n yes?: boolean\r\n}\r\n\r\ninterface ProjectInfo {\r\n framework: 'next' | 'vite' | 'remix' | 'astro' | 'unknown'\r\n packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun'\r\n typescript: boolean\r\n srcDir: boolean\r\n tailwindConfigPath: string | null\r\n cssPath: string\r\n}\r\n\r\n/**\r\n * Detect project configuration from package.json and file structure\r\n */\r\nfunction detectProject(cwd: string): ProjectInfo {\r\n const packageJsonPath = path.join(cwd, 'package.json')\r\n let packageJson: Record<string, unknown> = {}\r\n\r\n if (fs.existsSync(packageJsonPath)) {\r\n packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\r\n }\r\n\r\n const deps = {\r\n ...(packageJson.dependencies as Record<string, string> || {}),\r\n ...(packageJson.devDependencies as Record<string, string> || {}),\r\n }\r\n\r\n // Detect framework\r\n let framework: ProjectInfo['framework'] = 'unknown'\r\n if (deps.next) {\r\n framework = 'next'\r\n } else if (deps.vite) {\r\n framework = 'vite'\r\n } else if (deps['@remix-run/react']) {\r\n framework = 'remix'\r\n } else if (deps.astro) {\r\n framework = 'astro'\r\n }\r\n\r\n // Detect package manager\r\n let packageManager: ProjectInfo['packageManager'] = 'npm'\r\n if (fs.existsSync(path.join(cwd, 'bun.lockb')) || fs.existsSync(path.join(cwd, 'bun.lock'))) {\r\n packageManager = 'bun'\r\n } else if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) {\r\n packageManager = 'pnpm'\r\n } else if (fs.existsSync(path.join(cwd, 'yarn.lock'))) {\r\n packageManager = 'yarn'\r\n }\r\n\r\n // Detect TypeScript\r\n const typescript = fs.existsSync(path.join(cwd, 'tsconfig.json'))\r\n\r\n // Detect src directory\r\n const srcDir = fs.existsSync(path.join(cwd, 'src'))\r\n\r\n // Detect Tailwind config (v4 uses CSS-first, but some projects may have config)\r\n let tailwindConfigPath: string | null = null\r\n const tailwindConfigFiles = [\r\n 'tailwind.config.js',\r\n 'tailwind.config.ts',\r\n 'tailwind.config.mjs',\r\n 'tailwind.config.cjs',\r\n ]\r\n for (const configFile of tailwindConfigFiles) {\r\n if (fs.existsSync(path.join(cwd, configFile))) {\r\n tailwindConfigPath = configFile\r\n break\r\n }\r\n }\r\n\r\n // Determine default CSS path based on framework\r\n let cssPath = srcDir ? 'src/index.css' : 'index.css'\r\n if (framework === 'next') {\r\n cssPath = srcDir ? 'src/app/globals.css' : 'app/globals.css'\r\n } else if (framework === 'remix') {\r\n cssPath = 'app/tailwind.css'\r\n } else if (framework === 'astro') {\r\n cssPath = 'src/styles/global.css'\r\n }\r\n\r\n return {\r\n framework,\r\n packageManager,\r\n typescript,\r\n srcDir,\r\n tailwindConfigPath,\r\n cssPath,\r\n }\r\n}\r\n\r\n/**\r\n * Get the install command for the package manager\r\n */\r\nfunction getInstallCommand(packageManager: ProjectInfo['packageManager'], packages: string[]): string {\r\n const pkgList = packages.join(' ')\r\n switch (packageManager) {\r\n case 'bun':\r\n return `bun add ${pkgList}`\r\n case 'pnpm':\r\n return `pnpm add ${pkgList}`\r\n case 'yarn':\r\n return `yarn add ${pkgList}`\r\n default:\r\n return `npm install ${pkgList}`\r\n }\r\n}\r\n\r\n/**\r\n * Create the cn utility file\r\n */\r\nfunction createCnUtility(cwd: string, utilsPath: string, typescript: boolean): void {\r\n const ext = typescript ? 'ts' : 'js'\r\n const utilsDir = resolveAliasPath(utilsPath, cwd)\r\n const cnFilePath = path.join(utilsDir, `cn.${ext}`)\r\n\r\n // Ensure directory exists\r\n if (!fs.existsSync(utilsDir)) {\r\n fs.mkdirSync(utilsDir, { recursive: true })\r\n }\r\n\r\n const cnContent = typescript\r\n ? `import { type ClassValue, clsx } from \"clsx\"\r\nimport { twMerge } from \"tailwind-merge\"\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs))\r\n}\r\n`\r\n : `import { clsx } from \"clsx\"\r\nimport { twMerge } from \"tailwind-merge\"\r\n\r\nexport function cn(...inputs) {\r\n return twMerge(clsx(inputs))\r\n}\r\n`\r\n\r\n fs.writeFileSync(cnFilePath, cnContent, 'utf-8')\r\n logger.log(` ${dim('✓')} Created ${highlight(`cn.${ext}`)} utility`)\r\n}\r\n\r\n/**\r\n * Update CSS file with Nexa UI theme imports\r\n */\r\nfunction updateCssFile(cwd: string, cssPath: string): void {\r\n const fullCssPath = path.join(cwd, cssPath)\r\n const cssDir = path.dirname(fullCssPath)\r\n\r\n // Ensure directory exists\r\n if (!fs.existsSync(cssDir)) {\r\n fs.mkdirSync(cssDir, { recursive: true })\r\n }\r\n\r\n const nexaImports = `/* Nexa UI Theme */\r\n@import \"@nexa-ui-kit/theme-default/components\";\r\n`\r\n\r\n if (fs.existsSync(fullCssPath)) {\r\n // Read existing content\r\n let content = fs.readFileSync(fullCssPath, 'utf-8')\r\n\r\n // Check if already has Nexa UI imports\r\n if (content.includes('@nexa-ui-kit/theme-default')) {\r\n logger.log(` ${dim('✓')} CSS already configured`)\r\n return\r\n }\r\n\r\n // Find the right place to insert (after @import \"tailwindcss\" or at the beginning)\r\n const tailwindImportMatch = content.match(/@import\\s+[\"']tailwindcss[\"'];?\\n?/)\r\n if (tailwindImportMatch) {\r\n const insertIndex = (tailwindImportMatch.index ?? 0) + tailwindImportMatch[0].length\r\n content = content.slice(0, insertIndex) + '\\n' + nexaImports + content.slice(insertIndex)\r\n } else {\r\n // Prepend at the beginning\r\n content = nexaImports + '\\n' + content\r\n }\r\n\r\n fs.writeFileSync(fullCssPath, content, 'utf-8')\r\n } else {\r\n // Create new CSS file with Tailwind v4 setup\r\n const newCssContent = `@import \"tailwindcss\";\r\n\r\n${nexaImports}\r\n`\r\n fs.writeFileSync(fullCssPath, newCssContent, 'utf-8')\r\n }\r\n\r\n logger.log(` ${dim('✓')} Updated ${highlight(cssPath)}`)\r\n}\r\n\r\n/**\r\n * Update tsconfig.json with path aliases\r\n */\r\nfunction updateTsConfig(cwd: string, aliases: Config['aliases']): void {\r\n const tsconfigPath = path.join(cwd, 'tsconfig.json')\r\n\r\n if (!fs.existsSync(tsconfigPath)) {\r\n return\r\n }\r\n\r\n try {\r\n const content = fs.readFileSync(tsconfigPath, 'utf-8')\r\n const tsconfig = JSON.parse(content)\r\n\r\n // Ensure compilerOptions exists\r\n tsconfig.compilerOptions = tsconfig.compilerOptions || {}\r\n tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {}\r\n\r\n // Add path aliases if not already present\r\n const baseUrl = tsconfig.compilerOptions.baseUrl || '.'\r\n const componentsAlias = aliases.components.replace(/\\/\\*?$/, '')\r\n const utilsAlias = aliases.utils.replace(/\\/\\*?$/, '')\r\n\r\n // Only add if using @ alias pattern\r\n if (componentsAlias.startsWith('@/')) {\r\n const aliasKey = componentsAlias.endsWith('*') ? componentsAlias : `${componentsAlias}/*`\r\n if (!tsconfig.compilerOptions.paths[aliasKey]) {\r\n const relativePath = `./src/${componentsAlias.slice(2)}/*`\r\n tsconfig.compilerOptions.paths[aliasKey] = [relativePath]\r\n tsconfig.compilerOptions.paths[componentsAlias] = [`./src/${componentsAlias.slice(2)}`]\r\n }\r\n }\r\n\r\n if (utilsAlias.startsWith('@/')) {\r\n const aliasKey = utilsAlias.endsWith('*') ? utilsAlias : `${utilsAlias}/*`\r\n if (!tsconfig.compilerOptions.paths[aliasKey]) {\r\n const relativePath = `./src/${utilsAlias.slice(2)}/*`\r\n tsconfig.compilerOptions.paths[aliasKey] = [relativePath]\r\n tsconfig.compilerOptions.paths[utilsAlias] = [`./src/${utilsAlias.slice(2)}`]\r\n }\r\n }\r\n\r\n // Set baseUrl if not set\r\n if (!tsconfig.compilerOptions.baseUrl) {\r\n tsconfig.compilerOptions.baseUrl = '.'\r\n }\r\n\r\n fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + '\\n', 'utf-8')\r\n logger.log(` ${dim('✓')} Updated ${highlight('tsconfig.json')} with path aliases`)\r\n } catch (error) {\r\n logger.warn(` Could not update tsconfig.json: ${error}`)\r\n }\r\n}\r\n\r\n/**\r\n * Resolve component alias path to actual directory\r\n */\r\nfunction resolveAliasPath(alias: string, cwd: string): string {\r\n if (alias.startsWith('@/')) {\r\n return path.join(cwd, 'src', alias.slice(2))\r\n }\r\n if (alias.startsWith('./') || alias.startsWith('../')) {\r\n return path.resolve(cwd, alias)\r\n }\r\n return path.join(cwd, alias)\r\n}\r\n\r\n/**\r\n * Ensure components directory exists\r\n */\r\nfunction ensureComponentsDir(cwd: string, componentsAlias: string): void {\r\n const componentsDir = resolveAliasPath(componentsAlias, cwd)\r\n if (!fs.existsSync(componentsDir)) {\r\n fs.mkdirSync(componentsDir, { recursive: true })\r\n logger.log(` ${dim('✓')} Created ${highlight(componentsAlias.replace('@/', 'src/'))} directory`)\r\n }\r\n}\r\n\r\nexport async function init(options: InitOptions): Promise<void> {\r\n const { cwd, yes } = options\r\n\r\n logger.break()\r\n logger.info('Initializing Nexa UI in your project...')\r\n logger.break()\r\n\r\n // Check if already initialized\r\n if (configExists(cwd)) {\r\n logger.warn('Nexa UI is already initialized in this project.')\r\n logger.info(`Config file exists at ${highlight('nexa-ui.json')}`)\r\n return\r\n }\r\n\r\n // Detect project info\r\n const projectInfo = detectProject(cwd)\r\n logger.log(` ${dim('Detected:')} ${highlight(projectInfo.framework)} with ${highlight(projectInfo.packageManager)}`)\r\n if (projectInfo.typescript) {\r\n logger.log(` ${dim('TypeScript:')} ${highlight('yes')}`)\r\n }\r\n logger.break()\r\n\r\n let config: Config\r\n\r\n if (yes) {\r\n // Use defaults based on detected project\r\n config = {\r\n style: 'default',\r\n css: projectInfo.cssPath,\r\n aliases: {\r\n components: '@/components',\r\n utils: '@/lib/utils',\r\n },\r\n }\r\n } else {\r\n // Interactive prompts\r\n const response = await prompts([\r\n {\r\n type: 'select',\r\n name: 'style',\r\n message: 'Which style would you like to use?',\r\n choices: [\r\n { title: 'Default', value: 'default' },\r\n { title: 'New York', value: 'new-york' },\r\n ],\r\n initial: 0,\r\n },\r\n {\r\n type: 'text',\r\n name: 'css',\r\n message: 'Where is your global CSS file?',\r\n initial: projectInfo.cssPath,\r\n },\r\n {\r\n type: 'text',\r\n name: 'componentsAlias',\r\n message: 'Configure the import alias for components:',\r\n initial: '@/components',\r\n },\r\n {\r\n type: 'text',\r\n name: 'utilsAlias',\r\n message: 'Configure the import alias for utils:',\r\n initial: '@/lib/utils',\r\n },\r\n ])\r\n\r\n // Check if user cancelled\r\n if (!response.style) {\r\n logger.break()\r\n logger.warn('Initialization cancelled.')\r\n return\r\n }\r\n\r\n config = {\r\n style: response.style,\r\n css: response.css,\r\n aliases: {\r\n components: response.componentsAlias,\r\n utils: response.utilsAlias,\r\n },\r\n }\r\n }\r\n\r\n logger.break()\r\n logger.info('Installing dependencies...')\r\n logger.break()\r\n\r\n // Install required packages\r\n const packages = [\r\n '@nexa-ui-kit/core',\r\n '@nexa-ui-kit/theme-default',\r\n 'clsx',\r\n 'tailwind-merge',\r\n 'class-variance-authority',\r\n ]\r\n\r\n const installCmd = getInstallCommand(projectInfo.packageManager, packages)\r\n logger.log(` ${dim('$')} ${installCmd}`)\r\n\r\n try {\r\n execSync(installCmd, { cwd, stdio: 'inherit' })\r\n } catch (error) {\r\n logger.error('Failed to install dependencies.')\r\n logger.info('Please install manually:')\r\n logger.log(` ${installCmd}`)\r\n logger.break()\r\n }\r\n\r\n logger.break()\r\n logger.info('Configuring project...')\r\n logger.break()\r\n\r\n // Create cn utility\r\n createCnUtility(cwd, config.aliases.utils, projectInfo.typescript)\r\n\r\n // Update CSS file\r\n updateCssFile(cwd, config.css)\r\n\r\n // Update tsconfig\r\n if (projectInfo.typescript) {\r\n updateTsConfig(cwd, config.aliases)\r\n }\r\n\r\n // Ensure components directory exists\r\n ensureComponentsDir(cwd, config.aliases.components)\r\n\r\n // Save config\r\n await saveConfig(cwd, config)\r\n\r\n logger.break()\r\n logger.success('Nexa UI initialized successfully!')\r\n logger.break()\r\n logger.info(`Configuration saved to ${highlight('nexa-ui.json')}`)\r\n logger.break()\r\n logger.info('Next steps:')\r\n logger.log(` 1. Add components: ${highlight('npx @nexa-ui-kit/cli add button')}`)\r\n logger.log(` 2. Import in your code: ${highlight(\"import { Button } from '@/components/button'\")}`)\r\n logger.break()\r\n}\r\n","/**\r\n * List of all available components from the core package\r\n * that can be added via the CLI.\r\n */\r\nexport const AVAILABLE_COMPONENTS = [\r\n 'accordion',\r\n 'aspect-ratio',\r\n 'avatar',\r\n 'badge',\r\n 'button',\r\n 'calendar',\r\n 'card',\r\n 'carousel',\r\n 'chart',\r\n 'checkbox',\r\n 'collapsible',\r\n 'command',\r\n 'context-menu',\r\n 'dropdown-menu',\r\n 'field',\r\n 'form',\r\n 'hover-card',\r\n 'input',\r\n 'input-group',\r\n 'item',\r\n 'kbd',\r\n 'label',\r\n 'menubar',\r\n 'navigation-menu',\r\n 'popover',\r\n 'progress',\r\n 'radio-group',\r\n 'select',\r\n 'separator',\r\n 'sidebar',\r\n 'skeleton',\r\n 'slider',\r\n 'sonner',\r\n 'spinner',\r\n 'switch',\r\n 'tabs',\r\n 'textarea',\r\n 'toggle',\r\n 'tooltip',\r\n] as const\r\n\r\nexport type AvailableComponent = (typeof AVAILABLE_COMPONENTS)[number]\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { AVAILABLE_COMPONENTS } from \"../constants/available-components\";\r\nimport { configExists, loadConfig } from \"../utils/config\";\r\nimport { dim, highlight, logger } from \"../utils/logger\";\r\n\r\nexport interface AddOptions {\r\n cwd: string;\r\n components: string[];\r\n overwrite?: boolean;\r\n}\r\n\r\n// Registry path (built from core components)\r\nconst REGISTRY_PATH = path.resolve(\r\n import.meta.dirname,\r\n \"../../../registry/dist/registry.json\",\r\n);\r\n\r\ninterface RegistryComponent {\r\n name: string;\r\n description?: string;\r\n dependencies: string[];\r\n devDependencies: string[];\r\n registryDependencies: string[];\r\n files: Array<{\r\n name: string;\r\n path: string;\r\n content: string;\r\n type: string;\r\n }>;\r\n}\r\n\r\ninterface Registry {\r\n name: string;\r\n version: string;\r\n components: RegistryComponent[];\r\n}\r\n\r\nexport async function add(options: AddOptions): Promise<void> {\r\n const { cwd, components, overwrite } = options;\r\n\r\n logger.break();\r\n\r\n // Check if initialized\r\n if (!configExists(cwd)) {\r\n logger.error(\"Nexa UI is not initialized in this project.\");\r\n logger.info(`Run ${highlight(\"npx @nexa-ui-kit/cli init\")} first.`);\r\n return;\r\n }\r\n\r\n // Load config\r\n const config = await loadConfig(cwd);\r\n if (!config) {\r\n logger.error(\"Failed to load Nexa UI configuration.\");\r\n return;\r\n }\r\n\r\n // Validate components\r\n const invalidComponents = components.filter(\r\n (c) => !(AVAILABLE_COMPONENTS as readonly string[]).includes(c),\r\n );\r\n\r\n if (invalidComponents.length > 0) {\r\n logger.error(`Unknown components: ${invalidComponents.join(\", \")}`);\r\n logger.info(\r\n `Run ${highlight(\r\n \"npx @nexa-ui-kit/cli list\",\r\n )} to see available components.`,\r\n );\r\n return;\r\n }\r\n\r\n // Load registry\r\n let registry: Registry;\r\n try {\r\n const registryContent = fs.readFileSync(REGISTRY_PATH, \"utf-8\");\r\n registry = JSON.parse(registryContent);\r\n } catch {\r\n logger.error(\"Failed to load component registry.\");\r\n logger.info(\"Please ensure the registry is built: npm run build:registry\");\r\n return;\r\n }\r\n\r\n // Get target directory from config\r\n const componentsDir = resolveAliasPath(config.aliases.components, cwd);\r\n\r\n // Track installed components and dependencies\r\n const installedComponents = new Set<string>();\r\n const componentsToInstall: string[] = [...components];\r\n\r\n // Collect all dependencies first\r\n const dependencies = new Set<string>();\r\n const devDependencies = new Set<string>();\r\n\r\n // Resolve registry dependencies recursively\r\n let index = 0;\r\n while (index < componentsToInstall.length) {\r\n const componentName = componentsToInstall[index];\r\n index++;\r\n\r\n if (installedComponents.has(componentName)) {\r\n continue;\r\n }\r\n\r\n const registryComponent = registry.components.find(\r\n (c) => c.name === componentName,\r\n );\r\n if (!registryComponent) {\r\n logger.error(`Component \"${componentName}\" not found in registry.`);\r\n continue;\r\n }\r\n\r\n // Add registry dependencies to the list\r\n for (const dep of registryComponent.registryDependencies) {\r\n if (!componentsToInstall.includes(dep)) {\r\n componentsToInstall.push(dep);\r\n }\r\n }\r\n\r\n registryComponent.dependencies.forEach((d) => dependencies.add(d));\r\n registryComponent.devDependencies.forEach((d) => devDependencies.add(d));\r\n installedComponents.add(componentName);\r\n }\r\n\r\n // Add components\r\n logger.info(`Adding ${installedComponents.size} component(s)...`);\r\n logger.break();\r\n\r\n // Ensure components directory exists\r\n if (!fs.existsSync(componentsDir)) {\r\n fs.mkdirSync(componentsDir, { recursive: true });\r\n }\r\n\r\n for (const componentName of componentsToInstall) {\r\n const registryComponent = registry.components.find(\r\n (c) => c.name === componentName,\r\n );\r\n if (!registryComponent) continue;\r\n\r\n const success = await writeComponentFile(\r\n registryComponent,\r\n componentsDir,\r\n overwrite,\r\n );\r\n if (success) {\r\n logger.log(` ${dim(\"✓\")} ${highlight(componentName)}`);\r\n }\r\n }\r\n\r\n logger.break();\r\n logger.success(\"Components added successfully!\");\r\n logger.break();\r\n\r\n // Show dependency info if any\r\n if (dependencies.size > 0 || devDependencies.size > 0) {\r\n logger.info(\"The following dependencies are required:\");\r\n if (dependencies.size > 0) {\r\n logger.log(\r\n ` ${dim(\"npm install\")} ${Array.from(dependencies).join(\" \")}`,\r\n );\r\n }\r\n if (devDependencies.size > 0) {\r\n logger.log(\r\n ` ${dim(\"npm install -D\")} ${Array.from(devDependencies).join(\" \")}`,\r\n );\r\n }\r\n logger.break();\r\n }\r\n\r\n if (overwrite) {\r\n logger.info(dim(\"Existing files were overwritten.\"));\r\n }\r\n}\r\n\r\n/**\r\n * Resolve component alias path to actual directory\r\n */\r\nfunction resolveAliasPath(alias: string, cwd: string): string {\r\n // Handle common aliases like \"@/components\" -> \"src/components\"\r\n if (alias.startsWith(\"@/\")) {\r\n return path.join(cwd, \"src\", alias.slice(2));\r\n }\r\n // Handle relative paths\r\n if (alias.startsWith(\"./\") || alias.startsWith(\"../\")) {\r\n return path.resolve(cwd, alias);\r\n }\r\n // Assume it's already a path\r\n return path.join(cwd, alias);\r\n}\r\n\r\n/**\r\n * Write component files to the target directory\r\n */\r\nasync function writeComponentFile(\r\n component: RegistryComponent,\r\n componentsDir: string,\r\n overwrite?: boolean,\r\n): Promise<boolean> {\r\n for (const file of component.files) {\r\n const filePath = path.join(componentsDir, file.name);\r\n\r\n // Check if file already exists\r\n if (fs.existsSync(filePath) && !overwrite) {\r\n logger.warn(\r\n ` File already exists: ${file.name} (use --overwrite to replace)`,\r\n );\r\n continue;\r\n }\r\n\r\n try {\r\n fs.writeFileSync(filePath, file.content, \"utf-8\");\r\n } catch (error) {\r\n logger.error(` Failed to write ${file.name}`);\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n","/**\r\n * Component descriptions for CLI list command\r\n * Maps component name to human-readable description\r\n */\r\nexport const COMPONENT_DESCRIPTIONS: Record<string, string> = {\r\n 'accordion': 'Vertically stacked collapsible sections',\r\n 'aspect-ratio': 'Maintains consistent width-to-height ratio',\r\n 'avatar': 'User avatar with image and fallback',\r\n 'badge': 'Small status indicator or label',\r\n 'button': 'Interactive button with variants',\r\n 'calendar': 'Date picker calendar (react-day-picker)',\r\n 'card': 'Container for grouping content',\r\n 'carousel': 'Slideshow component (embla-carousel)',\r\n 'chart': 'Data visualization charts (recharts)',\r\n 'checkbox': 'Checkbox input with label',\r\n 'collapsible': 'Expandable/collapsible content area',\r\n 'command': 'Command palette/search (cmdk)',\r\n 'context-menu': 'Right-click context menu',\r\n 'dropdown-menu': 'Dropdown menu with items',\r\n 'field': 'Form field layout with label/description',\r\n 'form': 'Form handling (react-hook-form)',\r\n 'hover-card': 'Card shown on hover',\r\n 'input': 'Text input field',\r\n 'input-group': 'Input with addons and buttons',\r\n 'item': 'List item with media and actions',\r\n 'kbd': 'Keyboard key indicator',\r\n 'label': 'Form label component',\r\n 'menubar': 'Horizontal menu bar',\r\n 'navigation-menu': 'Site navigation component',\r\n 'popover': 'Floating content popover',\r\n 'progress': 'Progress bar indicator',\r\n 'radio-group': 'Radio button group',\r\n 'select': 'Dropdown select input (Radix)',\r\n 'separator': 'Visual divider line',\r\n 'sidebar': 'Side navigation panel',\r\n 'skeleton': 'Loading placeholder skeleton',\r\n 'slider': 'Range slider input',\r\n 'sonner': 'Toast notifications (sonner)',\r\n 'spinner': 'Loading spinner indicator',\r\n 'switch': 'Toggle switch input',\r\n 'tabs': 'Tabbed content panels',\r\n 'textarea': 'Multi-line text input',\r\n 'toggle': 'Toggle button',\r\n 'tooltip': 'Hover tooltip',\r\n}\r\n","import { logger, highlight, dim } from '../utils/logger'\r\nimport { AVAILABLE_COMPONENTS } from '../constants/available-components'\r\nimport { COMPONENT_DESCRIPTIONS } from '../constants/component-descriptions'\r\n\r\nexport async function list(): Promise<void> {\r\n logger.break()\r\n logger.info(`Available Nexa UI components (${AVAILABLE_COMPONENTS.length}):`)\r\n logger.break()\r\n\r\n for (const name of AVAILABLE_COMPONENTS) {\r\n const description = COMPONENT_DESCRIPTIONS[name] || ''\r\n logger.log(` ${highlight(name.padEnd(20))} ${dim(description)}`)\r\n }\r\n\r\n logger.break()\r\n logger.info(`Add components with: ${highlight('npx @nexa-ui-kit/cli add <component>')}`)\r\n logger.info(`Add multiple: ${highlight('npx @nexa-ui-kit/cli add button card input')}`)\r\n logger.break()\r\n}\r\n","import { Command } from 'commander'\nimport { init } from './commands/init'\nimport { add } from './commands/add'\nimport { list } from './commands/list'\n\nconst program = new Command()\n\nprogram\n .name('nexa')\n .description('CLI for adding Nexa UI components to your project')\n .version('0.0.0')\n\nprogram\n .command('init')\n .description('Initialize Nexa UI in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action(async (options) => {\n await init({\n cwd: options.cwd,\n yes: options.yes,\n })\n })\n\nprogram\n .command('add')\n .description('Add components to your project')\n .argument('<components...>', 'Components to add')\n .option('-o, --overwrite', 'Overwrite existing files')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action(async (components, options) => {\n await add({\n cwd: options.cwd,\n components,\n overwrite: options.overwrite,\n })\n })\n\nprogram\n .command('list')\n .description('List available components')\n .action(async () => {\n await list()\n })\n\nprogram.parse()\n"]}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@nexa-ui-kit/cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI for adding Nexa UI components to your project",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "bin": {
11
+ "nexa": "./dist/index.js"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "clean": "rm -rf dist",
24
+ "validate": "attw --pack . --ignore-rules cjs-resolves-to-esm && publint ."
25
+ },
26
+ "dependencies": {
27
+ "commander": "^12.0.0",
28
+ "picocolors": "^1.1.0",
29
+ "prompts": "^2.4.0",
30
+ "zod": "^3.24.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.0.0",
34
+ "@types/prompts": "^2.4.0",
35
+ "tsup": "^8.4.0",
36
+ "typescript": "^5.7.0"
37
+ },
38
+ "keywords": [
39
+ "nexa-ui-kit",
40
+ "cli",
41
+ "components",
42
+ "react"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/nexa-opensource/nexa-ui-kit.git",
47
+ "directory": "packages/cli"
48
+ }
49
+ }