@tpitre/story-ui 4.3.0 → 4.4.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 +56 -34
- package/dist/cli/index.js +0 -0
- package/dist/mcp-server/index.js +68 -40
- package/dist/mcp-server/routes/mcpRemote.d.ts.map +1 -1
- package/dist/mcp-server/routes/mcpRemote.js +65 -36
- package/dist/templates/StoryUI/StoryUIPanel.css +1440 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
- package/dist/templates/StoryUI/StoryUIPanel.js +74 -0
- package/package.json +1 -1
- package/templates/StoryUI/StoryUIPanel.tsx +82 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoryUIPanel.d.ts","sourceRoot":"","sources":["../../../templates/StoryUI/StoryUIPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,oBAAoB,CAAC;AAwwB5B,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,iBAAS,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"StoryUIPanel.d.ts","sourceRoot":"","sources":["../../../templates/StoryUI/StoryUIPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,oBAAoB,CAAC;AAwwB5B,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,iBAAS,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,iBAAiB,2CA0sCnD;AAED,eAAe,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -452,12 +452,79 @@ function StoryUIPanel({ mcpPort }) {
|
|
|
452
452
|
const fileInputRef = useRef(null);
|
|
453
453
|
const abortControllerRef = useRef(null);
|
|
454
454
|
const hasShownRefreshHint = useRef(false);
|
|
455
|
+
// Track stories for MCP external generation detection
|
|
456
|
+
// Used to detect when stories are created via MCP remote (Claude Desktop)
|
|
457
|
+
// and trigger automatic refresh since MCP has no browser context
|
|
458
|
+
const panelGeneratedStoryIds = useRef(new Set());
|
|
459
|
+
const knownStoryIds = useRef(new Set());
|
|
460
|
+
const isPollingInitialized = useRef(false);
|
|
455
461
|
// Set port override if provided
|
|
456
462
|
useEffect(() => {
|
|
457
463
|
if (mcpPort && typeof window !== 'undefined') {
|
|
458
464
|
window.STORY_UI_MCP_PORT = String(mcpPort);
|
|
459
465
|
}
|
|
460
466
|
}, [mcpPort]);
|
|
467
|
+
// Poll for MCP-generated stories (stories created externally via Claude Desktop/Code)
|
|
468
|
+
// This solves the Vite HMR issue where stories generated via MCP remote don't trigger
|
|
469
|
+
// a browser refresh because MCP has no browser context to call window.location.reload()
|
|
470
|
+
useEffect(() => {
|
|
471
|
+
const POLL_INTERVAL_MS = 5000; // Check every 5 seconds
|
|
472
|
+
const pollForExternalStories = async () => {
|
|
473
|
+
try {
|
|
474
|
+
const baseUrl = getApiBaseUrl();
|
|
475
|
+
const response = await fetch(`${baseUrl}/story-ui/stories`);
|
|
476
|
+
if (!response.ok)
|
|
477
|
+
return;
|
|
478
|
+
const data = await response.json();
|
|
479
|
+
const currentStoryIds = new Set(data.stories?.map((s) => s.id) || []);
|
|
480
|
+
// On first poll, just record what's already there
|
|
481
|
+
if (!isPollingInitialized.current) {
|
|
482
|
+
knownStoryIds.current = currentStoryIds;
|
|
483
|
+
isPollingInitialized.current = true;
|
|
484
|
+
console.log('[Story UI] MCP story polling initialized with', currentStoryIds.size, 'stories');
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
// Check for new stories not created by this panel session
|
|
488
|
+
for (const storyId of currentStoryIds) {
|
|
489
|
+
if (!knownStoryIds.current.has(storyId) && !panelGeneratedStoryIds.current.has(storyId)) {
|
|
490
|
+
// New story detected that wasn't created by this panel - must be from MCP remote
|
|
491
|
+
console.log('[Story UI] Detected externally generated story:', storyId);
|
|
492
|
+
console.log('[Story UI] Triggering refresh to register new story in Vite import map...');
|
|
493
|
+
// Update known stories before refresh
|
|
494
|
+
knownStoryIds.current = currentStoryIds;
|
|
495
|
+
// Trigger refresh with a short delay
|
|
496
|
+
setTimeout(() => {
|
|
497
|
+
try {
|
|
498
|
+
if (window.top && window.top !== window) {
|
|
499
|
+
window.top.location.reload();
|
|
500
|
+
}
|
|
501
|
+
else if (window.parent && window.parent !== window) {
|
|
502
|
+
window.parent.location.reload();
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
window.location.reload();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
console.warn('[Story UI] Could not auto-refresh for MCP-generated story');
|
|
510
|
+
}
|
|
511
|
+
}, 1000);
|
|
512
|
+
return; // Only trigger one refresh
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
// Update known stories
|
|
516
|
+
knownStoryIds.current = currentStoryIds;
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
// Silently ignore polling errors - server may be unavailable temporarily
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
// Start polling
|
|
523
|
+
const intervalId = setInterval(pollForExternalStories, POLL_INTERVAL_MS);
|
|
524
|
+
// Initial poll
|
|
525
|
+
pollForExternalStories();
|
|
526
|
+
return () => clearInterval(intervalId);
|
|
527
|
+
}, []);
|
|
461
528
|
// Detect Storybook theme
|
|
462
529
|
useEffect(() => {
|
|
463
530
|
const detectTheme = () => {
|
|
@@ -863,6 +930,13 @@ function StoryUIPanel({ mcpPort }) {
|
|
|
863
930
|
title: completion.title,
|
|
864
931
|
action: completion.summary?.action,
|
|
865
932
|
});
|
|
933
|
+
// Track this story as panel-generated to prevent false MCP detection
|
|
934
|
+
// The story ID is the fileName without .stories.tsx extension
|
|
935
|
+
if (completion.success && completion.fileName) {
|
|
936
|
+
const storyId = completion.fileName.replace('.stories.tsx', '');
|
|
937
|
+
panelGeneratedStoryIds.current.add(storyId);
|
|
938
|
+
console.log('[Story UI] Tracking panel-generated story:', storyId);
|
|
939
|
+
}
|
|
866
940
|
const isUpdate = completion.summary.action === 'updated';
|
|
867
941
|
const responseMessage = buildConversationalResponse(completion, isUpdate);
|
|
868
942
|
const aiMsg = { role: 'ai', content: responseMessage };
|
package/package.json
CHANGED
|
@@ -800,6 +800,13 @@ function StoryUIPanel({ mcpPort }: StoryUIPanelProps) {
|
|
|
800
800
|
const abortControllerRef = useRef<AbortController | null>(null);
|
|
801
801
|
const hasShownRefreshHint = useRef(false);
|
|
802
802
|
|
|
803
|
+
// Track stories for MCP external generation detection
|
|
804
|
+
// Used to detect when stories are created via MCP remote (Claude Desktop)
|
|
805
|
+
// and trigger automatic refresh since MCP has no browser context
|
|
806
|
+
const panelGeneratedStoryIds = useRef<Set<string>>(new Set());
|
|
807
|
+
const knownStoryIds = useRef<Set<string>>(new Set());
|
|
808
|
+
const isPollingInitialized = useRef(false);
|
|
809
|
+
|
|
803
810
|
// Set port override if provided
|
|
804
811
|
useEffect(() => {
|
|
805
812
|
if (mcpPort && typeof window !== 'undefined') {
|
|
@@ -807,6 +814,73 @@ function StoryUIPanel({ mcpPort }: StoryUIPanelProps) {
|
|
|
807
814
|
}
|
|
808
815
|
}, [mcpPort]);
|
|
809
816
|
|
|
817
|
+
// Poll for MCP-generated stories (stories created externally via Claude Desktop/Code)
|
|
818
|
+
// This solves the Vite HMR issue where stories generated via MCP remote don't trigger
|
|
819
|
+
// a browser refresh because MCP has no browser context to call window.location.reload()
|
|
820
|
+
useEffect(() => {
|
|
821
|
+
const POLL_INTERVAL_MS = 5000; // Check every 5 seconds
|
|
822
|
+
|
|
823
|
+
const pollForExternalStories = async () => {
|
|
824
|
+
try {
|
|
825
|
+
const baseUrl = getApiBaseUrl();
|
|
826
|
+
const response = await fetch(`${baseUrl}/story-ui/stories`);
|
|
827
|
+
if (!response.ok) return;
|
|
828
|
+
|
|
829
|
+
const data = await response.json();
|
|
830
|
+
const currentStoryIds = new Set<string>(data.stories?.map((s: { id: string }) => s.id) || []);
|
|
831
|
+
|
|
832
|
+
// On first poll, just record what's already there
|
|
833
|
+
if (!isPollingInitialized.current) {
|
|
834
|
+
knownStoryIds.current = currentStoryIds;
|
|
835
|
+
isPollingInitialized.current = true;
|
|
836
|
+
console.log('[Story UI] MCP story polling initialized with', currentStoryIds.size, 'stories');
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Check for new stories not created by this panel session
|
|
841
|
+
for (const storyId of currentStoryIds) {
|
|
842
|
+
if (!knownStoryIds.current.has(storyId) && !panelGeneratedStoryIds.current.has(storyId)) {
|
|
843
|
+
// New story detected that wasn't created by this panel - must be from MCP remote
|
|
844
|
+
console.log('[Story UI] Detected externally generated story:', storyId);
|
|
845
|
+
console.log('[Story UI] Triggering refresh to register new story in Vite import map...');
|
|
846
|
+
|
|
847
|
+
// Update known stories before refresh
|
|
848
|
+
knownStoryIds.current = currentStoryIds;
|
|
849
|
+
|
|
850
|
+
// Trigger refresh with a short delay
|
|
851
|
+
setTimeout(() => {
|
|
852
|
+
try {
|
|
853
|
+
if (window.top && window.top !== window) {
|
|
854
|
+
window.top.location.reload();
|
|
855
|
+
} else if (window.parent && window.parent !== window) {
|
|
856
|
+
window.parent.location.reload();
|
|
857
|
+
} else {
|
|
858
|
+
window.location.reload();
|
|
859
|
+
}
|
|
860
|
+
} catch (error) {
|
|
861
|
+
console.warn('[Story UI] Could not auto-refresh for MCP-generated story');
|
|
862
|
+
}
|
|
863
|
+
}, 1000);
|
|
864
|
+
return; // Only trigger one refresh
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// Update known stories
|
|
869
|
+
knownStoryIds.current = currentStoryIds;
|
|
870
|
+
} catch (error) {
|
|
871
|
+
// Silently ignore polling errors - server may be unavailable temporarily
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
// Start polling
|
|
876
|
+
const intervalId = setInterval(pollForExternalStories, POLL_INTERVAL_MS);
|
|
877
|
+
|
|
878
|
+
// Initial poll
|
|
879
|
+
pollForExternalStories();
|
|
880
|
+
|
|
881
|
+
return () => clearInterval(intervalId);
|
|
882
|
+
}, []);
|
|
883
|
+
|
|
810
884
|
// Detect Storybook theme
|
|
811
885
|
useEffect(() => {
|
|
812
886
|
const detectTheme = () => {
|
|
@@ -1219,6 +1293,14 @@ function StoryUIPanel({ mcpPort }: StoryUIPanelProps) {
|
|
|
1219
1293
|
action: completion.summary?.action,
|
|
1220
1294
|
});
|
|
1221
1295
|
|
|
1296
|
+
// Track this story as panel-generated to prevent false MCP detection
|
|
1297
|
+
// The story ID is the fileName without .stories.tsx extension
|
|
1298
|
+
if (completion.success && completion.fileName) {
|
|
1299
|
+
const storyId = completion.fileName.replace('.stories.tsx', '');
|
|
1300
|
+
panelGeneratedStoryIds.current.add(storyId);
|
|
1301
|
+
console.log('[Story UI] Tracking panel-generated story:', storyId);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1222
1304
|
const isUpdate = completion.summary.action === 'updated';
|
|
1223
1305
|
const responseMessage = buildConversationalResponse(completion, isUpdate);
|
|
1224
1306
|
const aiMsg: Message = { role: 'ai', content: responseMessage };
|