vibe-design-system 2.8.78 → 2.8.81
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
|
@@ -2207,6 +2207,21 @@ function extractVariantUsage(componentResults) {
|
|
|
2207
2207
|
}
|
|
2208
2208
|
}
|
|
2209
2209
|
|
|
2210
|
+
/**
|
|
2211
|
+
* Heuristic: detect complex page-level components that should not get individual stories.
|
|
2212
|
+
* Criteria: 500+ lines AND 4+ internal capitalized component definitions AND no cva()/forwardRef.
|
|
2213
|
+
* Examples: a 900-line MethodologyMap.tsx with 8 inline sub-components.
|
|
2214
|
+
*/
|
|
2215
|
+
function isComplexPageComponent(content) {
|
|
2216
|
+
const lines = content.split("\n").length;
|
|
2217
|
+
if (lines < 500) return false;
|
|
2218
|
+
const internalComps = (content.match(/\bconst\s+[A-Z][A-Za-z]+\s*[:=]\s*\(/g) || []).length;
|
|
2219
|
+
if (internalComps < 4) return false;
|
|
2220
|
+
// Don't flag UI primitives that use cva() or forwardRef — those are styled components
|
|
2221
|
+
if (content.includes("cva(") || content.includes("forwardRef")) return false;
|
|
2222
|
+
return true;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2210
2225
|
function scan() {
|
|
2211
2226
|
const relativeFiles = COMPONENTS_DIR ? getAllComponentFiles(COMPONENTS_DIR) : [];
|
|
2212
2227
|
if (!COMPONENTS_DIR) {
|
|
@@ -2231,7 +2246,8 @@ function scan() {
|
|
|
2231
2246
|
description = "";
|
|
2232
2247
|
}
|
|
2233
2248
|
const tokens = extractTailwindTokens(content);
|
|
2234
|
-
|
|
2249
|
+
const isPageComponent = isComplexPageComponent(content);
|
|
2250
|
+
results.push({ file: rel, name, group, category, description, tokens, ...(isPageComponent ? { isPageComponent: true } : {}) });
|
|
2235
2251
|
}
|
|
2236
2252
|
if (PAGES_DIR && fs.existsSync(PAGES_DIR)) {
|
|
2237
2253
|
const pageFiles = getAllComponentFiles(PAGES_DIR);
|
|
@@ -2202,7 +2202,8 @@ function buildStoryFileContent(comp) {
|
|
|
2202
2202
|
// Strip opacity modifier (e.g. "muted/20" → "muted") as a fallback
|
|
2203
2203
|
const baseKey = key ? key.replace(/\/[\d.]+$/, "") : null;
|
|
2204
2204
|
const entry = key ? (foundColors[key] || (baseKey !== key ? foundColors[baseKey] : null)) : null;
|
|
2205
|
-
const
|
|
2205
|
+
const isValidCssColor = (v) => /^#[0-9a-fA-F]{3,8}$/.test(v) || /^(rgb|rgba|hsl|hsla|oklch|oklab|lch|lab|color)\s*\(/.test(v) || v === 'transparent';
|
|
2206
|
+
const hex = entry?.hex && isValidCssColor(entry.hex) ? entry.hex : null;
|
|
2206
2207
|
return { token, hex, label: baseKey || key };
|
|
2207
2208
|
});
|
|
2208
2209
|
|
|
@@ -4246,7 +4247,8 @@ function writeComponentInventoryStory(components, foundations) {
|
|
|
4246
4247
|
let key = m ? m[1] : null;
|
|
4247
4248
|
if (key) key = key.replace(/\/\d+$/, "");
|
|
4248
4249
|
const entry = key ? foundColors[key] : null;
|
|
4249
|
-
const
|
|
4250
|
+
const isValidCssColor = (v) => /^#[0-9a-fA-F]{3,8}$/.test(v) || /^(rgb|rgba|hsl|hsla|oklch|oklab|lch|lab|color)\s*\(/.test(v) || v === 'transparent';
|
|
4251
|
+
const hex = entry?.hex && isValidCssColor(entry.hex) ? entry.hex : null;
|
|
4250
4252
|
return { token, hex };
|
|
4251
4253
|
})
|
|
4252
4254
|
.filter(s => s.hex);
|
|
@@ -4906,6 +4908,11 @@ function main() {
|
|
|
4906
4908
|
const storyFileName = `${componentName}.stories.tsx`;
|
|
4907
4909
|
const storyPath = path.join(STORIES_DIR, storyFileName);
|
|
4908
4910
|
if (SKIP_LIST.includes(componentName)) continue;
|
|
4911
|
+
// Skip complex page-level components detected by scan (500+ lines, 4+ inline sub-components)
|
|
4912
|
+
if (comp.isPageComponent) {
|
|
4913
|
+
console.log(`[VDS] ${componentName} → skipped (complex page component — add to extraSkipList to suppress this message)`);
|
|
4914
|
+
continue;
|
|
4915
|
+
}
|
|
4909
4916
|
const requiredCount = Array.isArray(comp.props) ? comp.props.filter((p) => p.required === true).length : 0;
|
|
4910
4917
|
if (requiredCount > 3) {
|
|
4911
4918
|
console.log(`[VDS] ${componentName} → skipped (${requiredCount} required props — too complex to auto-generate)`);
|
|
@@ -262,6 +262,89 @@ function injectViteConfigAliases(projectRoot) {
|
|
|
262
262
|
console.log(`[VDS] Storybook adapt: injected vite aliases: ${missingAliases.map(([k]) => k).join(", ")}`);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
// ============================================================
|
|
266
|
+
// VERSION-PINNED IMPORT HANDLING (Bolt/Lovable/AI-generated)
|
|
267
|
+
// ============================================================
|
|
268
|
+
|
|
269
|
+
/** Detect if import specifier has a @version suffix (e.g. @radix-ui/react-slot@1.1.2) */
|
|
270
|
+
function isVersionPinned(spec) {
|
|
271
|
+
return /^(?:@[\w.-]+\/)?[\w.-]+@\d+\.\d+/.test(spec) && !spec.startsWith("@/");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Scan source files for any version-pinned imports */
|
|
275
|
+
function hasVersionPinnedImports() {
|
|
276
|
+
if (!fs.existsSync(SRC_DIR)) return false;
|
|
277
|
+
const files = getAllSourceFiles(SRC_DIR, SRC_DIR).map((r) => path.join(SRC_DIR, r));
|
|
278
|
+
for (const file of files) {
|
|
279
|
+
try {
|
|
280
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
281
|
+
for (const spec of extractImports(content)) {
|
|
282
|
+
if (isVersionPinned(spec)) return true;
|
|
283
|
+
}
|
|
284
|
+
} catch (_) {}
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Remove wrong version alias entries previously injected by a broken VDS run.
|
|
291
|
+
* These look like: "@radix-ui/react-slot@1.1.2": path.resolve(process.cwd(), "@radix-ui/react-slot"),
|
|
292
|
+
* They point to non-existent paths and must be replaced by the plugin approach.
|
|
293
|
+
*/
|
|
294
|
+
function cleanupWrongVersionAliases(projectRoot) {
|
|
295
|
+
const mainPath = getMainPath(projectRoot);
|
|
296
|
+
if (!mainPath) return;
|
|
297
|
+
let content = fs.readFileSync(mainPath, "utf-8");
|
|
298
|
+
const before = content;
|
|
299
|
+
// Remove any alias line where key has @version suffix
|
|
300
|
+
content = content.replace(
|
|
301
|
+
/\n?\s*"(?:@[\w.-]+\/)?[\w.-]+@[\d.]+"\s*:\s*path\.resolve\(process\.cwd\(\),\s*"[^"]+"\),?/g,
|
|
302
|
+
""
|
|
303
|
+
);
|
|
304
|
+
if (content !== before) {
|
|
305
|
+
fs.writeFileSync(mainPath, content, "utf-8");
|
|
306
|
+
console.log("[VDS] Storybook adapt: cleaned up incorrect version-pinned aliases from main.ts.");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Inject a Vite plugin that strips @version suffixes from package import specifiers.
|
|
312
|
+
* e.g. @radix-ui/react-slot@1.1.2 → @radix-ui/react-slot (resolved from node_modules normally).
|
|
313
|
+
* Only added to viteFinal-based configs (not Next.js @storybook/nextjs).
|
|
314
|
+
*/
|
|
315
|
+
function injectVersionStripPlugin(projectRoot) {
|
|
316
|
+
const mainPath = getMainPath(projectRoot);
|
|
317
|
+
if (!mainPath) return;
|
|
318
|
+
let content = fs.readFileSync(mainPath, "utf-8");
|
|
319
|
+
|
|
320
|
+
if (content.includes("vds-version-pin-strip")) return; // already injected
|
|
321
|
+
if (!content.includes("viteFinal")) return; // only for Vite-based storybook
|
|
322
|
+
|
|
323
|
+
// The plugin block to inject. Double-escaped backslashes become single in the written file.
|
|
324
|
+
const pluginBlock = ` plugins: [
|
|
325
|
+
{
|
|
326
|
+
name: "vds-version-pin-strip",
|
|
327
|
+
enforce: "pre",
|
|
328
|
+
async resolveId(id) {
|
|
329
|
+
// Strip @version suffix: @radix-ui/react-slot@1.1.2 → @radix-ui/react-slot
|
|
330
|
+
const m = id.match(/^((?:@[\\w.-]+\\/)?[\\w.-]+)@[\\d]+\\.[\\d]/);
|
|
331
|
+
if (m) return this.resolve(m[1], undefined, { skipSelf: true });
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
`;
|
|
336
|
+
|
|
337
|
+
// Insert before the resolve: { block inside viteFinal
|
|
338
|
+
const resolvePattern = /([ \t]+)(resolve\s*:\s*\{)/;
|
|
339
|
+
if (resolvePattern.test(content)) {
|
|
340
|
+
content = content.replace(resolvePattern, (_, indent, resolveKw) =>
|
|
341
|
+
`${indent}${pluginBlock}${resolveKw}`
|
|
342
|
+
);
|
|
343
|
+
fs.writeFileSync(mainPath, content, "utf-8");
|
|
344
|
+
console.log("[VDS] Storybook adapt: injected vds-version-pin-strip Vite plugin.");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
265
348
|
function main() {
|
|
266
349
|
const projectRoot = PROJECT_ROOT;
|
|
267
350
|
if (!fs.existsSync(path.join(projectRoot, ".storybook"))) {
|
|
@@ -272,10 +355,16 @@ function main() {
|
|
|
272
355
|
injectViteConfigAliases(projectRoot);
|
|
273
356
|
reportUnresolvedImports(projectRoot);
|
|
274
357
|
const problematic = collectProblematicImports(projectRoot);
|
|
275
|
-
if (problematic.size
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
358
|
+
if (problematic.size > 0) {
|
|
359
|
+
writeMocks(projectRoot, problematic);
|
|
360
|
+
injectAliases(projectRoot, problematic);
|
|
361
|
+
console.log("[VDS] Storybook adapt: mocked", [...problematic].join(", "));
|
|
362
|
+
}
|
|
363
|
+
// Handle version-pinned imports (AI/Bolt/Lovable-generated projects with @pkg@version syntax)
|
|
364
|
+
if (hasVersionPinnedImports()) {
|
|
365
|
+
cleanupWrongVersionAliases(projectRoot);
|
|
366
|
+
injectVersionStripPlugin(projectRoot);
|
|
367
|
+
}
|
|
279
368
|
}
|
|
280
369
|
|
|
281
370
|
main();
|