@tpitre/story-ui 4.6.1 → 4.6.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"generateStory.d.ts","sourceRoot":"","sources":["../../../mcp-server/routes/generateStory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAmd5C,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,2DA8lBxE"}
1
+ {"version":3,"file":"generateStory.d.ts","sourceRoot":"","sources":["../../../mcp-server/routes/generateStory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAyd5C,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,2DA8lBxE"}
@@ -312,29 +312,34 @@ async function preValidateImports(code, config, discovery) {
312
312
  }
313
313
  // Extract icon imports (keep existing icon validation)
314
314
  if (config.iconImports?.package) {
315
- const allowedIcons = new Set(config.iconImports?.commonIcons || []);
316
315
  const iconImports = extractImportsFromCode(code, config.iconImports.package);
317
- for (const iconName of iconImports) {
318
- if (isBlacklistedIcon(iconName, allowedIcons)) {
319
- const correction = ICON_CORRECTIONS[iconName];
320
- if (correction) {
321
- errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${correction}"?`);
322
- }
323
- else {
324
- errors.push(`Invalid icon: "${iconName}" is not in the list of available icons.`);
325
- }
326
- }
327
- else if (!allowedIcons.has(iconName)) {
328
- // Try to find a similar icon
329
- const similarIcon = findSimilarIcon(iconName, allowedIcons);
330
- if (similarIcon) {
331
- errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${similarIcon}"?`);
316
+ // If allowAllIcons is true, skip per-icon validation (trust the icon package)
317
+ // This is used when we auto-detect a known icon package but don't have a full manifest
318
+ if (!config.iconImports.allowAllIcons) {
319
+ const allowedIcons = new Set(config.iconImports?.commonIcons || []);
320
+ for (const iconName of iconImports) {
321
+ if (isBlacklistedIcon(iconName, allowedIcons)) {
322
+ const correction = ICON_CORRECTIONS[iconName];
323
+ if (correction) {
324
+ errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${correction}"?`);
325
+ }
326
+ else {
327
+ errors.push(`Invalid icon: "${iconName}" is not in the list of available icons.`);
328
+ }
332
329
  }
333
- else {
334
- errors.push(`Invalid icon: "${iconName}" is not in the list of available icons.`);
330
+ else if (!allowedIcons.has(iconName)) {
331
+ // Try to find a similar icon
332
+ const similarIcon = findSimilarIcon(iconName, allowedIcons);
333
+ if (similarIcon) {
334
+ errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${similarIcon}"?`);
335
+ }
336
+ else {
337
+ errors.push(`Invalid icon: "${iconName}" is not in the list of available icons.`);
338
+ }
335
339
  }
336
340
  }
337
341
  }
342
+ // When allowAllIcons is true, we trust that the LLM will use valid icons from the package
338
343
  }
339
344
  return {
340
345
  isValid: errors.length === 0,
@@ -1160,19 +1160,24 @@ async function preValidateImports(code, config, discovery) {
1160
1160
  }
1161
1161
  }
1162
1162
  if (config.iconImports?.package) {
1163
- const allowedIcons = new Set(config.iconImports?.commonIcons || []);
1164
1163
  const iconImports = extractImportsFromCode(code, config.iconImports.package);
1165
- for (const iconName of iconImports) {
1166
- if (isBlacklistedIcon(iconName, allowedIcons)) {
1167
- const correction = ICON_CORRECTIONS[iconName];
1168
- if (correction) {
1169
- errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${correction}"?`);
1170
- }
1171
- else {
1172
- errors.push(`Invalid icon: "${iconName}" is not available.`);
1164
+ // If allowAllIcons is true, skip per-icon validation (trust the icon package)
1165
+ // This is used when we auto-detect a known icon package but don't have a full manifest
1166
+ if (!config.iconImports.allowAllIcons) {
1167
+ const allowedIcons = new Set(config.iconImports?.commonIcons || []);
1168
+ for (const iconName of iconImports) {
1169
+ if (isBlacklistedIcon(iconName, allowedIcons)) {
1170
+ const correction = ICON_CORRECTIONS[iconName];
1171
+ if (correction) {
1172
+ errors.push(`Invalid icon: "${iconName}" does not exist. Did you mean "${correction}"?`);
1173
+ }
1174
+ else {
1175
+ errors.push(`Invalid icon: "${iconName}" is not available.`);
1176
+ }
1173
1177
  }
1174
1178
  }
1175
1179
  }
1180
+ // When allowAllIcons is true, we trust that the LLM will use valid icons from the package
1176
1181
  }
1177
1182
  return { isValid: errors.length === 0, errors };
1178
1183
  }
@@ -1,4 +1,4 @@
1
- import { StoryUIConfig } from '../story-ui.config.js';
1
+ import { StoryUIConfig, IconImportsConfig } from '../story-ui.config.js';
2
2
  /**
3
3
  * Loads Story UI configuration from the user's project
4
4
  * Looks for story-ui.config.js in the current working directory
@@ -30,4 +30,9 @@ export declare function detectStorybookFramework(dependencies: Record<string, st
30
30
  * Auto-detects design system configuration by analyzing the project structure
31
31
  */
32
32
  export declare function autoDetectDesignSystem(): Partial<StoryUIConfig> | null;
33
+ /**
34
+ * Detects installed icon package from package.json dependencies
35
+ * Returns configuration for the first detected icon package
36
+ */
37
+ export declare function detectInstalledIconPackage(projectPath?: string): IconImportsConfig | null;
33
38
  //# sourceMappingURL=configLoader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configLoader.d.ts","sourceRoot":"","sources":["../../story-generator/configLoader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAuC,MAAM,uBAAuB,CAAC;AAU3F;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,aAAa,CAmH9C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAsD5F;AA0DD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,GAAE,MAAsB,GAAG;IAC3E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAkGA;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAWrF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAqEtE"}
1
+ {"version":3,"file":"configLoader.d.ts","sourceRoot":"","sources":["../../story-generator/configLoader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAuC,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAuF9G;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,aAAa,CA4H9C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAsD5F;AA0DD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,GAAE,MAAsB,GAAG;IAC3E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAkGA;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAWrF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAqEtE;AAgPD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAkCzF"}
@@ -2,6 +2,71 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createRequire } from 'module';
4
4
  import { DEFAULT_CONFIG, createStoryUIConfig } from '../story-ui.config.js';
5
+ const KNOWN_ICON_PACKAGES = [
6
+ {
7
+ name: '@tabler/icons-react',
8
+ importPath: '@tabler/icons-react',
9
+ commonIcons: [
10
+ 'IconHome', 'IconSettings', 'IconUser', 'IconSearch', 'IconMenu2',
11
+ 'IconBell', 'IconMail', 'IconCalendar', 'IconClock', 'IconStar',
12
+ 'IconHeart', 'IconPlus', 'IconMinus', 'IconX', 'IconCheck',
13
+ 'IconChevronRight', 'IconChevronLeft', 'IconChevronDown', 'IconChevronUp',
14
+ 'IconArrowRight', 'IconArrowLeft', 'IconArrowUp', 'IconArrowDown',
15
+ 'IconEdit', 'IconTrash', 'IconDownload', 'IconUpload', 'IconShare',
16
+ 'IconFilter', 'IconSort', 'IconRefresh', 'IconEye', 'IconEyeOff',
17
+ 'IconLock', 'IconUnlock', 'IconCopy', 'IconClipboard', 'IconFolder',
18
+ 'IconFile', 'IconImage', 'IconVideo', 'IconMusic', 'IconLink',
19
+ 'IconExternalLink', 'IconDots', 'IconDotsVertical', 'IconGripVertical',
20
+ 'IconTrendingUp', 'IconTrendingDown', 'IconActivity', 'IconPieChart',
21
+ 'IconDatabase', 'IconServer', 'IconCode', 'IconTerminal',
22
+ ],
23
+ },
24
+ {
25
+ name: 'lucide-react',
26
+ importPath: 'lucide-react',
27
+ commonIcons: [
28
+ 'Home', 'Settings', 'User', 'Search', 'Menu',
29
+ 'Bell', 'Mail', 'Calendar', 'Clock', 'Star',
30
+ 'Heart', 'Plus', 'Minus', 'X', 'Check',
31
+ 'ChevronRight', 'ChevronLeft', 'ChevronDown', 'ChevronUp',
32
+ 'ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown',
33
+ 'Edit', 'Trash', 'Download', 'Upload', 'Share',
34
+ 'Filter', 'RefreshCw', 'Eye', 'EyeOff',
35
+ 'Lock', 'Unlock', 'Copy', 'Clipboard', 'Folder',
36
+ ],
37
+ },
38
+ {
39
+ name: '@heroicons/react',
40
+ importPath: '@heroicons/react/24/outline',
41
+ commonIcons: [
42
+ 'HomeIcon', 'Cog6ToothIcon', 'UserIcon', 'MagnifyingGlassIcon', 'Bars3Icon',
43
+ 'BellIcon', 'EnvelopeIcon', 'CalendarIcon', 'ClockIcon', 'StarIcon',
44
+ 'HeartIcon', 'PlusIcon', 'MinusIcon', 'XMarkIcon', 'CheckIcon',
45
+ 'ChevronRightIcon', 'ChevronLeftIcon', 'ChevronDownIcon', 'ChevronUpIcon',
46
+ 'ArrowRightIcon', 'ArrowLeftIcon', 'ArrowUpIcon', 'ArrowDownIcon',
47
+ ],
48
+ },
49
+ {
50
+ name: 'react-icons',
51
+ importPath: 'react-icons/fa',
52
+ commonIcons: [
53
+ 'FaHome', 'FaCog', 'FaUser', 'FaSearch', 'FaBars',
54
+ 'FaBell', 'FaEnvelope', 'FaCalendar', 'FaClock', 'FaStar',
55
+ 'FaHeart', 'FaPlus', 'FaMinus', 'FaTimes', 'FaCheck',
56
+ 'FaChevronRight', 'FaChevronLeft', 'FaChevronDown', 'FaChevronUp',
57
+ ],
58
+ },
59
+ {
60
+ name: '@phosphor-icons/react',
61
+ importPath: '@phosphor-icons/react',
62
+ commonIcons: [
63
+ 'House', 'Gear', 'User', 'MagnifyingGlass', 'List',
64
+ 'Bell', 'Envelope', 'Calendar', 'Clock', 'Star',
65
+ 'Heart', 'Plus', 'Minus', 'X', 'Check',
66
+ 'CaretRight', 'CaretLeft', 'CaretDown', 'CaretUp',
67
+ ],
68
+ },
69
+ ];
5
70
  // Create require function for ESM compatibility
6
71
  const require = createRequire(import.meta.url);
7
72
  // Config cache to prevent excessive loading
@@ -87,6 +152,14 @@ export function loadUserConfig() {
87
152
  }
88
153
  }
89
154
  }
155
+ // Auto-detect icon package if not already configured
156
+ // This is critical for allowing icon imports in generated stories
157
+ if (!config.iconImports) {
158
+ const detectedIconPackage = detectInstalledIconPackage();
159
+ if (detectedIconPackage) {
160
+ config.iconImports = detectedIconPackage;
161
+ }
162
+ }
90
163
  // Cache the loaded config
91
164
  cachedConfig = config;
92
165
  configLoadTime = now;
@@ -601,3 +674,39 @@ function detectLayoutPatterns(layoutPatterns, componentPrefix) {
601
674
  }
602
675
  return rules;
603
676
  }
677
+ /**
678
+ * Detects installed icon package from package.json dependencies
679
+ * Returns configuration for the first detected icon package
680
+ */
681
+ export function detectInstalledIconPackage(projectPath) {
682
+ const cwd = projectPath || process.cwd();
683
+ const packageJsonPath = path.join(cwd, 'package.json');
684
+ if (!fs.existsSync(packageJsonPath)) {
685
+ return null;
686
+ }
687
+ try {
688
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
689
+ const allDeps = {
690
+ ...packageJson.dependencies,
691
+ ...packageJson.devDependencies,
692
+ };
693
+ // Check for known icon packages
694
+ for (const iconPackage of KNOWN_ICON_PACKAGES) {
695
+ if (allDeps[iconPackage.name]) {
696
+ console.log(`🎨 Detected icon package: ${iconPackage.name}`);
697
+ return {
698
+ package: iconPackage.name,
699
+ importPath: iconPackage.importPath,
700
+ commonIcons: iconPackage.commonIcons,
701
+ // Allow all icons from this package - don't require explicit validation
702
+ // This is crucial: icon libraries have thousands of icons, we can't list them all
703
+ allowAllIcons: true,
704
+ };
705
+ }
706
+ }
707
+ }
708
+ catch (error) {
709
+ console.warn('Failed to detect icon package:', error);
710
+ }
711
+ return null;
712
+ }
@@ -69,7 +69,7 @@ export declare abstract class BaseFrameworkAdapter implements FrameworkAdapter {
69
69
  */
70
70
  protected log(message: string, data?: Record<string, unknown>): void;
71
71
  /**
72
- * Get common story structure rules
72
+ * Get common story structure rules including MANDATORY spacing
73
73
  */
74
74
  protected getCommonRules(): string;
75
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/base-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;GAEG;AACH,8BAAsB,oBAAqB,YAAW,gBAAgB;IACpE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAE3C;;OAEG;IACH,QAAQ,CAAC,oBAAoB,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAET;;OAEG;IACH,0BAA0B,CACxB,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;IAmBT;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAC5B,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,aAAa,GACpB,MAAM;IAkBT;;OAEG;IACH,SAAS,CAAC,aAAa,CACrB,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,aAAa,GACpB,MAAM;IAUT;;OAEG;IACH,SAAS,CAAC,wBAAwB,CAChC,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAcxC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAExD;;OAEG;IACH,QAAQ,CAAC,mBAAmB,CAC1B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAET;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;IAoBT;;;OAGG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAmBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAkBpE;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAEnE;;OAEG;IACH,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpE;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,MAAM;CAoBnC"}
1
+ {"version":3,"file":"base-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/base-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;GAEG;AACH,8BAAsB,oBAAqB,YAAW,gBAAgB;IACpE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAE3C;;OAEG;IACH,QAAQ,CAAC,oBAAoB,CAC3B,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAET;;OAEG;IACH,0BAA0B,CACxB,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;IAmBT;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAC5B,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,aAAa,GACpB,MAAM;IAkBT;;OAEG;IACH,SAAS,CAAC,aAAa,CACrB,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,aAAa,GACpB,MAAM;IAUT;;OAEG;IACH,SAAS,CAAC,wBAAwB,CAChC,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAcxC;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAExD;;OAEG;IACH,QAAQ,CAAC,mBAAmB,CAC1B,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAET;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;IAoBT;;;OAGG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAmBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAkBpE;;OAEG;IACH,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAEnE;;OAEG;IACH,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpE;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,MAAM;CA2DnC"}
@@ -132,7 +132,7 @@ export class BaseFrameworkAdapter {
132
132
  logger.debug(`[${this.name}Adapter] ${message}`, data);
133
133
  }
134
134
  /**
135
- * Get common story structure rules
135
+ * Get common story structure rules including MANDATORY spacing
136
136
  */
137
137
  getCommonRules() {
138
138
  return `
@@ -148,10 +148,49 @@ IMAGE RULES:
148
148
  - Always include alt text for images
149
149
  - Example: https://picsum.photos/400/300?random=1
150
150
 
151
- SPACING RULES:
152
- - Use the design system's spacing tokens when available
153
- - Maintain consistent margins and padding
154
- - Follow the layout grid system if present
151
+ MANDATORY SPACING & LAYOUT RULES (NON-NEGOTIABLE):
152
+ ** CRITICAL: Every generated component MUST have professional-quality spacing. Components without proper spacing look broken and unprofessional. **
153
+
154
+ 1. STORY WRAPPER (REQUIRED for every story):
155
+ - The render function MUST return a wrapper div with padding
156
+ - Pattern: render: () => <div style={{ padding: "24px" }}>...content...</div>
157
+ - This ensures content has breathing room within the Storybook canvas
158
+
159
+ 2. FORM FIELD SPACING (CRITICAL):
160
+ - ALWAYS wrap form fields in a container with vertical spacing
161
+ - Use flexbox column with gap: <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
162
+ - Or use design system spacing tokens if available
163
+ - MINIMUM 16px gap between form fields
164
+
165
+ 3. BUTTON SPACING:
166
+ - Submit/action buttons: 24px margin-top from form fields above
167
+ - Pattern: <div style={{ marginTop: "24px" }}><Button>Submit</Button></div>
168
+ - Button groups should be wrapped with margin-top from content
169
+
170
+ 4. SECTION SPACING:
171
+ - Between major sections: 32-48px
172
+ - Between related content groups: 24px
173
+ - Use dividers or significant whitespace between unrelated content
174
+
175
+ 5. HEADING SPACING:
176
+ - More space ABOVE headings (24-32px) than below (8-16px)
177
+ - Pattern: <Heading style={{ marginTop: "32px", marginBottom: "12px" }}>
178
+
179
+ 6. CARD/CONTAINER PADDING:
180
+ - Internal padding: minimum 16px, preferred 24px
181
+ - Pattern: <Card style={{ padding: "24px" }}>
182
+
183
+ 7. SPECIFIC VALUES TO USE:
184
+ - Tight spacing (icons, inline): 4-8px
185
+ - Related items: 8-12px
186
+ - Form fields: 16px gap
187
+ - Buttons from content: 24px margin-top
188
+ - Sections: 32-48px
189
+ - Major divisions: 48-64px
190
+
191
+ SPACING VALIDATION (Self-check before generating):
192
+ Ask yourself: "Does every element have adequate breathing room from its neighbors?"
193
+ If any elements appear cramped or touching, add appropriate spacing.
155
194
  `;
156
195
  }
157
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAOpB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D;;;;;GAKG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAmD;IACnE,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAkC;;IAU3D;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIzC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS;IAItD;;OAEG;IACH,MAAM,IAAI,gBAAgB,EAAE;IAI5B;;OAEG;IACH,iBAAiB,IAAI,aAAa,EAAE;IAIpC;;OAEG;IACH,sBAAsB,IAAI,aAAa,EAAE;IAIzC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB;IAIjD;;OAEG;IACH,UAAU,IAAI,gBAAgB;IAI9B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAQrC;;OAEG;IACG,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoBjE;;OAEG;IACH,oBAAoB,IAAI,iBAAiB,GAAG,IAAI;IAIhD;;OAEG;IACG,cAAc,CAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,eAAe,CAAC;CA8B5B;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAE5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,gBAAgB,CAEpD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEvF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAE1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAGzE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAOpB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAI/D;;;;;GAKG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAmD;IACnE,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,iBAAiB,CAAkC;;IAU3D;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIzC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS;IAItD;;OAEG;IACH,MAAM,IAAI,gBAAgB,EAAE;IAI5B;;OAEG;IACH,iBAAiB,IAAI,aAAa,EAAE;IAIpC;;OAEG;IACH,sBAAsB,IAAI,aAAa,EAAE;IAIzC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB;IAIjD;;OAEG;IACH,UAAU,IAAI,gBAAgB;IAI9B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAQrC;;OAEG;IACG,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoBjE;;OAEG;IACH,oBAAoB,IAAI,iBAAiB,GAAG,IAAI;IAIhD;;OAEG;IACG,cAAc,CAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,eAAe,CAAC;CAkC5B;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,SAAS,CAE5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,gBAAgB,CAEpD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAEvF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAE1B"}
@@ -22,6 +22,7 @@ import { AngularAdapter } from './angular-adapter.js';
22
22
  import { SvelteAdapter } from './svelte-adapter.js';
23
23
  import { detectFramework } from './framework-detector.js';
24
24
  import { logger } from '../logger.js';
25
+ import { generateLayoutInstructions } from '../promptGenerator.js';
25
26
  /**
26
27
  * Framework Adapter Registry
27
28
  *
@@ -147,10 +148,13 @@ class AdapterRegistry {
147
148
  adapter = await this.autoDetect();
148
149
  }
149
150
  logger.debug('Generating prompt with adapter', { adapter: adapter.type });
151
+ // Generate layout instructions including mandatory spacing rules
152
+ const layoutInstructionsArray = generateLayoutInstructions(config);
153
+ const layoutInstructionsString = layoutInstructionsArray.join('\n');
150
154
  return {
151
155
  systemPrompt: adapter.generateSystemPrompt(config, options),
152
156
  componentReference: adapter.generateComponentReference(components, config),
153
- layoutInstructions: '',
157
+ layoutInstructions: layoutInstructionsString,
154
158
  examples: adapter.generateExamples(config),
155
159
  sampleStory: adapter.generateSampleStory(config, components),
156
160
  framework: this.detectedFramework || {
@@ -19,6 +19,12 @@ export interface GeneratedPrompt {
19
19
  * Generates a comprehensive AI prompt based on the configuration and discovered components
20
20
  */
21
21
  export declare function generatePrompt(config: StoryUIConfig, components: DiscoveredComponent[]): GeneratedPrompt;
22
+ /**
23
+ * Generates layout-specific instructions including MANDATORY vertical spacing rules
24
+ * @param config - The StoryUI configuration object
25
+ * @returns Array of layout instruction strings to be included in the prompt
26
+ */
27
+ export declare function generateLayoutInstructions(config: StoryUIConfig): string[];
22
28
  /**
23
29
  * Builds the complete Claude prompt
24
30
  */
@@ -1 +1 @@
1
- {"version":3,"file":"promptGenerator.d.ts","sourceRoot":"","sources":["../../story-generator/promptGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAI9D,OAAO,EAEL,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAyOvC;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,eAAe,EAAE,oBAAoB,CAAC;IACvF,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,eAAe,CAcxG;AA2hBD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CA8JjB;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAiHjB;AA4ED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAIzF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,aAAa,GAAG,gBAAgB,CAG9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,EAAE,CAGxD"}
1
+ {"version":3,"file":"promptGenerator.d.ts","sourceRoot":"","sources":["../../story-generator/promptGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAI9D,OAAO,EAEL,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAyOvC;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,eAAe,EAAE,oBAAoB,CAAC;IACvF,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,eAAe,CAcxG;AAqTD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CA6D1E;AA0MD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CA8JjB;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAiHjB;AA4ED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAIzF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,aAAa,GAAG,gBAAgB,CAG9E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,EAAE,CAGxD"}
@@ -465,13 +465,47 @@ function formatComponentReference(component, config) {
465
465
  return reference;
466
466
  }
467
467
  /**
468
- * Generates layout-specific instructions
468
+ * Generates layout-specific instructions including MANDATORY vertical spacing rules
469
+ * @param config - The StoryUI configuration object
470
+ * @returns Array of layout instruction strings to be included in the prompt
469
471
  */
470
- function generateLayoutInstructions(config) {
472
+ export function generateLayoutInstructions(config) {
471
473
  const instructions = [];
472
474
  const layoutRules = config.layoutRules;
475
+ // MANDATORY VERTICAL SPACING RULES - These are non-negotiable for professional UI quality
476
+ instructions.push('MANDATORY VERTICAL SPACING RULES (NON-NEGOTIABLE):');
477
+ instructions.push('');
478
+ instructions.push('** CRITICAL: Every component MUST have proper vertical spacing. Components without spacing look broken and unprofessional. **');
479
+ instructions.push('');
480
+ instructions.push('1. FORM FIELDS: Always wrap form fields in a container with vertical spacing:');
481
+ instructions.push(' - Use flexbox column with gap: <div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>');
482
+ instructions.push(' - Or use your design system\'s spacing tokens if available');
483
+ instructions.push(' - MINIMUM 16px gap between form fields, 24px for complex forms');
484
+ instructions.push('');
485
+ instructions.push('2. BUTTON SPACING: Buttons MUST have margin-top from content above:');
486
+ instructions.push(' - Submit/action buttons: 24px margin-top from form fields');
487
+ instructions.push(' - Button groups: wrap in <div style={{ marginTop: "24px" }}>');
488
+ instructions.push('');
489
+ instructions.push('3. SECTION SPACING: Logical sections need clear visual separation:');
490
+ instructions.push(' - Between major sections: 32-48px');
491
+ instructions.push(' - Between related content groups: 24px');
492
+ instructions.push(' - Use dividers or significant whitespace between unrelated content');
493
+ instructions.push('');
494
+ instructions.push('4. HEADING SPACING: Headings need asymmetric spacing:');
495
+ instructions.push(' - More space ABOVE headings (24-32px) than below (8-16px)');
496
+ instructions.push(' - This creates visual hierarchy and groups content with its heading');
497
+ instructions.push('');
498
+ instructions.push('5. CARD/CONTAINER PADDING: Internal padding is mandatory:');
499
+ instructions.push(' - Minimum 16px padding on all sides');
500
+ instructions.push(' - Preferred 24px for cards with multiple elements');
501
+ instructions.push(' - Use design system spacing tokens when available');
502
+ instructions.push('');
503
+ instructions.push('6. WRAPPER PATTERN (REQUIRED): The story render function MUST return a wrapper div with padding:');
504
+ instructions.push(' - render: () => <div style={{ padding: "24px" }}>...content...</div>');
505
+ instructions.push(' - This ensures content has breathing room within the Storybook canvas');
506
+ instructions.push('');
473
507
  if (layoutRules.multiColumnWrapper && layoutRules.columnComponent) {
474
- instructions.push('CRITICAL LAYOUT RULES:');
508
+ instructions.push('MULTI-COLUMN LAYOUT RULES:');
475
509
  instructions.push(`- For ANY multi-column layout (2, 3, or more columns), use ${layoutRules.multiColumnWrapper} components`);
476
510
  instructions.push(`- Each column must be wrapped in its own ${layoutRules.columnComponent} element`);
477
511
  instructions.push(`- Structure: <${layoutRules.multiColumnWrapper}><${layoutRules.columnComponent}>column 1</${layoutRules.columnComponent}><${layoutRules.columnComponent}>column 2</${layoutRules.columnComponent}></${layoutRules.multiColumnWrapper}>`);
@@ -479,14 +513,17 @@ function generateLayoutInstructions(config) {
479
513
  instructions.push(`- NEVER use CSS properties as props (like display="grid" or gridTemplateColumns) - these are not valid props`);
480
514
  instructions.push(`- For grid-like layouts, use Flex with wrap prop and appropriate gap, NOT CSS Grid`);
481
515
  instructions.push(`- The ${layoutRules.multiColumnWrapper} should be the main component in your story for multi-column layouts`);
516
+ instructions.push('');
482
517
  }
483
518
  if (layoutRules.prohibitedElements && layoutRules.prohibitedElements.length > 0) {
484
519
  instructions.push(`- NEVER use plain HTML ${layoutRules.prohibitedElements.join(', ')} elements - ALWAYS use the provided design system components`);
485
520
  }
486
521
  // Generic layout instructions for all design systems
522
+ instructions.push('GENERAL LAYOUT BEST PRACTICES:');
487
523
  instructions.push(`- Use semantic heading components from your design system instead of raw <h1>-<h6> tags`);
488
- instructions.push(`- Use the design system's layout components and spacing tokens instead of inline styles`);
524
+ instructions.push(`- Use the design system's layout components and spacing tokens instead of inline styles when available`);
489
525
  instructions.push(`- Prefer design system components over plain HTML elements for consistent styling`);
526
+ instructions.push(`- ALWAYS test mentally: "Does this component have enough visual breathing room?" If not, add spacing.`);
490
527
  return instructions;
491
528
  }
492
529
  /**
@@ -23,6 +23,16 @@ export interface AdditionalImport {
23
23
  path: string;
24
24
  components: string[];
25
25
  }
26
+ export interface IconImportsConfig {
27
+ /** Package name for icon imports (e.g., '@tabler/icons-react', 'lucide-react') */
28
+ package: string;
29
+ /** Import path pattern (e.g., '@tabler/icons-react' or 'lucide-react') */
30
+ importPath: string;
31
+ /** Common icons that are known to exist (for validation fallback) */
32
+ commonIcons?: string[];
33
+ /** Whether to allow any icon from this package (skip individual validation) */
34
+ allowAllIcons?: boolean;
35
+ }
26
36
  export interface DesignSystemGuidelines {
27
37
  name: string;
28
38
  preferredComponents?: {
@@ -72,6 +82,8 @@ export interface StoryUIConfig {
72
82
  considerationsPath?: string;
73
83
  storybookFramework?: string;
74
84
  designSystemGuidelines?: DesignSystemGuidelines;
85
+ /** Icon imports configuration (auto-detected from package.json or manually configured) */
86
+ iconImports?: IconImportsConfig;
75
87
  }
76
88
  export declare const DEFAULT_CONFIG: StoryUIConfig;
77
89
  export declare const GENERIC_CONFIG_TEMPLATE: Partial<StoryUIConfig>;
@@ -1 +1 @@
1
- {"version":3,"file":"story-ui.config.d.ts","sourceRoot":"","sources":["../story-ui.config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"story-ui.config.d.ts","sourceRoot":"","sources":["../story-ui.config.ts"],"names":[],"mappings":"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"}
@@ -1248,6 +1248,7 @@
1248
1248
 
1249
1249
  /* ============================================
1250
1250
  Completion Card - shares bubble styling with message bubbles
1251
+ Uses explicit colors with !important to prevent design system overrides
1251
1252
  ============================================ */
1252
1253
  .sui-completion {
1253
1254
  max-width: 85%;
@@ -1256,9 +1257,17 @@
1256
1257
  border-bottom-left-radius: var(--radius-sm);
1257
1258
  font-size: 0.9375rem;
1258
1259
  line-height: 1.6;
1259
- border: 1px solid hsl(var(--border));
1260
- background: hsl(var(--card));
1261
- color: hsl(var(--foreground));
1260
+ /* Explicit light mode colors */
1261
+ background: #ffffff !important;
1262
+ color: #18181b !important;
1263
+ border: 1px solid #e4e4e7 !important;
1264
+ }
1265
+
1266
+ /* Completion card - dark mode */
1267
+ .sui-root.dark .sui-completion {
1268
+ background: #27272a !important;
1269
+ color: #fafafa !important;
1270
+ border: 1px solid #3f3f46 !important;
1262
1271
  }
1263
1272
 
1264
1273
  .sui-completion-header {
@@ -1266,7 +1275,13 @@
1266
1275
  align-items: center;
1267
1276
  gap: var(--space-2);
1268
1277
  font-weight: 500;
1269
- color: hsl(var(--success));
1278
+ /* Explicit green for success - readable on white */
1279
+ color: #16a34a !important;
1280
+ }
1281
+
1282
+ /* Completion header - dark mode */
1283
+ .sui-root.dark .sui-completion-header {
1284
+ color: #22c55e !important;
1270
1285
  }
1271
1286
 
1272
1287
  .sui-completion-components {
@@ -1278,48 +1293,81 @@
1278
1293
 
1279
1294
  .sui-completion-tag {
1280
1295
  padding: 0.125rem var(--space-2);
1281
- background: hsl(var(--info) / 0.15);
1282
- color: hsl(var(--info));
1296
+ /* Explicit blue colors - readable tag styling */
1297
+ background: #eff6ff !important;
1298
+ color: #2563eb !important;
1283
1299
  border-radius: var(--radius-full);
1284
1300
  font-size: 0.75rem;
1285
1301
  font-family: var(--font-mono);
1286
1302
  }
1287
1303
 
1304
+ /* Completion tag - dark mode */
1305
+ .sui-root.dark .sui-completion-tag {
1306
+ background: #1e3a5f !important;
1307
+ color: #60a5fa !important;
1308
+ }
1309
+
1288
1310
  .sui-completion-metrics {
1289
1311
  display: flex;
1290
1312
  gap: var(--space-4);
1291
1313
  margin-top: var(--space-3);
1292
1314
  font-size: 0.8125rem;
1293
- color: hsl(var(--muted-foreground));
1315
+ /* Explicit muted gray */
1316
+ color: #71717a !important;
1317
+ }
1318
+
1319
+ /* Completion metrics - dark mode */
1320
+ .sui-root.dark .sui-completion-metrics {
1321
+ color: #a1a1aa !important;
1294
1322
  }
1295
1323
 
1296
1324
  /* Fallback story styling (error placeholder was created) */
1297
1325
  .sui-completion-fallback .sui-completion-header {
1298
- color: hsl(var(--warning, 38 92% 50%));
1326
+ color: #ca8a04 !important; /* Amber/warning color */
1327
+ }
1328
+
1329
+ .sui-root.dark .sui-completion-fallback .sui-completion-header {
1330
+ color: #facc15 !important; /* Lighter amber for dark mode */
1299
1331
  }
1300
1332
 
1301
1333
  .sui-completion-fallback-warning {
1302
1334
  margin-top: var(--space-2);
1303
1335
  padding: var(--space-2) var(--space-3);
1304
- background: hsl(var(--warning, 38 92% 50%) / 0.15);
1336
+ background: #fef9c3 !important; /* Light amber background */
1305
1337
  border-radius: var(--radius-md);
1306
1338
  font-size: 0.8125rem;
1307
1339
  }
1308
1340
 
1341
+ .sui-root.dark .sui-completion-fallback-warning {
1342
+ background: #422006 !important; /* Dark amber background */
1343
+ }
1344
+
1309
1345
  .sui-completion-fallback-warning strong {
1310
1346
  display: block;
1311
- color: hsl(var(--warning, 38 92% 50%));
1347
+ color: #ca8a04 !important; /* Amber text */
1312
1348
  margin-bottom: var(--space-1);
1313
1349
  }
1314
1350
 
1351
+ .sui-root.dark .sui-completion-fallback-warning strong {
1352
+ color: #facc15 !important;
1353
+ }
1354
+
1315
1355
  .sui-completion-fallback-warning p {
1316
1356
  margin: 0;
1317
- color: hsl(var(--muted-foreground));
1357
+ color: #71717a !important; /* Muted gray */
1358
+ }
1359
+
1360
+ .sui-root.dark .sui-completion-fallback-warning p {
1361
+ color: #a1a1aa !important;
1318
1362
  }
1319
1363
 
1320
1364
  /* Error completion styling (generation failed completely) */
1321
1365
  .sui-completion-error .sui-completion-header {
1322
- color: hsl(var(--destructive));
1366
+ color: #dc2626 !important; /* Red for errors */
1367
+ }
1368
+
1369
+ .sui-root.dark .sui-completion-error .sui-completion-header {
1370
+ color: #f87171 !important; /* Lighter red for dark mode */
1323
1371
  }
1324
1372
 
1325
1373
  /* ============================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpitre/story-ui",
3
- "version": "4.6.1",
3
+ "version": "4.6.3",
4
4
  "description": "AI-powered Storybook story generator with dynamic component discovery",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1248,6 +1248,7 @@
1248
1248
 
1249
1249
  /* ============================================
1250
1250
  Completion Card - shares bubble styling with message bubbles
1251
+ Uses explicit colors with !important to prevent design system overrides
1251
1252
  ============================================ */
1252
1253
  .sui-completion {
1253
1254
  max-width: 85%;
@@ -1256,9 +1257,17 @@
1256
1257
  border-bottom-left-radius: var(--radius-sm);
1257
1258
  font-size: 0.9375rem;
1258
1259
  line-height: 1.6;
1259
- border: 1px solid hsl(var(--border));
1260
- background: hsl(var(--card));
1261
- color: hsl(var(--foreground));
1260
+ /* Explicit light mode colors */
1261
+ background: #ffffff !important;
1262
+ color: #18181b !important;
1263
+ border: 1px solid #e4e4e7 !important;
1264
+ }
1265
+
1266
+ /* Completion card - dark mode */
1267
+ .sui-root.dark .sui-completion {
1268
+ background: #27272a !important;
1269
+ color: #fafafa !important;
1270
+ border: 1px solid #3f3f46 !important;
1262
1271
  }
1263
1272
 
1264
1273
  .sui-completion-header {
@@ -1266,7 +1275,13 @@
1266
1275
  align-items: center;
1267
1276
  gap: var(--space-2);
1268
1277
  font-weight: 500;
1269
- color: hsl(var(--success));
1278
+ /* Explicit green for success - readable on white */
1279
+ color: #16a34a !important;
1280
+ }
1281
+
1282
+ /* Completion header - dark mode */
1283
+ .sui-root.dark .sui-completion-header {
1284
+ color: #22c55e !important;
1270
1285
  }
1271
1286
 
1272
1287
  .sui-completion-components {
@@ -1278,48 +1293,81 @@
1278
1293
 
1279
1294
  .sui-completion-tag {
1280
1295
  padding: 0.125rem var(--space-2);
1281
- background: hsl(var(--info) / 0.15);
1282
- color: hsl(var(--info));
1296
+ /* Explicit blue colors - readable tag styling */
1297
+ background: #eff6ff !important;
1298
+ color: #2563eb !important;
1283
1299
  border-radius: var(--radius-full);
1284
1300
  font-size: 0.75rem;
1285
1301
  font-family: var(--font-mono);
1286
1302
  }
1287
1303
 
1304
+ /* Completion tag - dark mode */
1305
+ .sui-root.dark .sui-completion-tag {
1306
+ background: #1e3a5f !important;
1307
+ color: #60a5fa !important;
1308
+ }
1309
+
1288
1310
  .sui-completion-metrics {
1289
1311
  display: flex;
1290
1312
  gap: var(--space-4);
1291
1313
  margin-top: var(--space-3);
1292
1314
  font-size: 0.8125rem;
1293
- color: hsl(var(--muted-foreground));
1315
+ /* Explicit muted gray */
1316
+ color: #71717a !important;
1317
+ }
1318
+
1319
+ /* Completion metrics - dark mode */
1320
+ .sui-root.dark .sui-completion-metrics {
1321
+ color: #a1a1aa !important;
1294
1322
  }
1295
1323
 
1296
1324
  /* Fallback story styling (error placeholder was created) */
1297
1325
  .sui-completion-fallback .sui-completion-header {
1298
- color: hsl(var(--warning, 38 92% 50%));
1326
+ color: #ca8a04 !important; /* Amber/warning color */
1327
+ }
1328
+
1329
+ .sui-root.dark .sui-completion-fallback .sui-completion-header {
1330
+ color: #facc15 !important; /* Lighter amber for dark mode */
1299
1331
  }
1300
1332
 
1301
1333
  .sui-completion-fallback-warning {
1302
1334
  margin-top: var(--space-2);
1303
1335
  padding: var(--space-2) var(--space-3);
1304
- background: hsl(var(--warning, 38 92% 50%) / 0.15);
1336
+ background: #fef9c3 !important; /* Light amber background */
1305
1337
  border-radius: var(--radius-md);
1306
1338
  font-size: 0.8125rem;
1307
1339
  }
1308
1340
 
1341
+ .sui-root.dark .sui-completion-fallback-warning {
1342
+ background: #422006 !important; /* Dark amber background */
1343
+ }
1344
+
1309
1345
  .sui-completion-fallback-warning strong {
1310
1346
  display: block;
1311
- color: hsl(var(--warning, 38 92% 50%));
1347
+ color: #ca8a04 !important; /* Amber text */
1312
1348
  margin-bottom: var(--space-1);
1313
1349
  }
1314
1350
 
1351
+ .sui-root.dark .sui-completion-fallback-warning strong {
1352
+ color: #facc15 !important;
1353
+ }
1354
+
1315
1355
  .sui-completion-fallback-warning p {
1316
1356
  margin: 0;
1317
- color: hsl(var(--muted-foreground));
1357
+ color: #71717a !important; /* Muted gray */
1358
+ }
1359
+
1360
+ .sui-root.dark .sui-completion-fallback-warning p {
1361
+ color: #a1a1aa !important;
1318
1362
  }
1319
1363
 
1320
1364
  /* Error completion styling (generation failed completely) */
1321
1365
  .sui-completion-error .sui-completion-header {
1322
- color: hsl(var(--destructive));
1366
+ color: #dc2626 !important; /* Red for errors */
1367
+ }
1368
+
1369
+ .sui-root.dark .sui-completion-error .sui-completion-header {
1370
+ color: #f87171 !important; /* Lighter red for dark mode */
1323
1371
  }
1324
1372
 
1325
1373
  /* ============================================