vibe-design-system 2.8.54 → 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.54",
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 {
@@ -3509,6 +3523,7 @@ function main() {
3509
3523
  }
3510
3524
  }
3511
3525
 
3526
+ let writtenCount = 0;
3512
3527
  for (const comp of components) {
3513
3528
  const componentName = toSafeComponentName(comp.name, comp.file);
3514
3529
  // Skip unclassified and shadcn/ui primitives (UI group) — they're documented at ui.shadcn.com
@@ -3518,8 +3533,9 @@ function main() {
3518
3533
  // Users can override with vds.config.js: includeGroups: ["shadcn"] or includeComponents: ["Button", "Badge"]
3519
3534
  const includeGroups = VDS_CONFIG.includeGroups || [];
3520
3535
  const includeComponents = VDS_CONFIG.includeComponents || [];
3521
- if (g === "Uncategorized" || g === "UI" || g === "shadcn" || g === "ui") {
3522
- 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);
3523
3539
  const compIncluded = includeComponents.includes(componentName);
3524
3540
  if (!groupIncluded && !compIncluded) {
3525
3541
  // Clean up leftover story files for components that are now in the skip group
@@ -3542,7 +3558,10 @@ function main() {
3542
3558
  const storyPath = path.join(STORIES_DIR, storyFileName);
3543
3559
  if (SKIP_LIST.includes(componentName)) continue;
3544
3560
  const requiredCount = Array.isArray(comp.props) ? comp.props.filter((p) => p.required === true).length : 0;
3545
- 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
+ }
3546
3565
 
3547
3566
  // Never overwrite existing story files — only create new ones
3548
3567
  // To regenerate a story: delete the file and re-run VDS
@@ -3554,6 +3573,22 @@ function main() {
3554
3573
  if (content == null) continue;
3555
3574
  fs.writeFileSync(storyPath, content, "utf-8");
3556
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.`);
3557
3592
  }
3558
3593
  }
3559
3594