@tpitre/story-ui 3.0.0 → 3.2.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/README.md +25 -72
  2. package/dist/cli/deploy.d.ts +0 -7
  3. package/dist/cli/deploy.d.ts.map +1 -1
  4. package/dist/cli/deploy.js +10 -421
  5. package/dist/cli/index.js +0 -0
  6. package/dist/mcp-server/index.js +7 -8
  7. package/dist/mcp-server/mcp-stdio-server.js +1 -2
  8. package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
  9. package/dist/mcp-server/routes/generateStory.js +3 -3
  10. package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
  11. package/dist/mcp-server/routes/generateStoryStream.js +3 -3
  12. package/dist/mcp-server/routes/hybridStories.d.ts +6 -6
  13. package/dist/mcp-server/routes/hybridStories.d.ts.map +1 -1
  14. package/dist/mcp-server/routes/hybridStories.js +29 -27
  15. package/dist/mcp-server/routes/memoryStories.d.ts +7 -7
  16. package/dist/mcp-server/routes/memoryStories.d.ts.map +1 -1
  17. package/dist/mcp-server/routes/memoryStories.js +37 -26
  18. package/dist/story-generator/postgresStoryService.d.ts +56 -0
  19. package/dist/story-generator/postgresStoryService.d.ts.map +1 -0
  20. package/dist/story-generator/postgresStoryService.js +240 -0
  21. package/dist/story-generator/storyServiceFactory.d.ts +22 -0
  22. package/dist/story-generator/storyServiceFactory.d.ts.map +1 -0
  23. package/dist/story-generator/storyServiceFactory.js +97 -0
  24. package/dist/story-generator/storyServiceInterface.d.ts +85 -0
  25. package/dist/story-generator/storyServiceInterface.d.ts.map +1 -0
  26. package/dist/story-generator/storyServiceInterface.js +5 -0
  27. package/dist/templates/StoryUI/StoryUIPanel.d.ts +5 -0
  28. package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
  29. package/dist/templates/StoryUI/StoryUIPanel.js +18 -3
  30. package/package.json +6 -6
  31. package/templates/StoryUI/StoryUIPanel.tsx +28 -3
  32. package/templates/StoryUI/manager.tsx +444 -213
  33. package/dist/cli/index.js.map +0 -1
  34. package/dist/cli/setup.js.map +0 -1
  35. package/dist/cloudflare-edge/src/mcp-session.js +0 -462
  36. package/dist/cloudflare-edge/src/types.js +0 -4
  37. package/dist/cloudflare-edge/src/worker.js +0 -106
  38. package/dist/cloudflare-pages/vite.config.js +0 -14
  39. package/dist/index.d.ts +0 -13
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/index.js +0 -12
  42. package/dist/index.js.map +0 -1
  43. package/dist/mcp-server/index.js.map +0 -1
  44. package/dist/mcp-server/mcp-stdio-server.js.map +0 -1
  45. package/dist/mcp-server/routes/claude.js.map +0 -1
  46. package/dist/mcp-server/routes/components.js.map +0 -1
  47. package/dist/mcp-server/routes/generateStory.js.map +0 -1
  48. package/dist/mcp-server/routes/hybridStories.js.map +0 -1
  49. package/dist/mcp-server/routes/memoryStories.js.map +0 -1
  50. package/dist/mcp-server/routes/storySync.js.map +0 -1
  51. package/dist/mcp-server/routes/updateStory.js +0 -246
  52. package/dist/mcp-server/sessionManager.js.map +0 -1
  53. package/dist/playground/components/AIAssistant/AIAssistant.d.ts +0 -6
  54. package/dist/playground/components/AIAssistant/AIAssistant.d.ts.map +0 -1
  55. package/dist/playground/components/AIAssistant/AIAssistant.js +0 -109
  56. package/dist/playground/components/AIAssistant/AIAssistant.js.map +0 -1
  57. package/dist/playground/components/AIAssistant/AIAssistant.module.css +0 -166
  58. package/dist/playground/components/Canvas/Canvas.d.ts +0 -9
  59. package/dist/playground/components/Canvas/Canvas.d.ts.map +0 -1
  60. package/dist/playground/components/Canvas/Canvas.js +0 -58
  61. package/dist/playground/components/Canvas/Canvas.js.map +0 -1
  62. package/dist/playground/components/Canvas/Canvas.module.css +0 -189
  63. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts +0 -9
  64. package/dist/playground/components/Canvas/CanvasWithDnd.d.ts.map +0 -1
  65. package/dist/playground/components/Canvas/CanvasWithDnd.js +0 -158
  66. package/dist/playground/components/Canvas/CanvasWithDnd.js.map +0 -1
  67. package/dist/playground/components/Canvas/ComponentRenderer.d.ts +0 -15
  68. package/dist/playground/components/Canvas/ComponentRenderer.d.ts.map +0 -1
  69. package/dist/playground/components/Canvas/ComponentRenderer.js +0 -177
  70. package/dist/playground/components/Canvas/ComponentRenderer.js.map +0 -1
  71. package/dist/playground/components/Canvas/DraggableComponent.d.ts +0 -15
  72. package/dist/playground/components/Canvas/DraggableComponent.d.ts.map +0 -1
  73. package/dist/playground/components/Canvas/DraggableComponent.js +0 -49
  74. package/dist/playground/components/Canvas/DraggableComponent.js.map +0 -1
  75. package/dist/playground/components/Canvas/index.d.ts +0 -9
  76. package/dist/playground/components/Canvas/index.d.ts.map +0 -1
  77. package/dist/playground/components/Canvas/index.js +0 -5
  78. package/dist/playground/components/Canvas/index.js.map +0 -1
  79. package/dist/playground/components/CodeView/CodeView.d.ts +0 -12
  80. package/dist/playground/components/CodeView/CodeView.d.ts.map +0 -1
  81. package/dist/playground/components/CodeView/CodeView.js +0 -77
  82. package/dist/playground/components/CodeView/CodeView.js.map +0 -1
  83. package/dist/playground/components/CodeView/CodeView.module.css +0 -178
  84. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts +0 -17
  85. package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts.map +0 -1
  86. package/dist/playground/components/ComponentPalette/ComponentPalette.js +0 -138
  87. package/dist/playground/components/ComponentPalette/ComponentPalette.js.map +0 -1
  88. package/dist/playground/components/ComponentPalette/ComponentPalette.module.css +0 -217
  89. package/dist/playground/components/ComponentPalette/index.d.ts +0 -3
  90. package/dist/playground/components/ComponentPalette/index.d.ts.map +0 -1
  91. package/dist/playground/components/ComponentPalette/index.js +0 -2
  92. package/dist/playground/components/ComponentPalette/index.js.map +0 -1
  93. package/dist/playground/components/DropZone/DropZone.d.ts +0 -17
  94. package/dist/playground/components/DropZone/DropZone.d.ts.map +0 -1
  95. package/dist/playground/components/DropZone/DropZone.js +0 -73
  96. package/dist/playground/components/DropZone/DropZone.js.map +0 -1
  97. package/dist/playground/components/DropZone/DropZone.module.css +0 -86
  98. package/dist/playground/components/ExportDialog/ExportDialog.d.ts +0 -10
  99. package/dist/playground/components/ExportDialog/ExportDialog.d.ts.map +0 -1
  100. package/dist/playground/components/ExportDialog/ExportDialog.js +0 -57
  101. package/dist/playground/components/ExportDialog/ExportDialog.js.map +0 -1
  102. package/dist/playground/components/ExportDialog/ExportDialog.module.css +0 -328
  103. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts +0 -134
  104. package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts.map +0 -1
  105. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js +0 -254
  106. package/dist/playground/components/LayoutHelpers/LayoutHelpers.js.map +0 -1
  107. package/dist/playground/components/LayoutHelpers/index.d.ts +0 -3
  108. package/dist/playground/components/LayoutHelpers/index.d.ts.map +0 -1
  109. package/dist/playground/components/LayoutHelpers/index.js +0 -2
  110. package/dist/playground/components/LayoutHelpers/index.js.map +0 -1
  111. package/dist/playground/components/Playground/Playground.d.ts +0 -10
  112. package/dist/playground/components/Playground/Playground.d.ts.map +0 -1
  113. package/dist/playground/components/Playground/Playground.js +0 -128
  114. package/dist/playground/components/Playground/Playground.js.map +0 -1
  115. package/dist/playground/components/Playground/Playground.module.css +0 -308
  116. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts +0 -10
  117. package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts.map +0 -1
  118. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js +0 -150
  119. package/dist/playground/components/PropertiesPanel/PropertiesPanel.js.map +0 -1
  120. package/dist/playground/components/PropertiesPanel/PropertiesPanel.module.css +0 -155
  121. package/dist/playground/components/PropertiesPanel/index.d.ts +0 -3
  122. package/dist/playground/components/PropertiesPanel/index.d.ts.map +0 -1
  123. package/dist/playground/components/PropertiesPanel/index.js +0 -2
  124. package/dist/playground/components/PropertiesPanel/index.js.map +0 -1
  125. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts +0 -12
  126. package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts.map +0 -1
  127. package/dist/playground/components/PropertyEditors/BooleanEditor.js +0 -14
  128. package/dist/playground/components/PropertyEditors/BooleanEditor.js.map +0 -1
  129. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts +0 -12
  130. package/dist/playground/components/PropertyEditors/ColorEditor.d.ts.map +0 -1
  131. package/dist/playground/components/PropertyEditors/ColorEditor.js +0 -62
  132. package/dist/playground/components/PropertyEditors/ColorEditor.js.map +0 -1
  133. package/dist/playground/components/PropertyEditors/IconEditor.d.ts +0 -12
  134. package/dist/playground/components/PropertyEditors/IconEditor.d.ts.map +0 -1
  135. package/dist/playground/components/PropertyEditors/IconEditor.js +0 -123
  136. package/dist/playground/components/PropertyEditors/IconEditor.js.map +0 -1
  137. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts +0 -15
  138. package/dist/playground/components/PropertyEditors/NumberEditor.d.ts.map +0 -1
  139. package/dist/playground/components/PropertyEditors/NumberEditor.js +0 -46
  140. package/dist/playground/components/PropertyEditors/NumberEditor.js.map +0 -1
  141. package/dist/playground/components/PropertyEditors/PropertyEditors.module.css +0 -432
  142. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts +0 -19
  143. package/dist/playground/components/PropertyEditors/SelectEditor.d.ts.map +0 -1
  144. package/dist/playground/components/PropertyEditors/SelectEditor.js +0 -17
  145. package/dist/playground/components/PropertyEditors/SelectEditor.js.map +0 -1
  146. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts +0 -19
  147. package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts.map +0 -1
  148. package/dist/playground/components/PropertyEditors/SpacingEditor.js +0 -162
  149. package/dist/playground/components/PropertyEditors/SpacingEditor.js.map +0 -1
  150. package/dist/playground/components/PropertyEditors/SpacingEditor.module.css +0 -214
  151. package/dist/playground/components/PropertyEditors/TextEditor.d.ts +0 -14
  152. package/dist/playground/components/PropertyEditors/TextEditor.d.ts.map +0 -1
  153. package/dist/playground/components/PropertyEditors/TextEditor.js +0 -38
  154. package/dist/playground/components/PropertyEditors/TextEditor.js.map +0 -1
  155. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts +0 -23
  156. package/dist/playground/components/PropertyEditors/TokenEditor.d.ts.map +0 -1
  157. package/dist/playground/components/PropertyEditors/TokenEditor.js +0 -50
  158. package/dist/playground/components/PropertyEditors/TokenEditor.js.map +0 -1
  159. package/dist/playground/components/PropertyEditors/index.d.ts +0 -20
  160. package/dist/playground/components/PropertyEditors/index.d.ts.map +0 -1
  161. package/dist/playground/components/PropertyEditors/index.js +0 -12
  162. package/dist/playground/components/PropertyEditors/index.js.map +0 -1
  163. package/dist/playground/components/TreeView/TreeView.d.ts +0 -10
  164. package/dist/playground/components/TreeView/TreeView.d.ts.map +0 -1
  165. package/dist/playground/components/TreeView/TreeView.js +0 -146
  166. package/dist/playground/components/TreeView/TreeView.js.map +0 -1
  167. package/dist/playground/components/TreeView/TreeView.module.css +0 -214
  168. package/dist/playground/components/TreeView/index.d.ts +0 -3
  169. package/dist/playground/components/TreeView/index.d.ts.map +0 -1
  170. package/dist/playground/components/TreeView/index.js +0 -2
  171. package/dist/playground/components/TreeView/index.js.map +0 -1
  172. package/dist/playground/config/propertyDefinitions.d.ts +0 -73
  173. package/dist/playground/config/propertyDefinitions.d.ts.map +0 -1
  174. package/dist/playground/config/propertyDefinitions.js +0 -809
  175. package/dist/playground/config/propertyDefinitions.js.map +0 -1
  176. package/dist/playground/hooks/useKeyboardShortcuts.d.ts +0 -38
  177. package/dist/playground/hooks/useKeyboardShortcuts.d.ts.map +0 -1
  178. package/dist/playground/hooks/useKeyboardShortcuts.js +0 -191
  179. package/dist/playground/hooks/useKeyboardShortcuts.js.map +0 -1
  180. package/dist/playground/index.d.ts +0 -21
  181. package/dist/playground/index.d.ts.map +0 -1
  182. package/dist/playground/index.js +0 -23
  183. package/dist/playground/index.js.map +0 -1
  184. package/dist/playground/services/CodeGenerator.d.ts +0 -73
  185. package/dist/playground/services/CodeGenerator.d.ts.map +0 -1
  186. package/dist/playground/services/CodeGenerator.js +0 -359
  187. package/dist/playground/services/CodeGenerator.js.map +0 -1
  188. package/dist/playground/services/DragDropManager.d.ts +0 -95
  189. package/dist/playground/services/DragDropManager.d.ts.map +0 -1
  190. package/dist/playground/services/DragDropManager.js +0 -408
  191. package/dist/playground/services/DragDropManager.js.map +0 -1
  192. package/dist/playground/services/StoryParser.d.ts +0 -73
  193. package/dist/playground/services/StoryParser.d.ts.map +0 -1
  194. package/dist/playground/services/StoryParser.js +0 -419
  195. package/dist/playground/services/StoryParser.js.map +0 -1
  196. package/dist/playground/store/playgroundStore.d.ts +0 -86
  197. package/dist/playground/store/playgroundStore.d.ts.map +0 -1
  198. package/dist/playground/store/playgroundStore.js +0 -337
  199. package/dist/playground/store/playgroundStore.js.map +0 -1
  200. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts +0 -13
  201. package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts.map +0 -1
  202. package/dist/playground/stories/PlaygroundDragDrop.stories.js +0 -227
  203. package/dist/playground/stories/PlaygroundDragDrop.stories.js.map +0 -1
  204. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts +0 -13
  205. package/dist/playground/stories/PlaygroundPhase4.stories.d.ts.map +0 -1
  206. package/dist/playground/stories/PlaygroundPhase4.stories.js +0 -334
  207. package/dist/playground/stories/PlaygroundPhase4.stories.js.map +0 -1
  208. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts +0 -14
  209. package/dist/playground/stories/PlaygroundPhase5.stories.d.ts.map +0 -1
  210. package/dist/playground/stories/PlaygroundPhase5.stories.js +0 -512
  211. package/dist/playground/stories/PlaygroundPhase5.stories.js.map +0 -1
  212. package/dist/playground/stories/PlaygroundProperties.stories.d.ts +0 -13
  213. package/dist/playground/stories/PlaygroundProperties.stories.d.ts.map +0 -1
  214. package/dist/playground/stories/PlaygroundProperties.stories.js +0 -342
  215. package/dist/playground/stories/PlaygroundProperties.stories.js.map +0 -1
  216. package/dist/playground/types/index.d.ts +0 -251
  217. package/dist/playground/types/index.d.ts.map +0 -1
  218. package/dist/playground/types/index.js +0 -5
  219. package/dist/playground/types/index.js.map +0 -1
  220. package/dist/scripts/verify-framework-adapters.js +0 -105
  221. package/dist/story-generator/componentBlacklist.js.map +0 -1
  222. package/dist/story-generator/componentDiscovery.js.map +0 -1
  223. package/dist/story-generator/configLoader.js.map +0 -1
  224. package/dist/story-generator/considerationsLoader.js.map +0 -1
  225. package/dist/story-generator/documentation-sources.js.map +0 -1
  226. package/dist/story-generator/documentationLoader.js.map +0 -1
  227. package/dist/story-generator/dynamicPackageDiscovery.js.map +0 -1
  228. package/dist/story-generator/enhancedComponentDiscovery.js.map +0 -1
  229. package/dist/story-generator/generateStory.js.map +0 -1
  230. package/dist/story-generator/gitignoreManager.js.map +0 -1
  231. package/dist/story-generator/inMemoryStoryService.js.map +0 -1
  232. package/dist/story-generator/logger.js.map +0 -1
  233. package/dist/story-generator/postProcessStory.js.map +0 -1
  234. package/dist/story-generator/productionGitignoreManager.js.map +0 -1
  235. package/dist/story-generator/promptGenerator.js.map +0 -1
  236. package/dist/story-generator/providerPresets.d.ts +0 -54
  237. package/dist/story-generator/providerPresets.d.ts.map +0 -1
  238. package/dist/story-generator/providerPresets.js +0 -214
  239. package/dist/story-generator/storyHistory.js.map +0 -1
  240. package/dist/story-generator/storySync.js.map +0 -1
  241. package/dist/story-generator/storyTracker.js.map +0 -1
  242. package/dist/story-generator/storyValidator.js.map +0 -1
  243. package/dist/story-generator/test_validation.d.ts +0 -2
  244. package/dist/story-generator/test_validation.d.ts.map +0 -1
  245. package/dist/story-generator/test_validation.js +0 -51
  246. package/dist/story-generator/universalDesignSystemAdapter.js.map +0 -1
  247. package/dist/story-generator/urlRedirectService.js.map +0 -1
  248. package/dist/story-generator/validateStory.js.map +0 -1
  249. package/dist/story-ui.config.js.map +0 -1
  250. package/dist/story-ui.config.loader.d.ts +0 -36
  251. package/dist/story-ui.config.loader.d.ts.map +0 -1
  252. package/dist/story-ui.config.loader.js +0 -205
  253. package/dist/story-ui.config.loader.js.map +0 -1
  254. package/dist/temp/package/templates/StoryUI/StoryUIPanel.js +0 -807
  255. package/dist/temp/package/templates/StoryUI/StoryUIPanel.stories.js +0 -37
  256. package/dist/temp/package/templates/StoryUI/index.js +0 -2
  257. package/dist/templates/StoryUI/StoryUIPanel.js.map +0 -1
  258. package/dist/templates/StoryUI/StoryUIPanel.stories.js.map +0 -1
  259. package/dist/templates/StoryUI/index.js.map +0 -1
  260. package/dist/templates/StoryUI/manager.d.ts +0 -14
  261. package/dist/templates/StoryUI/manager.d.ts.map +0 -1
  262. package/dist/templates/production-app/src/App.d.ts +0 -10
  263. package/dist/templates/production-app/src/App.d.ts.map +0 -1
  264. package/dist/templates/production-app/src/App.js +0 -653
  265. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts +0 -24
  266. package/dist/templates/production-app/src/LivePreviewRenderer.d.ts.map +0 -1
  267. package/dist/templates/production-app/src/LivePreviewRenderer.js +0 -199
  268. package/dist/templates/production-app/src/componentRegistry.d.ts +0 -20
  269. package/dist/templates/production-app/src/componentRegistry.d.ts.map +0 -1
  270. package/dist/templates/production-app/src/componentRegistry.js +0 -316
  271. package/dist/templates/production-app/src/main.d.ts +0 -9
  272. package/dist/templates/production-app/src/main.d.ts.map +0 -1
  273. package/dist/templates/production-app/src/main.js +0 -18
  274. package/dist/templates/production-app/vite.config.d.ts +0 -3
  275. package/dist/templates/production-app/vite.config.d.ts.map +0 -1
  276. package/dist/templates/production-app/vite.config.js +0 -71
  277. package/dist/test-storybooks/angular-material-storybook/src/main.js +0 -66
  278. package/dist/test-storybooks/chakra-storybook/vite.config.js +0 -6
  279. package/dist/test-storybooks/mantine-storybook/vite.config.js +0 -93
  280. package/dist/test-storybooks/web-components-shoelace/vite.config.js +0 -9
  281. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,264 +1,495 @@
