@tpitre/story-ui 4.6.2 → 4.7.0

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.
Files changed (29) hide show
  1. package/dist/story-generator/enhancedComponentDiscovery.d.ts +6 -1
  2. package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
  3. package/dist/story-generator/enhancedComponentDiscovery.js +62 -13
  4. package/dist/story-generator/framework-adapters/angular-adapter.d.ts +9 -0
  5. package/dist/story-generator/framework-adapters/angular-adapter.d.ts.map +1 -1
  6. package/dist/story-generator/framework-adapters/angular-adapter.js +54 -0
  7. package/dist/story-generator/framework-adapters/base-adapter.d.ts +11 -1
  8. package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -1
  9. package/dist/story-generator/framework-adapters/base-adapter.js +44 -5
  10. package/dist/story-generator/framework-adapters/index.d.ts.map +1 -1
  11. package/dist/story-generator/framework-adapters/index.js +5 -1
  12. package/dist/story-generator/framework-adapters/react-adapter.d.ts +9 -0
  13. package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -1
  14. package/dist/story-generator/framework-adapters/react-adapter.js +46 -0
  15. package/dist/story-generator/framework-adapters/svelte-adapter.d.ts +9 -0
  16. package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -1
  17. package/dist/story-generator/framework-adapters/svelte-adapter.js +58 -0
  18. package/dist/story-generator/framework-adapters/vue-adapter.d.ts +9 -0
  19. package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -1
  20. package/dist/story-generator/framework-adapters/vue-adapter.js +74 -0
  21. package/dist/story-generator/framework-adapters/web-components-adapter.d.ts +13 -0
  22. package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -1
  23. package/dist/story-generator/framework-adapters/web-components-adapter.js +80 -0
  24. package/dist/story-generator/promptGenerator.d.ts +6 -0
  25. package/dist/story-generator/promptGenerator.d.ts.map +1 -1
  26. package/dist/story-generator/promptGenerator.js +41 -4
  27. package/dist/templates/StoryUI/StoryUIPanel.css +60 -12
  28. package/package.json +1 -1
  29. package/templates/StoryUI/StoryUIPanel.css +60 -12
