@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.
Files changed (47) hide show
  1. package/README.md +36 -32
  2. package/dist/cli/index.js +0 -5
  3. package/dist/cli/setup.js +1 -1
  4. package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
  5. package/dist/mcp-server/routes/generateStory.js +178 -87
  6. package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
  7. package/dist/mcp-server/routes/generateStoryStream.js +149 -31
  8. package/dist/story-generator/dynamicPackageDiscovery.d.ts +35 -2
  9. package/dist/story-generator/dynamicPackageDiscovery.d.ts.map +1 -1
  10. package/dist/story-generator/dynamicPackageDiscovery.js +332 -6
  11. package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
  12. package/dist/story-generator/enhancedComponentDiscovery.js +149 -2
  13. package/dist/story-generator/framework-adapters/base-adapter.d.ts +1 -0
  14. package/dist/story-generator/framework-adapters/base-adapter.d.ts.map +1 -1
  15. package/dist/story-generator/framework-adapters/base-adapter.js +12 -2
  16. package/dist/story-generator/framework-adapters/react-adapter.d.ts.map +1 -1
  17. package/dist/story-generator/framework-adapters/react-adapter.js +2 -0
  18. package/dist/story-generator/framework-adapters/svelte-adapter.d.ts.map +1 -1
  19. package/dist/story-generator/framework-adapters/svelte-adapter.js +53 -7
  20. package/dist/story-generator/framework-adapters/vue-adapter.d.ts.map +1 -1
  21. package/dist/story-generator/framework-adapters/vue-adapter.js +21 -1
  22. package/dist/story-generator/framework-adapters/web-components-adapter.d.ts.map +1 -1
  23. package/dist/story-generator/framework-adapters/web-components-adapter.js +4 -0
  24. package/dist/story-generator/llm-providers/openai-provider.js +2 -2
  25. package/dist/story-generator/promptGenerator.d.ts.map +1 -1
  26. package/dist/story-generator/promptGenerator.js +179 -26
  27. package/dist/story-generator/runtimeValidator.d.ts +64 -0
  28. package/dist/story-generator/runtimeValidator.d.ts.map +1 -0
  29. package/dist/story-generator/runtimeValidator.js +356 -0
  30. package/dist/story-generator/selfHealingLoop.d.ts +112 -0
  31. package/dist/story-generator/selfHealingLoop.d.ts.map +1 -0
  32. package/dist/story-generator/selfHealingLoop.js +202 -0
  33. package/dist/story-generator/validateStory.d.ts.map +1 -1
  34. package/dist/story-generator/validateStory.js +81 -12
  35. package/dist/story-ui.config.d.ts +2 -0
  36. package/dist/story-ui.config.d.ts.map +1 -1
  37. package/dist/templates/StoryUI/StoryUIPanel.d.ts +0 -5
  38. package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
  39. package/dist/templates/StoryUI/StoryUIPanel.js +411 -223
  40. package/package.json +4 -4
  41. package/templates/StoryUI/StoryUIPanel.mdx +84 -0
  42. package/templates/StoryUI/StoryUIPanel.tsx +493 -265
  43. package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts +0 -18
  44. package/dist/templates/StoryUI/StoryUIPanel.stories.d.ts.map +0 -1
  45. package/dist/templates/StoryUI/StoryUIPanel.stories.js +0 -37
  46. package/templates/StoryUI/StoryUIPanel.stories.tsx +0 -44
  47. package/templates/StoryUI/manager.tsx +0 -859
@@ -9,12 +9,17 @@ export function validateStoryCode(code, fileName = 'story.tsx', config) {
9
9
  errors: [],
10
10
  warnings: []
11
11
  };
12
+ // Determine framework from config
13
+ const framework = config?.componentFramework || config?.framework || 'react';
14
+ const isJsxFramework = framework === 'react' || framework === 'vue';
12
15
  try {
13
16
  // Create a TypeScript source file
14
- const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
17
+ // Use appropriate script kind based on framework
18
+ const scriptKind = isJsxFramework ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
19
+ const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.Latest, true, scriptKind);
15
20
  // Check for syntax errors using the program API
16
21
  const compilerOptions = {
17
- jsx: ts.JsxEmit.ReactJSX,
22
+ jsx: isJsxFramework ? ts.JsxEmit.ReactJSX : ts.JsxEmit.None,
18
23
  target: ts.ScriptTarget.Latest,
19
24
  module: ts.ModuleKind.ESNext,
20
25
  allowJs: true,
@@ -47,11 +52,13 @@ export function validateStoryCode(code, fileName = 'story.tsx', config) {
47
52
  }
48
53
  }
