@srcroot/ui 0.0.33 → 0.0.35

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.
Files changed (2) hide show
  1. package/dist/index.js +101 -88
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -5,11 +5,12 @@ import { Command } from "commander";
5
5
  import chalk3 from "chalk";
6
6
 
7
7
  // src/cli/services/project-initializer.ts
8
- import fs2 from "fs-extra";
9
- import path2 from "path";
8
+ import fs3 from "fs-extra";
9
+ import path3 from "path";
10
10
  import ora from "ora";
11
11
  import prompts from "prompts";
12
12
  import { fileURLToPath as fileURLToPath2 } from "url";
13
+ import { execa } from "execa";
13
14
 
14
15
  // src/cli/services/theme-service.ts
15
16
  import fs from "fs-extra";
@@ -143,20 +144,21 @@ export default config
143
144
  `;
144
145
 
145
146
  // src/cli/utils/get-package-manager.ts
146
- function getPackageManager() {
147
+ import fs2 from "fs";
148
+ import path2 from "path";
149
+ function getPackageManager(cwd) {
147
150
  const userAgent = process.env.npm_config_user_agent;
148
- if (!userAgent) {
149
- return "npm";
150
- }
151
- if (userAgent.startsWith("yarn")) {
152
- return "yarn";
153
- }
154
- if (userAgent.startsWith("pnpm")) {
155
- return "pnpm";
156
- }
157
- if (userAgent.startsWith("bun")) {
158
- return "bun";
151
+ if (userAgent) {
152
+ if (userAgent.startsWith("yarn")) return "yarn";
153
+ if (userAgent.startsWith("pnpm")) return "pnpm";
154
+ if (userAgent.startsWith("bun")) return "bun";
155
+ if (userAgent.startsWith("npm")) return "npm";
159
156
  }
157
+ const dir = cwd || process.cwd();
158
+ if (fs2.existsSync(path2.join(dir, "bun.lockb"))) return "bun";
159
+ if (fs2.existsSync(path2.join(dir, "pnpm-lock.yaml"))) return "pnpm";
160
+ if (fs2.existsSync(path2.join(dir, "yarn.lock"))) return "yarn";
161
+ if (fs2.existsSync(path2.join(dir, "package-lock.json"))) return "npm";
160
162
  return "npm";
161
163
  }
162
164
 
@@ -178,7 +180,7 @@ var logger = {
178
180
  };
179
181
 
180
182
  // src/cli/services/project-initializer.ts
181
- var __dirname3 = path2.dirname(fileURLToPath2(import.meta.url));
183
+ var __dirname3 = path3.dirname(fileURLToPath2(import.meta.url));
182
184
  var ProjectInitializer = class {
183
185
  options;
184
186
  config = {};
@@ -193,16 +195,17 @@ var ProjectInitializer = class {
193
195
  await this.detectConfiguration();
194
196
  await this.promptUser();
195
197
  await this.scaffold();
198
+ await this.installDependencies();
196
199
  this.printSuccess();
197
200
  }
198
201
  async validateEnvironment() {
199
- const cwd = path2.resolve(this.options.cwd);
200
- const packageJsonPath = path2.join(cwd, "package.json");
201
- if (!fs2.existsSync(packageJsonPath)) {
202
+ const cwd = path3.resolve(this.options.cwd);
203
+ const packageJsonPath = path3.join(cwd, "package.json");
204
+ if (!fs3.existsSync(packageJsonPath)) {
202
205
  logger.error("Error: No package.json found. Please run this in a project directory.");
203
206
  process.exit(1);
204
207
  }
205
- const pkg = await fs2.readJson(packageJsonPath);
208
+ const pkg = await fs3.readJson(packageJsonPath);
206
209
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
207
210
  if (!allDeps["react"]) {
208
211
  logger.error("Error: React not found in dependencies. Please initialize this in a React project.");
@@ -210,33 +213,33 @@ var ProjectInitializer = class {
210
213
  }
211
214
  }
212
215
  async detectConfiguration() {
213
- const cwd = path2.resolve(this.options.cwd);
214
- const packageManager = getPackageManager();
216
+ const cwd = path3.resolve(this.options.cwd);
217
+ const packageManager = getPackageManager(cwd);
215
218
  const installCmd = packageManager === "npm" ? "install" : "add";
216
- const pkg = await fs2.readJson(path2.join(cwd, "package.json"));
219
+ const pkg = await fs3.readJson(path3.join(cwd, "package.json"));
217
220
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
218
221
  const tailwindVersion = allDeps["tailwindcss"] || "";
219
222
  const isTailwind4 = tailwindVersion.includes("^4") || tailwindVersion.startsWith("4") || allDeps["@tailwindcss/postcss"];
220
- const hasSrc = fs2.existsSync(path2.join(cwd, "src"));
221
- const srcPath = hasSrc ? path2.join(cwd, "src") : cwd;
222
- const appPath = path2.join(srcPath, "app");
223
- const pagesPath = path2.join(srcPath, "pages");
224
- const hasAppDir = fs2.existsSync(appPath);
225
- const hasPagesDir = fs2.existsSync(pagesPath);
226
- const libDir = path2.join(srcPath, "lib");
227
- const componentsDir = path2.join(srcPath, "components", "ui");
223
+ const hasSrc = fs3.existsSync(path3.join(cwd, "src"));
224
+ const srcPath = hasSrc ? path3.join(cwd, "src") : cwd;
225
+ const appPath = path3.join(srcPath, "app");
226
+ const pagesPath = path3.join(srcPath, "pages");
227
+ const hasAppDir = fs3.existsSync(appPath);
228
+ const hasPagesDir = fs3.existsSync(pagesPath);
229
+ const libDir = path3.join(srcPath, "lib");
230
+ const componentsDir = path3.join(srcPath, "components", "ui");
228
231
  let globalsPath = "";
229
232
  if (hasAppDir) {
230
- if (fs2.existsSync(path2.join(appPath, "globals.css"))) globalsPath = path2.join(appPath, "globals.css");
231
- else if (fs2.existsSync(path2.join(appPath, "global.css"))) globalsPath = path2.join(appPath, "global.css");
232
- else globalsPath = path2.join(appPath, "globals.css");
233
+ if (fs3.existsSync(path3.join(appPath, "globals.css"))) globalsPath = path3.join(appPath, "globals.css");
234
+ else if (fs3.existsSync(path3.join(appPath, "global.css"))) globalsPath = path3.join(appPath, "global.css");
235
+ else globalsPath = path3.join(appPath, "globals.css");
233
236
  } else if (hasPagesDir) {
234
- const stylesPath = path2.join(srcPath, "styles");
235
- if (fs2.existsSync(path2.join(stylesPath, "globals.css"))) globalsPath = path2.join(stylesPath, "globals.css");
236
- else if (fs2.existsSync(path2.join(stylesPath, "global.css"))) globalsPath = path2.join(stylesPath, "global.css");
237
- else globalsPath = path2.join(stylesPath, "globals.css");
237
+ const stylesPath = path3.join(srcPath, "styles");
238
+ if (fs3.existsSync(path3.join(stylesPath, "globals.css"))) globalsPath = path3.join(stylesPath, "globals.css");
239
+ else if (fs3.existsSync(path3.join(stylesPath, "global.css"))) globalsPath = path3.join(stylesPath, "global.css");
240
+ else globalsPath = path3.join(stylesPath, "globals.css");
238
241
  } else {
239
- globalsPath = path2.join(srcPath, "globals.css");
242
+ globalsPath = path3.join(srcPath, "globals.css");
240
243
  }
241
244
  this.config = {
242
245
  cwd,
@@ -264,7 +267,7 @@ var ProjectInitializer = class {
264
267
  return;
265
268
  }
266
269
  const themeChoices = availableThemes.map((theme) => ({
267
- title: `${theme.name} - ${theme.description}`,
270
+ title: theme.name,
268
271
  value: theme.file.replace(".css", "")
269
272
  }));
270
273
  const themeResponse = await prompts({
@@ -284,13 +287,13 @@ var ProjectInitializer = class {
284
287
  const spinner = ora("Creating project structure...").start();
285
288
  const cfg = this.config;
286
289
  try {
287
- await fs2.ensureDir(cfg.libDir);
288
- await fs2.ensureDir(cfg.componentsDir);
289
- const utilsPath = path2.join(cfg.libDir, "utils.ts");
290
- const registryUtilsPath = path2.resolve(__dirname3, "..", "src", "registry", "lib", "utils.ts");
290
+ await fs3.ensureDir(cfg.libDir);
291
+ await fs3.ensureDir(cfg.componentsDir);
292
+ const utilsPath = path3.join(cfg.libDir, "utils.ts");
293
+ const registryUtilsPath = path3.resolve(__dirname3, "..", "src", "registry", "lib", "utils.ts");
291
294
  let utilsContent = "";
292
- if (fs2.existsSync(registryUtilsPath)) {
293
- utilsContent = await fs2.readFile(registryUtilsPath, "utf-8");
295
+ if (fs3.existsSync(registryUtilsPath)) {
296
+ utilsContent = await fs3.readFile(registryUtilsPath, "utf-8");
294
297
  } else {
295
298
  utilsContent = `import { type ClassValue, clsx } from "clsx"
