vibe-design-system 2.5.29 → 2.5.30

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.5.29",
3
+ "version": "2.5.30",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -105,7 +105,28 @@ function getPreviewPath(projectRoot) {
105
105
  return null;
106
106
  }
107
107
 
108
- /** Collect all hooks used in project; return { providersToAdd: [{ name, importPath }], hooksWithoutProvider: Set, hooksByFile: Map } */
108
+ /** Detect if project uses react-dnd (useDrag, useDrop, or import from react-dnd). */
109
+ function detectReactDnd(projectRoot) {
110
+ const srcDir = path.join(projectRoot, "src");
111
+ const files = getAllSourceFiles(srcDir, srcDir).map((r) => path.join(projectRoot, "src", r));
112
+ for (const full of files) {
113
+ try {
114
+ const content = fs.readFileSync(full, "utf-8");
115
+ if (/\b(useDrag|useDrop|DndProvider)\b/.test(content) || /from\s+["']react-dnd["']/.test(content)) {
116
+ const pkgPath = path.join(projectRoot, "package.json");
117
+ if (fs.existsSync(pkgPath)) {
118
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
119
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
120
+ if (deps["react-dnd"]) return true;
121
+ }
122
+ return true;
123
+ }
124
+ } catch (_) {}
125
+ }
126
+ return false;
127
+ }
128
+
129
+ /** Collect all hooks used in project; return { providersToAdd: [{ name, importPath, props? }], ... } */
109
130
  function collectProvidersAndWarnings(projectRoot) {
110
131
  const hooksByFile = detectHooksUsedInProject(projectRoot);
111
132
  const allHooksUsed = new Set();
@@ -125,15 +146,25 @@ function collectProvidersAndWarnings(projectRoot) {
125
146
  hooksWithoutProvider.add(hook);
126
147
  }
127
148
  }
149
+ if (detectReactDnd(projectRoot) && !providersToAdd.some((p) => p.name === "DndProvider")) {
150
+ providersToAdd.unshift({
151
+ name: "DndProvider",
152
+ importPath: "react-dnd",
153
+ props: "{ backend: HTML5Backend }",
154
+ extraImport: { name: "HTML5Backend", from: "react-dnd-html5-backend" },
155
+ });
156
+ }
128
157
  return { providersToAdd, hooksWithoutProvider, hooksByFile };
129
158
  }
130
159
 
131
- /** Build withProviders decorator using React.createElement (no JSX so preview can stay .ts) */
160
+ /** Build withProviders decorator using React.createElement (no JSX so preview can stay .ts). Supports provider.props. */
132
161
  function buildWithProvidersCode(providers) {
133
162
  if (providers.length === 0) return null;
134
163
  let inner = "React.createElement(Story)";
135
164
  for (let i = providers.length - 1; i >= 0; i--) {
136
- inner = `React.createElement(${providers[i].name}, null, ${inner})`;
165
+ const p = providers[i];
166
+ const propsArg = p.props ? p.props : "null";
167
+ inner = `React.createElement(${p.name}, ${propsArg}, ${inner})`;
137
168
  }
138
169
  return `const withProviders = (Story: any) => ${inner};`;
139
170
  }
@@ -160,7 +191,11 @@ function injectProviderDecorators(projectRoot) {
160
191
  if (!content.includes(p.name)) {
161
192
  const lastImportIdx = content.search(/\nimport\s+.+?;\s*$/m);
162
193
  const insertAt = lastImportIdx >= 0 ? content.indexOf("\n", lastImportIdx) + 1 : content.indexOf("\n") + 1;
163
- content = content.slice(0, insertAt) + `import { ${p.name} } from "${p.importPath}";\n` + content.slice(insertAt);
194
+ let importLine = `import { ${p.name} } from "${p.importPath}";\n`;
195
+ if (p.extraImport && !content.includes(p.extraImport.name)) {
196
+ importLine += `import { ${p.extraImport.name} } from "${p.extraImport.from}";\n`;
197
+ }
198
+ content = content.slice(0, insertAt) + importLine + content.slice(insertAt);
164
199
  }
165
200
  }
166
201
  content = content.replace(/const withProviders\s*=\s*\([^)]*\)\s*=>\s*[\s\S]+?;\s*\n?/g, "").replace(/\n{3,}/g, "\n\n");
@@ -652,6 +652,24 @@ function buildDefaultArgsForRequiredProps(props, usageFromPages = null, componen
652
652
  } else if (/string/.test(type)) {
653
653
  argLines.push(` ${name}: ${stringFallback(name)},`);
654
654
  added.add(name);
655
+ } else if (/number/.test(type) || /^(value|amount|total|count|hours|minutes|progress|percent)$/.test(name)) {
656
+ argLines.push(` ${name}: 0,`);
657
+ added.add(name);
658
+ }
659
+ }
660
+ // Optional props that often cause "reading X of undefined" in Storybook if missing
661
+ const NUMBER_LIKE_OPTIONAL = new Set(["value", "amount", "total", "count", "hours", "minutes", "progress", "percent", "visibility"]);
662
+ const DATE_RANGE_DEFAULT = `{ dateRange: { from: new Date().toISOString(), to: new Date().toISOString() } }`;
663
+ for (const p of props) {
664
+ const type = String(p.type || "").trim();
665
+ const name = p.name;
666
+ if (added.has(name)) continue;
667
+ if (name === "filters" || /dateRange|Filter.*object/.test(type)) {
668
+ argLines.push(` ${name}: ${DATE_RANGE_DEFAULT},`);
669
+ added.add(name);
670
+ } else if (/number/.test(type) || NUMBER_LIKE_OPTIONAL.has(name)) {
671
+ argLines.push(` ${name}: ${name === "visibility" ? "1" : "0"},`);
672
+ added.add(name);
655
673
  }
656
674
  }
657
675
  }