@tpitre/story-ui 4.6.3 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +50 -9
- package/dist/mcp-server/index.js +2 -2
- package/dist/mcp-server/mcp-stdio-server.js +2 -1
- package/dist/mcp-server/routes/components.d.ts.map +1 -1
- package/dist/mcp-server/routes/components.js +12 -10
- package/dist/story-generator/enhancedComponentDiscovery.d.ts +21 -1
- package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
- package/dist/story-generator/enhancedComponentDiscovery.js +210 -14
- package/dist/story-generator/framework-adapters/angular-adapter.d.ts +9 -0
- package/dist/story-generator/framework-adapters/angular-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/angular-adapter.js +54 -0
- package/dist/story-generator/framework-adapters/base-adapter.d.ts +10 -0
- package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/react-adapter.d.ts +9 -0
- package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/react-adapter.js +46 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.d.ts +9 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/svelte-adapter.js +58 -0
- package/dist/story-generator/framework-adapters/vue-adapter.d.ts +9 -0
- package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/vue-adapter.js +74 -0
- package/dist/story-generator/framework-adapters/web-components-adapter.d.ts +13 -0
- package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/web-components-adapter.js +80 -0
- package/dist/story-generator/promptGenerator.d.ts.map +1 -1
- package/dist/story-generator/promptGenerator.js +75 -3
- package/dist/story-ui.config.d.ts +16 -0
- package/dist/story-ui.config.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -30,12 +30,16 @@ program
|
|
|
30
30
|
.description('Start the Story UI server')
|
|
31
31
|
.option('-p, --port <port>', 'Port to run the server on', '4001')
|
|
32
32
|
.option('-c, --config <config>', 'Path to configuration file')
|
|
33
|
+
.option('--mcp', 'Also start MCP stdio server for Claude Desktop integration')
|
|
33
34
|
.action(async (options) => {
|
|
34
|
-
|
|
35
|
+
// Use stderr for all logging to avoid breaking MCP JSON-RPC protocol
|
|
36
|
+
// when Claude Desktop spawns this process
|
|
37
|
+
console.error('🚀 Starting Story UI server...');
|
|
35
38
|
// Use absolute path to avoid dist/dist issue when package is linked
|
|
36
39
|
const pkgRoot = path.resolve(__dirname, '..');
|
|
37
40
|
const serverPath = path.join(pkgRoot, 'mcp-server/index.js');
|
|
38
|
-
|
|
41
|
+
const mcpStdioPath = path.join(pkgRoot, 'mcp-server/mcp-stdio-server.js');
|
|
42
|
+
console.error(`✅ Using HTTP server at: ${serverPath}`);
|
|
39
43
|
// FIRST_EDIT: determine an available port
|
|
40
44
|
const requestedPort = parseInt(options.port || '4001', 10);
|
|
41
45
|
const isPortFree = (port) => {
|
|
@@ -55,7 +59,7 @@ program
|
|
|
55
59
|
finalPort += 1;
|
|
56
60
|
}
|
|
57
61
|
if (finalPort !== requestedPort) {
|
|
58
|
-
console.
|
|
62
|
+
console.error(`⚠️ Port ${requestedPort} is in use. Using ${finalPort} instead.`);
|
|
59
63
|
}
|
|
60
64
|
const env = { ...process.env, PORT: String(finalPort) };
|
|
61
65
|
// Set memory limit to prevent heap exhaustion during vision/image processing
|
|
@@ -66,16 +70,53 @@ program
|
|
|
66
70
|
if (options.config) {
|
|
67
71
|
env.STORY_UI_CONFIG_PATH = options.config;
|
|
68
72
|
}
|
|
73
|
+
// Log the working directory for debugging
|
|
74
|
+
console.error(`📁 Working directory: ${process.cwd()}`);
|
|
75
|
+
// Redirect child stdout to stderr to avoid breaking MCP JSON-RPC protocol
|
|
76
|
+
// when Claude Desktop spawns this process. The HTTP server logs will still
|
|
77
|
+
// be visible but won't interfere with MCP communication.
|
|
69
78
|
const server = spawn('node', [serverPath], {
|
|
70
|
-
stdio: 'inherit',
|
|
71
|
-
env
|
|
79
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
80
|
+
env,
|
|
81
|
+
cwd: process.cwd() // Explicitly pass cwd to ensure config is found
|
|
72
82
|
});
|
|
83
|
+
// Pipe child's stdout to stderr so logs are visible without breaking MCP
|
|
84
|
+
if (server.stdout) {
|
|
85
|
+
server.stdout.pipe(process.stderr);
|
|
86
|
+
}
|
|
73
87
|
server.on('close', (code) => {
|
|
74
|
-
console.
|
|
75
|
-
});
|
|
76
|
-
process.on('SIGINT', () => {
|
|
77
|
-
server.kill('SIGINT');
|
|
88
|
+
console.error(`HTTP server exited with code ${code}`);
|
|
78
89
|
});
|
|
90
|
+
// If --mcp flag is set, also start the MCP stdio server for Claude Desktop
|
|
91
|
+
// This allows a single command to run both HTTP server and MCP protocol handler
|
|
92
|
+
if (options.mcp) {
|
|
93
|
+
console.error('📡 Starting MCP stdio server for Claude Desktop...');
|
|
94
|
+
// Wait a moment for HTTP server to start
|
|
95
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
96
|
+
const mcpEnv = {
|
|
97
|
+
...process.env,
|
|
98
|
+
STORY_UI_HTTP_PORT: String(finalPort)
|
|
99
|
+
};
|
|
100
|
+
// Spawn MCP stdio server with stdin/stdout inherited for JSON-RPC communication
|
|
101
|
+
const mcpServer = spawn('node', [mcpStdioPath], {
|
|
102
|
+
stdio: 'inherit',
|
|
103
|
+
env: mcpEnv,
|
|
104
|
+
cwd: process.cwd() // Explicitly pass cwd to ensure config is found
|
|
105
|
+
});
|
|
106
|
+
mcpServer.on('close', (code) => {
|
|
107
|
+
console.error(`MCP stdio server exited with code ${code}`);
|
|
108
|
+
server.kill('SIGTERM');
|
|
109
|
+
});
|
|
110
|
+
process.on('SIGINT', () => {
|
|
111
|
+
mcpServer.kill('SIGINT');
|
|
112
|
+
server.kill('SIGINT');
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
process.on('SIGINT', () => {
|
|
117
|
+
server.kill('SIGINT');
|
|
118
|
+
});
|
|
119
|
+
}
|
|
79
120
|
});
|
|
80
121
|
program
|
|
81
122
|
.command('config')
|
package/dist/mcp-server/index.js
CHANGED
|
@@ -769,8 +769,8 @@ if (storybookProxyEnabled) {
|
|
|
769
769
|
}
|
|
770
770
|
// Start server
|
|
771
771
|
app.listen(PORT, () => {
|
|
772
|
-
console.
|
|
773
|
-
console.
|
|
772
|
+
console.error(`MCP server running on port ${PORT}`);
|
|
773
|
+
console.error(`Stories will be generated to: ${config.generatedStoriesPath}`);
|
|
774
774
|
}).on('error', (err) => {
|
|
775
775
|
if (err.code === 'EADDRINUSE') {
|
|
776
776
|
console.error(`\n❌ Port ${PORT} is already in use!`);
|
|
@@ -12,7 +12,8 @@ import { fileURLToPath } from 'url';
|
|
|
12
12
|
// Get package version dynamically
|
|
13
13
|
const __filename_mcp = fileURLToPath(import.meta.url);
|
|
14
14
|
const __dirname_mcp = path.dirname(__filename_mcp);
|
|
15
|
-
|
|
15
|
+
// Go up two levels from dist/mcp-server/ to reach the project root
|
|
16
|
+
const packageJsonPath = path.resolve(__dirname_mcp, '../../package.json');
|
|
16
17
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
17
18
|
const PACKAGE_VERSION = packageJson.version;
|
|
18
19
|
// Check for working directory override from environment or command line
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../mcp-server/routes/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAW5C,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,2DAkC9D;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../mcp-server/routes/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAW5C,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,2DAkC9D;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,2DAgDzD"}
|
|
@@ -58,19 +58,21 @@ export async function getProps(req, res) {
|
|
|
58
58
|
// Find the requested component
|
|
59
59
|
const comp = cachedComponents.find(c => c.name === component);
|
|
60
60
|
if (!comp) {
|
|
61
|
-
return res.json(
|
|
61
|
+
return res.json({});
|
|
62
62
|
}
|
|
63
|
-
// Return props
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
// Return props as an object keyed by prop name (for MCP handler compatibility)
|
|
64
|
+
const propsObject = {};
|
|
65
|
+
for (const prop of comp.props) {
|
|
66
|
+
propsObject[prop] = {
|
|
67
|
+
type: 'string', // We'd need more sophisticated type detection
|
|
68
|
+
description: `${prop} property`,
|
|
69
|
+
required: false
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
res.json(propsObject);
|
|
71
73
|
}
|
|
72
74
|
catch (error) {
|
|
73
75
|
console.error('Error getting component props:', error);
|
|
74
|
-
res.json(
|
|
76
|
+
res.json({});
|
|
75
77
|
}
|
|
76
78
|
}
|
|
@@ -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,11 +81,26 @@ export declare class EnhancedComponentDiscovery {
|
|
|
76
81
|
/**
|
|
77
82
|
* Extract component name from file
|
|
78
83
|
*/
|
|
79
|
-
private
|
|
84
|
+
private extractComponentNames;
|
|
80
85
|
/**
|
|
81
86
|
* Extract props from file content
|
|
87
|
+
* Supports multiple patterns:
|
|
88
|
+
* - TypeScript interfaces (interface ButtonProps { variant: ... })
|
|
89
|
+
* - PropTypes (Component.propTypes = { variant: ... })
|
|
90
|
+
* - Function parameter destructuring ({ className, variant, ...props }: Props)
|
|
91
|
+
* - VariantProps from class-variance-authority
|
|
82
92
|
*/
|
|
83
93
|
private extractPropsFromFile;
|
|
94
|
+
/**
|
|
95
|
+
* Extract props from function parameter destructuring patterns
|
|
96
|
+
* Works with React, Vue <script setup>, and other frameworks
|
|
97
|
+
*/
|
|
98
|
+
private extractDestructuredProps;
|
|
99
|
+
/**
|
|
100
|
+
* Extract props from co-located story file (e.g., Button.stories.tsx)
|
|
101
|
+
* This is a fallback for components like shadcn/ui that don't use interface Props patterns
|
|
102
|
+
*/
|
|
103
|
+
private extractPropsFromStoryFile;
|
|
84
104
|
/**
|
|
85
105
|
* Extract slots from content
|
|
86
106
|
*/
|
|
@@ -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;
|
|
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;IAwDpC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA6B1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmC7B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAyD5B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkChC;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IA2EjC;;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,20 +634,35 @@ export class EnhancedComponentDiscovery {
|
|
|
609
634
|
if (!fs.existsSync(source.path)) {
|
|
610
635
|
return;
|
|
611
636
|
}
|
|
612
|
-
|
|
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
|
-
|
|
620
|
-
|
|
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;
|
|
624
656
|
}
|
|
625
|
-
|
|
657
|
+
let props = this.extractPropsFromFile(content);
|
|
658
|
+
// Always check co-located story file for additional props (argTypes, args)
|
|
659
|
+
// Story files often define props that aren't in the component source (e.g., disabled, children)
|
|
660
|
+
const storyProps = this.extractPropsFromStoryFile(file);
|
|
661
|
+
for (const prop of storyProps) {
|
|
662
|
+
if (!props.includes(prop)) {
|
|
663
|
+
props.push(prop);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
626
666
|
this.discoveredComponents.set(componentName, {
|
|
627
667
|
name: componentName,
|
|
628
668
|
filePath: file,
|
|
@@ -701,21 +741,43 @@ export class EnhancedComponentDiscovery {
|
|
|
701
741
|
/**
|
|
702
742
|
* Extract component name from file
|
|
703
743
|
*/
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
744
|
+
extractComponentNames(filePath, content) {
|
|
745
|
+
const names = new Set();
|
|
746
|
+
// 1. Check for inline exports: export function/const/class Name
|
|
747
|
+
const inlineExportRegex = /export\s+(default\s+)?(function|const|class)\s+([A-Z][A-Za-z0-9]*)/g;
|
|
748
|
+
let match;
|
|
749
|
+
while ((match = inlineExportRegex.exec(content)) !== null) {
|
|
750
|
+
names.add(match[3]);
|
|
709
751
|
}
|
|
710
|
-
//
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
752
|
+
// 2. Check for grouped exports: export { Name1, Name2 }
|
|
753
|
+
const groupedExportRegex = /export\s*\{\s*([^}]+)\s*\}/g;
|
|
754
|
+
while ((match = groupedExportRegex.exec(content)) !== null) {
|
|
755
|
+
const exports = match[1].split(',');
|
|
756
|
+
for (const exp of exports) {
|
|
757
|
+
// Handle "Name" or "Name as Alias" - we want the original name
|
|
758
|
+
const namePart = exp.trim().split(/\s+as\s+/)[0].trim();
|
|
759
|
+
// Only include PascalCase names (components start with uppercase)
|
|
760
|
+
if (/^[A-Z][A-Za-z0-9]*$/.test(namePart)) {
|
|
761
|
+
names.add(namePart);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
714
764
|
}
|
|
715
|
-
|
|
765
|
+
// 3. Fallback to filename if no exports found
|
|
766
|
+
if (names.size === 0) {
|
|
767
|
+
const fileName = path.basename(filePath, path.extname(filePath));
|
|
768
|
+
if (fileName !== 'index' && /^[A-Z]/.test(fileName)) {
|
|
769
|
+
names.add(fileName);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return Array.from(names);
|
|
716
773
|
}
|
|
717
774
|
/**
|
|
718
775
|
* Extract props from file content
|
|
776
|
+
* Supports multiple patterns:
|
|
777
|
+
* - TypeScript interfaces (interface ButtonProps { variant: ... })
|
|
778
|
+
* - PropTypes (Component.propTypes = { variant: ... })
|
|
779
|
+
* - Function parameter destructuring ({ className, variant, ...props }: Props)
|
|
780
|
+
* - VariantProps from class-variance-authority
|
|
719
781
|
*/
|
|
720
782
|
extractPropsFromFile(content) {
|
|
721
783
|
const props = [];
|
|
@@ -737,6 +799,140 @@ export class EnhancedComponentDiscovery {
|
|
|
737
799
|
props.push(match[1]);
|
|
738
800
|
}
|
|
739
801
|
}
|
|
802
|
+
// Extract from function parameter destructuring
|
|
803
|
+
// Matches patterns like:
|
|
804
|
+
// function Component({ prop1, prop2, ...rest }: Props)
|
|
805
|
+
// const Component = ({ prop1, prop2 }: Props) =>
|
|
806
|
+
// export function Component({ prop1, prop2 }: React.ComponentProps<"div">)
|
|
807
|
+
const destructuringProps = this.extractDestructuredProps(content);
|
|
808
|
+
for (const prop of destructuringProps) {
|
|
809
|
+
if (!props.includes(prop)) {
|
|
810
|
+
props.push(prop);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
// Extract from VariantProps (class-variance-authority pattern)
|
|
814
|
+
// Matches: VariantProps<typeof buttonVariants>
|
|
815
|
+
const variantPropsMatch = content.match(/VariantProps<typeof\s+(\w+)>/);
|
|
816
|
+
if (variantPropsMatch) {
|
|
817
|
+
const variantsName = variantPropsMatch[1];
|
|
818
|
+
// Look for the cva definition to extract variant names
|
|
819
|
+
const cvaMatch = content.match(new RegExp(`${variantsName}\\s*=\\s*cva\\([^,]+,\\s*{\\s*variants:\\s*{([^}]+(?:{[^}]*}[^}]*)*)}`));
|
|
820
|
+
if (cvaMatch) {
|
|
821
|
+
const variantsContent = cvaMatch[1];
|
|
822
|
+
// Extract variant property names (e.g., variant, size)
|
|
823
|
+
const variantMatches = variantsContent.matchAll(/^\s*(\w+)\s*:\s*{/gm);
|
|
824
|
+
for (const match of variantMatches) {
|
|
825
|
+
if (!props.includes(match[1])) {
|
|
826
|
+
props.push(match[1]);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return props;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Extract props from function parameter destructuring patterns
|
|
835
|
+
* Works with React, Vue <script setup>, and other frameworks
|
|
836
|
+
*/
|
|
837
|
+
extractDestructuredProps(content) {
|
|
838
|
+
const props = [];
|
|
839
|
+
// Pattern 1: function Component({ prop1, prop2, ...rest }: Type)
|
|
840
|
+
// Pattern 2: const Component = ({ prop1, prop2 }: Type) =>
|
|
841
|
+
// Pattern 3: export function Component({ prop1, prop2 }: Type)
|
|
842
|
+
const functionPatterns = [
|
|
843
|
+
// function Name({ destructured }: Type)
|
|
844
|
+
/(?:export\s+)?(?:default\s+)?function\s+[A-Z]\w*\s*\(\s*\{\s*([^}]+)\s*\}\s*:/g,
|
|
845
|
+
// const Name = ({ destructured }: Type) =>
|
|
846
|
+
/(?:export\s+)?const\s+[A-Z]\w*\s*=\s*\(\s*\{\s*([^}]+)\s*\}\s*:/g,
|
|
847
|
+
// const Name: FC<Props> = ({ destructured }) =>
|
|
848
|
+
/(?:export\s+)?const\s+[A-Z]\w*\s*:\s*\w+(?:<[^>]+>)?\s*=\s*\(\s*\{\s*([^}]+)\s*\}\s*\)/g,
|
|
849
|
+
];
|
|
850
|
+
for (const pattern of functionPatterns) {
|
|
851
|
+
let match;
|
|
852
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
853
|
+
const destructuredContent = match[1];
|
|
854
|
+
// Extract individual prop names, ignoring spread operator (...rest)
|
|
855
|
+
const propMatches = destructuredContent.matchAll(/(?:^|,)\s*(?!\.\.\.)([\w]+)(?:\s*=\s*[^,}]+)?(?=\s*[,}]|$)/g);
|
|
856
|
+
for (const propMatch of propMatches) {
|
|
857
|
+
const propName = propMatch[1].trim();
|
|
858
|
+
// Skip common internal props and rest patterns
|
|
859
|
+
if (propName && !['ref', 'props', 'rest'].includes(propName) && !props.includes(propName)) {
|
|
860
|
+
props.push(propName);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return props;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Extract props from co-located story file (e.g., Button.stories.tsx)
|
|
869
|
+
* This is a fallback for components like shadcn/ui that don't use interface Props patterns
|
|
870
|
+
*/
|
|
871
|
+
extractPropsFromStoryFile(componentPath) {
|
|
872
|
+
const props = [];
|
|
873
|
+
// Construct story file path: button.tsx -> button.stories.tsx
|
|
874
|
+
const dir = path.dirname(componentPath);
|
|
875
|
+
const ext = path.extname(componentPath);
|
|
876
|
+
const name = path.basename(componentPath, ext);
|
|
877
|
+
// Try different story file naming conventions
|
|
878
|
+
const storyPaths = [
|
|
879
|
+
path.join(dir, `${name}.stories.tsx`),
|
|
880
|
+
path.join(dir, `${name}.stories.ts`),
|
|
881
|
+
path.join(dir, `${name}.story.tsx`),
|
|
882
|
+
path.join(dir, `${name}.story.ts`),
|
|
883
|
+
];
|
|
884
|
+
let storyContent = '';
|
|
885
|
+
for (const storyPath of storyPaths) {
|
|
886
|
+
if (fs.existsSync(storyPath)) {
|
|
887
|
+
try {
|
|
888
|
+
storyContent = fs.readFileSync(storyPath, 'utf-8');
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
catch {
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (!storyContent) {
|
|
897
|
+
return props;
|
|
898
|
+
}
|
|
899
|
+
// Extract from argTypes: { propName: { control: ..., options: ... } }
|
|
900
|
+
// Only match prop names followed by `: {` to avoid picking up nested properties like control, options
|
|
901
|
+
const argTypesMatch = storyContent.match(/argTypes\s*:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/);
|
|
902
|
+
if (argTypesMatch) {
|
|
903
|
+
// Match prop names followed by `: {` which indicates argType config object
|
|
904
|
+
const propMatches = argTypesMatch[1].matchAll(/(\w+)\s*:\s*\{/g);
|
|
905
|
+
for (const match of propMatches) {
|
|
906
|
+
// Skip common argTypes meta-properties that shouldn't be props
|
|
907
|
+
const metaProps = ['control', 'options', 'description', 'table', 'type', 'defaultValue', 'if', 'mapping'];
|
|
908
|
+
if (!metaProps.includes(match[1]) && !props.includes(match[1])) {
|
|
909
|
+
props.push(match[1]);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
// Extract from args: { propName: value }
|
|
914
|
+
const argsMatches = storyContent.matchAll(/args\s*:\s*\{([^}]+)\}/g);
|
|
915
|
+
for (const argsMatch of argsMatches) {
|
|
916
|
+
const argContent = argsMatch[1];
|
|
917
|
+
const propMatches = argContent.matchAll(/^\s*(\w+)\s*:/gm);
|
|
918
|
+
for (const match of propMatches) {
|
|
919
|
+
if (!props.includes(match[1])) {
|
|
920
|
+
props.push(match[1]);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
// Extract from render function parameters if they use destructuring
|
|
925
|
+
// e.g., render: ({ variant, size }) => ...
|
|
926
|
+
const renderMatches = storyContent.matchAll(/render\s*:\s*\(\s*\{\s*([^}]+)\s*\}\s*\)/g);
|
|
927
|
+
for (const renderMatch of renderMatches) {
|
|
928
|
+
const paramContent = renderMatch[1];
|
|
929
|
+
const propMatches = paramContent.matchAll(/(\w+)(?:\s*,|\s*$)/g);
|
|
930
|
+
for (const match of propMatches) {
|
|
931
|
+
if (!props.includes(match[1])) {
|
|
932
|
+
props.push(match[1]);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
740
936
|
return props;
|
|
741
937
|
}
|
|
742
938
|
/**
|
|
@@ -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;
|
|
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
|
*/
|
|
@@ -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;CA2DnC"}
|
|
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"}
|
|
@@ -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;
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
@@ -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;AAqTD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CA6D1E;
|
|
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;AAsRD;;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"}
|
|
@@ -603,11 +603,71 @@ function generateExamples(config) {
|
|
|
603
603
|
}
|
|
604
604
|
return examples;
|
|
605
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Extracts the base component name from a compound component name.
|
|
608
|
+
* Used when generating individual file imports to group related components.
|
|
609
|
+
*
|
|
610
|
+
* Examples:
|
|
611
|
+
* - CardHeader -> Card (imports from card.tsx)
|
|
612
|
+
* - AlertDialogTrigger -> AlertDialog (imports from alert-dialog.tsx)
|
|
613
|
+
* - Button -> Button (imports from button.tsx)
|
|
614
|
+
*
|
|
615
|
+
* This pattern is common across multiple frameworks:
|
|
616
|
+
* - React: shadcn/ui, Radix UI compound components
|
|
617
|
+
* - Vue: Radix Vue, shadcn-vue compound components
|
|
618
|
+
* - Angular: Angular Material (mat-card-header -> mat-card)
|
|
619
|
+
* - Web Components: Shoelace (sl-card-header -> sl-card)
|
|
620
|
+
*
|
|
621
|
+
* Note: For frameworks that use slots instead of compound components
|
|
622
|
+
* (many Web Components, some Svelte), this function returns the name unchanged.
|
|
623
|
+
*/
|
|
624
|
+
function getBaseComponentName(componentName) {
|
|
625
|
+
// Known suffixes that indicate sub-components (order matters - check longer ones first)
|
|
626
|
+
const suffixes = [
|
|
627
|
+
'Fallback', 'Image', 'Trigger', 'Content', 'Header', 'Footer', 'Title',
|
|
628
|
+
'Description', 'Action', 'Cancel', 'Close', 'Overlay', 'Portal',
|
|
629
|
+
'Item', 'Group', 'Label', 'Separator', 'Root', 'List', 'Link',
|
|
630
|
+
'Previous', 'Next', 'Ellipsis', 'Viewport', 'ScrollBar', 'Corner',
|
|
631
|
+
'Thumb', 'Track', 'Range', 'Indicator', 'Icon', 'Slot', 'Input',
|
|
632
|
+
'Handle', 'Panel', 'Primitive'
|
|
633
|
+
];
|
|
634
|
+
for (const suffix of suffixes) {
|
|
635
|
+
if (componentName.endsWith(suffix) && componentName !== suffix) {
|
|
636
|
+
const base = componentName.slice(0, -suffix.length);
|
|
637
|
+
if (base.length > 0) {
|
|
638
|
+
return base;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return componentName;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Converts PascalCase to kebab-case for file names.
|
|
646
|
+
* Used when generating individual file imports.
|
|
647
|
+
*
|
|
648
|
+
* Examples:
|
|
649
|
+
* - AlertDialog -> alert-dialog
|
|
650
|
+
* - Button -> button
|
|
651
|
+
* - InputOTP -> input-otp
|
|
652
|
+
*
|
|
653
|
+
* This conversion works across frameworks since kebab-case file names are:
|
|
654
|
+
* - Required: Angular, Web Components
|
|
655
|
+
* - Common: Vue, React (for some libraries)
|
|
656
|
+
* - Accepted: Svelte (though PascalCase is more common)
|
|
657
|
+
*/
|
|
658
|
+
function toKebabCase(name) {
|
|
659
|
+
return name
|
|
660
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
661
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
662
|
+
.toLowerCase();
|
|
663
|
+
}
|
|
606
664
|
/**
|
|
607
665
|
* Generates import statements, using individual import paths if available
|
|
608
666
|
*/
|
|
609
667
|
function generateImportStatements(config, components, componentNames) {
|
|
610
668
|
const importMap = new Map();
|
|
669
|
+
// Check if individual file imports are configured (for libraries without barrel exports)
|
|
670
|
+
const useIndividualImports = config.importStyle === 'individual';
|
|
611
671
|
for (const componentName of componentNames) {
|
|
612
672
|
// Find the component in our discovered components to get its specific import path
|
|
613
673
|
const component = components.find(c => c.name === componentName);
|
|
@@ -619,8 +679,20 @@ function generateImportStatements(config, components, componentNames) {
|
|
|
619
679
|
}
|
|
620
680
|
importMap.get(importPath).push(componentName);
|
|
621
681
|
}
|
|
682
|
+
else if (useIndividualImports) {
|
|
683
|
+
// Generate individual file imports for libraries without barrel exports
|
|
684
|
+
// Group by base component: CardHeader, CardContent -> card.tsx
|
|
685
|
+
// This pattern works for React (shadcn/ui), Vue (PrimeVue), Angular (Material), Web Components (Shoelace)
|
|
686
|
+
const baseComponent = getBaseComponentName(componentName);
|
|
687
|
+
const fileName = toKebabCase(baseComponent);
|
|
688
|
+
const importPath = `${config.importPath}/${fileName}`;
|
|
689
|
+
if (!importMap.has(importPath)) {
|
|
690
|
+
importMap.set(importPath, []);
|
|
691
|
+
}
|
|
692
|
+
importMap.get(importPath).push(componentName);
|
|
693
|
+
}
|
|
622
694
|
else {
|
|
623
|
-
//
|
|
695
|
+
// Use barrel import (default) - import all from single entry point
|
|
624
696
|
if (!importMap.has(config.importPath)) {
|
|
625
697
|
importMap.set(config.importPath, []);
|
|
626
698
|
}
|
|
@@ -629,8 +701,8 @@ function generateImportStatements(config, components, componentNames) {
|
|
|
629
701
|
}
|
|
630
702
|
// Generate import statements
|
|
631
703
|
const importLines = [];
|
|
632
|
-
for (const [importPath,
|
|
633
|
-
importLines.push(`import { ${
|
|
704
|
+
for (const [importPath, comps] of importMap) {
|
|
705
|
+
importLines.push(`import { ${comps.join(', ')} } from '${importPath}';`);
|
|
634
706
|
}
|
|
635
707
|
return importLines.join('\n');
|
|
636
708
|
}
|
|
@@ -81,6 +81,22 @@ export interface StoryUIConfig {
|
|
|
81
81
|
additionalImports?: AdditionalImport[];
|
|
82
82
|
considerationsPath?: string;
|
|
83
83
|
storybookFramework?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Import style for generated stories:
|
|
86
|
+
* - 'barrel': Use barrel imports from a single entry point (e.g., `import { Button } from 'library'`)
|
|
87
|
+
* - 'individual': Use individual file imports (e.g., `import { Button } from 'library/button'`)
|
|
88
|
+
*
|
|
89
|
+
* Use 'individual' for libraries without barrel exports (index.ts), such as:
|
|
90
|
+
* - shadcn/ui, Radix Vue, PrimeVue (Vue)
|
|
91
|
+
* - Angular Material, PrimeNG (Angular)
|
|
92
|
+
* - Shoelace, Lion (Web Components)
|
|
93
|
+
*
|
|
94
|
+
* Use 'barrel' (default) for libraries with barrel exports, such as:
|
|
95
|
+
* - Chakra UI, Mantine, Ant Design (React)
|
|
96
|
+
* - Vuetify, Quasar (Vue)
|
|
97
|
+
* - Skeleton UI (Svelte)
|
|
98
|
+
*/
|
|
99
|
+
importStyle?: 'barrel' | 'individual';
|
|
84
100
|
designSystemGuidelines?: DesignSystemGuidelines;
|
|
85
101
|
/** Icon imports configuration (auto-detected from package.json or manually configured) */
|
|
86
102
|
iconImports?: IconImportsConfig;
|
|
@@ -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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"}
|