@tpitre/story-ui 2.6.1 → 2.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.
Files changed (295) hide show
  1. package/README.md +36 -37
  2. package/dist/cli/deploy.d.ts +4 -3
  3. package/dist/cli/deploy.d.ts.map +1 -1
  4. package/dist/cli/deploy.js +542 -46
  5. package/dist/cli/index.js +17 -14
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/setup.d.ts.map +1 -1
  8. package/dist/cli/setup.js +4 -110
  9. package/dist/cli/setup.js.map +1 -0
  10. package/dist/cloudflare-edge/src/mcp-session.js +462 -0
  11. package/dist/cloudflare-edge/src/types.js +4 -0
  12. package/dist/cloudflare-edge/src/worker.js +106 -0
  13. package/dist/cloudflare-pages/vite.config.js +14 -0
  14. package/dist/index.d.ts +13 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +12 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/mcp-server/index.js.map +1 -0
  19. package/dist/mcp-server/mcp-stdio-server.js.map +1 -0
  20. package/dist/mcp-server/routes/claude.js.map +1 -0
  21. package/dist/mcp-server/routes/components.js.map +1 -0
  22. package/dist/mcp-server/routes/generateStory.js.map +1 -0
  23. package/dist/mcp-server/routes/hybridStories.js.map +1 -0
  24. package/dist/mcp-server/routes/memoryStories.js.map +1 -0
  25. package/dist/mcp-server/routes/storySync.js.map +1 -0
  26. package/dist/mcp-server/routes/updateStory.js +246 -0
  27. package/dist/mcp-server/sessionManager.js.map +1 -0
  28. package/dist/playground/components/AIAssistant/AIAssistant.d.ts +6 -0
  29. package/dist/playground/components/AIAssistant/AIAssistant.d.ts.map +1 -0
  30. package/dist/playground/components/AIAssistant/AIAssistant.js +109 -0
  31. package/dist/playground/components/AIAssistant/AIAssistant.js.map +1 -0
  32. package/dist/playground/components/AIAssistant/AIAssistant.module.css +166 -0
  33. package/dist/playground/components/Canvas/Canvas.d.ts +9 -0
  34. package/dist/playground/components/Canvas/Canvas.d.ts.map +1 -0
  35. package/dist/playground/components/Canvas/Canvas.js +58 -0
  36. package/dist/playground/components/Canvas/Canvas.js.map +1 -0
  37. package/dist/playground/components/Canvas/Canvas.module.css +189 -0
  38. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts +9 -0
  39. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts.map +1 -0
  40. package/dist/playground/components/Canvas/CanvasWithDnd.js +158 -0
  41. package/dist/playground/components/Canvas/CanvasWithDnd.js.map +1 -0
  42. package/dist/playground/components/Canvas/ComponentRenderer.d.ts +15 -0
  43. package/dist/playground/components/Canvas/ComponentRenderer.d.ts.map +1 -0
  44. package/dist/playground/components/Canvas/ComponentRenderer.js +177 -0
  45. package/dist/playground/components/Canvas/ComponentRenderer.js.map +1 -0
  46. package/dist/playground/components/Canvas/DraggableComponent.d.ts +15 -0
  47. package/dist/playground/components/Canvas/DraggableComponent.d.ts.map +1 -0
  48. package/dist/playground/components/Canvas/DraggableComponent.js +49 -0
  49. package/dist/playground/components/Canvas/DraggableComponent.js.map +1 -0
  50. package/dist/playground/components/Canvas/index.d.ts +9 -0
  51. package/dist/playground/components/Canvas/index.d.ts.map +1 -0
  52. package/dist/playground/components/Canvas/index.js +5 -0
  53. package/dist/playground/components/Canvas/index.js.map +1 -0
  54. package/dist/playground/components/CodeView/CodeView.d.ts +12 -0
  55. package/dist/playground/components/CodeView/CodeView.d.ts.map +1 -0
  56. package/dist/playground/components/CodeView/CodeView.js +77 -0
  57. package/dist/playground/components/CodeView/CodeView.js.map +1 -0
  58. package/dist/playground/components/CodeView/CodeView.module.css +178 -0
  59. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts +17 -0
  60. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts.map +1 -0
  61. package/dist/playground/components/ComponentPalette/ComponentPalette.js +138 -0
  62. package/dist/playground/components/ComponentPalette/ComponentPalette.js.map +1 -0
  63. package/dist/playground/components/ComponentPalette/ComponentPalette.module.css +217 -0
  64. package/dist/playground/components/ComponentPalette/index.d.ts +3 -0
  65. package/dist/playground/components/ComponentPalette/index.d.ts.map +1 -0
  66. package/dist/playground/components/ComponentPalette/index.js +2 -0
  67. package/dist/playground/components/ComponentPalette/index.js.map +1 -0
  68. package/dist/playground/components/DropZone/DropZone.d.ts +17 -0
  69. package/dist/playground/components/DropZone/DropZone.d.ts.map +1 -0
  70. package/dist/playground/components/DropZone/DropZone.js +73 -0
  71. package/dist/playground/components/DropZone/DropZone.js.map +1 -0
  72. package/dist/playground/components/DropZone/DropZone.module.css +86 -0
  73. package/dist/playground/components/ExportDialog/ExportDialog.d.ts +10 -0
  74. package/dist/playground/components/ExportDialog/ExportDialog.d.ts.map +1 -0
  75. package/dist/playground/components/ExportDialog/ExportDialog.js +57 -0
  76. package/dist/playground/components/ExportDialog/ExportDialog.js.map +1 -0
  77. package/dist/playground/components/ExportDialog/ExportDialog.module.css +328 -0
  78. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts +134 -0
  79. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts.map +1 -0
  80. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js +254 -0
  81. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js.map +1 -0
  82. package/dist/playground/components/LayoutHelpers/index.d.ts +3 -0
  83. package/dist/playground/components/LayoutHelpers/index.d.ts.map +1 -0
  84. package/dist/playground/components/LayoutHelpers/index.js +2 -0
  85. package/dist/playground/components/LayoutHelpers/index.js.map +1 -0
  86. package/dist/playground/components/Playground/Playground.d.ts +10 -0
  87. package/dist/playground/components/Playground/Playground.d.ts.map +1 -0
  88. package/dist/playground/components/Playground/Playground.js +128 -0
  89. package/dist/playground/components/Playground/Playground.js.map +1 -0
  90. package/dist/playground/components/Playground/Playground.module.css +308 -0
  91. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts +10 -0
  92. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts.map +1 -0
  93. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js +150 -0
  94. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js.map +1 -0
  95. package/dist/playground/components/PropertiesPanel/PropertiesPanel.module.css +155 -0
  96. package/dist/playground/components/PropertiesPanel/index.d.ts +3 -0
  97. package/dist/playground/components/PropertiesPanel/index.d.ts.map +1 -0
  98. package/dist/playground/components/PropertiesPanel/index.js +2 -0
  99. package/dist/playground/components/PropertiesPanel/index.js.map +1 -0
  100. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts +12 -0
  101. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts.map +1 -0
  102. package/dist/playground/components/PropertyEditors/BooleanEditor.js +14 -0
  103. package/dist/playground/components/PropertyEditors/BooleanEditor.js.map +1 -0
  104. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts +12 -0
  105. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts.map +1 -0
  106. package/dist/playground/components/PropertyEditors/ColorEditor.js +62 -0
  107. package/dist/playground/components/PropertyEditors/ColorEditor.js.map +1 -0
  108. package/dist/playground/components/PropertyEditors/IconEditor.d.ts +12 -0
  109. package/dist/playground/components/PropertyEditors/IconEditor.d.ts.map +1 -0
  110. package/dist/playground/components/PropertyEditors/IconEditor.js +123 -0
  111. package/dist/playground/components/PropertyEditors/IconEditor.js.map +1 -0
  112. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts +15 -0
  113. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts.map +1 -0
  114. package/dist/playground/components/PropertyEditors/NumberEditor.js +46 -0
  115. package/dist/playground/components/PropertyEditors/NumberEditor.js.map +1 -0
  116. package/dist/playground/components/PropertyEditors/PropertyEditors.module.css +432 -0
  117. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts +19 -0
  118. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts.map +1 -0
  119. package/dist/playground/components/PropertyEditors/SelectEditor.js +17 -0
  120. package/dist/playground/components/PropertyEditors/SelectEditor.js.map +1 -0
  121. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts +19 -0
  122. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts.map +1 -0
  123. package/dist/playground/components/PropertyEditors/SpacingEditor.js +162 -0
  124. package/dist/playground/components/PropertyEditors/SpacingEditor.js.map +1 -0
  125. package/dist/playground/components/PropertyEditors/SpacingEditor.module.css +214 -0
  126. package/dist/playground/components/PropertyEditors/TextEditor.d.ts +14 -0
  127. package/dist/playground/components/PropertyEditors/TextEditor.d.ts.map +1 -0
  128. package/dist/playground/components/PropertyEditors/TextEditor.js +38 -0
  129. package/dist/playground/components/PropertyEditors/TextEditor.js.map +1 -0
  130. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts +23 -0
  131. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts.map +1 -0
  132. package/dist/playground/components/PropertyEditors/TokenEditor.js +50 -0
  133. package/dist/playground/components/PropertyEditors/TokenEditor.js.map +1 -0
  134. package/dist/playground/components/PropertyEditors/index.d.ts +20 -0
  135. package/dist/playground/components/PropertyEditors/index.d.ts.map +1 -0
  136. package/dist/playground/components/PropertyEditors/index.js +12 -0
  137. package/dist/playground/components/PropertyEditors/index.js.map +1 -0
  138. package/dist/playground/components/TreeView/TreeView.d.ts +10 -0
  139. package/dist/playground/components/TreeView/TreeView.d.ts.map +1 -0
  140. package/dist/playground/components/TreeView/TreeView.js +146 -0
  141. package/dist/playground/components/TreeView/TreeView.js.map +1 -0
  142. package/dist/playground/components/TreeView/TreeView.module.css +214 -0
  143. package/dist/playground/components/TreeView/index.d.ts +3 -0
  144. package/dist/playground/components/TreeView/index.d.ts.map +1 -0
  145. package/dist/playground/components/TreeView/index.js +2 -0
  146. package/dist/playground/components/TreeView/index.js.map +1 -0
  147. package/dist/playground/config/propertyDefinitions.d.ts +73 -0
  148. package/dist/playground/config/propertyDefinitions.d.ts.map +1 -0
  149. package/dist/playground/config/propertyDefinitions.js +809 -0
  150. package/dist/playground/config/propertyDefinitions.js.map +1 -0
  151. package/dist/playground/hooks/useKeyboardShortcuts.d.ts +38 -0
  152. package/dist/playground/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  153. package/dist/playground/hooks/useKeyboardShortcuts.js +191 -0
  154. package/dist/playground/hooks/useKeyboardShortcuts.js.map +1 -0
  155. package/dist/playground/index.d.ts +21 -0
  156. package/dist/playground/index.d.ts.map +1 -0
  157. package/dist/playground/index.js +23 -0
  158. package/dist/playground/index.js.map +1 -0
  159. package/dist/playground/services/CodeGenerator.d.ts +73 -0
  160. package/dist/playground/services/CodeGenerator.d.ts.map +1 -0
  161. package/dist/playground/services/CodeGenerator.js +359 -0
  162. package/dist/playground/services/CodeGenerator.js.map +1 -0
  163. package/dist/playground/services/DragDropManager.d.ts +95 -0
  164. package/dist/playground/services/DragDropManager.d.ts.map +1 -0
  165. package/dist/playground/services/DragDropManager.js +408 -0
  166. package/dist/playground/services/DragDropManager.js.map +1 -0
  167. package/dist/playground/services/StoryParser.d.ts +73 -0
  168. package/dist/playground/services/StoryParser.d.ts.map +1 -0
  169. package/dist/playground/services/StoryParser.js +419 -0
  170. package/dist/playground/services/StoryParser.js.map +1 -0
  171. package/dist/playground/store/playgroundStore.d.ts +86 -0
  172. package/dist/playground/store/playgroundStore.d.ts.map +1 -0
  173. package/dist/playground/store/playgroundStore.js +337 -0
  174. package/dist/playground/store/playgroundStore.js.map +1 -0
  175. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts +13 -0
  176. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts.map +1 -0
  177. package/dist/playground/stories/PlaygroundDragDrop.stories.js +227 -0
  178. package/dist/playground/stories/PlaygroundDragDrop.stories.js.map +1 -0
  179. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts +13 -0
  180. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts.map +1 -0
  181. package/dist/playground/stories/PlaygroundPhase4.stories.js +334 -0
  182. package/dist/playground/stories/PlaygroundPhase4.stories.js.map +1 -0
  183. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts +14 -0
  184. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts.map +1 -0
  185. package/dist/playground/stories/PlaygroundPhase5.stories.js +512 -0
  186. package/dist/playground/stories/PlaygroundPhase5.stories.js.map +1 -0
  187. package/dist/playground/stories/PlaygroundProperties.stories.d.ts +13 -0
  188. package/dist/playground/stories/PlaygroundProperties.stories.d.ts.map +1 -0
  189. package/dist/playground/stories/PlaygroundProperties.stories.js +342 -0
  190. package/dist/playground/stories/PlaygroundProperties.stories.js.map +1 -0
  191. package/dist/playground/types/index.d.ts +251 -0
  192. package/dist/playground/types/index.d.ts.map +1 -0
  193. package/dist/playground/types/index.js +5 -0
  194. package/dist/playground/types/index.js.map +1 -0
  195. package/dist/scripts/verify-framework-adapters.js +105 -0
  196. package/dist/story-generator/componentBlacklist.js.map +1 -0
  197. package/dist/story-generator/componentDiscovery.js.map +1 -0
  198. package/dist/story-generator/configLoader.js.map +1 -0
  199. package/dist/story-generator/considerationsLoader.js.map +1 -0
  200. package/dist/story-generator/documentation-sources.js.map +1 -0
  201. package/dist/story-generator/documentationLoader.js.map +1 -0
  202. package/dist/story-generator/dynamicPackageDiscovery.js.map +1 -0
  203. package/dist/story-generator/enhancedComponentDiscovery.d.ts.map +1 -1
  204. package/dist/story-generator/enhancedComponentDiscovery.js +4 -6
  205. package/dist/story-generator/enhancedComponentDiscovery.js.map +1 -0
  206. package/dist/story-generator/generateStory.js.map +1 -0
  207. package/dist/story-generator/gitignoreManager.js.map +1 -0
  208. package/dist/story-generator/inMemoryStoryService.js.map +1 -0
  209. package/dist/story-generator/llm-providers/settings-manager.js +4 -4
  210. package/dist/story-generator/logger.js.map +1 -0
  211. package/dist/story-generator/postProcessStory.js.map +1 -0
  212. package/dist/story-generator/productionGitignoreManager.d.ts.map +1 -1
  213. package/dist/story-generator/productionGitignoreManager.js +6 -0
  214. package/dist/story-generator/productionGitignoreManager.js.map +1 -0
  215. package/dist/story-generator/promptGenerator.js.map +1 -0
  216. package/dist/story-generator/providerPresets.d.ts +54 -0
  217. package/dist/story-generator/providerPresets.d.ts.map +1 -0
  218. package/dist/story-generator/providerPresets.js +214 -0
  219. package/dist/story-generator/storyHistory.js.map +1 -0
  220. package/dist/story-generator/storySync.js.map +1 -0
  221. package/dist/story-generator/storyTracker.js.map +1 -0
  222. package/dist/story-generator/storyValidator.js.map +1 -0
  223. package/dist/story-generator/test_validation.d.ts +2 -0
  224. package/dist/story-generator/test_validation.d.ts.map +1 -0
  225. package/dist/story-generator/test_validation.js +51 -0
  226. package/dist/story-generator/universalDesignSystemAdapter.js.map +1 -0
  227. package/dist/story-generator/urlRedirectService.js.map +1 -0
  228. package/dist/story-generator/validateStory.js.map +1 -0
  229. package/dist/story-ui.config.js.map +1 -0
  230. package/dist/story-ui.config.loader.d.ts +36 -0
  231. package/dist/story-ui.config.loader.d.ts.map +1 -0
  232. package/dist/story-ui.config.loader.js +205 -0
  233. package/dist/story-ui.config.loader.js.map +1 -0
  234. package/dist/temp/package/templates/StoryUI/StoryUIPanel.js +807 -0
  235. package/dist/temp/package/templates/StoryUI/StoryUIPanel.stories.js +37 -0
  236. package/dist/temp/package/templates/StoryUI/index.js +2 -0
  237. package/dist/templates/StoryUI/StoryUIPanel.js.map +1 -0
  238. package/dist/templates/StoryUI/StoryUIPanel.stories.js.map +1 -0
  239. package/dist/templates/StoryUI/index.js.map +1 -0
  240. package/dist/templates/StoryUI/manager.d.ts +14 -0
  241. package/dist/templates/StoryUI/manager.d.ts.map +1 -0
  242. package/dist/templates/production-app/src/App.d.ts +10 -0
  243. package/dist/templates/production-app/src/App.d.ts.map +1 -0
  244. package/dist/templates/production-app/src/App.js +653 -0
  245. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts +24 -0
  246. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts.map +1 -0
  247. package/dist/templates/production-app/src/LivePreviewRenderer.js +199 -0
  248. package/dist/templates/production-app/src/componentRegistry.d.ts +20 -0
  249. package/dist/templates/production-app/src/componentRegistry.d.ts.map +1 -0
  250. package/dist/templates/production-app/src/componentRegistry.js +316 -0
  251. package/dist/templates/production-app/src/main.d.ts +9 -0
  252. package/dist/templates/production-app/src/main.d.ts.map +1 -0
  253. package/dist/templates/production-app/src/main.js +18 -0
  254. package/dist/templates/production-app/vite.config.d.ts +3 -0
  255. package/dist/templates/production-app/vite.config.d.ts.map +1 -0
  256. package/dist/templates/production-app/vite.config.js +71 -0
  257. package/dist/test-storybooks/angular-material-storybook/src/main.js +66 -0
  258. package/dist/test-storybooks/chakra-storybook/vite.config.js +6 -0
  259. package/dist/test-storybooks/mantine-storybook/vite.config.js +93 -0
  260. package/dist/test-storybooks/web-components-shoelace/vite.config.js +9 -0
  261. package/dist/tsconfig.tsbuildinfo +1 -0
  262. package/dist/visual-builder/components/Canvas/Canvas.js +70 -0
  263. package/dist/visual-builder/components/Canvas/ComponentRenderer.js +545 -0
  264. package/dist/visual-builder/components/CodeExporter/CodeExporter.js +25 -0
  265. package/dist/visual-builder/components/CodeExporter/codeGenerator.js +99 -0
  266. package/dist/visual-builder/components/ComponentPalette/ComponentPalette.js +8 -0
  267. package/dist/visual-builder/components/ComponentPalette/ComponentPaletteItem.js +51 -0
  268. package/dist/visual-builder/components/EmbeddedVisualBuilder.js +107 -0
  269. package/dist/visual-builder/components/PropertyEditor/PropertyEditor.js +16 -0
  270. package/dist/visual-builder/components/PropertyEditor/PropertyForm.js +88 -0
  271. package/dist/visual-builder/components/PropertyEditor/SpacingControl.js +145 -0
  272. package/dist/visual-builder/components/PropertyEditor/SpacingEditor.js +32 -0
  273. package/dist/visual-builder/components/StoryManager/SaveOnlyManager.js +94 -0
  274. package/dist/visual-builder/components/StoryManager/StoryManager.js +68 -0
  275. package/dist/visual-builder/components/StoryManager/index.js +1 -0
  276. package/dist/visual-builder/components/VisualBuilder.js +256 -0
  277. package/dist/visual-builder/config/componentRegistry.js +1758 -0
  278. package/dist/visual-builder/decorators/VisualBuilderDecorator.js +184 -0
  279. package/dist/visual-builder/example-integration.js +59 -0
  280. package/dist/visual-builder/example.js +23 -0
  281. package/dist/visual-builder/hooks/useDragAndDrop.js +137 -0
  282. package/dist/visual-builder/hooks/useSelection.js +27 -0
  283. package/dist/visual-builder/index.js +7 -0
  284. package/dist/visual-builder/store/visualBuilderStore.js +305 -0
  285. package/dist/visual-builder/types/index.js +1 -0
  286. package/dist/visual-builder/utils/__tests__/storyFileUpdater.test.js +145 -0
  287. package/dist/visual-builder/utils/aiParser.js +336 -0
  288. package/dist/visual-builder/utils/componentTreeUtils.js +111 -0
  289. package/dist/visual-builder/utils/parserValidation.js +122 -0
  290. package/dist/visual-builder/utils/storyFileManager.js +73 -0
  291. package/dist/visual-builder/utils/storyFileUpdater.js +326 -0
  292. package/dist/visual-builder/utils/storyNameExtraction.test.js +211 -0
  293. package/dist/visual-builder/utils/storyPersistence.js +180 -0
  294. package/dist/visual-builder/utils/storyToBuilder.js +813 -0
  295. package/package.json +1 -1
