vibe-design-system 2.5.28 → 2.5.29

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.28",
3
+ "version": "2.5.29",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,7 +56,7 @@ To see **live renders** of components in the dashboard (isolated, no app chrome)
56
56
  "vds:stories": "node vds-core/story-generator.mjs"
57
57
  ```
58
58
 
59
- 2. **Context providers:** If components use React context (e.g. `useTimer`, `useSidebar`, `useCircles`, drag-drop context), they will error in Storybook unless wrapped with the right providers. In your project, add decorators in `.storybook/preview.tsx` to wrap all stories (or per-story) with your app’s providers (e.g. `TimerProvider`, `SidebarProvider`, `CirclesProvider`). See [Storybook decorators](https://storybook.js.org/docs/writing-stories/decorators).
59
+ 2. **Context providers:** Run `node vds-core/setup-storybook-providers.mjs` to detect hooks (useTimer, useSidebar, useCircles, useAuth, useSearch) and inject the matching providers into `.storybook/preview.ts`. The script prefers the provider from the same file as the hook (e.g. `context/SidebarContext.tsx` for useSidebar over `components/ui/sidebar`). If a component still errors with "Cannot read properties of undefined (reading 'x')", add default args or mock context state in that component’s story.
60
60
 
61
61
  3. **Icons:** The Foundations/Icons story lists only icons that are imported from `lucide-react` in your app code (src/, excluding `src/stories`), so it reflects real usage.
62
62
 
@@ -22,6 +22,7 @@ const HOOK_TO_PROVIDER = {
22
22
  useCircles: "CirclesProvider",
23
23
  useSidebar: "SidebarProvider",
24
24
  useAuth: "AuthProvider",
25
+ useSearch: "SearchProvider",
25
26
  };
26
27
 
27
28
  const IGNORE_DIRS = new Set(["node_modules", "dist", ".next", "build", ".storybook", "stories"]);
@@ -67,24 +68,29 @@ function detectHooksUsedInProject(projectRoot) {
67
68
  return byFile;
68
69
  }
69
70
 
70
- /** Find file that exports providerName (e.g. TimerProvider). Returns import path from project root for @/ alias: "contexts/TimerContext" */
71
- function findProviderExportPath(projectRoot, providerName) {
71
+ /** Find file that exports providerName (e.g. TimerProvider). If hookName is given, prefer a file that also contains that hook (e.g. context/SidebarContext.tsx for useSidebar over ui/sidebar). */
72
+ function findProviderExportPath(projectRoot, providerName, hookName) {
72
73
  const srcDir = path.join(projectRoot, "src");
73
74
  const files = getAllSourceFiles(srcDir, srcDir).map((r) => path.join("src", r));
74
75
  const exportRe = new RegExp(
75
76
  "export\\s+(?:default\\s+)?(?:const|function|class)\\s+" + providerName + "\\b|export\\s*\\{[^}]*\\b" + providerName + "\\b[^}]*\\}"
76
77
  );
78
+ const candidates = [];
77
79
  for (const rel of files) {
78
80
  const full = path.join(projectRoot, rel);
79
81
  try {
80
82
  const content = fs.readFileSync(full, "utf-8");
81
83
  if (exportRe.test(content)) {
82
84
  const withoutExt = rel.replace(/\.(tsx?|jsx?)$/i, "").replace(/^src\/?/, "");
83
- return "@/" + withoutExt;
85
+ const pathForImport = "@/" + withoutExt;
86
+ const hasHook = hookName && new RegExp("\\b" + hookName + "\\b").test(content);
87
+ candidates.push({ pathForImport, hasHook });
84
88
  }
85
89
  } catch (_) {}
86
90
  }
87
- return null;
91
+ const preferred = hookName ? candidates.find((c) => c.hasHook) : null;
92
+ const pick = preferred || candidates[0];
93
+ return pick ? pick.pathForImport : null;
88
94
  }
89
95
 
90
96
  function getPreviewPath(projectRoot) {
@@ -110,7 +116,7 @@ function collectProvidersAndWarnings(projectRoot) {
110
116
  const hooksWithoutProvider = new Set();
111
117
  for (const hook of allHooksUsed) {
112
118
  const providerName = HOOK_TO_PROVIDER[hook];
113
- const importPath = findProviderExportPath(projectRoot, providerName);
119
+ const importPath = findProviderExportPath(projectRoot, providerName, hook);
114
120
  if (importPath) {
115
121
  if (!providersToAdd.some((p) => p.name === providerName)) {
116
122
  providersToAdd.push({ name: providerName, importPath });