vibe-design-system 2.9.2 → 2.9.4

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/bin/init.js CHANGED
@@ -399,12 +399,12 @@ const config: StorybookConfig = {
399
399
  ];
400
400
  for (const tcp of tsConfigPaths) {
401
401
  if (!fs.existsSync(tcp)) continue;
402
- const raw = JSON.parse(fs.readFileSync(tcp, "utf-8").replace(/\/\/[^\n]*/g, "").replace(/,(\s*[}\]])/g, "$1"));
402
+ const raw = JSON.parse(fs.readFileSync(tcp, "utf-8").replace(/\\/\\/[^\\n]*/g, "").replace(/,(\\s*[}\\]])/g, "$1"));
403
403
  const paths = raw?.compilerOptions?.paths || {};
404
404
  const aliases: Record<string, string> = {};
405
405
  for (const [alias, targets] of Object.entries(paths) as [string, string[]][]) {
406
- const cleanAlias = alias.replace(/\/\*$/, "");
407
- const target = targets[0]?.replace(/\/\*$/, "") || "";
406
+ const cleanAlias = alias.replace(/\\/\\*$/, "");
407
+ const target = targets[0]?.replace(/\\/\\*$/, "") || "";
408
408
  if (cleanAlias && target && cleanAlias !== "@") {
409
409
  aliases[cleanAlias] = path.resolve(process.cwd(), target);
410
410
  }
@@ -415,6 +415,19 @@ const config: StorybookConfig = {
415
415
  return {};
416
416
  })();
