vibe-design-system 2.8.69 → 2.8.70

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.69",
3
+ "version": "2.8.70",
4
4
  "description": "Auto-generate design systems for vibe coding projects",
5
5
  "homepage": "https://vibedesign.tech",
6
6
  "repository": {
@@ -4036,10 +4036,39 @@ function writeComponentInventoryStory(components, foundations) {
4036
4036
  return name.replace(/[-\s]+(.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, c => c.toUpperCase());
4037
4037
  }
4038
4038
 
4039
- const importInfoMap = {}; // comp.name → { identifier, importAlias, isDefault }
4039
+ const importInfoMap = {}; // comp.name → { identifier, importAlias, isDefault, actualExport, skip }
4040
4040
  const seenAliases = new Set();
4041
4041
  const orderedImports = []; // deduplicated
4042
4042
 
4043
+ // Detect actual usable export from a source file.
4044
+ // Returns { actualExport, isDefault } or null if no PascalCase export found.
4045
+ function detectExport(srcPath, expectedId) {
4046
+ try {
4047
+ const src = fs.readFileSync(srcPath, 'utf-8');
4048
+ // Exact named export: export { Foo } or export const/function/class Foo
4049
+ if (new RegExp(`export\\s*\\{[^}]*\\b${expectedId}\\b`).test(src) ||
4050
+ new RegExp(`export\\s+(?:const|function|class)\\s+${expectedId}\\b`).test(src)) {
4051
+ return { actualExport: expectedId, isDefault: false };
4052
+ }
4053
+ // Default export
4054
+ if (/export\s+default\b/.test(src)) {
4055
+ return { actualExport: expectedId, isDefault: true };
4056
+ }
4057
+ // Any PascalCase named export from brace-export block
4058
+ const braceMatch = src.match(/export\s*\{([^}]+)\}/);
4059
+ if (braceMatch) {
4060
+ const names = braceMatch[1].split(',')
4061
+ .map(n => n.trim().replace(/\s+as\s+\S+/, '').trim())
4062
+ .filter(n => /^[A-Z]/.test(n));
4063
+ if (names.length > 0) return { actualExport: names[0], isDefault: false };
4064
+ }
4065
+ // Any PascalCase direct export
4066
+ const directMatch = src.match(/export\s+(?:const|function|class)\s+([A-Z]\w*)/);
4067
+ if (directMatch) return { actualExport: directMatch[1], isDefault: false };
4068
+ return null; // no usable export
4069
+ } catch { return { actualExport: expectedId, isDefault: false }; }
4070
+ }
4071
+
4043
4072
  for (const comp of components) {
4044
4073
  if (!comp.file) continue;
4045
4074
  const identifier = toPascalLocal(comp.name);
@@ -4057,20 +4086,24 @@ function writeComponentInventoryStory(components, foundations) {
4057
4086
  importAlias = `@/${compBase}/${posixNoExt}`;
4058
4087
  }
4059
4088
 
4060
- // Detect default vs named export
4061
- let isDefault = false;
4062
- try {
4063
- const srcPath = isProjectRelative
4064
- ? absFromRoot
4065
- : path.join(PROJECT_ROOT, COMPONENTS_REL_DIR, comp.file);
4066
- isDefault = /export\s+default\b/.test(fs.readFileSync(srcPath, 'utf-8'));
4067
- } catch { /* keep false */ }
4089
+ // Detect actual export name in the file
4090
+ const srcPath = isProjectRelative
4091
+ ? absFromRoot
4092
+ : path.join(PROJECT_ROOT, COMPONENTS_REL_DIR, comp.file);
4093
+ const exportInfo = detectExport(srcPath, identifier);
4068
4094
 
4069
- importInfoMap[comp.name] = { identifier, importAlias, isDefault };
4095
+ if (!exportInfo) {
4096
+ // No usable export — skip import, will fall back to shape HTML
4097
+ importInfoMap[comp.name] = { identifier, importAlias, isDefault: false, actualExport: null, skip: true };
4098
+ continue;
4099
+ }
4100
+
4101
+ const { actualExport, isDefault } = exportInfo;
4102
+ importInfoMap[comp.name] = { identifier, importAlias, isDefault, actualExport, skip: false };
4070
4103
 
4071
4104
  if (!seenAliases.has(importAlias)) {
4072
4105
  seenAliases.add(importAlias);
4073
- orderedImports.push({ identifier, importAlias, isDefault });
4106
+ orderedImports.push({ identifier, importAlias, isDefault, actualExport });
4074
4107
  }
4075
4108
  }
4076
4109
 
@@ -4144,16 +4177,19 @@ function writeComponentInventoryStory(components, foundations) {
4144
4177
  )].length;
4145
4178
 
4146
4179
  // ── Build import lines ─────────────────────────────────────────────────────
4147
- const importLines = orderedImports.map(imp =>
4148
- imp.isDefault
4149
- ? `import ${imp.identifier} from "${imp.importAlias}";`
4150
- : `import { ${imp.identifier} } from "${imp.importAlias}";`
4151
- );
4180
+ const importLines = orderedImports.map(imp => {
4181
+ if (imp.isDefault) return `import ${imp.identifier} from "${imp.importAlias}";`;
4182
+ // If actual export name differs from identifier, use "as" renaming
4183
+ const namedPart = (imp.actualExport && imp.actualExport !== imp.identifier)
4184
+ ? `${imp.actualExport} as ${imp.identifier}`
4185
+ : imp.identifier;
4186
+ return `import { ${namedPart} } from "${imp.importAlias}";`;
4187
+ });
4152
4188
 
4153
- // ── PREVIEWS map entries ───────────────────────────────────────────────────
4189
+ // ── PREVIEWS map entries (only for non-skipped components) ─────────────────
4154
4190
  const TEXT_CHILD_NAMES = new Set(['button','badge','toggle','label','link','chip','tag','pill']);
4155
4191
  const previewEntries = components
4156
- .filter(comp => importInfoMap[comp.name])
4192
+ .filter(comp => importInfoMap[comp.name] && !importInfoMap[comp.name].skip)
4157
4193
  .map(comp => {
4158
4194
  const { identifier } = importInfoMap[comp.name];
4159
4195
  const hasText = TEXT_CHILD_NAMES.has(identifier.toLowerCase());