@tpitre/story-ui 3.6.2 → 3.8.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.
- package/README.md +36 -32
- package/dist/cli/index.js +0 -5
- package/dist/cli/setup.js +1 -1
- package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStory.js +178 -87
- package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStoryStream.js +149 -31
- package/dist/story-generator/dynamicPackageDiscovery.d.ts +35 -2
- package/dist/story-generator/dynamicPackageDiscovery.d.ts.map +1 -1
- package/dist/story-generator/dynamicPackageDiscovery.js +332 -6
- package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
- package/dist/story-generator/enhancedComponentDiscovery.js +149 -2
- package/dist/story-generator/framework-adapters/base-adapter.d.ts +1 -0
- package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/base-adapter.js +12 -2
- package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/react-adapter.js +2 -0
- package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/svelte-adapter.js +53 -7
- package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/vue-adapter.js +21 -1
- package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -1
- package/dist/story-generator/framework-adapters/web-components-adapter.js +4 -0
- package/dist/story-generator/llm-providers/openai-provider.js +2 -2
- package/dist/story-generator/promptGenerator.d.ts.map +1 -1
- package/dist/story-generator/promptGenerator.js +179 -26
- package/dist/story-generator/runtimeValidator.d.ts +64 -0
- package/dist/story-generator/runtimeValidator.d.ts.map +1 -0
- package/dist/story-generator/runtimeValidator.js +356 -0
- package/dist/story-generator/selfHealingLoop.d.ts +112 -0
- package/dist/story-generator/selfHealingLoop.d.ts.map +1 -0
- package/dist/story-generator/selfHealingLoop.js +202 -0
- package/dist/story-generator/validateStory.d.ts.map +1 -1
- package/dist/story-generator/validateStory.js +81 -12
- package/dist/story-ui.config.d.ts +2 -0
- package/dist/story-ui.config.d.ts.map +1 -1
- package/dist/templates/StoryUI/StoryUIPanel.d.ts +0 -5
- package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
- package/dist/templates/StoryUI/StoryUIPanel.js +411 -223
- package/package.json +4 -4
- package/templates/StoryUI/StoryUIPanel.mdx +84 -0
- package/templates/StoryUI/StoryUIPanel.tsx +493 -265
- package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts +0 -18
- package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts.map +0 -1
- package/dist/templates/StoryUI/StoryUIPanel.stories.js +0 -37
- package/templates/StoryUI/StoryUIPanel.stories.tsx +0 -44
- package/templates/StoryUI/manager.tsx +0 -859
|
@@ -45,10 +45,15 @@ CRITICAL RULES:
|
|
|
45
45
|
- For slots, use render with a wrapper component
|
|
46
46
|
- Events use on: directive in Svelte templates
|
|
47
47
|
|
|
48
|
+
CRITICAL - SVELTE SLOT CONTENT:
|
|
49
|
+
- Svelte components use SLOTS for content, NOT children props
|
|
50
|
+
- Always use render function with 'slot' property for text/content
|
|
51
|
+
- Never use 'children' in args - it will cause runtime errors
|
|
52
|
+
|
|
48
53
|
Example structure:
|
|
49
54
|
\`\`\`typescript
|
|
50
55
|
import type { Meta, StoryObj } from '@storybook/svelte';
|
|
51
|
-
import Button from 'your-library
|
|
56
|
+
import { Button } from 'your-library';
|
|
52
57
|
|
|
53
58
|
const meta: Meta<Button> = {
|
|
54
59
|
title: 'Components/Button',
|
|
@@ -69,8 +74,12 @@ type Story = StoryObj<typeof meta>;
|
|
|
69
74
|
export const Primary: Story = {
|
|
70
75
|
args: {
|
|
71
76
|
variant: 'primary',
|
|
72
|
-
children: 'Click me',
|
|
73
77
|
},
|
|
78
|
+
render: (args) => ({
|
|
79
|
+
Component: Button,
|
|
80
|
+
props: args,
|
|
81
|
+
slot: 'Click me',
|
|
82
|
+
}),
|
|
74
83
|
};
|
|
75
84
|
\`\`\`
|
|
76
85
|
|
|
@@ -122,7 +131,7 @@ ${this.getCommonRules()}`;
|
|
|
122
131
|
### TypeScript Stories File
|
|
123
132
|
\`\`\`typescript
|
|
124
133
|
import type { Meta, StoryObj } from '@storybook/svelte';
|
|
125
|
-
import Button from 'your-library
|
|
134
|
+
import { Button } from 'your-library';
|
|
126
135
|
|
|
127
136
|
const meta: Meta<Button> = {
|
|
128
137
|
title: 'Components/Button',
|
|
@@ -144,20 +153,29 @@ const meta: Meta<Button> = {
|
|
|
144
153
|
export default meta;
|
|
145
154
|
type Story = StoryObj<typeof meta>;
|
|
146
155
|
|
|
156
|
+
// IMPORTANT: Use render with slot property for content
|
|
147
157
|
export const Default: Story = {
|
|
148
158
|
args: {
|
|
149
159
|
variant: 'primary',
|
|
150
160
|
size: 'medium',
|
|
151
|
-
children: 'Button',
|
|
152
161
|
},
|
|
162
|
+
render: (args) => ({
|
|
163
|
+
Component: Button,
|
|
164
|
+
props: args,
|
|
165
|
+
slot: 'Button',
|
|
166
|
+
}),
|
|
153
167
|
};
|
|
154
168
|
|
|
155
169
|
export const Disabled: Story = {
|
|
156
170
|
args: {
|
|
157
171
|
variant: 'primary',
|
|
158
172
|
disabled: true,
|
|
159
|
-
children: 'Disabled',
|
|
160
173
|
},
|
|
174
|
+
render: (args) => ({
|
|
175
|
+
Component: Button,
|
|
176
|
+
props: args,
|
|
177
|
+
slot: 'Disabled',
|
|
178
|
+
}),
|
|
161
179
|
};
|
|
162
180
|
\`\`\`
|
|
163
181
|
|
|
@@ -230,7 +248,7 @@ export const Disabled: Story = {
|
|
|
230
248
|
\`\`\`typescript
|
|
231
249
|
import type { Meta, StoryObj } from '@storybook/svelte';
|
|
232
250
|
import { action } from '@storybook/addon-actions';
|
|
233
|
-
import Button from 'your-library
|
|
251
|
+
import { Button } from 'your-library';
|
|
234
252
|
|
|
235
253
|
const meta: Meta<Button> = {
|
|
236
254
|
title: 'Components/Button',
|
|
@@ -243,9 +261,13 @@ type Story = StoryObj<typeof meta>;
|
|
|
243
261
|
export const WithClickHandler: Story = {
|
|
244
262
|
args: {
|
|
245
263
|
variant: 'primary',
|
|
246
|
-
children: 'Click me',
|
|
247
264
|
onclick: action('button-clicked'),
|
|
248
265
|
},
|
|
266
|
+
render: (args) => ({
|
|
267
|
+
Component: Button,
|
|
268
|
+
props: args,
|
|
269
|
+
slot: 'Click me',
|
|
270
|
+
}),
|
|
249
271
|
};
|
|
250
272
|
\`\`\`
|
|
251
273
|
`;
|
|
@@ -319,6 +341,28 @@ export const Default: Story = {
|
|
|
319
341
|
let processed = super.postProcess(storyContent);
|
|
320
342
|
// Remove React imports if present
|
|
321
343
|
processed = processed.replace(/import React from ['"]react['"];?\n?/g, '');
|
|
344
|
+
// Fix flowbite-svelte imports - convert deep path imports to named exports
|
|
345
|
+
// e.g., import Card from 'flowbite-svelte/dist/card/Card.svelte' → import { Card } from 'flowbite-svelte'
|
|
346
|
+
const flowbiteDeepImportPattern = /import\s+(\w+)\s+from\s+['"]flowbite-svelte\/[^'"]+['"];?/g;
|
|
347
|
+
const flowbiteImports = [];
|
|
348
|
+
processed = processed.replace(flowbiteDeepImportPattern, (match, componentName) => {
|
|
349
|
+
flowbiteImports.push(componentName);
|
|
350
|
+
return ''; // Remove the line, we'll add a consolidated import later
|
|
351
|
+
});
|
|
352
|
+
// If we found flowbite-svelte deep imports, add a consolidated named export import
|
|
353
|
+
if (flowbiteImports.length > 0) {
|
|
354
|
+
const uniqueImports = [...new Set(flowbiteImports)];
|
|
355
|
+
const consolidatedImport = `import { ${uniqueImports.join(', ')} } from 'flowbite-svelte';`;
|
|
356
|
+
// Find where to insert - after the @storybook/svelte import
|
|
357
|
+
const storybookImportMatch = processed.match(/import.*from\s+['"]@storybook\/svelte['"];?\n/);
|
|
358
|
+
if (storybookImportMatch) {
|
|
359
|
+
processed = processed.replace(storybookImportMatch[0], storybookImportMatch[0] + consolidatedImport + '\n');
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
// Insert at the beginning if no storybook import found
|
|
363
|
+
processed = consolidatedImport + '\n' + processed;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
322
366
|
// Fix JSX to Svelte syntax
|
|
323
367
|
processed = processed
|
|
324
368
|
// Fix className to class
|
|
@@ -327,6 +371,8 @@ export const Default: Story = {
|
|
|
327
371
|
.replace(/onClick=/g, 'on:click=')
|
|
328
372
|
.replace(/onChange=/g, 'on:change=')
|
|
329
373
|
.replace(/onInput=/g, 'on:input=');
|
|
374
|
+
// Clean up multiple empty lines that might result from import removal
|
|
375
|
+
processed = processed.replace(/\n{3,}/g, '\n\n');
|
|
330
376
|
return processed;
|
|
331
377
|
}
|
|
332
378
|
/**
|
|
@@ -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;
|
|
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"}
|
|
@@ -293,8 +293,10 @@ export const Default: Story = {
|
|
|
293
293
|
*/
|
|
294
294
|
postProcess(storyContent) {
|
|
295
295
|
let processed = super.postProcess(storyContent);
|
|
296
|
-
// Remove React imports if present
|
|
296
|
+
// Remove React imports if present (multiple patterns)
|
|
297
297
|
processed = processed.replace(/import React from ['"]react['"];?\n?/g, '');
|
|
298
|
+
processed = processed.replace(/import \* as React from ['"]react['"];?\n?/g, '');
|
|
299
|
+
processed = processed.replace(/import { .* } from ['"]react['"];?\n?/g, '');
|
|
298
300
|
// Fix JSX to Vue template syntax
|
|
299
301
|
processed = processed
|
|
300
302
|
// Fix className to class
|
|
@@ -303,6 +305,24 @@ export const Default: Story = {
|
|
|
303
305
|
.replace(/onClick=/g, '@click=')
|
|
304
306
|
.replace(/onChange=/g, '@change=')
|
|
305
307
|
.replace(/onInput=/g, '@input=');
|
|
308
|
+
// Convert Vuetify PascalCase to kebab-case in templates
|
|
309
|
+
// Match opening tags like <VBtn, <VCard, etc. and convert to <v-btn, <v-card
|
|
310
|
+
processed = processed.replace(/<(V[A-Z][a-zA-Z]*)/g, (match, componentName) => {
|
|
311
|
+
// Convert VBtn -> v-btn, VCard -> v-card, VTextField -> v-text-field
|
|
312
|
+
const kebabCase = componentName
|
|
313
|
+
.replace(/^V/, 'v-')
|
|
314
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
315
|
+
.toLowerCase();
|
|
316
|
+
return '<' + kebabCase;
|
|
317
|
+
});
|
|
318
|
+
// Convert closing tags </VBtn> -> </v-btn>
|
|
319
|
+
processed = processed.replace(/<\/(V[A-Z][a-zA-Z]*)/g, (match, componentName) => {
|
|
320
|
+
const kebabCase = componentName
|
|
321
|
+
.replace(/^V/, 'v-')
|
|
322
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
323
|
+
.toLowerCase();
|
|
324
|
+
return '</' + kebabCase;
|
|
325
|
+
});
|
|
306
326
|
return processed;
|
|
307
327
|
}
|
|
308
328
|
/**
|
|
@@ -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;
|
|
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"}
|
|
@@ -294,6 +294,10 @@ export const Default: Story = {
|
|
|
294
294
|
// LLMs sometimes incorrectly include React imports in non-React frameworks
|
|
295
295
|
processed = processed.replace(/import React from ['"]react['"];?\n?/g, '');
|
|
296
296
|
processed = processed.replace(/import \* as React from ['"]react['"];?\n?/g, '');
|
|
297
|
+
// Fix Shoelace imports - add /dist to the path
|
|
298
|
+
// Wrong: @shoelace-style/shoelace/components/...
|
|
299
|
+
// Right: @shoelace-style/shoelace/dist/components/...
|
|
300
|
+
processed = processed.replace(/@shoelace-style\/shoelace\/components\//g, '@shoelace-style/shoelace/dist/components/');
|
|
297
301
|
// Fix common issues
|
|
298
302
|
processed = processed
|
|
299
303
|
// Remove React-style className
|
|
@@ -152,8 +152,8 @@ const OPENAI_MODELS = [
|
|
|
152
152
|
outputPricePer1kTokens: 0.0015,
|
|
153
153
|
},
|
|
154
154
|
];
|
|
155
|
-
// Default model
|
|
156
|
-
const DEFAULT_MODEL = 'gpt-
|
|
155
|
+
// Default model - Updated to latest GPT-5.1 (December 2025)
|
|
156
|
+
const DEFAULT_MODEL = 'gpt-5.1';
|
|
157
157
|
// API configuration
|
|
158
158
|
const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';
|
|
159
159
|
export class OpenAIProvider extends BaseLLMProvider {
|
|
@@ -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;AAEvC;;;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;
|
|
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;AAEvC;;;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;AA0gBD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,mBAAmB,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CA4JjB;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,CA6GjB;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"}
|
|
@@ -31,12 +31,129 @@ function generateSystemPrompt(config) {
|
|
|
31
31
|
// Get the library name for prominent constraint
|
|
32
32
|
const libraryName = config.designSystemGuidelines?.name || config.importPath || 'configured library';
|
|
33
33
|
const importPath = config.importPath || 'your-library';
|
|
34
|
+
// Determine the framework from config (componentFramework takes precedence)
|
|
35
|
+
const framework = config.componentFramework || config.framework || 'react';
|
|
36
|
+
const isReactFramework = framework === 'react' || framework.includes('react');
|
|
37
|
+
const storybookFramework = config.storybookFramework || '@storybook/react';
|
|
38
|
+
// Build framework-specific import instructions
|
|
39
|
+
let frameworkImportInstructions = '';
|
|
40
|
+
let frameworkExampleImports = '';
|
|
41
|
+
if (isReactFramework) {
|
|
42
|
+
frameworkImportInstructions = `
|
|
43
|
+
🚨 CRITICAL: EVERY STORY MUST START WITH "import React from 'react';" AS THE FIRST LINE 🚨
|
|
44
|
+
|
|
45
|
+
🔴 MANDATORY FIRST LINE - NO EXCEPTIONS:
|
|
46
|
+
The VERY FIRST LINE of every story file MUST be:
|
|
47
|
+
import React from 'react';
|
|
48
|
+
|
|
49
|
+
CRITICAL IMPORT RULES - MUST FOLLOW EXACTLY:
|
|
50
|
+
1. **LINE 1: import React from 'react';** (MANDATORY - NEVER SKIP THIS)
|
|
51
|
+
2. **LINE 2: import type { StoryObj } from '${storybookFramework}';**
|
|
52
|
+
3. **LINE 3: import { ComponentName } from '[your-import-path]';**
|
|
53
|
+
|
|
54
|
+
⚠️ WITHOUT "import React from 'react';" THE STORY WILL FAIL WITH "React is not defined" ERROR ⚠️`;
|
|
55
|
+
frameworkExampleImports = `Example correct order:
|
|
56
|
+
import React from 'react';
|
|
57
|
+
import type { StoryObj } from '${storybookFramework}';
|
|
58
|
+
import { ComponentName } from '[your-import-path]';
|
|
59
|
+
|
|
60
|
+
REQUIRED STORY STRUCTURE:
|
|
61
|
+
Every story MUST start with these three imports in this order:
|
|
62
|
+
1. import React from 'react';
|
|
63
|
+
2. import type { StoryObj } from '${storybookFramework}';
|
|
64
|
+
3. import { ComponentName } from '[library-path]';`;
|
|
65
|
+
}
|
|
66
|
+
else if (framework === 'vue') {
|
|
67
|
+
frameworkImportInstructions = `
|
|
68
|
+
CRITICAL IMPORT RULES FOR VUE STORIES:
|
|
69
|
+
1. **DO NOT import React** - This is a Vue project, not React!
|
|
70
|
+
2. **LINE 1: import type { Meta, StoryObj } from '${storybookFramework}';**
|
|
71
|
+
3. **LINE 2: import { ComponentName } from '[your-import-path]';**
|
|
72
|
+
|
|
73
|
+
⚠️ DO NOT ADD "import React from 'react';" - Vue does NOT use React! ⚠️`;
|
|
74
|
+
frameworkExampleImports = `Example correct order for Vue:
|
|
75
|
+
import type { Meta, StoryObj } from '${storybookFramework}';
|
|
76
|
+
import { VBtn, VCard } from 'vuetify/components';
|
|
77
|
+
|
|
78
|
+
REQUIRED STORY STRUCTURE:
|
|
79
|
+
Every Vue story MUST start with:
|
|
80
|
+
1. import type { Meta, StoryObj } from '${storybookFramework}';
|
|
81
|
+
2. import { ComponentName } from '[library-path]';`;
|
|
82
|
+
}
|
|
83
|
+
else if (framework === 'angular') {
|
|
84
|
+
frameworkImportInstructions = `
|
|
85
|
+
CRITICAL IMPORT RULES FOR ANGULAR STORIES:
|
|
86
|
+
1. **DO NOT import React** - This is an Angular project, not React!
|
|
87
|
+
2. **LINE 1: import type { Meta, StoryObj } from '${storybookFramework}';**
|
|
88
|
+
3. **LINE 2: Import Angular Material modules as needed**
|
|
89
|
+
|
|
90
|
+
⚠️ DO NOT ADD "import React from 'react';" - Angular does NOT use React! ⚠️`;
|
|
91
|
+
frameworkExampleImports = `Example correct order for Angular:
|
|
92
|
+
import type { Meta, StoryObj } from '${storybookFramework}';
|
|
93
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
94
|
+
import { moduleMetadata } from '@storybook/angular';
|
|
95
|
+
|
|
96
|
+
REQUIRED STORY STRUCTURE:
|
|
97
|
+
Every Angular story MUST:
|
|
98
|
+
1. Import from '${storybookFramework}';
|
|
99
|
+
2. Import Angular Material modules from their specific paths
|
|
100
|
+
3. Use moduleMetadata or applicationConfig decorators`;
|
|
101
|
+
}
|
|
102
|
+
else if (framework === 'svelte') {
|
|
103
|
+
frameworkImportInstructions = `
|
|
104
|
+
CRITICAL IMPORT RULES FOR SVELTE STORIES:
|
|
105
|
+
1. **DO NOT import React** - This is a Svelte project, not React!
|
|
106
|
+
2. **LINE 1: import type { Meta, StoryObj } from '${storybookFramework}';**
|
|
107
|
+
3. **LINE 2: import { ComponentName } from '[your-import-path]';**
|
|
108
|
+
|
|
109
|
+
⚠️ DO NOT ADD "import React from 'react';" - Svelte does NOT use React! ⚠️`;
|
|
110
|
+
frameworkExampleImports = `Example correct order for Svelte:
|
|
111
|
+
import type { Meta, StoryObj } from '${storybookFramework}';
|
|
112
|
+
import { Button, Card } from 'flowbite-svelte';
|
|
113
|
+
|
|
114
|
+
REQUIRED STORY STRUCTURE:
|
|
115
|
+
Every Svelte story MUST:
|
|
116
|
+
1. Import from '${storybookFramework}';
|
|
117
|
+
2. Import Svelte components from the library`;
|
|
118
|
+
}
|
|
119
|
+
else if (framework === 'web-components') {
|
|
120
|
+
frameworkImportInstructions = `
|
|
121
|
+
CRITICAL IMPORT RULES FOR WEB COMPONENTS STORIES:
|
|
122
|
+
1. **DO NOT import React** - This is a Web Components project!
|
|
123
|
+
2. **LINE 1: import { html } from 'lit';**
|
|
124
|
+
3. **LINE 2: import type { Meta, StoryObj } from '${storybookFramework}';**
|
|
125
|
+
4. **LINE 3: Import web components from the library**
|
|
126
|
+
|
|
127
|
+
⚠️ DO NOT ADD "import React from 'react';" - Web Components do NOT use React! ⚠️
|
|
128
|
+
⚠️ Use html\`\` template literals, NOT JSX! ⚠️`;
|
|
129
|
+
frameworkExampleImports = `Example correct order for Web Components:
|
|
130
|
+
import { html } from 'lit';
|
|
131
|
+
import type { Meta, StoryObj } from '${storybookFramework}';
|
|
132
|
+
import '@shoelace-style/shoelace/dist/components/button/button.js';
|
|
133
|
+
|
|
134
|
+
REQUIRED STORY STRUCTURE:
|
|
135
|
+
Every Web Components story MUST:
|
|
136
|
+
1. Import { html } from 'lit';
|
|
137
|
+
2. Import from '${storybookFramework}';
|
|
138
|
+
3. Import web components as side-effect imports`;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Generic fallback
|
|
142
|
+
frameworkImportInstructions = `
|
|
143
|
+
CRITICAL IMPORT RULES:
|
|
144
|
+
1. Import type { Meta, StoryObj } from '${storybookFramework}';
|
|
145
|
+
2. Import components from the configured library`;
|
|
146
|
+
frameworkExampleImports = `Example imports:
|
|
147
|
+
import type { Meta, StoryObj } from '${storybookFramework}';
|
|
148
|
+
import { ComponentName } from '[your-import-path]';`;
|
|
149
|
+
}
|
|
34
150
|
return `
|
|
35
151
|
╔════════════════════════════════════════════════════════════════════╗
|
|
36
152
|
║ 🚨 MANDATORY LIBRARY CONSTRAINT 🚨 ║
|
|
37
153
|
╠════════════════════════════════════════════════════════════════════╣
|
|
38
154
|
║ REQUIRED LIBRARY: ${libraryName.padEnd(46)}║
|
|
39
155
|
║ IMPORT PATH: ${importPath.padEnd(46)}║
|
|
156
|
+
║ FRAMEWORK: ${framework.padEnd(46)}║
|
|
40
157
|
╠════════════════════════════════════════════════════════════════════╣
|
|
41
158
|
║ ALL component imports MUST use: ║
|
|
42
159
|
║ import { ComponentName } from '${importPath}';${' '.repeat(Math.max(0, 32 - importPath.length))}║
|
|
@@ -48,23 +165,11 @@ function generateSystemPrompt(config) {
|
|
|
48
165
|
║ - antd (unless configured) ║
|
|
49
166
|
║ - Any library NOT matching: ${importPath.padEnd(36)}║
|
|
50
167
|
╚════════════════════════════════════════════════════════════════════╝
|
|
51
|
-
|
|
52
|
-
🚨 CRITICAL: EVERY STORY MUST START WITH "import React from 'react';" AS THE FIRST LINE 🚨
|
|
168
|
+
${frameworkImportInstructions}
|
|
53
169
|
|
|
54
170
|
🔴 CRITICAL RULE: NEVER use children in args for ANY component or layout. Always use render functions. 🔴
|
|
55
171
|
|
|
56
|
-
You are an expert UI developer creating Storybook stories. Use ONLY the
|
|
57
|
-
|
|
58
|
-
🔴 MANDATORY FIRST LINE - NO EXCEPTIONS:
|
|
59
|
-
The VERY FIRST LINE of every story file MUST be:
|
|
60
|
-
import React from 'react';
|
|
61
|
-
|
|
62
|
-
CRITICAL IMPORT RULES - MUST FOLLOW EXACTLY:
|
|
63
|
-
1. **LINE 1: import React from 'react';** (MANDATORY - NEVER SKIP THIS)
|
|
64
|
-
2. **LINE 2: import type { StoryObj } from '@storybook/[framework]';**
|
|
65
|
-
3. **LINE 3: import { ComponentName } from '[your-import-path]';**
|
|
66
|
-
|
|
67
|
-
⚠️ WITHOUT "import React from 'react';" THE STORY WILL FAIL WITH "React is not defined" ERROR ⚠️
|
|
172
|
+
You are an expert UI developer creating Storybook stories for ${framework.toUpperCase()}. Use ONLY the components from the ${componentSystemName} listed below.
|
|
68
173
|
|
|
69
174
|
🚨 COMPONENT IMPORT VALIDATION - CRITICAL 🚨
|
|
70
175
|
You can ONLY import components that are explicitly listed in the "Available components" section below.
|
|
@@ -74,15 +179,12 @@ If a component is not listed, DO NOT use it - choose an alternative from the ava
|
|
|
74
179
|
|
|
75
180
|
🔴 IMPORT PATH RULE - MANDATORY 🔴
|
|
76
181
|
ALWAYS use the EXACT import path shown in parentheses after each component name.
|
|
77
|
-
For example: If the Available components list shows "Button (import from 'antd')",
|
|
182
|
+
For example: If the Available components list shows "Button (import from 'antd')",
|
|
78
183
|
you MUST use: import { Button } from 'antd';
|
|
79
184
|
NEVER use the main package import if a specific path is shown.
|
|
80
185
|
This is critical for proper component resolution.
|
|
81
186
|
|
|
82
|
-
|
|
83
|
-
import React from 'react';
|
|
84
|
-
import type { StoryObj } from '@storybook/[framework]';
|
|
85
|
-
import { ComponentName } from '[your-import-path]';
|
|
187
|
+
${frameworkExampleImports}
|
|
86
188
|
|
|
87
189
|
2. Use the correct Storybook framework import for your environment
|
|
88
190
|
3. ONLY import components that are explicitly listed in the "Available components" section below
|
|
@@ -90,12 +192,6 @@ import { ComponentName } from '[your-import-path]';
|
|
|
90
192
|
5. Do NOT import story exports from other story files
|
|
91
193
|
6. When in doubt, use the basic components listed below
|
|
92
194
|
|
|
93
|
-
REQUIRED STORY STRUCTURE:
|
|
94
|
-
Every story MUST start with these three imports in this order:
|
|
95
|
-
1. import React from 'react';
|
|
96
|
-
2. import type { StoryObj } from '@storybook/[framework]';
|
|
97
|
-
3. import { ComponentName } from '[library-path]';
|
|
98
|
-
|
|
99
195
|
GENERAL COMPONENT RULES:
|
|
100
196
|
- StoryUIPanel is the Story UI interface, not a design system component - never import it
|
|
101
197
|
- Do not import components that end with Story, Example, Demo, or that appear to be story exports
|
|
@@ -367,6 +463,7 @@ const meta = {
|
|
|
367
463
|
parameters: {
|
|
368
464
|
layout: 'centered',
|
|
369
465
|
},
|
|
466
|
+
tags: ['autodocs'],
|
|
370
467
|
} satisfies Meta;
|
|
371
468
|
|
|
372
469
|
export default meta;
|
|
@@ -388,6 +485,7 @@ const meta = {
|
|
|
388
485
|
parameters: {
|
|
389
486
|
layout: 'centered',
|
|
390
487
|
},
|
|
488
|
+
tags: ['autodocs'],
|
|
391
489
|
} satisfies Meta<typeof ${mainComponent}>;
|
|
392
490
|
|
|
393
491
|
export default meta;
|
|
@@ -467,7 +565,42 @@ export async function buildClaudePrompt(userPrompt, config, components) {
|
|
|
467
565
|
// Icons and other specific imports should be handled through additionalImports or considerations
|
|
468
566
|
// Reinforce NO children in args rule
|
|
469
567
|
promptParts.push('', '🔴 CRITICAL REMINDER: NEVER use children in args 🔴', 'Always use render functions for any layout or component composition.', '');
|
|
470
|
-
|
|
568
|
+
// Determine framework from config for rules section
|
|
569
|
+
const framework = config.componentFramework || config.framework || 'react';
|
|
570
|
+
const isReactFramework = framework === 'react' || framework.includes('react');
|
|
571
|
+
// Build framework-specific first line rules
|
|
572
|
+
let frameworkFirstLineRules = '';
|
|
573
|
+
if (isReactFramework) {
|
|
574
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS 🚨
|
|
575
|
+
🔴 FIRST LINE MUST BE: import React from 'react';
|
|
576
|
+
🔴 WITHOUT THIS IMPORT, THE STORY WILL BREAK!`;
|
|
577
|
+
}
|
|
578
|
+
else if (framework === 'vue') {
|
|
579
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS FOR VUE 🚨
|
|
580
|
+
🔴 DO NOT import React - this is a Vue project!
|
|
581
|
+
🔴 First line should be: import type { Meta, StoryObj } from '@storybook/vue3';`;
|
|
582
|
+
}
|
|
583
|
+
else if (framework === 'angular') {
|
|
584
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS FOR ANGULAR 🚨
|
|
585
|
+
🔴 DO NOT import React - this is an Angular project!
|
|
586
|
+
🔴 First line should be: import type { Meta, StoryObj } from '@storybook/angular';`;
|
|
587
|
+
}
|
|
588
|
+
else if (framework === 'svelte') {
|
|
589
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS FOR SVELTE 🚨
|
|
590
|
+
🔴 DO NOT import React - this is a Svelte project!
|
|
591
|
+
🔴 First line should be: import type { Meta, StoryObj } from '@storybook/svelte';`;
|
|
592
|
+
}
|
|
593
|
+
else if (framework === 'web-components') {
|
|
594
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS FOR WEB COMPONENTS 🚨
|
|
595
|
+
🔴 DO NOT import React - this is a Web Components project!
|
|
596
|
+
🔴 First line should be: import { html } from 'lit';
|
|
597
|
+
🔴 Use html\`\` template literals, NOT JSX!`;
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
frameworkFirstLineRules = `🚨 FINAL CRITICAL REMINDERS 🚨
|
|
601
|
+
Follow the framework-specific import patterns shown above.`;
|
|
602
|
+
}
|
|
603
|
+
promptParts.push(`Output a complete Storybook story file in TypeScript. Import components as shown in the sample template below. Use the following sample as a template. Respond ONLY with a single code block containing the full file, and nothing else.`, '', '<rules>', frameworkFirstLineRules, '', 'OTHER CRITICAL RULES:', '- Story title MUST always start with "Generated/" (e.g., title: "Generated/Recipe Card")', '- Do NOT use prefixes like "Content/", "Components/", or any other section name', '- ONLY import components that are listed in the "Available components" section', '- ALWAYS use the exact import path shown in parentheses after each component', '- NEVER use main package imports when specific subpath imports are shown', '- Do NOT import story exports - these are NOT real components', '- Check every import against the Available components list before using it', '- FORBIDDEN: Any component not explicitly listed in the Available components section', '- FORBIDDEN: Theme setup components (providers should be configured at the app level, not in individual stories)', '- All images MUST have a src attribute with placeholder URLs (use https://picsum.photos/)', '- Never create <img> tags without src attributes', '- MUST use ES modules syntax: "export default meta;" NOT "module.exports = meta;"', '- The file MUST have a default export for the meta object', '- Keep the story concise and focused - avoid overly complex layouts that might exceed token limits', '- Ensure all JSX tags are properly closed', '- Story must be complete and syntactically valid', '- CRITICAL: Never put ANY content in args.children - always use render function', '- Use render functions for ALL layouts and component compositions', '- For layouts: DO NOT set component in meta', '- Only set component in meta when showcasing a SINGLE component', '- Use appropriate styling for the component library (design tokens, className, or inline styles as needed)', '</rules>', '', 'Sample story format:', generated.sampleStory, '', 'User request:', userPrompt);
|
|
471
604
|
return promptParts.join('\n');
|
|
472
605
|
}
|
|
473
606
|
/**
|
|
@@ -576,6 +709,9 @@ function getFrameworkSpecificRules(framework) {
|
|
|
576
709
|
rules.push('- Use JSX syntax for templates');
|
|
577
710
|
rules.push('- NEVER pass children through args - use render functions');
|
|
578
711
|
rules.push('- For layouts with multiple components, DO NOT set component in meta');
|
|
712
|
+
rules.push('- 🚫 NEVER use Angular Material (MatCardModule, MatButtonModule, etc.)');
|
|
713
|
+
rules.push('- 🚫 NEVER use Vue components (VCard, VBtn, etc.)');
|
|
714
|
+
rules.push('- ✅ ONLY use React components from the configured import path');
|
|
579
715
|
break;
|
|
580
716
|
case 'vue':
|
|
581
717
|
rules.push("- Import from '@storybook/vue3'");
|
|
@@ -583,6 +719,14 @@ function getFrameworkSpecificRules(framework) {
|
|
|
583
719
|
rules.push('- Use render functions with template for complex content');
|
|
584
720
|
rules.push('- Event bindings use @event or v-on:event syntax');
|
|
585
721
|
rules.push('- Slots use v-slot directive or # shorthand');
|
|
722
|
+
rules.push("- 🚫 NEVER import React from 'react' - this is Vue, NOT React!");
|
|
723
|
+
rules.push('- 🚫 NEVER use Angular Material (MatCardModule, MatButtonModule, etc.)');
|
|
724
|
+
rules.push('- 🚫 NEVER use @angular/material or moduleMetadata');
|
|
725
|
+
rules.push('- ✅ ONLY use Vue components from the configured import path');
|
|
726
|
+
rules.push('- ✅ Use KEBAB-CASE in templates: <v-btn>, <v-card>, NOT <VBtn>, <VCard>');
|
|
727
|
+
rules.push('- ✅ Vuetify components: v-btn, v-card, v-text-field, v-row, v-col, etc.');
|
|
728
|
+
rules.push('- ✅ Import with PascalCase: import { VBtn } from "vuetify/components"');
|
|
729
|
+
rules.push('- ✅ Use kebab-case in template: <v-btn v-bind="args">Click</v-btn>');
|
|
586
730
|
break;
|
|
587
731
|
case 'angular':
|
|
588
732
|
rules.push("- Import from '@storybook/angular'");
|
|
@@ -590,12 +734,18 @@ function getFrameworkSpecificRules(framework) {
|
|
|
590
734
|
rules.push('- Property binding: [property]="value"');
|
|
591
735
|
rules.push('- Event binding: (event)="handler($event)"');
|
|
592
736
|
rules.push('- Use Angular template syntax in render functions');
|
|
737
|
+
rules.push("- 🚫 NEVER import React from 'react' - this is Angular, NOT React!");
|
|
738
|
+
rules.push('- 🚫 NEVER use Vue components (VCard, VBtn, etc.)');
|
|
739
|
+
rules.push('- ✅ ONLY use Angular Material or configured library components');
|
|
593
740
|
break;
|
|
594
741
|
case 'svelte':
|
|
595
742
|
rules.push("- Import from '@storybook/svelte'");
|
|
596
743
|
rules.push('- Import .svelte files directly as default exports');
|
|
597
744
|
rules.push('- Events use on: directive (e.g., on:click)');
|
|
598
745
|
rules.push('- Use bind: for two-way binding');
|
|
746
|
+
rules.push("- 🚫 NEVER import React from 'react' - this is Svelte, NOT React!");
|
|
747
|
+
rules.push('- 🚫 NEVER use Angular Material or Vue components');
|
|
748
|
+
rules.push('- ✅ ONLY use Svelte components from the configured import path');
|
|
599
749
|
break;
|
|
600
750
|
case 'web-components':
|
|
601
751
|
rules.push("- Import { html } from 'lit'");
|
|
@@ -605,6 +755,9 @@ function getFrameworkSpecificRules(framework) {
|
|
|
605
755
|
rules.push('- Property binding: .property=${value}');
|
|
606
756
|
rules.push('- Event binding: @event=${handler}');
|
|
607
757
|
rules.push('- Boolean attributes: ?disabled=${true}');
|
|
758
|
+
rules.push("- 🚫 NEVER import React from 'react' - this is Web Components, NOT React!");
|
|
759
|
+
rules.push('- 🚫 NEVER use JSX syntax - use html`` template literals only');
|
|
760
|
+
rules.push('- ✅ ONLY use Web Components from the configured import path');
|
|
608
761
|
break;
|
|
609
762
|
default:
|
|
610
763
|
break;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Validator for Story UI
|
|
3
|
+
*
|
|
4
|
+
* Validates that generated stories actually load and render in Storybook
|
|
5
|
+
* by making HTTP requests to the running Storybook instance after HMR processes
|
|
6
|
+
* the new story file.
|
|
7
|
+
*
|
|
8
|
+
* This catches runtime errors that static validation cannot detect, such as:
|
|
9
|
+
* - "importers[path] is not a function" - Storybook CSF loader errors
|
|
10
|
+
* - Module resolution failures
|
|
11
|
+
* - Runtime component errors
|
|
12
|
+
*/
|
|
13
|
+
export interface RuntimeValidationResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
storyExists: boolean;
|
|
16
|
+
renderError?: string;
|
|
17
|
+
errorType?: 'module_error' | 'render_error' | 'not_found' | 'timeout' | 'connection_error';
|
|
18
|
+
details?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RuntimeValidatorConfig {
|
|
21
|
+
storybookUrl: string;
|
|
22
|
+
hmrWaitMs?: number;
|
|
23
|
+
fetchTimeoutMs?: number;
|
|
24
|
+
retryAttempts?: number;
|
|
25
|
+
retryDelayMs?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the Storybook URL based on environment configuration
|
|
29
|
+
*/
|
|
30
|
+
export declare function getStorybookUrl(): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Check if runtime validation is enabled
|
|
33
|
+
*/
|
|
34
|
+
export declare function isRuntimeValidationEnabled(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Convert a story title to the Storybook story ID prefix format
|
|
37
|
+
* e.g., "Simple Card" with prefix "Generated/" -> "generated-simple-card"
|
|
38
|
+
* Note: This returns the prefix only, without the story export name
|
|
39
|
+
*/
|
|
40
|
+
export declare function titleToStoryIdPrefix(title: string, storyPrefix?: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Extract the actual title from generated story content
|
|
43
|
+
* Looks for: title: 'Generated/Something' or title: "Generated/Something"
|
|
44
|
+
*/
|
|
45
|
+
export declare function extractTitleFromStory(storyContent: string): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Convert a full story title (like "Generated/Button Click Counter") to story ID prefix
|
|
48
|
+
*/
|
|
49
|
+
export declare function fullTitleToStoryIdPrefix(fullTitle: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Validate that a story loads and renders correctly in Storybook
|
|
52
|
+
*
|
|
53
|
+
* @param storyContent - The generated story content (used to extract the actual title)
|
|
54
|
+
* @param fallbackTitle - Fallback title if extraction fails (e.g., "Simple Card")
|
|
55
|
+
* @param storyPrefix - The story prefix from config (e.g., "Generated/")
|
|
56
|
+
* @param customConfig - Runtime validator configuration
|
|
57
|
+
* @returns Validation result with success status and any errors
|
|
58
|
+
*/
|
|
59
|
+
export declare function validateStoryRuntime(storyContent: string, fallbackTitle: string, storyPrefix?: string, customConfig?: Partial<RuntimeValidatorConfig>): Promise<RuntimeValidationResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Format runtime validation errors for the self-healing prompt
|
|
62
|
+
*/
|
|
63
|
+
export declare function formatRuntimeErrorForHealing(result: RuntimeValidationResult): string;
|
|
64
|
+
//# sourceMappingURL=runtimeValidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimeValidator.d.ts","sourceRoot":"","sources":["../../story-generator/runtimeValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAeD;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAmB/C;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAcpD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,GAAE,MAAqB,GAAG,MAAM,CAQ9F;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKlE;AAiJD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,WAAW,GAAE,MAAqB,EAClC,YAAY,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAC7C,OAAO,CAAC,uBAAuB,CAAC,CA6FlC;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAoDpF"}
|