296
299
  import { twMerge } from "tailwind-merge"
@@ -301,15 +304,15 @@ export function cn(...inputs: ClassValue[]) {
301
304
  `;
302
305
  spinner.warn(`Could not find registry/utils.ts, using fallback content.`);
303
306
  }
304
- await fs2.writeFile(utilsPath, utilsContent);
305
- spinner.succeed(`Created ${path2.relative(cfg.cwd, utilsPath)}`);
307
+ await fs3.writeFile(utilsPath, utilsContent);
308
+ spinner.succeed(`Created ${path3.relative(cfg.cwd, utilsPath)}`);
306
309
  spinner.start(`Setting up ${cfg.selectedTheme} theme...`);
307
- const stylesDir = path2.dirname(cfg.globalsPath);
308
- await fs2.ensureDir(stylesDir);
310
+ const stylesDir = path3.dirname(cfg.globalsPath);
311
+ await fs3.ensureDir(stylesDir);
309
312
  try {
310
313
  const cssContent = await this.themeService.getThemeCss(cfg.selectedTheme, cfg.isTailwind4);
311
- await fs2.writeFile(cfg.globalsPath, cssContent);
312
- spinner.succeed(`Updated ${path2.relative(cfg.cwd, cfg.globalsPath)} with ${cfg.selectedTheme} theme (${cfg.isTailwind4 ? "Tailwind 4" : "Tailwind 3"})`);
314
+ await fs3.writeFile(cfg.globalsPath, cssContent);
315
+ spinner.succeed(`Updated ${path3.relative(cfg.cwd, cfg.globalsPath)} with ${cfg.selectedTheme} theme (${cfg.isTailwind4 ? "Tailwind 4" : "Tailwind 3"})`);
313
316
  } catch (error) {
314
317
  spinner.fail(`Failed to load theme: ${cfg.selectedTheme}`);
315
318
  console.error(error);
@@ -317,11 +320,9 @@ export function cn(...inputs: ClassValue[]) {
317
320
  }
318
321
  if (!cfg.isTailwind4) {
319
322
  spinner.start("Setting up Tailwind config...");
320
- const tailwindConfigPath = path2.join(cfg.cwd, "tailwind.config.ts");
321
- await fs2.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
323
+ const tailwindConfigPath = path3.join(cfg.cwd, "tailwind.config.ts");
324
+ await fs3.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
322
325
  spinner.succeed(`Created tailwind.config.ts`);
323
- } else {
324
- spinner.info(`Tailwind 4 detected - skipping tailwind.config.ts`);
325
326
  }
326
327
  } catch (error) {
327
328
  spinner.fail("Failed to initialize project");
@@ -329,26 +330,38 @@ export function cn(...inputs: ClassValue[]) {
329
330
  process.exit(1);
330
331
  }
331
332
  }
332
- printSuccess() {
333
+ async installDependencies() {
333
334
  const cfg = this.config;
334
- logger.success("\n\u2705 Project initialized successfully!\n");
335
- console.log(`Theme: ${cfg.selectedTheme}`);
336
- console.log(`Tailwind: ${cfg.isTailwind4 ? "v4" : "v3"}`);
337
- const requiredDeps = [
335
+ const spinner = ora("Installing dependencies...").start();
336
+ const deps = [
338
337
  "clsx",
339
338
  "tailwind-merge",
340
339
  "class-variance-authority",
341
340
  "react-icons"
342
341
  ];
343
342
  if (!cfg.isTailwind4) {
344
- requiredDeps.push("tailwindcss-animate");
343
+ deps.push("tailwindcss-animate");
344
+ }
345
+ try {
346
+ await execa(cfg.packageManager, [cfg.installCmd, ...deps], {
347
+ cwd: cfg.cwd,
348
+ stdio: "pipe"
349
+ });
350
+ spinner.succeed(`Installed ${deps.length} dependencies`);
351
+ } catch (error) {
352
+ spinner.fail("Failed to install dependencies");
353
+ logger.warn(`
354
+ Manually run: ${cfg.packageManager} ${cfg.installCmd} ${deps.join(" ")}`);
345
355
  }
346
- logger.info("\n\u{1F4E6} Required dependencies:");
347
- console.log(` ${cfg.packageManager} ${cfg.installCmd} ${requiredDeps.join(" ")}`);
356
+ }
357
+ printSuccess() {
358
+ const cfg = this.config;
359
+ logger.success("\n\u2705 Project initialized successfully!\n");
360
+ console.log(`Theme: ${cfg.selectedTheme}`);
361
+ console.log(`Tailwind: ${cfg.isTailwind4 ? "v4" : "v3"}`);
348
362
  console.log("\n\u2728 Next steps:");
349
- console.log(" 1. Install dependencies (command above)");
350
- console.log(" 2. npx @srcroot/ui add button");
351
- console.log(" 3. npx @srcroot/ui add --all");
363
+ console.log(" 1. npx @srcroot/ui add button");
364
+ console.log(" 2. npx @srcroot/ui add --all");
352
365
  console.log();
353
366
  }
354
367
  };
@@ -360,8 +373,8 @@ async function init(options) {
360
373
  }
361
374
 
362
375
  // src/cli/commands/add.ts
363
- import fs3 from "fs-extra";
364
- import path3 from "path";
376
+ import fs4 from "fs-extra";
377
+ import path4 from "path";
365
378
  import ora2 from "ora";
366
379
  import prompts2 from "prompts";
367
380
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -746,9 +759,9 @@ var REGISTRY = {
746
759
  };
747
760
 
748
761
  // src/cli/commands/add.ts
749
- var __dirname4 = path3.dirname(fileURLToPath3(import.meta.url));
762
+ var __dirname4 = path4.dirname(fileURLToPath3(import.meta.url));
750
763
  async function add(components, options) {
751
- const cwd = path3.resolve(options.cwd);
764
+ const cwd = path4.resolve(options.cwd);
752
765
  if (options.all) {
753
766
  components = Object.keys(REGISTRY);
754
767
  }
@@ -811,16 +824,16 @@ async function add(components, options) {
811
824
  }
812
825
  console.log();
813
826
  const spinner = ora2("Adding components...").start();
814
- const hasSrc = fs3.existsSync(path3.join(cwd, "src"));
815
- const srcPath = hasSrc ? path3.join(cwd, "src") : cwd;
816
- const componentsDir = path3.join(srcPath, "components", "ui");
827
+ const hasSrc = fs4.existsSync(path4.join(cwd, "src"));
828
+ const srcPath = hasSrc ? path4.join(cwd, "src") : cwd;
829
+ const componentsDir = path4.join(srcPath, "components", "ui");
817
830
  try {
818
- await fs3.ensureDir(componentsDir);
831
+ await fs4.ensureDir(componentsDir);
819
832
  for (const name of componentsToAdd) {
820
833
  const comp = REGISTRY[name];
821
- const fileName = path3.basename(comp.file);
822
- const targetPath = path3.join(componentsDir, fileName);
823
- if (fs3.existsSync(targetPath) && !options.overwrite) {
834
+ const fileName = path4.basename(comp.file);
835
+ const targetPath = path4.join(componentsDir, fileName);
836
+ if (fs4.existsSync(targetPath) && !options.overwrite) {
824
837
  spinner.stop();
825
838
  const { overwrite } = await prompts2({
826
839
  type: "confirm",
@@ -835,13 +848,13 @@ async function add(components, options) {
835
848
  }
836
849
  spinner.start("Adding components...");
837
850
  }
838
- const registryPath = path3.resolve(__dirname4, "..", "src", "registry", comp.file);
839
- if (!fs3.existsSync(registryPath)) {
851
+ const registryPath = path4.resolve(__dirname4, "..", "src", "registry", comp.file);
852
+ if (!fs4.existsSync(registryPath)) {
840
853
  spinner.warn(`Registry file not found for ${name}: ${registryPath}`);
841
854
  continue;
842
855
  }
843
- const content = await fs3.readFile(registryPath, "utf-8");
844
- await fs3.writeFile(targetPath, content);
856
+ const content = await fs4.readFile(registryPath, "utf-8");
857
+ await fs4.writeFile(targetPath, content);
845
858
  if (componentsToAdd.length > 10) {
846
859
  spinner.text = `Adding ${fileName}...`;
847
860
  } else {
@@ -891,19 +904,19 @@ async function list() {
891
904
  }
892
905
 
893
906
  // src/cli/utils/get-package-info.ts
894
- import path4 from "path";
895
- import fs4 from "fs-extra";
907
+ import path5 from "path";
908
+ import fs5 from "fs-extra";
896
909
  import { fileURLToPath as fileURLToPath4 } from "url";
897
910
  function getPackageInfo() {
898
911
  const __filename2 = fileURLToPath4(import.meta.url);
899
- const __dirname5 = path4.dirname(__filename2);
912
+ const __dirname5 = path5.dirname(__filename2);
900
913
  const pathsToCheck = [
901
- path4.resolve(__dirname5, "..", "package.json"),
902
- path4.resolve(__dirname5, "..", "..", "..", "package.json")
914
+ path5.resolve(__dirname5, "..", "package.json"),
915
+ path5.resolve(__dirname5, "..", "..", "..", "package.json")
903
916
  ];
904
917
  for (const pkgPath of pathsToCheck) {
905
- if (fs4.existsSync(pkgPath)) {
906
- return fs4.readJSONSync(pkgPath);
918
+ if (fs5.existsSync(pkgPath)) {
919
+ return fs5.readJSONSync(pkgPath);
907
920
  }
908
921
  }
909
922
  return { version: "0.0.0" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srcroot/ui",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "description": "A UI library with polymorphic, accessible React components",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,6 +25,7 @@
25
25
  "dependencies": {
26
26
  "chalk": "^5.3.0",
27
27
  "commander": "^12.1.0",
28
+ "execa": "^9.6.1",
28
29
  "fs-extra": "^11.2.0",
29
30
  "ora": "^8.1.1",
30
31
  "prompts": "^2.4.2"