@tpitre/story-ui 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/dist/cli/index.js +0 -0
  2. package/dist/cli/index.js.map +1 -0
  3. package/dist/cli/setup.js.map +1 -0
  4. package/dist/cloudflare-edge/src/mcp-session.js +462 -0
  5. package/dist/cloudflare-edge/src/types.js +4 -0
  6. package/dist/cloudflare-edge/src/worker.js +106 -0
  7. package/dist/cloudflare-pages/vite.config.js +14 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +12 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/mcp-server/index.js.map +1 -0
  13. package/dist/mcp-server/mcp-stdio-server.js.map +1 -0
  14. package/dist/mcp-server/routes/claude.js.map +1 -0
  15. package/dist/mcp-server/routes/components.js.map +1 -0
  16. package/dist/mcp-server/routes/generateStory.js.map +1 -0
  17. package/dist/mcp-server/routes/hybridStories.d.ts +18 -0
  18. package/dist/mcp-server/routes/hybridStories.d.ts.map +1 -0
  19. package/dist/mcp-server/routes/hybridStories.js +216 -0
  20. package/dist/mcp-server/routes/hybridStories.js.map +1 -0
  21. package/dist/mcp-server/routes/memoryStories.d.ts +26 -0
  22. package/dist/mcp-server/routes/memoryStories.d.ts.map +1 -0
  23. package/dist/mcp-server/routes/memoryStories.js +158 -0
  24. package/dist/mcp-server/routes/memoryStories.js.map +1 -0
  25. package/dist/mcp-server/routes/storySync.d.ts +26 -0
  26. package/dist/mcp-server/routes/storySync.d.ts.map +1 -0
  27. package/dist/mcp-server/routes/storySync.js +147 -0
  28. package/dist/mcp-server/routes/storySync.js.map +1 -0
  29. package/dist/mcp-server/routes/updateStory.js +246 -0
  30. package/dist/mcp-server/sessionManager.d.ts +50 -0
  31. package/dist/mcp-server/sessionManager.d.ts.map +1 -0
  32. package/dist/mcp-server/sessionManager.js +125 -0
  33. package/dist/mcp-server/sessionManager.js.map +1 -0
  34. package/dist/playground/components/AIAssistant/AIAssistant.d.ts +6 -0
  35. package/dist/playground/components/AIAssistant/AIAssistant.d.ts.map +1 -0
  36. package/dist/playground/components/AIAssistant/AIAssistant.js +109 -0
  37. package/dist/playground/components/AIAssistant/AIAssistant.js.map +1 -0
  38. package/dist/playground/components/AIAssistant/AIAssistant.module.css +166 -0
  39. package/dist/playground/components/Canvas/Canvas.d.ts +9 -0
  40. package/dist/playground/components/Canvas/Canvas.d.ts.map +1 -0
  41. package/dist/playground/components/Canvas/Canvas.js +58 -0
  42. package/dist/playground/components/Canvas/Canvas.js.map +1 -0
  43. package/dist/playground/components/Canvas/Canvas.module.css +189 -0
  44. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts +9 -0
  45. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts.map +1 -0
  46. package/dist/playground/components/Canvas/CanvasWithDnd.js +158 -0
  47. package/dist/playground/components/Canvas/CanvasWithDnd.js.map +1 -0
  48. package/dist/playground/components/Canvas/ComponentRenderer.d.ts +15 -0
  49. package/dist/playground/components/Canvas/ComponentRenderer.d.ts.map +1 -0
  50. package/dist/playground/components/Canvas/ComponentRenderer.js +177 -0
  51. package/dist/playground/components/Canvas/ComponentRenderer.js.map +1 -0
  52. package/dist/playground/components/Canvas/DraggableComponent.d.ts +15 -0
  53. package/dist/playground/components/Canvas/DraggableComponent.d.ts.map +1 -0
  54. package/dist/playground/components/Canvas/DraggableComponent.js +49 -0
  55. package/dist/playground/components/Canvas/DraggableComponent.js.map +1 -0
  56. package/dist/playground/components/Canvas/index.d.ts +9 -0
  57. package/dist/playground/components/Canvas/index.d.ts.map +1 -0
  58. package/dist/playground/components/Canvas/index.js +5 -0
  59. package/dist/playground/components/Canvas/index.js.map +1 -0
  60. package/dist/playground/components/CodeView/CodeView.d.ts +12 -0
  61. package/dist/playground/components/CodeView/CodeView.d.ts.map +1 -0
  62. package/dist/playground/components/CodeView/CodeView.js +77 -0
  63. package/dist/playground/components/CodeView/CodeView.js.map +1 -0
  64. package/dist/playground/components/CodeView/CodeView.module.css +178 -0
  65. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts +17 -0
  66. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts.map +1 -0
  67. package/dist/playground/components/ComponentPalette/ComponentPalette.js +138 -0
  68. package/dist/playground/components/ComponentPalette/ComponentPalette.js.map +1 -0
  69. package/dist/playground/components/ComponentPalette/ComponentPalette.module.css +217 -0
  70. package/dist/playground/components/ComponentPalette/index.d.ts +3 -0
  71. package/dist/playground/components/ComponentPalette/index.d.ts.map +1 -0
  72. package/dist/playground/components/ComponentPalette/index.js +2 -0
  73. package/dist/playground/components/ComponentPalette/index.js.map +1 -0
  74. package/dist/playground/components/DropZone/DropZone.d.ts +17 -0
  75. package/dist/playground/components/DropZone/DropZone.d.ts.map +1 -0
  76. package/dist/playground/components/DropZone/DropZone.js +73 -0
  77. package/dist/playground/components/DropZone/DropZone.js.map +1 -0
  78. package/dist/playground/components/DropZone/DropZone.module.css +86 -0
  79. package/dist/playground/components/ExportDialog/ExportDialog.d.ts +10 -0
  80. package/dist/playground/components/ExportDialog/ExportDialog.d.ts.map +1 -0
  81. package/dist/playground/components/ExportDialog/ExportDialog.js +57 -0
  82. package/dist/playground/components/ExportDialog/ExportDialog.js.map +1 -0
  83. package/dist/playground/components/ExportDialog/ExportDialog.module.css +328 -0
  84. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts +134 -0
  85. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts.map +1 -0
  86. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js +254 -0
  87. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js.map +1 -0
  88. package/dist/playground/components/LayoutHelpers/index.d.ts +3 -0
  89. package/dist/playground/components/LayoutHelpers/index.d.ts.map +1 -0
  90. package/dist/playground/components/LayoutHelpers/index.js +2 -0
  91. package/dist/playground/components/LayoutHelpers/index.js.map +1 -0
  92. package/dist/playground/components/Playground/Playground.d.ts +10 -0
  93. package/dist/playground/components/Playground/Playground.d.ts.map +1 -0
  94. package/dist/playground/components/Playground/Playground.js +128 -0
  95. package/dist/playground/components/Playground/Playground.js.map +1 -0
  96. package/dist/playground/components/Playground/Playground.module.css +308 -0
  97. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts +10 -0
  98. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts.map +1 -0
  99. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js +150 -0
  100. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js.map +1 -0
  101. package/dist/playground/components/PropertiesPanel/PropertiesPanel.module.css +155 -0
  102. package/dist/playground/components/PropertiesPanel/index.d.ts +3 -0
  103. package/dist/playground/components/PropertiesPanel/index.d.ts.map +1 -0
  104. package/dist/playground/components/PropertiesPanel/index.js +2 -0
  105. package/dist/playground/components/PropertiesPanel/index.js.map +1 -0
  106. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts +12 -0
  107. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts.map +1 -0
  108. package/dist/playground/components/PropertyEditors/BooleanEditor.js +14 -0
  109. package/dist/playground/components/PropertyEditors/BooleanEditor.js.map +1 -0
  110. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts +12 -0
  111. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts.map +1 -0
  112. package/dist/playground/components/PropertyEditors/ColorEditor.js +62 -0
  113. package/dist/playground/components/PropertyEditors/ColorEditor.js.map +1 -0
  114. package/dist/playground/components/PropertyEditors/IconEditor.d.ts +12 -0
  115. package/dist/playground/components/PropertyEditors/IconEditor.d.ts.map +1 -0
  116. package/dist/playground/components/PropertyEditors/IconEditor.js +123 -0
  117. package/dist/playground/components/PropertyEditors/IconEditor.js.map +1 -0
  118. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts +15 -0
  119. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts.map +1 -0
  120. package/dist/playground/components/PropertyEditors/NumberEditor.js +46 -0
  121. package/dist/playground/components/PropertyEditors/NumberEditor.js.map +1 -0
  122. package/dist/playground/components/PropertyEditors/PropertyEditors.module.css +432 -0
  123. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts +19 -0
  124. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts.map +1 -0
  125. package/dist/playground/components/PropertyEditors/SelectEditor.js +17 -0
  126. package/dist/playground/components/PropertyEditors/SelectEditor.js.map +1 -0
  127. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts +19 -0
  128. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts.map +1 -0
  129. package/dist/playground/components/PropertyEditors/SpacingEditor.js +162 -0
  130. package/dist/playground/components/PropertyEditors/SpacingEditor.js.map +1 -0
  131. package/dist/playground/components/PropertyEditors/SpacingEditor.module.css +214 -0
  132. package/dist/playground/components/PropertyEditors/TextEditor.d.ts +14 -0
  133. package/dist/playground/components/PropertyEditors/TextEditor.d.ts.map +1 -0
  134. package/dist/playground/components/PropertyEditors/TextEditor.js +38 -0
  135. package/dist/playground/components/PropertyEditors/TextEditor.js.map +1 -0
  136. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts +23 -0
  137. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts.map +1 -0
  138. package/dist/playground/components/PropertyEditors/TokenEditor.js +50 -0
  139. package/dist/playground/components/PropertyEditors/TokenEditor.js.map +1 -0
  140. package/dist/playground/components/PropertyEditors/index.d.ts +20 -0
  141. package/dist/playground/components/PropertyEditors/index.d.ts.map +1 -0
  142. package/dist/playground/components/PropertyEditors/index.js +12 -0
  143. package/dist/playground/components/PropertyEditors/index.js.map +1 -0
  144. package/dist/playground/components/TreeView/TreeView.d.ts +10 -0
  145. package/dist/playground/components/TreeView/TreeView.d.ts.map +1 -0
  146. package/dist/playground/components/TreeView/TreeView.js +146 -0
  147. package/dist/playground/components/TreeView/TreeView.js.map +1 -0
  148. package/dist/playground/components/TreeView/TreeView.module.css +214 -0
  149. package/dist/playground/components/TreeView/index.d.ts +3 -0
  150. package/dist/playground/components/TreeView/index.d.ts.map +1 -0
  151. package/dist/playground/components/TreeView/index.js +2 -0
  152. package/dist/playground/components/TreeView/index.js.map +1 -0
  153. package/dist/playground/config/propertyDefinitions.d.ts +73 -0
  154. package/dist/playground/config/propertyDefinitions.d.ts.map +1 -0
  155. package/dist/playground/config/propertyDefinitions.js +809 -0
  156. package/dist/playground/config/propertyDefinitions.js.map +1 -0
  157. package/dist/playground/hooks/useKeyboardShortcuts.d.ts +38 -0
  158. package/dist/playground/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  159. package/dist/playground/hooks/useKeyboardShortcuts.js +191 -0
  160. package/dist/playground/hooks/useKeyboardShortcuts.js.map +1 -0
  161. package/dist/playground/index.d.ts +21 -0
  162. package/dist/playground/index.d.ts.map +1 -0
  163. package/dist/playground/index.js +23 -0
  164. package/dist/playground/index.js.map +1 -0
  165. package/dist/playground/services/CodeGenerator.d.ts +73 -0
  166. package/dist/playground/services/CodeGenerator.d.ts.map +1 -0
  167. package/dist/playground/services/CodeGenerator.js +359 -0
  168. package/dist/playground/services/CodeGenerator.js.map +1 -0
  169. package/dist/playground/services/DragDropManager.d.ts +95 -0
  170. package/dist/playground/services/DragDropManager.d.ts.map +1 -0
  171. package/dist/playground/services/DragDropManager.js +408 -0
  172. package/dist/playground/services/DragDropManager.js.map +1 -0
  173. package/dist/playground/services/StoryParser.d.ts +73 -0
  174. package/dist/playground/services/StoryParser.d.ts.map +1 -0
  175. package/dist/playground/services/StoryParser.js +419 -0
  176. package/dist/playground/services/StoryParser.js.map +1 -0
  177. package/dist/playground/store/playgroundStore.d.ts +86 -0
  178. package/dist/playground/store/playgroundStore.d.ts.map +1 -0
  179. package/dist/playground/store/playgroundStore.js +337 -0
  180. package/dist/playground/store/playgroundStore.js.map +1 -0
  181. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts +13 -0
  182. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts.map +1 -0
  183. package/dist/playground/stories/PlaygroundDragDrop.stories.js +227 -0
  184. package/dist/playground/stories/PlaygroundDragDrop.stories.js.map +1 -0
  185. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts +13 -0
  186. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts.map +1 -0
  187. package/dist/playground/stories/PlaygroundPhase4.stories.js +334 -0
  188. package/dist/playground/stories/PlaygroundPhase4.stories.js.map +1 -0
  189. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts +14 -0
  190. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts.map +1 -0
  191. package/dist/playground/stories/PlaygroundPhase5.stories.js +512 -0
  192. package/dist/playground/stories/PlaygroundPhase5.stories.js.map +1 -0
  193. package/dist/playground/stories/PlaygroundProperties.stories.d.ts +13 -0
  194. package/dist/playground/stories/PlaygroundProperties.stories.d.ts.map +1 -0
  195. package/dist/playground/stories/PlaygroundProperties.stories.js +342 -0
  196. package/dist/playground/stories/PlaygroundProperties.stories.js.map +1 -0
  197. package/dist/playground/types/index.d.ts +251 -0
  198. package/dist/playground/types/index.d.ts.map +1 -0
  199. package/dist/playground/types/index.js +5 -0
  200. package/dist/playground/types/index.js.map +1 -0
  201. package/dist/scripts/verify-framework-adapters.js +105 -0
  202. package/dist/story-generator/componentBlacklist.js.map +1 -0
  203. package/dist/story-generator/componentDiscovery.js.map +1 -0
  204. package/dist/story-generator/configLoader.js.map +1 -0
  205. package/dist/story-generator/considerationsLoader.js.map +1 -0
  206. package/dist/story-generator/documentation-sources.js.map +1 -0
  207. package/dist/story-generator/documentationLoader.js.map +1 -0
  208. package/dist/story-generator/dynamicPackageDiscovery.js.map +1 -0
  209. package/dist/story-generator/enhancedComponentDiscovery.js.map +1 -0
  210. package/dist/story-generator/generateStory.js.map +1 -0
  211. package/dist/story-generator/gitignoreManager.js.map +1 -0
  212. package/dist/story-generator/inMemoryStoryService.d.ts +89 -0
  213. package/dist/story-generator/inMemoryStoryService.d.ts.map +1 -0
  214. package/dist/story-generator/inMemoryStoryService.js +128 -0
  215. package/dist/story-generator/inMemoryStoryService.js.map +1 -0
  216. package/dist/story-generator/logger.js.map +1 -0
  217. package/dist/story-generator/postProcessStory.js.map +1 -0
  218. package/dist/story-generator/postgresStoryService.d.ts +56 -0
  219. package/dist/story-generator/postgresStoryService.d.ts.map +1 -0
  220. package/dist/story-generator/postgresStoryService.js +240 -0
  221. package/dist/story-generator/productionGitignoreManager.d.ts +91 -0
  222. package/dist/story-generator/productionGitignoreManager.d.ts.map +1 -0
  223. package/dist/story-generator/productionGitignoreManager.js +340 -0
  224. package/dist/story-generator/productionGitignoreManager.js.map +1 -0
  225. package/dist/story-generator/promptGenerator.js.map +1 -0
  226. package/dist/story-generator/providerPresets.d.ts +54 -0
  227. package/dist/story-generator/providerPresets.d.ts.map +1 -0
  228. package/dist/story-generator/providerPresets.js +214 -0
  229. package/dist/story-generator/storyHistory.js.map +1 -0
  230. package/dist/story-generator/storyServiceFactory.d.ts +22 -0
  231. package/dist/story-generator/storyServiceFactory.d.ts.map +1 -0
  232. package/dist/story-generator/storyServiceFactory.js +97 -0
  233. package/dist/story-generator/storyServiceInterface.d.ts +85 -0
  234. package/dist/story-generator/storyServiceInterface.d.ts.map +1 -0
  235. package/dist/story-generator/storyServiceInterface.js +5 -0
  236. package/dist/story-generator/storySync.d.ts +68 -0
  237. package/dist/story-generator/storySync.d.ts.map +1 -0
  238. package/dist/story-generator/storySync.js +201 -0
  239. package/dist/story-generator/storySync.js.map +1 -0
  240. package/dist/story-generator/storyTracker.js.map +1 -0
  241. package/dist/story-generator/storyValidator.js.map +1 -0
  242. package/dist/story-generator/test_validation.d.ts +2 -0
  243. package/dist/story-generator/test_validation.d.ts.map +1 -0
  244. package/dist/story-generator/test_validation.js +51 -0
  245. package/dist/story-generator/universalDesignSystemAdapter.js.map +1 -0
  246. package/dist/story-generator/urlRedirectService.js.map +1 -0
  247. package/dist/story-generator/validateStory.js.map +1 -0
  248. package/dist/story-ui.config.js.map +1 -0
  249. package/dist/story-ui.config.loader.d.ts +36 -0
  250. package/dist/story-ui.config.loader.d.ts.map +1 -0
  251. package/dist/story-ui.config.loader.js +205 -0
  252. package/dist/story-ui.config.loader.js.map +1 -0
  253. package/dist/temp/package/templates/StoryUI/StoryUIPanel.js +807 -0
  254. package/dist/temp/package/templates/StoryUI/StoryUIPanel.stories.js +37 -0
  255. package/dist/temp/package/templates/StoryUI/index.js +2 -0
  256. package/dist/templates/StoryUI/StoryUIPanel.js.map +1 -0
  257. package/dist/templates/StoryUI/StoryUIPanel.stories.js.map +1 -0
  258. package/dist/templates/StoryUI/index.js.map +1 -0
  259. package/dist/templates/StoryUI/manager.d.ts +14 -0
  260. package/dist/templates/StoryUI/manager.d.ts.map +1 -0
  261. package/dist/templates/production-app/src/App.d.ts +10 -0
  262. package/dist/templates/production-app/src/App.d.ts.map +1 -0
  263. package/dist/templates/production-app/src/App.js +653 -0
  264. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts +24 -0
  265. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts.map +1 -0
  266. package/dist/templates/production-app/src/LivePreviewRenderer.js +199 -0
  267. package/dist/templates/production-app/src/componentRegistry.d.ts +20 -0
  268. package/dist/templates/production-app/src/componentRegistry.d.ts.map +1 -0
  269. package/dist/templates/production-app/src/componentRegistry.js +316 -0
  270. package/dist/templates/production-app/src/main.d.ts +9 -0
  271. package/dist/templates/production-app/src/main.d.ts.map +1 -0
  272. package/dist/templates/production-app/src/main.js +18 -0
  273. package/dist/templates/production-app/vite.config.d.ts +3 -0
  274. package/dist/templates/production-app/vite.config.d.ts.map +1 -0
  275. package/dist/templates/production-app/vite.config.js +71 -0
  276. package/dist/test-storybooks/angular-material-storybook/src/main.js +66 -0
  277. package/dist/test-storybooks/chakra-storybook/vite.config.js +6 -0
  278. package/dist/test-storybooks/mantine-storybook/vite.config.js +93 -0
  279. package/dist/test-storybooks/web-components-shoelace/vite.config.js +9 -0
  280. package/dist/tsconfig.tsbuildinfo +1 -0
  281. package/package.json +1 -1