1
1
  /**
2
2
  * Story UI Storybook Manager Addon
3
3
  *
4
- * This addon integrates with Storybook's sidebar to show generated stories.
5
- * In Edge mode, it fetches stories from the Edge Worker and adds them to the sidebar.
4
+ * This addon adds a "Source Code" panel to Storybook that displays
5
+ * the source code of the currently viewed story with syntax highlighting.
6
+ *
7
+ * Works in both local development and production deployments.
6
8
  */
7
9
 
8
- import React, { useEffect, useState, useCallback } from 'react';
9
- import { addons, types } from '@storybook/manager-api';
10
- import { useStorybookApi, useChannel } from '@storybook/manager-api';
11
- import { IconButton } from '@storybook/components';
12
- import { styled } from '@storybook/theming';
10
+ import { addons, types, useStorybookApi, useStorybookState } from 'storybook/manager-api';
11
+ import React, { useEffect, useState, useCallback, useMemo } from 'react';
13
12
 
14
13
  // Addon identifier
15
14
  const ADDON_ID = 'story-ui';
16
- const PANEL_ID = `${ADDON_ID}/generated-stories`;
17
- const TOOL_ID = `${ADDON_ID}/tool`;
18
-
19
- // Event channels for communication between panel and manager
20
- export const EVENTS = {
21
- STORY_GENERATED: `${ADDON_ID}/story-generated`,
22
- REFRESH_STORIES: `${ADDON_ID}/refresh-stories`,
23
- SELECT_GENERATED_STORY: `${ADDON_ID}/select-generated-story`,
15
+ const PANEL_ID = `${ADDON_ID}/source-code`;
16
+
17
+ // Event channel for receiving generated code from StoryUIPanel
18
+ const EVENTS = {
19
+ CODE_GENERATED: `${ADDON_ID}/code-generated`,
20
+ STORY_SELECTED: `${ADDON_ID}/story-selected`,
24
21
  };
25
22
 
26
- // Types
27
- interface GeneratedStory {
28
- id: string;
29
- title: string;
30
- createdAt: number;
31
- framework?: string;
23
+ // Extend Window to include generated stories cache
24
+ declare global {
25
+ interface Window {
26
+ __STORY_UI_GENERATED_CODE__?: Record<string, string>;
27
+ }
32
28
  }
33
29
 
34
- // Styled components
35
- const SidebarContainer = styled.div`
36
- padding: 10px;
37
- `;
38
-
39
- const SectionTitle = styled.div`
40
- font-size: 11px;
41
- font-weight: 700;
42
- color: ${({ theme }) => theme.color.mediumdark};
43
- text-transform: uppercase;
44
- letter-spacing: 0.35em;
45
- padding: 10px 0;
46
- border-bottom: 1px solid ${({ theme }) => theme.appBorderColor};
47
- margin-bottom: 8px;
48
- display: flex;
49
- justify-content: space-between;
50
- align-items: center;
51
- `;
52
-
53
- const StoryList = styled.ul`
54
- list-style: none;
55
- padding: 0;
56
- margin: 0;
57
- `;
58
-
59
- const StoryItem = styled.li<{ isActive?: boolean }>`
60
- padding: 8px 12px;
61
- cursor: pointer;
62
- border-radius: 4px;
63
- font-size: 13px;
64
- color: ${({ theme, isActive }) => isActive ? theme.color.secondary : theme.color.defaultText};
65
- background: ${({ theme, isActive }) => isActive ? theme.background.hoverable : 'transparent'};
66
-
67
- &:hover {
68
- background: ${({ theme }) => theme.background.hoverable};
30
+ /**
31
+ * Extract clean component usage JSX from a full Storybook story file.
32
+ *
33
+ * Transforms:
34
+ * import { Button } from '@mantine/core';
35
+ * export default { title: 'Generated/Button' };
36
+ * export const Default: Story = { render: () => <Button>Click</Button> };
37
+ *
38
+ * Into:
39
+ * <Button>Click</Button>
40
+ */
41
+ const extractUsageCode = (fullStoryCode: string): string => {
42
+ // Try to extract JSX from render function: render: () => (<JSX>) or render: () => <JSX>
43
+ // Pattern 1: render: () => (\n <Component...>\n)
44
+ const renderWithParensMatch = fullStoryCode.match(/render:\s*\([^)]*\)\s*=>\s*\(\s*([\s\S]*?)\s*\)\s*[,}]/);
45
+ if (renderWithParensMatch) {
46
+ const jsx = renderWithParensMatch[1].trim();
47
+ // Clean up any trailing commas or extra whitespace
48
+ return jsx.replace(/,\s*$/, '').trim();
49
+ }
50
+
51
+ // Pattern 2: render: () => <Component...> (no parentheses, single line)
52
+ const renderNoParensMatch = fullStoryCode.match(/render:\s*\([^)]*\)\s*=>\s*(<[A-Z][^,}]*(?:\/>|<\/[A-Za-z.]+>))/s);
53
+ if (renderNoParensMatch) {
54
+ return renderNoParensMatch[1].trim();
55
+ }
56
+
57
+ // Pattern 3: Arrow function story: () => (<JSX>)
58
+ const arrowWithParensMatch = fullStoryCode.match(/export\s+const\s+\w+\s*=\s*\(\)\s*=>\s*\(\s*([\s\S]*?)\s*\)\s*;/);
59
+ if (arrowWithParensMatch) {
60
+ const jsx = arrowWithParensMatch[1].trim();
61
+ return jsx.replace(/,\s*$/, '').trim();
69
62
  }
70
63
 
71
- display: flex;
72
- align-items: center;
73
- gap: 8px;
74
- `;
75
-
76
- const StoryIcon = styled.span`
77
- font-size: 14px;
78
- `;
79
-
80
- const EmptyState = styled.div`
81
- padding: 20px;
82
- text-align: center;
83
- color: ${({ theme }) => theme.color.mediumdark};
84
- font-size: 12px;
85
- `;
86
-
87
- const RefreshButton = styled.button`
88
- background: none;
89
- border: none;
90
- cursor: pointer;
91
- padding: 4px;
92
- color: ${({ theme }) => theme.color.mediumdark};
93
- font-size: 14px;
94
-
95
- &:hover {
96
- color: ${({ theme }) => theme.color.secondary};
64
+ // Pattern 4: Arrow function story: () => <Component...>
65
+ const arrowNoParensMatch = fullStoryCode.match(/export\s+const\s+\w+\s*=\s*\(\)\s*=>\s*(<[A-Z][^;]*(?:\/>|<\/[A-Za-z.]+>))\s*;/s);
66
+ if (arrowNoParensMatch) {
67
+ return arrowNoParensMatch[1].trim();
97
68
  }
98
- `;
69
+
70
+ // Pattern 5: Look for args-based stories with component prop spreading
71
+ // e.g., args: { children: 'Click me', color: 'blue' }
72
+ const argsMatch = fullStoryCode.match(/args:\s*(\{[\s\S]*?\})\s*[,}]/);
73
+ if (argsMatch) {
74
+ // Try to find the component from the meta
75
+ const componentMatch = fullStoryCode.match(/component:\s*([A-Z][A-Za-z0-9]*)/);
76
+ if (componentMatch) {
77
+ const componentName = componentMatch[1];
78
+ try {
79
+ // Parse the args to generate JSX
80
+ const argsStr = argsMatch[1];
81
+ // Extract children if present
82
+ const childrenMatch = argsStr.match(/children:\s*['"`]([^'"`]+)['"`]/);
83
+ const children = childrenMatch ? childrenMatch[1] : '';
84
+
85
+ // Extract other props (simplified)
86
+ const propsStr = argsStr
87
+ .replace(/children:\s*['"`][^'"`]*['"`],?/, '') // Remove children
88
+ .replace(/^\{|\}$/g, '') // Remove braces
89
+ .trim();
90
+
91
+ if (children) {
92
+ if (propsStr) {
93
+ return `<${componentName} ${propsStr.replace(/,\s*$/, '')}>${children}</${componentName}>`;
94
+ }
95
+ return `<${componentName}>${children}</${componentName}>`;
96
+ } else if (propsStr) {
97
+ return `<${componentName} ${propsStr.replace(/,\s*$/, '')} />`;
98
+ }
99
+ return `<${componentName} />`;
100
+ } catch {
101
+ // Fall through to return full code
102
+ }
103
+ }
104
+ }
105
+
106
+ // Pattern 6: Look for any JSX block starting with < and ending with /> or </Component>
107
+ // This is a fallback for any JSX we can find
108
+ const jsxBlockMatch = fullStoryCode.match(/(<[A-Z][a-zA-Z0-9.]*[\s\S]*?(?:\/>|<\/[A-Za-z.]+>))/);
109
+ if (jsxBlockMatch) {
110
+ // Don't return if it looks like an import or type definition
111
+ const match = jsxBlockMatch[1];
112
+ if (!match.includes('import') && !match.includes('Meta<') && !match.includes('StoryObj<')) {
113
+ return match.trim();
114
+ }
115
+ }
116
+
117
+ // If no patterns matched, return the original code
118
+ // (better than showing nothing)
119
+ return fullStoryCode;
120
+ };
99
121
 
100
122
  /**
101
- * Get the Edge URL from environment variable.
102
- * This must be configured via VITE_STORY_UI_EDGE_URL environment variable.
103
- * No hardcoded URLs - each deployment must configure their own backend.
123
+ * Simple Prism-like syntax highlighting for JSX/TSX
124
+ * Uses inline styles for portability (no external CSS needed)
104
125
  */
105
- function getEdgeUrl(): string {
106
- // Check for Vite env variable - this is the ONLY source for the Edge URL
107
- if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_STORY_UI_EDGE_URL) {
108
- return import.meta.env.VITE_STORY_UI_EDGE_URL;
126
+ const tokenize = (code: string): Array<{ type: string; value: string }> => {
127
+ const tokens: Array<{ type: string; value: string }> = [];
128
+ let remaining = code;
129
+
130
+ const patterns: Array<{ type: string; regex: RegExp }> = [
131
+ // Comments
132
+ { type: 'comment', regex: /^(\/\/[^\n]*|\/\*[\s\S]*?\*\/)/ },
133
+ // Strings (double, single, template)
134
+ { type: 'string', regex: /^("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*'|`[^`\\]*(?:\\.[^`\\]*)*`)/ },
135
+ // JSX tags
136
+ { type: 'tag', regex: /^(<\/?[A-Z][a-zA-Z0-9.]*|<\/?[a-z][a-z0-9-]*)/ },
137
+ // Closing tag bracket
138
+ { type: 'punctuation', regex: /^(\/>|>)/ },
139
+ // Keywords
140
+ { type: 'keyword', regex: /^(const|let|var|function|return|export|default|import|from|if|else|for|while|class|extends|new|this|typeof|instanceof|async|await|try|catch|throw|finally)\b/ },
141
+ // Booleans and null
142
+ { type: 'boolean', regex: /^(true|false|null|undefined)\b/ },
143
+ // Numbers
144
+ { type: 'number', regex: /^-?\d+\.?\d*(e[+-]?\d+)?/ },
145
+ // Props/attributes (word followed by =)
146
+ { type: 'attr-name', regex: /^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?==)/ },
147
+ // Function names
148
+ { type: 'function', regex: /^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?=\()/ },
149
+ // Identifiers
150
+ { type: 'plain', regex: /^[a-zA-Z_$][a-zA-Z0-9_$]*/ },
151
+ // Operators
152
+ { type: 'operator', regex: /^(=>|===|!==|==|!=|<=|>=|&&|\|\||[+\-*/%=<>!&|^~?:])/ },
153
+ // Punctuation
154
+ { type: 'punctuation', regex: /^[{}[\]();,.]/ },
155
+ // Whitespace
156
+ { type: 'whitespace', regex: /^\s+/ },
157
+ ];
158
+
159
+ while (remaining.length > 0) {
160
+ let matched = false;
161
+
162
+ for (const { type, regex } of patterns) {
163
+ const match = remaining.match(regex);
164
+ if (match) {
165
+ tokens.push({ type, value: match[0] });
166
+ remaining = remaining.slice(match[0].length);
167
+ matched = true;
168
+ break;
169
+ }
170
+ }
171
+
172
+ if (!matched) {
173
+ // Unknown character, add as plain
174
+ tokens.push({ type: 'plain', value: remaining[0] });
175
+ remaining = remaining.slice(1);
176
+ }
109
177
  }
110
178
 
111
- // No fallback - environment variable must be configured
112
- return '';
113
- }
179
+ return tokens;
180
+ };
114
181
 
115
182
  /**
116
- * Check if we're in Edge mode
183
+ * Color scheme for syntax highlighting (VS Code-like dark theme)
117
184
  */
118
- function isEdgeMode(): boolean {
119
- const edgeUrl = getEdgeUrl();
120
- if (edgeUrl) return true;
121
-
122
- // Check if we're on a production domain
123
- if (typeof window !== 'undefined') {
124
- const hostname = window.location.hostname;
125
- return hostname !== 'localhost' && hostname !== '127.0.0.1';
126
- }
185
+ const tokenColors: Record<string, React.CSSProperties> = {
186
+ comment: { color: '#6A9955', fontStyle: 'italic' },
187
+ string: { color: '#CE9178' },
188
+ tag: { color: '#569CD6' },
189
+ keyword: { color: '#C586C0' },
190
+ boolean: { color: '#569CD6' },
191
+ number: { color: '#B5CEA8' },
192
+ 'attr-name': { color: '#9CDCFE' },
193
+ function: { color: '#DCDCAA' },
194
+ operator: { color: '#D4D4D4' },
195
+ punctuation: { color: '#D4D4D4' },
196
+ plain: { color: '#D4D4D4' },
197
+ whitespace: {},
198
+ };
127
199
 
128
- return false;
129
- }
200
+ /**
201
+ * Syntax Highlighter Component
202
+ */
203
+ const SyntaxHighlighter: React.FC<{ code: string }> = ({ code }) => {
204
+ const tokens = useMemo(() => tokenize(code), [code]);
205
+
206
+ return (
207
+ <pre
208
+ style={{
209
+ margin: 0,
210
+ padding: '16px',
211
+ background: '#1E1E1E',
212
+ borderRadius: '4px',
213
+ overflow: 'auto',
214
+ fontSize: '13px',
215
+ lineHeight: '1.5',
216
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
217
+ }}
218
+ >
219
+ <code>
220
+ {tokens.map((token, index) => (
221
+ <span key={index} style={tokenColors[token.type] || {}}>
222
+ {token.value}
223
+ </span>
224
+ ))}
225
+ </code>
226
+ </pre>
227
+ );
228
+ };
130
229
 
131
230
  /**
132
- * Generated Stories Sidebar Component
231
+ * Inline styles for the panel
133
232
  */
134
- const GeneratedStoriesSidebar: React.FC = () => {
135
- const [stories, setStories] = useState<GeneratedStory[]>([]);
136
- const [loading, setLoading] = useState(false);
137
- const [activeStoryId, setActiveStoryId] = useState<string | null>(null);
138
-
139
- // Listen for story generation events from the panel
140
- useChannel({
141
- [EVENTS.STORY_GENERATED]: (data: GeneratedStory) => {
142
- setStories(prev => [data, ...prev.filter(s => s.id !== data.id)]);
143
- },
144
- [EVENTS.REFRESH_STORIES]: () => {
145
- fetchStories();
146
- },
147
- });
233
+ const styles = {
234
+ container: {
235
+ height: '100%',
236
+ display: 'flex',
237
+ flexDirection: 'column' as const,
238
+ background: '#1E1E1E',
239
+ color: '#D4D4D4',
240
+ },
241
+ header: {
242
+ display: 'flex',
243
+ justifyContent: 'space-between',
244
+ alignItems: 'center',
245
+ padding: '8px 12px',
246
+ borderBottom: '1px solid #3C3C3C',
247
+ background: '#252526',
248
+ },
249
+ title: {
250
+ fontSize: '12px',
251
+ fontWeight: 600,
252
+ color: '#CCCCCC',
253
+ textTransform: 'uppercase' as const,
254
+ letterSpacing: '0.5px',
255
+ },
256
+ copyButton: {
257
+ background: '#0E639C',
258
+ color: 'white',
259
+ border: 'none',
260
+ borderRadius: '4px',
261
+ padding: '4px 10px',
262
+ fontSize: '11px',
263
+ cursor: 'pointer',
264
+ fontWeight: 500,
265
+ },
266
+ codeContainer: {
267
+ flex: 1,
268
+ overflow: 'auto',
269
+ padding: '0',
270
+ },
271
+ emptyState: {
272
+ display: 'flex',
273
+ flexDirection: 'column' as const,
274
+ alignItems: 'center',
275
+ justifyContent: 'center',
276
+ height: '100%',
277
+ color: '#888',
278
+ fontSize: '13px',
279
+ textAlign: 'center' as const,
280
+ padding: '20px',
281
+ },
282
+ storyInfo: {
283
+ fontSize: '11px',
284
+ color: '#888',
285
+ marginTop: '4px',
286
+ },
287
+ };
288
+
289
+ /**
290
+ * Source Code Panel Component
291
+ */
292
+ const SourceCodePanel: React.FC<{ active?: boolean }> = ({ active }) => {
293
+ const api = useStorybookApi();
294
+ const state = useStorybookState();
295
+ const [sourceCode, setSourceCode] = useState<string>('');
296
+ const [storyTitle, setStoryTitle] = useState<string>('');
297
+ const [copied, setCopied] = useState(false);
298
+ const [showFullCode, setShowFullCode] = useState(false);
299
+
300
+ // Memoize the usage code extraction
301
+ const displayCode = useMemo(() => {
302
+ if (!sourceCode) return '';
303
+ return showFullCode ? sourceCode : extractUsageCode(sourceCode);
304
+ }, [sourceCode, showFullCode]);
305
+
306
+ // Get the current story ID
307
+ const currentStoryId = state?.storyId;
308
+
309
+ // Try to get source code from the story
310
+ useEffect(() => {
311
+ if (!currentStoryId || !active) return;
312
+
313
+ // Get story data from the API
314
+ const story = api.getData(currentStoryId);
315
+
316
+ // Check if this is a generated story based on ID (works even if story doesn't exist in Storybook yet)
317
+ const isGeneratedStory = currentStoryId.includes('generated');
318
+
319
+ if (story) {
320
+ setStoryTitle(story.title || '');
148
321
 
149
- const fetchStories = useCallback(async () => {
150
- if (!isEdgeMode()) return;
322
+ // Try to get source from story parameters
323
+ const storySource = (story as any)?.parameters?.docs?.source?.code ||
324
+ (story as any)?.parameters?.storySource?.source ||
325
+ (story as any)?.parameters?.source?.code;
151
326
 
152
- setLoading(true);
153
- try {
154
- const edgeUrl = getEdgeUrl();
155
- const response = await fetch(`${edgeUrl}/story-ui/stories`);
156
- if (response.ok) {
157
- const data = await response.json();
158
- setStories(Array.isArray(data) ? data : []);
327
+ if (storySource) {
328
+ setSourceCode(storySource);
329
+ return;
159
330
  }
160
- } catch (error) {
161
- console.error('Failed to fetch generated stories:', error);
162
- } finally {
163
- setLoading(false);
331
+ } else {
332
+ // Story doesn't exist in Storybook yet, set title from story ID
333
+ setStoryTitle(currentStoryId);
164
334
  }
165
- }, []);
166
335
 
167
- useEffect(() => {
168
- fetchStories();
169
- }, [fetchStories]);
336
+ // For generated stories (whether or not they exist in Storybook), try to get from cache/localStorage
337
+ if (isGeneratedStory) {
338
+ // Try to get from window cache first
339
+ const topWindow = window.top || window;
340
+ let cachedCode = topWindow.__STORY_UI_GENERATED_CODE__?.[currentStoryId] ||
341
+ window.__STORY_UI_GENERATED_CODE__?.[currentStoryId];
342
+
343
+ // If not in memory cache, check localStorage (survives page navigation)
344
+ if (!cachedCode) {
345
+ try {
346
+ const stored = JSON.parse(localStorage.getItem('storyui_generated_code') || '{}');
347
+ cachedCode = stored[currentStoryId];
348
+ // Restore to memory cache if found
349
+ if (cachedCode) {
350
+ if (!topWindow.__STORY_UI_GENERATED_CODE__) {
351
+ topWindow.__STORY_UI_GENERATED_CODE__ = {};
352
+ }
353
+ topWindow.__STORY_UI_GENERATED_CODE__[currentStoryId] = cachedCode;
354
+ }
355
+ } catch (e) {
356
+ console.warn('[Story UI] Failed to read from localStorage:', e);
357
+ }
358
+ }
170
359
 
171
- const handleStoryClick = useCallback((story: GeneratedStory) => {
172
- setActiveStoryId(story.id);
360
+ if (cachedCode) {
361
+ setSourceCode(cachedCode);
362
+ } else {
363
+ setSourceCode('');
364
+ }
365
+ } else {
366
+ setSourceCode('');
367
+ }
368
+ }, [currentStoryId, active, api]);
173
369
 
174
- // Emit event for the Story UI panel to display the story
370
+ // Listen for code generated events from StoryUIPanel
371
+ useEffect(() => {
175
372
  const channel = addons.getChannel();
176
- channel.emit(EVENTS.SELECT_GENERATED_STORY, story);
177
- }, []);
373
+ const topWindow = window.top || window;
374
+
375
+ const handleCodeGenerated = (data: { storyId: string; code: string }) => {
376
+ // Store in window cache (both local and top window)
377
+ if (!window.__STORY_UI_GENERATED_CODE__) {
378
+ window.__STORY_UI_GENERATED_CODE__ = {};
379
+ }
380
+ window.__STORY_UI_GENERATED_CODE__[data.storyId] = data.code;
381
+
382
+ if (topWindow !== window) {
383
+ if (!topWindow.__STORY_UI_GENERATED_CODE__) {
384
+ topWindow.__STORY_UI_GENERATED_CODE__ = {};
385
+ }
386
+ topWindow.__STORY_UI_GENERATED_CODE__[data.storyId] = data.code;
387
+ }
388
+
389
+ // If this is the current story, update the display
390
+ if (data.storyId === currentStoryId) {
391
+ setSourceCode(data.code);
392
+ }
393
+ };
394
+
395
+ channel.on(EVENTS.CODE_GENERATED, handleCodeGenerated);
396
+
397
+ return () => {
398
+ channel.off(EVENTS.CODE_GENERATED, handleCodeGenerated);
399
+ };
400
+ }, [currentStoryId]);
401
+
402
+ const handleCopy = useCallback(() => {
403
+ if (displayCode) {
404
+ navigator.clipboard.writeText(displayCode).then(() => {
405
+ setCopied(true);
406
+ setTimeout(() => setCopied(false), 2000);
407
+ });
408
+ }
409
+ }, [displayCode]);
178
410
 
179
- if (!isEdgeMode()) {
411
+ if (!active) return null;
412
+
413
+ // No story selected
414
+ if (!currentStoryId) {
180
415
  return (
181
- <SidebarContainer>
182
- <EmptyState>
183
- Generated stories appear here in Edge mode
184
- </EmptyState>
185
- </SidebarContainer>
416
+ <div style={styles.container}>
417
+ <div style={styles.emptyState}>
418
+ <span>Select a story to view its source code</span>
419
+ </div>
420
+ </div>
186
421
  );
187
422
  }
188
423
 
189
- return (
190
- <SidebarContainer>
191
- <SectionTitle>
192
- Generated Stories
193
- <RefreshButton onClick={fetchStories} title="Refresh stories">
194
- {loading ? '...' : '\u21bb'}
195
- </RefreshButton>
196
- </SectionTitle>
197
-
198
- {stories.length === 0 ? (
199
- <EmptyState>
200
- {loading ? 'Loading...' : 'No generated stories yet'}
201
- </EmptyState>
202
- ) : (
203
- <StoryList>
204
- {stories.map((story) => (
205
- <StoryItem
206
- key={story.id}
207
- isActive={activeStoryId === story.id}
208
- onClick={() => handleStoryClick(story)}
209
- >
210
- <StoryIcon>&#128214;</StoryIcon>
211
- {story.title}
212
- </StoryItem>
213
- ))}
214
- </StoryList>
215
- )}
216
- </SidebarContainer>
217
- );
218
- };
219
-
220
- /**
221
- * Toolbar button to toggle generated stories panel
222
- */
223
- const GeneratedStoriesToolbar: React.FC = () => {
224
- const api = useStorybookApi();
424
+ // No source code available
425
+ if (!sourceCode) {
426
+ return (
427
+ <div style={styles.container}>
428
+ <div style={styles.header}>
429
+ <span style={styles.title}>Source Code</span>
430
+ </div>
431
+ <div style={styles.emptyState}>
432
+ <span>No source code available for this story</span>
433
+ <span style={styles.storyInfo}>
434
+ {storyTitle || currentStoryId}
435
+ </span>
436
+ <span style={{ ...styles.storyInfo, marginTop: '12px', maxWidth: '280px' }}>
437
+ Generate a story using the Story UI panel to see the code here.
438
+ </span>
439
+ </div>
440
+ </div>
441
+ );
442
+ }
225
443
 
226
- if (!isEdgeMode()) return null;
444
+ // Check if extraction was successful (displayCode is different from sourceCode)
445
+ const hasUsageCode = displayCode !== sourceCode;
227
446
 
228
447
  return (
229
- <IconButton
230
- key={TOOL_ID}
231
- title="Generated Stories"
232
- onClick={() => {
233
- api.togglePanel(true);
234
- api.setSelectedPanel(PANEL_ID);
235
- }}
236
- >
237
- <span style={{ fontSize: '14px' }}>&#10024;</span>
238
- </IconButton>
448
+ <div style={styles.container}>
449
+ <div style={styles.header}>
450
+ <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
451
+ <span style={styles.title}>{showFullCode ? 'Full Story' : 'Usage Code'}</span>
452
+ {hasUsageCode && (
453
+ <button
454
+ style={{
455
+ background: 'transparent',
456
+ color: '#888',
457
+ border: '1px solid #555',
458
+ borderRadius: '4px',
459
+ padding: '2px 8px',
460
+ fontSize: '10px',
461
+ cursor: 'pointer',
462
+ fontWeight: 400,
463
+ }}
464
+ onClick={() => setShowFullCode(!showFullCode)}
465
+ >
466
+ {showFullCode ? 'Show Usage' : 'Show Full'}
467
+ </button>
468
+ )}
469
+ </div>
470
+ <button
471
+ style={{
472
+ ...styles.copyButton,
473
+ background: copied ? '#16825D' : '#0E639C',
474
+ }}
475
+ onClick={handleCopy}
476
+ >
477
+ {copied ? 'Copied!' : 'Copy'}
478
+ </button>
479
+ </div>
480
+ <div style={styles.codeContainer}>
481
+ <SyntaxHighlighter code={displayCode} />
482
+ </div>
483
+ </div>
239
484
  );
240
485
  };
241
486
 
242
- // Register the addon
243
- addons.register(ADDON_ID, (api) => {
244
- // Only register in Edge mode
245
- if (!isEdgeMode()) return;
246
-
247
- // Register the toolbar button
248
- addons.add(TOOL_ID, {
249
- type: types.TOOL,
250
- title: 'Generated Stories',
251
- match: ({ viewMode }) => viewMode === 'story' || viewMode === 'docs',
252
- render: () => <GeneratedStoriesToolbar />,
253
- });
254
-
255
- // Register the sidebar panel
487
+ // Register the addon - always register, not just in Edge mode
488
+ addons.register(ADDON_ID, () => {
256
489
  addons.add(PANEL_ID, {
257
490
  type: types.PANEL,
258
- title: 'Generated',
491
+ title: 'Source Code',
259
492
  match: ({ viewMode }) => viewMode === 'story' || viewMode === 'docs',
260
- render: ({ active }) => active ? <GeneratedStoriesSidebar /> : null,
493
+ render: ({ active }) => <SourceCodePanel active={active} />,
261
494
  });
262
495
  });
263
-
264
- export default {};