@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
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
5
|
+
import type { SurfaceRailView } from "../workspace/WorkspaceSurface.js";
|
|
6
|
+
import type { SelectedThreadItem } from "../internal/store/selection-store.js";
|
|
7
|
+
import type { ApplyResourceResult } from "../library/useApplyResource.js";
|
|
8
|
+
import { useSessionWriteBacks } from "./useSessionWriteBacks.js";
|
|
9
|
+
import { useSessionArtifacts } from "./useSessionArtifacts.js";
|
|
10
|
+
import { SetupTab, type SetupTabProps } from "./facets/SetupTab.js";
|
|
11
|
+
import { ChangesTab } from "./facets/ChangesTab.js";
|
|
12
|
+
import { ArtifactsTab } from "./facets/ArtifactsTab.js";
|
|
13
|
+
import { UsageTab } from "./facets/UsageTab.js";
|
|
14
|
+
import { InspectTab } from "./facets/InspectTab.js";
|
|
15
|
+
|
|
16
|
+
/** Options for {@link useSessionRailViews}. */
|
|
17
|
+
export interface UseSessionRailViewsOptions {
|
|
18
|
+
/** All executions in the session — drives Changes/Artifacts/Usage. */
|
|
19
|
+
readonly allExecutions: readonly AgentExecution[];
|
|
20
|
+
/** Organization slug for artifact Apply CTA. */
|
|
21
|
+
readonly org: string;
|
|
22
|
+
/** Session configuration for the Config facet. */
|
|
23
|
+
readonly sessionConfig: SetupTabProps | undefined;
|
|
24
|
+
/** Currently selected thread item — surfaces the Inspect facet. */
|
|
25
|
+
readonly selectedItem: SelectedThreadItem | null;
|
|
26
|
+
/** Called after a resource is applied from the Artifacts facet. */
|
|
27
|
+
readonly onApplied?: (result: ApplyResourceResult) => void;
|
|
28
|
+
/** Implement a plan — the Artifacts facet's preview action for `plan.md`. */
|
|
29
|
+
readonly onImplementPlan?: () => void;
|
|
30
|
+
/**
|
|
31
|
+
* Open a plan in the panel's plan document tab. Routed to the Artifacts
|
|
32
|
+
* facet so clicking `plan.md` there opens the editor-area document instead
|
|
33
|
+
* of the preview modal.
|
|
34
|
+
*/
|
|
35
|
+
readonly onOpenPlan?: (executionId: string) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to offer the execution-derived facets (Changes / Artifacts /
|
|
38
|
+
* Usage). The launcher passes `false` — before a session exists there are no
|
|
39
|
+
* executions to aggregate, so only Config applies.
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
readonly includeExecutionFacets?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Composes the session facets (Config / Changes / Artifacts / Usage / Inspect)
|
|
47
|
+
* as {@link SurfaceRailView}s for the workspace surface's activity rail.
|
|
48
|
+
*
|
|
49
|
+
* This is the session-domain half of the unified panel: the surface stays a
|
|
50
|
+
* domain-pure workspace organism and these views are injected into its rail
|
|
51
|
+
* (DD-004 composition). Contextual visibility mirrors the retired inspector's
|
|
52
|
+
* tab rules — Changes/Artifacts surface only when data exists (with count
|
|
53
|
+
* badges), Inspect only when a thread item is selected.
|
|
54
|
+
*/
|
|
55
|
+
export function useSessionRailViews({
|
|
56
|
+
allExecutions,
|
|
57
|
+
org,
|
|
58
|
+
sessionConfig,
|
|
59
|
+
selectedItem,
|
|
60
|
+
onApplied,
|
|
61
|
+
onImplementPlan,
|
|
62
|
+
onOpenPlan,
|
|
63
|
+
includeExecutionFacets = true,
|
|
64
|
+
}: UseSessionRailViewsOptions): readonly SurfaceRailView[] {
|
|
65
|
+
const { hasWriteBacks, writeBackCount } = useSessionWriteBacks(allExecutions);
|
|
66
|
+
const { hasArtifacts, artifactCount } = useSessionArtifacts(allExecutions);
|
|
67
|
+
|
|
68
|
+
return useMemo(() => {
|
|
69
|
+
const views: SurfaceRailView[] = [];
|
|
70
|
+
|
|
71
|
+
if (sessionConfig) {
|
|
72
|
+
views.push({
|
|
73
|
+
id: "configure",
|
|
74
|
+
label: "Config",
|
|
75
|
+
icon: <GearIcon />,
|
|
76
|
+
content: <SetupTab {...sessionConfig} />,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (includeExecutionFacets) {
|
|
81
|
+
if (hasWriteBacks) {
|
|
82
|
+
views.push({
|
|
83
|
+
id: "changes",
|
|
84
|
+
label: "Changes",
|
|
85
|
+
icon: <ChangesIcon />,
|
|
86
|
+
badge: writeBackCount,
|
|
87
|
+
content: <ChangesTab executions={allExecutions} />,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (hasArtifacts) {
|
|
92
|
+
views.push({
|
|
93
|
+
id: "artifacts",
|
|
94
|
+
label: "Artifacts",
|
|
95
|
+
icon: <ArtifactsIcon />,
|
|
96
|
+
badge: artifactCount,
|
|
97
|
+
content: (
|
|
98
|
+
<ArtifactsTab
|
|
99
|
+
executions={allExecutions}
|
|
100
|
+
org={org}
|
|
101
|
+
onApplied={onApplied}
|
|
102
|
+
onImplementPlan={onImplementPlan}
|
|
103
|
+
onOpenPlan={onOpenPlan}
|
|
104
|
+
/>
|
|
105
|
+
),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
views.push({
|
|
110
|
+
id: "usage",
|
|
111
|
+
label: "Usage",
|
|
112
|
+
icon: <UsageIcon />,
|
|
113
|
+
content: <UsageTab executions={allExecutions} />,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (selectedItem) {
|
|
118
|
+
views.push({
|
|
119
|
+
id: "inspect",
|
|
120
|
+
label: "Inspect",
|
|
121
|
+
icon: <InspectIcon />,
|
|
122
|
+
content: <InspectTab selectedItem={selectedItem} />,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return views;
|
|
127
|
+
}, [
|
|
128
|
+
sessionConfig,
|
|
129
|
+
includeExecutionFacets,
|
|
130
|
+
hasWriteBacks,
|
|
131
|
+
writeBackCount,
|
|
132
|
+
hasArtifacts,
|
|
133
|
+
artifactCount,
|
|
134
|
+
allExecutions,
|
|
135
|
+
org,
|
|
136
|
+
onApplied,
|
|
137
|
+
onImplementPlan,
|
|
138
|
+
onOpenPlan,
|
|
139
|
+
selectedItem,
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// Inline SVG icons — monochrome, `currentColor`-tinted (DD-005; SDK
|
|
145
|
+
// independence — no lucide dependency)
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
function GearIcon() {
|
|
149
|
+
return (
|
|
150
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
151
|
+
<circle cx="12" cy="12" r="3" />
|
|
152
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h.01a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v.01a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
153
|
+
</svg>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Source-control style branch glyph — the session's git write-backs. */
|
|
158
|
+
function ChangesIcon() {
|
|
159
|
+
return (
|
|
160
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
161
|
+
<circle cx="6" cy="6" r="2.5" />
|
|
162
|
+
<circle cx="6" cy="18" r="2.5" />
|
|
163
|
+
<circle cx="18" cy="8" r="2.5" />
|
|
164
|
+
<path d="M6 8.5v7" />
|
|
165
|
+
<path d="M18 10.5a7 7 0 0 1-7 5H8.5" />
|
|
166
|
+
</svg>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function ArtifactsIcon() {
|
|
171
|
+
return (
|
|
172
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
173
|
+
<path d="M21 8l-9-5-9 5v8l9 5 9-5z" />
|
|
174
|
+
<path d="M3 8l9 5 9-5" />
|
|
175
|
+
<path d="M12 13v9" />
|
|
176
|
+
</svg>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function UsageIcon() {
|
|
181
|
+
return (
|
|
182
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
183
|
+
<path d="M3 20h18" />
|
|
184
|
+
<path d="M6 20v-6" />
|
|
185
|
+
<path d="M11 20V9" />
|
|
186
|
+
<path d="M16 20v-9" />
|
|
187
|
+
<path d="M21 20V5" />
|
|
188
|
+
</svg>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Crosshair glyph — inspecting a selected thread item. */
|
|
193
|
+
function InspectIcon() {
|
|
194
|
+
return (
|
|
195
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
196
|
+
<circle cx="12" cy="12" r="7" />
|
|
197
|
+
<path d="M12 2v4M12 18v4M2 12h4M18 12h4" />
|
|
198
|
+
</svg>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
@@ -26,7 +26,7 @@ import { useFollowExecution, computeFollowSelection } from "./useFollowExecution
|
|
|
26
26
|
import { useActiveTaskName } from "./useActiveTaskName.js";
|
|
27
27
|
import { useExecutionAnnouncements } from "./useExecutionAnnouncements.js";
|
|
28
28
|
import { ExecutionActiveTaskIndicator } from "./ExecutionActiveTaskIndicator.js";
|
|
29
|
-
import { getAnimationDuration } from "
|
|
29
|
+
import { getAnimationDuration } from "../internal/motion-preference.js";
|
|
30
30
|
|
|
31
31
|
/** Props for {@link WorkflowExecutionGraph}. */
|
|
32
32
|
export interface WorkflowExecutionGraphProps {
|
package/src/workflow/index.ts
CHANGED
|
@@ -531,7 +531,7 @@ export {
|
|
|
531
531
|
type ExecutionActiveTaskIndicatorProps,
|
|
532
532
|
} from "./ExecutionActiveTaskIndicator.js";
|
|
533
533
|
export { useExecutionAnnouncements } from "./useExecutionAnnouncements.js";
|
|
534
|
-
export { getAnimationDuration, prefersReducedMotion } from "
|
|
534
|
+
export { getAnimationDuration, prefersReducedMotion } from "../internal/motion-preference.js";
|
|
535
535
|
|
|
536
536
|
// T05: Shared formatting utilities
|
|
537
537
|
export {
|
|
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
4
4
|
import type { Node, Viewport } from "@xyflow/react";
|
|
5
5
|
import { useReactFlow } from "@xyflow/react";
|
|
6
6
|
import type { CanvasTaskNodeData } from "./workflow-graph-conversions.js";
|
|
7
|
-
import { getAnimationDuration } from "
|
|
7
|
+
import { getAnimationDuration } from "../internal/motion-preference.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Follow-execution state machine states.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, type KeyboardEvent, type MouseEvent } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { editorKey, type OpenEditor } from "../internal/store/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Deterministic, space-free DOM id for a tab, built from an instance-scoped
|
|
9
|
+
* `prefix` (a `useId()` value) and the editor `key`. Shared by the tab (its
|
|
10
|
+
* `id`) and the editor body (its `aria-labelledby`) so the two associate; the
|
|
11
|
+
* key is percent-encoded because editor keys embed file paths that may contain
|
|
12
|
+
* characters (spaces) illegal in a space-separated IDREF.
|
|
13
|
+
*/
|
|
14
|
+
export function editorTabDomId(prefix: string, key: string): string {
|
|
15
|
+
return `${prefix}${encodeURIComponent(key)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Props for {@link EditorTabs}. */
|
|
19
|
+
export interface EditorTabsProps {
|
|
20
|
+
/** Open editors in tab order. */
|
|
21
|
+
readonly editors: readonly OpenEditor[];
|
|
22
|
+
/** Key of the active editor (`editorKey(entryId, path)`), or `null`. */
|
|
23
|
+
readonly activeKey: string | null;
|
|
24
|
+
/** Focus an open editor (single click). */
|
|
25
|
+
readonly onActivate: (entryId: string, path: string) => void;
|
|
26
|
+
/** Pin an editor (double-click) so it stops being the reusable preview tab. */
|
|
27
|
+
readonly onPin: (entryId: string, path: string) => void;
|
|
28
|
+
/** Close an editor (close button or middle click). */
|
|
29
|
+
readonly onClose: (entryId: string, path: string) => void;
|
|
30
|
+
/**
|
|
31
|
+
* DOM id of the editor body (`role="tabpanel"`). When provided together with
|
|
32
|
+
* {@link tabIdPrefix}, each tab gets a stable `id` and `aria-controls` linking
|
|
33
|
+
* it to that panel. Optional so the strip degrades gracefully without a panel.
|
|
34
|
+
*/
|
|
35
|
+
readonly panelId?: string;
|
|
36
|
+
/** Instance-scoped prefix for per-tab ids (see {@link editorTabDomId}). */
|
|
37
|
+
readonly tabIdPrefix?: string;
|
|
38
|
+
/** Additional CSS classes for the root element. */
|
|
39
|
+
readonly className?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The editor group's tab strip, following VS Code preview-tab semantics:
|
|
44
|
+
* a single-click preview tab renders in italics and is reused as the user
|
|
45
|
+
* browses; double-clicking a tab pins it (persistent). Each tab has a close
|
|
46
|
+
* control, also reachable by middle-click.
|
|
47
|
+
*
|
|
48
|
+
* A `role="tablist"` of `role="tab"` items; the matching `tabpanel` is the
|
|
49
|
+
* editor body rendered by the surface. Arrow keys move focus between tabs and
|
|
50
|
+
* activate; Delete/Backspace closes the focused tab. The visual close "X" is a
|
|
51
|
+
* presentational (`aria-hidden`) mouse affordance — assistive tech closes via
|
|
52
|
+
* the keyboard, so the X is not a nested interactive control (WCAG 4.1.2). All
|
|
53
|
+
* visual properties flow through `--stgm-*` tokens (DD-005).
|
|
54
|
+
*/
|
|
55
|
+
export function EditorTabs({
|
|
56
|
+
editors,
|
|
57
|
+
activeKey,
|
|
58
|
+
onActivate,
|
|
59
|
+
onPin,
|
|
60
|
+
onClose,
|
|
61
|
+
panelId,
|
|
62
|
+
tabIdPrefix,
|
|
63
|
+
className,
|
|
64
|
+
}: EditorTabsProps) {
|
|
65
|
+
const move = useCallback(
|
|
66
|
+
(from: number, delta: number) => {
|
|
67
|
+
const next = from + delta;
|
|
68
|
+
if (next < 0 || next >= editors.length) return;
|
|
69
|
+
const editor = editors[next];
|
|
70
|
+
onActivate(editor.entryId, editor.path);
|
|
71
|
+
},
|
|
72
|
+
[editors, onActivate],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div
|
|
77
|
+
role="tablist"
|
|
78
|
+
aria-label="Open editors"
|
|
79
|
+
aria-orientation="horizontal"
|
|
80
|
+
className={cn(
|
|
81
|
+
"flex shrink-0 items-stretch overflow-x-auto border-b border-border",
|
|
82
|
+
className,
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
85
|
+
{editors.map((editor, index) => {
|
|
86
|
+
const key = editorKey(editor.entryId, editor.path);
|
|
87
|
+
const isActive = key === activeKey;
|
|
88
|
+
const lastSlash = editor.path.lastIndexOf("/");
|
|
89
|
+
const basename =
|
|
90
|
+
lastSlash >= 0 ? editor.path.slice(lastSlash + 1) : editor.path;
|
|
91
|
+
|
|
92
|
+
const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
93
|
+
if (e.key === "ArrowRight") {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
move(index, 1);
|
|
96
|
+
} else if (e.key === "ArrowLeft") {
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
move(index, -1);
|
|
99
|
+
} else if (e.key === "Enter" || e.key === " ") {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
onActivate(editor.entryId, editor.path);
|
|
102
|
+
} else if (e.key === "Delete" || e.key === "Backspace") {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
onClose(editor.entryId, editor.path);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const handleAuxClick = (e: MouseEvent<HTMLDivElement>) => {
|
|
109
|
+
// Middle click closes, matching browser/editor tab conventions.
|
|
110
|
+
if (e.button === 1) {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
onClose(editor.entryId, editor.path);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div
|
|
118
|
+
key={key}
|
|
119
|
+
role="tab"
|
|
120
|
+
id={tabIdPrefix ? editorTabDomId(tabIdPrefix, key) : undefined}
|
|
121
|
+
aria-selected={isActive}
|
|
122
|
+
aria-controls={panelId}
|
|
123
|
+
tabIndex={isActive ? 0 : -1}
|
|
124
|
+
title={editor.path}
|
|
125
|
+
onClick={() => onActivate(editor.entryId, editor.path)}
|
|
126
|
+
onDoubleClick={() => onPin(editor.entryId, editor.path)}
|
|
127
|
+
onAuxClick={handleAuxClick}
|
|
128
|
+
onKeyDown={handleKeyDown}
|
|
129
|
+
className={cn(
|
|
130
|
+
"group flex max-w-[12rem] shrink-0 cursor-pointer items-center gap-1.5 border-r border-border px-3 py-1.5 text-xs transition-colors",
|
|
131
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
132
|
+
isActive
|
|
133
|
+
? "bg-background text-foreground"
|
|
134
|
+
: "bg-muted-faint text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
135
|
+
)}
|
|
136
|
+
>
|
|
137
|
+
<span className={cn("truncate", editor.preview && "italic")}>
|
|
138
|
+
{basename}
|
|
139
|
+
</span>
|
|
140
|
+
{/* The visual close "X" is a presentational mouse affordance, NOT a
|
|
141
|
+
nested interactive control: a `<button>` inside `role="tab"` would
|
|
142
|
+
violate WCAG 4.1.2 (axe `nested-interactive`). Assistive tech and
|
|
143
|
+
keyboard users close the focused tab via Delete/Backspace (handled
|
|
144
|
+
above), so `aria-hidden` here removes the redundant nested control
|
|
145
|
+
without losing the close action for anyone. */}
|
|
146
|
+
<span
|
|
147
|
+
aria-hidden="true"
|
|
148
|
+
title={`Close ${basename}`}
|
|
149
|
+
onClick={(e) => {
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
onClose(editor.entryId, editor.path);
|
|
152
|
+
}}
|
|
153
|
+
className={cn(
|
|
154
|
+
"shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground transition-opacity hover:bg-accent-hover hover:text-foreground",
|
|
155
|
+
isActive ? "opacity-100" : "opacity-0 group-hover:opacity-100",
|
|
156
|
+
)}
|
|
157
|
+
>
|
|
158
|
+
<CloseIcon />
|
|
159
|
+
</span>
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
})}
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function CloseIcon() {
|
|
168
|
+
return (
|
|
169
|
+
<svg width="12" height="12" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
170
|
+
<path d="M3.5 3.5L10.5 10.5" />
|
|
171
|
+
<path d="M10.5 3.5L3.5 10.5" />
|
|
172
|
+
</svg>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { FileTreeNode } from "../internal/file-tree/index.js";
|
|
6
|
+
import type { SelectedWorkspaceFile } from "../internal/store/index.js";
|
|
7
|
+
import { useWorkspaceFiles } from "./useWorkspaceFiles.js";
|
|
8
|
+
import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
|
|
9
|
+
import type { WorkspaceFileLister } from "./WorkspaceFileLister.js";
|
|
10
|
+
|
|
11
|
+
/** Props for {@link ExplorerTree}. */
|
|
12
|
+
export interface ExplorerTreeProps {
|
|
13
|
+
/** Workspace entries, each rendered as a collapsible root (multi-root). */
|
|
14
|
+
readonly entries: readonly WorkspaceEntry[];
|
|
15
|
+
/** Platform-injected file lister. */
|
|
16
|
+
readonly lister: WorkspaceFileLister;
|
|
17
|
+
/** The active file, highlighted in the tree. */
|
|
18
|
+
readonly selectedFile: SelectedWorkspaceFile | null;
|
|
19
|
+
/** Single click: open as a preview tab. */
|
|
20
|
+
readonly onOpenFile: (entryId: string, path: string) => void;
|
|
21
|
+
/** Double click: pin the file (persistent tab). */
|
|
22
|
+
readonly onActivateFile: (entryId: string, path: string) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Detach a workspace entry. When provided, each root header carries a remove
|
|
25
|
+
* control (VS Code's "Remove Folder from Workspace"); when absent the
|
|
26
|
+
* explorer is browse-only.
|
|
27
|
+
*/
|
|
28
|
+
readonly onRemoveEntry?: (entryId: string) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The workspace surface's multi-root file explorer — the bare, VS Code-style
|
|
33
|
+
* tree: file-type icons, indent guides, single-click preview / double-click
|
|
34
|
+
* pin, optional per-root remove controls. Search lives in the surface's rail,
|
|
35
|
+
* not per root; listings come from the shared `useWorkspaceFiles` cache.
|
|
36
|
+
*
|
|
37
|
+
* All visual properties flow through `--stgm-*` tokens (DD-005).
|
|
38
|
+
*/
|
|
39
|
+
export function ExplorerTree({
|
|
40
|
+
entries,
|
|
41
|
+
lister,
|
|
42
|
+
selectedFile,
|
|
43
|
+
onOpenFile,
|
|
44
|
+
onActivateFile,
|
|
45
|
+
onRemoveEntry,
|
|
46
|
+
}: ExplorerTreeProps) {
|
|
47
|
+
return (
|
|
48
|
+
<div className="flex flex-col">
|
|
49
|
+
{entries.map((entry, index) => (
|
|
50
|
+
<ExplorerRoot
|
|
51
|
+
key={entry.id}
|
|
52
|
+
entry={entry}
|
|
53
|
+
lister={lister}
|
|
54
|
+
defaultExpanded={index === 0}
|
|
55
|
+
selectedPath={
|
|
56
|
+
selectedFile?.entryId === entry.id ? selectedFile.path : undefined
|
|
57
|
+
}
|
|
58
|
+
onOpenFile={onOpenFile}
|
|
59
|
+
onActivateFile={onActivateFile}
|
|
60
|
+
onRemove={onRemoveEntry}
|
|
61
|
+
/>
|
|
62
|
+
))}
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** One workspace root: a collapsible header over its file tree. */
|
|
68
|
+
function ExplorerRoot({
|
|
69
|
+
entry,
|
|
70
|
+
lister,
|
|
71
|
+
defaultExpanded,
|
|
72
|
+
selectedPath,
|
|
73
|
+
onOpenFile,
|
|
74
|
+
onActivateFile,
|
|
75
|
+
onRemove,
|
|
76
|
+
}: {
|
|
77
|
+
readonly entry: WorkspaceEntry;
|
|
78
|
+
readonly lister: WorkspaceFileLister;
|
|
79
|
+
readonly defaultExpanded: boolean;
|
|
80
|
+
readonly selectedPath: string | undefined;
|
|
81
|
+
readonly onOpenFile: (entryId: string, path: string) => void;
|
|
82
|
+
readonly onActivateFile: (entryId: string, path: string) => void;
|
|
83
|
+
readonly onRemove?: (entryId: string) => void;
|
|
84
|
+
}) {
|
|
85
|
+
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
86
|
+
const { tree, isLoading, error, truncated, refresh } = useWorkspaceFiles({
|
|
87
|
+
entry: expanded ? entry : null,
|
|
88
|
+
lister,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div className="flex flex-col">
|
|
93
|
+
<div className="group/root flex items-stretch">
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
onClick={() => setExpanded((prev) => !prev)}
|
|
97
|
+
aria-expanded={expanded}
|
|
98
|
+
className={cn(
|
|
99
|
+
"flex min-w-0 flex-1 items-center gap-1.5 px-1.5 py-1 text-left text-[0.7rem] font-semibold uppercase tracking-wide text-foreground transition-colors hover:bg-accent-hover",
|
|
100
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
101
|
+
)}
|
|
102
|
+
title={entry.type === "local" ? entry.localPath : entry.gitUrl}
|
|
103
|
+
>
|
|
104
|
+
<span
|
|
105
|
+
aria-hidden="true"
|
|
106
|
+
className="text-[10px] text-muted-foreground-subtle"
|
|
107
|
+
>
|
|
108
|
+
{expanded ? "▼" : "▶"}
|
|
109
|
+
</span>
|
|
110
|
+
<span className="truncate">{entry.name}</span>
|
|
111
|
+
</button>
|
|
112
|
+
{onRemove && (
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
onClick={() => onRemove(entry.id)}
|
|
116
|
+
aria-label={`Remove ${entry.name} from workspace`}
|
|
117
|
+
title={`Remove ${entry.name} from workspace`}
|
|
118
|
+
className={cn(
|
|
119
|
+
"shrink-0 px-1.5 text-muted-foreground opacity-0 transition-opacity",
|
|
120
|
+
"group-hover/root:opacity-100 focus-visible:opacity-100",
|
|
121
|
+
"hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
<RemoveIcon />
|
|
125
|
+
</button>
|
|
126
|
+
)}
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
{expanded && (
|
|
130
|
+
<ExplorerRootBody
|
|
131
|
+
entryName={entry.name}
|
|
132
|
+
entryId={entry.id}
|
|
133
|
+
tree={tree}
|
|
134
|
+
isLoading={isLoading}
|
|
135
|
+
error={error}
|
|
136
|
+
truncated={truncated}
|
|
137
|
+
selectedPath={selectedPath}
|
|
138
|
+
onOpenFile={onOpenFile}
|
|
139
|
+
onActivateFile={onActivateFile}
|
|
140
|
+
onRetry={refresh}
|
|
141
|
+
/>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function ExplorerRootBody({
|
|
148
|
+
entryName,
|
|
149
|
+
entryId,
|
|
150
|
+
tree,
|
|
151
|
+
isLoading,
|
|
152
|
+
error,
|
|
153
|
+
truncated,
|
|
154
|
+
selectedPath,
|
|
155
|
+
onOpenFile,
|
|
156
|
+
onActivateFile,
|
|
157
|
+
onRetry,
|
|
158
|
+
}: {
|
|
159
|
+
readonly entryName: string;
|
|
160
|
+
readonly entryId: string;
|
|
161
|
+
readonly tree: ReturnType<typeof useWorkspaceFiles>["tree"];
|
|
162
|
+
readonly isLoading: boolean;
|
|
163
|
+
readonly error: Error | null;
|
|
164
|
+
readonly truncated: boolean;
|
|
165
|
+
readonly selectedPath: string | undefined;
|
|
166
|
+
readonly onOpenFile: (entryId: string, path: string) => void;
|
|
167
|
+
readonly onActivateFile: (entryId: string, path: string) => void;
|
|
168
|
+
readonly onRetry: () => void;
|
|
169
|
+
}) {
|
|
170
|
+
if (isLoading) {
|
|
171
|
+
return (
|
|
172
|
+
<div
|
|
173
|
+
// role="status" both announces the loading state to assistive tech and
|
|
174
|
+
// makes aria-label permitted here (a role-less generic div cannot carry
|
|
175
|
+
// an accessible name — axe `aria-prohibited-attr`).
|
|
176
|
+
role="status"
|
|
177
|
+
className="space-y-1.5 px-2 py-2"
|
|
178
|
+
aria-busy="true"
|
|
179
|
+
aria-label={`Loading files for ${entryName}`}
|
|
180
|
+
>
|
|
181
|
+
{[1, 2, 3, 4].map((i) => (
|
|
182
|
+
<div
|
|
183
|
+
key={i}
|
|
184
|
+
className="h-3.5 animate-pulse rounded bg-muted"
|
|
185
|
+
style={{ width: `${50 + i * 10}%` }}
|
|
186
|
+
aria-hidden="true"
|
|
187
|
+
/>
|
|
188
|
+
))}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (error) {
|
|
194
|
+
return (
|
|
195
|
+
<div className="px-2 py-2 text-xs text-destructive">
|
|
196
|
+
Failed to list files: {error.message}
|
|
197
|
+
<button
|
|
198
|
+
type="button"
|
|
199
|
+
onClick={onRetry}
|
|
200
|
+
className="ml-2 rounded-sm underline transition-colors hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
201
|
+
>
|
|
202
|
+
Retry
|
|
203
|
+
</button>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (tree.length === 0) {
|
|
209
|
+
return (
|
|
210
|
+
<p className="px-3 py-2 text-xs text-muted-foreground">No files found.</p>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<>
|
|
216
|
+
<nav aria-label={`File tree for ${entryName}`}>
|
|
217
|
+
<ul className="py-0.5 pl-1.5" role="tree">
|
|
218
|
+
{tree.map((node) => (
|
|
219
|
+
<FileTreeNode
|
|
220
|
+
key={node.path}
|
|
221
|
+
node={node}
|
|
222
|
+
selectedPath={selectedPath ?? ""}
|
|
223
|
+
onSelect={(path) => onOpenFile(entryId, path)}
|
|
224
|
+
onActivate={(path) => onActivateFile(entryId, path)}
|
|
225
|
+
depth={0}
|
|
226
|
+
enableDrag
|
|
227
|
+
showIcons
|
|
228
|
+
indentGuides
|
|
229
|
+
maxInitialDepth={0}
|
|
230
|
+
/>
|
|
231
|
+
))}
|
|
232
|
+
</ul>
|
|
233
|
+
</nav>
|
|
234
|
+
{truncated && (
|
|
235
|
+
<p className="px-3 py-1.5 text-[0.65rem] text-muted-foreground">
|
|
236
|
+
Showing a partial listing — too many files to load in full.
|
|
237
|
+
</p>
|
|
238
|
+
)}
|
|
239
|
+
</>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Inline SVG icons (SDK independence — no lucide dependency)
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
function RemoveIcon() {
|
|
248
|
+
return (
|
|
249
|
+
<svg width="12" height="12" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
250
|
+
<path d="M4 4L10 10M10 4L4 10" />
|
|
251
|
+
</svg>
|
|
252
|
+
);
|
|
253
|
+
}
|