49
54
  }
50
- // Additional semantic checks
51
- const semanticErrors = performSemanticChecks(sourceFile, config);
52
- result.errors.push(...semanticErrors);
55
+ // Additional semantic checks - only for JSX frameworks (React, Vue with JSX)
56
+ // For non-JSX frameworks (Angular, Svelte, Web Components), skip JSX-specific validation
57
+ if (isJsxFramework) {
58
+ const semanticErrors = performSemanticChecks(sourceFile, config);
59
+ result.errors.push(...semanticErrors);
60
+ }
53
61
  // Check for React import - but only for React-based frameworks
54
- const framework = config?.framework || 'react';
55
62
  const isReactFramework = framework === 'react' || framework.includes('react');
56
63
  const hasJSX = code.includes('<') || code.includes('/>');
57
64
  const hasReactImport = code.includes('import React from \'react\';');
@@ -61,6 +68,12 @@ export function validateStoryCode(code, fileName = 'story.tsx', config) {
61
68
  result.errors.push('Missing React import - add "import React from \'react\';" at the top of the file');
62
69
  result.isValid = false;
63
70
  }
71
+ // CRITICAL: For non-React frameworks, REMOVE any React imports that the LLM incorrectly generated
72
+ if (!isReactFramework && hasReactImport) {
73
+ result.warnings.push(`Removed incorrect React import for ${framework} framework`);
74
+ code = removeReactImport(code);
75
+ result.fixedCode = code;
76
+ }
64
77
  if (result.errors.length > 0) {
65
78
  result.isValid = false;
66
79
  // Attempt to fix common issues
@@ -89,6 +102,7 @@ function performSemanticChecks(sourceFile, config) {
89
102
  const errors = [];
90
103
  const availableComponents = new Set();
91
104
  const importedComponents = new Set();
105
+ const usedJsxComponents = new Set();
92
106
  // If config is provided, collect available components
93
107
  if (config && config.componentsToImport) {
94
108
  config.componentsToImport.forEach((comp) => availableComponents.add(comp));
@@ -127,19 +141,54 @@ function performSemanticChecks(sourceFile, config) {
127
141
  });
128
142
  }
129
143
  }
144
+ // Track all named imports from any module (React, icons, etc.)
145
+ if (ts.isNamedImports(node.importClause.namedBindings)) {
146
+ node.importClause.namedBindings.elements.forEach(element => {
147
+ importedComponents.add(element.name.text);
148
+ });
149
+ }
130
150
  }
131
151
  }
132
- // Check for unclosed JSX elements
133
- if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
134
- // Additional JSX-specific checks could go here
152
+ // Track default imports (e.g., import React from 'react')
153
+ if (ts.isImportDeclaration(node) && node.importClause && node.importClause.name) {
154
+ importedComponents.add(node.importClause.name.text);
135
155
  }
136
- // Check for missing imports
137
- if (ts.isIdentifier(node) && node.text && /^[A-Z]/.test(node.text)) {
138
- // This is a potential component reference - would need more context to validate
156
+ // Track JSX element names - CRITICAL: Catch undefined components
157
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
158
+ const tagName = node.tagName;
159
+ // Handle different tag name types
160
+ if (ts.isIdentifier(tagName)) {
161
+ // Simple identifier like <Card> or <CardSection>
162
+ const name = tagName.text;
163
+ // Only track PascalCase names (components, not HTML elements like div, span)
164
+ if (/^[A-Z]/.test(name)) {
165
+ usedJsxComponents.add(name);
166
+ }
167
+ }
168
+ else if (ts.isPropertyAccessExpression(tagName)) {
169
+ // Compound component like <Card.Section>
170
+ // The parent (Card) needs to be imported, not Card.Section
171
+ if (ts.isIdentifier(tagName.expression)) {
172
+ const parentName = tagName.expression.text;
173
+ if (/^[A-Z]/.test(parentName)) {
174
+ usedJsxComponents.add(parentName);
175
+ }
176
+ }
177
+ }
139
178
  }
140
179
  ts.forEachChild(node, visit);
141
180
  }
142
181
  visit(sourceFile);
