@stigmer/react 3.1.1 → 3.1.3
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/composer/SessionComposer.d.ts +25 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +19 -8
- package/composer/SessionComposer.js.map +1 -1
- package/execution/ArtifactContentRenderer.d.ts +11 -1
- package/execution/ArtifactContentRenderer.d.ts.map +1 -1
- package/execution/ArtifactContentRenderer.js +39 -15
- package/execution/ArtifactContentRenderer.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts +5 -5
- package/execution/ArtifactPreviewModal.js +4 -4
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/FileChangeProgressBar.d.ts +47 -0
- package/execution/FileChangeProgressBar.d.ts.map +1 -0
- package/execution/FileChangeProgressBar.js +49 -0
- package/execution/FileChangeProgressBar.js.map +1 -0
- package/execution/FileChangesView.d.ts.map +1 -1
- package/execution/FileChangesView.js +19 -4
- package/execution/FileChangesView.js.map +1 -1
- package/execution/FilePathContext.d.ts +8 -1
- package/execution/FilePathContext.d.ts.map +1 -1
- package/execution/FilePathContext.js.map +1 -1
- package/execution/FilePathLink.d.ts.map +1 -1
- package/execution/FilePathLink.js +21 -6
- package/execution/FilePathLink.js.map +1 -1
- package/execution/FileReviewAtoms.d.ts +27 -0
- package/execution/FileReviewAtoms.d.ts.map +1 -0
- package/execution/FileReviewAtoms.js +64 -0
- package/execution/FileReviewAtoms.js.map +1 -0
- package/execution/FileReviewCard.d.ts +2 -2
- package/execution/FileReviewCard.d.ts.map +1 -1
- package/execution/FileReviewCard.js +32 -62
- package/execution/FileReviewCard.js.map +1 -1
- package/execution/MessageEntry.d.ts +20 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +19 -5
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +75 -13
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +195 -27
- package/execution/MessageThread.js.map +1 -1
- package/execution/PlanArtifactCard.d.ts +36 -21
- package/execution/PlanArtifactCard.d.ts.map +1 -1
- package/execution/PlanArtifactCard.js +39 -25
- package/execution/PlanArtifactCard.js.map +1 -1
- package/execution/PlanCompletionCard.d.ts +4 -4
- package/execution/PlanCompletionCard.d.ts.map +1 -1
- package/execution/PlanCompletionCard.js +4 -4
- package/execution/PlanCompletionCard.js.map +1 -1
- package/execution/PlanDocumentMessage.d.ts +32 -0
- package/execution/PlanDocumentMessage.d.ts.map +1 -0
- package/execution/PlanDocumentMessage.js +37 -0
- package/execution/PlanDocumentMessage.js.map +1 -0
- package/execution/PlanStreamingCard.d.ts +50 -0
- package/execution/PlanStreamingCard.d.ts.map +1 -0
- package/execution/PlanStreamingCard.js +40 -0
- package/execution/PlanStreamingCard.js.map +1 -0
- package/execution/index.d.ts +9 -1
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +4 -0
- package/execution/index.js.map +1 -1
- package/execution/use-build-from-plan-hotkey.d.ts +1 -1
- package/execution/use-build-from-plan-hotkey.js +1 -1
- package/execution/useArtifactCopy.d.ts +51 -0
- package/execution/useArtifactCopy.d.ts.map +1 -0
- package/execution/useArtifactCopy.js +75 -0
- package/execution/useArtifactCopy.js.map +1 -0
- package/execution/useArtifactDownload.d.ts.map +1 -1
- package/execution/useArtifactDownload.js +17 -5
- package/execution/useArtifactDownload.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +12 -0
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +5 -1
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/github/decodeGitHubContent.d.ts +29 -0
- package/github/decodeGitHubContent.d.ts.map +1 -0
- package/github/decodeGitHubContent.js +72 -0
- package/github/decodeGitHubContent.js.map +1 -0
- package/github/index.d.ts +1 -0
- package/github/index.d.ts.map +1 -1
- package/github/index.js +1 -0
- package/github/index.js.map +1 -1
- package/github/useGitHubFileReader.d.ts +26 -0
- package/github/useGitHubFileReader.d.ts.map +1 -0
- package/github/useGitHubFileReader.js +106 -0
- package/github/useGitHubFileReader.js.map +1 -0
- package/github/useGitHubTreeLister.d.ts.map +1 -1
- package/github/useGitHubTreeLister.js +6 -2
- package/github/useGitHubTreeLister.js.map +1 -1
- package/index.d.ts +9 -9
- package/index.d.ts.map +1 -1
- package/index.js +5 -5
- package/index.js.map +1 -1
- package/internal/ResizableSplit.d.ts +72 -22
- package/internal/ResizableSplit.d.ts.map +1 -1
- package/internal/ResizableSplit.js +96 -38
- package/internal/ResizableSplit.js.map +1 -1
- package/internal/VirtualizedThread.d.ts +5 -3
- package/internal/VirtualizedThread.d.ts.map +1 -1
- package/internal/VirtualizedThread.js +6 -4
- package/internal/VirtualizedThread.js.map +1 -1
- package/internal/file-icons/index.d.ts +17 -0
- package/internal/file-icons/index.d.ts.map +1 -0
- package/internal/file-icons/index.js +60 -0
- package/internal/file-icons/index.js.map +1 -0
- package/internal/file-tree/FileTreeNode.d.ts +18 -1
- package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
- package/internal/file-tree/FileTreeNode.js +11 -2
- package/internal/file-tree/FileTreeNode.js.map +1 -1
- package/internal/markdown-components.d.ts +38 -1
- package/internal/markdown-components.d.ts.map +1 -1
- package/internal/markdown-components.js +86 -11
- package/internal/markdown-components.js.map +1 -1
- package/{workflow → internal}/motion-preference.d.ts +7 -4
- package/internal/motion-preference.d.ts.map +1 -0
- package/{workflow → internal}/motion-preference.js +7 -4
- package/internal/motion-preference.js.map +1 -0
- package/internal/store/index.d.ts +33 -0
- package/internal/store/index.d.ts.map +1 -1
- package/internal/store/index.js +59 -0
- package/internal/store/index.js.map +1 -1
- package/internal/store/workspace-editors-store.d.ts +145 -0
- package/internal/store/workspace-editors-store.d.ts.map +1 -0
- package/internal/store/workspace-editors-store.js +208 -0
- package/internal/store/workspace-editors-store.js.map +1 -0
- package/internal/store/workspace-file-selection-store.d.ts +38 -0
- package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
- package/internal/store/workspace-file-selection-store.js +62 -0
- package/internal/store/workspace-file-selection-store.js.map +1 -0
- package/internal/useRevealLine.d.ts +49 -0
- package/internal/useRevealLine.d.ts.map +1 -0
- package/internal/useRevealLine.js +43 -0
- package/internal/useRevealLine.js.map +1 -0
- package/library/detect-plan-artifact.d.ts +43 -4
- package/library/detect-plan-artifact.d.ts.map +1 -1
- package/library/detect-plan-artifact.js +45 -5
- package/library/detect-plan-artifact.js.map +1 -1
- package/library/detect-streaming-plan.d.ts +45 -0
- package/library/detect-streaming-plan.d.ts.map +1 -0
- package/library/detect-streaming-plan.js +83 -0
- package/library/detect-streaming-plan.js.map +1 -0
- package/library/index.d.ts +4 -1
- package/library/index.d.ts.map +1 -1
- package/library/index.js +2 -1
- package/library/index.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +19 -4
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +52 -25
- package/session/NewSessionViewer.js.map +1 -1
- package/session/PlanEditor.d.ts +55 -0
- package/session/PlanEditor.d.ts.map +1 -0
- package/session/PlanEditor.js +88 -0
- package/session/PlanEditor.js.map +1 -0
- package/session/PlanStreamingDocument.d.ts +30 -0
- package/session/PlanStreamingDocument.d.ts.map +1 -0
- package/session/PlanStreamingDocument.js +37 -0
- package/session/PlanStreamingDocument.js.map +1 -0
- package/session/SessionPanelChip.d.ts +26 -0
- package/session/SessionPanelChip.d.ts.map +1 -0
- package/session/SessionPanelChip.js +40 -0
- package/session/SessionPanelChip.js.map +1 -0
- package/session/SessionViewer.d.ts +34 -7
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +334 -33
- package/session/SessionViewer.js.map +1 -1
- package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
- package/session/facets/ArtifactsTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ArtifactsTab.js +8 -3
- package/session/facets/ArtifactsTab.js.map +1 -0
- package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
- package/session/facets/ChangesTab.d.ts.map +1 -0
- package/session/{inspector → facets}/ChangesTab.js +3 -3
- package/session/facets/ChangesTab.js.map +1 -0
- package/session/facets/InspectTab.d.ts.map +1 -0
- package/session/facets/InspectTab.js.map +1 -0
- package/session/{inspector → facets}/SetupTab.d.ts +11 -2
- package/session/facets/SetupTab.d.ts.map +1 -0
- package/session/{inspector → facets}/SetupTab.js +4 -3
- package/session/facets/SetupTab.js.map +1 -0
- package/session/{inspector → facets}/UsageTab.d.ts +1 -1
- package/session/facets/UsageTab.d.ts.map +1 -0
- package/session/{inspector → facets}/UsageTab.js +1 -1
- package/session/facets/UsageTab.js.map +1 -0
- package/session/{inspector → facets}/index.d.ts +0 -6
- package/session/facets/index.d.ts.map +1 -0
- package/session/{inspector → facets}/index.js +0 -3
- package/session/facets/index.js.map +1 -0
- package/session/index.d.ts +11 -2
- package/session/index.d.ts.map +1 -1
- package/session/index.js +15 -2
- package/session/index.js.map +1 -1
- package/session/plan-document.d.ts +21 -0
- package/session/plan-document.d.ts.map +1 -0
- package/session/plan-document.js +28 -0
- package/session/plan-document.js.map +1 -0
- package/session/useOpenFileChange.d.ts +20 -0
- package/session/useOpenFileChange.d.ts.map +1 -0
- package/session/useOpenFileChange.js +31 -0
- package/session/useOpenFileChange.js.map +1 -0
- package/session/usePlanDraft.d.ts +52 -0
- package/session/usePlanDraft.d.ts.map +1 -0
- package/session/usePlanDraft.js +63 -0
- package/session/usePlanDraft.js.map +1 -0
- package/session/useSessionConversation.d.ts +14 -1
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +20 -2
- package/session/useSessionConversation.js.map +1 -1
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +1 -0
- package/session/useSessionPageFlow.js.map +1 -1
- package/session/useSessionPanel.d.ts +120 -0
- package/session/useSessionPanel.d.ts.map +1 -0
- package/session/useSessionPanel.js +130 -0
- package/session/useSessionPanel.js.map +1 -0
- package/session/useSessionRailViews.d.ts +45 -0
- package/session/useSessionRailViews.d.ts.map +1 -0
- package/session/useSessionRailViews.js +105 -0
- package/session/useSessionRailViews.js.map +1 -0
- package/src/composer/SessionComposer.tsx +53 -10
- package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
- package/src/execution/ArtifactContentRenderer.tsx +101 -24
- package/src/execution/ArtifactPreviewModal.tsx +9 -9
- package/src/execution/FileChangeProgressBar.tsx +121 -0
- package/src/execution/FileChangesView.tsx +18 -4
- package/src/execution/FilePathContext.tsx +8 -1
- package/src/execution/FilePathLink.tsx +22 -6
- package/src/execution/FileReviewAtoms.tsx +89 -0
- package/src/execution/FileReviewCard.tsx +57 -90
- package/src/execution/MessageEntry.tsx +49 -1
- package/src/execution/MessageThread.tsx +308 -39
- package/src/execution/PlanArtifactCard.tsx +174 -64
- package/src/execution/PlanCompletionCard.tsx +5 -5
- package/src/execution/PlanDocumentMessage.tsx +96 -0
- package/src/execution/PlanStreamingCard.tsx +141 -0
- package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
- package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
- package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
- package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
- package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
- package/src/execution/__tests__/MessageThread.test.tsx +102 -1
- package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
- package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
- package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
- package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
- package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
- package/src/execution/__tests__/message-entry.test.tsx +17 -0
- package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
- package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
- package/src/execution/index.ts +13 -1
- package/src/execution/use-build-from-plan-hotkey.ts +1 -1
- package/src/execution/useArtifactCopy.ts +109 -0
- package/src/execution/useArtifactDownload.ts +17 -5
- package/src/execution/useCreateAgentExecution.ts +18 -1
- package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
- package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
- package/src/github/decodeGitHubContent.ts +83 -0
- package/src/github/index.ts +1 -0
- package/src/github/useGitHubFileReader.ts +152 -0
- package/src/github/useGitHubTreeLister.ts +6 -2
- package/src/index.ts +69 -9
- package/src/internal/ResizableSplit.tsx +184 -51
- package/src/internal/VirtualizedThread.tsx +12 -4
- package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
- package/src/internal/__tests__/markdown-components.test.tsx +68 -0
- package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
- package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
- package/src/internal/file-icons/index.tsx +137 -0
- package/src/internal/file-tree/FileTreeNode.tsx +56 -5
- package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
- package/src/internal/markdown-components.tsx +116 -11
- package/src/{workflow → internal}/motion-preference.ts +7 -4
- package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
- package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
- package/src/internal/store/index.ts +94 -0
- package/src/internal/store/workspace-editors-store.ts +315 -0
- package/src/internal/store/workspace-file-selection-store.ts +88 -0
- package/src/internal/useRevealLine.ts +81 -0
- package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
- package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
- package/src/library/detect-plan-artifact.ts +62 -5
- package/src/library/detect-streaming-plan.ts +108 -0
- package/src/library/index.ts +7 -0
- package/src/session/NewSessionViewer.tsx +123 -55
- package/src/session/PlanEditor.tsx +361 -0
- package/src/session/PlanStreamingDocument.tsx +97 -0
- package/src/session/SessionPanelChip.tsx +103 -0
- package/src/session/SessionViewer.tsx +655 -96
- package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
- package/src/session/__tests__/PlanEditor.test.tsx +217 -0
- package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
- package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
- package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
- package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
- package/src/session/__tests__/audienceWiring.test.tsx +55 -19
- package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
- package/src/session/__tests__/usePlanDraft.test.ts +102 -0
- package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
- package/src/session/__tests__/useSessionPanel.test.ts +298 -0
- package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
- package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
- package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
- package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
- package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
- package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
- package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
- package/src/session/{inspector → facets}/index.ts +0 -16
- package/src/session/index.ts +30 -13
- package/src/session/plan-document.ts +30 -0
- package/src/session/useOpenFileChange.ts +53 -0
- package/src/session/usePlanDraft.ts +109 -0
- package/src/session/useSessionConversation.ts +38 -3
- package/src/session/useSessionPageFlow.ts +1 -0
- package/src/session/useSessionPanel.ts +288 -0
- package/src/session/useSessionRailViews.tsx +200 -0
- package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
- package/src/workflow/index.ts +1 -1
- package/src/workflow/useFollowExecution.ts +1 -1
- package/src/workspace/EditorTabs.tsx +174 -0
- package/src/workspace/ExplorerTree.tsx +253 -0
- package/src/workspace/FileViewer.tsx +537 -0
- package/src/workspace/WorkspaceContentSearch.tsx +502 -0
- package/src/workspace/WorkspaceContentSearcher.ts +70 -0
- package/src/workspace/WorkspaceEditor.tsx +19 -16
- package/src/workspace/WorkspaceFileLister.ts +11 -0
- package/src/workspace/WorkspaceFileReader.ts +57 -0
- package/src/workspace/WorkspaceFileSearch.tsx +452 -0
- package/src/workspace/WorkspaceSurface.tsx +839 -0
- package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
- package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
- package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
- package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
- package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
- package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
- package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
- package/src/workspace/__tests__/a11y/harness.tsx +140 -0
- package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
- package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
- package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
- package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
- package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
- package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
- package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
- package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
- package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
- package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
- package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
- package/src/workspace/findChangeForSelection.ts +61 -0
- package/src/workspace/index.ts +56 -2
- package/src/workspace/matchContentPreview.ts +51 -0
- package/src/workspace/matchWorkspaceFiles.ts +86 -0
- package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
- package/src/workspace/useWorkspaceContentSearch.ts +228 -0
- package/src/workspace/useWorkspaceFileContent.ts +129 -0
- package/src/workspace/useWorkspaceFileSearch.ts +184 -0
- package/src/workspace/useWorkspaceFiles.ts +27 -27
- package/src/workspace/workspaceListingCache.ts +93 -0
- package/styles.css +1 -1
- package/workflow/WorkflowExecutionGraph.js +1 -1
- package/workflow/WorkflowExecutionGraph.js.map +1 -1
- package/workflow/index.d.ts +1 -1
- package/workflow/index.d.ts.map +1 -1
- package/workflow/index.js +1 -1
- package/workflow/index.js.map +1 -1
- package/workflow/useFollowExecution.js +1 -1
- package/workflow/useFollowExecution.js.map +1 -1
- package/workspace/EditorTabs.d.ts +47 -0
- package/workspace/EditorTabs.d.ts.map +1 -0
- package/workspace/EditorTabs.js +78 -0
- package/workspace/EditorTabs.js.map +1 -0
- package/workspace/ExplorerTree.d.ts +32 -0
- package/workspace/ExplorerTree.d.ts.map +1 -0
- package/workspace/ExplorerTree.js +49 -0
- package/workspace/ExplorerTree.js.map +1 -0
- package/workspace/FileViewer.d.ts +93 -0
- package/workspace/FileViewer.d.ts.map +1 -0
- package/workspace/FileViewer.js +193 -0
- package/workspace/FileViewer.js.map +1 -0
- package/workspace/WorkspaceContentSearch.d.ts +41 -0
- package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearch.js +216 -0
- package/workspace/WorkspaceContentSearch.js.map +1 -0
- package/workspace/WorkspaceContentSearcher.d.ts +59 -0
- package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
- package/workspace/WorkspaceContentSearcher.js +7 -0
- package/workspace/WorkspaceContentSearcher.js.map +1 -0
- package/workspace/WorkspaceEditor.d.ts.map +1 -1
- package/workspace/WorkspaceEditor.js +8 -10
- package/workspace/WorkspaceEditor.js.map +1 -1
- package/workspace/WorkspaceFileLister.d.ts +11 -0
- package/workspace/WorkspaceFileLister.d.ts.map +1 -1
- package/workspace/WorkspaceFileReader.d.ts +48 -0
- package/workspace/WorkspaceFileReader.d.ts.map +1 -0
- package/workspace/WorkspaceFileReader.js +11 -0
- package/workspace/WorkspaceFileReader.js.map +1 -0
- package/workspace/WorkspaceFileSearch.d.ts +32 -0
- package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/WorkspaceFileSearch.js +175 -0
- package/workspace/WorkspaceFileSearch.js.map +1 -0
- package/workspace/WorkspaceSurface.d.ts +151 -0
- package/workspace/WorkspaceSurface.d.ts.map +1 -0
- package/workspace/WorkspaceSurface.js +220 -0
- package/workspace/WorkspaceSurface.js.map +1 -0
- package/workspace/findChangeForSelection.d.ts +19 -0
- package/workspace/findChangeForSelection.d.ts.map +1 -0
- package/workspace/findChangeForSelection.js +46 -0
- package/workspace/findChangeForSelection.js.map +1 -0
- package/workspace/index.d.ts +24 -2
- package/workspace/index.d.ts.map +1 -1
- package/workspace/index.js +13 -1
- package/workspace/index.js.map +1 -1
- package/workspace/matchContentPreview.d.ts +21 -0
- package/workspace/matchContentPreview.d.ts.map +1 -0
- package/workspace/matchContentPreview.js +36 -0
- package/workspace/matchContentPreview.js.map +1 -0
- package/workspace/matchWorkspaceFiles.d.ts +30 -0
- package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
- package/workspace/matchWorkspaceFiles.js +58 -0
- package/workspace/matchWorkspaceFiles.js.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
- package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
- package/workspace/resolveWorkspaceFileSelection.js +115 -0
- package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
- package/workspace/useWorkspaceContentSearch.d.ts +69 -0
- package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceContentSearch.js +154 -0
- package/workspace/useWorkspaceContentSearch.js.map +1 -0
- package/workspace/useWorkspaceFileContent.d.ts +73 -0
- package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
- package/workspace/useWorkspaceFileContent.js +57 -0
- package/workspace/useWorkspaceFileContent.js.map +1 -0
- package/workspace/useWorkspaceFileSearch.d.ts +61 -0
- package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
- package/workspace/useWorkspaceFileSearch.js +119 -0
- package/workspace/useWorkspaceFileSearch.js.map +1 -0
- package/workspace/useWorkspaceFiles.d.ts +13 -5
- package/workspace/useWorkspaceFiles.d.ts.map +1 -1
- package/workspace/useWorkspaceFiles.js +18 -19
- package/workspace/useWorkspaceFiles.js.map +1 -1
- package/workspace/workspaceListingCache.d.ts +47 -0
- package/workspace/workspaceListingCache.d.ts.map +1 -0
- package/workspace/workspaceListingCache.js +55 -0
- package/workspace/workspaceListingCache.js.map +1 -0
- package/session/inspector/ArtifactsTab.d.ts.map +0 -1
- package/session/inspector/ArtifactsTab.js.map +0 -1
- package/session/inspector/ChangesTab.d.ts.map +0 -1
- package/session/inspector/ChangesTab.js.map +0 -1
- package/session/inspector/InspectTab.d.ts.map +0 -1
- package/session/inspector/InspectTab.js.map +0 -1
- package/session/inspector/SessionInspector.d.ts +0 -64
- package/session/inspector/SessionInspector.d.ts.map +0 -1
- package/session/inspector/SessionInspector.js +0 -53
- package/session/inspector/SessionInspector.js.map +0 -1
- package/session/inspector/SetupTab.d.ts.map +0 -1
- package/session/inspector/SetupTab.js.map +0 -1
- package/session/inspector/UsageTab.d.ts.map +0 -1
- package/session/inspector/UsageTab.js.map +0 -1
- package/session/inspector/WorkspaceTab.d.ts +0 -35
- package/session/inspector/WorkspaceTab.d.ts.map +0 -1
- package/session/inspector/WorkspaceTab.js +0 -75
- package/session/inspector/WorkspaceTab.js.map +0 -1
- package/session/inspector/index.d.ts.map +0 -1
- package/session/inspector/index.js.map +0 -1
- package/session/inspector/useSessionInspector.d.ts +0 -49
- package/session/inspector/useSessionInspector.d.ts.map +0 -1
- package/session/inspector/useSessionInspector.js +0 -122
- package/session/inspector/useSessionInspector.js.map +0 -1
- package/src/session/inspector/SessionInspector.tsx +0 -162
- package/src/session/inspector/WorkspaceTab.tsx +0 -245
- package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
- package/src/session/inspector/useSessionInspector.ts +0 -178
- package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
- package/workflow/motion-preference.d.ts.map +0 -1
- package/workflow/motion-preference.js.map +0 -1
- package/workspace/WorkspaceEntryFiles.d.ts +0 -22
- package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
- package/workspace/WorkspaceEntryFiles.js +0 -58
- package/workspace/WorkspaceEntryFiles.js.map +0 -1
- /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
- /package/session/{inspector → facets}/InspectTab.js +0 -0
- /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
- /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
- /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
|
@@ -9,29 +9,67 @@ import {
|
|
|
9
9
|
} from "react";
|
|
10
10
|
import { cn } from "@stigmer/theme";
|
|
11
11
|
|
|
12
|
+
/** Which pane carries the drag-controlled pixel width; its sibling flexes. */
|
|
13
|
+
export type ResizablePane = "primary" | "secondary";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Which pane (if any) collapses below the `lg` breakpoint, leaving its sibling
|
|
17
|
+
* full-width. Use this to hide the pixel-sized pane on narrow screens — always
|
|
18
|
+
* pair it with {@link ResizableSplitProps.resizablePane} (hide the fixed pane so
|
|
19
|
+
* the visible sibling is the flexing one and fills the row). `"none"` keeps both
|
|
20
|
+
* panes at every width.
|
|
21
|
+
*/
|
|
22
|
+
export type ResizableCollapse = "primary" | "secondary" | "none";
|
|
23
|
+
|
|
12
24
|
/** Props for {@link ResizableSplit}. */
|
|
13
25
|
export interface ResizableSplitProps {
|
|
14
|
-
/** Content rendered in the
|
|
26
|
+
/** Content rendered in the first (left) region. */
|
|
15
27
|
readonly primary: ReactNode;
|
|
16
|
-
/** Content rendered in the
|
|
28
|
+
/** Content rendered in the second (right) region. */
|
|
17
29
|
readonly secondary: ReactNode;
|
|
18
30
|
/**
|
|
19
|
-
*
|
|
31
|
+
* Which pane is pixel-sized and drag-resizable; the other flexes to fill.
|
|
32
|
+
* Child render order is fixed (`primary` then `secondary`) regardless of this
|
|
33
|
+
* value, so flipping it re-flows the layout without remounting either child.
|
|
34
|
+
* @default "secondary"
|
|
35
|
+
*/
|
|
36
|
+
readonly resizablePane?: ResizablePane;
|
|
37
|
+
/**
|
|
38
|
+
* Default width of the resizable pane in pixels.
|
|
20
39
|
* Overridden by a persisted value when `storageKey` is set.
|
|
21
40
|
* @default 384
|
|
22
41
|
*/
|
|
23
42
|
readonly defaultSize?: number;
|
|
24
|
-
/** Minimum width of the
|
|
43
|
+
/** Minimum width of the resizable pane in pixels. @default 280 */
|
|
25
44
|
readonly minSize?: number;
|
|
26
|
-
/** Maximum width of the
|
|
45
|
+
/** Maximum width of the resizable pane in pixels. @default 800 */
|
|
27
46
|
readonly maxSize?: number;
|
|
28
47
|
/**
|
|
29
|
-
* `localStorage` key for persisting the
|
|
30
|
-
* When omitted, the
|
|
48
|
+
* `localStorage` key for persisting the pane width across sessions.
|
|
49
|
+
* When omitted, the pane width resets to `defaultSize` on remount.
|
|
50
|
+
* Changing this key (or `resizablePane`) re-initializes the width from the
|
|
51
|
+
* new key without remounting — the mechanism the session layout uses to keep
|
|
52
|
+
* a distinct persisted width per mode.
|
|
31
53
|
*/
|
|
32
54
|
readonly storageKey?: string;
|
|
55
|
+
/** Which pane collapses below the `lg` breakpoint. @default "none" */
|
|
56
|
+
readonly responsiveCollapse?: ResizableCollapse;
|
|
57
|
+
/**
|
|
58
|
+
* Which pane (if any) is collapsed at every width, hiding the drag handle and
|
|
59
|
+
* letting the sibling fill the row. Unlike conditional rendering at the call
|
|
60
|
+
* site, collapsing through this prop keeps both children mounted at stable
|
|
61
|
+
* tree positions — the session panel uses it so opening/closing the panel
|
|
62
|
+
* never remounts the conversation. The persisted width survives a collapse
|
|
63
|
+
* and applies again on expand.
|
|
64
|
+
* @default "none"
|
|
65
|
+
*/
|
|
66
|
+
readonly collapsedPane?: ResizableCollapse;
|
|
67
|
+
/**
|
|
68
|
+
* Accessible label for the drag separator. @default "Resize panel"
|
|
69
|
+
*/
|
|
70
|
+
readonly ariaLabel?: string;
|
|
33
71
|
/**
|
|
34
|
-
* Called whenever the
|
|
72
|
+
* Called whenever the resizable pane width changes (during drag
|
|
35
73
|
* and on initial mount from persisted state). Consumers use this
|
|
36
74
|
* to thread the width into layout-dependent calculations like
|
|
37
75
|
* `WorkflowExecutionGraph.panelOffsetPx`.
|
|
@@ -44,62 +82,111 @@ export interface ResizableSplitProps {
|
|
|
44
82
|
const KEYBOARD_STEP_PX = 20;
|
|
45
83
|
|
|
46
84
|
/**
|
|
47
|
-
*
|
|
85
|
+
* Read the initial pane width for a given storage key, falling back to
|
|
86
|
+
* `defaultSize` when there is no valid persisted value. Pure of React state so
|
|
87
|
+
* it can seed `useState` and re-seed on a key/pane change.
|
|
88
|
+
*/
|
|
89
|
+
function readInitialWidth(
|
|
90
|
+
storageKey: string | undefined,
|
|
91
|
+
defaultSize: number,
|
|
92
|
+
minSize: number,
|
|
93
|
+
maxSize: number,
|
|
94
|
+
): number {
|
|
95
|
+
if (storageKey) {
|
|
96
|
+
try {
|
|
97
|
+
const stored = localStorage.getItem(storageKey);
|
|
98
|
+
if (stored) {
|
|
99
|
+
const parsed = Number(stored);
|
|
100
|
+
if (Number.isFinite(parsed) && parsed >= minSize && parsed <= maxSize) {
|
|
101
|
+
return parsed;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
/* localStorage may be unavailable */
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return defaultSize;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Horizontal split layout with one drag-resizable pixel-sized pane and one
|
|
113
|
+
* flexible pane.
|
|
48
114
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
115
|
+
* By default the right region (`secondary`) is pixel-sized and the left
|
|
116
|
+
* (`primary`) flexes. Set `resizablePane="primary"` to flip which side carries
|
|
117
|
+
* the width — the session layout uses this to invert between a chat-dominant
|
|
118
|
+
* layout (inspector on the right, fixed) and a workspace-dominant layout (chat
|
|
119
|
+
* on the left, fixed). Render order never changes, so flipping re-flows the row
|
|
120
|
+
* without remounting either child (preserving streaming/scroll state).
|
|
52
121
|
*
|
|
53
122
|
* Design:
|
|
54
123
|
* - Pointer-based drag with `setPointerCapture` for reliable tracking
|
|
55
124
|
* - `requestAnimationFrame` coalescing during drag (DD-009 pattern)
|
|
56
|
-
* - Keyboard accessible:
|
|
57
|
-
*
|
|
125
|
+
* - Keyboard accessible: arrow keys nudge by {@link KEYBOARD_STEP_PX}, oriented
|
|
126
|
+
* so the pane always grows toward its own side
|
|
127
|
+
* - Optional `localStorage` persistence via `storageKey`, re-initialized when
|
|
128
|
+
* the key or resizable side changes (no remount required)
|
|
129
|
+
* - Optional responsive collapse of the pixel pane below `lg`
|
|
58
130
|
* - Styled with `--stgm-*` tokens; no hardcoded colors
|
|
59
131
|
*
|
|
60
132
|
* @example
|
|
61
133
|
* ```tsx
|
|
134
|
+
* // Chat-dominant: inspector fixed on the right (default)
|
|
135
|
+
* <ResizableSplit
|
|
136
|
+
* primary={<Conversation />}
|
|
137
|
+
* secondary={<Inspector />}
|
|
138
|
+
* storageKey="stgm-session-inspector-width"
|
|
139
|
+
* responsiveCollapse="secondary"
|
|
140
|
+
* />
|
|
141
|
+
*
|
|
142
|
+
* // Workspace-dominant: chat fixed on the left
|
|
62
143
|
* <ResizableSplit
|
|
63
|
-
* primary
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* storageKey="wf-exec-inspector-width"
|
|
69
|
-
* onResize={setPanelWidth}
|
|
144
|
+
* resizablePane="primary"
|
|
145
|
+
* primary={<Conversation />}
|
|
146
|
+
* secondary={<WorkspaceSurface />}
|
|
147
|
+
* storageKey="stgm-session-chat-width"
|
|
148
|
+
* responsiveCollapse="primary"
|
|
70
149
|
* />
|
|
71
150
|
* ```
|
|
72
151
|
*/
|
|
73
152
|
export function ResizableSplit({
|
|
74
153
|
primary,
|
|
75
154
|
secondary,
|
|
155
|
+
resizablePane = "secondary",
|
|
76
156
|
defaultSize = 384,
|
|
77
157
|
minSize = 280,
|
|
78
158
|
maxSize = 800,
|
|
79
159
|
storageKey,
|
|
160
|
+
responsiveCollapse = "none",
|
|
161
|
+
collapsedPane = "none",
|
|
162
|
+
ariaLabel = "Resize panel",
|
|
80
163
|
onResize,
|
|
81
164
|
className,
|
|
82
165
|
}: ResizableSplitProps) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
166
|
+
const isPrimaryResizable = resizablePane === "primary";
|
|
167
|
+
const isCollapsed = collapsedPane !== "none";
|
|
168
|
+
|
|
169
|
+
const [panelWidth, setPanelWidth] = useState(() =>
|
|
170
|
+
readInitialWidth(storageKey, defaultSize, minSize, maxSize),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Re-initialize the width when the storage key or resizable side changes —
|
|
174
|
+
// the session layout swaps both together on a mode flip and expects the width
|
|
175
|
+
// to come from the new key, not carry over. Adjust-state-during-render
|
|
176
|
+
// (matching `useSessionPanel`) so it lands before paint without a remount.
|
|
177
|
+
const [prevStorageKey, setPrevStorageKey] = useState(storageKey);
|
|
178
|
+
const [prevResizablePane, setPrevResizablePane] = useState(resizablePane);
|
|
179
|
+
if (storageKey !== prevStorageKey || resizablePane !== prevResizablePane) {
|
|
180
|
+
setPrevStorageKey(storageKey);
|
|
181
|
+
setPrevResizablePane(resizablePane);
|
|
182
|
+
setPanelWidth(readInitialWidth(storageKey, defaultSize, minSize, maxSize));
|
|
183
|
+
}
|
|
97
184
|
|
|
98
185
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
99
186
|
const rafRef = useRef(0);
|
|
100
187
|
const isDraggingRef = useRef(false);
|
|
101
188
|
|
|
102
|
-
// Notify consumer of
|
|
189
|
+
// Notify consumer of the current width whenever it changes (incl. on re-init).
|
|
103
190
|
const onResizeRef = useRef(onResize);
|
|
104
191
|
onResizeRef.current = onResize;
|
|
105
192
|
useEffect(() => {
|
|
@@ -116,7 +203,9 @@ export function ResizableSplit({
|
|
|
116
203
|
if (!storageKey) return;
|
|
117
204
|
try {
|
|
118
205
|
localStorage.setItem(storageKey, String(width));
|
|
119
|
-
} catch {
|
|
206
|
+
} catch {
|
|
207
|
+
/* quota or security error */
|
|
208
|
+
}
|
|
120
209
|
},
|
|
121
210
|
[storageKey],
|
|
122
211
|
);
|
|
@@ -140,11 +229,15 @@ export function ResizableSplit({
|
|
|
140
229
|
const container = containerRef.current;
|
|
141
230
|
if (!container) return;
|
|
142
231
|
const rect = container.getBoundingClientRect();
|
|
143
|
-
|
|
144
|
-
|
|
232
|
+
// The resizable pane's width is the distance from its own edge to the
|
|
233
|
+
// pointer: left edge for a primary pane, right edge for a secondary one.
|
|
234
|
+
const raw = isPrimaryResizable
|
|
235
|
+
? clientX - rect.left
|
|
236
|
+
: rect.right - clientX;
|
|
237
|
+
setPanelWidth(clampWidth(raw));
|
|
145
238
|
});
|
|
146
239
|
},
|
|
147
|
-
[clampWidth],
|
|
240
|
+
[clampWidth, isPrimaryResizable],
|
|
148
241
|
);
|
|
149
242
|
|
|
150
243
|
const handlePointerUp = useCallback(
|
|
@@ -160,9 +253,11 @@ export function ResizableSplit({
|
|
|
160
253
|
|
|
161
254
|
const handleKeyDown = useCallback(
|
|
162
255
|
(e: React.KeyboardEvent) => {
|
|
256
|
+
// Arrow keys grow the pane toward its own side: a primary (left) pane
|
|
257
|
+
// grows on ArrowRight, a secondary (right) pane grows on ArrowLeft.
|
|
163
258
|
let delta = 0;
|
|
164
|
-
if (e.key === "ArrowLeft") delta = KEYBOARD_STEP_PX;
|
|
165
|
-
else if (e.key === "ArrowRight") delta = -KEYBOARD_STEP_PX;
|
|
259
|
+
if (e.key === "ArrowLeft") delta = isPrimaryResizable ? -KEYBOARD_STEP_PX : KEYBOARD_STEP_PX;
|
|
260
|
+
else if (e.key === "ArrowRight") delta = isPrimaryResizable ? KEYBOARD_STEP_PX : -KEYBOARD_STEP_PX;
|
|
166
261
|
if (delta === 0) return;
|
|
167
262
|
|
|
168
263
|
e.preventDefault();
|
|
@@ -172,26 +267,57 @@ export function ResizableSplit({
|
|
|
172
267
|
return next;
|
|
173
268
|
});
|
|
174
269
|
},
|
|
175
|
-
[clampWidth, persist],
|
|
270
|
+
[clampWidth, persist, isPrimaryResizable],
|
|
176
271
|
);
|
|
177
272
|
|
|
178
273
|
// Cleanup rAF on unmount
|
|
179
274
|
useEffect(() => () => cancelAnimationFrame(rafRef.current), []);
|
|
180
275
|
|
|
276
|
+
const fixedPaneClass = "shrink-0 overflow-hidden";
|
|
277
|
+
const flexPaneClass = "min-w-0 flex-1";
|
|
278
|
+
|
|
279
|
+
// A collapsed pane hides entirely and its sibling flexes to fill the row,
|
|
280
|
+
// overriding the fixed/flex split. Width state is untouched, so expanding
|
|
281
|
+
// restores the previous size.
|
|
282
|
+
const primaryPaneClass =
|
|
283
|
+
collapsedPane === "primary"
|
|
284
|
+
? "hidden"
|
|
285
|
+
: collapsedPane === "secondary" || !isPrimaryResizable
|
|
286
|
+
? flexPaneClass
|
|
287
|
+
: fixedPaneClass;
|
|
288
|
+
const secondaryPaneClass =
|
|
289
|
+
collapsedPane === "secondary"
|
|
290
|
+
? "hidden"
|
|
291
|
+
: collapsedPane === "primary" || isPrimaryResizable
|
|
292
|
+
? flexPaneClass
|
|
293
|
+
: fixedPaneClass;
|
|
294
|
+
|
|
181
295
|
return (
|
|
182
296
|
<div ref={containerRef} className={cn("flex min-h-0 flex-1", className)}>
|
|
183
|
-
{/* Primary region (
|
|
184
|
-
<div
|
|
297
|
+
{/* Primary region (first child, order-stable across flips/collapses) */}
|
|
298
|
+
<div
|
|
299
|
+
className={cn(
|
|
300
|
+
primaryPaneClass,
|
|
301
|
+
responsiveCollapse === "primary" && "max-lg:hidden",
|
|
302
|
+
)}
|
|
303
|
+
style={
|
|
304
|
+
isPrimaryResizable && !isCollapsed ? { width: panelWidth } : undefined
|
|
305
|
+
}
|
|
306
|
+
>
|
|
307
|
+
{primary}
|
|
308
|
+
</div>
|
|
185
309
|
|
|
186
|
-
{/* Drag handle
|
|
310
|
+
{/* Drag handle — CSS-hidden (not unmounted) while collapsed so all three
|
|
311
|
+
children keep stable tree positions across a collapse toggle. */}
|
|
187
312
|
<div
|
|
188
313
|
role="separator"
|
|
189
314
|
aria-orientation="vertical"
|
|
190
315
|
aria-valuenow={panelWidth}
|
|
191
316
|
aria-valuemin={minSize}
|
|
192
317
|
aria-valuemax={maxSize}
|
|
193
|
-
aria-label=
|
|
194
|
-
|
|
318
|
+
aria-label={ariaLabel}
|
|
319
|
+
aria-hidden={isCollapsed || undefined}
|
|
320
|
+
tabIndex={isCollapsed ? -1 : 0}
|
|
195
321
|
onPointerDown={handlePointerDown}
|
|
196
322
|
onPointerMove={handlePointerMove}
|
|
197
323
|
onPointerUp={handlePointerUp}
|
|
@@ -203,16 +329,23 @@ export function ResizableSplit({
|
|
|
203
329
|
"focus-visible:bg-[var(--stgm-primary,#6366f1)] focus-visible:outline-none",
|
|
204
330
|
"active:bg-[var(--stgm-primary,#6366f1)]",
|
|
205
331
|
"transition-colors duration-100",
|
|
332
|
+
responsiveCollapse !== "none" && "max-lg:hidden",
|
|
333
|
+
isCollapsed && "hidden",
|
|
206
334
|
)}
|
|
207
335
|
>
|
|
208
336
|
{/* Wider invisible hit target (12px) for easier grabbing */}
|
|
209
337
|
<div className="absolute inset-y-0 -left-1.5 -right-1.5" />
|
|
210
338
|
</div>
|
|
211
339
|
|
|
212
|
-
{/* Secondary region (
|
|
340
|
+
{/* Secondary region (second child, order-stable across flips/collapses) */}
|
|
213
341
|
<div
|
|
214
|
-
className=
|
|
215
|
-
|
|
342
|
+
className={cn(
|
|
343
|
+
secondaryPaneClass,
|
|
344
|
+
responsiveCollapse === "secondary" && "max-lg:hidden",
|
|
345
|
+
)}
|
|
346
|
+
style={
|
|
347
|
+
!isPrimaryResizable && !isCollapsed ? { width: panelWidth } : undefined
|
|
348
|
+
}
|
|
216
349
|
>
|
|
217
350
|
{secondary}
|
|
218
351
|
</div>
|
|
@@ -14,7 +14,9 @@ import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution
|
|
|
14
14
|
import { ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
15
15
|
import {
|
|
16
16
|
ThreadItemRenderer,
|
|
17
|
+
threadContentColumnClass,
|
|
17
18
|
type ThreadItem,
|
|
19
|
+
type ThreadContentColumn,
|
|
18
20
|
} from "../execution/MessageThread.js";
|
|
19
21
|
import { FilePathContext, type FilePathContextValue } from "../execution/FilePathContext.js";
|
|
20
22
|
import { SandboxContext, type SandboxContextValue } from "../execution/SandboxContext.js";
|
|
@@ -45,9 +47,11 @@ export interface VirtualizedThreadProps {
|
|
|
45
47
|
readonly fileReviewCtx: FileReviewContextValue;
|
|
46
48
|
readonly unresolvedApprovalCount: number;
|
|
47
49
|
readonly onBuildFromPlan?: () => void;
|
|
50
|
+
readonly onOpenPlan?: (executionId: string) => void;
|
|
48
51
|
readonly org?: string;
|
|
49
52
|
readonly planActionsDisabled?: boolean;
|
|
50
|
-
readonly
|
|
53
|
+
readonly planBuildPending?: boolean;
|
|
54
|
+
readonly contentColumn?: ThreadContentColumn;
|
|
51
55
|
readonly onRetrySend?: () => void;
|
|
52
56
|
readonly onRetryExecution?: (message: string) => void;
|
|
53
57
|
readonly onEditMessage?: (text: string) => void;
|
|
@@ -112,9 +116,11 @@ export function VirtualizedThread({
|
|
|
112
116
|
fileReviewCtx,
|
|
113
117
|
unresolvedApprovalCount,
|
|
114
118
|
onBuildFromPlan,
|
|
119
|
+
onOpenPlan,
|
|
115
120
|
org,
|
|
116
121
|
planActionsDisabled,
|
|
117
|
-
|
|
122
|
+
planBuildPending,
|
|
123
|
+
contentColumn,
|
|
118
124
|
onRetrySend,
|
|
119
125
|
onRetryExecution,
|
|
120
126
|
onEditMessage,
|
|
@@ -148,13 +154,15 @@ export function VirtualizedThread({
|
|
|
148
154
|
submittingApprovalIds,
|
|
149
155
|
approvalErrors,
|
|
150
156
|
onBuildFromPlan,
|
|
157
|
+
onOpenPlan,
|
|
151
158
|
org,
|
|
152
159
|
planActionsDisabled,
|
|
160
|
+
planBuildPending,
|
|
153
161
|
onRetrySend,
|
|
154
162
|
onRetryExecution,
|
|
155
163
|
onEditMessage,
|
|
156
164
|
}),
|
|
157
|
-
[formatToolCallSummary, onApprovalSubmit, submittingApprovalIds, approvalErrors, onBuildFromPlan, org, planActionsDisabled, onRetrySend, onRetryExecution, onEditMessage],
|
|
165
|
+
[formatToolCallSummary, onApprovalSubmit, submittingApprovalIds, approvalErrors, onBuildFromPlan, onOpenPlan, org, planActionsDisabled, planBuildPending, onRetrySend, onRetryExecution, onEditMessage],
|
|
158
166
|
);
|
|
159
167
|
|
|
160
168
|
return (
|
|
@@ -177,7 +185,7 @@ export function VirtualizedThread({
|
|
|
177
185
|
className="h-full"
|
|
178
186
|
components={{ Scroller: ScrollerWithA11y }}
|
|
179
187
|
itemContent={(index, item) => (
|
|
180
|
-
<div className={cn("pb-4 pt-0 first:pt-6",
|
|
188
|
+
<div className={cn("pb-4 pt-0 first:pt-6", threadContentColumnClass(contentColumn))}>
|
|
181
189
|
<ThreadItemWrapper animate={index >= items.length - 2}>
|
|
182
190
|
<ThreadItemRenderer
|
|
183
191
|
item={item}
|
|
@@ -72,6 +72,67 @@ describe("ResizableSplit", () => {
|
|
|
72
72
|
});
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
describe("collapsedPane", () => {
|
|
76
|
+
/** The pane wrapper div for a rendered probe. */
|
|
77
|
+
function paneOf(testId: string): HTMLElement {
|
|
78
|
+
return screen.getByTestId(testId).parentElement as HTMLElement;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
it("hides the collapsed pane and the separator; the sibling flexes", () => {
|
|
82
|
+
renderSplit({ collapsedPane: "secondary" });
|
|
83
|
+
expect(paneOf("secondary").className).toContain("hidden");
|
|
84
|
+
expect(paneOf("primary").className).toContain("flex-1");
|
|
85
|
+
const separator = screen.getByRole("separator", { hidden: true });
|
|
86
|
+
expect(separator.className).toContain("hidden");
|
|
87
|
+
expect(separator.getAttribute("tabindex")).toBe("-1");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("overrides the resizable pane's fixed width while collapsed", () => {
|
|
91
|
+
renderSplit({ resizablePane: "primary", collapsedPane: "secondary" });
|
|
92
|
+
// Primary is normally pixel-sized; with its sibling collapsed it flexes.
|
|
93
|
+
expect(paneOf("primary").style.width).toBe("");
|
|
94
|
+
expect(paneOf("primary").className).toContain("flex-1");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("keeps both children mounted (same DOM nodes) across a collapse toggle", () => {
|
|
98
|
+
const { rerender } = render(
|
|
99
|
+
<ResizableSplit
|
|
100
|
+
resizablePane="primary"
|
|
101
|
+
collapsedPane="secondary"
|
|
102
|
+
primary={<div data-testid="primary">Primary</div>}
|
|
103
|
+
secondary={<div data-testid="secondary">Secondary</div>}
|
|
104
|
+
/>,
|
|
105
|
+
);
|
|
106
|
+
const primaryBefore = screen.getByTestId("primary");
|
|
107
|
+
const secondaryBefore = screen.getByTestId("secondary");
|
|
108
|
+
rerender(
|
|
109
|
+
<ResizableSplit
|
|
110
|
+
resizablePane="primary"
|
|
111
|
+
collapsedPane="none"
|
|
112
|
+
primary={<div data-testid="primary">Primary</div>}
|
|
113
|
+
secondary={<div data-testid="secondary">Secondary</div>}
|
|
114
|
+
/>,
|
|
115
|
+
);
|
|
116
|
+
// Identical node references — expanding never remounted either pane.
|
|
117
|
+
expect(screen.getByTestId("primary")).toBe(primaryBefore);
|
|
118
|
+
expect(screen.getByTestId("secondary")).toBe(secondaryBefore);
|
|
119
|
+
expect(paneOf("primary").style.width).toBe("384px");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("restores the persisted width when expanding after a collapse", () => {
|
|
123
|
+
localStorage.setItem("collapse-key", "451");
|
|
124
|
+
renderSplit({
|
|
125
|
+
resizablePane: "primary",
|
|
126
|
+
collapsedPane: "secondary",
|
|
127
|
+
storageKey: "collapse-key",
|
|
128
|
+
minSize: 300,
|
|
129
|
+
maxSize: 600,
|
|
130
|
+
});
|
|
131
|
+
const separator = screen.getByRole("separator", { hidden: true });
|
|
132
|
+
expect(separator.getAttribute("aria-valuenow")).toBe("451");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
75
136
|
describe("keyboard interaction", () => {
|
|
76
137
|
it("increases panel width on ArrowLeft", () => {
|
|
77
138
|
renderSplit({ defaultSize: 400 });
|
|
@@ -145,11 +206,72 @@ describe("ResizableSplit", () => {
|
|
|
145
206
|
expect(separator.getAttribute("tabindex")).toBe("0");
|
|
146
207
|
});
|
|
147
208
|
|
|
148
|
-
it("has accessible label", () => {
|
|
209
|
+
it("has a default accessible label", () => {
|
|
149
210
|
renderSplit();
|
|
150
211
|
const separator = screen.getByRole("separator");
|
|
151
|
-
expect(separator.getAttribute("aria-label")).toBe(
|
|
152
|
-
|
|
212
|
+
expect(separator.getAttribute("aria-label")).toBe("Resize panel");
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("uses a custom accessible label", () => {
|
|
216
|
+
renderSplit({ ariaLabel: "Resize file explorer" });
|
|
217
|
+
const separator = screen.getByRole("separator");
|
|
218
|
+
expect(separator.getAttribute("aria-label")).toBe("Resize file explorer");
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("resizablePane", () => {
|
|
223
|
+
it("grows a primary pane on ArrowRight (toward its own side)", () => {
|
|
224
|
+
renderSplit({ resizablePane: "primary", defaultSize: 400 });
|
|
225
|
+
const separator = screen.getByRole("separator");
|
|
226
|
+
|
|
227
|
+
fireEvent.keyDown(separator, { key: "ArrowRight" });
|
|
228
|
+
|
|
229
|
+
expect(separator.getAttribute("aria-valuenow")).toBe("420");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("shrinks a primary pane on ArrowLeft", () => {
|
|
233
|
+
renderSplit({ resizablePane: "primary", defaultSize: 400 });
|
|
234
|
+
const separator = screen.getByRole("separator");
|
|
235
|
+
|
|
236
|
+
fireEvent.keyDown(separator, { key: "ArrowLeft" });
|
|
237
|
+
|
|
238
|
+
expect(separator.getAttribute("aria-valuenow")).toBe("380");
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe("width re-initialization on key change", () => {
|
|
243
|
+
it("reloads the width from the new storageKey without remounting", () => {
|
|
244
|
+
localStorage.setItem("key-a", "300");
|
|
245
|
+
localStorage.setItem("key-b", "520");
|
|
246
|
+
const { rerender } = render(
|
|
247
|
+
<ResizableSplit
|
|
248
|
+
primary={<div data-testid="primary">Primary</div>}
|
|
249
|
+
secondary={<div data-testid="secondary">Secondary</div>}
|
|
250
|
+
storageKey="key-a"
|
|
251
|
+
minSize={200}
|
|
252
|
+
maxSize={600}
|
|
253
|
+
/>,
|
|
254
|
+
);
|
|
255
|
+
const primary = screen.getByTestId("primary");
|
|
256
|
+
expect(screen.getByRole("separator").getAttribute("aria-valuenow")).toBe(
|
|
257
|
+
"300",
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
rerender(
|
|
261
|
+
<ResizableSplit
|
|
262
|
+
primary={<div data-testid="primary">Primary</div>}
|
|
263
|
+
secondary={<div data-testid="secondary">Secondary</div>}
|
|
264
|
+
storageKey="key-b"
|
|
265
|
+
resizablePane="primary"
|
|
266
|
+
minSize={200}
|
|
267
|
+
maxSize={600}
|
|
268
|
+
/>,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// Same DOM node — the child was re-flowed, not remounted.
|
|
272
|
+
expect(screen.getByTestId("primary")).toBe(primary);
|
|
273
|
+
expect(screen.getByRole("separator").getAttribute("aria-valuenow")).toBe(
|
|
274
|
+
"520",
|
|
153
275
|
);
|
|
154
276
|
});
|
|
155
277
|
});
|
|
@@ -3,6 +3,7 @@ import { render, cleanup } from "@testing-library/react";
|
|
|
3
3
|
import type { ComponentType, ReactNode } from "react";
|
|
4
4
|
import {
|
|
5
5
|
MARKDOWN_COMPONENTS,
|
|
6
|
+
extractLeadingH1,
|
|
6
7
|
unwrapEnclosingMarkdownFence,
|
|
7
8
|
} from "../markdown-components";
|
|
8
9
|
|
|
@@ -63,6 +64,73 @@ describe("unwrapEnclosingMarkdownFence", () => {
|
|
|
63
64
|
const once = unwrapEnclosingMarkdownFence(wrapped);
|
|
64
65
|
expect(unwrapEnclosingMarkdownFence(once)).toBe(once);
|
|
65
66
|
});
|
|
67
|
+
|
|
68
|
+
describe("allowBareFence (plan-document surfaces)", () => {
|
|
69
|
+
it.each([
|
|
70
|
+
["a bare whole-body fence", "```\n# Plan\n- step\n```", "# Plan\n- step"],
|
|
71
|
+
[
|
|
72
|
+
"a bare fence with surrounding whitespace",
|
|
73
|
+
"\n```\n# Plan\n```\n",
|
|
74
|
+
"# Plan",
|
|
75
|
+
],
|
|
76
|
+
[
|
|
77
|
+
"still unwraps the tagged form",
|
|
78
|
+
"```markdown\n# Plan\n```",
|
|
79
|
+
"# Plan",
|
|
80
|
+
],
|
|
81
|
+
])("unwraps %s", (_label, input, expected) => {
|
|
82
|
+
expect(unwrapEnclosingMarkdownFence(input, true)).toBe(expected);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it.each([
|
|
86
|
+
["a language-tagged code block", "```python\nprint('hi')\n```"],
|
|
87
|
+
["an unclosed bare fence (mid-stream)", "```\n# Plan in progr"],
|
|
88
|
+
["trailing content after the fence", "```\n# Plan\n```\nthen more"],
|
|
89
|
+
["leading content before the fence", "intro\n```\n# Plan\n```"],
|
|
90
|
+
["plain markdown (no fence)", "# Plan\n\n- step"],
|
|
91
|
+
])("leaves %s untouched even with allowBareFence", (_label, input) => {
|
|
92
|
+
expect(unwrapEnclosingMarkdownFence(input, true)).toBe(input);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe("extractLeadingH1", () => {
|
|
98
|
+
it("splits a leading # heading into title and body", () => {
|
|
99
|
+
expect(extractLeadingH1("# The Plan\n\nFirst paragraph.")).toEqual({
|
|
100
|
+
title: "The Plan",
|
|
101
|
+
body: "First paragraph.",
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("handles a document that is only a heading", () => {
|
|
106
|
+
expect(extractLeadingH1("# Just a Title")).toEqual({
|
|
107
|
+
title: "Just a Title",
|
|
108
|
+
body: "",
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("ignores leading whitespace before the heading", () => {
|
|
113
|
+
expect(extractLeadingH1("\n\n# The Plan\nBody")).toEqual({
|
|
114
|
+
title: "The Plan",
|
|
115
|
+
body: "Body",
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("returns null title when the document does not open with an H1", () => {
|
|
120
|
+
const doc = "Intro paragraph.\n\n# Later Heading\nBody";
|
|
121
|
+
expect(extractLeadingH1(doc)).toEqual({ title: null, body: doc });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("does not treat deeper headings as the title", () => {
|
|
125
|
+
const doc = "## Section\nBody";
|
|
126
|
+
expect(extractLeadingH1(doc)).toEqual({ title: null, body: doc });
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("trims trailing whitespace from the title", () => {
|
|
130
|
+
expect(extractLeadingH1("# Spaced Title \nBody").title).toBe(
|
|
131
|
+
"Spaced Title",
|
|
132
|
+
);
|
|
133
|
+
});
|
|
66
134
|
});
|
|
67
135
|
|
|
68
136
|
describe("MARKDOWN_COMPONENTS.code (shared highlight seam)", () => {
|