@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.
- package/README.md +25 -72
- package/dist/cli/deploy.d.ts +0 -7
- package/dist/cli/deploy.d.ts.map +1 -1
- package/dist/cli/deploy.js +10 -421
- package/dist/cli/index.js +0 -0
- package/dist/mcp-server/index.js +7 -8
- package/dist/mcp-server/mcp-stdio-server.js +1 -2
- package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStory.js +3 -3
- package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStoryStream.js +3 -3
- package/dist/mcp-server/routes/hybridStories.d.ts +6 -6
- package/dist/mcp-server/routes/hybridStories.d.ts.map +1 -1
- package/dist/mcp-server/routes/hybridStories.js +29 -27
- package/dist/mcp-server/routes/memoryStories.d.ts +7 -7
- package/dist/mcp-server/routes/memoryStories.d.ts.map +1 -1
- package/dist/mcp-server/routes/memoryStories.js +37 -26
- package/dist/story-generator/postgresStoryService.d.ts +56 -0
- package/dist/story-generator/postgresStoryService.d.ts.map +1 -0
- package/dist/story-generator/postgresStoryService.js +240 -0
- package/dist/story-generator/storyServiceFactory.d.ts +22 -0
- package/dist/story-generator/storyServiceFactory.d.ts.map +1 -0
- package/dist/story-generator/storyServiceFactory.js +97 -0
- package/dist/story-generator/storyServiceInterface.d.ts +85 -0
- package/dist/story-generator/storyServiceInterface.d.ts.map +1 -0
- package/dist/story-generator/storyServiceInterface.js +5 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts +5 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
- package/dist/templates/StoryUI/StoryUIPanel.js +18 -3
- package/package.json +6 -6
- package/templates/StoryUI/StoryUIPanel.tsx +28 -3
- package/templates/StoryUI/manager.tsx +444 -213
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/setup.js.map +0 -1
- package/dist/cloudflare-edge/src/mcp-session.js +0 -462
- package/dist/cloudflare-edge/src/types.js +0 -4
- package/dist/cloudflare-edge/src/worker.js +0 -106
- package/dist/cloudflare-pages/vite.config.js +0 -14
- package/dist/index.d.ts +0 -13
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/mcp-server/index.js.map +0 -1
- package/dist/mcp-server/mcp-stdio-server.js.map +0 -1
- package/dist/mcp-server/routes/claude.js.map +0 -1
- package/dist/mcp-server/routes/components.js.map +0 -1
- package/dist/mcp-server/routes/generateStory.js.map +0 -1
- package/dist/mcp-server/routes/hybridStories.js.map +0 -1
- package/dist/mcp-server/routes/memoryStories.js.map +0 -1
- package/dist/mcp-server/routes/storySync.js.map +0 -1
- package/dist/mcp-server/routes/updateStory.js +0 -246
- package/dist/mcp-server/sessionManager.js.map +0 -1
- package/dist/playground/components/AIAssistant/AIAssistant.d.ts +0 -6
- package/dist/playground/components/AIAssistant/AIAssistant.d.ts.map +0 -1
- package/dist/playground/components/AIAssistant/AIAssistant.js +0 -109
- package/dist/playground/components/AIAssistant/AIAssistant.js.map +0 -1
- package/dist/playground/components/AIAssistant/AIAssistant.module.css +0 -166
- package/dist/playground/components/Canvas/Canvas.d.ts +0 -9
- package/dist/playground/components/Canvas/Canvas.d.ts.map +0 -1
- package/dist/playground/components/Canvas/Canvas.js +0 -58
- package/dist/playground/components/Canvas/Canvas.js.map +0 -1
- package/dist/playground/components/Canvas/Canvas.module.css +0 -189
- package/dist/playground/components/Canvas/CanvasWithDnd.d.ts +0 -9
- package/dist/playground/components/Canvas/CanvasWithDnd.d.ts.map +0 -1
- package/dist/playground/components/Canvas/CanvasWithDnd.js +0 -158
- package/dist/playground/components/Canvas/CanvasWithDnd.js.map +0 -1
- package/dist/playground/components/Canvas/ComponentRenderer.d.ts +0 -15
- package/dist/playground/components/Canvas/ComponentRenderer.d.ts.map +0 -1
- package/dist/playground/components/Canvas/ComponentRenderer.js +0 -177
- package/dist/playground/components/Canvas/ComponentRenderer.js.map +0 -1
- package/dist/playground/components/Canvas/DraggableComponent.d.ts +0 -15
- package/dist/playground/components/Canvas/DraggableComponent.d.ts.map +0 -1
- package/dist/playground/components/Canvas/DraggableComponent.js +0 -49
- package/dist/playground/components/Canvas/DraggableComponent.js.map +0 -1
- package/dist/playground/components/Canvas/index.d.ts +0 -9
- package/dist/playground/components/Canvas/index.d.ts.map +0 -1
- package/dist/playground/components/Canvas/index.js +0 -5
- package/dist/playground/components/Canvas/index.js.map +0 -1
- package/dist/playground/components/CodeView/CodeView.d.ts +0 -12
- package/dist/playground/components/CodeView/CodeView.d.ts.map +0 -1
- package/dist/playground/components/CodeView/CodeView.js +0 -77
- package/dist/playground/components/CodeView/CodeView.js.map +0 -1
- package/dist/playground/components/CodeView/CodeView.module.css +0 -178
- package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts +0 -17
- package/dist/playground/components/ComponentPalette/ComponentPalette.d.ts.map +0 -1
- package/dist/playground/components/ComponentPalette/ComponentPalette.js +0 -138
- package/dist/playground/components/ComponentPalette/ComponentPalette.js.map +0 -1
- package/dist/playground/components/ComponentPalette/ComponentPalette.module.css +0 -217
- package/dist/playground/components/ComponentPalette/index.d.ts +0 -3
- package/dist/playground/components/ComponentPalette/index.d.ts.map +0 -1
- package/dist/playground/components/ComponentPalette/index.js +0 -2
- package/dist/playground/components/ComponentPalette/index.js.map +0 -1
- package/dist/playground/components/DropZone/DropZone.d.ts +0 -17
- package/dist/playground/components/DropZone/DropZone.d.ts.map +0 -1
- package/dist/playground/components/DropZone/DropZone.js +0 -73
- package/dist/playground/components/DropZone/DropZone.js.map +0 -1
- package/dist/playground/components/DropZone/DropZone.module.css +0 -86
- package/dist/playground/components/ExportDialog/ExportDialog.d.ts +0 -10
- package/dist/playground/components/ExportDialog/ExportDialog.d.ts.map +0 -1
- package/dist/playground/components/ExportDialog/ExportDialog.js +0 -57
- package/dist/playground/components/ExportDialog/ExportDialog.js.map +0 -1
- package/dist/playground/components/ExportDialog/ExportDialog.module.css +0 -328
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts +0 -134
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.d.ts.map +0 -1
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.js +0 -254
- package/dist/playground/components/LayoutHelpers/LayoutHelpers.js.map +0 -1
- package/dist/playground/components/LayoutHelpers/index.d.ts +0 -3
- package/dist/playground/components/LayoutHelpers/index.d.ts.map +0 -1
- package/dist/playground/components/LayoutHelpers/index.js +0 -2
- package/dist/playground/components/LayoutHelpers/index.js.map +0 -1
- package/dist/playground/components/Playground/Playground.d.ts +0 -10
- package/dist/playground/components/Playground/Playground.d.ts.map +0 -1
- package/dist/playground/components/Playground/Playground.js +0 -128
- package/dist/playground/components/Playground/Playground.js.map +0 -1
- package/dist/playground/components/Playground/Playground.module.css +0 -308
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts +0 -10
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.d.ts.map +0 -1
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.js +0 -150
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.js.map +0 -1
- package/dist/playground/components/PropertiesPanel/PropertiesPanel.module.css +0 -155
- package/dist/playground/components/PropertiesPanel/index.d.ts +0 -3
- package/dist/playground/components/PropertiesPanel/index.d.ts.map +0 -1
- package/dist/playground/components/PropertiesPanel/index.js +0 -2
- package/dist/playground/components/PropertiesPanel/index.js.map +0 -1
- package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts +0 -12
- package/dist/playground/components/PropertyEditors/BooleanEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/BooleanEditor.js +0 -14
- package/dist/playground/components/PropertyEditors/BooleanEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/ColorEditor.d.ts +0 -12
- package/dist/playground/components/PropertyEditors/ColorEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/ColorEditor.js +0 -62
- package/dist/playground/components/PropertyEditors/ColorEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/IconEditor.d.ts +0 -12
- package/dist/playground/components/PropertyEditors/IconEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/IconEditor.js +0 -123
- package/dist/playground/components/PropertyEditors/IconEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/NumberEditor.d.ts +0 -15
- package/dist/playground/components/PropertyEditors/NumberEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/NumberEditor.js +0 -46
- package/dist/playground/components/PropertyEditors/NumberEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/PropertyEditors.module.css +0 -432
- package/dist/playground/components/PropertyEditors/SelectEditor.d.ts +0 -19
- package/dist/playground/components/PropertyEditors/SelectEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/SelectEditor.js +0 -17
- package/dist/playground/components/PropertyEditors/SelectEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts +0 -19
- package/dist/playground/components/PropertyEditors/SpacingEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/SpacingEditor.js +0 -162
- package/dist/playground/components/PropertyEditors/SpacingEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/SpacingEditor.module.css +0 -214
- package/dist/playground/components/PropertyEditors/TextEditor.d.ts +0 -14
- package/dist/playground/components/PropertyEditors/TextEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/TextEditor.js +0 -38
- package/dist/playground/components/PropertyEditors/TextEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/TokenEditor.d.ts +0 -23
- package/dist/playground/components/PropertyEditors/TokenEditor.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/TokenEditor.js +0 -50
- package/dist/playground/components/PropertyEditors/TokenEditor.js.map +0 -1
- package/dist/playground/components/PropertyEditors/index.d.ts +0 -20
- package/dist/playground/components/PropertyEditors/index.d.ts.map +0 -1
- package/dist/playground/components/PropertyEditors/index.js +0 -12
- package/dist/playground/components/PropertyEditors/index.js.map +0 -1
- package/dist/playground/components/TreeView/TreeView.d.ts +0 -10
- package/dist/playground/components/TreeView/TreeView.d.ts.map +0 -1
- package/dist/playground/components/TreeView/TreeView.js +0 -146
- package/dist/playground/components/TreeView/TreeView.js.map +0 -1
- package/dist/playground/components/TreeView/TreeView.module.css +0 -214
- package/dist/playground/components/TreeView/index.d.ts +0 -3
- package/dist/playground/components/TreeView/index.d.ts.map +0 -1
- package/dist/playground/components/TreeView/index.js +0 -2
- package/dist/playground/components/TreeView/index.js.map +0 -1
- package/dist/playground/config/propertyDefinitions.d.ts +0 -73
- package/dist/playground/config/propertyDefinitions.d.ts.map +0 -1
- package/dist/playground/config/propertyDefinitions.js +0 -809
- package/dist/playground/config/propertyDefinitions.js.map +0 -1
- package/dist/playground/hooks/useKeyboardShortcuts.d.ts +0 -38
- package/dist/playground/hooks/useKeyboardShortcuts.d.ts.map +0 -1
- package/dist/playground/hooks/useKeyboardShortcuts.js +0 -191
- package/dist/playground/hooks/useKeyboardShortcuts.js.map +0 -1
- package/dist/playground/index.d.ts +0 -21
- package/dist/playground/index.d.ts.map +0 -1
- package/dist/playground/index.js +0 -23
- package/dist/playground/index.js.map +0 -1
- package/dist/playground/services/CodeGenerator.d.ts +0 -73
- package/dist/playground/services/CodeGenerator.d.ts.map +0 -1
- package/dist/playground/services/CodeGenerator.js +0 -359
- package/dist/playground/services/CodeGenerator.js.map +0 -1
- package/dist/playground/services/DragDropManager.d.ts +0 -95
- package/dist/playground/services/DragDropManager.d.ts.map +0 -1
- package/dist/playground/services/DragDropManager.js +0 -408
- package/dist/playground/services/DragDropManager.js.map +0 -1
- package/dist/playground/services/StoryParser.d.ts +0 -73
- package/dist/playground/services/StoryParser.d.ts.map +0 -1
- package/dist/playground/services/StoryParser.js +0 -419
- package/dist/playground/services/StoryParser.js.map +0 -1
- package/dist/playground/store/playgroundStore.d.ts +0 -86
- package/dist/playground/store/playgroundStore.d.ts.map +0 -1
- package/dist/playground/store/playgroundStore.js +0 -337
- package/dist/playground/store/playgroundStore.js.map +0 -1
- package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts +0 -13
- package/dist/playground/stories/PlaygroundDragDrop.stories.d.ts.map +0 -1
- package/dist/playground/stories/PlaygroundDragDrop.stories.js +0 -227
- package/dist/playground/stories/PlaygroundDragDrop.stories.js.map +0 -1
- package/dist/playground/stories/PlaygroundPhase4.stories.d.ts +0 -13
- package/dist/playground/stories/PlaygroundPhase4.stories.d.ts.map +0 -1
- package/dist/playground/stories/PlaygroundPhase4.stories.js +0 -334
- package/dist/playground/stories/PlaygroundPhase4.stories.js.map +0 -1
- package/dist/playground/stories/PlaygroundPhase5.stories.d.ts +0 -14
- package/dist/playground/stories/PlaygroundPhase5.stories.d.ts.map +0 -1
- package/dist/playground/stories/PlaygroundPhase5.stories.js +0 -512
- package/dist/playground/stories/PlaygroundPhase5.stories.js.map +0 -1
- package/dist/playground/stories/PlaygroundProperties.stories.d.ts +0 -13
- package/dist/playground/stories/PlaygroundProperties.stories.d.ts.map +0 -1
- package/dist/playground/stories/PlaygroundProperties.stories.js +0 -342
- package/dist/playground/stories/PlaygroundProperties.stories.js.map +0 -1
- package/dist/playground/types/index.d.ts +0 -251
- package/dist/playground/types/index.d.ts.map +0 -1
- package/dist/playground/types/index.js +0 -5
- package/dist/playground/types/index.js.map +0 -1
- package/dist/scripts/verify-framework-adapters.js +0 -105
- package/dist/story-generator/componentBlacklist.js.map +0 -1
- package/dist/story-generator/componentDiscovery.js.map +0 -1
- package/dist/story-generator/configLoader.js.map +0 -1
- package/dist/story-generator/considerationsLoader.js.map +0 -1
- package/dist/story-generator/documentation-sources.js.map +0 -1
- package/dist/story-generator/documentationLoader.js.map +0 -1
- package/dist/story-generator/dynamicPackageDiscovery.js.map +0 -1
- package/dist/story-generator/enhancedComponentDiscovery.js.map +0 -1
- package/dist/story-generator/generateStory.js.map +0 -1
- package/dist/story-generator/gitignoreManager.js.map +0 -1
- package/dist/story-generator/inMemoryStoryService.js.map +0 -1
- package/dist/story-generator/logger.js.map +0 -1
- package/dist/story-generator/postProcessStory.js.map +0 -1
- package/dist/story-generator/productionGitignoreManager.js.map +0 -1
- package/dist/story-generator/promptGenerator.js.map +0 -1
- package/dist/story-generator/providerPresets.d.ts +0 -54
- package/dist/story-generator/providerPresets.d.ts.map +0 -1
- package/dist/story-generator/providerPresets.js +0 -214
- package/dist/story-generator/storyHistory.js.map +0 -1
- package/dist/story-generator/storySync.js.map +0 -1
- package/dist/story-generator/storyTracker.js.map +0 -1
- package/dist/story-generator/storyValidator.js.map +0 -1
- package/dist/story-generator/test_validation.d.ts +0 -2
- package/dist/story-generator/test_validation.d.ts.map +0 -1
- package/dist/story-generator/test_validation.js +0 -51
- package/dist/story-generator/universalDesignSystemAdapter.js.map +0 -1
- package/dist/story-generator/urlRedirectService.js.map +0 -1
- package/dist/story-generator/validateStory.js.map +0 -1
- package/dist/story-ui.config.js.map +0 -1
- package/dist/story-ui.config.loader.d.ts +0 -36
- package/dist/story-ui.config.loader.d.ts.map +0 -1
- package/dist/story-ui.config.loader.js +0 -205
- package/dist/story-ui.config.loader.js.map +0 -1
- package/dist/temp/package/templates/StoryUI/StoryUIPanel.js +0 -807
- package/dist/temp/package/templates/StoryUI/StoryUIPanel.stories.js +0 -37
- package/dist/temp/package/templates/StoryUI/index.js +0 -2
- package/dist/templates/StoryUI/StoryUIPanel.js.map +0 -1
- package/dist/templates/StoryUI/StoryUIPanel.stories.js.map +0 -1
- package/dist/templates/StoryUI/index.js.map +0 -1
- package/dist/templates/StoryUI/manager.d.ts +0 -14
- package/dist/templates/StoryUI/manager.d.ts.map +0 -1
- package/dist/templates/production-app/src/App.d.ts +0 -10
- package/dist/templates/production-app/src/App.d.ts.map +0 -1
- package/dist/templates/production-app/src/App.js +0 -653
- package/dist/templates/production-app/src/LivePreviewRenderer.d.ts +0 -24
- package/dist/templates/production-app/src/LivePreviewRenderer.d.ts.map +0 -1
- package/dist/templates/production-app/src/LivePreviewRenderer.js +0 -199
- package/dist/templates/production-app/src/componentRegistry.d.ts +0 -20
- package/dist/templates/production-app/src/componentRegistry.d.ts.map +0 -1
- package/dist/templates/production-app/src/componentRegistry.js +0 -316
- package/dist/templates/production-app/src/main.d.ts +0 -9
- package/dist/templates/production-app/src/main.d.ts.map +0 -1
- package/dist/templates/production-app/src/main.js +0 -18
- package/dist/templates/production-app/vite.config.d.ts +0 -3
- package/dist/templates/production-app/vite.config.d.ts.map +0 -1
- package/dist/templates/production-app/vite.config.js +0 -71
- package/dist/test-storybooks/angular-material-storybook/src/main.js +0 -66
- package/dist/test-storybooks/chakra-storybook/vite.config.js +0 -6
- package/dist/test-storybooks/mantine-storybook/vite.config.js +0 -93
- package/dist/test-storybooks/web-components-shoelace/vite.config.js +0 -9
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,264 +1,495 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Story UI Storybook Manager Addon
|
|
3
3
|
*
|
|
4
|
-
* This addon
|
|
5
|
-
*
|
|
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
|
|
9
|
-
import {
|
|
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}/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
*
|
|
102
|
-
*
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
179
|
+
return tokens;
|
|
180
|
+
};
|
|
114
181
|
|
|
115
182
|
/**
|
|
116
|
-
*
|
|
183
|
+
* Color scheme for syntax highlighting (VS Code-like dark theme)
|
|
117
184
|
*/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
231
|
+
* Inline styles for the panel
|
|
133
232
|
*/
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
150
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
172
|
-
|
|
360
|
+
if (cachedCode) {
|
|
361
|
+
setSourceCode(cachedCode);
|
|
362
|
+
} else {
|
|
363
|
+
setSourceCode('');
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
setSourceCode('');
|
|
367
|
+
}
|
|
368
|
+
}, [currentStoryId, active, api]);
|
|
173
369
|
|
|
174
|
-
|
|
370
|
+
// Listen for code generated events from StoryUIPanel
|
|
371
|
+
useEffect(() => {
|
|
175
372
|
const channel = addons.getChannel();
|
|
176
|
-
|
|
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 (!
|
|
411
|
+
if (!active) return null;
|
|
412
|
+
|
|
413
|
+
// No story selected
|
|
414
|
+
if (!currentStoryId) {
|
|
180
415
|
return (
|
|
181
|
-
<
|
|
182
|
-
<
|
|
183
|
-
|
|
184
|
-
</
|
|
185
|
-
</
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
<
|
|
194
|
-
{
|
|
195
|
-
</
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
onClick={() => handleStoryClick(story)}
|
|
209
|
-
>
|
|
210
|
-
<StoryIcon>📖</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 (
|
|
444
|
+
// Check if extraction was successful (displayCode is different from sourceCode)
|
|
445
|
+
const hasUsageCode = displayCode !== sourceCode;
|
|
227
446
|
|
|
228
447
|
return (
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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, (
|
|
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: '
|
|
491
|
+
title: 'Source Code',
|
|
259
492
|
match: ({ viewMode }) => viewMode === 'story' || viewMode === 'docs',
|
|
260
|
-
render: ({ active }) =>
|
|
493
|
+
render: ({ active }) => <SourceCodePanel active={active} />,
|
|
261
494
|
});
|
|
262
495
|
});
|
|
263
|
-
|
|
264
|
-
export default {};
|