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 +11 -3
- package/package.json +1 -1
- package/vds-core-template/story-generator.mjs +55 -20
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
|
@@ -425,13 +425,21 @@ function componentWrapsVoidElement(source) {
|
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
function toSafeComponentName(name, file) {
|
|
428
|
-
|
|
429
|
-
|
|
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
|
|
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
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
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
|
-
|
|
3522
|
-
|
|
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)
|
|
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
|
|