@@ -0,0 +1,653 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Story UI Production App
4
+ *
5
+ * A Lovable/Bolt-style interface for generating UI components
6
+ * using AI and a user's component library.
7
+ */
8
+ import { useState, useEffect, useRef, useCallback } from 'react';
9
+ import { LivePreviewRenderer } from './LivePreviewRenderer';
10
+ import { availableComponents } from './componentRegistry';
11
+ // ============================================================================
12
+ // CONSTANTS & CONFIG
13
+ // ============================================================================
14
+ const getServerUrl = () => {
15
+ if (import.meta.env.VITE_STORY_UI_SERVER) {
16
+ return import.meta.env.VITE_STORY_UI_SERVER;
17
+ }
18
+ return window.location.origin;
19
+ };
20
+ const SERVER_URL = getServerUrl();
21
+ const THEME = {
22
+ bg: '#09090b',
23
+ bgSurface: '#18181b',
24
+ bgElevated: '#27272a',
25
+ bgHover: '#3f3f46',
26
+ border: '#27272a',
27
+ borderSubtle: '#3f3f46',
28
+ text: '#fafafa',
29
+ textMuted: '#a1a1aa',
30
+ textSubtle: '#71717a',
31
+ accent: '#3b82f6',
32
+ accentHover: '#2563eb',
33
+ accentMuted: 'rgba(59, 130, 246, 0.15)',
34
+ success: '#22c55e',
35
+ error: '#ef4444',
36
+ warning: '#f59e0b',
37
+ };
38
+ const generateId = () => Math.random().toString(36).substring(2, 15);
39
+ // ============================================================================
40
+ // HOOKS
41
+ // ============================================================================
42
+ const useLocalStorage = (key, initialValue) => {
43
+ const [storedValue, setStoredValue] = useState(() => {
44
+ try {
45
+ const item = window.localStorage.getItem(key);
46
+ return item ? JSON.parse(item) : initialValue;
47
+ }
48
+ catch {
49
+ return initialValue;
50
+ }
51
+ });
52
+ const setValue = (value) => {
53
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
54
+ setStoredValue(valueToStore);
55
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
56
+ };
57
+ return [storedValue, setValue];
58
+ };
59
+ const useResizable = (initialWidth, minWidth, maxWidth) => {
60
+ const [width, setWidth] = useState(initialWidth);
61
+ const isDragging = useRef(false);
62
+ const startX = useRef(0);
63
+ const startWidth = useRef(0);
64
+ const startResize = useCallback((e) => {
65
+ isDragging.current = true;
66
+ startX.current = e.clientX;
67
+ startWidth.current = width;
68
+ document.body.style.cursor = 'col-resize';
69
+ document.body.style.userSelect = 'none';
70
+ }, [width]);
71
+ useEffect(() => {
72
+ const handleMouseMove = (e) => {
73
+ if (!isDragging.current)
74
+ return;
75
+ const delta = e.clientX - startX.current;
76
+ const newWidth = Math.min(Math.max(startWidth.current + delta, minWidth), maxWidth);
77
+ setWidth(newWidth);
78
+ };
79
+ const handleMouseUp = () => {
80
+ isDragging.current = false;
81
+ document.body.style.cursor = '';
82
+ document.body.style.userSelect = '';
83
+ };
84
+ document.addEventListener('mousemove', handleMouseMove);
85
+ document.addEventListener('mouseup', handleMouseUp);
86
+ return () => {
87
+ document.removeEventListener('mousemove', handleMouseMove);
88
+ document.removeEventListener('mouseup', handleMouseUp);
89
+ };
90
+ }, [minWidth, maxWidth]);
91
+ return { width, startResize };
92
+ };
93
+ // ============================================================================
94
+ // ICON COMPONENTS
95
+ // ============================================================================
96
+ const Icons = {
97
+ Plus: () => (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M8 3v10M3 8h10" }) })),
98
+ Trash: () => (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: _jsx("path", { d: "M3 4h10M6 4V3a1 1 0 011-1h2a1 1 0 011 1v1M5 4v9a1 1 0 001 1h4a1 1 0 001-1V4" }) })),
99
+ Send: () => (_jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" }) })),
100
+ Image: () => (_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), _jsx("path", { d: "M21 15l-5-5L5 21" })] })),
101
+ Code: () => (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M16 18l6-6-6-6M8 6l-6 6 6 6" }) })),
102
+ Eye: () => (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), _jsx("circle", { cx: "12", cy: "12", r: "3" })] })),
103
+ Copy: () => (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" })] })),
104
+ Sidebar: () => (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("path", { d: "M9 3v18" })] })),
105
+ Check: () => (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M20 6L9 17l-5-5" }) })),
106
+ X: () => (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12" }) })),
107
+ };
108
+ // ============================================================================
109
+ // SUB-COMPONENTS
110
+ // ============================================================================
111
+ const LoadingDots = () => (_jsx("div", { style: { display: 'flex', gap: '4px', alignItems: 'center' }, children: [0, 1, 2].map(i => (_jsx("div", { style: {
112
+ width: '6px',
113
+ height: '6px',
114
+ borderRadius: '50%',
115
+ background: THEME.accent,
116
+ animation: `pulse 1.4s ease-in-out ${i * 0.2}s infinite`,
117
+ } }, i))) }));
118
+ const ImageUploadArea = ({ images, onImagesChange, disabled }) => {
119
+ const fileInputRef = useRef(null);
120
+ const handleFiles = useCallback((files) => {
121
+ Array.from(files).forEach(file => {
122
+ if (file.type.startsWith('image/')) {
123
+ const reader = new FileReader();
124
+ reader.onload = (e) => {
125
+ const newImage = {
126
+ id: generateId(),
127
+ data: e.target?.result,
128
+ type: file.type,
129
+ name: file.name,
130
+ };
131
+ onImagesChange([...images, newImage]);
132
+ };
133
+ reader.readAsDataURL(file);
134
+ }
135
+ });
136
+ }, [images, onImagesChange]);
137
+ const removeImage = (id) => {
138
+ onImagesChange(images.filter(img => img.id !== id));
139
+ };
140
+ return (_jsxs("div", { style: { marginBottom: images.length > 0 ? '12px' : 0 }, children: [_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, style: { display: 'none' }, onChange: (e) => e.target.files && handleFiles(e.target.files), disabled: disabled }), images.length > 0 && (_jsx("div", { style: { display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '8px' }, children: images.map(img => (_jsxs("div", { style: {
141
+ position: 'relative',
142
+ width: '64px',
143
+ height: '64px',
144
+ borderRadius: '8px',
145
+ overflow: 'hidden',
146
+ border: `1px solid ${THEME.border}`,
147
+ }, children: [_jsx("img", { src: img.data, alt: img.name, style: { width: '100%', height: '100%', objectFit: 'cover' } }), _jsx("button", { onClick: () => removeImage(img.id), style: {
148
+ position: 'absolute',
149
+ top: '2px',
150
+ right: '2px',
151
+ width: '18px',
152
+ height: '18px',
153
+ borderRadius: '50%',
154
+ background: 'rgba(0,0,0,0.7)',
155
+ border: 'none',
156
+ color: '#fff',
157
+ cursor: 'pointer',
158
+ display: 'flex',
159
+ alignItems: 'center',
160
+ justifyContent: 'center',
161
+ fontSize: '10px',
162
+ }, children: _jsx(Icons.X, {}) })] }, img.id))) })), _jsxs("button", { onClick: () => fileInputRef.current?.click(), disabled: disabled, style: {
163
+ display: 'flex',
164
+ alignItems: 'center',
165
+ gap: '6px',
166
+ padding: '6px 10px',
167
+ background: 'transparent',
168
+ border: `1px dashed ${THEME.border}`,
169
+ borderRadius: '6px',
170
+ color: THEME.textMuted,
171
+ fontSize: '12px',
172
+ cursor: disabled ? 'not-allowed' : 'pointer',
173
+ transition: 'all 0.2s',
174
+ opacity: disabled ? 0.5 : 1,
175
+ }, children: [_jsx(Icons.Image, {}), _jsx("span", { children: "Add image" })] })] }));
176
+ };
177
+ const CodeViewer = ({ code }) => {
178
+ const [copied, setCopied] = useState(false);
179
+ const handleCopy = async () => {
180
+ await navigator.clipboard.writeText(code);
181
+ setCopied(true);
182
+ setTimeout(() => setCopied(false), 2000);
183
+ };
184
+ return (_jsxs("div", { style: { height: '100%', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { style: {
185
+ padding: '8px 12px',
186
+ borderBottom: `1px solid ${THEME.border}`,
187
+ display: 'flex',
188
+ justifyContent: 'space-between',
189
+ alignItems: 'center',
190
+ }, children: [_jsx("span", { style: { fontSize: '12px', color: THEME.textMuted }, children: "Generated Code" }), _jsxs("button", { onClick: handleCopy, style: {
191
+ display: 'flex',
192
+ alignItems: 'center',
193
+ gap: '4px',
194
+ padding: '4px 8px',
195
+ background: copied ? 'rgba(34, 197, 94, 0.2)' : 'transparent',
196
+ border: `1px solid ${copied ? THEME.success : THEME.border}`,
197
+ borderRadius: '4px',
198
+ color: copied ? THEME.success : THEME.textMuted,
199
+ fontSize: '11px',
200
+ cursor: 'pointer',
201
+ transition: 'all 0.2s',
202
+ }, children: [copied ? _jsx(Icons.Check, {}) : _jsx(Icons.Copy, {}), copied ? 'Copied!' : 'Copy'] })] }), _jsx("pre", { style: {
203
+ flex: 1,
204
+ margin: 0,
205
+ padding: '16px',
206
+ overflow: 'auto',
207
+ fontSize: '13px',
208
+ lineHeight: 1.6,
209
+ fontFamily: '"Fira Code", "SF Mono", Monaco, monospace',
210
+ background: '#0d1117',
211
+ color: '#e6edf3',
212
+ }, children: code })] }));
213
+ };
214
+ // ============================================================================
215
+ // MAIN APP
216
+ // ============================================================================
217
+ const App = () => {
218
+ const [conversations, setConversations] = useLocalStorage('storyui_conversations', []);
219
+ const [activeConversationId, setActiveConversationId] = useState(null);
220
+ const [inputValue, setInputValue] = useState('');
221
+ const [isGenerating, setIsGenerating] = useState(false);
222
+ const [previewCode, setPreviewCode] = useState(null);
223
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
224
+ const [previewTab, setPreviewTab] = useState('preview');
225
+ const [images, setImages] = useState([]);
226
+ const messagesEndRef = useRef(null);
227
+ const inputRef = useRef(null);
228
+ const { width: chatWidth, startResize } = useResizable(400, 320, 600);
229
+ const activeConversation = conversations.find(c => c.id === activeConversationId);
230
+ // Auto-scroll messages
231
+ useEffect(() => {
232
+ messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
233
+ }, [activeConversation?.messages]);
234
+ // Initialize first conversation
235
+ useEffect(() => {
236
+ if (conversations.length > 0 && !activeConversationId) {
237
+ setActiveConversationId(conversations[0].id);
238
+ const lastMsgWithCode = [...conversations[0].messages].reverse().find(m => m.generatedCode);
239
+ setPreviewCode(lastMsgWithCode?.generatedCode || null);
240
+ }
241
+ else if (conversations.length === 0) {
242
+ createNewConversation();
243
+ }
244
+ }, [conversations.length, activeConversationId]);
245
+ const createNewConversation = useCallback(() => {
246
+ const newConversation = {
247
+ id: generateId(),
248
+ title: 'New Conversation',
249
+ messages: [],
250
+ createdAt: Date.now(),
251
+ updatedAt: Date.now(),
252
+ };
253
+ setConversations(prev => [newConversation, ...prev]);
254
+ setActiveConversationId(newConversation.id);
255
+ setPreviewCode(null);
256
+ setImages([]);
257
+ inputRef.current?.focus();
258
+ }, [setConversations]);
259
+ const deleteConversation = (id) => {
260
+ setConversations(prev => prev.filter(c => c.id !== id));
261
+ if (activeConversationId === id) {
262
+ const remaining = conversations.filter(c => c.id !== id);
263
+ if (remaining.length > 0) {
264
+ setActiveConversationId(remaining[0].id);
265
+ }
266
+ else {
267
+ createNewConversation();
268
+ }
269
+ }
270
+ };
271
+ const generateComponent = async (prompt, imageAttachments) => {
272
+ const conversationHistory = activeConversation?.messages.map(msg => ({
273
+ role: msg.role,
274
+ content: msg.role === 'assistant' && msg.generatedCode
275
+ ? `Generated component:\n${msg.generatedCode}`
276
+ : msg.content
277
+ })) || [];
278
+ const systemPrompt = `You are a UI component generator. Generate React JSX code using ONLY these available components: ${availableComponents.join(', ')}.
279
+
280
+ IMPORTANT RULES:
281
+ 1. Return ONLY the JSX code - a single JSX expression that can be rendered
282
+ 2. Use ONLY the components listed above - they are from the user's component library
283
+ 3. Do NOT include imports, exports, or component definitions
284
+ 4. Generate professional, polished UI layouts
285
+ 5. Use proper props for each component based on their typical API
286
+
287
+ Example response format:
288
+ <Card>
289
+ <Text>Hello World</Text>
290
+ <Button>Click me</Button>
291
+ </Card>
292
+
293
+ Only respond with the JSX code, nothing else.`;
294
+ const response = await fetch(`${SERVER_URL}/story-ui/claude`, {
295
+ method: 'POST',
296
+ headers: { 'Content-Type': 'application/json' },
297
+ body: JSON.stringify({
298
+ prompt,
299
+ messages: conversationHistory,
300
+ systemPrompt,
301
+ maxTokens: 4096,
302
+ images: imageAttachments.map(img => ({
303
+ type: img.type,
304
+ data: img.data.split(',')[1],
305
+ })),
306
+ }),
307
+ });
308
+ if (!response.ok) {
309
+ const errorData = await response.json().catch(() => ({}));
310
+ throw new Error(errorData.error || `Server Error: ${response.status}`);
311
+ }
312
+ const data = await response.json();
313
+ const content = data.content?.[0]?.text || data.content || '';
314
+ // Clean up the response
315
+ let cleanCode = content.trim();
316
+ if (cleanCode.startsWith('```')) {
317
+ cleanCode = cleanCode
318
+ .replace(/^```(?:jsx|tsx|javascript|js)?\n?/, '')
319
+ .replace(/\n?```$/, '');
320
+ }
321
+ return cleanCode;
322
+ };
323
+ const sendMessage = async () => {
324
+ if (!inputValue.trim() || !activeConversationId || isGenerating)
325
+ return;
326
+ const userMessage = {
327
+ id: generateId(),
328
+ role: 'user',
329
+ content: inputValue.trim(),
330
+ timestamp: Date.now(),
331
+ images: images.length > 0 ? [...images] : undefined,
332
+ };
333
+ setConversations(prev => prev.map(conv => {
334
+ if (conv.id === activeConversationId) {
335
+ return {
336
+ ...conv,
337
+ messages: [...conv.messages, userMessage],
338
+ updatedAt: Date.now(),
339
+ title: conv.messages.length === 0 ? inputValue.trim().substring(0, 40) : conv.title,
340
+ };
341
+ }
342
+ return conv;
343
+ }));
344
+ const currentImages = [...images];
345
+ setInputValue('');
346
+ setImages([]);
347
+ setIsGenerating(true);
348
+ try {
349
+ const generatedCode = await generateComponent(inputValue.trim(), currentImages);
350
+ const assistantMessage = {
351
+ id: generateId(),
352
+ role: 'assistant',
353
+ content: 'Component generated successfully.',
354
+ timestamp: Date.now(),
355
+ generatedCode,
356
+ };
357
+ setConversations(prev => prev.map(conv => {
358
+ if (conv.id === activeConversationId) {
359
+ return {
360
+ ...conv,
361
+ messages: [...conv.messages, assistantMessage],
362
+ updatedAt: Date.now(),
363
+ };
364
+ }
365
+ return conv;
366
+ }));
367
+ if (generatedCode) {
368
+ setPreviewCode(generatedCode);
369
+ setPreviewTab('preview');
370
+ }
371
+ }
372
+ catch (error) {
373
+ const errorMessage = {
374
+ id: generateId(),
375
+ role: 'assistant',
376
+ content: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
377
+ timestamp: Date.now(),
378
+ };
379
+ setConversations(prev => prev.map(conv => {
380
+ if (conv.id === activeConversationId) {
381
+ return {
382
+ ...conv,
383
+ messages: [...conv.messages, errorMessage],
384
+ updatedAt: Date.now(),
385
+ };
386
+ }
387
+ return conv;
388
+ }));
389
+ }
390
+ finally {
391
+ setIsGenerating(false);
392
+ }
393
+ };
394
+ const handleKeyPress = (e) => {
395
+ if (e.key === 'Enter' && !e.shiftKey) {
396
+ e.preventDefault();
397
+ sendMessage();
398
+ }
399
+ };
400
+ return (_jsxs("div", { style: {
401
+ display: 'flex',
402
+ height: '100vh',
403
+ overflow: 'hidden',
404
+ background: THEME.bg,
405
+ color: THEME.text,
406
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
407
+ }, children: [_jsx("style", { children: `
408
+ @keyframes pulse {
409
+ 0%, 100% { opacity: 0.4; transform: scale(0.8); }
410
+ 50% { opacity: 1; transform: scale(1); }
411
+ }
412
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
413
+ ::-webkit-scrollbar-track { background: transparent; }
414
+ ::-webkit-scrollbar-thumb { background: ${THEME.bgElevated}; border-radius: 3px; }
415
+ ::-webkit-scrollbar-thumb:hover { background: ${THEME.bgHover}; }
416
+ ` }), _jsxs("aside", { style: {
417
+ width: sidebarCollapsed ? '60px' : '240px',
418
+ background: THEME.bgSurface,
419
+ borderRight: `1px solid ${THEME.border}`,
420
+ display: 'flex',
421
+ flexDirection: 'column',
422
+ transition: 'width 0.2s ease',
423
+ overflow: 'hidden',
424
+ }, children: [_jsxs("div", { style: {
425
+ padding: '16px',
426
+ borderBottom: `1px solid ${THEME.border}`,
427
+ display: 'flex',
428
+ alignItems: 'center',
429
+ justifyContent: sidebarCollapsed ? 'center' : 'space-between',
430
+ }, children: [!sidebarCollapsed && (_jsx("h1", { style: {
431
+ fontSize: '16px',
432
+ fontWeight: 600,
433
+ background: `linear-gradient(135deg, ${THEME.accent}, #8b5cf6)`,
434
+ WebkitBackgroundClip: 'text',
435
+ WebkitTextFillColor: 'transparent',
436
+ letterSpacing: '-0.5px',
437
+ }, children: "Story UI" })), _jsx("button", { onClick: () => setSidebarCollapsed(!sidebarCollapsed), style: {
438
+ padding: '8px',
439
+ background: 'transparent',
440
+ border: 'none',
441
+ color: THEME.textMuted,
442
+ cursor: 'pointer',
443
+ borderRadius: '6px',
444
+ }, children: _jsx(Icons.Sidebar, {}) })] }), _jsx("div", { style: { padding: sidebarCollapsed ? '8px' : '12px' }, children: _jsxs("button", { onClick: createNewConversation, style: {
445
+ width: '100%',
446
+ padding: sidebarCollapsed ? '10px' : '10px 14px',
447
+ background: THEME.accent,
448
+ border: 'none',
449
+ borderRadius: '8px',
450
+ color: '#fff',
451
+ fontSize: '13px',
452
+ fontWeight: 500,
453
+ cursor: 'pointer',
454
+ display: 'flex',
455
+ alignItems: 'center',
456
+ justifyContent: 'center',
457
+ gap: '8px',
458
+ }, children: [_jsx(Icons.Plus, {}), !sidebarCollapsed && 'New Chat'] }) }), !sidebarCollapsed && (_jsx("div", { style: { flex: 1, overflow: 'auto', padding: '8px 12px' }, children: conversations.map(conv => (_jsxs("div", { onClick: () => {
459
+ setActiveConversationId(conv.id);
460
+ const lastMsgWithCode = [...conv.messages].reverse().find(m => m.generatedCode);
461
+ setPreviewCode(lastMsgWithCode?.generatedCode || null);
462
+ }, style: {
463
+ padding: '10px 12px',
464
+ marginBottom: '4px',
465
+ borderRadius: '8px',
466
+ cursor: 'pointer',
467
+ display: 'flex',
468
+ alignItems: 'center',
469
+ justifyContent: 'space-between',
470
+ background: conv.id === activeConversationId ? THEME.bgElevated : 'transparent',
471
+ }, children: [_jsx("span", { style: {
472
+ fontSize: '13px',
473
+ color: conv.id === activeConversationId ? THEME.text : THEME.textMuted,
474
+ overflow: 'hidden',
475
+ textOverflow: 'ellipsis',
476
+ whiteSpace: 'nowrap',
477
+ flex: 1,
478
+ }, children: conv.title }), _jsx("button", { onClick: (e) => {
479
+ e.stopPropagation();
480
+ deleteConversation(conv.id);
481
+ }, style: {
482
+ padding: '4px',
483
+ background: 'transparent',
484
+ border: 'none',
485
+ color: THEME.textSubtle,
486
+ cursor: 'pointer',
487
+ opacity: 0.5,
488
+ }, children: _jsx(Icons.Trash, {}) })] }, conv.id))) })), !sidebarCollapsed && (_jsx("div", { style: {
489
+ padding: '12px',
490
+ borderTop: `1px solid ${THEME.border}`,
491
+ fontSize: '11px',
492
+ color: THEME.textSubtle,
493
+ }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx("div", { style: {
494
+ width: '6px',
495
+ height: '6px',
496
+ borderRadius: '50%',
497
+ background: THEME.success,
498
+ } }), _jsxs("span", { children: [availableComponents.length, " components available"] })] }) }))] }), _jsxs("div", { style: {
499
+ width: `${chatWidth}px`,
500
+ display: 'flex',
501
+ flexDirection: 'column',
502
+ background: THEME.bg,
503
+ borderRight: `1px solid ${THEME.border}`,
504
+ position: 'relative',
505
+ }, children: [_jsxs("div", { style: { flex: 1, overflow: 'auto', padding: '16px' }, children: [activeConversation?.messages.length === 0 && (_jsxs("div", { style: {
506
+ padding: '32px 16px',
507
+ textAlign: 'center',
508
+ }, children: [_jsx("h2", { style: {
509
+ fontSize: '24px',
510
+ fontWeight: 600,
511
+ marginBottom: '8px',
512
+ background: `linear-gradient(135deg, ${THEME.text}, ${THEME.textMuted})`,
513
+ WebkitBackgroundClip: 'text',
514
+ WebkitTextFillColor: 'transparent',
515
+ }, children: "Build UI Components" }), _jsx("p", { style: {
516
+ color: THEME.textMuted,
517
+ fontSize: '14px',
518
+ marginBottom: '24px',
519
+ lineHeight: 1.6,
520
+ }, children: "Describe what you want to build using your component library." }), _jsx("div", { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', justifyContent: 'center' }, children: ['Create a pricing card', 'Build a dashboard', 'Design a login form'].map(suggestion => (_jsx("button", { onClick: () => setInputValue(suggestion), style: {
521
+ padding: '8px 14px',
522
+ background: THEME.bgSurface,
523
+ border: `1px solid ${THEME.border}`,
524
+ borderRadius: '20px',
525
+ color: THEME.textMuted,
526
+ fontSize: '13px',
527
+ cursor: 'pointer',
528
+ }, children: suggestion }, suggestion))) })] })), activeConversation?.messages.map(message => (_jsxs("div", { style: {
529
+ marginBottom: '16px',
530
+ padding: '14px 16px',
531
+ borderRadius: '12px',
532
+ maxWidth: '90%',
533
+ marginLeft: message.role === 'user' ? 'auto' : '0',
534
+ marginRight: message.role === 'user' ? '0' : 'auto',
535
+ background: message.role === 'user' ? THEME.bgElevated : THEME.bgSurface,
536
+ border: `1px solid ${THEME.border}`,
537
+ }, children: [message.images && message.images.length > 0 && (_jsx("div", { style: { display: 'flex', gap: '8px', marginBottom: '10px', flexWrap: 'wrap' }, children: message.images.map(img => (_jsx("img", { src: img.data, alt: img.name, style: {
538
+ width: '80px',
539
+ height: '80px',
540
+ objectFit: 'cover',
541
+ borderRadius: '8px',
542
+ border: `1px solid ${THEME.border}`,
543
+ } }, img.id))) })), _jsx("div", { style: { fontSize: '14px', lineHeight: 1.6, color: THEME.text }, children: message.content }), message.generatedCode && (_jsxs("button", { onClick: () => {
544
+ setPreviewCode(message.generatedCode);
545
+ setPreviewTab('preview');
546
+ }, style: {
547
+ marginTop: '10px',
548
+ padding: '6px 12px',
549
+ background: THEME.accentMuted,
550
+ border: `1px solid ${THEME.accent}`,
551
+ borderRadius: '6px',
552
+ color: THEME.accent,
553
+ fontSize: '12px',
554
+ cursor: 'pointer',
555
+ display: 'flex',
556
+ alignItems: 'center',
557
+ gap: '6px',
558
+ }, children: [_jsx(Icons.Eye, {}), "View Component"] }))] }, message.id))), isGenerating && (_jsx("div", { style: {
559
+ marginBottom: '16px',
560
+ padding: '14px 16px',
561
+ borderRadius: '12px',
562
+ maxWidth: '90%',
563
+ background: THEME.bgSurface,
564
+ border: `1px solid ${THEME.border}`,
565
+ }, children: _jsx(LoadingDots, {}) })), _jsx("div", { ref: messagesEndRef })] }), _jsxs("div", { style: {
566
+ padding: '16px',
567
+ borderTop: `1px solid ${THEME.border}`,
568
+ background: THEME.bgSurface,
569
+ }, children: [_jsx(ImageUploadArea, { images: images, onImagesChange: setImages, disabled: isGenerating }), _jsxs("div", { style: { display: 'flex', gap: '10px', alignItems: 'flex-end' }, children: [_jsx("textarea", { ref: inputRef, value: inputValue, onChange: e => setInputValue(e.target.value), onKeyDown: handleKeyPress, placeholder: "Describe the component you want to create...", disabled: isGenerating, style: {
570
+ flex: 1,
571
+ padding: '12px 14px',
572
+ background: THEME.bgElevated,
573
+ border: `1px solid ${THEME.border}`,
574
+ borderRadius: '10px',
575
+ color: THEME.text,
576
+ fontSize: '14px',
577
+ resize: 'none',
578
+ outline: 'none',
579
+ fontFamily: 'inherit',
580
+ minHeight: '44px',
581
+ maxHeight: '120px',
582
+ }, rows: 1 }), _jsx("button", { onClick: sendMessage, disabled: isGenerating || !inputValue.trim(), style: {
583
+ padding: '12px',
584
+ background: (isGenerating || !inputValue.trim()) ? THEME.bgElevated : THEME.accent,
585
+ border: 'none',
586
+ borderRadius: '10px',
587
+ color: (isGenerating || !inputValue.trim()) ? THEME.textSubtle : '#fff',
588
+ cursor: (isGenerating || !inputValue.trim()) ? 'not-allowed' : 'pointer',
589
+ minWidth: '44px',
590
+ height: '44px',
591
+ }, children: _jsx(Icons.Send, {}) })] })] }), _jsx("div", { onMouseDown: startResize, style: {
592
+ position: 'absolute',
593
+ right: 0,
594
+ top: 0,
595
+ bottom: 0,
596
+ width: '4px',
597
+ cursor: 'col-resize',
598
+ background: 'transparent',
599
+ } })] }), _jsxs("div", { style: {
600
+ flex: 1,
601
+ display: 'flex',
602
+ flexDirection: 'column',
603
+ background: THEME.bg,
604
+ minWidth: 0,
605
+ }, children: [_jsxs("div", { style: {
606
+ padding: '12px 16px',
607
+ borderBottom: `1px solid ${THEME.border}`,
608
+ display: 'flex',
609
+ alignItems: 'center',
610
+ justifyContent: 'space-between',
611
+ }, children: [_jsxs("div", { style: { display: 'flex', gap: '4px' }, children: [_jsxs("button", { onClick: () => setPreviewTab('preview'), style: {
612
+ padding: '8px 14px',
613
+ background: previewTab === 'preview' ? THEME.bgElevated : 'transparent',
614
+ border: 'none',
615
+ borderRadius: '6px',
616
+ color: previewTab === 'preview' ? THEME.text : THEME.textMuted,
617
+ fontSize: '13px',
618
+ cursor: 'pointer',
619
+ display: 'flex',
620
+ alignItems: 'center',
621
+ gap: '6px',
622
+ }, children: [_jsx(Icons.Eye, {}), "Preview"] }), _jsxs("button", { onClick: () => setPreviewTab('code'), style: {
623
+ padding: '8px 14px',
624
+ background: previewTab === 'code' ? THEME.bgElevated : 'transparent',
625
+ border: 'none',
626
+ borderRadius: '6px',
627
+ color: previewTab === 'code' ? THEME.text : THEME.textMuted,
628
+ fontSize: '13px',
629
+ cursor: 'pointer',
630
+ display: 'flex',
631
+ alignItems: 'center',
632
+ gap: '6px',
633
+ }, children: [_jsx(Icons.Code, {}), "Code"] })] }), previewCode && previewTab === 'preview' && (_jsx("span", { style: { fontSize: '12px', color: THEME.textMuted }, children: "Live Preview" }))] }), _jsx("div", { style: { flex: 1, overflow: 'hidden' }, children: previewCode ? (previewTab === 'preview' ? (_jsx(LivePreviewRenderer, { code: previewCode, containerStyle: { height: '100%', background: THEME.bgSurface }, onError: (err) => console.error('Preview error:', err) })) : (_jsx(CodeViewer, { code: previewCode }))) : (_jsxs("div", { style: {
634
+ height: '100%',
635
+ display: 'flex',
636
+ flexDirection: 'column',
637
+ alignItems: 'center',
638
+ justifyContent: 'center',
639
+ color: THEME.textSubtle,
640
+ padding: '40px',
641
+ }, children: [_jsx("div", { style: {
642
+ width: '80px',
643
+ height: '80px',
644
+ borderRadius: '20px',
645
+ background: THEME.bgSurface,
646
+ display: 'flex',
647
+ alignItems: 'center',
648
+ justifyContent: 'center',
649
+ marginBottom: '20px',
650
+ border: `1px solid ${THEME.border}`,
651
+ }, children: _jsxs("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("path", { d: "M3 9h18M9 21V9" })] }) }), _jsx("p", { style: { fontSize: '16px', fontWeight: 500, marginBottom: '8px', color: THEME.textMuted }, children: "Ready to Build" }), _jsx("p", { style: { fontSize: '14px', maxWidth: '260px', textAlign: 'center', lineHeight: 1.5 }, children: "Describe a component and watch it come to life" })] })) })] })] }));
652
+ };
653
+ export default App;