@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,94 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ActionIcon, Tooltip } from '@mantine/core';
3
+ import { IconDeviceFloppy } from '@tabler/icons-react';
4
+ import { useVisualBuilderStore } from '../../store/visualBuilderStore';
5
+ import { saveStoryFile, getCleanFileName, filePathToStoryName } from '../../utils/storyFileManager';
6
+ export const SaveOnlyManager = ({ storyFilePath, size = 'xs' }) => {
7
+ const { components, isDirty, markClean } = useVisualBuilderStore();
8
+ const handleSave = async () => {
9
+ if (!storyFilePath) {
10
+ // If no file path, save to sessionStorage for now
11
+ const storyData = {
12
+ components,
13
+ timestamp: Date.now()
14
+ };
15
+ sessionStorage.setItem('visualBuilderComponents', JSON.stringify(storyData));
16
+ markClean();
17
+ console.log('✅ Saved to session storage');
18
+ return;
19
+ }
20
+ try {
21
+ // Debug: Check components before saving
22
+ console.log('🔍 Components before save:', JSON.stringify(components, null, 2));
23
+ // Fix style props if they're strings
24
+ const fixedComponents = JSON.parse(JSON.stringify(components, (key, value) => {
25
+ if (key === 'style' && typeof value === 'string') {
26
+ console.warn('⚠️ Found string style prop, attempting to parse:', value);
27
+ // Try to parse string style back to object
28
+ try {
29
+ // Remove outer quotes if present
30
+ let styleStr = value;
31
+ if (styleStr.startsWith('"') && styleStr.endsWith('"')) {
32
+ styleStr = styleStr.slice(1, -1);
33
+ }
34
+ // Check if it looks like an object string
35
+ if (styleStr.startsWith('{') && styleStr.endsWith('}')) {
36
+ // Remove braces and parse
37
+ const innerStr = styleStr.slice(1, -1).trim();
38
+ const styleObj = {};
39
+ // Split by comma (careful with values that might contain commas)
40
+ const pairs = innerStr.split(/,(?![^(]*\))/);
41
+ for (const pair of pairs) {
42
+ const colonIndex = pair.indexOf(':');
43
+ if (colonIndex > -1) {
44
+ const prop = pair.substring(0, colonIndex).trim();
45
+ let val = pair.substring(colonIndex + 1).trim();
46
+ // Remove quotes from property name
47
+ const cleanProp = prop.replace(/['"]/g, '');
48
+ // Parse value
49
+ if (val.startsWith("'") && val.endsWith("'")) {
50
+ val = val.slice(1, -1);
51
+ }
52
+ else if (val.startsWith('"') && val.endsWith('"')) {
53
+ val = val.slice(1, -1);
54
+ }
55
+ else if (/^\d+$/.test(val)) {
56
+ val = parseInt(val, 10);
57
+ }
58
+ else if (/^\d*\.\d+$/.test(val)) {
59
+ val = parseFloat(val);
60
+ }
61
+ styleObj[cleanProp] = val;
62
+ }
63
+ }
64
+ console.log('✅ Parsed style object:', styleObj);
65
+ return styleObj;
66
+ }
67
+ }
68
+ catch (e) {
69
+ console.error('❌ Failed to parse style string:', e);
70
+ }
71
+ }
72
+ return value;
73
+ }));
74
+ // Use the new simplified save system
75
+ const cleanFileName = getCleanFileName(storyFilePath.split('/').pop() || storyFilePath);
76
+ const storyName = filePathToStoryName(cleanFileName);
77
+ const result = await saveStoryFile(storyFilePath, fixedComponents, {
78
+ storyName,
79
+ createBackup: false // Visual Builder never creates backups
80
+ });
81
+ if (result.success) {
82
+ markClean();
83
+ console.log(`✅ Saved story: ${result.fileName}`);
84
+ }
85
+ else {
86
+ console.error(`❌ Failed to save: ${result.error}`);
87
+ }
88
+ }
89
+ catch (error) {
90
+ console.error('Failed to save story:', error);
91
+ }
92
+ };
93
+ return (_jsx(Tooltip, { label: isDirty ? "Save changes" : "No changes to save", children: _jsx(ActionIcon, { size: size, variant: isDirty ? 'filled' : 'subtle', color: isDirty ? 'blue' : 'gray', onClick: handleSave, disabled: !isDirty, children: _jsx(IconDeviceFloppy, { size: 14 }) }) }));
94
+ };
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Group, ActionIcon, Tooltip, Modal, TextInput, Button, Text, Stack, List } from '@mantine/core';
4
+ import { IconDeviceFloppy, IconFolderOpen, IconPlus, IconTrash } from '@tabler/icons-react';
5
+ import { useVisualBuilderStore } from '../../store/visualBuilderStore';
6
+ import { getSavedStories, deleteStory } from '../../utils/storyPersistence';
7
+ export const StoryManager = ({ size = 'xs' }) => {
8
+ const [isLoadModalOpen, setIsLoadModalOpen] = useState(false);
9
+ const [isSaveModalOpen, setIsSaveModalOpen] = useState(false);
10
+ const [savedStories, setSavedStories] = useState([]);
11
+ const [saveStoryName, setSaveStoryName] = useState('');
12
+ const { saveCurrentStory, loadStoryById, newStory, currentStoryName, currentStoryId, isDirty } = useVisualBuilderStore();
13
+ const refreshSavedStories = () => {
14
+ setSavedStories(getSavedStories());
15
+ };
16
+ const handleOpenLoadModal = () => {
17
+ refreshSavedStories();
18
+ setIsLoadModalOpen(true);
19
+ };
20
+ const handleOpenSaveModal = () => {
21
+ setSaveStoryName(currentStoryName);
22
+ setIsSaveModalOpen(true);
23
+ };
24
+ const handleQuickSave = () => {
25
+ if (currentStoryId || currentStoryName !== 'Untitled Story') {
26
+ saveCurrentStory();
27
+ }
28
+ else {
29
+ handleOpenSaveModal();
30
+ }
31
+ };
32
+ const handleSaveStory = () => {
33
+ if (saveStoryName.trim()) {
34
+ saveCurrentStory(saveStoryName.trim());
35
+ setIsSaveModalOpen(false);
36
+ setSaveStoryName('');
37
+ }
38
+ };
39
+ const handleLoadStory = (storyId) => {
40
+ const success = loadStoryById(storyId);
41
+ if (success) {
42
+ setIsLoadModalOpen(false);
43
+ }
44
+ };
45
+ const handleDeleteStory = (storyId, event) => {
46
+ event.stopPropagation();
47
+ if (confirm('Are you sure you want to delete this story?')) {
48
+ deleteStory(storyId);
49
+ refreshSavedStories();
50
+ // If we deleted the current story, create a new one
51
+ if (currentStoryId === storyId) {
52
+ newStory();
53
+ }
54
+ }
55
+ };
56
+ const handleNewStory = () => {
57
+ if (isDirty && !confirm('You have unsaved changes. Are you sure you want to create a new story?')) {
58
+ return;
59
+ }
60
+ newStory();
61
+ };
62
+ return (_jsxs(_Fragment, { children: [_jsxs(Group, { gap: "xs", children: [_jsx(Tooltip, { label: "New Story", children: _jsx(ActionIcon, { size: size, variant: "subtle", onClick: handleNewStory, children: _jsx(IconPlus, { size: 14 }) }) }), _jsx(Tooltip, { label: "Save Story", children: _jsx(ActionIcon, { size: size, variant: isDirty ? 'filled' : 'subtle', color: isDirty ? 'blue' : 'gray', onClick: handleQuickSave, children: _jsx(IconDeviceFloppy, { size: 14 }) }) }), _jsx(Tooltip, { label: "Load Story", children: _jsx(ActionIcon, { size: size, variant: "subtle", onClick: handleOpenLoadModal, children: _jsx(IconFolderOpen, { size: 14 }) }) })] }), _jsx(Modal, { opened: isSaveModalOpen, onClose: () => setIsSaveModalOpen(false), title: "Save Story", size: "sm", children: _jsxs(Stack, { gap: "md", children: [_jsx(TextInput, { label: "Story Name", placeholder: "Enter story name...", value: saveStoryName, onChange: (event) => setSaveStoryName(event.currentTarget.value), "data-autofocus": true }), _jsxs(Group, { justify: "flex-end", gap: "xs", children: [_jsx(Button, { variant: "outline", onClick: () => setIsSaveModalOpen(false), children: "Cancel" }), _jsx(Button, { onClick: handleSaveStory, disabled: !saveStoryName.trim(), children: "Save" })] })] }) }), _jsx(Modal, { opened: isLoadModalOpen, onClose: () => setIsLoadModalOpen(false), title: "Load Story", size: "md", children: _jsxs(Stack, { gap: "md", children: [savedStories.length === 0 ? (_jsx(Text, { c: "dimmed", ta: "center", py: "lg", children: "No saved stories found" })) : (_jsx(List, { spacing: "xs", size: "sm", children: savedStories.map((story) => (_jsx(List.Item, { style: { listStyle: 'none', padding: 0 }, children: _jsxs(Group, { justify: "space-between", p: "sm", style: {
63
+ border: '1px solid #e9ecef',
64
+ borderRadius: '4px',
65
+ cursor: 'pointer',
66
+ backgroundColor: story.id === currentStoryId ? '#f1f3f4' : 'white'
67
+ }, onClick: () => handleLoadStory(story.id), children: [_jsxs(Stack, { gap: "xs", style: { flex: 1 }, children: [_jsx(Text, { fw: 500, children: story.name }), _jsxs(Text, { size: "xs", c: "dimmed", children: [story.components.length, " components \u2022 Updated ", new Date(story.updatedAt).toLocaleDateString()] })] }), _jsx(ActionIcon, { size: "sm", variant: "subtle", color: "red", onClick: (e) => handleDeleteStory(story.id, e), children: _jsx(IconTrash, { size: 14 }) })] }) }, story.id))) })), _jsx(Group, { justify: "flex-end", children: _jsx(Button, { variant: "outline", onClick: () => setIsLoadModalOpen(false), children: "Close" }) })] }) })] }));
68
+ };
@@ -0,0 +1 @@
1
+ export { StoryManager } from './StoryManager';
@@ -0,0 +1,256 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { DndContext } from '@dnd-kit/core';
4
+ import { Box, Group, Button, Badge, Text } from '@mantine/core';
5
+ import { IconDeviceFloppy } from '@tabler/icons-react';
6
+ import { Canvas } from './Canvas/Canvas';
7
+ import { ComponentPalette } from './ComponentPalette/ComponentPalette';
8
+ import { PropertyEditor } from './PropertyEditor/PropertyEditor';
9
+ import { CodeExporter } from './CodeExporter/CodeExporter';
10
+ import { useDragAndDrop } from '../hooks/useDragAndDrop';
11
+ import { useVisualBuilderStore } from '../store/visualBuilderStore';
12
+ import { getStoryIdFromURL, saveDraft, restoreDraft, getVisualBuilderEditURL } from '../utils/storyPersistence';
13
+ import { updateStoryFile } from '../utils/storyFileUpdater';
14
+ export const VisualBuilder = ({ style, height = '100vh', initialCode, initialContent, onCodeExport, storyFilePath }) => {
15
+ const { sensors, handleDragStart, handleDragOver, handleDragEnd, handleDragCancel } = useDragAndDrop();
16
+ const { components, clearCanvas, openCodeModal, loadFromCode, loadFromAI, importFromStoryUI, saveCurrentStory, loadStoryById, currentStoryName, isDirty, isImportedFromStory } = useVisualBuilderStore();
17
+ // Create a stable story ID for drafts
18
+ const [storyId] = React.useState(() => {
19
+ const urlStoryId = getStoryIdFromURL();
20
+ const urlParams = new URLSearchParams(window.location.search);
21
+ const editId = urlParams.get('edit');
22
+ return editId || urlStoryId || `story-${Date.now()}`;
23
+ });
24
+ // Update URL when story ID changes
25
+ React.useEffect(() => {
26
+ if (storyId) {
27
+ const url = new URL(window.location.href);
28
+ url.searchParams.set('story', storyId);
29
+ window.history.replaceState({}, '', url.toString());
30
+ }
31
+ }, [storyId]);
32
+ // Track if initial load is complete
33
+ const [isInitialLoadComplete, setIsInitialLoadComplete] = React.useState(false);
34
+ // Load story from URL or initial code
35
+ React.useEffect(() => {
36
+ console.log('🚀 Visual Builder initializing...');
37
+ // Check for story ID in URL first
38
+ const storyIdFromURL = getStoryIdFromURL();
39
+ if (storyIdFromURL) {
40
+ const success = loadStoryById(storyIdFromURL);
41
+ if (success) {
42
+ console.log('✅ Loaded story from URL:', storyIdFromURL);
43
+ setIsInitialLoadComplete(true);
44
+ return; // Successfully loaded story from URL
45
+ }
46
+ }
47
+ // Check for sessionStorage content from Visual Builder button
48
+ let sessionStorageCode = '';
49
+ let sourceFile = '';
50
+ try {
51
+ sessionStorageCode = sessionStorage.getItem('visualBuilderInitialCode') || '';
52
+ sourceFile = sessionStorage.getItem('visualBuilderSourceFile') || '';
53
+ console.log('📂 SessionStorage check:', {
54
+ hasCode: !!sessionStorageCode,
55
+ codeLength: sessionStorageCode.length,
56
+ sourceFile: sourceFile,
57
+ preview: sessionStorageCode.substring(0, 100) + '...'
58
+ });
59
+ // Clear sessionStorage after reading to prevent re-loading
60
+ if (sessionStorageCode) {
61
+ sessionStorage.removeItem('visualBuilderInitialCode');
62
+ sessionStorage.removeItem('visualBuilderSourceFile');
63
+ sessionStorage.removeItem('visualBuilderStoryVariant');
64
+ }
65
+ }
66
+ catch (e) {
67
+ console.error('❌ Error reading from sessionStorage:', e);
68
+ }
69
+ // Prioritize sessionStorage code over props
70
+ const codeToLoad = sessionStorageCode || initialContent || initialCode;
71
+ // Try to restore draft if no explicit code to load
72
+ if (!codeToLoad) {
73
+ const draft = restoreDraft(storyId);
74
+ if (draft && draft.components && draft.components.length > 0) {
75
+ console.log('📝 Restored draft from localStorage');
76
+ // Load components and restore the isImportedFromStory flag
77
+ loadFromAI(draft.components);
78
+ // Restore the isImportedFromStory flag and other metadata
79
+ if (draft.isImportedFromStory) {
80
+ useVisualBuilderStore.setState({ isImportedFromStory: true });
81
+ }
82
+ if (draft.storyName) {
83
+ useVisualBuilderStore.setState({ currentStoryName: draft.storyName });
84
+ }
85
+ if (draft.sourceFile) {
86
+ // Store source file in sessionStorage for later use
87
+ sessionStorage.setItem('visualBuilderSourceFile', draft.sourceFile);
88
+ }
89
+ setIsInitialLoadComplete(true);
90
+ return;
91
+ }
92
+ }
93
+ // Load the code if available
94
+ if (codeToLoad) {
95
+ console.log('📎 Loading code into Visual Builder:', {
96
+ source: sessionStorageCode ? 'sessionStorage' : 'props',
97
+ length: codeToLoad.length,
98
+ hasRender: codeToLoad.includes('render:'),
99
+ hasStories: codeToLoad.includes('.stories'),
100
+ isTemplate: codeToLoad.includes('Component ready for editing')
101
+ });
102
+ // Try Story UI import first if content looks like a story
103
+ if (codeToLoad.includes('render:') || codeToLoad.includes('.stories')) {
104
+ importFromStoryUI(codeToLoad).then((result) => {
105
+ console.log('🎉 Story UI import result:', result);
106
+ setIsInitialLoadComplete(true);
107
+ }).catch((error) => {
108
+ console.error('❌ Story UI import failed, falling back to regular load:', error);
109
+ loadFromCode(codeToLoad).then(() => {
110
+ setIsInitialLoadComplete(true);
111
+ }).catch(console.error);
112
+ });
113
+ }
114
+ else {
115
+ loadFromCode(codeToLoad).then(() => {
116
+ setIsInitialLoadComplete(true);
117
+ }).catch(console.error);
118
+ }
119
+ }
120
+ else {
121
+ console.log('🎨 No code to load, starting with empty canvas');
122
+ setIsInitialLoadComplete(true);
123
+ }
124
+ }, []); // Run only once on mount
125
+ // Save components to draft when they change after initial load
126
+ React.useEffect(() => {
127
+ if (isInitialLoadComplete && components.length > 0) {
128
+ // Save immediately when components are loaded from initial content
129
+ const sourceFile = sessionStorage.getItem('visualBuilderSourceFile') || storyFilePath || undefined;
130
+ saveDraft(storyId, components, isImportedFromStory, currentStoryName, sourceFile);
131
+ console.log('💾 Saved story to draft with ID:', storyId);
132
+ }
133
+ }, [components, isInitialLoadComplete, storyId, isImportedFromStory, currentStoryName, storyFilePath]);
134
+ // Auto-save drafts when dirty
135
+ React.useEffect(() => {
136
+ if (components.length > 0 && isDirty && isInitialLoadComplete) {
137
+ const timer = setTimeout(() => {
138
+ const sourceFile = sessionStorage.getItem('visualBuilderSourceFile') || storyFilePath || undefined;
139
+ saveDraft(storyId, components, isImportedFromStory, currentStoryName, sourceFile);
140
+ console.log('💾 Auto-saved draft');
141
+ }, 2000);
142
+ return () => clearTimeout(timer);
143
+ }
144
+ }, [components, isDirty, storyId, isImportedFromStory, isInitialLoadComplete, currentStoryName, storyFilePath]);
145
+ // Update URL when editing
146
+ React.useEffect(() => {
147
+ if (window.location.pathname.includes('visual-builder')) {
148
+ const editURL = getVisualBuilderEditURL(storyId);
149
+ window.history.replaceState({}, '', editURL);
150
+ }
151
+ }, [storyId]);
152
+ return (_jsx(DndContext, { sensors: sensors, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragEnd: handleDragEnd, onDragCancel: handleDragCancel, children: _jsxs(Box, { style: {
153
+ display: 'flex',
154
+ height,
155
+ backgroundColor: '#f8f9fa',
156
+ ...style
157
+ }, children: [_jsxs(Box, { style: {
158
+ width: 280,
159
+ backgroundColor: 'white',
160
+ borderRight: '1px solid #e9ecef',
161
+ display: 'flex',
162
+ flexDirection: 'column'
163
+ }, children: [_jsxs(Box, { p: "sm", style: { borderBottom: '1px solid #e9ecef' }, children: [_jsx(Group, { justify: "space-between", mb: "sm", children: _jsx("h3", { style: { margin: 0, fontSize: '1.1rem' }, children: "Components" }) }), _jsxs(Group, { gap: "xs", children: [_jsx(Button, { size: "xs", variant: "outline", onClick: clearCanvas, children: "Clear" }), _jsx(Button, { size: "xs", variant: "filled", onClick: async () => {
164
+ if (onCodeExport) {
165
+ try {
166
+ const { generateJSXCode } = await import('./CodeExporter/codeGenerator');
167
+ const { components } = useVisualBuilderStore.getState();
168
+ const code = generateJSXCode(components);
169
+ onCodeExport(code);
170
+ }
171
+ catch (error) {
172
+ console.error('Failed to generate code:', error);
173
+ openCodeModal();
174
+ }
175
+ }
176
+ else {
177
+ openCodeModal();
178
+ }
179
+ }, children: "Export" })] })] }), _jsx(Box, { style: { flex: 1, overflow: 'auto' }, children: _jsx(ComponentPalette, {}) })] }), _jsxs(Box, { style: { flex: 1, display: 'flex', flexDirection: 'column' }, children: [_jsx(Box, { p: "sm", style: { borderBottom: '1px solid #e9ecef', backgroundColor: 'white' }, children: _jsxs(Group, { justify: "space-between", align: "center", children: [_jsxs(Group, { align: "center", gap: "sm", children: [_jsx(Text, { fw: 500, size: "lg", children: "Canvas" }), currentStoryName && currentStoryName !== 'Untitled Story' && (_jsxs(Group, { gap: "xs", align: "center", children: [_jsx(Text, { size: "sm", c: "dimmed", children: "\u2022" }), _jsx(Text, { size: "sm", c: "dimmed", children: currentStoryName }), isDirty && (_jsx(Badge, { size: "xs", color: "orange", variant: "filled", children: "Unsaved" }))] }))] }), _jsx(Button, { size: "sm", variant: isDirty ? 'filled' : 'outline', color: isDirty ? 'blue' : 'gray', leftSection: _jsx(IconDeviceFloppy, { size: 16 }), onClick: async () => {
180
+ // Check if we're editing an existing story (came from Storybook)
181
+ const sourceFile = sessionStorage.getItem('visualBuilderSourceFile');
182
+ const isEditingExistingStory = Boolean(sourceFile) || isImportedFromStory || Boolean(storyFilePath);
183
+ let finalName = currentStoryName;
184
+ let fileToUpdate = storyFilePath;
185
+ if (isEditingExistingStory) {
186
+ // We're editing an existing story - NEVER prompt for a name
187
+ // Use the source file as the file to update
188
+ if (sourceFile) {
189
+ fileToUpdate = sourceFile;
190
+ // Extract a clean name from the file if we don't have one
191
+ if (!currentStoryName || currentStoryName === 'Untitled Story' || currentStoryName === 'Imported Story') {
192
+ finalName = sourceFile
193
+ .replace(/^(edited-|generated-)/, '') // Remove prefixes
194
+ .replace(/\.stories\.(tsx?|jsx?)$/, '') // Remove extension
195
+ .replace(/[_-]/g, ' ')
196
+ .split(' ')
197
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
198
+ .join(' ');
199
+ console.log(`Using name from source file: ${sourceFile} → ${finalName}`);
200
+ }
201
+ }
202
+ else if (!fileToUpdate) {
203
+ // Fallback: use the current story name to generate a file path
204
+ fileToUpdate = `${(currentStoryName || 'updated-story').toLowerCase().replace(/[^a-z0-9]+/g, '-')}.stories.tsx`;
205
+ }
206
+ }
207
+ else {
208
+ // We're creating a new story - may need to prompt for a name
209
+ const isGenericName = !currentStoryName ||
210
+ currentStoryName === 'Untitled Story' ||
211
+ currentStoryName === 'Imported Story';
212
+ if (isGenericName) {
213
+ const name = prompt('Enter story name:', currentStoryName || '');
214
+ if (name && name.trim()) {
215
+ finalName = name.trim();
216
+ }
217
+ else {
218
+ return; // User cancelled
219
+ }
220
+ }
221
+ // Generate file path from the story name
222
+ fileToUpdate = `${finalName.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.stories.tsx`;
223
+ }
224
+ // Save to store
225
+ saveCurrentStory(finalName);
226
+ // Always try to update the story file if we have components
227
+ if (components.length > 0 && fileToUpdate) {
228
+ const result = await updateStoryFile(fileToUpdate, components, finalName);
229
+ if (result.success) {
230
+ console.log(`✅ Updated story file: ${fileToUpdate}`);
231
+ // Show success message
232
+ const message = result.message || 'Story saved successfully!';
233
+ alert(`${message}\n\nRefresh Storybook to see your changes.`);
234
+ }
235
+ else {
236
+ console.error('Failed to update story file:', result.error);
237
+ // Show error but reassure user that changes are saved locally
238
+ if (result.error?.includes('server not available')) {
239
+ alert('Story UI server is not running.\n\nYour changes have been saved locally.\nMake sure the Story UI server is running to save to files.');
240
+ }
241
+ else {
242
+ alert(`Failed to save story: ${result.error}\n\nPlease try again.`);
243
+ }
244
+ }
245
+ }
246
+ else {
247
+ console.log(`✅ Saved story: ${finalName}`);
248
+ }
249
+ }, disabled: !isDirty && !components.length, children: "Save Story" })] }) }), _jsx(Box, { style: { flex: 1, overflow: 'auto' }, children: _jsx(Canvas, {}) })] }), _jsxs(Box, { style: {
250
+ width: 320,
251
+ backgroundColor: 'white',
252
+ borderLeft: '1px solid #e9ecef',
253
+ display: 'flex',
254
+ flexDirection: 'column'
255
+ }, children: [_jsx(Box, { p: "sm", style: { borderBottom: '1px solid #e9ecef' }, children: _jsx("h3", { style: { margin: 0, fontSize: '1.1rem' }, children: "Properties" }) }), _jsx(Box, { style: { flex: 1, overflow: 'auto' }, children: _jsx(PropertyEditor, {}) })] }), _jsx(CodeExporter, {})] }) }));
256
+ };