@flanksource/clicky-ui 0.3.45 → 0.3.47
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/NOTICE.md +11 -0
- package/README.md +22 -0
- package/dist/ai.cjs +13 -8
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +7 -2
- package/dist/ai.js.map +1 -1
- package/dist/components/ErrorWrapper.cjs +2 -3
- package/dist/components/ErrorWrapper.cjs.map +1 -1
- package/dist/components/ErrorWrapper.d.ts.map +1 -1
- package/dist/components/ErrorWrapper.js +3 -4
- package/dist/components/ErrorWrapper.js.map +1 -1
- package/dist/data/AccessMark.cjs +23 -0
- package/dist/data/AccessMark.cjs.map +1 -0
- package/dist/data/AccessMark.d.ts +11 -0
- package/dist/data/AccessMark.d.ts.map +1 -0
- package/dist/data/AccessMark.js +23 -0
- package/dist/data/AccessMark.js.map +1 -0
- package/dist/data/Clicky.cjs +3 -0
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.js +3 -0
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/CodeDiff.cjs +116 -23
- package/dist/data/CodeDiff.cjs.map +1 -1
- package/dist/data/CodeDiff.d.ts +26 -0
- package/dist/data/CodeDiff.d.ts.map +1 -1
- package/dist/data/CodeDiff.js +116 -23
- package/dist/data/CodeDiff.js.map +1 -1
- package/dist/data/FilterPill.cjs +15 -2
- package/dist/data/FilterPill.cjs.map +1 -1
- package/dist/data/FilterPill.d.ts +1 -1
- package/dist/data/FilterPill.d.ts.map +1 -1
- package/dist/data/FilterPill.js +15 -2
- package/dist/data/FilterPill.js.map +1 -1
- package/dist/data/GraphDiagram.cjs +65 -13
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +9 -2
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +66 -14
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramGroups.cjs +100 -0
- package/dist/data/GraphDiagramGroups.cjs.map +1 -0
- package/dist/data/GraphDiagramGroups.d.ts +24 -0
- package/dist/data/GraphDiagramGroups.d.ts.map +1 -0
- package/dist/data/GraphDiagramGroups.js +100 -0
- package/dist/data/GraphDiagramGroups.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +17 -31
- package/dist/data/GraphDiagramNodes.cjs.map +1 -1
- package/dist/data/GraphDiagramNodes.d.ts +6 -13
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
- package/dist/data/GraphDiagramNodes.js +17 -31
- package/dist/data/GraphDiagramNodes.js.map +1 -1
- package/dist/data/LogViewer.cjs +27 -8
- package/dist/data/LogViewer.cjs.map +1 -1
- package/dist/data/LogViewer.d.ts +11 -3
- package/dist/data/LogViewer.d.ts.map +1 -1
- package/dist/data/LogViewer.js +27 -8
- package/dist/data/LogViewer.js.map +1 -1
- package/dist/data/Properties.cjs +2 -15
- package/dist/data/Properties.cjs.map +1 -1
- package/dist/data/Properties.d.ts +4 -0
- package/dist/data/Properties.d.ts.map +1 -1
- package/dist/data/Properties.js +2 -15
- package/dist/data/Properties.js.map +1 -1
- package/dist/data/PropertyValue.cjs +37 -0
- package/dist/data/PropertyValue.cjs.map +1 -0
- package/dist/data/PropertyValue.d.ts +6 -0
- package/dist/data/PropertyValue.d.ts.map +1 -0
- package/dist/data/PropertyValue.js +37 -0
- package/dist/data/PropertyValue.js.map +1 -0
- package/dist/data/Tree.cjs +4 -3
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.d.ts +3 -1
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +4 -3
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/TreeNode.cjs +1 -1
- package/dist/data/TreeNode.cjs.map +1 -1
- package/dist/data/TreeNode.d.ts.map +1 -1
- package/dist/data/TreeNode.js +1 -1
- package/dist/data/TreeNode.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +1 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.js +1 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +106 -171
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts +6 -2
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.header.cjs +104 -0
- package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.header.d.ts +29 -0
- package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.header.js +104 -0
- package/dist/data/ai/ChatWindow.header.js.map +1 -0
- package/dist/data/ai/ChatWindow.js +107 -172
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.placement.cjs +95 -0
- package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
- package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.placement.js +95 -0
- package/dist/data/ai/ChatWindow.placement.js.map +1 -0
- package/dist/data/ai/SessionChatComposer.cjs +3 -1
- package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
- package/dist/data/ai/SessionChatComposer.d.ts +4 -1
- package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
- package/dist/data/ai/SessionChatComposer.js +3 -1
- package/dist/data/ai/SessionChatComposer.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +68 -72
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
- package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
- package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
- package/dist/data/ai/SessionInspector.d.ts +6 -1
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.js +69 -73
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
- package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.js +41 -42
- package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
- package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
- package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.js +14 -9
- package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote.cjs +84 -16
- package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
- package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.remote.js +86 -18
- package/dist/data/ai/SessionInspector.remote.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +5 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionTail.cjs +63 -0
- package/dist/data/ai/SessionTail.cjs.map +1 -0
- package/dist/data/ai/SessionTail.d.ts +14 -0
- package/dist/data/ai/SessionTail.d.ts.map +1 -0
- package/dist/data/ai/SessionTail.js +63 -0
- package/dist/data/ai/SessionTail.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +10 -3
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +7 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.js +10 -3
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/index.d.ts +4 -3
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +30 -6
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +7 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +30 -6
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/call-graph/CallGraph.cjs +50 -31
- package/dist/data/call-graph/CallGraph.cjs.map +1 -1
- package/dist/data/call-graph/CallGraph.d.ts +10 -1
- package/dist/data/call-graph/CallGraph.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraph.js +52 -33
- package/dist/data/call-graph/CallGraph.js.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.cjs +5 -4
- package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.d.ts +1 -1
- package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraphMembers.js +5 -4
- package/dist/data/call-graph/CallGraphMembers.js.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.cjs +17 -5
- package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.d.ts +10 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -1
- package/dist/data/call-graph/CallGraphToolbar.js +18 -6
- package/dist/data/call-graph/CallGraphToolbar.js.map +1 -1
- package/dist/data/call-graph/call-graph-model.cjs +169 -18
- package/dist/data/call-graph/call-graph-model.cjs.map +1 -1
- package/dist/data/call-graph/call-graph-model.d.ts +40 -4
- package/dist/data/call-graph/call-graph-model.d.ts.map +1 -1
- package/dist/data/call-graph/call-graph-model.js +170 -19
- package/dist/data/call-graph/call-graph-model.js.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.cjs +19 -1
- package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.d.ts +4 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -1
- package/dist/data/call-graph/call-graph-vocabulary.js +19 -1
- package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -1
- package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -1
- package/dist/data/call-graph/index.d.ts +2 -2
- package/dist/data/call-graph/index.d.ts.map +1 -1
- package/dist/data/call-graph/types.cjs.map +1 -1
- package/dist/data/call-graph/types.d.ts +7 -2
- package/dist/data/call-graph/types.d.ts.map +1 -1
- package/dist/data/call-graph/types.js.map +1 -1
- package/dist/data/chat/Chat.cjs +1 -1
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.js +1 -1
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/PromptInput.cjs +4 -2
- package/dist/data/chat/PromptInput.cjs.map +1 -1
- package/dist/data/chat/PromptInput.d.ts +5 -1
- package/dist/data/chat/PromptInput.d.ts.map +1 -1
- package/dist/data/chat/PromptInput.js +4 -2
- package/dist/data/chat/PromptInput.js.map +1 -1
- package/dist/data/data-access.cjs +8 -0
- package/dist/data/data-access.cjs.map +1 -0
- package/dist/data/data-access.d.ts +5 -0
- package/dist/data/data-access.d.ts.map +1 -0
- package/dist/data/data-access.js +8 -0
- package/dist/data/data-access.js.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
- package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
- package/dist/data/diagnostics/ErrorDetails.js +14 -3
- package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
- package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
- package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
- package/dist/data/diagnostics/error-diagnostics.js +6 -1
- package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
- package/dist/data/git/GitChangeList.cjs +6 -2
- package/dist/data/git/GitChangeList.cjs.map +1 -1
- package/dist/data/git/GitChangeList.d.ts +6 -1
- package/dist/data/git/GitChangeList.d.ts.map +1 -1
- package/dist/data/git/GitChangeList.js +6 -2
- package/dist/data/git/GitChangeList.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +47 -16
- package/dist/data/graph-columns-layout.cjs.map +1 -1
- package/dist/data/graph-columns-layout.d.ts +34 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -1
- package/dist/data/graph-columns-layout.js +47 -16
- package/dist/data/graph-columns-layout.js.map +1 -1
- package/dist/data/graph-diagram-model.cjs +5 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -1
- package/dist/data/graph-diagram-model.d.ts +19 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -1
- package/dist/data/graph-diagram-model.js +5 -0
- package/dist/data/graph-diagram-model.js.map +1 -1
- package/dist/data/graph-group-window.cjs +60 -0
- package/dist/data/graph-group-window.cjs.map +1 -0
- package/dist/data/graph-group-window.d.ts +33 -0
- package/dist/data/graph-group-window.d.ts.map +1 -0
- package/dist/data/graph-group-window.js +60 -0
- package/dist/data/graph-group-window.js.map +1 -0
- package/dist/data/har/HarPanel.cjs +3 -1
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +4 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +3 -1
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/test-runner/Expectation.cjs +57 -0
- package/dist/data/test-runner/Expectation.cjs.map +1 -0
- package/dist/data/test-runner/Expectation.d.ts +19 -0
- package/dist/data/test-runner/Expectation.d.ts.map +1 -0
- package/dist/data/test-runner/Expectation.js +57 -0
- package/dist/data/test-runner/Expectation.js.map +1 -0
- package/dist/data/test-runner/MarkIcons.cjs +38 -0
- package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
- package/dist/data/test-runner/MarkIcons.d.ts +15 -0
- package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
- package/dist/data/test-runner/MarkIcons.js +38 -0
- package/dist/data/test-runner/MarkIcons.js.map +1 -0
- package/dist/data/test-runner/TestDetailPanel.cjs +74 -42
- package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
- package/dist/data/test-runner/TestDetailPanel.js +76 -44
- package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
- package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
- package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
- package/dist/data/test-runner/TestFailureDetail.js +23 -27
- package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
- package/dist/data/test-runner/TestFilterBar.cjs +87 -93
- package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
- package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
- package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
- package/dist/data/test-runner/TestFilterBar.js +89 -95
- package/dist/data/test-runner/TestFilterBar.js.map +1 -1
- package/dist/data/test-runner/TestRunSummary.cjs +35 -21
- package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
- package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunSummary.js +35 -21
- package/dist/data/test-runner/TestRunSummary.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +52 -30
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +3 -2
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +52 -30
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/test-runner/TestTree.cjs +5 -2
- package/dist/data/test-runner/TestTree.cjs.map +1 -1
- package/dist/data/test-runner/TestTree.d.ts +5 -2
- package/dist/data/test-runner/TestTree.d.ts.map +1 -1
- package/dist/data/test-runner/TestTree.js +5 -2
- package/dist/data/test-runner/TestTree.js.map +1 -1
- package/dist/data/test-runner/TestTreeNode.cjs +27 -19
- package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
- package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
- package/dist/data/test-runner/TestTreeNode.js +28 -20
- package/dist/data/test-runner/TestTreeNode.js.map +1 -1
- package/dist/data/test-runner/adapter.cjs +11 -0
- package/dist/data/test-runner/adapter.cjs.map +1 -1
- package/dist/data/test-runner/adapter.d.ts +18 -7
- package/dist/data/test-runner/adapter.d.ts.map +1 -1
- package/dist/data/test-runner/adapter.js +11 -0
- package/dist/data/test-runner/adapter.js.map +1 -1
- package/dist/data/test-runner/copy.cjs +114 -0
- package/dist/data/test-runner/copy.cjs.map +1 -0
- package/dist/data/test-runner/copy.d.ts +47 -0
- package/dist/data/test-runner/copy.d.ts.map +1 -0
- package/dist/data/test-runner/copy.js +114 -0
- package/dist/data/test-runner/copy.js.map +1 -0
- package/dist/data/test-runner/index.d.ts +5 -2
- package/dist/data/test-runner/index.d.ts.map +1 -1
- package/dist/data/test-runner/marks.cjs +143 -0
- package/dist/data/test-runner/marks.cjs.map +1 -0
- package/dist/data/test-runner/marks.d.ts +30 -0
- package/dist/data/test-runner/marks.d.ts.map +1 -0
- package/dist/data/test-runner/marks.js +143 -0
- package/dist/data/test-runner/marks.js.map +1 -0
- package/dist/data/test-runner/status.cjs +27 -44
- package/dist/data/test-runner/status.cjs.map +1 -1
- package/dist/data/test-runner/status.d.ts +12 -3
- package/dist/data/test-runner/status.d.ts.map +1 -1
- package/dist/data/test-runner/status.js +27 -44
- package/dist/data/test-runner/status.js.map +1 -1
- package/dist/data/use-group-windows.cjs +50 -0
- package/dist/data/use-group-windows.cjs.map +1 -0
- package/dist/data/use-group-windows.d.ts +27 -0
- package/dist/data/use-group-windows.d.ts.map +1 -0
- package/dist/data/use-group-windows.js +50 -0
- package/dist/data/use-group-windows.js.map +1 -0
- package/dist/data/verification/adapterViews.cjs +16 -41
- package/dist/data/verification/adapterViews.cjs.map +1 -1
- package/dist/data/verification/adapterViews.d.ts.map +1 -1
- package/dist/data/verification/adapterViews.js +16 -41
- package/dist/data/verification/adapterViews.js.map +1 -1
- package/dist/data/verification/adapters.cjs +115 -3
- package/dist/data/verification/adapters.cjs.map +1 -1
- package/dist/data/verification/adapters.d.ts.map +1 -1
- package/dist/data/verification/adapters.js +115 -3
- package/dist/data/verification/adapters.js.map +1 -1
- package/dist/data/verification/verifyReportTests.cjs.map +1 -1
- package/dist/data/verification/verifyReportTests.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +54 -3
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +6 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +58 -7
- package/dist/data.js.map +1 -1
- package/dist/hooks/event-hub.cjs +229 -0
- package/dist/hooks/event-hub.cjs.map +1 -0
- package/dist/hooks/event-hub.d.ts +26 -0
- package/dist/hooks/event-hub.d.ts.map +1 -0
- package/dist/hooks/event-hub.js +229 -0
- package/dist/hooks/event-hub.js.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/icons/components/UiLogoEslint.cjs +10 -0
- package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
- package/dist/icons/components/UiLogoEslint.d.ts +9 -0
- package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
- package/dist/icons/components/UiLogoEslint.js +10 -0
- package/dist/icons/components/UiLogoEslint.js.map +1 -0
- package/dist/icons/components/UiLogoGo.cjs +10 -0
- package/dist/icons/components/UiLogoGo.cjs.map +1 -0
- package/dist/icons/components/UiLogoGo.d.ts +9 -0
- package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
- package/dist/icons/components/UiLogoGo.js +10 -0
- package/dist/icons/components/UiLogoGo.js.map +1 -0
- package/dist/icons/components/UiLogoJest.cjs +10 -0
- package/dist/icons/components/UiLogoJest.cjs.map +1 -0
- package/dist/icons/components/UiLogoJest.d.ts +9 -0
- package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoJest.js +10 -0
- package/dist/icons/components/UiLogoJest.js.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
- package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
- package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
- package/dist/icons/components/UiLogoMarkdown.js +10 -0
- package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
- package/dist/icons/components/UiLogoOxc.cjs +10 -0
- package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
- package/dist/icons/components/UiLogoOxc.d.ts +9 -0
- package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
- package/dist/icons/components/UiLogoOxc.js +10 -0
- package/dist/icons/components/UiLogoOxc.js.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
- package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
- package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPlaywright.js +10 -0
- package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
- package/dist/icons/components/UiLogoPython.cjs +10 -0
- package/dist/icons/components/UiLogoPython.cjs.map +1 -0
- package/dist/icons/components/UiLogoPython.d.ts +9 -0
- package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
- package/dist/icons/components/UiLogoPython.js +10 -0
- package/dist/icons/components/UiLogoPython.js.map +1 -0
- package/dist/icons/components/UiLogoReact.cjs +10 -0
- package/dist/icons/components/UiLogoReact.cjs.map +1 -0
- package/dist/icons/components/UiLogoReact.d.ts +9 -0
- package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
- package/dist/icons/components/UiLogoReact.js +10 -0
- package/dist/icons/components/UiLogoReact.js.map +1 -0
- package/dist/icons/components/UiLogoRuff.cjs +10 -0
- package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
- package/dist/icons/components/UiLogoRuff.d.ts +9 -0
- package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
- package/dist/icons/components/UiLogoRuff.js +10 -0
- package/dist/icons/components/UiLogoRuff.js.map +1 -0
- package/dist/icons/components/UiLogoTypescript.cjs +10 -0
- package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
- package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
- package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
- package/dist/icons/components/UiLogoTypescript.js +10 -0
- package/dist/icons/components/UiLogoTypescript.js.map +1 -0
- package/dist/icons/components/UiLogoVitest.cjs +10 -0
- package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
- package/dist/icons/components/UiLogoVitest.d.ts +9 -0
- package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
- package/dist/icons/components/UiLogoVitest.js +10 -0
- package/dist/icons/components/UiLogoVitest.js.map +1 -0
- package/dist/icons/index.d.ts +11 -0
- package/dist/icons/index.d.ts.map +1 -1
- package/dist/icons/registry.cjs +22 -0
- package/dist/icons/registry.cjs.map +1 -1
- package/dist/icons/registry.d.ts.map +1 -1
- package/dist/icons/registry.js +22 -0
- package/dist/icons/registry.js.map +1 -1
- package/dist/icons.cjs +22 -0
- package/dist/icons.cjs.map +1 -1
- package/dist/icons.js +22 -0
- package/dist/icons.js.map +1 -1
- package/dist/index.cjs +56 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +60 -7
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +4 -4
- package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
- package/dist/overlay/modalStack.cjs +13 -6
- package/dist/overlay/modalStack.cjs.map +1 -1
- package/dist/overlay/modalStack.d.ts.map +1 -1
- package/dist/overlay/modalStack.js +13 -6
- package/dist/overlay/modalStack.js.map +1 -1
- package/dist/rpc/InlineError.cjs +12 -43
- package/dist/rpc/InlineError.cjs.map +1 -1
- package/dist/rpc/InlineError.d.ts.map +1 -1
- package/dist/rpc/InlineError.js +13 -44
- package/dist/rpc/InlineError.js.map +1 -1
- package/dist/rpc/OperationScheduleDialog.cjs +63 -10
- package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
- package/dist/rpc/OperationScheduleDialog.d.ts +4 -0
- package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
- package/dist/rpc/OperationScheduleDialog.js +63 -10
- package/dist/rpc/OperationScheduleDialog.js.map +1 -1
- package/dist/rpc/OperationSchedules.cjs +12 -2
- package/dist/rpc/OperationSchedules.cjs.map +1 -1
- package/dist/rpc/OperationSchedules.d.ts.map +1 -1
- package/dist/rpc/OperationSchedules.js +12 -2
- package/dist/rpc/OperationSchedules.js.map +1 -1
- package/dist/rpc/operation-schedule-model.cjs +2 -0
- package/dist/rpc/operation-schedule-model.cjs.map +1 -1
- package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
- package/dist/rpc/operation-schedule-model.js +2 -0
- package/dist/rpc/operation-schedule-model.js.map +1 -1
- package/dist/rpc/operation-schedule-types.d.ts +7 -1
- package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/data/test-runner/frameworkIcon.cjs +0 -27
- package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
- package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
- package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
- package/dist/data/test-runner/frameworkIcon.js +0 -27
- package/dist/data/test-runner/frameworkIcon.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraph.js","sources":["../../../src/data/call-graph/CallGraph.tsx"],"sourcesContent":["// A call graph around one root: fetched through the host, with `+N` expansions merged in, the call\n// sites of a selected edge (guards fetched on selection when the host's graph leaves them out) and the\n// details of a selected node. It knows no language: the host's vocabulary names and draws node kinds,\n// and the host's callbacks open nodes and sites.\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../../components/button\";\nimport { cn } from \"../../lib/utils\";\nimport { GraphDiagram } from \"../GraphDiagram\";\nimport { matchesExclude, type ExcludeMatcher } from \"./call-graph-exclude\";\nimport type { GuardLabel } from \"./call-graph-labels\";\nimport {\n CALL_GRAPH_DEFAULT_DEPTH,\n CALL_GRAPH_MAX_DEPTH,\n columnGap,\n DEFAULT_EDGE_LABELS,\n expansionDirection,\n mergeGraph,\n requireNode,\n toDiagram,\n visibleGraph,\n type DiagramGlyphs,\n type DiagramOptions,\n} from \"./call-graph-model\";\nimport { UIR_CALL_GRAPH_VOCABULARY, type CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport { EdgeTypeGlyph, GroupCaption, NodeGlyphIcon } from \"./CallGraphGlyphs\";\nimport { EdgeSites, Legend, NodeDetails, type CallGraphAction } from \"./CallGraphParts\";\nimport { CallGraphToolbar } from \"./CallGraphToolbar\";\nimport {\n CALL_GRAPH_ACCESS,\n type CallGraph as Graph,\n type CallGraphAccess,\n type CallGraphDirection,\n type CallGraphEdge,\n type CallGraphEdgeLabels,\n type CallGraphFetchParams,\n type CallGraphGroupFact,\n type CallGraphNode,\n type CallGraphSelection,\n type CallGraphSite,\n} from \"./types\";\nimport { errorMessage, useGraphLoad, useHeld, useSiteGuards, type GraphRequest } from \"./use-call-graph\";\n\nexport interface CallGraphProps<G extends Graph = Graph> {\n /** What the graph is drawn around, in the host's terms. Undefined shows `emptyMessage`. */\n root: string | undefined;\n /** Loads the graph around `params.root`, and one hop around a node for its `+N`. */\n fetchGraph: (params: CallGraphFetchParams) => Promise<G>;\n /** What else `fetchGraph` reads, such as the host's scope: part of the request's key, so a change refetches. */\n fetchKey?: string;\n /** Pass `onDirectionChange` to control it; without one the component holds it, starting here. */\n direction?: CallGraphDirection;\n onDirectionChange?: (direction: CallGraphDirection) => void;\n depth?: number;\n onDepthChange?: (depth: number) => void;\n /** The exclusion patterns; undefined takes the host's defaults. Controlled with `onExcludeChange`. */\n exclude?: string[] | undefined;\n onExcludeChange?: (exclude: string[] | undefined) => void;\n selected?: CallGraphSelection | undefined;\n onSelectedChange?: (selected: CallGraphSelection | undefined) => void;\n /** The source reports reads and writes of data: shows the Access toggles and the Columns switch. */\n dataAccess?: boolean;\n /** The edge types the host follows, never empty; all three by default. Controlled with `onAccessChange`. */\n access?: CallGraphAccess[];\n onAccessChange?: (access: CallGraphAccess[]) => void;\n /** Columns and fields as nodes of their own; collapsed into tables and entities by default. */\n columns?: boolean;\n onColumnsChange?: (columns: boolean) => void;\n /** The groups the graph reached, drawn or excluded. Without it the graph offers no exclusions. */\n groupFacts?: (graph: G) => CallGraphGroupFact[];\n /** The patterns in force when `exclude` is undefined: the host's defaults, as its response reports them. */\n defaultExclude?: (graph: G) => string[];\n /** How a pattern matches a group, for a host with keywords of its own. */\n excludeMatcher?: ExcludeMatcher;\n /**\n * Where a node opens. A node the vocabulary gives no source is never opened, and Open is disabled on\n * a node with no href that `onOpenNode` does not accept.\n */\n nodeHref?: (node: CallGraphNode, graph: G) => string | undefined;\n /** Opens a node; with `nodeHref` it handles a plain click on the link. */\n onOpenNode?: (node: CallGraphNode, graph: G) => void;\n /** Whether `onOpenNode` opens a node; every node by default. */\n canOpenNode?: (node: CallGraphNode, graph: G) => boolean;\n openLabel?: string;\n /** Re-roots the graph on a node, by id: a drawn node the vocabulary can root, or the column behind a field. */\n onFocusNode?: (nodeId: string, graph: G) => void;\n /** Where a call site opens; a site opens only when its caller has a source. */\n siteHref?: (site: CallGraphSite, edge: CallGraphEdge, graph: G) => string | undefined;\n onRevealSite?: (site: CallGraphSite, edge: CallGraphEdge, graph: G) => void;\n /** Fetches the guards of a selected edge's sites, for a host whose graph leaves them out. */\n loadSiteGuards?: (edge: CallGraphEdge, graph: G, signal: AbortSignal) => Promise<CallGraphSite[]>;\n edgeLabels?: Partial<CallGraphEdgeLabels>;\n /** What a conditional edge's pill says of its guards; \"innermost\" by default. The edge's tooltip always lists them. */\n guardLabel?: GuardLabel;\n vocabulary?: CallGraphVocabulary;\n /** Shows a Pin root toggle; the host keeps `root` while pinned. */\n pinned?: boolean;\n onPinnedChange?: (pinned: boolean, rootId: string | undefined) => void;\n /** Host facts above the diagram, such as how the root was resolved. */\n renderHeader?: (graph: G) => ReactNode;\n toolbarEnd?: ReactNode;\n emptyMessage?: ReactNode;\n maxDepth?: number;\n className?: string;\n}\n\ntype Held<G> = { key: string; graph: G; revealed: string[] };\ntype PendingExpansion = { key: string; nodeId: string; label: string; controller: AbortController };\n\nconst NODE_WIDTH = 188;\nconst NODE_HEIGHT = 32;\nconst COMPACT_NODE_HEIGHT = 22;\nconst ROW_GAP = 14;\n/** Node labels are 12px: at this scale they are 7.2px, the smallest that still reads. */\nconst READABLE_SCALE = 0.6;\nconst OPTIONS: Omit<DiagramOptions, \"guardLabel\"> = { truncateAt: 32, grouped: true };\n\nfunction Notice({ children }: { children: ReactNode }) {\n return (\n <div className=\"flex h-full items-center justify-center p-6 text-center\">\n <span className=\"text-sm text-muted-foreground\">{children}</span>\n </div>\n );\n}\n\nfunction Alert({ message }: { message: string | undefined }) {\n if (!message) return null;\n return <div role=\"alert\" className=\"whitespace-pre-wrap rounded-md border border-destructive p-3 text-sm text-destructive\">{message}</div>;\n}\n\nconst ACCESS_WORDS: Record<CallGraphAccess, string> = { call: \"Calls\", read: \"Reads\", write: \"Writes\" };\n\nfunction accessWords(access: readonly CallGraphAccess[]): string {\n return access.map((type) => ACCESS_WORDS[type]).join(\" and \");\n}\n\nfunction action(href: string | undefined, onSelect: (() => void) | undefined): CallGraphAction | undefined {\n if (href === undefined && onSelect === undefined) return undefined;\n return { ...(href !== undefined ? { href } : {}), ...(onSelect ? { onSelect } : {}) };\n}\n\nexport function CallGraph<G extends Graph = Graph>(props: CallGraphProps<G>) {\n const { root, fetchGraph, vocabulary = UIR_CALL_GRAPH_VOCABULARY, maxDepth = CALL_GRAPH_MAX_DEPTH } = props;\n const labels: CallGraphEdgeLabels = { ...DEFAULT_EDGE_LABELS, ...props.edgeLabels };\n const [direction, setDirection] = useHeld(props.direction ?? \"both\", props.onDirectionChange);\n const [depth, setDepth] = useHeld(props.depth ?? CALL_GRAPH_DEFAULT_DEPTH, props.onDepthChange);\n const [exclude, setExclude] = useHeld(props.exclude, props.onExcludeChange);\n const [access, setAccess] = useHeld(props.access ?? [...CALL_GRAPH_ACCESS], props.onAccessChange);\n const [columns, setColumns] = useHeld(props.columns ?? false, props.onColumnsChange);\n if (access.length === 0) throw new Error(\"call graph: access must name at least one of call, read and write\");\n const [ownSelection, setOwnSelection] = useState<{ key: string; selected: CallGraphSelection }>();\n\n const request: GraphRequest | undefined = root === undefined ? undefined : { root, direction, depth, exclude, access, columns, purpose: \"load\" };\n const key = `call-graph:${JSON.stringify([request ?? null, props.fetchKey ?? null])}`;\n const load = useGraphLoad(fetchGraph, request, key);\n\n const [expanded, setExpanded] = useState<Held<G>>();\n const [expanding, setExpanding] = useState<{ request: PendingExpansion; error?: string }>();\n const pendingExpansion = useRef<PendingExpansion | undefined>(undefined);\n const activeKey = useRef(key);\n activeKey.current = key;\n useEffect(() => {\n setExpanding((current) => current?.request.key === key && !current.request.controller.signal.aborted ? current : undefined);\n return () => {\n if (pendingExpansion.current?.key === key) {\n pendingExpansion.current.controller.abort();\n pendingExpansion.current = undefined;\n }\n };\n }, [key]);\n const [opening, setOpening] = useState({ nonce: 0, fit: false });\n const fresh = useMemo<Held<G> | undefined>(\n () => load.fresh && (expanded?.key === key ? expanded : { key, graph: load.fresh, revealed: [] }),\n [load.fresh, expanded, key],\n );\n const [last, setLast] = useState<Held<G>>();\n if (fresh && fresh !== last) setLast(fresh);\n const shown = root === undefined ? undefined : (fresh ?? last);\n const graph = shown?.graph;\n\n const visible = useMemo(() => shown && visibleGraph(shown.graph, { direction, depth, revealed: shown.revealed }), [shown, direction, depth]);\n const glyphs = useMemo<DiagramGlyphs>(() => ({\n node: (glyph, words) => <NodeGlyphIcon vocabulary={vocabulary} glyph={glyph} title={words} />,\n edge: (type) => (type === \"call\" ? undefined : <EdgeTypeGlyph type={type} title={labels[type]} />),\n group: (caption) => <GroupCaption icon={vocabulary.group.icon} caption={caption} />,\n }), [vocabulary, labels.dispatch, labels.read, labels.write]);\n const guardLabel = props.guardLabel ?? \"innermost\";\n const diagram = useMemo(\n () => graph && visible && toDiagram({ graph, visible, direction, options: { ...OPTIONS, guardLabel }, glyphs, vocabulary, edgeLabels: labels }),\n [graph, visible, direction, guardLabel, glyphs, vocabulary, labels.call, labels.dispatch, labels.read, labels.write],\n );\n\n const rootId = graph?.roots[0];\n const selection = props.onSelectedChange ? props.selected : ownSelection?.key === shown?.key ? ownSelection?.selected : undefined;\n const select = (next: CallGraphSelection | undefined) => {\n if (props.onSelectedChange) props.onSelectedChange(next);\n else setOwnSelection(next && shown ? { key: shown.key, selected: next } : undefined);\n };\n const openAction = (node: CallGraphNode, drawn: G) => {\n const { onOpenNode, canOpenNode } = props;\n const accepted = onOpenNode && (canOpenNode?.(node, drawn) ?? true) ? () => onOpenNode(node, drawn) : undefined;\n return action(props.nodeHref?.(node, drawn), accepted);\n };\n const selectedNode = selection?.kind === \"node\" ? visible?.nodes.find((node) => node.id === selection.id) : undefined;\n const selectedEdge = selection?.kind === \"edge\" ? visible?.edges.find((edge) => edge.id === selection.id) : undefined;\n const guards = useSiteGuards(props.loadSiteGuards, shown?.key, selectedEdge, graph);\n const expansion = expanding?.request.key === key ? expanding : undefined;\n\n // A `+N` loads one more hop on the node's outer side and merges it into the graph this request drew.\n const expand = async (drawn: Held<G>, id: string) => {\n if (drawn.key !== activeKey.current) return;\n if (pendingExpansion.current?.key === drawn.key && pendingExpansion.current.nodeId === id) return;\n pendingExpansion.current?.controller.abort();\n const node = requireNode(drawn.graph, id);\n const request: PendingExpansion = { key: drawn.key, nodeId: id, label: node.label, controller: new AbortController() };\n pendingExpansion.current = request;\n setExpanding({ request });\n try {\n const data = await fetchGraph({\n root: id, direction: expansionDirection(node), depth: 1, exclude, access, columns, purpose: \"expand\", signal: request.controller.signal,\n });\n if (request.controller.signal.aborted || activeKey.current !== drawn.key || pendingExpansion.current !== request) return;\n setExpanded((held) => {\n if (request.controller.signal.aborted || activeKey.current !== drawn.key) return held;\n const base = held?.key === drawn.key ? held : drawn;\n return { key: drawn.key, graph: mergeGraph(base.graph, data), revealed: [...base.revealed, ...data.nodes.map((entry) => entry.id)] };\n });\n setExpanding((current) => current?.request === request ? undefined : current);\n } catch (error) {\n if (request.controller.signal.aborted || activeKey.current !== drawn.key || pendingExpansion.current !== request) return;\n setExpanding((current) => current?.request === request\n ? { request, error: `Cannot expand ${node.label}: ${errorMessage(error)}` } : current);\n } finally {\n if (pendingExpansion.current === request) pendingExpansion.current = undefined;\n }\n };\n\n const groups = graph && props.groupFacts?.(graph);\n const effectiveExclude = exclude ?? (graph && props.defaultExclude ? props.defaultExclude(graph) : []);\n const { onPinnedChange } = props;\n const toolbar = (\n <CallGraphToolbar direction={direction} depth={depth} maxDepth={maxDepth} omitted={graph?.omitted} end={props.toolbarEnd} vocabulary={vocabulary}\n {...(onPinnedChange ? { pin: { pinned: props.pinned ?? false, canPin: rootId !== undefined, onPin: (pinned: boolean) => onPinnedChange(pinned, rootId) } } : {})}\n {...(groups ? { exclusions: { exclude: effectiveExclude, groups, matches: props.excludeMatcher ?? matchesExclude, busy: load.loading, vocabulary,\n onExclude: (patterns: string[]) => setExclude(patterns), onDefaults: () => setExclude(undefined) } } : {})}\n {...(props.dataAccess ? { data: { access, onAccess: setAccess, columns, onColumns: setColumns } } : {})}\n onDirection={setDirection} onDepth={setDepth}\n onFit={() => setOpening({ nonce: opening.nonce + 1, fit: true })} onReset={() => setOpening({ nonce: opening.nonce + 1, fit: false })} />\n );\n\n const frame = cn(\"flex h-full min-h-0 flex-col gap-2 p-2\", props.className);\n if (root === undefined) {\n return <div className={frame}>{toolbar}<Notice>{props.emptyMessage ?? \"Select a node to draw its call graph.\"}</Notice></div>;\n }\n const loadError = load.error && `Cannot draw the call graph: ${load.error}`;\n return (\n <div className={frame} aria-busy={load.loading}>\n {toolbar}\n <Alert message={loadError} />\n {graph && props.renderHeader?.(graph)}\n {!shown && load.loading && <Notice>Loading call graph…</Notice>}\n {graph && !rootId && <Notice>The root resolved to no node in this scope.</Notice>}\n {graph && rootId && graph.edges.length === 0 && access.length < CALL_GRAPH_ACCESS.length && (\n <Notice>{`Nothing is reachable with ${accessWords(access)} only.`}</Notice>\n )}\n {graph && rootId && graph.edges.length > 0 && !selectedEdge && !selectedNode && (\n <p className=\"text-xs text-muted-foreground\">Select an edge to list its sites, or a node to see its details.</p>\n )}\n {shown && graph && rootId && diagram && (\n <div className=\"flex min-h-0 flex-1 gap-3\">\n <div className={cn(\"relative min-h-64 min-w-0 flex-1 rounded-lg border border-border bg-background\", load.loading && \"opacity-60\")}>\n <GraphDiagram key={`${shown.key}:${opening.nonce}`} nodes={diagram.nodes} edges={diagram.edges} groups={diagram.groups} layout=\"columns\" zoomable wheelZoom=\"zoom\" edgeFocus=\"auto\"\n focusId={rootId} {...(opening.fit ? {} : { fitMinScale: READABLE_SCALE })} nodeWidth={NODE_WIDTH} nodeHeight={NODE_HEIGHT} compactNodeHeight={COMPACT_NODE_HEIGHT} columnGap={columnGap(diagram)} rowGap={ROW_GAP}\n className=\"h-full\" ariaLabel={`Call graph of ${requireNode(graph, rootId).label}`}\n onNodeSelect={(id: string) => select({ kind: \"node\", id })} onEdgeSelect={(id: string) => select({ kind: \"edge\", id })}\n {...(fresh ? { onNodeExpand: (id: string) => void expand(fresh, id) } : {})}\n {...(selectedNode ? { selectedId: selectedNode.id } : {})} {...(selectedEdge ? { selectedEdgeId: selectedEdge.id } : {})} />\n </div>\n {(selectedEdge || selectedNode || expansion) && (\n <aside className=\"w-80 max-w-[45%] shrink-0 overflow-y-auto rounded-lg border border-border bg-card p-3\" aria-label=\"Selection\">\n {expansion && <p role=\"status\" className=\"mb-2 text-xs text-muted-foreground\">{expansion.error ?? `Loading more around ${expansion.request.label}…`}</p>}\n {(selectedEdge || selectedNode) && (\n <div className=\"mb-1 flex justify-end\">\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" aria-label=\"Close selection\" onClick={() => select(undefined)}>×</Button>\n </div>\n )}\n {selectedEdge ? (\n <EdgeSites edge={selectedEdge} graph={graph} labels={labels} guards={guards} lazyGuards={props.loadSiteGuards !== undefined}\n siteAction={(props.siteHref || props.onRevealSite) && vocabulary.hasSource(requireNode(graph, selectedEdge.from))\n ? (site) => action(props.siteHref?.(site, selectedEdge, graph), props.onRevealSite && (() => props.onRevealSite?.(site, selectedEdge, graph))) ?? {}\n : undefined} />\n ) : selectedNode && (\n <NodeDetails node={selectedNode} graph={graph} vocabulary={vocabulary} isRoot={selectedNode.id === rootId} openLabel={props.openLabel ?? \"Open\"}\n opens={props.nodeHref !== undefined || props.onOpenNode !== undefined} open={openAction(selectedNode, graph)}\n onFocus={props.onFocusNode && ((id: string) => props.onFocusNode?.(id, graph))} />\n )}\n </aside>\n )}\n </div>\n )}\n {graph && rootId && <div className=\"shrink-0\"><Legend graph={graph} vocabulary={vocabulary} labels={labels} /></div>}\n </div>\n );\n}\n"],"names":["_a","_b","request"],"mappings":";;;;;;;;;;;;;AA4GA,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,sBAAsB;AAC5B,MAAM,UAAU;AAEhB,MAAM,iBAAiB;AACvB,MAAM,UAA8C,EAAE,YAAY,IAAI,SAAS,KAAA;AAE/E,SAAS,OAAO,EAAE,YAAqC;AACrD,SACE,oBAAC,SAAI,WAAU,2DACb,8BAAC,QAAA,EAAK,WAAU,iCAAiC,SAAA,CAAS,EAAA,CAC5D;AAEJ;AAEA,SAAS,MAAM,EAAE,WAA4C;AAC3D,MAAI,CAAC,QAAS,QAAO;AACrB,6BAAQ,OAAA,EAAI,MAAK,SAAQ,WAAU,yFAAyF,UAAA,SAAQ;AACtI;AAEA,MAAM,eAAgD,EAAE,MAAM,SAAS,MAAM,SAAS,OAAO,SAAA;AAE7F,SAAS,YAAY,QAA4C;AAC/D,SAAO,OAAO,IAAI,CAAC,SAAS,aAAa,IAAI,CAAC,EAAE,KAAK,OAAO;AAC9D;AAEA,SAAS,OAAO,MAA0B,UAAiE;AACzG,MAAI,SAAS,UAAa,aAAa,OAAW,QAAO;AACzD,SAAO,EAAE,GAAI,SAAS,SAAY,EAAE,KAAA,IAAS,CAAA,GAAK,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA,EAAC;AACnF;AAEO,SAAS,UAAmC,OAA0B;;AAC3E,QAAM,EAAE,MAAM,YAAY,aAAa,2BAA2B,WAAW,yBAAyB;AACtG,QAAM,SAA8B,EAAE,GAAG,qBAAqB,GAAG,MAAM,WAAA;AACvE,QAAM,CAAC,WAAW,YAAY,IAAI,QAAQ,MAAM,aAAa,QAAQ,MAAM,iBAAiB;AAC5F,QAAM,CAAC,OAAO,QAAQ,IAAI,QAAQ,MAAM,SAAS,0BAA0B,MAAM,aAAa;AAC9F,QAAM,CAAC,SAAS,UAAU,IAAI,QAAQ,MAAM,SAAS,MAAM,eAAe;AAC1E,QAAM,CAAC,QAAQ,SAAS,IAAI,QAAQ,MAAM,UAAU,CAAC,GAAG,iBAAiB,GAAG,MAAM,cAAc;AAChG,QAAM,CAAC,SAAS,UAAU,IAAI,QAAQ,MAAM,WAAW,OAAO,MAAM,eAAe;AACnF,MAAI,OAAO,WAAW,EAAG,OAAM,IAAI,MAAM,mEAAmE;AAC5G,QAAM,CAAC,cAAc,eAAe,IAAI,SAAA;AAExC,QAAM,UAAoC,SAAS,SAAY,SAAY,EAAE,MAAM,WAAW,OAAO,SAAS,QAAQ,SAAS,SAAS,OAAA;AACxI,QAAM,MAAM,cAAc,KAAK,UAAU,CAAC,WAAW,MAAM,MAAM,YAAY,IAAI,CAAC,CAAC;AACnF,QAAM,OAAO,aAAa,YAAY,SAAS,GAAG;AAElD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAA;AAChC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAA;AAClC,QAAM,mBAAmB,OAAqC,MAAS;AACvE,QAAM,YAAY,OAAO,GAAG;AAC5B,YAAU,UAAU;AACpB,YAAU,MAAM;AACd,iBAAa,CAAC,aAAY,mCAAS,QAAQ,SAAQ,OAAO,CAAC,QAAQ,QAAQ,WAAW,OAAO,UAAU,UAAU,MAAS;AAC1H,WAAO,MAAM;;AACX,YAAIA,MAAA,iBAAiB,YAAjB,gBAAAA,IAA0B,SAAQ,KAAK;AACzC,yBAAiB,QAAQ,WAAW,MAAA;AACpC,yBAAiB,UAAU;AAAA,MAC7B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AACR,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,EAAE,OAAO,GAAG,KAAK,OAAO;AAC/D,QAAM,QAAQ;AAAA,IACZ,MAAM,KAAK,WAAU,qCAAU,SAAQ,MAAM,WAAW,EAAE,KAAK,OAAO,KAAK,OAAO,UAAU,CAAA,EAAC;AAAA,IAC7F,CAAC,KAAK,OAAO,UAAU,GAAG;AAAA,EAAA;AAE5B,QAAM,CAAC,MAAM,OAAO,IAAI,SAAA;AACxB,MAAI,SAAS,UAAU,KAAM,SAAQ,KAAK;AAC1C,QAAM,QAAQ,SAAS,SAAY,SAAa,SAAS;AACzD,QAAM,QAAQ,+BAAO;AAErB,QAAM,UAAU,QAAQ,MAAM,SAAS,aAAa,MAAM,OAAO,EAAE,WAAW,OAAO,UAAU,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,KAAK,CAAC;AAC3I,QAAM,SAAS,QAAuB,OAAO;AAAA,IAC3C,MAAM,CAAC,OAAO,8BAAW,eAAA,EAAc,YAAwB,OAAc,OAAO,OAAO;AAAA,IAC3F,MAAM,CAAC,SAAU,SAAS,SAAS,SAAY,oBAAC,eAAA,EAAc,MAAY,OAAO,OAAO,IAAI,EAAA,CAAG;AAAA,IAC/F,OAAO,CAAC,YAAY,oBAAC,gBAAa,MAAM,WAAW,MAAM,MAAM,QAAA,CAAkB;AAAA,EAAA,IAC/E,CAAC,YAAY,OAAO,UAAU,OAAO,MAAM,OAAO,KAAK,CAAC;AAC5D,QAAM,aAAa,MAAM,cAAc;AACvC,QAAM,UAAU;AAAA,IACd,MAAM,SAAS,WAAW,UAAU,EAAE,OAAO,SAAS,WAAW,SAAS,EAAE,GAAG,SAAS,cAAc,QAAQ,YAAY,YAAY,QAAQ;AAAA,IAC9I,CAAC,OAAO,SAAS,WAAW,YAAY,QAAQ,YAAY,OAAO,MAAM,OAAO,UAAU,OAAO,MAAM,OAAO,KAAK;AAAA,EAAA;AAGrH,QAAM,SAAS,+BAAO,MAAM;AAC5B,QAAM,YAAY,MAAM,mBAAmB,MAAM,YAAW,6CAAc,UAAQ,+BAAO,OAAM,6CAAc,WAAW;AACxH,QAAM,SAAS,CAAC,SAAyC;AACvD,QAAI,MAAM,iBAAkB,OAAM,iBAAiB,IAAI;AAAA,QAClD,iBAAgB,QAAQ,QAAQ,EAAE,KAAK,MAAM,KAAK,UAAU,KAAA,IAAS,MAAS;AAAA,EACrF;AACA,QAAM,aAAa,CAAC,MAAqB,UAAa;;AACpD,UAAM,EAAE,YAAY,YAAA,IAAgB;AACpC,UAAM,WAAW,gBAAe,2CAAc,MAAM,WAAU,QAAQ,MAAM,WAAW,MAAM,KAAK,IAAI;AACtG,WAAO,QAAOA,MAAA,MAAM,aAAN,gBAAAA,IAAA,YAAiB,MAAM,QAAQ,QAAQ;AAAA,EACvD;AACA,QAAM,gBAAe,uCAAW,UAAS,SAAS,mCAAS,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,UAAU,MAAM;AAC5G,QAAM,gBAAe,uCAAW,UAAS,SAAS,mCAAS,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,UAAU,MAAM;AAC5G,QAAM,SAAS,cAAc,MAAM,gBAAgB,+BAAO,KAAK,cAAc,KAAK;AAClF,QAAM,aAAY,uCAAW,QAAQ,SAAQ,MAAM,YAAY;AAG/D,QAAM,SAAS,OAAO,OAAgB,OAAe;;AACnD,QAAI,MAAM,QAAQ,UAAU,QAAS;AACrC,UAAIA,MAAA,iBAAiB,YAAjB,gBAAAA,IAA0B,SAAQ,MAAM,OAAO,iBAAiB,QAAQ,WAAW,GAAI;AAC3F,KAAAC,MAAA,iBAAiB,YAAjB,gBAAAA,IAA0B,WAAW;AACrC,UAAM,OAAO,YAAY,MAAM,OAAO,EAAE;AACxC,UAAMC,WAA4B,EAAE,KAAK,MAAM,KAAK,QAAQ,IAAI,OAAO,KAAK,OAAO,YAAY,IAAI,kBAAgB;AACnH,qBAAiB,UAAUA;AAC3B,iBAAa,EAAE,SAAAA,UAAS;AACxB,QAAI;AACF,YAAM,OAAO,MAAM,WAAW;AAAA,QAC5B,MAAM;AAAA,QAAI,WAAW,mBAAmB,IAAI;AAAA,QAAG,OAAO;AAAA,QAAG;AAAA,QAAS;AAAA,QAAQ;AAAA,QAAS,SAAS;AAAA,QAAU,QAAQA,SAAQ,WAAW;AAAA,MAAA,CAClI;AACD,UAAIA,SAAQ,WAAW,OAAO,WAAW,UAAU,YAAY,MAAM,OAAO,iBAAiB,YAAYA,SAAS;AAClH,kBAAY,CAAC,SAAS;AACpB,YAAIA,SAAQ,WAAW,OAAO,WAAW,UAAU,YAAY,MAAM,IAAK,QAAO;AACjF,cAAM,QAAO,6BAAM,SAAQ,MAAM,MAAM,OAAO;AAC9C,eAAO,EAAE,KAAK,MAAM,KAAK,OAAO,WAAW,KAAK,OAAO,IAAI,GAAG,UAAU,CAAC,GAAG,KAAK,UAAU,GAAG,KAAK,MAAM,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC,EAAA;AAAA,MACnI,CAAC;AACD,mBAAa,CAAC,aAAY,mCAAS,aAAYA,WAAU,SAAY,OAAO;AAAA,IAC9E,SAAS,OAAO;AACd,UAAIA,SAAQ,WAAW,OAAO,WAAW,UAAU,YAAY,MAAM,OAAO,iBAAiB,YAAYA,SAAS;AAClH,mBAAa,CAAC,aAAY,mCAAS,aAAYA,WAC3C,EAAE,SAAAA,UAAS,OAAO,iBAAiB,KAAK,KAAK,KAAK,aAAa,KAAK,CAAC,GAAA,IAAO,OAAO;AAAA,IACzF,UAAA;AACE,UAAI,iBAAiB,YAAYA,SAAS,kBAAiB,UAAU;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,SAAS,WAAS,WAAM,eAAN,+BAAmB;AAC3C,QAAM,mBAAmB,YAAY,SAAS,MAAM,iBAAiB,MAAM,eAAe,KAAK,IAAI;AACnG,QAAM,EAAE,mBAAmB;AAC3B,QAAM,UACJ;AAAA,IAAC;AAAA,IAAA;AAAA,MAAiB;AAAA,MAAsB;AAAA,MAAc;AAAA,MAAoB,SAAS,+BAAO;AAAA,MAAS,KAAK,MAAM;AAAA,MAAY;AAAA,MACvH,GAAI,iBAAiB,EAAE,KAAK,EAAE,QAAQ,MAAM,UAAU,OAAO,QAAQ,WAAW,QAAW,OAAO,CAAC,WAAoB,eAAe,QAAQ,MAAM,EAAA,EAAE,IAAM,CAAA;AAAA,MAC5J,GAAI,SAAS,EAAE,YAAY;AAAA,QAAE,SAAS;AAAA,QAAkB;AAAA,QAAQ,SAAS,MAAM,kBAAkB;AAAA,QAAgB,MAAM,KAAK;AAAA,QAAS;AAAA,QACpI,WAAW,CAAC,aAAuB,WAAW,QAAQ;AAAA,QAAG,YAAY,MAAM,WAAW,MAAS;AAAA,MAAA,EAAE,IAAM,CAAA;AAAA,MACxG,GAAI,MAAM,aAAa,EAAE,MAAM,EAAE,QAAQ,UAAU,WAAW,SAAS,WAAW,WAAA,EAAW,IAAM,CAAA;AAAA,MACpG,aAAa;AAAA,MAAc,SAAS;AAAA,MACpC,OAAO,MAAM,WAAW,EAAE,OAAO,QAAQ,QAAQ,GAAG,KAAK,MAAM;AAAA,MAAG,SAAS,MAAM,WAAW,EAAE,OAAO,QAAQ,QAAQ,GAAG,KAAK,MAAA,CAAO;AAAA,IAAA;AAAA,EAAA;AAGxI,QAAM,QAAQ,GAAG,0CAA0C,MAAM,SAAS;AAC1E,MAAI,SAAS,QAAW;AACtB,WAAO,qBAAC,OAAA,EAAI,WAAW,OAAQ,UAAA;AAAA,MAAA;AAAA,MAAQ,oBAAC,QAAA,EAAQ,UAAA,MAAM,gBAAgB,wCAAA,CAAwC;AAAA,IAAA,GAAS;AAAA,EACzH;AACA,QAAM,YAAY,KAAK,SAAS,+BAA+B,KAAK,KAAK;AACzE,8BACG,OAAA,EAAI,WAAW,OAAO,aAAW,KAAK,SACpC,UAAA;AAAA,IAAA;AAAA,IACD,oBAAC,OAAA,EAAM,SAAS,UAAA,CAAW;AAAA,IAC1B,WAAS,WAAM,iBAAN,+BAAqB;AAAA,IAC9B,CAAC,SAAS,KAAK,WAAW,oBAAC,UAAO,UAAA,uBAAmB;AAAA,IACrD,SAAS,CAAC,UAAU,oBAAC,UAAO,UAAA,+CAA2C;AAAA,IACvE,SAAS,UAAU,MAAM,MAAM,WAAW,KAAK,OAAO,SAAS,kBAAkB,8BAC/E,QAAA,EAAQ,UAAA,6BAA6B,YAAY,MAAM,CAAC,UAAS;AAAA,IAEnE,SAAS,UAAU,MAAM,MAAM,SAAS,KAAK,CAAC,gBAAgB,CAAC,gBAC9D,oBAAC,KAAA,EAAE,WAAU,iCAAgC,UAAA,mEAA+D;AAAA,IAE7G,SAAS,SAAS,UAAU,WAC3B,qBAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,MAAA,oBAAC,SAAI,WAAW,GAAG,kFAAkF,KAAK,WAAW,YAAY,GAC/H,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAmD,OAAO,QAAQ;AAAA,UAAO,OAAO,QAAQ;AAAA,UAAO,QAAQ,QAAQ;AAAA,UAAQ,QAAO;AAAA,UAAU,UAAQ;AAAA,UAAC,WAAU;AAAA,UAAO,WAAU;AAAA,UAC3K,SAAS;AAAA,UAAS,GAAI,QAAQ,MAAM,CAAA,IAAK,EAAE,aAAa,eAAA;AAAA,UAAmB,WAAW;AAAA,UAAY,YAAY;AAAA,UAAa,mBAAmB;AAAA,UAAqB,WAAW,UAAU,OAAO;AAAA,UAAG,QAAQ;AAAA,UAC1M,WAAU;AAAA,UAAS,WAAW,iBAAiB,YAAY,OAAO,MAAM,EAAE,KAAK;AAAA,UAC/E,cAAc,CAAC,OAAe,OAAO,EAAE,MAAM,QAAQ,IAAI;AAAA,UAAG,cAAc,CAAC,OAAe,OAAO,EAAE,MAAM,QAAQ,IAAI;AAAA,UACpH,GAAI,QAAQ,EAAE,cAAc,CAAC,OAAe,KAAK,OAAO,OAAO,EAAE,EAAA,IAAM,CAAA;AAAA,UACvE,GAAI,eAAe,EAAE,YAAY,aAAa,GAAA,IAAO,CAAA;AAAA,UAAM,GAAI,eAAe,EAAE,gBAAgB,aAAa,GAAA,IAAO,CAAA;AAAA,QAAC;AAAA,QALrG,GAAG,MAAM,GAAG,IAAI,QAAQ,KAAK;AAAA,MAAA,GAMlD;AAAA,OACE,gBAAgB,gBAAgB,cAChC,qBAAC,WAAM,WAAU,yFAAwF,cAAW,aACjH,UAAA;AAAA,QAAA,aAAa,oBAAC,KAAA,EAAE,MAAK,UAAS,WAAU,sCAAsC,UAAA,UAAU,SAAS,uBAAuB,UAAU,QAAQ,KAAK,KAAI;AAAA,SAClJ,gBAAgB,iBAChB,oBAAC,OAAA,EAAI,WAAU,yBACb,UAAA,oBAAC,QAAA,EAAO,MAAK,UAAS,MAAK,MAAK,SAAQ,SAAQ,cAAW,mBAAkB,SAAS,MAAM,OAAO,MAAS,GAAG,UAAA,IAAA,CAAC,EAAA,CAClH;AAAA,QAED,eACC;AAAA,UAAC;AAAA,UAAA;AAAA,YAAU,MAAM;AAAA,YAAc;AAAA,YAAc;AAAA,YAAgB;AAAA,YAAgB,YAAY,MAAM,mBAAmB;AAAA,YAChH,aAAa,MAAM,YAAY,MAAM,iBAAiB,WAAW,UAAU,YAAY,OAAO,aAAa,IAAI,CAAC,IAC5G,CAAC,SAAA;;AAAS,6BAAOF,MAAA,MAAM,aAAN,gBAAAA,IAAA,YAAiB,MAAM,cAAc,QAAQ,MAAM,iBAAiB,MAAA;;AAAM,wBAAAA,MAAA,MAAM,iBAAN,gBAAAA,IAAA,YAAqB,MAAM,cAAc;AAAA,gBAAO,KAAK,CAAA;AAAA,gBAChJ;AAAA,UAAA;AAAA,QAAA,IACJ,gBACF;AAAA,UAAC;AAAA,UAAA;AAAA,YAAY,MAAM;AAAA,YAAc;AAAA,YAAc;AAAA,YAAwB,QAAQ,aAAa,OAAO;AAAA,YAAQ,WAAW,MAAM,aAAa;AAAA,YACvI,OAAO,MAAM,aAAa,UAAa,MAAM,eAAe;AAAA,YAAW,MAAM,WAAW,cAAc,KAAK;AAAA,YAC3G,SAAS,MAAM,gBAAgB,CAAC;;AAAe,sBAAAA,MAAA,MAAM,gBAAN,gBAAAA,IAAA,YAAoB,IAAI;AAAA;AAAA,UAAK;AAAA,QAAA;AAAA,MAAI,EAAA,CAEtF;AAAA,IAAA,GAEJ;AAAA,IAED,SAAS,UAAU,oBAAC,OAAA,EAAI,WAAU,YAAW,UAAA,oBAAC,QAAA,EAAO,OAAc,YAAwB,OAAA,CAAgB,EAAA,CAAE;AAAA,EAAA,GAChH;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"CallGraph.js","sources":["../../../src/data/call-graph/CallGraph.tsx"],"sourcesContent":["// A call graph around one root: fetched through the host, with `+N` expansions merged in, the call\n// sites of a selected edge (guards fetched on selection when the host's graph leaves them out) and the\n// details of a selected node. It knows no language: the host's vocabulary names and draws node kinds,\n// and the host's callbacks open nodes and sites.\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../../components/button\";\nimport { cn } from \"../../lib/utils\";\nimport { AccessMark } from \"../AccessMark\";\nimport { GraphDiagram } from \"../GraphDiagram\";\nimport { matchesExclude, type ExcludeMatcher } from \"./call-graph-exclude\";\nimport type { GuardLabel } from \"./call-graph-labels\";\nimport {\n baseAccess,\n CALL_GRAPH_DEFAULT_DEPTH,\n CALL_GRAPH_MAX_DEPTH,\n collapsibleGroups,\n columnGap,\n DEFAULT_EDGE_LABELS,\n expansionDirection,\n mergeGraph,\n requireNode,\n toDiagram,\n visibleGraph,\n type DiagramGlyphs,\n type DiagramOptions,\n} from \"./call-graph-model\";\nimport { requireGlyph, UIR_CALL_GRAPH_VOCABULARY, type CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport { EdgeTypeGlyph, GroupCaption, NodeGlyphIcon } from \"./CallGraphGlyphs\";\nimport { EdgeSites, Legend, NodeDetails, type CallGraphAction } from \"./CallGraphParts\";\nimport { CallGraphToolbar } from \"./CallGraphToolbar\";\nimport {\n CALL_GRAPH_ACCESS,\n type CallGraph as Graph,\n type CallGraphAccess,\n type CallGraphDirection,\n type CallGraphEdge,\n type CallGraphEdgeLabels,\n type CallGraphFetchParams,\n type CallGraphGroupFact,\n type CallGraphNode,\n type CallGraphSelection,\n type CallGraphSite,\n} from \"./types\";\nimport { errorMessage, useGraphLoad, useHeld, useSiteGuards, type GraphRequest } from \"./use-call-graph\";\n\nexport interface CallGraphProps<G extends Graph = Graph> {\n /** What the graph is drawn around, in the host's terms. Undefined shows `emptyMessage`. */\n root: string | undefined;\n /** Loads the graph around `params.root`, and one hop around a node for its `+N`. */\n fetchGraph: (params: CallGraphFetchParams) => Promise<G>;\n /** What else `fetchGraph` reads, such as the host's scope: part of the request's key, so a change refetches. */\n fetchKey?: string;\n /** Pass `onDirectionChange` to control it; without one the component holds it, starting here. */\n direction?: CallGraphDirection;\n onDirectionChange?: (direction: CallGraphDirection) => void;\n depth?: number;\n onDepthChange?: (depth: number) => void;\n /** The exclusion patterns; undefined takes the host's defaults. Controlled with `onExcludeChange`. */\n exclude?: string[] | undefined;\n onExcludeChange?: (exclude: string[] | undefined) => void;\n selected?: CallGraphSelection | undefined;\n onSelectedChange?: (selected: CallGraphSelection | undefined) => void;\n /** The source reports reads and writes of data: shows the Access toggles and the Columns switch. */\n dataAccess?: boolean;\n /** The source can follow the variables a body reads and writes: shows a Variables toggle beside the Access ones. Needs `dataAccess`. */\n variableAccess?: boolean;\n /** The edge types the host follows, at least one of call, read and write; all three by default. Controlled with `onAccessChange`. */\n access?: CallGraphAccess[];\n onAccessChange?: (access: CallGraphAccess[]) => void;\n /** Columns and fields as nodes of their own; collapsed into tables and entities by default. */\n columns?: boolean;\n onColumnsChange?: (columns: boolean) => void;\n /**\n * The groups drawn as their header alone, by `graph.groups` id: each folds into one node, and its\n * members' edges merge onto it, counting the members. The root's group never folds. Controlled with\n * `onCollapsedGroupsChange`; without one the component holds it, starting here, none by default.\n */\n collapsedGroups?: string[];\n onCollapsedGroupsChange?: (ids: string[]) => void;\n /** The groups the graph reached, drawn or excluded. Without it the graph offers no exclusions. */\n groupFacts?: (graph: G) => CallGraphGroupFact[];\n /** The patterns in force when `exclude` is undefined: the host's defaults, as its response reports them. */\n defaultExclude?: (graph: G) => string[];\n /** How a pattern matches a group, for a host with keywords of its own. */\n excludeMatcher?: ExcludeMatcher;\n /**\n * Where a node opens. A node the vocabulary gives no source is never opened, and Open is disabled on\n * a node with no href that `onOpenNode` does not accept.\n */\n nodeHref?: (node: CallGraphNode, graph: G) => string | undefined;\n /** Opens a node; with `nodeHref` it handles a plain click on the link. */\n onOpenNode?: (node: CallGraphNode, graph: G) => void;\n /** Whether `onOpenNode` opens a node; every node by default. */\n canOpenNode?: (node: CallGraphNode, graph: G) => boolean;\n openLabel?: string;\n /** Re-roots the graph on a node, by id: a drawn node the vocabulary can root, or the column behind a field. */\n onFocusNode?: (nodeId: string, graph: G) => void;\n /** Where a call site opens; a site opens only when its caller has a source. */\n siteHref?: (site: CallGraphSite, edge: CallGraphEdge, graph: G) => string | undefined;\n onRevealSite?: (site: CallGraphSite, edge: CallGraphEdge, graph: G) => void;\n /** Fetches the guards of a selected edge's sites, for a host whose graph leaves them out. */\n loadSiteGuards?: (edge: CallGraphEdge, graph: G, signal: AbortSignal) => Promise<CallGraphSite[]>;\n edgeLabels?: Partial<CallGraphEdgeLabels>;\n /** What a conditional edge's pill says of its guards; \"innermost\" by default. The edge's tooltip always lists them. */\n guardLabel?: GuardLabel;\n vocabulary?: CallGraphVocabulary;\n /** Shows a Pin root toggle; the host keeps `root` while pinned. */\n pinned?: boolean;\n onPinnedChange?: (pinned: boolean, rootId: string | undefined) => void;\n /** Host facts above the diagram, such as how the root was resolved. */\n renderHeader?: (graph: G) => ReactNode;\n toolbarEnd?: ReactNode;\n emptyMessage?: ReactNode;\n maxDepth?: number;\n className?: string;\n}\n\ntype Held<G> = { key: string; graph: G; revealed: string[] };\ntype PendingExpansion = { key: string; nodeId: string; label: string; controller: AbortController };\n\nconst NODE_WIDTH = 188;\nconst NODE_HEIGHT = 32;\nconst COMPACT_NODE_HEIGHT = 22;\nconst ROW_GAP = 14;\n/** Node labels are 12px: at this scale they are 7.2px, the smallest that still reads. */\nconst READABLE_SCALE = 0.6;\nconst OPTIONS: Omit<DiagramOptions, \"guardLabel\"> = { truncateAt: 32, grouped: true };\n\nfunction Notice({ children }: { children: ReactNode }) {\n return (\n <div className=\"flex h-full items-center justify-center p-6 text-center\">\n <span className=\"text-sm text-muted-foreground\">{children}</span>\n </div>\n );\n}\n\nfunction Alert({ message }: { message: string | undefined }) {\n if (!message) return null;\n return <div role=\"alert\" className=\"whitespace-pre-wrap rounded-md border border-destructive p-3 text-sm text-destructive\">{message}</div>;\n}\n\nconst ACCESS_WORDS: Record<CallGraphAccess, string> = { call: \"Calls\", read: \"Reads\", write: \"Writes\", variable: \"Variables\" };\n\nfunction accessWords(access: readonly CallGraphAccess[]): string {\n return access.map((type) => ACCESS_WORDS[type]).join(\" and \");\n}\n\nfunction action(href: string | undefined, onSelect: (() => void) | undefined): CallGraphAction | undefined {\n if (href === undefined && onSelect === undefined) return undefined;\n return { ...(href !== undefined ? { href } : {}), ...(onSelect ? { onSelect } : {}) };\n}\n\nexport function CallGraph<G extends Graph = Graph>(props: CallGraphProps<G>) {\n const { root, fetchGraph, vocabulary = UIR_CALL_GRAPH_VOCABULARY, maxDepth = CALL_GRAPH_MAX_DEPTH } = props;\n const labels: CallGraphEdgeLabels = { ...DEFAULT_EDGE_LABELS, ...props.edgeLabels };\n const [direction, setDirection] = useHeld(props.direction ?? \"both\", props.onDirectionChange);\n const [depth, setDepth] = useHeld(props.depth ?? CALL_GRAPH_DEFAULT_DEPTH, props.onDepthChange);\n const [exclude, setExclude] = useHeld(props.exclude, props.onExcludeChange);\n const [access, setAccess] = useHeld(props.access ?? [...CALL_GRAPH_ACCESS], props.onAccessChange);\n const [columns, setColumns] = useHeld(props.columns ?? false, props.onColumnsChange);\n const [collapsedGroups, setCollapsedGroups] = useHeld(props.collapsedGroups ?? [], props.onCollapsedGroupsChange);\n if (baseAccess(access).length === 0) throw new Error(\"call graph: access must name at least one of call, read and write\");\n if (access.includes(\"variable\") && !(props.dataAccess && props.variableAccess)) {\n throw new Error(\"call graph: access names variable, but the host does not offer variableAccess\");\n }\n const [ownSelection, setOwnSelection] = useState<{ key: string; selected: CallGraphSelection }>();\n\n const request: GraphRequest | undefined = root === undefined ? undefined : { root, direction, depth, exclude, access, columns, purpose: \"load\" };\n const key = `call-graph:${JSON.stringify([request ?? null, props.fetchKey ?? null])}`;\n const load = useGraphLoad(fetchGraph, request, key);\n\n const [expanded, setExpanded] = useState<Held<G>>();\n const [expanding, setExpanding] = useState<{ request: PendingExpansion; error?: string }>();\n const pendingExpansion = useRef<PendingExpansion | undefined>(undefined);\n const activeKey = useRef(key);\n activeKey.current = key;\n useEffect(() => {\n setExpanding((current) => current?.request.key === key && !current.request.controller.signal.aborted ? current : undefined);\n return () => {\n if (pendingExpansion.current?.key === key) {\n pendingExpansion.current.controller.abort();\n pendingExpansion.current = undefined;\n }\n };\n }, [key]);\n const [opening, setOpening] = useState({ nonce: 0, fit: false });\n const fresh = useMemo<Held<G> | undefined>(\n () => load.fresh && (expanded?.key === key ? expanded : { key, graph: load.fresh, revealed: [] }),\n [load.fresh, expanded, key],\n );\n const [last, setLast] = useState<Held<G>>();\n if (fresh && fresh !== last) setLast(fresh);\n const shown = root === undefined ? undefined : (fresh ?? last);\n const graph = shown?.graph;\n\n const visible = useMemo(() => shown && visibleGraph(shown.graph, { direction, depth, revealed: shown.revealed }), [shown, direction, depth]);\n const glyphs = useMemo<DiagramGlyphs>(() => ({\n node: (glyph, words) => <NodeGlyphIcon vocabulary={vocabulary} glyph={glyph} title={words} />,\n edge: (type) => (type === \"call\" ? undefined : <EdgeTypeGlyph type={type} title={labels[type]} />),\n group: (caption, glyph) => <GroupCaption icon={glyph === undefined ? vocabulary.group.icon : requireGlyph(vocabulary, glyph).icon} caption={caption} />,\n access: (access) => <AccessMark access={access} />,\n }), [vocabulary, labels.dispatch, labels.read, labels.write]);\n const guardLabel = props.guardLabel ?? \"innermost\";\n const diagram = useMemo(\n () => graph && visible && toDiagram({ graph, visible, direction, options: { ...OPTIONS, guardLabel }, glyphs, vocabulary, edgeLabels: labels, collapsed: collapsedGroups }),\n [graph, visible, direction, guardLabel, glyphs, vocabulary, labels.call, labels.dispatch, labels.read, labels.write, collapsedGroups],\n );\n // What a selection is looked up in: the graph as drawn, collapsed groups folded into their stand-ins.\n const drawn = diagram?.drawn;\n const collapsible = useMemo(() => (graph && visible ? collapsibleGroups(graph, visible) : []), [graph, visible]);\n const toggleGroup = (id: string) => setCollapsedGroups(collapsedGroups.includes(id) ? collapsedGroups.filter((entry) => entry !== id) : [...collapsedGroups, id]);\n\n const rootId = graph?.roots[0];\n const selection = props.onSelectedChange ? props.selected : ownSelection?.key === shown?.key ? ownSelection?.selected : undefined;\n const select = (next: CallGraphSelection | undefined) => {\n if (props.onSelectedChange) props.onSelectedChange(next);\n else setOwnSelection(next && shown ? { key: shown.key, selected: next } : undefined);\n };\n const openAction = (node: CallGraphNode, drawn: G) => {\n const { onOpenNode, canOpenNode } = props;\n const accepted = onOpenNode && (canOpenNode?.(node, drawn) ?? true) ? () => onOpenNode(node, drawn) : undefined;\n return action(props.nodeHref?.(node, drawn), accepted);\n };\n const selectedNode = selection?.kind === \"node\" ? drawn?.visible.nodes.find((node) => node.id === selection.id) : undefined;\n const selectedEdge = selection?.kind === \"edge\" ? drawn?.visible.edges.find((edge) => edge.id === selection.id) : undefined;\n // A merged edge stands for several the host knows: it has no guards of its own to load.\n const mergedEdge = selectedEdge !== undefined && drawn?.merged.has(selectedEdge.id) === true;\n const standIn = selectedNode !== undefined && drawn?.folds.has(selectedNode.id) === true;\n const guards = useSiteGuards(props.loadSiteGuards, shown?.key, mergedEdge ? undefined : selectedEdge, graph);\n const expansion = expanding?.request.key === key ? expanding : undefined;\n\n // A `+N` loads one more hop on the node's outer side and merges it into the graph this request drew.\n const expand = async (drawn: Held<G>, id: string) => {\n if (drawn.key !== activeKey.current) return;\n if (pendingExpansion.current?.key === drawn.key && pendingExpansion.current.nodeId === id) return;\n pendingExpansion.current?.controller.abort();\n const node = requireNode(drawn.graph, id);\n const request: PendingExpansion = { key: drawn.key, nodeId: id, label: node.label, controller: new AbortController() };\n pendingExpansion.current = request;\n setExpanding({ request });\n try {\n const data = await fetchGraph({\n root: id, direction: expansionDirection(node), depth: 1, exclude, access, columns, purpose: \"expand\", signal: request.controller.signal,\n });\n if (request.controller.signal.aborted || activeKey.current !== drawn.key || pendingExpansion.current !== request) return;\n setExpanded((held) => {\n if (request.controller.signal.aborted || activeKey.current !== drawn.key) return held;\n const base = held?.key === drawn.key ? held : drawn;\n return { key: drawn.key, graph: mergeGraph(base.graph, data), revealed: [...base.revealed, ...data.nodes.map((entry) => entry.id)] };\n });\n setExpanding((current) => current?.request === request ? undefined : current);\n } catch (error) {\n if (request.controller.signal.aborted || activeKey.current !== drawn.key || pendingExpansion.current !== request) return;\n setExpanding((current) => current?.request === request\n ? { request, error: `Cannot expand ${node.label}: ${errorMessage(error)}` } : current);\n } finally {\n if (pendingExpansion.current === request) pendingExpansion.current = undefined;\n }\n };\n\n const groups = graph && props.groupFacts?.(graph);\n const effectiveExclude = exclude ?? (graph && props.defaultExclude ? props.defaultExclude(graph) : []);\n const { onPinnedChange } = props;\n const toolbar = (\n <CallGraphToolbar direction={direction} depth={depth} maxDepth={maxDepth} omitted={graph?.omitted} end={props.toolbarEnd} vocabulary={vocabulary}\n {...(onPinnedChange ? { pin: { pinned: props.pinned ?? false, canPin: rootId !== undefined, onPin: (pinned: boolean) => onPinnedChange(pinned, rootId) } } : {})}\n {...(groups ? { exclusions: { exclude: effectiveExclude, groups, matches: props.excludeMatcher ?? matchesExclude, busy: load.loading, vocabulary,\n onExclude: (patterns: string[]) => setExclude(patterns), onDefaults: () => setExclude(undefined) } } : {})}\n {...(props.dataAccess ? { data: { access, onAccess: setAccess, columns, onColumns: setColumns, variables: props.variableAccess ?? false } } : {})}\n {...(collapsible.length > 0 ? { groupCollapse: {\n anyCollapsed: collapsedGroups.some((id) => collapsible.includes(id)),\n anyExpanded: collapsible.some((id) => !collapsedGroups.includes(id)),\n onExpandAll: () => setCollapsedGroups([]),\n onCollapseAll: () => setCollapsedGroups(collapsible),\n } } : {})}\n onDirection={setDirection} onDepth={setDepth}\n onFit={() => setOpening({ nonce: opening.nonce + 1, fit: true })} onReset={() => setOpening({ nonce: opening.nonce + 1, fit: false })} />\n );\n\n const frame = cn(\"flex h-full min-h-0 flex-col gap-2 p-2\", props.className);\n if (root === undefined) {\n return <div className={frame}>{toolbar}<Notice>{props.emptyMessage ?? \"Select a node to draw its call graph.\"}</Notice></div>;\n }\n const loadError = load.error && `Cannot draw the call graph: ${load.error}`;\n return (\n <div className={frame} aria-busy={load.loading}>\n {toolbar}\n <Alert message={loadError} />\n {graph && props.renderHeader?.(graph)}\n {!shown && load.loading && <Notice>Loading call graph…</Notice>}\n {graph && !rootId && <Notice>The root resolved to no node in this scope.</Notice>}\n {graph && rootId && graph.edges.length === 0 && baseAccess(access).length < CALL_GRAPH_ACCESS.length && (\n <Notice>{`Nothing is reachable with ${accessWords(baseAccess(access))} only.`}</Notice>\n )}\n {graph && rootId && graph.edges.length > 0 && !selectedEdge && !selectedNode && (\n <p className=\"text-xs text-muted-foreground\">Select an edge to list its sites, or a node to see its details.</p>\n )}\n {shown && graph && rootId && diagram && (\n <div className=\"flex min-h-0 flex-1 gap-3\">\n <div className={cn(\"relative min-h-64 min-w-0 flex-1 rounded-lg border border-border bg-background\", load.loading && \"opacity-60\")}>\n <GraphDiagram key={`${shown.key}:${opening.nonce}`} nodes={diagram.nodes} edges={diagram.edges} groups={diagram.groups} layout=\"columns\" zoomable wheelZoom=\"zoom\" edgeFocus=\"auto\"\n focusId={rootId} {...(opening.fit ? {} : { fitMinScale: READABLE_SCALE })} nodeWidth={NODE_WIDTH} nodeHeight={NODE_HEIGHT} compactNodeHeight={COMPACT_NODE_HEIGHT} recordHeaderHeight={24} columnGap={columnGap(diagram)} rowGap={ROW_GAP}\n className=\"h-full\" ariaLabel={`Call graph of ${requireNode(graph, rootId).label}`} onGroupToggle={toggleGroup}\n onNodeSelect={(id: string) => select({ kind: \"node\", id })} onEdgeSelect={(id: string) => select({ kind: \"edge\", id })}\n {...(fresh ? { onNodeExpand: (id: string) => void expand(fresh, id) } : {})}\n {...(selectedNode ? { selectedId: selectedNode.id } : {})} {...(selectedEdge ? { selectedEdgeId: selectedEdge.id } : {})} />\n </div>\n {(selectedEdge || selectedNode || expansion) && (\n <aside className=\"w-80 max-w-[45%] shrink-0 overflow-y-auto rounded-lg border border-border bg-card p-3\" aria-label=\"Selection\">\n {expansion && <p role=\"status\" className=\"mb-2 text-xs text-muted-foreground\">{expansion.error ?? `Loading more around ${expansion.request.label}…`}</p>}\n {(selectedEdge || selectedNode) && (\n <div className=\"mb-1 flex justify-end\">\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" aria-label=\"Close selection\" onClick={() => select(undefined)}>×</Button>\n </div>\n )}\n {selectedEdge && drawn ? (\n <EdgeSites edge={selectedEdge} graph={drawn.graph} labels={labels} guards={guards} lazyGuards={props.loadSiteGuards !== undefined}\n siteAction={(props.siteHref || props.onRevealSite) && !drawn.folds.has(selectedEdge.from) && vocabulary.hasSource(requireNode(graph, selectedEdge.from))\n ? (site) => action(props.siteHref?.(site, selectedEdge, graph), props.onRevealSite && (() => props.onRevealSite?.(site, selectedEdge, graph))) ?? {}\n : undefined} />\n ) : selectedNode && drawn && (\n <NodeDetails node={selectedNode} graph={drawn.graph} vocabulary={vocabulary} isRoot={selectedNode.id === rootId} openLabel={props.openLabel ?? \"Open\"}\n opens={!standIn && (props.nodeHref !== undefined || props.onOpenNode !== undefined)} open={standIn ? undefined : openAction(selectedNode, graph)}\n onFocus={standIn ? undefined : props.onFocusNode && ((id: string) => props.onFocusNode?.(id, graph))} />\n )}\n </aside>\n )}\n </div>\n )}\n {graph && rootId && <div className=\"shrink-0\"><Legend graph={graph} vocabulary={vocabulary} labels={labels} /></div>}\n </div>\n );\n}\n"],"names":["_a","access","drawn","_b","request"],"mappings":"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"}
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const react = require("react");
|
|
5
5
|
const utils = require("../../lib/utils.cjs");
|
|
6
|
+
const AccessMark = require("../AccessMark.cjs");
|
|
6
7
|
const Badge = require("../Badge.cjs");
|
|
7
8
|
const MEMBER_LIMIT = 8;
|
|
8
9
|
const ACCESS_MARK = {
|
|
9
|
-
read: {
|
|
10
|
-
write: {
|
|
11
|
-
both: {
|
|
10
|
+
read: { access: "read", words: "read" },
|
|
11
|
+
write: { access: "write", words: "written" },
|
|
12
|
+
both: { access: "readwrite", words: "read and written" }
|
|
12
13
|
};
|
|
13
14
|
function Overflowing({ label, items, limit, className }) {
|
|
14
15
|
const [expanded, setExpanded] = react.useState(false);
|
|
@@ -28,7 +29,7 @@ function MemberChipList({ label, members, limit = MEMBER_LIMIT }) {
|
|
|
28
29
|
const mark = ACCESS_MARK[member.access];
|
|
29
30
|
return /* @__PURE__ */ jsxRuntime.jsx("li", { "data-member": member.name, ...marked ? { "data-access": member.access, title: `${member.name}: ${mark.words}` } : {}, children: /* @__PURE__ */ jsxRuntime.jsxs(Badge.Badge, { variant: "outline", size: "sm", clickToCopy: false, className: "gap-1 font-mono", children: [
|
|
30
31
|
member.name,
|
|
31
|
-
marked && /* @__PURE__ */ jsxRuntime.jsx(
|
|
32
|
+
marked && /* @__PURE__ */ jsxRuntime.jsx(AccessMark.AccessMark, { access: mark.access, className: "text-xs" })
|
|
32
33
|
] }) }, member.name);
|
|
33
34
|
});
|
|
34
35
|
return /* @__PURE__ */ jsxRuntime.jsx(Overflowing, { label, items: chips, limit });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraphMembers.cjs","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Badge } from \"../Badge\";\nimport type { MemberAccess, MemberAccessKind } from \"./call-graph-labels\";\n\n/** How many chips or names a list shows before a \"+N more\" button reveals the rest. */\nconst MEMBER_LIMIT = 8;\n\nconst ACCESS_MARK: Record<MemberAccessKind, {
|
|
1
|
+
{"version":3,"file":"CallGraphMembers.cjs","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { AccessMark } from \"../AccessMark\";\nimport { Badge } from \"../Badge\";\nimport type { DataAccess } from \"../data-access\";\nimport type { MemberAccess, MemberAccessKind } from \"./call-graph-labels\";\n\n/** How many chips or names a list shows before a \"+N more\" button reveals the rest. */\nconst MEMBER_LIMIT = 8;\n\nconst ACCESS_MARK: Record<MemberAccessKind, { access: DataAccess; words: string }> = {\n read: { access: \"read\", words: \"read\" },\n write: { access: \"write\", words: \"written\" },\n both: { access: \"readwrite\", words: \"read and written\" },\n};\n\n/** The first `limit` items on one wrapping line, then a button that shows the rest. */\nfunction Overflowing({ label, items, limit, className }: { label: string; items: ReactNode[]; limit: number; className?: string }) {\n const [expanded, setExpanded] = useState(false);\n const hidden = expanded ? 0 : Math.max(0, items.length - limit);\n return (\n <div className=\"flex min-w-0 flex-wrap items-center gap-1\">\n <ul className={cn(\"flex min-w-0 flex-wrap items-center gap-1\", className)} aria-label={label}>\n {hidden > 0 ? items.slice(0, limit) : items}\n </ul>\n {hidden > 0 && (\n <button type=\"button\" className=\"rounded px-1 text-xs font-medium text-primary hover:underline\" onClick={() => setExpanded(true)}>\n +{hidden} more\n </button>\n )}\n </div>\n );\n}\n\n/**\n * The columns or fields a read or write touches, as chips on one wrapping line. When they are not all\n * touched the same way, each chip carries its `AccessMark`.\n */\nexport function MemberChipList({ label, members, limit = MEMBER_LIMIT }: { label: string; members: readonly MemberAccess[]; limit?: number }) {\n const marked = new Set(members.map((member) => member.access)).size > 1;\n const chips = members.map((member) => {\n const mark = ACCESS_MARK[member.access];\n return (\n <li key={member.name} data-member={member.name} {...(marked ? { \"data-access\": member.access, title: `${member.name}: ${mark.words}` } : {})}>\n <Badge variant=\"outline\" size=\"sm\" clickToCopy={false} className=\"gap-1 font-mono\">\n {member.name}\n {marked && <AccessMark access={mark.access} className=\"text-xs\" />}\n </Badge>\n </li>\n );\n });\n return <Overflowing label={label} items={chips} limit={limit} />;\n}\n\n/** `MemberChipList` after its label, or nothing when there are no members. */\nexport function MemberChips({ label, members }: { label: string; members: readonly MemberAccess[] }) {\n if (members.length === 0) return null;\n return (\n <div className=\"flex items-start gap-1.5 text-xs\">\n <span className=\"shrink-0 leading-5 text-muted-foreground\">{label}</span>\n <MemberChipList label={label} members={members} />\n </div>\n );\n}\n\n/** Node names on one wrapping line, such as who reads or writes a column. */\nexport function NameList({ label, names, limit = MEMBER_LIMIT }: { label: string; names: readonly string[]; limit?: number }) {\n // Two rules in different tiers can share a name.\n const items = names.map((name, index) => <li key={`${index}:${name}`} className=\"break-words text-xs\">{name}</li>);\n return <Overflowing label={label} items={items} limit={limit} className=\"gap-x-2\" />;\n}\n"],"names":["useState","jsxs","jsx","cn","Badge","AccessMark"],"mappings":";;;;;;;AAQA,MAAM,eAAe;AAErB,MAAM,cAA+E;AAAA,EACnF,MAAM,EAAE,QAAQ,QAAQ,OAAO,OAAA;AAAA,EAC/B,OAAO,EAAE,QAAQ,SAAS,OAAO,UAAA;AAAA,EACjC,MAAM,EAAE,QAAQ,aAAa,OAAO,mBAAA;AACtC;AAGA,SAAS,YAAY,EAAE,OAAO,OAAO,OAAO,aAAuF;AACjI,QAAM,CAAC,UAAU,WAAW,IAAIA,MAAAA,SAAS,KAAK;AAC9C,QAAM,SAAS,WAAW,IAAI,KAAK,IAAI,GAAG,MAAM,SAAS,KAAK;AAC9D,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,6CACb,UAAA;AAAA,IAAAC,2BAAAA,IAAC,MAAA,EAAG,WAAWC,MAAAA,GAAG,6CAA6C,SAAS,GAAG,cAAY,OACpF,UAAA,SAAS,IAAI,MAAM,MAAM,GAAG,KAAK,IAAI,OACxC;AAAA,IACC,SAAS,KACRF,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,WAAU,iEAAgE,SAAS,MAAM,YAAY,IAAI,GAAG,UAAA;AAAA,MAAA;AAAA,MAC9H;AAAA,MAAO;AAAA,IAAA,EAAA,CACX;AAAA,EAAA,GAEJ;AAEJ;AAMO,SAAS,eAAe,EAAE,OAAO,SAAS,QAAQ,gBAAqF;AAC5I,QAAM,SAAS,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,MAAM,CAAC,EAAE,OAAO;AACtE,QAAM,QAAQ,QAAQ,IAAI,CAAC,WAAW;AACpC,UAAM,OAAO,YAAY,OAAO,MAAM;AACtC,WACEC,2BAAAA,IAAC,MAAA,EAAqB,eAAa,OAAO,MAAO,GAAI,SAAS,EAAE,eAAe,OAAO,QAAQ,OAAO,GAAG,OAAO,IAAI,KAAK,KAAK,KAAK,GAAA,IAAO,CAAA,GACvI,UAAAD,2BAAAA,KAACG,MAAAA,OAAA,EAAM,SAAQ,WAAU,MAAK,MAAK,aAAa,OAAO,WAAU,mBAC9D,UAAA;AAAA,MAAA,OAAO;AAAA,MACP,UAAUF,2BAAAA,IAACG,WAAAA,YAAA,EAAW,QAAQ,KAAK,QAAQ,WAAU,UAAA,CAAU;AAAA,IAAA,GAClE,EAAA,GAJO,OAAO,IAKhB;AAAA,EAEJ,CAAC;AACD,SAAOH,2BAAAA,IAAC,aAAA,EAAY,OAAc,OAAO,OAAO,OAAc;AAChE;AAGO,SAAS,YAAY,EAAE,OAAO,WAAgE;AACnG,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACED,2BAAAA,KAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,IAAAC,2BAAAA,IAAC,QAAA,EAAK,WAAU,4CAA4C,UAAA,OAAM;AAAA,IAClEA,2BAAAA,IAAC,gBAAA,EAAe,OAAc,QAAA,CAAkB;AAAA,EAAA,GAClD;AAEJ;AAGO,SAAS,SAAS,EAAE,OAAO,OAAO,QAAQ,gBAA6E;AAE5H,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,UAAUA,2BAAAA,IAAC,MAAA,EAA4B,WAAU,uBAAuB,kBAArD,GAAG,KAAK,IAAI,IAAI,EAA0C,CAAK;AACjH,wCAAQ,aAAA,EAAY,OAAc,OAAc,OAAc,WAAU,WAAU;AACpF;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MemberAccess } from './call-graph-labels.js';
|
|
2
2
|
/**
|
|
3
3
|
* The columns or fields a read or write touches, as chips on one wrapping line. When they are not all
|
|
4
|
-
* touched the same way, each chip
|
|
4
|
+
* touched the same way, each chip carries its `AccessMark`.
|
|
5
5
|
*/
|
|
6
6
|
export declare function MemberChipList({ label, members, limit }: {
|
|
7
7
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraphMembers.d.ts","sourceRoot":"","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CallGraphMembers.d.ts","sourceRoot":"","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AA6B1E;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAoB,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAc3I;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,sCAQlG;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAoB,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BAI3H"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { AccessMark } from "../AccessMark.js";
|
|
4
5
|
import { Badge } from "../Badge.js";
|
|
5
6
|
const MEMBER_LIMIT = 8;
|
|
6
7
|
const ACCESS_MARK = {
|
|
7
|
-
read: {
|
|
8
|
-
write: {
|
|
9
|
-
both: {
|
|
8
|
+
read: { access: "read", words: "read" },
|
|
9
|
+
write: { access: "write", words: "written" },
|
|
10
|
+
both: { access: "readwrite", words: "read and written" }
|
|
10
11
|
};
|
|
11
12
|
function Overflowing({ label, items, limit, className }) {
|
|
12
13
|
const [expanded, setExpanded] = useState(false);
|
|
@@ -26,7 +27,7 @@ function MemberChipList({ label, members, limit = MEMBER_LIMIT }) {
|
|
|
26
27
|
const mark = ACCESS_MARK[member.access];
|
|
27
28
|
return /* @__PURE__ */ jsx("li", { "data-member": member.name, ...marked ? { "data-access": member.access, title: `${member.name}: ${mark.words}` } : {}, children: /* @__PURE__ */ jsxs(Badge, { variant: "outline", size: "sm", clickToCopy: false, className: "gap-1 font-mono", children: [
|
|
28
29
|
member.name,
|
|
29
|
-
marked && /* @__PURE__ */ jsx(
|
|
30
|
+
marked && /* @__PURE__ */ jsx(AccessMark, { access: mark.access, className: "text-xs" })
|
|
30
31
|
] }) }, member.name);
|
|
31
32
|
});
|
|
32
33
|
return /* @__PURE__ */ jsx(Overflowing, { label, items: chips, limit });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraphMembers.js","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Badge } from \"../Badge\";\nimport type { MemberAccess, MemberAccessKind } from \"./call-graph-labels\";\n\n/** How many chips or names a list shows before a \"+N more\" button reveals the rest. */\nconst MEMBER_LIMIT = 8;\n\nconst ACCESS_MARK: Record<MemberAccessKind, {
|
|
1
|
+
{"version":3,"file":"CallGraphMembers.js","sources":["../../../src/data/call-graph/CallGraphMembers.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { AccessMark } from \"../AccessMark\";\nimport { Badge } from \"../Badge\";\nimport type { DataAccess } from \"../data-access\";\nimport type { MemberAccess, MemberAccessKind } from \"./call-graph-labels\";\n\n/** How many chips or names a list shows before a \"+N more\" button reveals the rest. */\nconst MEMBER_LIMIT = 8;\n\nconst ACCESS_MARK: Record<MemberAccessKind, { access: DataAccess; words: string }> = {\n read: { access: \"read\", words: \"read\" },\n write: { access: \"write\", words: \"written\" },\n both: { access: \"readwrite\", words: \"read and written\" },\n};\n\n/** The first `limit` items on one wrapping line, then a button that shows the rest. */\nfunction Overflowing({ label, items, limit, className }: { label: string; items: ReactNode[]; limit: number; className?: string }) {\n const [expanded, setExpanded] = useState(false);\n const hidden = expanded ? 0 : Math.max(0, items.length - limit);\n return (\n <div className=\"flex min-w-0 flex-wrap items-center gap-1\">\n <ul className={cn(\"flex min-w-0 flex-wrap items-center gap-1\", className)} aria-label={label}>\n {hidden > 0 ? items.slice(0, limit) : items}\n </ul>\n {hidden > 0 && (\n <button type=\"button\" className=\"rounded px-1 text-xs font-medium text-primary hover:underline\" onClick={() => setExpanded(true)}>\n +{hidden} more\n </button>\n )}\n </div>\n );\n}\n\n/**\n * The columns or fields a read or write touches, as chips on one wrapping line. When they are not all\n * touched the same way, each chip carries its `AccessMark`.\n */\nexport function MemberChipList({ label, members, limit = MEMBER_LIMIT }: { label: string; members: readonly MemberAccess[]; limit?: number }) {\n const marked = new Set(members.map((member) => member.access)).size > 1;\n const chips = members.map((member) => {\n const mark = ACCESS_MARK[member.access];\n return (\n <li key={member.name} data-member={member.name} {...(marked ? { \"data-access\": member.access, title: `${member.name}: ${mark.words}` } : {})}>\n <Badge variant=\"outline\" size=\"sm\" clickToCopy={false} className=\"gap-1 font-mono\">\n {member.name}\n {marked && <AccessMark access={mark.access} className=\"text-xs\" />}\n </Badge>\n </li>\n );\n });\n return <Overflowing label={label} items={chips} limit={limit} />;\n}\n\n/** `MemberChipList` after its label, or nothing when there are no members. */\nexport function MemberChips({ label, members }: { label: string; members: readonly MemberAccess[] }) {\n if (members.length === 0) return null;\n return (\n <div className=\"flex items-start gap-1.5 text-xs\">\n <span className=\"shrink-0 leading-5 text-muted-foreground\">{label}</span>\n <MemberChipList label={label} members={members} />\n </div>\n );\n}\n\n/** Node names on one wrapping line, such as who reads or writes a column. */\nexport function NameList({ label, names, limit = MEMBER_LIMIT }: { label: string; names: readonly string[]; limit?: number }) {\n // Two rules in different tiers can share a name.\n const items = names.map((name, index) => <li key={`${index}:${name}`} className=\"break-words text-xs\">{name}</li>);\n return <Overflowing label={label} items={items} limit={limit} className=\"gap-x-2\" />;\n}\n"],"names":[],"mappings":";;;;;AAQA,MAAM,eAAe;AAErB,MAAM,cAA+E;AAAA,EACnF,MAAM,EAAE,QAAQ,QAAQ,OAAO,OAAA;AAAA,EAC/B,OAAO,EAAE,QAAQ,SAAS,OAAO,UAAA;AAAA,EACjC,MAAM,EAAE,QAAQ,aAAa,OAAO,mBAAA;AACtC;AAGA,SAAS,YAAY,EAAE,OAAO,OAAO,OAAO,aAAuF;AACjI,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,SAAS,WAAW,IAAI,KAAK,IAAI,GAAG,MAAM,SAAS,KAAK;AAC9D,SACE,qBAAC,OAAA,EAAI,WAAU,6CACb,UAAA;AAAA,IAAA,oBAAC,MAAA,EAAG,WAAW,GAAG,6CAA6C,SAAS,GAAG,cAAY,OACpF,UAAA,SAAS,IAAI,MAAM,MAAM,GAAG,KAAK,IAAI,OACxC;AAAA,IACC,SAAS,KACR,qBAAC,UAAA,EAAO,MAAK,UAAS,WAAU,iEAAgE,SAAS,MAAM,YAAY,IAAI,GAAG,UAAA;AAAA,MAAA;AAAA,MAC9H;AAAA,MAAO;AAAA,IAAA,EAAA,CACX;AAAA,EAAA,GAEJ;AAEJ;AAMO,SAAS,eAAe,EAAE,OAAO,SAAS,QAAQ,gBAAqF;AAC5I,QAAM,SAAS,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,MAAM,CAAC,EAAE,OAAO;AACtE,QAAM,QAAQ,QAAQ,IAAI,CAAC,WAAW;AACpC,UAAM,OAAO,YAAY,OAAO,MAAM;AACtC,WACE,oBAAC,MAAA,EAAqB,eAAa,OAAO,MAAO,GAAI,SAAS,EAAE,eAAe,OAAO,QAAQ,OAAO,GAAG,OAAO,IAAI,KAAK,KAAK,KAAK,GAAA,IAAO,CAAA,GACvI,UAAA,qBAAC,OAAA,EAAM,SAAQ,WAAU,MAAK,MAAK,aAAa,OAAO,WAAU,mBAC9D,UAAA;AAAA,MAAA,OAAO;AAAA,MACP,UAAU,oBAAC,YAAA,EAAW,QAAQ,KAAK,QAAQ,WAAU,UAAA,CAAU;AAAA,IAAA,GAClE,EAAA,GAJO,OAAO,IAKhB;AAAA,EAEJ,CAAC;AACD,SAAO,oBAAC,aAAA,EAAY,OAAc,OAAO,OAAO,OAAc;AAChE;AAGO,SAAS,YAAY,EAAE,OAAO,WAAgE;AACnG,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACE,qBAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,WAAU,4CAA4C,UAAA,OAAM;AAAA,IAClE,oBAAC,gBAAA,EAAe,OAAc,QAAA,CAAkB;AAAA,EAAA,GAClD;AAEJ;AAGO,SAAS,SAAS,EAAE,OAAO,OAAO,QAAQ,gBAA6E;AAE5H,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,UAAU,oBAAC,MAAA,EAA4B,WAAU,uBAAuB,kBAArD,GAAG,KAAK,IAAI,IAAI,EAA0C,CAAK;AACjH,6BAAQ,aAAA,EAAY,OAAc,OAAc,OAAc,WAAU,WAAU;AACpF;"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const react = require("react");
|
|
5
5
|
const button = require("../../components/button.cjs");
|
|
6
|
+
const IconButton = require("../../components/IconButton.cjs");
|
|
6
7
|
const InputField = require("../../components/InputField.cjs");
|
|
7
8
|
const SegmentedControl = require("../../components/SegmentedControl.cjs");
|
|
8
9
|
const Switch = require("../../components/Switch.cjs");
|
|
@@ -14,6 +15,8 @@ const callGraphModel = require("./call-graph-model.cjs");
|
|
|
14
15
|
const types = require("./types.cjs");
|
|
15
16
|
const UiHome = require("../../icons/components/UiHome.cjs");
|
|
16
17
|
const UiFilter = require("../../icons/components/UiFilter.cjs");
|
|
18
|
+
const UiExpandAll = require("../../icons/components/UiExpandAll.cjs");
|
|
19
|
+
const UiCollapseAll = require("../../icons/components/UiCollapseAll.cjs");
|
|
17
20
|
const UiWarningTriangle = require("../../icons/components/UiWarningTriangle.cjs");
|
|
18
21
|
const DIRECTIONS = [
|
|
19
22
|
{ id: "callers", label: "Callers" },
|
|
@@ -105,11 +108,13 @@ function GroupFacets({ exclude, groups, matches, onExclude, onDefaults, busy, vo
|
|
|
105
108
|
] })
|
|
106
109
|
] });
|
|
107
110
|
}
|
|
108
|
-
const ACCESS_LABELS = { call: "Calls", read: "Reads", write: "Writes" };
|
|
109
|
-
function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
111
|
+
const ACCESS_LABELS = { call: "Calls", read: "Reads", write: "Writes", variable: "Variables" };
|
|
112
|
+
function DataAccessControls({ access, onAccess, columns, onColumns, variables }) {
|
|
113
|
+
const lastOn = callGraphModel.baseAccess(access).length === 1;
|
|
110
114
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
111
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Access", children: types.CALL_GRAPH_ACCESS.map((type) => {
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Access", children: (variables ? [...types.CALL_GRAPH_ACCESS, "variable"] : types.CALL_GRAPH_ACCESS).map((type) => {
|
|
112
116
|
const on = access.includes(type);
|
|
117
|
+
const kept = on && lastOn && type !== "variable";
|
|
113
118
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
114
119
|
button.Button,
|
|
115
120
|
{
|
|
@@ -117,8 +122,8 @@ function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
|
117
122
|
size: "sm",
|
|
118
123
|
variant: on ? "secondary" : "outline",
|
|
119
124
|
"aria-pressed": on,
|
|
120
|
-
disabled:
|
|
121
|
-
title:
|
|
125
|
+
disabled: kept,
|
|
126
|
+
title: kept ? "At least one kind of access stays on" : void 0,
|
|
122
127
|
onClick: () => onAccess(callGraphModel.toggleAccess(access, type)),
|
|
123
128
|
children: ACCESS_LABELS[type]
|
|
124
129
|
},
|
|
@@ -128,6 +133,12 @@ function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
|
128
133
|
/* @__PURE__ */ jsxRuntime.jsx(Switch.Switch, { checked: columns, label: "Columns", onChange: onColumns })
|
|
129
134
|
] });
|
|
130
135
|
}
|
|
136
|
+
function GroupCollapseControls({ anyCollapsed, anyExpanded, onExpandAll, onCollapseAll }) {
|
|
137
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", role: "group", "aria-label": "Groups", children: [
|
|
138
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton.IconButton, { icon: UiExpandAll.UiExpandAll, label: "Expand all groups", className: "size-7", disabled: !anyCollapsed, onClick: onExpandAll }),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconButton.IconButton, { icon: UiCollapseAll.UiCollapseAll, label: "Collapse all groups", className: "size-7", disabled: !anyExpanded, onClick: onCollapseAll })
|
|
140
|
+
] });
|
|
141
|
+
}
|
|
131
142
|
function CallGraphToolbar(props) {
|
|
132
143
|
const { exclusions, pin, vocabulary } = props;
|
|
133
144
|
const excludedCount = (exclusions == null ? void 0 : exclusions.groups.filter((group) => group.excluded).length) ?? 0;
|
|
@@ -155,6 +166,7 @@ function CallGraphToolbar(props) {
|
|
|
155
166
|
/* @__PURE__ */ jsxRuntime.jsx(UiHome.UiHome, {}),
|
|
156
167
|
"Reset"
|
|
157
168
|
] }),
|
|
169
|
+
props.groupCollapse && /* @__PURE__ */ jsxRuntime.jsx(GroupCollapseControls, { ...props.groupCollapse }),
|
|
158
170
|
exclusions && hasExternal && /* @__PURE__ */ jsxRuntime.jsx(
|
|
159
171
|
Switch.Switch,
|
|
160
172
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraphToolbar.cjs","sources":["../../../src/data/call-graph/CallGraphToolbar.tsx"],"sourcesContent":["import { useState, type FormEvent, type ReactNode } from \"react\";\nimport { Button } from \"../../components/button\";\nimport { InputField } from \"../../components/InputField\";\nimport { SegmentedControl } from \"../../components/SegmentedControl\";\nimport { Switch } from \"../../components/Switch\";\nimport { UiFilter, UiHome, UiWarningTriangle } from \"../../icons\";\nimport { DropdownMenu } from \"../../overlay/DropdownMenu\";\nimport { Badge } from \"../Badge\";\nimport {\n addExcludePattern,\n EXCLUDE_EXTERNAL,\n excludeGroup,\n excludePatternError,\n includeGroup,\n removeExcludePattern,\n setExternalHidden,\n type ExcludeMatcher,\n} from \"./call-graph-exclude\";\nimport { capitalize, excludedTally, omittedParts } from \"./call-graph-labels\";\nimport { toggleAccess } from \"./call-graph-model\";\nimport type { CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport { CALL_GRAPH_ACCESS, type CallGraphAccess, type CallGraphDirection, type CallGraphGroupFact, type CallGraphOmitted } from \"./types\";\n\nconst DIRECTIONS: { id: CallGraphDirection; label: string }[] = [\n { id: \"callers\", label: \"Callers\" },\n { id: \"both\", label: \"Both\" },\n { id: \"callees\", label: \"Callees\" },\n];\n\nfunction DepthStepper({ depth, maxDepth, onChange }: { depth: number; maxDepth: number; onChange: (depth: number) => void }) {\n return (\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Depth\">\n <span className=\"text-xs text-muted-foreground\">Depth</span>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"size-8 px-0\" aria-label=\"Decrease depth\" disabled={depth <= 1} onClick={() => onChange(depth - 1)}>−</Button>\n <output className=\"w-5 text-center text-sm font-medium tabular-nums\" aria-live=\"polite\" aria-label=\"Graph depth\">{depth}</output>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"size-8 px-0\" aria-label=\"Increase depth\" disabled={depth >= maxDepth} onClick={() => onChange(depth + 1)}>+</Button>\n </div>\n );\n}\n\nfunction OmittedChip({ omitted, noun }: { omitted: CallGraphOmitted; noun: string }) {\n const parts = omittedParts(omitted);\n if (parts.length === 0) return null;\n const tally = excludedTally(omitted).map(({ group, count }) => `${group}: ${count}`);\n const title = [`Not drawn: ${parts.join(\", \")}`, ...(tally.length ? [`Excluded per ${noun}:`, ...tally] : [])].join(\"\\n\");\n return (\n <span title={title} data-testid=\"graph-omitted\">\n <Badge tone=\"warning\" size=\"md\" icon={UiWarningTriangle} clickToCopy={false}>{parts.join(\" · \")}</Badge>\n </span>\n );\n}\n\nexport interface ExclusionsProps {\n /** The patterns in force. */\n exclude: string[];\n groups: CallGraphGroupFact[];\n matches: ExcludeMatcher;\n onExclude: (patterns: string[]) => void;\n onDefaults: () => void;\n /** A graph for the last edit is loading: the facts describe the one before it, so editing waits. */\n busy: boolean;\n vocabulary: CallGraphVocabulary;\n}\n\nfunction GroupRow({ group, onToggle }: { group: CallGraphGroupFact; onToggle: () => void }) {\n const name = group.label ?? group.name;\n return (\n <li className=\"flex items-center gap-2 py-1\">\n <Switch checked={!group.excluded} onChange={onToggle} aria-label={`Show ${name}`} />\n <span className=\"min-w-0 flex-1 truncate font-mono text-xs\" title={group.name}>{name}</span>\n {group.external && <Badge variant=\"outline\" size=\"sm\" clickToCopy={false}>external</Badge>}\n <span className=\"w-8 shrink-0 text-right text-xs tabular-nums text-muted-foreground\" title={`${group.nodes} nodes`}>{group.nodes}</span>\n </li>\n );\n}\n\n/** The group facets: one switch per group the walk reached, the patterns in force, and free-text patterns. */\nfunction GroupFacets({ exclude, groups, matches, onExclude, onDefaults, busy, vocabulary }: ExclusionsProps) {\n const [filter, setFilter] = useState(\"\");\n const [pattern, setPattern] = useState(\"\");\n const [error, setError] = useState<string>();\n const { plural, patternHint } = vocabulary.group;\n const needle = filter.trim().toLowerCase();\n const shown = groups.filter((group) => `${group.name} ${group.label ?? \"\"}`.toLowerCase().includes(needle));\n const submit = (event: FormEvent) => {\n event.preventDefault();\n const typed = pattern.trim();\n const problem = excludePatternError(exclude, typed);\n setError(problem);\n if (problem) return;\n setPattern(\"\");\n onExclude(addExcludePattern(exclude, typed));\n };\n // The filter box comes first: the menu focuses its first control on opening, which must not be one that drops an exclusion.\n return (\n <fieldset disabled={busy} aria-busy={busy} className=\"flex w-96 min-w-0 max-w-[90vw] flex-col gap-2 p-2 text-sm\">\n <InputField aria-label={`Filter ${plural}`} placeholder={`Filter ${plural}`} value={filter} onChange={setFilter} />\n <div className=\"flex flex-wrap items-center gap-1\" aria-label=\"Exclusion patterns\">\n <span className=\"text-xs text-muted-foreground\">Excluding</span>\n {exclude.length === 0 && <span className=\"text-xs text-muted-foreground\">nothing</span>}\n {exclude.map((entry) => (\n <button key={entry} type=\"button\" className=\"rounded border border-border px-1.5 font-mono text-xs hover:bg-muted\"\n aria-label={`Stop excluding ${entry}`} title={`Stop excluding ${entry}`} onClick={() => onExclude(removeExcludePattern(exclude, entry))}>\n {entry} ×\n </button>\n ))}\n </div>\n <ul className=\"max-h-72 overflow-y-auto pr-1\" aria-label={plural}>\n {shown.map((group) => (\n <GroupRow key={group.name} group={group}\n onToggle={() => onExclude(group.excluded ? includeGroup(exclude, group, groups, matches) : excludeGroup(exclude, group.name))} />\n ))}\n {shown.length === 0 && (\n <li className=\"py-1 text-xs text-muted-foreground\">{groups.length ? `No ${vocabulary.group.noun} matches the filter.` : `The graph reached no ${vocabulary.group.noun}.`}</li>\n )}\n </ul>\n <form className=\"flex items-start gap-2\" onSubmit={submit}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <InputField aria-label=\"Exclude pattern\" placeholder={patternHint} value={pattern} onChange={setPattern} />\n {error && <span role=\"alert\" className=\"text-xs text-destructive\">{error}</span>}\n </div>\n <Button type=\"submit\" size=\"sm\" variant=\"outline\">Exclude</Button>\n </form>\n <div className=\"flex justify-between gap-2 border-t border-border pt-2\">\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={onDefaults}>Reset to defaults</Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => onExclude([])}>Show all</Button>\n </div>\n </fieldset>\n );\n}\n\nconst ACCESS_LABELS: Record<CallGraphAccess, string> = { call: \"Calls\", read: \"Reads\", write: \"Writes\" };\n\nexport interface DataAccessProps {\n access: CallGraphAccess[];\n onAccess: (access: CallGraphAccess[]) => void;\n columns: boolean;\n onColumns: (columns: boolean) => void;\n}\n\n/** Which edge types the graph follows, at least one, and whether columns and fields are nodes of their own. */\nfunction DataAccessControls({ access, onAccess, columns, onColumns }: DataAccessProps) {\n return (\n <>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Access\">\n {CALL_GRAPH_ACCESS.map((type) => {\n const on = access.includes(type);\n return (\n <Button key={type} type=\"button\" size=\"sm\" variant={on ? \"secondary\" : \"outline\"} aria-pressed={on} disabled={on && access.length === 1}\n title={on && access.length === 1 ? \"At least one kind of access stays on\" : undefined} onClick={() => onAccess(toggleAccess(access, type))}>\n {ACCESS_LABELS[type]}\n </Button>\n );\n })}\n </div>\n <Switch checked={columns} label=\"Columns\" onChange={onColumns} />\n </>\n );\n}\n\nexport interface CallGraphToolbarProps {\n /** Shown only when the host's graph has reads and writes. */\n data?: DataAccessProps | undefined;\n direction: CallGraphDirection;\n depth: number;\n maxDepth: number;\n /** Shown only when the host keeps a root across selection changes. */\n pin?: { pinned: boolean; canPin: boolean; onPin: (pinned: boolean) => void } | undefined;\n exclusions?: ExclusionsProps | undefined;\n omitted?: CallGraphOmitted | undefined;\n /** Host content at the toolbar's end, such as server timing. */\n end?: ReactNode;\n onDirection: (direction: CallGraphDirection) => void;\n onDepth: (depth: number) => void;\n onFit: () => void;\n onReset: () => void;\n vocabulary: CallGraphVocabulary;\n}\n\nexport function CallGraphToolbar(props: CallGraphToolbarProps) {\n const { exclusions, pin, vocabulary } = props;\n const excludedCount = exclusions?.groups.filter((group) => group.excluded).length ?? 0;\n const hasExternal = exclusions?.groups.some((group) => group.external) ?? false;\n const { noun, plural } = vocabulary.group;\n return (\n <div className=\"flex flex-wrap items-center gap-3\">\n <SegmentedControl value={props.direction} options={DIRECTIONS} onChange={props.onDirection} size=\"sm\" aria-label=\"Direction\" />\n <DepthStepper depth={props.depth} maxDepth={props.maxDepth} onChange={props.onDepth} />\n {props.data && <DataAccessControls {...props.data} />}\n {pin && (\n <Button type=\"button\" variant={pin.pinned ? \"secondary\" : \"outline\"} size=\"sm\" disabled={!pin.pinned && !pin.canPin} aria-pressed={pin.pinned}\n title={pin.pinned ? \"The graph keeps this root while the selection changes\" : \"Keep this root while the selection changes\"} onClick={() => pin.onPin(!pin.pinned)}>\n {pin.pinned ? \"Unpin root\" : \"Pin root\"}\n </Button>\n )}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={props.onFit}>Fit</Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={props.onReset}><UiHome />Reset</Button>\n {exclusions && hasExternal && (\n <Switch checked={exclusions.exclude.includes(EXCLUDE_EXTERNAL)} disabled={exclusions.busy} label=\"Hide all external\"\n onChange={(hidden) => exclusions.onExclude(setExternalHidden(exclusions.exclude, hidden))} />\n )}\n {exclusions && (\n <DropdownMenu icon={UiFilter} label={`${capitalize(plural)}${excludedCount ? ` (${excludedCount} excluded)` : \"\"}`} variant=\"outline\" size=\"sm\"\n menuLabel={`${capitalize(noun)} exclusions`} title={`Choose the ${plural} the graph leaves out`}>\n {() => <GroupFacets {...exclusions} />}\n </DropdownMenu>\n )}\n <div className=\"ml-auto flex items-center gap-2\">\n {props.omitted && <OmittedChip omitted={props.omitted} noun={noun} />}\n {props.end}\n </div>\n </div>\n );\n}\n"],"names":["jsx","Button","omittedParts","excludedTally","Badge","UiWarningTriangle","jsxs","Switch","useState","excludePatternError","addExcludePattern","InputField","removeExcludePattern","includeGroup","excludeGroup","Fragment","CALL_GRAPH_ACCESS","toggleAccess","SegmentedControl","UiHome","EXCLUDE_EXTERNAL","setExternalHidden","DropdownMenu","UiFilter","capitalize"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CallGraphToolbar.cjs","sources":["../../../src/data/call-graph/CallGraphToolbar.tsx"],"sourcesContent":["import { useState, type FormEvent, type ReactNode } from \"react\";\nimport { Button } from \"../../components/button\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { InputField } from \"../../components/InputField\";\nimport { SegmentedControl } from \"../../components/SegmentedControl\";\nimport { Switch } from \"../../components/Switch\";\nimport { UiCollapseAll, UiExpandAll, UiFilter, UiHome, UiWarningTriangle } from \"../../icons\";\nimport { DropdownMenu } from \"../../overlay/DropdownMenu\";\nimport { Badge } from \"../Badge\";\nimport {\n addExcludePattern,\n EXCLUDE_EXTERNAL,\n excludeGroup,\n excludePatternError,\n includeGroup,\n removeExcludePattern,\n setExternalHidden,\n type ExcludeMatcher,\n} from \"./call-graph-exclude\";\nimport { capitalize, excludedTally, omittedParts } from \"./call-graph-labels\";\nimport { baseAccess, toggleAccess } from \"./call-graph-model\";\nimport type { CallGraphVocabulary } from \"./call-graph-vocabulary\";\nimport { CALL_GRAPH_ACCESS, type CallGraphAccess, type CallGraphDirection, type CallGraphGroupFact, type CallGraphOmitted } from \"./types\";\n\nconst DIRECTIONS: { id: CallGraphDirection; label: string }[] = [\n { id: \"callers\", label: \"Callers\" },\n { id: \"both\", label: \"Both\" },\n { id: \"callees\", label: \"Callees\" },\n];\n\nfunction DepthStepper({ depth, maxDepth, onChange }: { depth: number; maxDepth: number; onChange: (depth: number) => void }) {\n return (\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Depth\">\n <span className=\"text-xs text-muted-foreground\">Depth</span>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"size-8 px-0\" aria-label=\"Decrease depth\" disabled={depth <= 1} onClick={() => onChange(depth - 1)}>−</Button>\n <output className=\"w-5 text-center text-sm font-medium tabular-nums\" aria-live=\"polite\" aria-label=\"Graph depth\">{depth}</output>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"size-8 px-0\" aria-label=\"Increase depth\" disabled={depth >= maxDepth} onClick={() => onChange(depth + 1)}>+</Button>\n </div>\n );\n}\n\nfunction OmittedChip({ omitted, noun }: { omitted: CallGraphOmitted; noun: string }) {\n const parts = omittedParts(omitted);\n if (parts.length === 0) return null;\n const tally = excludedTally(omitted).map(({ group, count }) => `${group}: ${count}`);\n const title = [`Not drawn: ${parts.join(\", \")}`, ...(tally.length ? [`Excluded per ${noun}:`, ...tally] : [])].join(\"\\n\");\n return (\n <span title={title} data-testid=\"graph-omitted\">\n <Badge tone=\"warning\" size=\"md\" icon={UiWarningTriangle} clickToCopy={false}>{parts.join(\" · \")}</Badge>\n </span>\n );\n}\n\nexport interface ExclusionsProps {\n /** The patterns in force. */\n exclude: string[];\n groups: CallGraphGroupFact[];\n matches: ExcludeMatcher;\n onExclude: (patterns: string[]) => void;\n onDefaults: () => void;\n /** A graph for the last edit is loading: the facts describe the one before it, so editing waits. */\n busy: boolean;\n vocabulary: CallGraphVocabulary;\n}\n\nfunction GroupRow({ group, onToggle }: { group: CallGraphGroupFact; onToggle: () => void }) {\n const name = group.label ?? group.name;\n return (\n <li className=\"flex items-center gap-2 py-1\">\n <Switch checked={!group.excluded} onChange={onToggle} aria-label={`Show ${name}`} />\n <span className=\"min-w-0 flex-1 truncate font-mono text-xs\" title={group.name}>{name}</span>\n {group.external && <Badge variant=\"outline\" size=\"sm\" clickToCopy={false}>external</Badge>}\n <span className=\"w-8 shrink-0 text-right text-xs tabular-nums text-muted-foreground\" title={`${group.nodes} nodes`}>{group.nodes}</span>\n </li>\n );\n}\n\n/** The group facets: one switch per group the walk reached, the patterns in force, and free-text patterns. */\nfunction GroupFacets({ exclude, groups, matches, onExclude, onDefaults, busy, vocabulary }: ExclusionsProps) {\n const [filter, setFilter] = useState(\"\");\n const [pattern, setPattern] = useState(\"\");\n const [error, setError] = useState<string>();\n const { plural, patternHint } = vocabulary.group;\n const needle = filter.trim().toLowerCase();\n const shown = groups.filter((group) => `${group.name} ${group.label ?? \"\"}`.toLowerCase().includes(needle));\n const submit = (event: FormEvent) => {\n event.preventDefault();\n const typed = pattern.trim();\n const problem = excludePatternError(exclude, typed);\n setError(problem);\n if (problem) return;\n setPattern(\"\");\n onExclude(addExcludePattern(exclude, typed));\n };\n // The filter box comes first: the menu focuses its first control on opening, which must not be one that drops an exclusion.\n return (\n <fieldset disabled={busy} aria-busy={busy} className=\"flex w-96 min-w-0 max-w-[90vw] flex-col gap-2 p-2 text-sm\">\n <InputField aria-label={`Filter ${plural}`} placeholder={`Filter ${plural}`} value={filter} onChange={setFilter} />\n <div className=\"flex flex-wrap items-center gap-1\" aria-label=\"Exclusion patterns\">\n <span className=\"text-xs text-muted-foreground\">Excluding</span>\n {exclude.length === 0 && <span className=\"text-xs text-muted-foreground\">nothing</span>}\n {exclude.map((entry) => (\n <button key={entry} type=\"button\" className=\"rounded border border-border px-1.5 font-mono text-xs hover:bg-muted\"\n aria-label={`Stop excluding ${entry}`} title={`Stop excluding ${entry}`} onClick={() => onExclude(removeExcludePattern(exclude, entry))}>\n {entry} ×\n </button>\n ))}\n </div>\n <ul className=\"max-h-72 overflow-y-auto pr-1\" aria-label={plural}>\n {shown.map((group) => (\n <GroupRow key={group.name} group={group}\n onToggle={() => onExclude(group.excluded ? includeGroup(exclude, group, groups, matches) : excludeGroup(exclude, group.name))} />\n ))}\n {shown.length === 0 && (\n <li className=\"py-1 text-xs text-muted-foreground\">{groups.length ? `No ${vocabulary.group.noun} matches the filter.` : `The graph reached no ${vocabulary.group.noun}.`}</li>\n )}\n </ul>\n <form className=\"flex items-start gap-2\" onSubmit={submit}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <InputField aria-label=\"Exclude pattern\" placeholder={patternHint} value={pattern} onChange={setPattern} />\n {error && <span role=\"alert\" className=\"text-xs text-destructive\">{error}</span>}\n </div>\n <Button type=\"submit\" size=\"sm\" variant=\"outline\">Exclude</Button>\n </form>\n <div className=\"flex justify-between gap-2 border-t border-border pt-2\">\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={onDefaults}>Reset to defaults</Button>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => onExclude([])}>Show all</Button>\n </div>\n </fieldset>\n );\n}\n\nconst ACCESS_LABELS: Record<CallGraphAccess, string> = { call: \"Calls\", read: \"Reads\", write: \"Writes\", variable: \"Variables\" };\n\nexport interface DataAccessProps {\n access: CallGraphAccess[];\n onAccess: (access: CallGraphAccess[]) => void;\n columns: boolean;\n onColumns: (columns: boolean) => void;\n /** Offers the Variables toggle, on top of the access types. */\n variables?: boolean;\n}\n\n/** Which edge types the graph follows, at least one of calls, reads and writes, and whether columns and fields are nodes of their own. */\nfunction DataAccessControls({ access, onAccess, columns, onColumns, variables }: DataAccessProps) {\n const lastOn = baseAccess(access).length === 1;\n return (\n <>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Access\">\n {(variables ? [...CALL_GRAPH_ACCESS, \"variable\" as const] : CALL_GRAPH_ACCESS).map((type) => {\n const on = access.includes(type);\n const kept = on && lastOn && type !== \"variable\";\n return (\n <Button key={type} type=\"button\" size=\"sm\" variant={on ? \"secondary\" : \"outline\"} aria-pressed={on} disabled={kept}\n title={kept ? \"At least one kind of access stays on\" : undefined} onClick={() => onAccess(toggleAccess(access, type))}>\n {ACCESS_LABELS[type]}\n </Button>\n );\n })}\n </div>\n <Switch checked={columns} label=\"Columns\" onChange={onColumns} />\n </>\n );\n}\n\nexport interface GroupCollapseProps {\n anyCollapsed: boolean;\n anyExpanded: boolean;\n onExpandAll: () => void;\n onCollapseAll: () => void;\n}\n\n/** Expand or collapse every group the graph draws at once. */\nfunction GroupCollapseControls({ anyCollapsed, anyExpanded, onExpandAll, onCollapseAll }: GroupCollapseProps) {\n return (\n <div className=\"flex items-center gap-0.5\" role=\"group\" aria-label=\"Groups\">\n <IconButton icon={UiExpandAll} label=\"Expand all groups\" className=\"size-7\" disabled={!anyCollapsed} onClick={onExpandAll} />\n <IconButton icon={UiCollapseAll} label=\"Collapse all groups\" className=\"size-7\" disabled={!anyExpanded} onClick={onCollapseAll} />\n </div>\n );\n}\n\nexport interface CallGraphToolbarProps {\n /** Shown only when the host's graph has reads and writes. */\n data?: DataAccessProps | undefined;\n /** Shown only when the graph draws a group that can collapse. */\n groupCollapse?: GroupCollapseProps | undefined;\n direction: CallGraphDirection;\n depth: number;\n maxDepth: number;\n /** Shown only when the host keeps a root across selection changes. */\n pin?: { pinned: boolean; canPin: boolean; onPin: (pinned: boolean) => void } | undefined;\n exclusions?: ExclusionsProps | undefined;\n omitted?: CallGraphOmitted | undefined;\n /** Host content at the toolbar's end, such as server timing. */\n end?: ReactNode;\n onDirection: (direction: CallGraphDirection) => void;\n onDepth: (depth: number) => void;\n onFit: () => void;\n onReset: () => void;\n vocabulary: CallGraphVocabulary;\n}\n\nexport function CallGraphToolbar(props: CallGraphToolbarProps) {\n const { exclusions, pin, vocabulary } = props;\n const excludedCount = exclusions?.groups.filter((group) => group.excluded).length ?? 0;\n const hasExternal = exclusions?.groups.some((group) => group.external) ?? false;\n const { noun, plural } = vocabulary.group;\n return (\n <div className=\"flex flex-wrap items-center gap-3\">\n <SegmentedControl value={props.direction} options={DIRECTIONS} onChange={props.onDirection} size=\"sm\" aria-label=\"Direction\" />\n <DepthStepper depth={props.depth} maxDepth={props.maxDepth} onChange={props.onDepth} />\n {props.data && <DataAccessControls {...props.data} />}\n {pin && (\n <Button type=\"button\" variant={pin.pinned ? \"secondary\" : \"outline\"} size=\"sm\" disabled={!pin.pinned && !pin.canPin} aria-pressed={pin.pinned}\n title={pin.pinned ? \"The graph keeps this root while the selection changes\" : \"Keep this root while the selection changes\"} onClick={() => pin.onPin(!pin.pinned)}>\n {pin.pinned ? \"Unpin root\" : \"Pin root\"}\n </Button>\n )}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={props.onFit}>Fit</Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={props.onReset}><UiHome />Reset</Button>\n {props.groupCollapse && <GroupCollapseControls {...props.groupCollapse} />}\n {exclusions && hasExternal && (\n <Switch checked={exclusions.exclude.includes(EXCLUDE_EXTERNAL)} disabled={exclusions.busy} label=\"Hide all external\"\n onChange={(hidden) => exclusions.onExclude(setExternalHidden(exclusions.exclude, hidden))} />\n )}\n {exclusions && (\n <DropdownMenu icon={UiFilter} label={`${capitalize(plural)}${excludedCount ? ` (${excludedCount} excluded)` : \"\"}`} variant=\"outline\" size=\"sm\"\n menuLabel={`${capitalize(noun)} exclusions`} title={`Choose the ${plural} the graph leaves out`}>\n {() => <GroupFacets {...exclusions} />}\n </DropdownMenu>\n )}\n <div className=\"ml-auto flex items-center gap-2\">\n {props.omitted && <OmittedChip omitted={props.omitted} noun={noun} />}\n {props.end}\n </div>\n </div>\n );\n}\n"],"names":["jsx","Button","omittedParts","excludedTally","Badge","UiWarningTriangle","jsxs","Switch","useState","excludePatternError","addExcludePattern","InputField","removeExcludePattern","includeGroup","excludeGroup","baseAccess","Fragment","CALL_GRAPH_ACCESS","toggleAccess","IconButton","UiExpandAll","UiCollapseAll","SegmentedControl","UiHome","EXCLUDE_EXTERNAL","setExternalHidden","DropdownMenu","UiFilter","capitalize"],"mappings":"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"}
|
|
@@ -18,10 +18,20 @@ export interface DataAccessProps {
|
|
|
18
18
|
onAccess: (access: CallGraphAccess[]) => void;
|
|
19
19
|
columns: boolean;
|
|
20
20
|
onColumns: (columns: boolean) => void;
|
|
21
|
+
/** Offers the Variables toggle, on top of the access types. */
|
|
22
|
+
variables?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface GroupCollapseProps {
|
|
25
|
+
anyCollapsed: boolean;
|
|
26
|
+
anyExpanded: boolean;
|
|
27
|
+
onExpandAll: () => void;
|
|
28
|
+
onCollapseAll: () => void;
|
|
21
29
|
}
|
|
22
30
|
export interface CallGraphToolbarProps {
|
|
23
31
|
/** Shown only when the host's graph has reads and writes. */
|
|
24
32
|
data?: DataAccessProps | undefined;
|
|
33
|
+
/** Shown only when the graph draws a group that can collapse. */
|
|
34
|
+
groupCollapse?: GroupCollapseProps | undefined;
|
|
25
35
|
direction: CallGraphDirection;
|
|
26
36
|
depth: number;
|
|
27
37
|
maxDepth: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallGraphToolbar.d.ts","sourceRoot":"","sources":["../../../src/data/call-graph/CallGraphToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CallGraphToolbar.d.ts","sourceRoot":"","sources":["../../../src/data/call-graph/CallGraphToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASjE,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAqB,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA+B3I,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,oGAAoG;IACpG,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,mBAAmB,CAAC;CACjC;AAuED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAwBD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAYD,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,IAAI,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACnC,iEAAiE;IACjE,aAAa,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC/C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;IACzF,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,mBAAmB,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,+BAmC5D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Button } from "../../components/button.js";
|
|
4
|
+
import { IconButton } from "../../components/IconButton.js";
|
|
4
5
|
import { InputField } from "../../components/InputField.js";
|
|
5
6
|
import { SegmentedControl } from "../../components/SegmentedControl.js";
|
|
6
7
|
import { Switch } from "../../components/Switch.js";
|
|
@@ -8,10 +9,12 @@ import { DropdownMenu } from "../../overlay/DropdownMenu.js";
|
|
|
8
9
|
import { Badge } from "../Badge.js";
|
|
9
10
|
import { setExternalHidden, EXCLUDE_EXTERNAL, removeExcludePattern, includeGroup, excludeGroup, excludePatternError, addExcludePattern } from "./call-graph-exclude.js";
|
|
10
11
|
import { capitalize, omittedParts, excludedTally } from "./call-graph-labels.js";
|
|
11
|
-
import { toggleAccess } from "./call-graph-model.js";
|
|
12
|
+
import { baseAccess, toggleAccess } from "./call-graph-model.js";
|
|
12
13
|
import { CALL_GRAPH_ACCESS } from "./types.js";
|
|
13
14
|
import { UiHome } from "../../icons/components/UiHome.js";
|
|
14
15
|
import { UiFilter } from "../../icons/components/UiFilter.js";
|
|
16
|
+
import { UiExpandAll } from "../../icons/components/UiExpandAll.js";
|
|
17
|
+
import { UiCollapseAll } from "../../icons/components/UiCollapseAll.js";
|
|
15
18
|
import { UiWarningTriangle } from "../../icons/components/UiWarningTriangle.js";
|
|
16
19
|
const DIRECTIONS = [
|
|
17
20
|
{ id: "callers", label: "Callers" },
|
|
@@ -103,11 +106,13 @@ function GroupFacets({ exclude, groups, matches, onExclude, onDefaults, busy, vo
|
|
|
103
106
|
] })
|
|
104
107
|
] });
|
|
105
108
|
}
|
|
106
|
-
const ACCESS_LABELS = { call: "Calls", read: "Reads", write: "Writes" };
|
|
107
|
-
function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
109
|
+
const ACCESS_LABELS = { call: "Calls", read: "Reads", write: "Writes", variable: "Variables" };
|
|
110
|
+
function DataAccessControls({ access, onAccess, columns, onColumns, variables }) {
|
|
111
|
+
const lastOn = baseAccess(access).length === 1;
|
|
108
112
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
109
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Access", children: CALL_GRAPH_ACCESS.map((type) => {
|
|
113
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Access", children: (variables ? [...CALL_GRAPH_ACCESS, "variable"] : CALL_GRAPH_ACCESS).map((type) => {
|
|
110
114
|
const on = access.includes(type);
|
|
115
|
+
const kept = on && lastOn && type !== "variable";
|
|
111
116
|
return /* @__PURE__ */ jsx(
|
|
112
117
|
Button,
|
|
113
118
|
{
|
|
@@ -115,8 +120,8 @@ function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
|
115
120
|
size: "sm",
|
|
116
121
|
variant: on ? "secondary" : "outline",
|
|
117
122
|
"aria-pressed": on,
|
|
118
|
-
disabled:
|
|
119
|
-
title:
|
|
123
|
+
disabled: kept,
|
|
124
|
+
title: kept ? "At least one kind of access stays on" : void 0,
|
|
120
125
|
onClick: () => onAccess(toggleAccess(access, type)),
|
|
121
126
|
children: ACCESS_LABELS[type]
|
|
122
127
|
},
|
|
@@ -126,6 +131,12 @@ function DataAccessControls({ access, onAccess, columns, onColumns }) {
|
|
|
126
131
|
/* @__PURE__ */ jsx(Switch, { checked: columns, label: "Columns", onChange: onColumns })
|
|
127
132
|
] });
|
|
128
133
|
}
|
|
134
|
+
function GroupCollapseControls({ anyCollapsed, anyExpanded, onExpandAll, onCollapseAll }) {
|
|
135
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", role: "group", "aria-label": "Groups", children: [
|
|
136
|
+
/* @__PURE__ */ jsx(IconButton, { icon: UiExpandAll, label: "Expand all groups", className: "size-7", disabled: !anyCollapsed, onClick: onExpandAll }),
|
|
137
|
+
/* @__PURE__ */ jsx(IconButton, { icon: UiCollapseAll, label: "Collapse all groups", className: "size-7", disabled: !anyExpanded, onClick: onCollapseAll })
|
|
138
|
+
] });
|
|
139
|
+
}
|
|
129
140
|
function CallGraphToolbar(props) {
|
|
130
141
|
const { exclusions, pin, vocabulary } = props;
|
|
131
142
|
const excludedCount = (exclusions == null ? void 0 : exclusions.groups.filter((group) => group.excluded).length) ?? 0;
|
|
@@ -153,6 +164,7 @@ function CallGraphToolbar(props) {
|
|
|
153
164
|
/* @__PURE__ */ jsx(UiHome, {}),
|
|
154
165
|
"Reset"
|
|
155
166
|
] }),
|
|
167
|
+
props.groupCollapse && /* @__PURE__ */ jsx(GroupCollapseControls, { ...props.groupCollapse }),
|
|
156
168
|
exclusions && hasExternal && /* @__PURE__ */ jsx(
|
|
157
169
|
Switch,
|
|
158
170
|
{
|