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