@@ -16,7 +16,12 @@ export declare class EnhancedComponentDiscovery {
16
16
  private config;
17
17
  private discoveredComponents;
18
18
  private validateAvailableComponents;
19
+ private frameworkAdapter;
19
20
  constructor(config: StoryUIConfig);
21
+ /**
22
+ * Create the appropriate framework adapter based on config
23
+ */
24
+ private createFrameworkAdapter;
20
25
  /**
21
26
  * Discover components from all available sources
22
27
  * Priority: 1. Dynamic Discovery 2. Static Lists 3. Manual Config
@@ -76,7 +81,7 @@ export declare class EnhancedComponentDiscovery {
76
81
  /**
77
82
  * Extract component name from file
78
83
  */
79
- private extractComponentName;
84
+ private extractComponentNames;
80
85
  /**
81
86
  * Extract props from file content
82
87
  */
@@ -1 +1 @@
1
- {"version":3,"file":"enhancedComponentDiscovery.d.ts","sourceRoot":"","sources":["../../story-generator/enhancedComponentDiscovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,iBAAiB,GAAG,YAAY,CAAC;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,oBAAoB,CAA6C;IACzE,OAAO,CAAC,2BAA2B,CAA0B;gBAEjD,MAAM,EAAE,aAAa;IAIjC;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA2CjD;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAyCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAWvB;;GAED;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IA6GvB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA6B9B;;KAEC;YACW,sBAAsB;IAgGpC;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAoRtC;;OAEG;YACW,sBAAsB;IAsCpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA6B1B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0B5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiBpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;OAEG;YACW,0BAA0B;IAmCxC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAcnC;;OAEG;YACW,sBAAsB;IAMpC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA4CjC;;OAEG;IACG,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC,CAAC;IAwCF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAwC5B;;OAEG;IACH,0BAA0B,IAAI,MAAM,EAAE;CAMvC"}
1
+ {"version":3,"file":"enhancedComponentDiscovery.d.ts","sourceRoot":"","sources":["../../story-generator/enhancedComponentDiscovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAWtD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,iBAAiB,GAAG,YAAY,CAAC;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,oBAAoB,CAA6C;IACzE,OAAO,CAAC,2BAA2B,CAA0B;IAC7D,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,MAAM,EAAE,aAAa;IAKjC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA2CjD;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAyCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAWvB;;GAED;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IA6GvB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA6B9B;;KAEC;YACW,sBAAsB;IAgGpC;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAoRtC;;OAEG;YACW,sBAAsB;IA+CpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA6B1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmC7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0B5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAiBpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;OAEG;YACW,0BAA0B;IAmCxC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAcnC;;OAEG;YACW,sBAAsB;IAMpC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA4CjC;;OAEG;IACG,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC,CAAC;IAwCF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAwC5B;;OAEG;IACH,0BAA0B,IAAI,MAAM,EAAE;CAMvC"}
@@ -2,11 +2,36 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { DynamicPackageDiscovery } from './dynamicPackageDiscovery.js';
4
4
  import { logger } from './logger.js';
5
+ import { ReactAdapter } from './framework-adapters/react-adapter.js';
6
+ import { VueAdapter } from './framework-adapters/vue-adapter.js';
7
+ import { AngularAdapter } from './framework-adapters/angular-adapter.js';
8
+ import { SvelteAdapter } from './framework-adapters/svelte-adapter.js';
9
+ import { WebComponentsAdapter } from './framework-adapters/web-components-adapter.js';
5
10
  export class EnhancedComponentDiscovery {
6
11
  constructor(config) {
7
12
  this.discoveredComponents = new Map();
8
13
  this.validateAvailableComponents = new Set();
9
14
  this.config = config;
15
+ this.frameworkAdapter = this.createFrameworkAdapter();
16
+ }
17
+ /**
18
+ * Create the appropriate framework adapter based on config
19
+ */
20
+ createFrameworkAdapter() {
21
+ const framework = (this.config.componentFramework || 'react');
22
+ switch (framework) {
23
+ case 'vue':
24
+ return new VueAdapter();
25
+ case 'angular':
26
+ return new AngularAdapter();
27
+ case 'svelte':
28
+ return new SvelteAdapter();
29
+ case 'web-components':
30
+ return new WebComponentsAdapter();
31
+ case 'react':
32
+ default:
33
+ return new ReactAdapter();
34
+ }
10
35
  }
11
36
  /**
12
37
  * Discover components from all available sources
@@ -609,15 +634,22 @@ export class EnhancedComponentDiscovery {
609
634
  if (!fs.existsSync(source.path)) {
610
635
  return;
611
636
  }
612
- const files = this.findComponentFiles(source.path, source.patterns || ['*.tsx', '*.jsx']);
637
+ // Use adapter's file patterns if source doesn't specify patterns
638
+ const defaultPatterns = this.frameworkAdapter.getComponentFilePatterns()
639
+ .map(p => p.replace('**/', '')); // Convert glob to simpler patterns
640
+ const files = this.findComponentFiles(source.path, source.patterns || defaultPatterns);
613
641
  for (const file of files) {
614
642
  // Skip story files, test files, and other non-component files
615
643
  if (this.isNonComponentFile(file)) {
616
644
  continue;
617
645
  }
618
646
  const content = fs.readFileSync(file, 'utf-8');
619
- const componentName = this.extractComponentName(file, content);
620
- if (componentName && !this.discoveredComponents.has(componentName)) {
647
+ // Use framework adapter for component extraction
648
+ const componentNames = this.frameworkAdapter.extractComponentNamesFromFile(file, content);
649
+ for (const componentName of componentNames) {
650
+ if (this.discoveredComponents.has(componentName)) {
651
+ continue;
652
+ }
621
653
  // Skip Story UI components and other internal components
622
654
  if (this.shouldSkipComponent(componentName, content)) {
623
655
  continue;
@@ -701,18 +733,35 @@ export class EnhancedComponentDiscovery {
701
733
  /**
702
734
  * Extract component name from file
703
735
  */
704
- extractComponentName(filePath, content) {
705
- // Try to extract from export statements
706
- const exportMatch = content.match(/export\s+(default\s+)?(function|const|class)\s+([A-Z][A-Za-z0-9]*)/);
707
- if (exportMatch) {
708
- return exportMatch[3];
736
+ extractComponentNames(filePath, content) {
737
+ const names = new Set();
738
+ // 1. Check for inline exports: export function/const/class Name
739
+ const inlineExportRegex = /export\s+(default\s+)?(function|const|class)\s+([A-Z][A-Za-z0-9]*)/g;
740
+ let match;
741
+ while ((match = inlineExportRegex.exec(content)) !== null) {
742
+ names.add(match[3]);
743
+ }
744
+ // 2. Check for grouped exports: export { Name1, Name2 }
745
+ const groupedExportRegex = /export\s*\{\s*([^}]+)\s*\}/g;
746
+ while ((match = groupedExportRegex.exec(content)) !== null) {
747
+ const exports = match[1].split(',');
748
+ for (const exp of exports) {
749
+ // Handle "Name" or "Name as Alias" - we want the original name
750
+ const namePart = exp.trim().split(/\s+as\s+/)[0].trim();
751
+ // Only include PascalCase names (components start with uppercase)
752
+ if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
753
+ names.add(namePart);
754
+ }
755
+ }
709
756
  }
710
- // Try to extract from file name
711
- const fileName = path.basename(filePath, path.extname(filePath));
712
- if (fileName !== 'index' && /^[A-Z]/.test(fileName)) {
713
- return fileName;
757
+ // 3. Fallback to filename if no exports found
758
+ if (names.size === 0) {
759
+ const fileName = path.basename(filePath, path.extname(filePath));
760
+ if (fileName !== 'index' && /^[A-Z]/.test(fileName)) {
761
+ names.add(fileName);
762
+ }
714
763
  }
715
- return null;
764
+ return Array.from(names);
716
765
  }
717
766
  /**
718
767
  * Extract props from file content
@@ -13,6 +13,15 @@ export declare class AngularAdapter extends BaseFrameworkAdapter {
13
13
  readonly name = "Angular";
14
14
  readonly supportedStoryFrameworks: StoryFramework[];
15
15
  readonly defaultExtension = ".stories.ts";
16
+ /**
17
+ * Get glob patterns for Angular component files
18
+ */
19
+ getComponentFilePatterns(): string[];
20
+ /**
21
+ * Extract component names from an Angular source file.
22
+ * Handles @Component decorators and NgModule exports.
23
+ */
24
+ extractComponentNamesFromFile(filePath: string, content: string): string[];
16
25
  generateSystemPrompt(config: StoryUIConfig, options?: StoryGenerationOptions): string;
17
26
  generateExamples(config: StoryUIConfig): string;
18
27
  generateSampleStory(config: StoryUIConfig, components: DiscoveredComponent[]): string;
@@ -1 +1 @@
1
- {"version":3,"file":"angular-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/angular-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,cAAe,SAAQ,oBAAoB;IACtD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAa;IACzC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAuJT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAsL/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqDT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA4B1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAkBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA+CrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAErD"}
1
+ {"version":3,"file":"angular-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/angular-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,cAAe,SAAQ,oBAAoB;IACtD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAa;IACzC,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C;;OAEG;IACH,wBAAwB,IAAI,MAAM,EAAE;IAIpC;;;OAGG;IACH,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAmD1E,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAuJT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAsL/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqDT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA4B1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAkBzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA+CrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAErD"}
@@ -16,6 +16,60 @@ export class AngularAdapter extends BaseFrameworkAdapter {
16
16
  ];
17
17
  this.defaultExtension = '.stories.ts';
18
18
  }
19
+ /**
20
+ * Get glob patterns for Angular component files
21
+ */
22
+ getComponentFilePatterns() {
23
+ return ['**/*.component.ts', '**/*.ts'];
24
+ }
25
+ /**
26
+ * Extract component names from an Angular source file.
27
+ * Handles @Component decorators and NgModule exports.
28
+ */
29
+ extractComponentNamesFromFile(filePath, content) {
30
+ const names = new Set();
31
+ // Pattern 1: @Component decorator with class
32
+ // @Component({ selector: 'app-name' }) export class NameComponent
33
+ const componentRegex = /@Component\s*\(\s*\{[\s\S]*?\}\s*\)\s*export\s+class\s+(\w+)/g;
34
+ let match;
35
+ while ((match = componentRegex.exec(content)) !== null) {
36
+ names.add(match[1]);
37
+ }
38
+ // Pattern 2: NgModule exports array - for barrel files
39
+ const exportsArrayRegex = /exports\s*:\s*\[([\s\S]*?)\]/g;
40
+ while ((match = exportsArrayRegex.exec(content)) !== null) {
41
+ const exportsContent = match[1];
42
+ const componentNames = exportsContent
43
+ .split(',')
44
+ .map(item => item.trim())
45
+ .filter(item => item && !item.startsWith('//') && /^[A-Z]/.test(item));
46
+ componentNames.forEach(name => names.add(name));
47
+ }
48
+ // Pattern 3: Named exports from barrel files
49
+ // export { NameComponent } from './name.component'
50
+ const namedExportRegex = /export\s*\{\s*([^}]+)\s*\}\s*from\s*['"`]([^'"`]+)['"`]/g;
51
+ while ((match = namedExportRegex.exec(content)) !== null) {
52
+ const exports = match[1].split(',');
53
+ for (const exp of exports) {
54
+ const namePart = exp.trim().split(/\s+as\s+/).pop()?.trim() || '';
55
+ if (/^[A-Z][A-Za-z0-9]*(?:Component)?$/.test(namePart)) {
56
+ names.add(namePart);
57
+ }
58
+ }
59
+ }
60
+ // Pattern 4: export * from './path' - track for further resolution
61
+ // (handled at discovery level, not here)
62
+ // Filter out non-components (services, modules, etc.)
63
+ const filteredNames = Array.from(names).filter(name => {
64
+ // Keep if ends with Component or doesn't end with Service/Module/Directive/Pipe
65
+ return name.endsWith('Component') ||
66
+ (!name.endsWith('Service') &&
67
+ !name.endsWith('Module') &&
68
+ !name.endsWith('Directive') &&
69
+ !name.endsWith('Pipe'));
70
+ });
71
+ return filteredNames;
72
+ }
19
73
  generateSystemPrompt(config, options) {
20
74
  if (config.systemPrompt) {
21
75
  return config.systemPrompt;
@@ -16,6 +16,16 @@ export declare abstract class BaseFrameworkAdapter implements FrameworkAdapter {
16
16
  abstract readonly name: string;
17
17
  abstract readonly supportedStoryFrameworks: StoryFramework[];
18
18
  abstract readonly defaultExtension: string;
19
+ /**
20
+ * Get glob patterns for component files in this framework.
21
+ * Used by component discovery to find relevant files.
22
+ */
23
+ abstract getComponentFilePatterns(): string[];
24
+ /**
25
+ * Extract component names from a source file.
26
+ * Framework-specific implementation to detect component exports.
27
+ */
28
+ abstract extractComponentNamesFromFile(filePath: string, content: string): string[];
19
29
  /**
20
30
  * Generate the system prompt for this framework
21
31
  */
@@ -69,7 +79,7 @@ export declare abstract class BaseFrameworkAdapter implements FrameworkAdapter {
69
79
  */
70
80
  protected log(message: string, data?: Record<string, unknown>): void;
71
81
  /**
72
- * Get common story structure rules
82
+ * Get common story structure rules including MANDATORY spacing
73
83
  */
74
84
  protected getCommonRules(): string;
75
85
  }
@@ -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;;;OAGG;IACH,QAAQ,CAAC,wBAAwB,IAAI,MAAM,EAAE;IAE7C;;;OAGG;IACH,QAAQ,CAAC,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAEnF;;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 || {
@@ -13,6 +13,15 @@ export declare class ReactAdapter extends BaseFrameworkAdapter {
13
13
  readonly name = "React";
14
14
  readonly supportedStoryFrameworks: StoryFramework[];
15
15
  readonly defaultExtension = ".stories.tsx";
16
+ /**
17
+ * Get glob patterns for React component files
18
+ */
19
+ getComponentFilePatterns(): string[];
20
+ /**
21
+ * Extract component names from a React source file.
22
+ * Handles both inline exports and grouped exports.
23
+ */
24
+ extractComponentNamesFromFile(filePath: string, content: string): string[];
16
25
  generateSystemPrompt(config: StoryUIConfig, options?: StoryGenerationOptions): string;
17
26
  /**
18
27
  * FIX #2: Detect if the project uses Chakra UI v3
@@ -1 +1 @@
1
- {"version":3,"file":"react-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/react-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,YAAa,SAAQ,oBAAoB;IACpD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAW;IACvC,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAIjD;IACF,QAAQ,CAAC,gBAAgB,kBAAkB;IAE3C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA+GT;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAkE/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA0B1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA4BzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA2BrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD"}
1
+ {"version":3,"file":"react-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/react-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,YAAa,SAAQ,oBAAoB;IACpD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAW;IACvC,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAIjD;IACF,QAAQ,CAAC,gBAAgB,kBAAkB;IAE3C;;OAEG;IACH,wBAAwB,IAAI,MAAM,EAAE;IAIpC;;;OAGG;IACH,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAyC1E,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA+GT;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAkE/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IA0B1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA4BzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CA2BrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD"}
@@ -4,6 +4,7 @@
4
4
  * Generates Storybook stories for React components.
5
5
  * Supports CSF 3.0 format with TypeScript.
6
6
  */
7
+ import * as path from 'path';
7
8
  import { BaseFrameworkAdapter } from './base-adapter.js';
8
9
  export class ReactAdapter extends BaseFrameworkAdapter {
9
10
  constructor() {
@@ -17,6 +18,51 @@ export class ReactAdapter extends BaseFrameworkAdapter {
17
18
  ];
18
19
  this.defaultExtension = '.stories.tsx';
19
20
  }
21
+ /**
22
+ * Get glob patterns for React component files
23
+ */
24
+ getComponentFilePatterns() {
25
+ return ['**/*.tsx', '**/*.jsx', '**/*.ts', '**/*.js'];
26
+ }
27
+ /**
28
+ * Extract component names from a React source file.
29
+ * Handles both inline exports and grouped exports.
30
+ */
31
+ extractComponentNamesFromFile(filePath, content) {
32
+ const names = new Set();
33
+ // 1. Check for inline exports: export function/const/class Name
34
+ const inlineExportRegex = /export\s+(default\s+)?(function|const|class)\s+([A-Z][A-Za-z0-9]*)/g;
35
+ let match;
36
+ while ((match = inlineExportRegex.exec(content)) !== null) {
37
+ names.add(match[3]);
38
+ }
39
+ // 2. Check for grouped exports: export { Name1, Name2 }
40
+ const groupedExportRegex = /export\s*\{\s*([^}]+)\s*\}/g;
41
+ while ((match = groupedExportRegex.exec(content)) !== null) {
42
+ const exports = match[1].split(',');
43
+ for (const exp of exports) {
44
+ // Handle "Name" or "Name as Alias" - we want the original name
45
+ const namePart = exp.trim().split(/\s+as\s+/)[0].trim();
46
+ // Only include PascalCase names (components start with uppercase)
47
+ if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
48
+ names.add(namePart);
49
+ }
50
+ }
51
+ }
52
+ // 3. Check for React.forwardRef patterns
53
+ const forwardRefRegex = /export\s+const\s+([A-Z][A-Za-z0-9]*)\s*=\s*(?:React\.)?forwardRef/g;
54
+ while ((match = forwardRefRegex.exec(content)) !== null) {
55
+ names.add(match[1]);
56
+ }
57
+ // 4. Fallback to filename if no exports found
58
+ if (names.size === 0) {
59
+ const fileName = path.basename(filePath, path.extname(filePath));
60
+ if (fileName !== 'index' && /^[A-Z]/.test(fileName)) {
61
+ names.add(fileName);
62
+ }
63
+ }
64
+ return Array.from(names);
65
+ }
20
66
  generateSystemPrompt(config, options) {
21
67
  if (config.systemPrompt) {
22
68
  return config.systemPrompt;
@@ -13,6 +13,15 @@ export declare class SvelteAdapter extends BaseFrameworkAdapter {
13
13
  readonly name = "Svelte";
14
14
  readonly supportedStoryFrameworks: StoryFramework[];
15
15
  readonly defaultExtension = ".stories.svelte";
16
+ /**
17
+ * Get glob patterns for Svelte component files
18
+ */
19
+ getComponentFilePatterns(): string[];
20
+ /**
21
+ * Extract component names from a Svelte source file.
22
+ * Handles .svelte files and barrel exports.
23
+ */
24
+ extractComponentNamesFromFile(filePath: string, content: string): string[];
16
25
  generateSystemPrompt(config: StoryUIConfig, options?: StoryGenerationOptions): string;
17
26
  generateExamples(config: StoryUIConfig): string;
18
27
  generateSampleStory(config: StoryUIConfig, components: DiscoveredComponent[]): string;
@@ -1 +1 @@
1
- {"version":3,"file":"svelte-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/svelte-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,aAAc,SAAQ,oBAAoB;IACrD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAY;IACxC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,qBAAqB;IAE9C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAgJT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IA2H/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqCT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAmB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA8HzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IA2CpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAWV;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD"}
1
+ {"version":3,"file":"svelte-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/svelte-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,aAAc,SAAQ,oBAAoB;IACrD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAY;IACxC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,qBAAqB;IAE9C;;OAEG;IACH,wBAAwB,IAAI,MAAM,EAAE;IAIpC;;;OAGG;IACH,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAoD1E,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IAgJT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IA2H/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IAqCT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAmB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA8HzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IA2CpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAWV;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD"}
@@ -4,6 +4,7 @@
4
4
  * Generates Storybook stories for Svelte components.
5
5
  * Supports both Svelte 4 and Svelte 5 (runes).
6
6
  */
7
+ import * as path from 'path';
7
8
  import { BaseFrameworkAdapter } from './base-adapter.js';
8
9
  export class SvelteAdapter extends BaseFrameworkAdapter {
9
10
  constructor() {
@@ -16,6 +17,63 @@ export class SvelteAdapter extends BaseFrameworkAdapter {
16
17
  ];
17
18
  this.defaultExtension = '.stories.svelte';
18
19
  }
20
+ /**
21
+ * Get glob patterns for Svelte component files
22
+ */
23
+ getComponentFilePatterns() {
24
+ return ['**/*.svelte', '**/*.ts', '**/*.js'];
25
+ }
26
+ /**
27
+ * Extract component names from a Svelte source file.
28
+ * Handles .svelte files and barrel exports.
29
+ */
30
+ extractComponentNamesFromFile(filePath, content) {
31
+ const names = new Set();
32
+ // For .svelte files, derive name from filename
33
+ if (filePath.endsWith('.svelte')) {
34
+ const fileName = path.basename(filePath, '.svelte');
35
+ // Skip SvelteKit special files
36
+ if (fileName.startsWith('+')) {
37
+ return [];
38
+ }
39
+ // If already PascalCase, use as-is; otherwise convert kebab-case/snake_case
40
+ if (/^[A-Z][a-zA-Z0-9]*$/.test(fileName)) {
41
+ names.add(fileName);
42
+ }
43
+ else {
44
+ // Convert kebab-case or snake_case to PascalCase
45
+ const pascalName = fileName
46
+ .split(/[-_]/)
47
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
48
+ .join('');
49
+ if (/^[A-Z]/.test(pascalName)) {
50
+ names.add(pascalName);
51
+ }
52
+ }
53
+ return Array.from(names);
54
+ }
55
+ // For .ts/.js barrel files
56
+ // Pattern: export { default as ComponentName } from './Component.svelte'
57
+ const barrelExportRegex = /export\s*\{\s*default\s+as\s+([A-Z][a-zA-Z0-9]*)\s*\}\s*from\s*['"`]([^'"`]+\.svelte)['"`]/g;
58
+ let match;
59
+ while ((match = barrelExportRegex.exec(content)) !== null) {
60
+ names.add(match[1]);
61
+ }
62
+ // Pattern: export { ComponentName } from './path'
63
+ const namedExportRegex = /export\s*\{\s*([^}]+)\s*\}\s*from\s*['"`]([^'"`]+)['"`]/g;
64
+ while ((match = namedExportRegex.exec(content)) !== null) {
65
+ const exports = match[1].split(',');
66
+ for (const exp of exports) {
67
+ const namePart = exp.trim().split(/\s+as\s+/).pop()?.trim() || '';
68
+ if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
69
+ names.add(namePart);
70
+ }
71
+ }
72
+ }
73
+ // Pattern: export * from './Component.svelte'
74
+ // These need to be resolved at discovery level
75
+ return Array.from(names);
76
+ }
19
77
  generateSystemPrompt(config, options) {
20
78
  if (config.systemPrompt) {
21
79
  return config.systemPrompt;
@@ -13,6 +13,15 @@ export declare class VueAdapter extends BaseFrameworkAdapter {
13
13
  readonly name = "Vue";
14
14
  readonly supportedStoryFrameworks: StoryFramework[];
15
15
  readonly defaultExtension = ".stories.ts";
16
+ /**
17
+ * Get glob patterns for Vue component files
18
+ */
19
+ getComponentFilePatterns(): string[];
20
+ /**
21
+ * Extract component names from a Vue source file.
22
+ * Handles .vue SFCs and barrel files.
23
+ */
24
+ extractComponentNamesFromFile(filePath: string, content: string): string[];
16
25
  generateSystemPrompt(config: StoryUIConfig, options?: StoryGenerationOptions): string;
17
26
  generateExamples(config: StoryUIConfig): string;
18
27
  generateSampleStory(config: StoryUIConfig, components: DiscoveredComponent[]): string;
@@ -1 +1 @@
1
- {"version":3,"file":"vue-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/vue-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,UAAW,SAAQ,oBAAoB;IAClD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAS;IACrC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAIjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA+FT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAuH/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA8CzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAuBrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAE7C"}
1
+ {"version":3,"file":"vue-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/vue-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,UAAW,SAAQ,oBAAoB;IAClD,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAS;IACrC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAIjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C;;OAEG;IACH,wBAAwB,IAAI,MAAM,EAAE;IAIpC;;;OAGG;IACH,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAkE1E,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA+FT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IAuH/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA4CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IA8CzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAuBrE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAE7C"}
@@ -4,6 +4,7 @@
4
4
  * Generates Storybook stories for Vue 3 components.
5
5
  * Supports Composition API and Options API.
6
6
  */
7
+ import * as path from 'path';
7
8
  import { BaseFrameworkAdapter } from './base-adapter.js';
8
9
  export class VueAdapter extends BaseFrameworkAdapter {
9
10
  constructor() {
@@ -17,6 +18,79 @@ export class VueAdapter extends BaseFrameworkAdapter {
17
18
  ];
18
19
  this.defaultExtension = '.stories.ts';
19
20
  }
21
+ /**
22
+ * Get glob patterns for Vue component files
23
+ */
24
+ getComponentFilePatterns() {
25
+ return ['**/*.vue', '**/*.ts', '**/*.js'];
26
+ }
27
+ /**
28
+ * Extract component names from a Vue source file.
29
+ * Handles .vue SFCs and barrel files.
30
+ */
31
+ extractComponentNamesFromFile(filePath, content) {
32
+ const names = new Set();
33
+ // For .vue files, derive name from filename or defineComponent name
34
+ if (filePath.endsWith('.vue')) {
35
+ // Try to extract name from defineComponent({ name: 'ComponentName' })
36
+ const defineComponentNameRegex = /defineComponent\s*\(\s*\{[^]*?name\s*:\s*['"`]([A-Z][a-zA-Z0-9]*)['"`]/;
37
+ const nameMatch = content.match(defineComponentNameRegex);
38
+ if (nameMatch) {
39
+ names.add(nameMatch[1]);
40
+ }
41
+ else {
42
+ // Try Options API name property
43
+ const optionsNameRegex = /name\s*:\s*['"`]([A-Z][a-zA-Z0-9]*)['"`]/;
44
+ const optionsMatch = content.match(optionsNameRegex);
45
+ if (optionsMatch) {
46
+ names.add(optionsMatch[1]);
47
+ }
48
+ else {
49
+ // Fallback to filename
50
+ const fileName = path.basename(filePath, '.vue');
51
+ // If already PascalCase, use as-is; otherwise convert kebab-case/snake_case
52
+ if (/^[A-Z][a-zA-Z0-9]*$/.test(fileName)) {
53
+ names.add(fileName);
54
+ }
55
+ else {
56
+ // Convert kebab-case or snake_case to PascalCase
57
+ const pascalName = fileName
58
+ .split(/[-_]/)
59
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
60
+ .join('');
61
+ if (/^[A-Z]/.test(pascalName)) {
62
+ names.add(pascalName);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return Array.from(names);
68
+ }
69
+ // For .ts/.js barrel files, look for re-exports
70
+ // Pattern: export { default as ComponentName } from './Component.vue'
71
+ const barrelExportRegex = /export\s*\{\s*default\s+as\s+([A-Z][a-zA-Z0-9]*)\s*\}\s*from\s*['"`]([^'"`]+\.vue)['"`]/g;
72
+ let match;
73
+ while ((match = barrelExportRegex.exec(content)) !== null) {
74
+ names.add(match[1]);
75
+ }
76
+ // Pattern: export { ComponentName } from './path'
77
+ const namedExportRegex = /export\s*\{\s*([^}]+)\s*\}\s*from\s*['"`]([^'"`]+)['"`]/g;
78
+ while ((match = namedExportRegex.exec(content)) !== null) {
79
+ const exports = match[1].split(',');
80
+ for (const exp of exports) {
81
+ const namePart = exp.trim().split(/\s+as\s+/).pop()?.trim() || '';
82
+ if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
83
+ names.add(namePart);
84
+ }
85
+ }
86
+ }
87
+ // Pattern: export const ComponentName = ...
88
+ const constExportRegex = /export\s+const\s+([A-Z][A-Za-z0-9]*)\s*=/g;
89
+ while ((match = constExportRegex.exec(content)) !== null) {
90
+ names.add(match[1]);
91
+ }
92
+ return Array.from(names);
93
+ }
20
94
  generateSystemPrompt(config, options) {
21
95
  if (config.systemPrompt) {
22
96
  return config.systemPrompt;
@@ -13,6 +13,19 @@ export declare class WebComponentsAdapter extends BaseFrameworkAdapter {
13
13
  readonly name = "Web Components";
14
14
  readonly supportedStoryFrameworks: StoryFramework[];
15
15
  readonly defaultExtension = ".stories.ts";
16
+ /**
17
+ * Get glob patterns for Web Component files
18
+ */
19
+ getComponentFilePatterns(): string[];
20
+ /**
21
+ * Extract component names from a Web Component source file.
22
+ * Handles vanilla customElements.define, Lit @customElement, and Stencil @Component.
23
+ */
24
+ extractComponentNamesFromFile(filePath: string, content: string): string[];
25
+ /**
26
+ * Convert a kebab-case tag name to PascalCase
27
+ */
28
+ private tagToPascalCase;
16
29
  generateSystemPrompt(config: StoryUIConfig, options?: StoryGenerationOptions): string;
17
30
  generateExamples(config: StoryUIConfig): string;
18
31
  generateSampleStory(config: StoryUIConfig, components: DiscoveredComponent[]): string;
@@ -1 +1 @@
1
- {"version":3,"file":"web-components-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/web-components-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,oBAAqB,SAAQ,oBAAoB;IAC5D,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAoB;IAChD,QAAQ,CAAC,IAAI,oBAAoB;IACjC,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA4FT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IA0G/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA8CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAuCzC;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IAiCjC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAwBpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAYV;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,oBAAoB,CAEjE"}
1
+ {"version":3,"file":"web-components-adapter.d.ts","sourceRoot":"","sources":["../../../story-generator/framework-adapters/web-components-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,aAAa,EACb,cAAc,EACd,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,qBAAa,oBAAqB,SAAQ,oBAAoB;IAC5D,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAoB;IAChD,QAAQ,CAAC,IAAI,oBAAoB;IACjC,QAAQ,CAAC,wBAAwB,EAAE,cAAc,EAAE,CAGjD;IACF,QAAQ,CAAC,gBAAgB,iBAAiB;IAE1C;;OAEG;IACH,wBAAwB,IAAI,MAAM,EAAE;IAIpC;;;OAGG;IACH,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAoE1E;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB,oBAAoB,CAClB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM;IA4FT,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM;IA0G/C,mBAAmB,CACjB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,MAAM;IA8CT,gBAAgB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM;IAsB1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAuCzC;;;;;;;;OAQG;IACH,OAAO,CAAC,yBAAyB;IAiCjC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAwBpE;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,mBAAmB,EAAE,EACjC,MAAM,EAAE,aAAa,GACpB,MAAM;CAYV;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,oBAAoB,CAEjE"}
@@ -16,6 +16,86 @@ export class WebComponentsAdapter extends BaseFrameworkAdapter {
16
16
  ];
17
17
  this.defaultExtension = '.stories.ts';
18
18
  }
19
+ /**
20
+ * Get glob patterns for Web Component files
21
+ */
22
+ getComponentFilePatterns() {
23
+ return ['**/*.ts', '**/*.js', '**/custom-elements.json'];
24
+ }
25
+ /**
26
+ * Extract component names from a Web Component source file.
27
+ * Handles vanilla customElements.define, Lit @customElement, and Stencil @Component.
28
+ */
29
+ extractComponentNamesFromFile(filePath, content) {
30
+ const names = new Set();
31
+ // Check for Custom Elements Manifest (preferred)
32
+ if (filePath.endsWith('custom-elements.json')) {
33
+ try {
34
+ const manifest = JSON.parse(content);
35
+ if (manifest.modules) {
36
+ for (const module of manifest.modules) {
37
+ if (module.declarations) {
38
+ for (const declaration of module.declarations) {
39
+ if (declaration.customElement && declaration.tagName) {
40
+ // Convert tag-name to PascalCase
41
+ const pascalName = this.tagToPascalCase(declaration.tagName);
42
+ names.add(pascalName);
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ return Array.from(names);
49
+ }
50
+ catch {
51
+ // Invalid JSON, continue with regex patterns
52
+ }
53
+ }
54
+ // Pattern 1: Vanilla customElements.define('tag-name', ClassName) with named class
55
+ const vanillaDefineNamedRegex = /customElements\.define\(\s*['"]([a-z][\w-]*)['"],\s*([A-Z][A-Za-z0-9]*)\s*[),]/g;
56
+ let match;
57
+ while ((match = vanillaDefineNamedRegex.exec(content)) !== null) {
58
+ names.add(match[2]); // Use the class name
59
+ }
60
+ // Pattern 1b: Vanilla customElements.define('tag-name', class extends...) - inline class
61
+ // For inline classes, convert tag name to PascalCase
62
+ const vanillaDefineInlineRegex = /customElements\.define\(\s*['"]([a-z][\w-]*)['"],\s*class\s+extends/gi;
63
+ while ((match = vanillaDefineInlineRegex.exec(content)) !== null) {
64
+ const pascalName = this.tagToPascalCase(match[1]);
65
+ names.add(pascalName);
66
+ }
67
+ // Pattern 2: Lit @customElement('tag-name') decorator (handles multiline)
68
+ const litDecoratorRegex = /@customElement\(\s*['"]([a-z][\w-]*)['"][^)]*\)[\s\S]*?(?:export\s+)?class\s+([A-Z][A-Za-z0-9]*)/g;
69
+ while ((match = litDecoratorRegex.exec(content)) !== null) {
70
+ names.add(match[2]); // Use the class name
71
+ }
72
+ // Pattern 3: Stencil @Component({ tag: 'tag-name' }) decorator
73
+ const stencilRegex = /@Component\(\s*\{[^}]*tag:\s*['"]([a-z][\w-]*)['"][^}]*\}\s*\)\s*(?:export\s+)?class\s+(\w+)/gi;
74
+ while ((match = stencilRegex.exec(content)) !== null) {
75
+ names.add(match[2]); // Use the class name
76
+ }
77
+ // Pattern 4: Named exports from barrel files
78
+ const namedExportRegex = /export\s*\{\s*([^}]+)\s*\}\s*from\s*['"`]([^'"`]+)['"`]/g;
79
+ while ((match = namedExportRegex.exec(content)) !== null) {
80
+ const exports = match[1].split(',');
81
+ for (const exp of exports) {
82
+ const namePart = exp.trim().split(/\s+as\s+/).pop()?.trim() || '';
83
+ if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
84
+ names.add(namePart);
85
+ }
86
+ }
87
+ }
88
+ return Array.from(names);
89
+ }
90
+ /**
91
+ * Convert a kebab-case tag name to PascalCase
92
+ */
93
+ tagToPascalCase(tagName) {
94
+ return tagName
95
+ .split('-')
96
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
97
+ .join('');
98
+ }
19
99
  generateSystemPrompt(config, options) {
20
100
  if (config.systemPrompt) {
21
101
  return config.systemPrompt;
@@ -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
  /**
@@ -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.2",
3
+ "version": "4.7.0",
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
  /* ============================================