182
+ // CRITICAL CHECK: Verify all used JSX components are imported
183
+ // This catches bugs where a component is used but never imported
184
+ // This is framework-agnostic - works for any JSX-based framework
185
+ for (const componentName of usedJsxComponents) {
186
+ if (!importedComponents.has(componentName)) {
187
+ errors.push(`JSX error: "${componentName}" is used but was never imported. ` +
188
+ `Either add it to your imports, or if you intended to use a sub-component, ` +
189
+ `use the correct syntax (e.g., Parent.Child instead of ParentChild).`);
190
+ }
191
+ }
143
192
  return errors;
144
193
  }
145
194
  /**
@@ -307,6 +356,26 @@ function fixMissingReactImport(code) {
307
356
  }
308
357
  return code;
309
358
  }
359
+ /**
360
+ * Removes React import for non-React frameworks (Vue, Angular, Svelte, Web Components)
361
+ * The LLM sometimes incorrectly generates React imports for these frameworks
362
+ */
363
+ function removeReactImport(code) {
364
+ // Remove various forms of React import
365
+ const reactImportPatterns = [
366
+ /import\s+React\s+from\s+['"]react['"]\s*;?\n?/g,
367
+ /import\s+\*\s+as\s+React\s+from\s+['"]react['"]\s*;?\n?/g,
368
+ /import\s+React,?\s*\{[^}]*\}\s+from\s+['"]react['"]\s*;?\n?/g,
369
+ /import\s+\{[^}]*\}\s+from\s+['"]react['"]\s*;?\n?/g,
370
+ ];
371
+ let cleanedCode = code;
372
+ for (const pattern of reactImportPatterns) {
373
+ cleanedCode = cleanedCode.replace(pattern, '');
374
+ }
375
+ // Clean up any resulting double newlines
376
+ cleanedCode = cleanedCode.replace(/\n\n\n+/g, '\n\n');
377
+ return cleanedCode;
378
+ }
310
379
  /**
311
380
  * Fixes unclosed JSX elements
312
381
  */
@@ -59,6 +59,8 @@ export interface StoryUIConfig {
59
59
  componentPrefix: string;
60
60
  /** Framework type for story generation (e.g., 'react', 'web-components', 'angular', 'vue', 'svelte') */
61
61
  framework?: string;
62
+ /** Component framework type for discovery routing (e.g., 'react', 'vue', 'angular', 'svelte', 'web-components') */
63
+ componentFramework?: string;
62
64
  components: ComponentConfig[];
63
65
  layoutComponents?: ComponentConfig[];
64
66
  layoutRules: LayoutRules;
@@ -1 +1 @@
1
- {"version":3,"file":"story-ui.config.d.ts","sourceRoot":"","sources":["../story-ui.config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;IAC/E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAGD,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;IACF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAKD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,CAAC,EAAE;QACpB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;KAC5B,CAAC;IACF,aAAa,CAAC,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF,kBAAkB,CAAC,EAAE;QACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IACF,gBAAgB,CAAC,EAAE;QACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;QAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;KACnC,CAAC;IACF,+FAA+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,aAAa;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,wGAAwG;IACxG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACjD;AAGD,eAAO,MAAM,cAAc,EAAE,aA4E5B,CAAC;AAGF,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAAC,aAAa,CAoB1D,CAAC;AAGF,eAAO,MAAM,eAAe,EAAE,aAA8B,CAAC;AAG7D,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAarF"}
1
+ {"version":3,"file":"story-ui.config.d.ts","sourceRoot":"","sources":["../story-ui.config.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,3 @@
1
- declare global {
2
- interface Window {
3
- __STORY_UI_GENERATED_CODE__?: Record<string, string>;
4
- }
5
- }
6
1
  declare function StoryUIPanel(): import("react/jsx-runtime").JSX.Element;
7
2
  export default StoryUIPanel;
8
3
  export { StoryUIPanel };
@@ -1 +1 @@
1
- {"version":3,"file":"StoryUIPanel.d.ts","sourceRoot":"","sources":["../../../templates/StoryUI/StoryUIPanel.tsx"],"names":[],"mappings":"AAkTA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,2BAA2B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtD;CACF;AAooCD,iBAAS,YAAY,4CAkvCpB;AAED,eAAe,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"StoryUIPanel.d.ts","sourceRoot":"","sources":["../../../templates/StoryUI/StoryUIPanel.tsx"],"names":[],"mappings":"AAymDA,iBAAS,YAAY,4CAuyCpB;AAED,eAAe,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,CAAC"}