vibe-design-system 2.8.32 → 2.8.34

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.32",
3
+ "version": "2.8.34",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "homepage": "https://vibedesign.tech",
6
6
  "repository": {
@@ -385,6 +385,10 @@ function classifyByPath(rel) {
385
385
  // ui/ → always "UI" (shadcn primitives)
386
386
  if (firstSegment === "ui") return { group: "UI", category: null };
387
387
 
388
+ // Root-level file (no subdirectory): firstSegment is a filename like "NavLink.tsx"
389
+ // Use "Components" instead of the filename as the group
390
+ if (firstSegment.includes(".")) return { group: "Components", category: null };
391
+
388
392
  // Convert kebab-case folder to Title Case (time-resources → Time Resources)
389
393
  const group = firstSegment
390
394
  .split("-")
@@ -974,7 +974,13 @@ function getExampleItemForArrayType(itemType) {
974
974
 
975
975
  function capitalize(str) {
976
976
  if (!str) return "";
977
- return str.charAt(0).toUpperCase() + str.slice(1);
977
+ // Convert to valid JS identifier: remove invalid chars, camelCase hyphens, prefix digit-starts
978
+ const safe = str
979
+ .replace(/[:\s]+([a-z])/g, (_, c) => c.toUpperCase()) // sm:full → smFull
980
+ .replace(/-+([a-zA-Z0-9])/g, (_, c) => c.toUpperCase()) // outline-ghost → outlineGhost
981
+ .replace(/[^a-zA-Z0-9_$]/g, "") // strip remaining invalid chars
982
+ .replace(/^([0-9])/, "_$1"); // 2xl → _2xl
983
+ return safe.charAt(0).toUpperCase() + safe.slice(1);
978
984
  }
979
985
 
980
986
  function detectExportStyle(source, componentName) {
@@ -1304,9 +1310,11 @@ function buildStoryFileContent(comp) {
1304
1310
  }
1305
1311
  if (!importPath.startsWith(".")) importPath = "./" + importPath;
1306
1312
 
1307
- // Normalize legacy "shadcn" group → "UI", everything else kept as-is
1313
+ // Normalize legacy "shadcn" group → "UI"; filename groups (e.g. "NavLink.tsx") → "Components"
1308
1314
  const rawGroup = comp.group || "Components";
1309
- const group = rawGroup === "shadcn" ? "UI" : rawGroup;
1315
+ const group = rawGroup === "shadcn" ? "UI"
1316
+ : rawGroup.includes(".") ? "Components" // root-level file without subdirectory
1317
+ : rawGroup;
1310
1318
  // Title: "Module/ComponentName" (category intentionally dropped — folder is the context)
1311
1319
  const title = `${group}/${componentName}`;
1312
1320
 
@@ -1400,7 +1408,8 @@ function buildStoryFileContent(comp) {
1400
1408
  lines.push(`const meta = {`);
1401
1409
  lines.push(` title: ${JSON.stringify(title)},`);
1402
1410
  lines.push(` component: ComponentRef,`);
1403
- lines.push(` tags: ["autodocs"],`);
1411
+ // SECTION: no props/args → autodocs tries to render React.lazy without Suspense → useRef crash
1412
+ if (profile !== "SECTION") lines.push(` tags: ["autodocs"],`);
1404
1413
 
1405
1414
  // Build argTypes from extracted TypeScript props + icon-specific overrides
1406
1415
  const argTypeEntries = [];
@@ -204,12 +204,33 @@ function injectAliases(projectRoot, specifiers) {
204
204
  }
205
205
  }
206
206
 
207
+ /** Inject resolve.dedupe into .storybook/main.* viteFinal to prevent multiple React instances.
208
+ * Multiple React instances cause "Cannot read properties of null (reading 'useRef')" at MemoryRouter. */
209
+ function injectDedupe(projectRoot) {
210
+ const mainPath = getMainPath(projectRoot);
211
+ if (!mainPath) return;
212
+ let content = fs.readFileSync(mainPath, "utf-8");
213
+ if (content.includes("dedupe")) return; // idempotent
214
+ // Match: alias block + its trailing comma + whitespace/newline + resolve closing }
215
+ // e.g. alias: { "@": path.resolve(...) },\n },
216
+ // [^{}]* ensures we skip injection if alias has nested object values (safe fallback)
217
+ const pattern = /(\balias\s*:\s*\{[^{}]*\}),(\s*\})/;
218
+ if (!pattern.test(content)) return;
219
+ content = content.replace(pattern, (_, aliasBlock, resolveClose) =>
220
+ `${aliasBlock},\n dedupe: ["react", "react-dom", "react-router-dom"],${resolveClose}`
221
+ );
222
+ fs.writeFileSync(mainPath, content, "utf-8");
223
+ console.log("[VDS] Storybook adapt: injected React dedupe into viteFinal");
224
+ }
225
+
207
226
  function main() {
208
227
  const projectRoot = PROJECT_ROOT;
209
228
  if (!fs.existsSync(path.join(projectRoot, ".storybook"))) {
210
229
  console.log("[VDS] .storybook not found; skip storybook-adapt.");
211
230
  return;
212
231
  }
232
+ // Always inject dedupe — prevents "useRef null" crashes from multiple React instances
233
+ injectDedupe(projectRoot);
213
234
  reportUnresolvedImports(projectRoot);
214
235
  const problematic = collectProblematicImports(projectRoot);
215
236
  if (problematic.size === 0) return;