vibe-design-system 2.8.50 → 2.8.53

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.8.50",
3
+ "version": "2.8.53",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "homepage": "https://vibedesign.tech",
6
6
  "repository": {
@@ -1429,7 +1429,7 @@ function buildSpecialStories(componentName, variants) {
1429
1429
  return "";
1430
1430
  }
1431
1431
 
1432
- function buildRecipeStoryContent(comp, componentName, importPath, title, source, exportStyle, recipe, defaultArgLines = [], lucideImports = [], iconPropNames = [], needReact = false) {
1432
+ function buildRecipeStoryContent(comp, componentName, importPath, title, source, exportStyle, recipe, defaultArgLines = [], lucideImports = [], iconPropNames = [], needReact = false, variantMap = null) {
1433
1433
  const lines = [];
1434
1434
  lines.push(`// @vds-regenerate — VDS auto-generated. Remove this line to prevent overwrite.`);
1435
1435
  lines.push(`import type { Meta, StoryObj } from "@storybook/react";`);
@@ -1492,14 +1492,66 @@ function buildRecipeStoryContent(comp, componentName, importPath, title, source,
1492
1492
  lines.push(`export default meta;`);
1493
1493
  lines.push(`type Story = StoryObj<typeof meta>;`);
1494
1494
  lines.push("");
1495
- lines.push(`export const Default: Story = {`);
1496
- lines.push(` render: ${effectiveRecipe.render},`);
1497
- if (defaultArgLines.length > 0) {
1495
+ // --- Dimension-aware recipe stories ---
1496
+ const hasDims = variantMap && Object.keys(variantMap.dimensions).length > 0;
1497
+ if (hasDims) {
1498
+ const primaryDim = variantMap.primaryDimension || Object.keys(variantMap.dimensions)[0];
1499
+ const primaryInfo = variantMap.dimensions[primaryDim];
1500
+ const primaryValues = primaryInfo?.values || [];
1501
+ const primaryDefault = primaryInfo?.default || primaryValues[0];
1502
+
1503
+ // Default story (primary default variant)
1504
+ lines.push(`export const Default: Story = {`);
1505
+ lines.push(` render: ${effectiveRecipe.render},`);
1498
1506
  lines.push(` args: {`);
1507
+ lines.push(` ${primaryDim}: ${JSON.stringify(primaryDefault)},`);
1499
1508
  for (const line of defaultArgLines) lines.push(line);
1500
1509
  lines.push(` },`);
1510
+ lines.push(`};`);
1511
+
1512
+ // Per-variant stories for remaining primary values
1513
+ for (const val of primaryValues) {
1514
+ if (val === primaryDefault) continue;
1515
+ const storyName = val.charAt(0).toUpperCase() + val.slice(1);
1516
+ lines.push("");
1517
+ lines.push(`export const ${storyName}: Story = {`);
1518
+ lines.push(` render: ${effectiveRecipe.render},`);
1519
+ lines.push(` args: {`);
1520
+ lines.push(` ${primaryDim}: ${JSON.stringify(val)},`);
1521
+ for (const line of defaultArgLines) lines.push(line);
1522
+ lines.push(` },`);
1523
+ lines.push(`};`);
1524
+ }
1525
+
1526
+ // Secondary dimensions (e.g., size) — skip default value, one story per non-default
1527
+ const secondaryDims = Object.keys(variantMap.dimensions).filter(d => d !== primaryDim);
1528
+ for (const dim of secondaryDims) {
1529
+ const dimInfo = variantMap.dimensions[dim];
1530
+ const dimDefault = dimInfo?.default || dimInfo?.values?.[0];
1531
+ for (const val of dimInfo?.values || []) {
1532
+ if (val === dimDefault) continue;
1533
+ const storyName = `${dim.charAt(0).toUpperCase() + dim.slice(1)}${val.charAt(0).toUpperCase() + val.slice(1)}`;
1534
+ lines.push("");
1535
+ lines.push(`export const ${storyName}: Story = {`);
1536
+ lines.push(` render: ${effectiveRecipe.render},`);
1537
+ lines.push(` args: {`);
1538
+ lines.push(` ${dim}: ${JSON.stringify(val)},`);
1539
+ for (const line of defaultArgLines) lines.push(line);
1540
+ lines.push(` },`);
1541
+ lines.push(`};`);
1542
+ }
1543
+ }
1544
+ } else {
1545
+ // Original: single Default story
1546
+ lines.push(`export const Default: Story = {`);
1547
+ lines.push(` render: ${effectiveRecipe.render},`);
1548
+ if (defaultArgLines.length > 0) {
1549
+ lines.push(` args: {`);
1550
+ for (const line of defaultArgLines) lines.push(line);
1551
+ lines.push(` },`);
1552
+ }
1553
+ lines.push(`};`);
1501
1554
  }
1502
- lines.push(`};`);
1503
1555
  return lines.join("\n");
1504
1556
  }
1505
1557
 
@@ -1603,7 +1655,15 @@ function buildProfileRenderLine(profile, RenderTarget, argsFallback) {
1603
1655
  )},`;
1604
1656
  case "SAFE":
1605
1657
  return ` render: (args = {}) => ${suspense(`React.createElement(${RenderTarget}, args)`)},`;
1606
- default: { // CONFIGURED, VARIANT
1658
+ case "VARIANT": {
1659
+ // Wrap in inline-block div to prevent vertical stretching caused by
1660
+ // global SidebarProvider/flex decorators or layout: "fullscreen" in preview.
1661
+ const argsParam = argsFallback ? "(args = {})" : "(args)";
1662
+ const propsArg = argsFallback ? `{ ...args${argsFallback} }` : "args";
1663
+ const inner = suspense(`React.createElement(${RenderTarget}, ${propsArg})`);
1664
+ return ` render: ${argsParam} => React.createElement('div', { style: { display: 'inline-block' } }, ${inner}),`;
1665
+ }
1666
+ default: { // CONFIGURED
1607
1667
  const argsParam = argsFallback ? "(args = {})" : "(args)";
1608
1668
  const propsArg = argsFallback ? `{ ...args${argsFallback} }` : "args";
1609
1669
  return ` render: ${argsParam} => ${suspense(`React.createElement(${RenderTarget}, ${propsArg})`)},`;
@@ -1693,7 +1753,7 @@ function buildStoryFileContent(comp) {
1693
1753
  }
1694
1754
 
1695
1755
  if (RECIPES[componentName]) {
1696
- return buildRecipeStoryContent(comp, componentName, importPath, title, source, exportStyle, RECIPES[componentName], defaultArgLines, lucideImports, iconPropNames, needReact);
1756
+ return buildRecipeStoryContent(comp, componentName, importPath, title, source, exportStyle, RECIPES[componentName], defaultArgLines, lucideImports, iconPropNames, needReact, variantMap);
1697
1757
  }
1698
1758
 
1699
1759
  const lines = [];
@@ -1750,10 +1810,13 @@ function buildStoryFileContent(comp) {
1750
1810
  lines.push(`type Story = StoryObj<typeof meta>;`);
1751
1811
  lines.push("");
1752
1812
 
1813
+ // Multi-dimension story generation: variant × size × disabled × AllVariants grid
1814
+ const hasDimensions = Object.keys(variantMap.dimensions).length > 0 || variantMap.booleanStates.length > 0;
1815
+
1753
1816
  // Component-specific stories for non-variant components (Input, Textarea, etc.)
1754
- // Button and Badge are now handled generically by multi-dimension detection.
1755
- const skipSpecialFor = new Set(["Button", "Badge"]);
1756
- if (!skipSpecialFor.has(componentName)) {
1817
+ // Skip buildSpecialStories when multi-dimension detection found CVA dimensions
1818
+ // generic detection produces better stories than hardcoded ones.
1819
+ if (!hasDimensions) {
1757
1820
  const specialStories = buildSpecialStories(componentName, variants);
1758
1821
  if (specialStories) {
1759
1822
  lines.push(specialStories);
@@ -1768,9 +1831,6 @@ function buildStoryFileContent(comp) {
1768
1831
  const renderLine = buildProfileRenderLine(profile, RenderTarget, argsFallback);
1769
1832
  const childrenArgLine = buildProfileChildrenArgLine(profile);
1770
1833
 
1771
- // Multi-dimension story generation: variant × size × disabled × AllVariants grid
1772
- const hasDimensions = Object.keys(variantMap.dimensions).length > 0 || variantMap.booleanStates.length > 0;
1773
-
1774
1834
  if (hasDimensions) {
1775
1835
  const multiStories = buildMultiDimensionStories(
1776
1836
  variantMap, renderLine, childrenArgLine, defaultArgLines, componentName
@@ -1796,6 +1856,96 @@ function buildStoryFileContent(comp) {
1796
1856
  return lines.join("\n");
1797
1857
  }
1798
1858
 
1859
+ /**
1860
+ * Fallback grid system scanner — reads source files for Tailwind grid patterns
1861
+ * when scan.mjs didn't produce gridSystem data.
1862
+ */
1863
+ function scanGridSystemFallback() {
1864
+ const srcDirs = [
1865
+ path.join(PROJECT_ROOT, "src"),
1866
+ path.join(PROJECT_ROOT, "client/src"),
1867
+ path.join(PROJECT_ROOT, "app"),
1868
+ ];
1869
+ const breakpoints = {}; // { "md": { count, topFiles: [] }, ... }
1870
+ const gridCols = {}; // { "2": { count }, "3": { count }, ... }
1871
+ const gaps = {}; // { "4": { count }, "6": { count }, ... }
1872
+ const maxWidths = {}; // { "7xl": count, ... }
1873
+ let containerCount = 0;
1874
+
1875
+ const BP_NAMES = ["sm", "md", "lg", "xl", "2xl"];
1876
+ const bpRe = /\b(sm|md|lg|xl|2xl):/g;
1877
+ const colRe = /\bgrid-cols-(\w+)/g;
1878
+ const gapRe = /\bgap-(\w+)/g;
1879
+ const maxWRe = /\bmax-w-(\w+)/g;
1880
+ const containerRe = /\bcontainer\b/g;
1881
+
1882
+ function walkFiles(dir) {
1883
+ if (!fs.existsSync(dir)) return;
1884
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
1885
+ for (const entry of entries) {
1886
+ const full = path.join(dir, entry.name);
1887
+ if (entry.isDirectory()) {
1888
+ if (["node_modules", ".next", "dist", "build", ".storybook", "stories"].includes(entry.name)) continue;
1889
+ walkFiles(full);
1890
+ } else if (/\.(tsx|jsx|ts|js|css)$/.test(entry.name)) {
1891
+ try {
1892
+ const content = fs.readFileSync(full, "utf-8");
1893
+ const relFile = path.relative(PROJECT_ROOT, full).replace(/^(client\/)?src\//, "");
1894
+ const shortName = path.basename(relFile, path.extname(relFile));
1895
+
1896
+ // Breakpoints
1897
+ let m;
1898
+ while ((m = bpRe.exec(content)) !== null) {
1899
+ const bp = m[1];
1900
+ if (!breakpoints[bp]) breakpoints[bp] = { count: 0, topFiles: [] };
1901
+ breakpoints[bp].count++;
1902
+ if (!breakpoints[bp].topFiles.includes(shortName) && breakpoints[bp].topFiles.length < 5) {
1903
+ breakpoints[bp].topFiles.push(shortName);
1904
+ }
1905
+ }
1906
+
1907
+ // Grid columns
1908
+ while ((m = colRe.exec(content)) !== null) {
1909
+ const col = m[1];
1910
+ if (!gridCols[col]) gridCols[col] = { count: 0, topFiles: [] };
1911
+ gridCols[col].count++;
1912
+ if (!gridCols[col].topFiles.includes(shortName) && gridCols[col].topFiles.length < 5) {
1913
+ gridCols[col].topFiles.push(shortName);
1914
+ }
1915
+ }
1916
+
1917
+ // Gaps
1918
+ while ((m = gapRe.exec(content)) !== null) {
1919
+ const gap = m[1];
1920
+ if (!gaps[gap]) gaps[gap] = { count: 0, topFiles: [] };
1921
+ gaps[gap].count++;
1922
+ if (!gaps[gap].topFiles.includes(shortName) && gaps[gap].topFiles.length < 5) {
1923
+ gaps[gap].topFiles.push(shortName);
1924
+ }
1925
+ }
1926
+
1927
+ // Max widths
1928
+ while ((m = maxWRe.exec(content)) !== null) {
1929
+ const mw = m[1];
1930
+ if (!maxWidths[mw]) maxWidths[mw] = 0;
1931
+ maxWidths[mw]++;
1932
+ }
1933
+
1934
+ // Container
1935
+ const cMatches = content.match(containerRe);
1936
+ if (cMatches) containerCount += cMatches.length;
1937
+
1938
+ } catch { /* skip unreadable files */ }
1939
+ }
1940
+ }
1941
+ }
1942
+
1943
+ for (const dir of srcDirs) walkFiles(dir);
1944
+
1945
+ if (Object.keys(breakpoints).length === 0 && Object.keys(gridCols).length === 0) return null;
1946
+ return { breakpoints, gridCols, gaps, maxWidths, containerCount };
1947
+ }
1948
+
1799
1949
  function writeFoundationsStories(foundations) {
1800
1950
  const foundationsDir = path.join(STORIES_DIR, "foundations");
1801
1951
  ensureDir(foundationsDir);
@@ -2275,7 +2425,11 @@ function writeFoundationsStories(foundations) {
2275
2425
  console.log("[VDS] Wrote " + path.relative(PROJECT_ROOT, path.join(foundationsDir, "Icons.stories.tsx")));
2276
2426
  }
2277
2427
 
2278
- const gridSystem = foundations?.gridSystem;
2428
+ // Fallback: if scan.mjs didn't produce gridSystem data, scan source files directly
2429
+ let gridSystem = foundations?.gridSystem || null;
2430
+ if (!gridSystem || (Object.keys(gridSystem.breakpoints || {}).length === 0 && Object.keys(gridSystem.gridCols || {}).length === 0)) {
2431
+ gridSystem = scanGridSystemFallback();
2432
+ }
2279
2433
  if (gridSystem && (Object.keys(gridSystem.breakpoints || {}).length > 0 || Object.keys(gridSystem.gridCols || {}).length > 0)) {
2280
2434
  const bpEntries = Object.entries(gridSystem.breakpoints || {});
2281
2435
  const colEntries = Object.entries(gridSystem.gridCols || {});