@work-rjkashyap/unified-ui 0.3.2 → 0.3.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/CHANGELOG.md +7 -0
- package/bin/cli.mjs +248 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
### 🚀 Features
|
|
12
12
|
|
|
13
|
+
- Add motion tokens for animation consistency
|
|
14
|
+
- Introduced motion tokens in `motion.ts` for durations, easings, springs, and stagger timings to standardize animations across the design system. ([65feea0](https://github.com/imrj05/unified-ui/commit/65feea0c5ab3b43d3aa6a4300aedda58b9769fad))
|
|
15
|
+
## [0.3.2] — 2026-03-09
|
|
16
|
+
|
|
17
|
+
### 🚀 Features
|
|
18
|
+
|
|
13
19
|
- Update composer.json version to 0.0.5, add PHP config integration, and enhance InitCommand ([26cacd4](https://github.com/imrj05/unified-ui/commit/26cacd4b8a16ea4cc31d7894c5fb0dbbb0541f8a))
|
|
14
20
|
- Update composer.json version to 0.0.4 and enhance InitCommand with skip-npm option ([0ce9f0e](https://github.com/imrj05/unified-ui/commit/0ce9f0eb0e9da9bdf8e421a27571b160b343e293))
|
|
15
21
|
- Update composer.json version and enhance InitCommand for app.js and app.css patching ([67ee978](https://github.com/imrj05/unified-ui/commit/67ee97825c2c89ef7c2da15bc41532c1aa776da7))
|
|
@@ -45,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
45
51
|
|
|
46
52
|
### 🏗️ Miscellaneous
|
|
47
53
|
|
|
54
|
+
- **changelog:** Auto-update unreleased entries [skip ci] ([7fb15c9](https://github.com/imrj05/unified-ui/commit/7fb15c907a060b6c15d65fd85e073ed1cbcff740))
|
|
48
55
|
- **changelog:** Auto-update unreleased entries [skip ci] ([7dbe966](https://github.com/imrj05/unified-ui/commit/7dbe96600fe84196757a878c4256a3e3cb0f6682))
|
|
49
56
|
- **changelog:** Auto-update unreleased entries [skip ci] ([6569725](https://github.com/imrj05/unified-ui/commit/656972599dd7703317fbd6b184b95050aca092d8))
|
|
50
57
|
- **changelog:** Auto-update unreleased entries [skip ci] ([57bfcc3](https://github.com/imrj05/unified-ui/commit/57bfcc37256d43487f773bddda7d8c70e7c89b31))
|
package/bin/cli.mjs
CHANGED
|
@@ -27,12 +27,12 @@ import { execSync } from "node:child_process";
|
|
|
27
27
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
28
28
|
import { dirname, join, resolve } from "node:path";
|
|
29
29
|
import { createInterface } from "node:readline";
|
|
30
|
+
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
// Config
|
|
32
33
|
// ---------------------------------------------------------------------------
|
|
33
34
|
const REGISTRY_BASE_URL =
|
|
34
|
-
process.env.UNIFIED_UI_REGISTRY_URL ||
|
|
35
|
-
"https://www.unified-ui.space/r";
|
|
35
|
+
process.env.UNIFIED_UI_REGISTRY_URL || "https://www.unified-ui.space/r";
|
|
36
36
|
const CONFIG_FILE = "unified-ui.json";
|
|
37
37
|
// ---------------------------------------------------------------------------
|
|
38
38
|
// Starter kit templates
|
|
@@ -333,6 +333,248 @@ async function installNpmDeps(deps, root) {
|
|
|
333
333
|
);
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
|
+
async function installNpmDevDeps(deps, root) {
|
|
337
|
+
if (deps.length === 0) return;
|
|
338
|
+
const pm = await detectPackageManager(root);
|
|
339
|
+
const cmd = getInstallCommand(pm, deps)
|
|
340
|
+
.replace(" add ", " add -D ")
|
|
341
|
+
.replace(" install ", " install -D ");
|
|
342
|
+
logStep("📦", `Installing dev dependencies with ${c("cyan", pm)}...`);
|
|
343
|
+
logStep(" ", c("dim", cmd));
|
|
344
|
+
try {
|
|
345
|
+
execSync(cmd, { cwd: root, stdio: "pipe" });
|
|
346
|
+
logStep("✓", c("green", `${deps.length} dev package(s) installed`));
|
|
347
|
+
} catch (_err) {
|
|
348
|
+
logStep(
|
|
349
|
+
"⚠",
|
|
350
|
+
c("yellow", `Auto-install failed. Run manually:\n ${cmd}`),
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Vite + Tailwind CSS detection & setup
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
function detectViteConfig(root) {
|
|
358
|
+
for (const name of [
|
|
359
|
+
"vite.config.ts",
|
|
360
|
+
"vite.config.js",
|
|
361
|
+
"vite.config.mjs",
|
|
362
|
+
"vite.config.mts",
|
|
363
|
+
]) {
|
|
364
|
+
if (existsSync(join(root, name))) return name;
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
function hasDependency(root, pkg) {
|
|
369
|
+
try {
|
|
370
|
+
const raw = readFileSync(join(root, "package.json"), "utf-8");
|
|
371
|
+
const json = JSON.parse(raw);
|
|
372
|
+
const all = {
|
|
373
|
+
...json.dependencies,
|
|
374
|
+
...json.devDependencies,
|
|
375
|
+
...json.peerDependencies,
|
|
376
|
+
};
|
|
377
|
+
return Boolean(all[pkg]);
|
|
378
|
+
} catch {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async function setupTailwindForVite(root, config) {
|
|
383
|
+
const viteConfigName = detectViteConfig(root);
|
|
384
|
+
if (!viteConfigName) return; // Not a Vite project
|
|
385
|
+
|
|
386
|
+
logStep("🔍", "Detected Vite project");
|
|
387
|
+
|
|
388
|
+
// 1. Install tailwindcss + @tailwindcss/vite if missing
|
|
389
|
+
const missingDevDeps = [];
|
|
390
|
+
if (!hasDependency(root, "tailwindcss")) missingDevDeps.push("tailwindcss");
|
|
391
|
+
if (!hasDependency(root, "@tailwindcss/vite"))
|
|
392
|
+
missingDevDeps.push("@tailwindcss/vite");
|
|
393
|
+
if (missingDevDeps.length > 0) {
|
|
394
|
+
await installNpmDevDeps(missingDevDeps, root);
|
|
395
|
+
} else {
|
|
396
|
+
logStep("✓", c("dim", "tailwindcss + @tailwindcss/vite already installed"));
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// 2. Patch vite.config to add tailwindcss plugin, path import, and @ alias
|
|
400
|
+
const viteConfigPath = join(root, viteConfigName);
|
|
401
|
+
let viteContent = readFileSync(viteConfigPath, "utf-8");
|
|
402
|
+
let viteModified = false;
|
|
403
|
+
|
|
404
|
+
// 2a. Add @tailwindcss/vite import + plugin
|
|
405
|
+
if (!viteContent.includes("@tailwindcss/vite")) {
|
|
406
|
+
const tailwindImport = 'import tailwindcss from "@tailwindcss/vite";\n';
|
|
407
|
+
const importMatch = viteContent.match(/^(import\s.+\n)+/m);
|
|
408
|
+
if (importMatch) {
|
|
409
|
+
const lastImportEnd = importMatch.index + importMatch[0].length;
|
|
410
|
+
viteContent =
|
|
411
|
+
viteContent.slice(0, lastImportEnd) +
|
|
412
|
+
tailwindImport +
|
|
413
|
+
viteContent.slice(lastImportEnd);
|
|
414
|
+
} else {
|
|
415
|
+
viteContent = tailwindImport + viteContent;
|
|
416
|
+
}
|
|
417
|
+
if (viteContent.includes("plugins:")) {
|
|
418
|
+
viteContent = viteContent.replace(
|
|
419
|
+
/plugins:\s*\[/,
|
|
420
|
+
"plugins: [\n tailwindcss(),",
|
|
421
|
+
);
|
|
422
|
+
} else if (viteContent.includes("defineConfig({")) {
|
|
423
|
+
viteContent = viteContent.replace(
|
|
424
|
+
/defineConfig\(\{/,
|
|
425
|
+
"defineConfig({\n plugins: [tailwindcss()],",
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
viteModified = true;
|
|
429
|
+
} else {
|
|
430
|
+
logStep("✓", c("dim", `${viteConfigName} already has @tailwindcss/vite`));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// 2b. Add path import + resolve.alias for @
|
|
434
|
+
if (
|
|
435
|
+
!viteContent.includes("node:path") &&
|
|
436
|
+
!viteContent.match(/import\s+path\s+from\s+["']path["']/)
|
|
437
|
+
) {
|
|
438
|
+
const pathImport = 'import path from "node:path";\n';
|
|
439
|
+
const importMatch = viteContent.match(/^(import\s.+\n)+/m);
|
|
440
|
+
if (importMatch) {
|
|
441
|
+
const lastImportEnd = importMatch.index + importMatch[0].length;
|
|
442
|
+
viteContent =
|
|
443
|
+
viteContent.slice(0, lastImportEnd) +
|
|
444
|
+
pathImport +
|
|
445
|
+
viteContent.slice(lastImportEnd);
|
|
446
|
+
} else {
|
|
447
|
+
viteContent = pathImport + viteContent;
|
|
448
|
+
}
|
|
449
|
+
viteModified = true;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (
|
|
453
|
+
!viteContent.includes("resolve:") &&
|
|
454
|
+
!viteContent.includes("resolve.alias")
|
|
455
|
+
) {
|
|
456
|
+
// Add resolve.alias block before the closing of defineConfig
|
|
457
|
+
const resolveBlock = ` resolve: {\n alias: {\n "@": path.resolve(__dirname, "src"),\n },\n },`;
|
|
458
|
+
if (viteContent.includes("plugins:")) {
|
|
459
|
+
// Insert after plugins block — find the plugins array closing and add after
|
|
460
|
+
viteContent = viteContent.replace(
|
|
461
|
+
/(plugins:\s*\[[\s\S]*?\],?\n)/m,
|
|
462
|
+
`$1${resolveBlock}\n`,
|
|
463
|
+
);
|
|
464
|
+
} else if (viteContent.includes("defineConfig({")) {
|
|
465
|
+
viteContent = viteContent.replace(
|
|
466
|
+
/defineConfig\(\{/,
|
|
467
|
+
`defineConfig({\n${resolveBlock}`,
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
viteModified = true;
|
|
471
|
+
} else {
|
|
472
|
+
logStep("✓", c("dim", `${viteConfigName} already has resolve.alias`));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (viteModified) {
|
|
476
|
+
writeFileSync(viteConfigPath, viteContent);
|
|
477
|
+
logStep(
|
|
478
|
+
"✓",
|
|
479
|
+
`Patched ${c("cyan", viteConfigName)} with Tailwind CSS plugin + @ alias`,
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// 2c. Patch tsconfig to add @/* path alias
|
|
484
|
+
const tsconfigCandidates = ["tsconfig.app.json", "tsconfig.json"];
|
|
485
|
+
for (const tscName of tsconfigCandidates) {
|
|
486
|
+
const tscPath = join(root, tscName);
|
|
487
|
+
if (!existsSync(tscPath)) continue;
|
|
488
|
+
const tscContent = readFileSync(tscPath, "utf-8");
|
|
489
|
+
if (tscContent.includes('"@/*"')) {
|
|
490
|
+
logStep("✓", c("dim", `${tscName} already has @/* path alias`));
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
// Strip comments for JSON parsing (single-line // comments)
|
|
495
|
+
const stripped = tscContent.replace(/^\s*\/\/.*$/gm, "");
|
|
496
|
+
const tsconfig = JSON.parse(stripped);
|
|
497
|
+
if (!tsconfig.compilerOptions) tsconfig.compilerOptions = {};
|
|
498
|
+
if (!tsconfig.compilerOptions.paths) tsconfig.compilerOptions.paths = {};
|
|
499
|
+
tsconfig.compilerOptions.paths["@/*"] = ["./src/*"];
|
|
500
|
+
// Also ensure baseUrl is set for paths to work
|
|
501
|
+
if (!tsconfig.compilerOptions.baseUrl) {
|
|
502
|
+
tsconfig.compilerOptions.baseUrl = ".";
|
|
503
|
+
}
|
|
504
|
+
writeFileSync(tscPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
505
|
+
logStep("✓", `Patched ${c("cyan", tscName)} with @/* path alias`);
|
|
506
|
+
} catch {
|
|
507
|
+
logStep(
|
|
508
|
+
"⚠",
|
|
509
|
+
c("yellow", `Could not patch ${tscName} — add @/* path alias manually`),
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// 3. Patch CSS entry file
|
|
516
|
+
const srcDir = join(root, config.srcDir);
|
|
517
|
+
const cssCandidates = [
|
|
518
|
+
"index.css",
|
|
519
|
+
"App.css",
|
|
520
|
+
"style.css",
|
|
521
|
+
"main.css",
|
|
522
|
+
"globals.css",
|
|
523
|
+
];
|
|
524
|
+
let cssPath = null;
|
|
525
|
+
for (const name of cssCandidates) {
|
|
526
|
+
const candidate = join(srcDir, name);
|
|
527
|
+
if (existsSync(candidate)) {
|
|
528
|
+
cssPath = candidate;
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (!cssPath) {
|
|
533
|
+
// Create src/index.css if no CSS file found
|
|
534
|
+
cssPath = join(srcDir, "index.css");
|
|
535
|
+
}
|
|
536
|
+
const tailwindDirective = '@import "tailwindcss";';
|
|
537
|
+
const unifiedUiImport = '@import "@/styles/unified-ui.css";';
|
|
538
|
+
if (existsSync(cssPath)) {
|
|
539
|
+
let cssContent = readFileSync(cssPath, "utf-8");
|
|
540
|
+
let modified = false;
|
|
541
|
+
if (!cssContent.includes(tailwindDirective)) {
|
|
542
|
+
cssContent = `${tailwindDirective}\n${cssContent}`;
|
|
543
|
+
modified = true;
|
|
544
|
+
}
|
|
545
|
+
if (!cssContent.includes(unifiedUiImport)) {
|
|
546
|
+
// Insert right after the tailwindcss import
|
|
547
|
+
cssContent = cssContent.replace(
|
|
548
|
+
tailwindDirective,
|
|
549
|
+
`${tailwindDirective}\n${unifiedUiImport}`,
|
|
550
|
+
);
|
|
551
|
+
modified = true;
|
|
552
|
+
}
|
|
553
|
+
if (modified) {
|
|
554
|
+
writeFileSync(cssPath, cssContent);
|
|
555
|
+
logStep(
|
|
556
|
+
"✓",
|
|
557
|
+
`Updated ${c("cyan", cssPath.replace(`${root}/`, ""))} with Tailwind imports`,
|
|
558
|
+
);
|
|
559
|
+
} else {
|
|
560
|
+
logStep(
|
|
561
|
+
"✓",
|
|
562
|
+
c(
|
|
563
|
+
"dim",
|
|
564
|
+
`${cssPath.replace(`${root}/`, "")} already has Tailwind imports`,
|
|
565
|
+
),
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
} else {
|
|
569
|
+
const content = `${tailwindDirective}\n${unifiedUiImport}\n`;
|
|
570
|
+
mkdirSync(dirname(cssPath), { recursive: true });
|
|
571
|
+
writeFileSync(cssPath, content);
|
|
572
|
+
logStep(
|
|
573
|
+
"✓",
|
|
574
|
+
`Created ${c("cyan", cssPath.replace(`${root}/`, ""))} with Tailwind imports`,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
336
578
|
// ---------------------------------------------------------------------------
|
|
337
579
|
// File writer
|
|
338
580
|
// ---------------------------------------------------------------------------
|
|
@@ -1757,9 +1999,12 @@ async function cmdInit(positional = [], flags = {}) {
|
|
|
1757
1999
|
}
|
|
1758
2000
|
// Install base npm deps
|
|
1759
2001
|
await installNpmDeps(
|
|
1760
|
-
["class-variance-authority", "clsx", "tailwind-merge"],
|
|
2002
|
+
["class-variance-authority", "clsx", "tailwind-merge", "lucide-react"],
|
|
1761
2003
|
config.root,
|
|
1762
2004
|
);
|
|
2005
|
+
// Set up Tailwind CSS for Vite projects
|
|
2006
|
+
log();
|
|
2007
|
+
await setupTailwindForVite(config.root, config);
|
|
1763
2008
|
log();
|
|
1764
2009
|
logStep("🎉", c("green", "Project initialized! Start adding components:"));
|
|
1765
2010
|
log();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@work-rjkashyap/unified-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A scalable, token-driven React design system with 75+ components, built with Tailwind CSS v4, Radix UI, and Framer Motion.",
|
|
5
5
|
"author": "Rajeshwar Kashyap",
|
|
6
6
|
"license": "MIT",
|