417
417
  return mergeConfig(config, {
418
+ plugins: [
419
+ {
420
+ // Mock figma:asset/* imports — returns empty string so components render without crashing in Storybook
421
+ name: "vds-figma-asset-mock",
422
+ enforce: "pre" as const,
423
+ resolveId(id: string) {
424
+ if (id.startsWith("figma:asset")) return "\\0vds-figma-asset-mock";
425
+ },
426
+ load(id: string) {
427
+ if (id === "\\0vds-figma-asset-mock") return "export default '';";
428
+ },
429
+ },
430
+ ],
418
431
  resolve: {
419
432
  alias: {
420
433
  "@": path.resolve(process.cwd(), "${srcPrefix}"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-design-system",
3
- "version": "2.9.2",
3
+ "version": "2.9.4",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "homepage": "https://vibedesign.tech",
6
6
  "repository": {
@@ -5284,15 +5284,26 @@ function parseLocalDataImports(content) {
5284
5284
  }
5285
5285
 
5286
5286
  /**
5287
- * Detect named exports from a data file: returns { exportName → 'array' | 'object' | 'scalar' }
5287
+ * Detect named exports from a data file.
5288
+ * Returns { exportName → 'array' | 'object' | 'scalar' }
5289
+ * Also captures element type annotations: { 'EXPORTS_ELEMENT_TYPE' → 'TypeName' }
5290
+ * e.g. `export const METHODOLOGY_DATA: Stage[] = [...]` → { METHODOLOGY_DATA: 'array', METHODOLOGY_DATA_ELEMENT_TYPE: 'Stage' }
5288
5291
  */
5289
5292
  function parseDataFileExports(filePath) {
5290
5293
  if (!fs.existsSync(filePath)) return {};
5291
5294
  const src = fs.readFileSync(filePath, "utf-8");
5292
5295
  const result = {};
5293
- const re = /^export\s+const\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*[=:]/gm;
5296
+ // Typed array exports: export const NAME: ElemType[] = [
5297
+ const typedRe = /^export\s+const\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*:\s*([A-Za-z_$][A-Za-z0-9_$]*)\[\]/gm;
5294
5298
  let m;
5299
+ while ((m = typedRe.exec(src)) !== null) {
5300
+ result[m[1]] = "array";
5301
+ result[`${m[1]}_ELEMENT_TYPE`] = m[2]; // e.g. METHODOLOGY_DATA_ELEMENT_TYPE = "Stage"
5302
+ }
5303
+ // Untyped / other exports (fallback detection)
5304
+ const re = /^export\s+const\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*[=:]/gm;
5295
5305
  while ((m = re.exec(src)) !== null) {
5306
+ if (result[m[1]]) continue; // already captured above
5296
5307
  const name = m[1];
5297
5308
  const afterIdx = src.indexOf("=", m.index) + 1;
5298
5309
  const afterSlice = src.slice(afterIdx, afterIdx + 10).trimStart();
@@ -5378,9 +5389,17 @@ function mockValueForType(type, localExports, sourceContent) {
5378
5389
  if (/^[A-Z][A-Za-z0-9]+$/.test(t)) {
5379
5390
  const typeLower = t.toLowerCase().replace(/def$|id$|key$|type$|interface$|kind$/i, "");
5380
5391
 
5381
- // Strategy 1: Direct top-level array match (RouteDef → ROUTES[0])
5392
+ // Strategy 1: Direct top-level array match (RouteDef → ROUTES[0], Stage → METHODOLOGY_DATA[0])
5382
5393
  if (typeLower.length >= 3) {
5383
- for (const [expName, expKind] of Object.entries(localExports)) {
5394
+ // Sort by export name length descending — more-specific exports (METHODOLOGY_DATA) tried before simple ones (ROUTES)
5395
+ const sortedExports = Object.entries(localExports).sort((a, b) => b[0].length - a[0].length);
5396
+ // 1a: Exact element type annotation match (Stage → METHODOLOGY_DATA_ELEMENT_TYPE=Stage → METHODOLOGY_DATA[0])
5397
+ for (const [expName, expKind] of sortedExports) {
5398
+ if (expKind !== "array") continue;
5399
+ if (localExports[`${expName}_ELEMENT_TYPE`] === t) return `${expName}[0]`;
5400
+ }
5401
+ // 1b: Name prefix match (RouteDef → ROUTES[0])
5402
+ for (const [expName, expKind] of sortedExports) {
5384
5403
  if (expKind !== "array") continue;
5385
5404
  const expBase = expName.toLowerCase().replace(/_/g, "").replace(/s$/, "").replace(/data$/, "");
5386
5405
  if (expBase.slice(0, 4) === typeLower.slice(0, 4) || typeLower.slice(0, 4) === expBase.slice(0, 4)) {
@@ -5389,10 +5408,19 @@ function mockValueForType(type, localExports, sourceContent) {
5389
5408
  }
5390
5409
  }
5391
5410
 
5392
- // Strategy 2: Local interface/type alias generate inline object
5393
- // e.g. FilterState → { level1: null, level2: null }
5411
+ // Strategy 2: Local type alias resolution e.g. Level1Filter = 'A' | 'B' | null → null
5394
5412
  if (sourceContent) {
5395
5413
  const esc = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5414
+ // 2a: Non-object type alias: type Foo = ...
5415
+ const aliasRe = new RegExp(`type\\s+${esc}\\s*=\\s*([^{;\\n]+)`);
5416
+ const aliasMatch = sourceContent.match(aliasRe);
5417
+ if (aliasMatch) {
5418
+ const aliasValue = aliasMatch[1].trim().replace(/;$/, "");
5419
+ // Recursively resolve the alias value (pass sourceContent for chained aliases)
5420
+ return mockValueForType(aliasValue, localExports, sourceContent);
5421
+ }
5422
+ // 2b: Interface or object type alias → generate inline default object
5423
+ // e.g. FilterState → { level1: null, level2: null }
5396
5424
  const bodyRe = new RegExp(`(?:interface|type)\\s+${esc}\\s*(?:=\\s*)?\\{([^}]+)\\}`);
5397
5425
  const m = sourceContent.match(bodyRe);
5398
5426
  if (m) {
@@ -5402,8 +5430,8 @@ function mockValueForType(type, localExports, sourceContent) {
5402
5430
  if (ci < 0) return null;
5403
5431
  const fname = f.slice(0, ci).trim().replace(/\?$/, "");
5404
5432
  const ftype = f.slice(ci + 1).trim();
5405
- // Resolve field type (no recursion with sourceContent to prevent deep loops)
5406
- const fmock = mockValueForType(ftype, localExports, null);
5433
+ // Resolve field type with sourceContent for alias chaining
5434
+ const fmock = mockValueForType(ftype, localExports, sourceContent);
5407
5435
  return ` ${fname}: ${fmock}`;
5408
5436
  }).filter(Boolean);
5409
5437
  if (fieldPairs.length > 0) return `{\n${fieldPairs.join(",\n")}\n}`;
@@ -5411,11 +5439,14 @@ function mockValueForType(type, localExports, sourceContent) {
5411
5439
  }
5412
5440
 
5413
5441
  // Strategy 3: Nested array property lookup
5414
- // SubStation → DATA[0]?.subStations?.[0] (camelCase plural of type name)
5442
+ // SubStation → METHODOLOGY_DATA[0]?.subStations?.[0] (prefer longer export names)
5415
5443
  const camel = t[0].toLowerCase() + t.slice(1);
5416
5444
  const plural = camel + "s";
5417
- for (const [expName, expKind] of Object.entries(localExports)) {
5418
- if (expKind !== "array") continue;
5445
+ const sortedForNested = Object.entries(localExports)
5446
+ .filter(([, k]) => k === "array")
5447
+ .sort((a, b) => b[0].length - a[0].length); // longest name first
5448
+ if (sortedForNested.length > 0) {
5449
+ const [expName] = sortedForNested[0];
5419
5450
  return `${expName}[0]?.${plural}?.[0]`;
5420
5451
  }
5421
5452
  }