vibe-design-system 2.8.53 → 2.8.56

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/bin/init.js CHANGED
@@ -606,9 +606,17 @@ function runStorybookAdapt(projectRoot) {
606
606
  }
607
607
 
608
608
  // ADIM 9b — vds.config.js oluştur (yoksa)
609
- function ensureVdsConfig(projectRoot) {
609
+ function ensureVdsConfig(projectRoot, srcPrefix) {
610
610
  const configPath = path.join(projectRoot, "vds.config.js");
611
611
  if (fs.existsSync(configPath)) return;
612
+
613
+ // Detect shadcn/ui: if components/ui/ directory exists, add includeGroups by default
614
+ const uiDir = path.join(projectRoot, srcPrefix || "src", "components", "ui");
615
+ const hasShadcn = fs.existsSync(uiDir);
616
+ const includeGroupsLine = hasShadcn
617
+ ? ` includeGroups: ["shadcn", "UI", "ui"], // Auto-detected shadcn/ui: generate stories for UI components\n`
618
+ : ` // includeGroups: ["shadcn", "UI"], // Uncomment to generate stories for shadcn/ui primitives\n`;
619
+
612
620
  const content = `/**
613
621
  * VDS Configuration — auto-created by VDS installer
614
622
  * All fields are optional. Remove comments to activate overrides.
@@ -617,7 +625,7 @@ module.exports = {
617
625
  // skipList: ["MyHeavyPage"], // Replace the default story skip list entirely
618
626
  // extraSkipList: ["OrderCard"], // Add to the default skip list
619
627
  // extraIgnoreDirs: ["fixtures"], // Additional dirs to skip during component scan
620
- };
628
+ ${includeGroupsLine}};
621
629
  `;
622
630
  fs.writeFileSync(configPath, content, "utf-8");
623
631
  console.log("⚙️ vds.config.js oluşturuldu.");
@@ -697,7 +705,7 @@ ensureStoriesDir(projectRoot, srcPrefix);
697
705
  removeStorybookExamples(projectRoot, srcPrefix);
698
706
 
699
707
  // ADIM 9b
700
- ensureVdsConfig(projectRoot);
708
+ ensureVdsConfig(projectRoot, srcPrefix);
701
709
 
702
710
  // ADIM 7
703
711
  runScan(projectRoot);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.8.53",
3
+ "version": "2.8.56",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "homepage": "https://vibedesign.tech",
6
6
  "repository": {
@@ -425,13 +425,21 @@ function componentWrapsVoidElement(source) {
425
425
  }
426
426
 
427
427
  function toSafeComponentName(name, file) {
428
- if (name && typeof name === "string") {
429
- return name.replace(/[^A-Za-z0-9]+/g, " ").trim().replace(/\s+([a-z])/g, (_, c) => c.toUpperCase()).replace(/^\w/, (c) => c.toUpperCase()).replace(/\s+/g, "");
430
- }
428
+ // Convert any string (spaces, hyphens, underscores) to PascalCase.
429
+ // If no separators present, treat as already-PascalCase and just capitalise the first letter.
430
+ const toPascal = (s) => {
431
+ if (!s) return "Component";
432
+ if (!/[-\s_]/.test(s)) return s.charAt(0).toUpperCase() + s.slice(1); // already camel/PascalCase
433
+ return s.replace(/[^A-Za-z0-9]+/g, " ").trim()
434
+ .split(" ").filter(Boolean)
435
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
436
+ .join("") || "Component";
437
+ };
438
+ if (name && typeof name === "string") return toPascal(name);
431
439
  const base = (file || "").replace(/\.[^.]+$/, "");
432
440
  const parts = base.split(/[\\/]/g);
433
441
  const last = parts[parts.length - 1] || "Component";
434
- return last.charAt(0).toUpperCase() + last.slice(1);
442
+ return toPascal(last);
435
443
  }
436
444
 
437
445
  function parseUnionLiterals(type) {
@@ -1686,16 +1694,26 @@ function buildProfileChildrenArgLine(profile) {
1686
1694
 
1687
1695
  function buildStoryFileContent(comp) {
1688
1696
  const componentName = toSafeComponentName(comp.name, comp.file);
1689
- const fileNoExt = comp.file.replace(/\.(tsx|jsx)$/, "");
1690
- // Compute import path relative to src/stories/ using the actual components directory.
1691
- let importPath = "";
1692
- const isPageFile = fileNoExt.startsWith("pages/") || fileNoExt.startsWith("src/pages/");
1693
- if (isPageFile) {
1694
- // Keep full path with src/ prefix so relative is computed correctly from src/stories/
1695
- // e.g. "src/pages/Admin" → "../pages/Admin" (NOT "../../pages/Admin")
1696
- const fullPath = fileNoExt.startsWith("src/") ? fileNoExt : "src/" + fileNoExt;
1697
- importPath = path.posix.relative("src/stories", fullPath);
1697
+ const fileNoExt = comp.file.replace(/\.(tsx|jsx|ts|js)$/, "");
1698
+
1699
+ // Determine if comp.file is project-root-relative (e.g. "client/src/pages/Foo.tsx")
1700
+ // or components-dir-relative (e.g. "ui/badge.tsx").
1701
+ // Try project-root first; fall back to components-dir.
1702
+ const absoluteFromRoot = path.join(PROJECT_ROOT, comp.file);
1703
+ const absoluteFromComponents = path.join(PROJECT_ROOT, COMPONENTS_REL_DIR, comp.file);
1704
+ const isProjectRelative = fs.existsSync(absoluteFromRoot);
1705
+ const srcPath = isProjectRelative ? absoluteFromRoot : absoluteFromComponents;
1706
+
1707
+ // isPageFile: detect components that live inside a pages/ directory
1708
+ const isPageFile = fileNoExt.includes("/pages/") || fileNoExt.startsWith("pages/");
1709
+
1710
+ // Compute import path relative to src/stories/
1711
+ let importPath;
1712
+ if (isProjectRelative) {
1713
+ // File path is already relative to project root — use directly
1714
+ importPath = path.posix.relative("src/stories", fileNoExt);
1698
1715
  } else {
1716
+ // File path is relative to components dir — prefix with components dir
1699
1717
  const targetPath = path.posix.join(COMPONENTS_REL_DIR, fileNoExt);
1700
1718
  importPath = path.posix.relative("src/stories", targetPath);
1701
1719
  }
@@ -1709,10 +1727,6 @@ function buildStoryFileContent(comp) {
1709
1727
  // Title: "Module/ComponentName" (category intentionally dropped — folder is the context)
1710
1728
  const title = `${group}/${componentName}`;
1711
1729
 
1712
- const srcPath = isPageFile
1713
- ? path.join(PROJECT_ROOT, fileNoExt.replace(/^src\//, "src/") + ".tsx")
1714
- : path.join(PROJECT_ROOT, COMPONENTS_REL_DIR, comp.file);
1715
-
1716
1730
  // Read component source once (used for export style, props, CVA parsing)
1717
1731
  let source = "";
1718
1732
  try {
@@ -2577,11 +2591,11 @@ function writeFoundationsStories(foundations) {
2577
2591
  " </p>",
2578
2592
  " <p style={{ margin: \"0 0 12px\", fontSize: 12, color: \"#475569\" }}>gap-* values across all components.</p>",
2579
2593
  " <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>",
2580
- " {(gapEntries as [string, number][]).map(([val, count]) => (",
2594
+ " {(gapEntries as [string, { count: number; topFiles: string[] }][]).map(([val, data]) => (",
2581
2595
  " <span key={val} style={{ display: \"flex\", alignItems: \"center\", gap: 6,",
2582
2596
  " background: \"#0a0f1a\", border: \"1px solid #1e293b\", borderRadius: 6, padding: \"5px 10px\", fontSize: 12 }}>",
2583
2597
  " <code style={{ color: \"#67e8f9\" }}>gap-{val}</code>",
2584
- " <span style={{ color: \"#475569\", fontSize: 11 }}>×{count}</span>",
2598
+ " <span style={{ color: \"#475569\", fontSize: 11 }}>×{data.count}</span>",
2585
2599
  " </span>",
2586
2600
  " ))}",
2587
2601
  " </div>",
@@ -3383,9 +3397,12 @@ function writeCursorRules(components, foundations) {
3383
3397
  const gridSystem = foundations?.gridSystem;
3384
3398
  if (gridSystem) {
3385
3399
  lines.push(`## 📐 Spacing & Layout (detected in this project)`);
3386
- if (Object.keys(gaps).length > 0) {
3387
- const gapLine = Object.entries(gaps).sort((a,b)=>b[1]-a[1]).slice(0,8)
3388
- .map(([v, c]) => `\`gap-${v}\` ×${c}`).join(" · ");
3400
+ const _gaps = gridSystem.gaps || {};
3401
+ if (Object.keys(_gaps).length > 0) {
3402
+ const gapLine = Object.entries(_gaps)
3403
+ .sort((a,b) => (typeof b[1] === "object" ? b[1].count : b[1]) - (typeof a[1] === "object" ? a[1].count : a[1]))
3404
+ .slice(0,8)
3405
+ .map(([v, d]) => `\`gap-${v}\` ×${typeof d === "object" ? d.count : d}`).join(" · ");
3389
3406
  lines.push(`**Common gaps:** ${gapLine}`);
3390
3407
  }
3391
3408
  if (Object.keys(gridSystem.gridCols || {}).length > 0) {
@@ -3506,6 +3523,7 @@ function main() {
3506
3523
  }
3507
3524
  }
3508
3525
 
3526
+ let writtenCount = 0;
3509
3527
  for (const comp of components) {
3510
3528
  const componentName = toSafeComponentName(comp.name, comp.file);
3511
3529
  // Skip unclassified and shadcn/ui primitives (UI group) — they're documented at ui.shadcn.com
@@ -3515,8 +3533,9 @@ function main() {
3515
3533
  // Users can override with vds.config.js: includeGroups: ["shadcn"] or includeComponents: ["Button", "Badge"]
3516
3534
  const includeGroups = VDS_CONFIG.includeGroups || [];
3517
3535
  const includeComponents = VDS_CONFIG.includeComponents || [];
3518
- if (g === "Uncategorized" || g === "UI" || g === "shadcn" || g === "ui") {
3519
- const groupIncluded = includeGroups.some((ig) => ig.toLowerCase() === g.toLowerCase());
3536
+ const gLower = g.toLowerCase();
3537
+ if (g === "Uncategorized" || gLower === "ui" || gLower === "shadcn") {
3538
+ const groupIncluded = includeGroups.some((ig) => ig.toLowerCase() === gLower);
3520
3539
  const compIncluded = includeComponents.includes(componentName);
3521
3540
  if (!groupIncluded && !compIncluded) {
3522
3541
  // Clean up leftover story files for components that are now in the skip group
@@ -3539,7 +3558,10 @@ function main() {
3539
3558
  const storyPath = path.join(STORIES_DIR, storyFileName);
3540
3559
  if (SKIP_LIST.includes(componentName)) continue;
3541
3560
  const requiredCount = Array.isArray(comp.props) ? comp.props.filter((p) => p.required === true).length : 0;
3542
- if (requiredCount > 3) continue;
3561
+ if (requiredCount > 3) {
3562
+ console.log(`[VDS] ${componentName} → skipped (${requiredCount} required props — too complex to auto-generate)`);
3563
+ continue;
3564
+ }
3543
3565
 
3544
3566
  // Never overwrite existing story files — only create new ones
3545
3567
  // To regenerate a story: delete the file and re-run VDS
@@ -3551,6 +3573,22 @@ function main() {
3551
3573
  if (content == null) continue;
3552
3574
  fs.writeFileSync(storyPath, content, "utf-8");
3553
3575
  console.log(`[VDS] Wrote ${path.relative(PROJECT_ROOT, storyPath)}`);
3576
+ writtenCount++;
3577
+ }
3578
+
3579
+ // Summary
3580
+ if (writtenCount === 0 && components.length > 0) {
3581
+ const hasShadcnGroup = components.some(c => {
3582
+ const gr = (c.group || "").toLowerCase();
3583
+ return gr === "shadcn" || gr === "ui";
3584
+ });
3585
+ console.log("[VDS] ⚠️ No new component stories were generated.");
3586
+ if (hasShadcnGroup && (VDS_CONFIG.includeGroups || []).length === 0) {
3587
+ console.log("[VDS] Tip: shadcn/ui components detected. Add to vds.config.js:");
3588
+ console.log('[VDS] includeGroups: ["shadcn", "UI"]');
3589
+ }
3590
+ } else if (writtenCount > 0) {
3591
+ console.log(`[VDS] ✓ Generated ${writtenCount} new component stories.`);
3554
3592
  }
3555
3593
  }
3556
3594