@@ -0,0 +1,813 @@
1
+ // Component type mappings from JSX to Visual Builder format
2
+ const COMPONENT_TYPE_MAP = {
3
+ 'Container': 'Container',
4
+ 'Stack': 'Stack',
5
+ 'SimpleGrid': 'SimpleGrid',
6
+ 'Card': 'Card',
7
+ 'Card.Section': 'CardSection',
8
+ 'Image': 'Image',
9
+ 'Text': 'Text',
10
+ 'Title': 'Title',
11
+ 'Badge': 'Badge',
12
+ 'Button': 'Button',
13
+ 'Group': 'Group',
14
+ 'Avatar': 'Avatar',
15
+ 'div': 'Box',
16
+ 'span': 'Text',
17
+ // Add more mappings as needed
18
+ };
19
+ // Category mappings for Visual Builder
20
+ const COMPONENT_CATEGORIES = {
21
+ 'Container': 'Layout',
22
+ 'Stack': 'Layout',
23
+ 'SimpleGrid': 'Layout',
24
+ 'Group': 'Layout',
25
+ 'Box': 'Layout',
26
+ 'Card': 'Data Display',
27
+ 'CardSection': 'Data Display',
28
+ 'Image': 'Data Display',
29
+ 'Avatar': 'Data Display',
30
+ 'Text': 'Typography',
31
+ 'Title': 'Typography',
32
+ 'Badge': 'Feedback',
33
+ 'Button': 'Inputs',
34
+ };
35
+ /**
36
+ * Extracts JSX from a React story component render function
37
+ */
38
+ export function extractJSXFromStory(storyCode) {
39
+ try {
40
+ console.log('🔍 Extracting JSX from story code:', {
41
+ length: storyCode.length,
42
+ hasTransformed: storyCode.includes('__vite__') || storyCode.includes('_jsxDEV'),
43
+ preview: storyCode.substring(0, 300) + '...'
44
+ });
45
+ // Check for Vite-transformed code and reject it
46
+ if (storyCode.includes('__vite__cjsImport') || storyCode.includes('_jsxDEV') || storyCode.includes('import.meta.hot')) {
47
+ console.error('❌ Detected Vite-transformed code - cannot parse');
48
+ throw new Error('Received Vite-transformed code instead of source code. Cannot parse transformed JSX.');
49
+ }
50
+ // Check if this is the placeholder template
51
+ if (storyCode.includes('Component ready for editing in Visual Builder')) {
52
+ console.error('❌ Detected placeholder template - source code fetch failed');
53
+ throw new Error('Received placeholder template instead of actual story source. Please check if the Story UI server is running correctly.');
54
+ }
55
+ // Match the render function and extract its return JSX
56
+ const renderMatch = storyCode.match(/render:\s*\(\)\s*=>\s*\(([\s\S]*?)\)\s*[,}]/);
57
+ if (renderMatch) {
58
+ console.log('✅ Found JSX in render function');
59
+ return renderMatch[1].trim();
60
+ }
61
+ // Fallback: try to find JSX in return statement
62
+ const returnMatch = storyCode.match(/return\s*\(([\s\S]*?)\);?\s*}/);
63
+ if (returnMatch) {
64
+ console.log('✅ Found JSX in return statement');
65
+ return returnMatch[1].trim();
66
+ }
67
+ // Fallback: try to find JSX after => without parentheses
68
+ const arrowMatch = storyCode.match(/=>\s*([<][\s\S]*?)(?=;|\n|$)/);
69
+ if (arrowMatch) {
70
+ console.log('✅ Found JSX after arrow function');
71
+ return arrowMatch[1].trim();
72
+ }
73
+ // Fallback: try to find JSX in parentheses after =>
74
+ const arrowParenMatch = storyCode.match(/=>\s*\(([\s\S]*?)\)/);
75
+ if (arrowParenMatch) {
76
+ console.log('✅ Found JSX in parentheses after arrow');
77
+ return arrowParenMatch[1].trim();
78
+ }
79
+ console.warn('⚠️ No JSX pattern matched, returning original code');
80
+ return storyCode;
81
+ }
82
+ catch (error) {
83
+ console.error('❌ Error extracting JSX from story:', error);
84
+ throw error;
85
+ }
86
+ }
87
+ /**
88
+ * Parses JSX attributes into props object
89
+ */
90
+ function parseAttributes(attributeString) {
91
+ const props = {};
92
+ if (!attributeString.trim()) {
93
+ return props;
94
+ }
95
+ try {
96
+ // Improved attribute parsing to handle nested braces in style objects
97
+ const parseAttributeString = (str) => {
98
+ const attrs = [];
99
+ let current = '';
100
+ let braceDepth = 0;
101
+ let inQuotes = false;
102
+ let quoteChar = '';
103
+ for (let i = 0; i < str.length; i++) {
104
+ const char = str[i];
105
+ if (!inQuotes) {
106
+ if (char === '"' || char === "'") {
107
+ inQuotes = true;
108
+ quoteChar = char;
109
+ }
110
+ else if (char === '{') {
111
+ braceDepth++;
112
+ }
113
+ else if (char === '}') {
114
+ braceDepth--;
115
+ }
116
+ else if (char === ' ' && braceDepth === 0 && current && current.includes('=')) {
117
+ attrs.push(current);
118
+ current = '';
119
+ continue;
120
+ }
121
+ }
122
+ else if (char === quoteChar && str[i - 1] !== '\\') {
123
+ inQuotes = false;
124
+ quoteChar = '';
125
+ }
126
+ current += char;
127
+ }
128
+ if (current) {
129
+ attrs.push(current);
130
+ }
131
+ return attrs;
132
+ };
133
+ const attributes = parseAttributeString(attributeString);
134
+ for (const attr of attributes) {
135
+ if (!attr.trim())
136
+ continue;
137
+ const eqIndex = attr.indexOf('=');
138
+ if (eqIndex === -1) {
139
+ // Boolean attribute
140
+ props[attr.trim()] = true;
141
+ continue;
142
+ }
143
+ const key = attr.substring(0, eqIndex).trim();
144
+ let value = attr.substring(eqIndex + 1).trim();
145
+ // Remove quotes
146
+ if ((value.startsWith('"') && value.endsWith('"')) ||
147
+ (value.startsWith("'") && value.endsWith("'"))) {
148
+ value = value.slice(1, -1);
149
+ props[key] = value;
150
+ }
151
+ else if (value.startsWith('{') && value.endsWith('}')) {
152
+ // Handle JSX expressions
153
+ const expression = value.slice(1, -1);
154
+ // Special handling for style prop - parse as object
155
+ if (key === 'style' && expression.startsWith('{') && expression.endsWith('}')) {
156
+ try {
157
+ // Parse style object - convert JS object syntax to JSON
158
+ const styleStr = expression.slice(1, -1); // Remove outer braces
159
+ const jsonStr = styleStr
160
+ .replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2":') // Quote keys
161
+ .replace(/'/g, '"'); // Single to double quotes
162
+ console.log('🎨 Parsing style:', { original: expression, converted: jsonStr });
163
+ // Try to parse as JSON
164
+ const parsedStyle = JSON.parse(`{${jsonStr}}`);
165
+ // Sanitize arrays in style properties
166
+ const sanitizedStyle = {};
167
+ for (const [styleProp, styleValue] of Object.entries(parsedStyle)) {
168
+ if (Array.isArray(styleValue)) {
169
+ // Convert array to string using first value
170
+ sanitizedStyle[styleProp] = String(styleValue[0]);
171
+ }
172
+ else {
173
+ sanitizedStyle[styleProp] = styleValue;
174
+ }
175
+ }
176
+ props[key] = sanitizedStyle;
177
+ console.log('✅ Successfully parsed style object:', props[key]);
178
+ }
179
+ catch (e) {
180
+ // If JSON parsing fails, try to parse manually
181
+ const styleObj = {};
182
+ const stylePairs = expression.slice(1, -1).split(',');
183
+ for (const pair of stylePairs) {
184
+ const colonIndex = pair.indexOf(':');
185
+ if (colonIndex > -1) {
186
+ const styleProp = pair.substring(0, colonIndex).trim().replace(/['"]/g, '');
187
+ let styleValue = pair.substring(colonIndex + 1).trim();
188
+ // Check if value looks like an array (e.g., "[14, 16, 18]")
189
+ if (styleValue.startsWith('[') && styleValue.endsWith(']')) {
190
+ // Extract first value from array
191
+ const arrayContent = styleValue.slice(1, -1).split(',')[0].trim();
192
+ styleValue = arrayContent;
193
+ }
194
+ // Remove quotes if present
195
+ if ((styleValue.startsWith('"') && styleValue.endsWith('"')) ||
196
+ (styleValue.startsWith("'") && styleValue.endsWith("'"))) {
197
+ styleValue = styleValue.slice(1, -1);
198
+ }
199
+ else if (/^\d+$/.test(styleValue)) {
200
+ // Preserve numeric values as numbers
201
+ styleValue = parseInt(styleValue, 10);
202
+ }
203
+ else if (/^\d*\.\d+$/.test(styleValue)) {
204
+ // Preserve decimal values as numbers
205
+ styleValue = parseFloat(styleValue);
206
+ }
207
+ else {
208
+ // Remove any remaining quotes
209
+ styleValue = styleValue.replace(/['"]/g, '');
210
+ }
211
+ // Convert camelCase to kebab-case for CSS properties if needed
212
+ // But keep camelCase for React style props
213
+ styleObj[styleProp] = styleValue;
214
+ }
215
+ }
216
+ props[key] = styleObj;
217
+ }
218
+ }
219
+ else if (expression === 'true' || expression === 'false') {
220
+ props[key] = expression === 'true';
221
+ }
222
+ else if (/^\d+$/.test(expression)) {
223
+ props[key] = parseInt(expression, 10);
224
+ }
225
+ else if (/^\d*\.\d+$/.test(expression)) {
226
+ props[key] = parseFloat(expression);
227
+ }
228
+ else if (expression.startsWith('"') && expression.endsWith('"')) {
229
+ props[key] = expression.slice(1, -1);
230
+ }
231
+ else {
232
+ // Keep as string for complex expressions
233
+ props[key] = expression;
234
+ }
235
+ }
236
+ else {
237
+ props[key] = value;
238
+ }
239
+ }
240
+ }
241
+ catch (error) {
242
+ console.error('Error parsing attributes:', error);
243
+ }
244
+ return props;
245
+ }
246
+ /**
247
+ * Advanced JSX tokenizer that properly handles nested structures
248
+ */
249
+ function tokenizeJSX(jsx) {
250
+ const tokens = [];
251
+ let i = 0;
252
+ while (i < jsx.length) {
253
+ // Skip whitespace at the beginning
254
+ while (i < jsx.length && /\s/.test(jsx[i])) {
255
+ i++;
256
+ }
257
+ if (i >= jsx.length)
258
+ break;
259
+ // Handle JSX elements
260
+ if (jsx[i] === '<') {
261
+ const tokenStart = i;
262
+ i++; // skip '<'
263
+ // Check for comment
264
+ if (jsx.substring(i, i + 3) === '!--') {
265
+ // Skip comment
266
+ const commentEnd = jsx.indexOf('-->', i);
267
+ if (commentEnd !== -1) {
268
+ i = commentEnd + 3;
269
+ continue;
270
+ }
271
+ }
272
+ // Check for closing tag
273
+ const isClosingTag = jsx[i] === '/';
274
+ if (isClosingTag) {
275
+ i++; // skip '/'
276
+ }
277
+ // Extract tag name
278
+ let tagName = '';
279
+ while (i < jsx.length && /[a-zA-Z0-9._]/.test(jsx[i])) {
280
+ tagName += jsx[i];
281
+ i++;
282
+ }
283
+ if (!tagName) {
284
+ i++; // skip invalid character
285
+ continue;
286
+ }
287
+ // Handle closing tag
288
+ if (isClosingTag) {
289
+ // Skip to closing >
290
+ while (i < jsx.length && jsx[i] !== '>') {
291
+ i++;
292
+ }
293
+ if (jsx[i] === '>')
294
+ i++;
295
+ tokens.push({
296
+ type: 'tag_close',
297
+ content: jsx.substring(tokenStart, i),
298
+ tagName,
299
+ position: { start: tokenStart, end: i }
300
+ });
301
+ continue;
302
+ }
303
+ // Extract attributes for opening tag
304
+ let attributes = '';
305
+ let inString = false;
306
+ let stringChar = '';
307
+ let braceDepth = 0;
308
+ while (i < jsx.length) {
309
+ const char = jsx[i];
310
+ if (!inString) {
311
+ if (char === '"' || char === "'") {
312
+ inString = true;
313
+ stringChar = char;
314
+ }
315
+ else if (char === '{') {
316
+ braceDepth++;
317
+ }
318
+ else if (char === '}') {
319
+ braceDepth--;
320
+ }
321
+ else if (char === '>' && braceDepth === 0) {
322
+ break; // Found end of opening tag
323
+ }
324
+ else if (char === '/' && jsx[i + 1] === '>' && braceDepth === 0) {
325
+ // Self-closing tag
326
+ break;
327
+ }
328
+ }
329
+ else if (char === stringChar && jsx[i - 1] !== '\\') {
330
+ inString = false;
331
+ stringChar = '';
332
+ }
333
+ attributes += char;
334
+ i++;
335
+ }
336
+ // Check for self-closing tag
337
+ const isSelfClosing = jsx[i] === '/' && jsx[i + 1] === '>';
338
+ if (isSelfClosing) {
339
+ i += 2; // skip '/>'
340
+ tokens.push({
341
+ type: 'tag_self_close',
342
+ content: jsx.substring(tokenStart, i),
343
+ tagName,
344
+ attributes: attributes.trim(),
345
+ position: { start: tokenStart, end: i }
346
+ });
347
+ }
348
+ else if (jsx[i] === '>') {
349
+ i++; // skip '>'
350
+ tokens.push({
351
+ type: 'tag_open',
352
+ content: jsx.substring(tokenStart, i),
353
+ tagName,
354
+ attributes: attributes.trim(),
355
+ position: { start: tokenStart, end: i }
356
+ });
357
+ }
358
+ }
359
+ else {
360
+ // Handle text content
361
+ const textStart = i;
362
+ let textContent = '';
363
+ while (i < jsx.length && jsx[i] !== '<') {
364
+ textContent += jsx[i];
365
+ i++;
366
+ }
367
+ const trimmedText = textContent.trim();
368
+ if (trimmedText) {
369
+ tokens.push({
370
+ type: 'text',
371
+ content: trimmedText,
372
+ position: { start: textStart, end: i }
373
+ });
374
+ }
375
+ }
376
+ }
377
+ return tokens;
378
+ }
379
+ /**
380
+ * Recursively parses JSX tokens into ComponentDefinition tree using stack-based approach
381
+ */
382
+ function parseJSXElement(jsx, idCounter) {
383
+ const components = [];
384
+ try {
385
+ jsx = jsx.trim();
386
+ if (!jsx)
387
+ return components;
388
+ // Handle pure text content
389
+ if (!jsx.startsWith('<')) {
390
+ const textContent = jsx.replace(/^\{|\}$/g, '').trim();
391
+ if (textContent && textContent !== '') {
392
+ components.push({
393
+ id: `text-${idCounter.value++}`,
394
+ type: 'Text',
395
+ displayName: 'Text',
396
+ category: 'Typography',
397
+ props: {
398
+ children: textContent.replace(/^["']|["']$/g, '')
399
+ }
400
+ });
401
+ }
402
+ return components;
403
+ }
404
+ // Tokenize the JSX
405
+ const tokens = tokenizeJSX(jsx);
406
+ console.log('🔍 Tokenized JSX:', tokens.map(t => `${t.type}:${t.tagName || t.content?.substring(0, 20)}`));
407
+ // Use corrected stack-based parsing to build component tree
408
+ const parseStack = [];
409
+ const childrenStack = [];
410
+ let currentChildren = [];
411
+ for (const token of tokens) {
412
+ console.log(`🔧 Processing token: ${token.type} - ${token.tagName || token.content?.substring(0, 30)}`);
413
+ switch (token.type) {
414
+ case 'tag_open': {
415
+ // Create new component
416
+ const tagName = token.tagName;
417
+ const componentType = COMPONENT_TYPE_MAP[tagName] || tagName;
418
+ const category = COMPONENT_CATEGORIES[componentType] || 'Other';
419
+ const props = parseAttributes(token.attributes || '');
420
+ const component = {
421
+ id: `${componentType.toLowerCase().replace('.', '-')}-${idCounter.value++}`,
422
+ type: componentType,
423
+ displayName: componentType,
424
+ category,
425
+ props
426
+ };
427
+ console.log(`📦 Created component: ${component.type} (${component.id})`);
428
+ // Push current state onto stack before processing this component
429
+ if (parseStack.length > 0 || currentChildren.length > 0) {
430
+ parseStack.push(component);
431
+ childrenStack.push(currentChildren);
432
+ currentChildren = [];
433
+ console.log(`📚 Pushed to stack. Stack depth: ${parseStack.length}`);
434
+ }
435
+ else {
436
+ // This is a potential root component
437
+ parseStack.push(component);
438
+ childrenStack.push([]);
439
+ currentChildren = [];
440
+ console.log(`🌳 Started root component: ${component.type}`);
441
+ }
442
+ break;
443
+ }
444
+ case 'tag_self_close': {
445
+ // Create self-closing component
446
+ const tagName = token.tagName;
447
+ const componentType = COMPONENT_TYPE_MAP[tagName] || tagName;
448
+ const category = COMPONENT_CATEGORIES[componentType] || 'Other';
449
+ const props = parseAttributes(token.attributes || '');
450
+ const component = {
451
+ id: `${componentType.toLowerCase().replace('.', '-')}-${idCounter.value++}`,
452
+ type: componentType,
453
+ displayName: componentType,
454
+ category,
455
+ props
456
+ };
457
+ console.log(`🏷️ Created self-closing: ${component.type} (${component.id})`);
458
+ // Add to current children
459
+ currentChildren.push(component);
460
+ console.log(`👶 Added to current children. Children count: ${currentChildren.length}`);
461
+ break;
462
+ }
463
+ case 'tag_close': {
464
+ // Complete current component and pop from stack
465
+ if (parseStack.length > 0) {
466
+ const completedComponent = parseStack.pop();
467
+ const parentChildren = childrenStack.pop();
468
+ // Assign accumulated children to the completed component
469
+ if (currentChildren.length > 0) {
470
+ completedComponent.children = [...currentChildren];
471
+ console.log(`✅ Assigned ${currentChildren.length} children to ${completedComponent.type}`);
472
+ }
473
+ console.log(`🔚 Completing component: ${completedComponent.type} with ${completedComponent.children?.length || 0} children`);
474
+ // Add completed component to parent's children or root
475
+ if (parseStack.length > 0) {
476
+ // Add to parent's children (which becomes new currentChildren)
477
+ currentChildren = parentChildren;
478
+ currentChildren.push(completedComponent);
479
+ console.log(`👨‍👩‍👧‍👦 Added ${completedComponent.type} to parent children. Parent children count: ${currentChildren.length}`);
480
+ }
481
+ else {
482
+ // This is a root component
483
+ components.push(completedComponent);
484
+ currentChildren = parentChildren;
485
+ console.log(`🌳 Added root component: ${completedComponent.type}`);
486
+ }
487
+ }
488
+ break;
489
+ }
490
+ case 'text': {
491
+ // Handle text content
492
+ const textContent = token.content.replace(/^\{|\}$/g, '').trim();
493
+ if (textContent && textContent.length > 0) {
494
+ // Check if this text should be inline content for the current component
495
+ if (parseStack.length > 0 && !parseStack[parseStack.length - 1].children) {
496
+ // Add as inline text content to the current component
497
+ parseStack[parseStack.length - 1].props.children = textContent.replace(/^["']|["']$/g, '');
498
+ console.log(`📝 Added inline text to ${parseStack[parseStack.length - 1].type}: "${textContent.substring(0, 30)}..."`);
499
+ }
500
+ else {
501
+ // Create a text component
502
+ const textComponent = {
503
+ id: `text-${idCounter.value++}`,
504
+ type: 'Text',
505
+ displayName: 'Text',
506
+ category: 'Typography',
507
+ props: {
508
+ children: textContent.replace(/^["']|["']$/g, '')
509
+ }
510
+ };
511
+ currentChildren.push(textComponent);
512
+ console.log(`📄 Created text component: "${textContent.substring(0, 30)}..."`);
513
+ }
514
+ }
515
+ break;
516
+ }
517
+ }
518
+ }
519
+ // Handle any remaining components on stack (error recovery)
520
+ while (parseStack.length > 0) {
521
+ const orphanComponent = parseStack.pop();
522
+ childrenStack.pop();
523
+ if (currentChildren.length > 0) {
524
+ orphanComponent.children = [...currentChildren];
525
+ currentChildren = [];
526
+ }
527
+ components.push(orphanComponent);
528
+ console.log(`🚨 Recovered orphan component: ${orphanComponent.type}`);
529
+ }
530
+ console.log(`✨ Parsing complete. Generated ${components.length} root components.`);
531
+ }
532
+ catch (error) {
533
+ console.error('❌ Error parsing JSX elements:', error);
534
+ }
535
+ return components;
536
+ }
537
+ /**
538
+ * Helper function to get original JSX tag name from component type
539
+ */
540
+ function getOriginalTagName(componentType) {
541
+ // Handle the reverse mapping more reliably
542
+ const reverseMap = {
543
+ 'Container': 'Container',
544
+ 'Stack': 'Stack',
545
+ 'SimpleGrid': 'SimpleGrid',
546
+ 'Card': 'Card',
547
+ 'CardSection': 'Card.Section',
548
+ 'Image': 'Image',
549
+ 'Text': 'Text',
550
+ 'Title': 'Title',
551
+ 'Badge': 'Badge',
552
+ 'Button': 'Button',
553
+ 'Group': 'Group',
554
+ 'Avatar': 'Avatar',
555
+ 'Box': 'div'
556
+ };
557
+ return reverseMap[componentType] || componentType;
558
+ }
559
+ /**
560
+ * Parses a single JSX element into ComponentDefinition - now handles proper nesting
561
+ */
562
+ function parseSingleJSXElement(jsx, idCounter) {
563
+ try {
564
+ jsx = jsx.trim();
565
+ // Use the new tokenized approach for single elements too
566
+ const tokens = tokenizeJSX(jsx);
567
+ if (tokens.length === 0) {
568
+ return null;
569
+ }
570
+ // For single elements, we should have at most one opening tag and one closing tag
571
+ const firstToken = tokens[0];
572
+ if (firstToken.type === 'tag_self_close') {
573
+ // Self-closing tag
574
+ const tagName = firstToken.tagName;
575
+ const componentType = COMPONENT_TYPE_MAP[tagName] || tagName;
576
+ const category = COMPONENT_CATEGORIES[componentType] || 'Other';
577
+ const props = parseAttributes(firstToken.attributes || '');
578
+ return {
579
+ id: `${componentType.toLowerCase()}-${idCounter.value++}`,
580
+ type: componentType,
581
+ displayName: componentType,
582
+ category,
583
+ props
584
+ };
585
+ }
586
+ else if (firstToken.type === 'tag_open') {
587
+ // Opening tag - parse the full structure
588
+ const components = parseJSXElement(jsx, idCounter);
589
+ return components.length > 0 ? components[0] : null;
590
+ }
591
+ return null;
592
+ }
593
+ catch (error) {
594
+ console.error('Error parsing single JSX element:', error);
595
+ return null;
596
+ }
597
+ }
598
+ /**
599
+ * Main function to parse Story UI content into Visual Builder format
600
+ */
601
+ export function parseStoryUIToBuilder(storyCode) {
602
+ const result = {
603
+ components: [],
604
+ errors: [],
605
+ warnings: []
606
+ };
607
+ try {
608
+ console.log('🚀 Starting to parse story code for Visual Builder', {
609
+ codeLength: storyCode.length,
610
+ hasCard: storyCode.includes('<Card'),
611
+ hasCardSection: storyCode.includes('Card.Section'),
612
+ hasBadge: storyCode.includes('<Badge'),
613
+ hasStack: storyCode.includes('<Stack'),
614
+ hasImage: storyCode.includes('<Image'),
615
+ firstLine: storyCode.split('\n')[0],
616
+ preview: storyCode.substring(0, 300)
617
+ });
618
+ // Check for placeholder template
619
+ if (storyCode.includes('Component ready for editing in Visual Builder')) {
620
+ const error = '⚠️ Received placeholder template instead of actual story source. The source code was not properly fetched from the server.';
621
+ console.error('❌ Placeholder template detected');
622
+ result.errors.push(error);
623
+ return result;
624
+ }
625
+ // Check for transformed code early and provide clear error
626
+ if (storyCode.includes('__vite__cjsImport') || storyCode.includes('_jsxDEV') || storyCode.includes('import.meta.hot')) {
627
+ const error = 'Visual Builder received Vite-transformed code instead of source code. Please ensure the raw source endpoint is working correctly.';
628
+ console.error('❌', error);
629
+ result.errors.push(error);
630
+ return result;
631
+ }
632
+ // Extract JSX from the story
633
+ const jsx = extractJSXFromStory(storyCode);
634
+ console.log('📝 Extracted JSX:', {
635
+ hasJSX: !!jsx,
636
+ jsxLength: jsx?.length || 0,
637
+ jsxPreview: jsx?.substring(0, 200)
638
+ });
639
+ if (!jsx) {
640
+ result.errors.push('No JSX content found in story');
641
+ return result;
642
+ }
643
+ console.log('📝 Extracted JSX:', jsx.substring(0, 200) + '...');
644
+ // Parse JSX into component tree
645
+ const idCounter = { value: 1 };
646
+ const components = parseJSXElement(jsx, idCounter);
647
+ if (components.length === 0) {
648
+ result.warnings.push('No components were parsed from the JSX');
649
+ }
650
+ else {
651
+ console.log(`✅ Successfully parsed ${components.length} components`);
652
+ // Log component structure for debugging
653
+ const logComponentStructure = (comps, depth = 0) => {
654
+ comps.forEach(comp => {
655
+ console.log(`${' '.repeat(depth)}📦 ${comp.type} (${comp.id}) - children: ${comp.children?.length || 0}`);
656
+ if (comp.children?.length) {
657
+ logComponentStructure(comp.children, depth + 1);
658
+ }
659
+ });
660
+ };
661
+ console.log('🌳 Component tree structure:');
662
+ logComponentStructure(components);
663
+ }
664
+ result.components = components;
665
+ // Add some warnings for unsupported features
666
+ if (jsx.includes('style={{')) {
667
+ result.warnings.push('Inline styles detected - these may not be fully preserved in Visual Builder');
668
+ }
669
+ if (jsx.includes('onClick') || jsx.includes('onHover') || jsx.includes('on[A-Z]')) {
670
+ result.warnings.push('Event handlers detected - these will need to be reconfigured in Visual Builder');
671
+ }
672
+ if (jsx.includes('import.meta') || jsx.includes('__vite__')) {
673
+ result.errors.push('Transformed code detected in JSX - parsing may be unreliable');
674
+ }
675
+ }
676
+ catch (error) {
677
+ const errorMessage = `Failed to parse story: ${error instanceof Error ? error.message : 'Unknown error'}`;
678
+ console.error('❌ Parse error:', errorMessage);
679
+ result.errors.push(errorMessage);
680
+ }
681
+ return result;
682
+ }
683
+ /**
684
+ * Utility function to validate parsed components
685
+ */
686
+ export function validateParsedComponents(components) {
687
+ const issues = [];
688
+ function validateComponent(component, path) {
689
+ if (!component.id) {
690
+ issues.push(`Component at ${path} is missing an ID`);
691
+ }
692
+ if (!component.type) {
693
+ issues.push(`Component at ${path} is missing a type`);
694
+ }
695
+ if (!COMPONENT_CATEGORIES[component.type] && component.type !== 'Text') {
696
+ issues.push(`Component type "${component.type}" at ${path} is not recognized`);
697
+ }
698
+ if (component.children) {
699
+ component.children.forEach((child, index) => {
700
+ validateComponent(child, `${path}.children[${index}]`);
701
+ });
702
+ }
703
+ }
704
+ components.forEach((component, index) => {
705
+ validateComponent(component, `components[${index}]`);
706
+ });
707
+ console.log(`🔍 Validation complete: ${issues.length} issues found`, issues);
708
+ return issues;
709
+ }
710
+ /**
711
+ * Utility function to detect if code is Vite-transformed
712
+ */
713
+ export function isViteTransformedCode(code) {
714
+ const transformedIndicators = [
715
+ '__vite__cjsImport',
716
+ '_jsxDEV',
717
+ 'import.meta.hot',
718
+ '__vite__updateStyle',
719
+ '__vite_ssr_',
720
+ 'createHotContext'
721
+ ];
722
+ return transformedIndicators.some(indicator => code.includes(indicator));
723
+ }
724
+ /**
725
+ * Enhanced story name extraction that handles multiple story formats
726
+ */
727
+ export function extractStoryName(storyCode) {
728
+ console.log('🔍 Extracting story name from code...');
729
+ // Method 1: Extract from story title property (title: "My Story") - HIGHEST PRIORITY
730
+ const titleMatch = storyCode.match(/title:\s*['"]([^'"]+)['"]/);
731
+ if (titleMatch && titleMatch[1]) {
732
+ console.log(`✅ Found title property: "${titleMatch[1]}"`);
733
+ return titleMatch[1];
734
+ }
735
+ // Method 2: Extract from meta title (export default { title: "My Story" })
736
+ const metaTitleMatch = storyCode.match(/export\s+default\s*{[^}]*title:\s*['"]([^'"]+)['"]/);
737
+ if (metaTitleMatch && metaTitleMatch[1]) {
738
+ console.log(`✅ Found meta title: "${metaTitleMatch[1]}"`);
739
+ return metaTitleMatch[1];
740
+ }
741
+ // Method 3: Extract from comment annotation (// @title My Story)
742
+ const commentMatch = storyCode.match(/\/\/\s*@title\s+(.+)/);
743
+ if (commentMatch && commentMatch[1]) {
744
+ const title = commentMatch[1].trim();
745
+ console.log(`✅ Found comment title: "${title}"`);
746
+ return title;
747
+ }
748
+ // Method 4: Extract from JSDoc comment (@title My Story)
749
+ const jsDocMatch = storyCode.match(/\*\s*@title\s+(.+)/);
750
+ if (jsDocMatch && jsDocMatch[1]) {
751
+ const title = jsDocMatch[1].trim();
752
+ console.log(`✅ Found JSDoc title: "${title}"`);
753
+ return title;
754
+ }
755
+ // Method 5: Extract from export const statement (e.g., export const MyStory = {...})
756
+ const exportMatch = storyCode.match(/export\s+const\s+(\w+)\s*=/);
757
+ if (exportMatch && exportMatch[1]) {
758
+ const rawName = exportMatch[1];
759
+ // Convert PascalCase or camelCase to readable format, but keep it clean
760
+ const readable = rawName
761
+ .replace(/([A-Z])/g, ' $1')
762
+ .replace(/^\s+/, '')
763
+ .trim();
764
+ console.log(`✅ Found export const name: "${rawName}" → "${readable}"`);
765
+ return readable;
766
+ }
767
+ // Method 6: Extract from component name in JSX (return <MyComponent />)
768
+ const componentMatch = storyCode.match(/return\s*\(?\s*<(\w+)/);
769
+ if (componentMatch && componentMatch[1]) {
770
+ const componentName = componentMatch[1];
771
+ // Only use this if it's not a generic HTML element
772
+ if (!['div', 'span', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(componentName.toLowerCase())) {
773
+ const readable = componentName
774
+ .replace(/([A-Z])/g, ' $1')
775
+ .replace(/^\s+/, '')
776
+ .trim();
777
+ console.log(`✅ Found component name: "${componentName}" → "${readable}"`);
778
+ return readable;
779
+ }
780
+ }
781
+ // Method 7: Extract from function name (export function MyStory())
782
+ const functionMatch = storyCode.match(/export\s+function\s+(\w+)/);
783
+ if (functionMatch && functionMatch[1]) {
784
+ const funcName = functionMatch[1];
785
+ const readable = funcName
786
+ .replace(/([A-Z])/g, ' $1')
787
+ .replace(/^\s+/, '')
788
+ .trim();
789
+ console.log(`✅ Found function name: "${funcName}" → "${readable}"`);
790
+ return readable;
791
+ }
792
+ console.log('❌ No story name found, using fallback');
793
+ return 'Imported Story';
794
+ }
795
+ /**
796
+ * Utility function to clean up code and provide helpful error messages
797
+ */
798
+ export function preprocessStoryCode(code) {
799
+ const warnings = [];
800
+ const errors = [];
801
+ if (isViteTransformedCode(code)) {
802
+ errors.push('Detected Vite-transformed code. Visual Builder requires original source code, not transformed modules.');
803
+ return { code, warnings, errors };
804
+ }
805
+ // Check for common issues that might indicate problems
806
+ if (code.length < 50) {
807
+ warnings.push('Story code seems unusually short - this might indicate an incomplete source');
808
+ }
809
+ if (!code.includes('render:') && !code.includes('export')) {
810
+ warnings.push('No render function or exports found - this might not be a valid story file');
811
+ }
812
+ return { code, warnings, errors };
813
+ }