@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.
@@ -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,2CAwnCnD;AAED,eAAe,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,CAAC"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpitre/story-ui",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
4
4
  "description": "AI-powered Storybook story generator with dynamic component discovery",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -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 };