@principal-ai/subsystems-react 0.56.11 → 0.56.13
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/dist/subsystem/C4Graph.d.ts.map +1 -1
- package/dist/subsystem/C4Graph.js +10 -4
- package/dist/subsystem/C4Graph.js.map +1 -1
- package/dist/subsystem/DescriptionOverlay.d.ts +6 -0
- package/dist/subsystem/DescriptionOverlay.d.ts.map +1 -0
- package/dist/subsystem/DescriptionOverlay.js +58 -0
- package/dist/subsystem/DescriptionOverlay.js.map +1 -0
- package/dist/subsystem/DiagnosticToggle.d.ts.map +1 -1
- package/dist/subsystem/DiagnosticToggle.js +2 -1
- package/dist/subsystem/DiagnosticToggle.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts +2 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +307 -284
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/SubsystemFileTree.d.ts.map +1 -1
- package/dist/subsystem/SubsystemFileTree.js +2 -1
- package/dist/subsystem/SubsystemFileTree.js.map +1 -1
- package/dist/subsystem/TrailStepsNav.d.ts.map +1 -1
- package/dist/subsystem/TrailStepsNav.js +11 -8
- package/dist/subsystem/TrailStepsNav.js.map +1 -1
- package/dist/subsystem/TrailsPanel.d.ts +1 -1
- package/dist/subsystem/TrailsPanel.d.ts.map +1 -1
- package/dist/subsystem/TrailsPanel.js +42 -66
- package/dist/subsystem/TrailsPanel.js.map +1 -1
- package/package.json +1 -1
- package/src/stories/Canvases/C4/C4Draft.stories.tsx +238 -0
- package/src/stories/Canvases/Subsystem/TrailSidebarViews.stories.tsx +2 -2
- package/src/subsystem/C4Graph.tsx +10 -4
- package/src/subsystem/DescriptionOverlay.test.tsx +76 -0
- package/src/subsystem/DescriptionOverlay.tsx +101 -0
- package/src/subsystem/DiagnosticToggle.tsx +2 -1
- package/src/subsystem/SubsystemComponentGraph.sidebar.test.tsx +81 -10
- package/src/subsystem/SubsystemComponentGraph.tsx +68 -26
- package/src/subsystem/SubsystemFileTree.tsx +2 -1
- package/src/subsystem/TrailStepsNav.test.tsx +38 -0
- package/src/subsystem/TrailStepsNav.tsx +11 -8
- package/src/subsystem/TrailsPanel.test.tsx +99 -35
- package/src/subsystem/TrailsPanel.tsx +38 -85
|
@@ -34,6 +34,7 @@ import { GRAPH_CANVAS_CLASS, GRAPH_NAV_PROPS, GraphChrome, GraphLayerStyle, LAYO
|
|
|
34
34
|
import { ComponentDeclaration } from './ComponentDeclaration';
|
|
35
35
|
import { FileDrawer, FILE_DRAWER_HEIGHT_MS } from './FileDrawer';
|
|
36
36
|
import { GraphWithSidebar } from './GraphWithSidebar';
|
|
37
|
+
import { DescriptionOverlay } from './DescriptionOverlay';
|
|
37
38
|
import { TrailsPanel, TRAIL_PLAY_PAUSE_MS } from './TrailsPanel';
|
|
38
39
|
import { EDGE_LABEL_WIDTH, EDGE_LABEL_HEIGHT, EDGE_LABEL_FONT_SIZE, EDGE_LABEL_CLOUD_PATH, EDGE_LABEL_CLOUD_EXTRA_TOP, } from '../utils/edgeLabel';
|
|
39
40
|
/** Identifiers a token could match to name this component as a construct. */
|
|
@@ -130,6 +131,7 @@ const TrailDrawerContent = memo(function TrailDrawerContent({ render, trail, ste
|
|
|
130
131
|
function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirection: layoutDirectionProp, defaultLayoutDirection = 'horizontal', onLayoutDirectionChange, hideLayoutToggle = false, refocusOnLayoutFlip = true, initialTrailId, onTrailSelect, onTrailStepHover, onReorderTrails, stepEmphasis, onRemoveStepEmphasis, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, showSingletonFrames = true, moduleNesting, edgeView, hideSidebar, trailStepMode = 'focus', autoPlayTrails = false, trailAutoPlayIntervalMs = TRAIL_PLAY_PAUSE_MS, zoomOnTrailFocus = true, trailFocusDurationMs = 300, graphTitle, showTrailTitle = false, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, issues, showIssues, filesActive, sidebarScope, onSidebarTrailChange, focusIssueCategory, laneStatus, onSelectIssue, onApplyIssueFix, onHoverIssue, renderFileViewer, renderTrailViewer, onFileSelect, componentVerification, onInspectSymbol, boundaryColors, codeProcessKeys, hideDrawer = false, persistKey, liveEvents, agentsPanel }) {
|
|
131
132
|
const { theme } = useTheme();
|
|
132
133
|
const { fitView, fitBounds } = useReactFlow();
|
|
134
|
+
const [descriptionOpen, setDescriptionOpen] = useState(false);
|
|
133
135
|
const viewport = useViewport();
|
|
134
136
|
// Restored once per mount from `localStorage` (see `readViewState`). Each
|
|
135
137
|
// graph is its own tab/mount, so `persistKey` is stable for a mount.
|
|
@@ -725,7 +727,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
725
727
|
// node says "diagnostics here" for every finding the sidebar lists.
|
|
726
728
|
const issueBadgeByAlias = useMemo(() => {
|
|
727
729
|
const map = new Map();
|
|
728
|
-
if (!issues?.length)
|
|
730
|
+
if (showIssues !== true || !issues?.length)
|
|
729
731
|
return map;
|
|
730
732
|
for (const issue of issues) {
|
|
731
733
|
const rung = issueRung(issue.kind);
|
|
@@ -760,7 +762,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
760
762
|
map.set(alias, { ...badge, kind: kinded.kind });
|
|
761
763
|
}
|
|
762
764
|
return map;
|
|
763
|
-
}, [issues, issueComponent]);
|
|
765
|
+
}, [showIssues, issues, issueComponent]);
|
|
764
766
|
// Per-frame diagnostics badge: the same fold, but for findings about a
|
|
765
767
|
// BOUNDARY rather than a construct. Keyed by the region's React Flow node
|
|
766
768
|
// id — a `module` target names a module frame, a `process` target a process
|
|
@@ -770,7 +772,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
770
772
|
// borrowing its layer's icon would imply the frame is at fault for it.
|
|
771
773
|
const regionIssueByNodeId = useMemo(() => {
|
|
772
774
|
const map = new Map();
|
|
773
|
-
if (!issues?.length)
|
|
775
|
+
if (showIssues !== true || !issues?.length)
|
|
774
776
|
return map;
|
|
775
777
|
for (const issue of issues) {
|
|
776
778
|
const target = issue.target;
|
|
@@ -791,7 +793,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
791
793
|
});
|
|
792
794
|
}
|
|
793
795
|
return map;
|
|
794
|
-
}, [issues]);
|
|
796
|
+
}, [showIssues, issues]);
|
|
795
797
|
// Per-edge step verification badge: maps edge IDs to step verification status.
|
|
796
798
|
// Keyed by the React Flow edge id (from → mechanism → to). An edge can have
|
|
797
799
|
// multiple steps with issues; we show the worst status.
|
|
@@ -804,7 +806,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
804
806
|
step_span_stale: 1,
|
|
805
807
|
};
|
|
806
808
|
const map = new Map();
|
|
807
|
-
if (!issues?.length || !trails?.length) {
|
|
809
|
+
if (showIssues !== true || !issues?.length || !trails?.length) {
|
|
808
810
|
return map;
|
|
809
811
|
}
|
|
810
812
|
for (const issue of issues) {
|
|
@@ -831,7 +833,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
831
833
|
});
|
|
832
834
|
}
|
|
833
835
|
return map;
|
|
834
|
-
}, [issues, trails, issueStep]);
|
|
836
|
+
}, [showIssues, issues, trails, issueStep]);
|
|
835
837
|
// Expanded verification layers in the diagnostics list. When any layer with
|
|
836
838
|
// findings is expanded, the canvas dims everything that layer does not
|
|
837
839
|
// implicate (see `issueFocus`). The list publishes this through
|
|
@@ -864,7 +866,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
864
866
|
// Returns null when nothing is expanded, no expanded layer has findings, or
|
|
865
867
|
// the findings implicate nothing — so no dimming is applied.
|
|
866
868
|
const issueFocus = useMemo(() => {
|
|
867
|
-
if (!issues?.length || expandedIssueCategories.length === 0)
|
|
869
|
+
if (showIssues !== true || !issues?.length || expandedIssueCategories.length === 0)
|
|
868
870
|
return null;
|
|
869
871
|
const active = new Set(expandedIssueCategories);
|
|
870
872
|
const activeIssues = issues.filter((i) => active.has(issueCategory(i)));
|
|
@@ -927,7 +929,7 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
927
929
|
edgeIds.add(e.id);
|
|
928
930
|
}
|
|
929
931
|
return { nodeIds, edgeIds };
|
|
930
|
-
}, [issues, expandedIssueCategories, components, trails, resolveAlias]);
|
|
932
|
+
}, [showIssues, issues, expandedIssueCategories, components, trails, resolveAlias]);
|
|
931
933
|
const issueFocusNodeIds = issueFocus?.nodeIds ?? null;
|
|
932
934
|
const issueFocusEdgeIds = issueFocus?.edgeIds ?? null;
|
|
933
935
|
// When an edge is selected, dim every other edge + its label to focus it.
|
|
@@ -2057,9 +2059,25 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
2057
2059
|
: undefined
|
|
2058
2060
|
: undefined;
|
|
2059
2061
|
// Header block: extras, then the description.
|
|
2060
|
-
const sidebarHeader = (_jsxs(_Fragment, { children: [sidebarExtra, description && (
|
|
2062
|
+
const sidebarHeader = (_jsxs(_Fragment, { children: [sidebarExtra, description && (_jsxs("div", { style: { fontSize: theme.fontSizes[0], lineHeight: 1.5 }, children: [_jsx("div", { style: {
|
|
2063
|
+
display: '-webkit-box',
|
|
2064
|
+
WebkitBoxOrient: 'vertical',
|
|
2065
|
+
WebkitLineClamp: 6,
|
|
2066
|
+
maxHeight: '9em',
|
|
2067
|
+
overflow: 'hidden',
|
|
2068
|
+
}, children: _jsx(IndustryMarkdownSlide, { content: description, slideIdPrefix: "subsystem-desc", slideIndex: 0, isVisible: true, theme: theme, disableScroll: true, disableBasePadding: true, enableKeyboardScrolling: false, autoFocusOnVisible: false }) }), _jsx("button", { type: "button", "aria-label": "Read full description", "aria-haspopup": "dialog", "aria-expanded": descriptionOpen, onClick: () => setDescriptionOpen(true), style: {
|
|
2069
|
+
marginTop: 6,
|
|
2070
|
+
padding: 0,
|
|
2071
|
+
border: 'none',
|
|
2072
|
+
background: 'transparent',
|
|
2073
|
+
color: theme.colors.textSecondary,
|
|
2074
|
+
fontFamily: theme.fonts.body,
|
|
2075
|
+
fontSize: theme.fontSizes[0],
|
|
2076
|
+
textDecoration: 'underline',
|
|
2077
|
+
cursor: 'pointer',
|
|
2078
|
+
}, children: "More" })] })), sidebarAfterDescription] }));
|
|
2061
2079
|
// Lower panel: diagnostics, the file tree, or the trail flow list.
|
|
2062
|
-
const sidebarPanel = issuesActive ? (diagnosticsTab === 'agents' && agentsPanel && !sidebarTrail ? (_jsx(SubsystemAgentsPanel, { ...agentsPanel })) : (_jsx(SubsystemIssueList, { issues: sidebarScope.issues, focusCategory: focusIssueCategory, laneStatus: sidebarTrail ? undefined : laneStatus, onSelectIssue: focusIssueTarget, onDeselectIssue: unfocusIssueTarget, onApplyFix: onApplyIssueFix, onHoverIssue: onHoverIssue, onExpandedCategoriesChange: handleExpandedCategoriesChange }))) : filesActive ? treePaths.entries.length === 0 ? (_jsx("div", { style: { padding: 16, color: theme.colors.textSecondary }, children: "No files for this trail." })) : (_jsx(SubsystemFileTree, { files: treeFilePaths, selectedFile: openFile ? treePaths.toDisplay.get(openFile) : null, onSelectFile: (path) => {
|
|
2080
|
+
const sidebarPanel = issuesActive ? (diagnosticsTab === 'agents' && agentsPanel && !sidebarTrail ? (_jsx(SubsystemAgentsPanel, { ...agentsPanel })) : (_jsx(SubsystemIssueList, { issues: sidebarScope.issues, focusCategory: focusIssueCategory, laneStatus: sidebarTrail ? undefined : laneStatus, onSelectIssue: focusIssueTarget, onDeselectIssue: unfocusIssueTarget, onApplyFix: onApplyIssueFix, onHoverIssue: onHoverIssue, onExpandedCategoriesChange: handleExpandedCategoriesChange }))) : filesActive ? treePaths.entries.length === 0 ? (_jsx("div", { style: { padding: 16, color: theme.colors.textSecondary }, children: "No files for this trail." })) : (_jsx(SubsystemFileTree, { headerless: true, files: treeFilePaths, selectedFile: openFile ? treePaths.toDisplay.get(openFile) : null, onSelectFile: (path) => {
|
|
2063
2081
|
const file = treePaths.toFile.get(path);
|
|
2064
2082
|
if (file)
|
|
2065
2083
|
onOpenDeclarationFile(file);
|
|
@@ -2102,279 +2120,279 @@ function Inner({ components, trails, graphifyRelations, orderByLine, layoutDirec
|
|
|
2102
2120
|
fontSize: theme.fontSizes[0],
|
|
2103
2121
|
color: theme.colors.textMuted ?? theme.colors.textSecondary,
|
|
2104
2122
|
}, children: fileOverlay.file }), _jsx(FileOverlayCloseButton, { onClose: closeFileOverlay })] }), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(FileDrawerContent, { render: renderDrawerContent, file: fileOverlay.file, startLine: fileOverlay.startLine, endLine: fileOverlay.endLine, fullFile: true }) })] }));
|
|
2105
|
-
return (
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
position: 'absolute',
|
|
2165
|
-
inset: 0,
|
|
2166
|
-
borderRadius: 4,
|
|
2167
|
-
border: `0.5px solid ${color}`,
|
|
2168
|
-
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2169
|
-
pointerEvents: 'none',
|
|
2170
|
-
} })) : (_jsx("svg", { "aria-hidden": true, width: EDGE_LABEL_WIDTH, height: EDGE_LABEL_HEIGHT + EDGE_LABEL_CLOUD_EXTRA_TOP, viewBox: `0 0 ${EDGE_LABEL_WIDTH} ${EDGE_LABEL_HEIGHT + EDGE_LABEL_CLOUD_EXTRA_TOP}`, style: {
|
|
2171
|
-
position: 'absolute',
|
|
2172
|
-
left: 0,
|
|
2173
|
-
top: -EDGE_LABEL_CLOUD_EXTRA_TOP,
|
|
2174
|
-
pointerEvents: 'none',
|
|
2175
|
-
}, children: _jsx("path", { d: EDGE_LABEL_CLOUD_PATH, fill: theme.colors.backgroundSecondary ?? theme.colors.background, stroke: hexWithAlpha(color, 0.75), strokeWidth: 1.2, strokeLinejoin: "round" }) })), _jsx("span", { style: {
|
|
2176
|
-
position: 'relative',
|
|
2177
|
-
display: 'block',
|
|
2178
|
-
maxWidth: '100%',
|
|
2179
|
-
overflow: 'hidden',
|
|
2180
|
-
textOverflow: 'ellipsis',
|
|
2181
|
-
whiteSpace: 'nowrap',
|
|
2182
|
-
fontSize: EDGE_LABEL_FONT_SIZE,
|
|
2183
|
-
lineHeight: 1,
|
|
2184
|
-
fontFamily: theme.fonts.monospace,
|
|
2185
|
-
fontWeight: 500,
|
|
2186
|
-
color,
|
|
2187
|
-
}, children: text }), lbl.stepIssue && (() => {
|
|
2188
|
-
const StepIssueIcon = ISSUE_KIND_ICON[lbl.stepIssue.kind];
|
|
2189
|
-
// Match IssueList: error severity = red, info severity = amber
|
|
2190
|
-
const issueColor = lbl.stepIssue.severity === 'error'
|
|
2191
|
-
? (theme.colors.error ?? '#e5534b')
|
|
2192
|
-
: (theme.colors.warning ?? '#d4a017');
|
|
2193
|
-
const badgeBg = theme.colors.backgroundSecondary ?? theme.colors.background;
|
|
2194
|
-
return (_jsxs("span", { "aria-hidden": true, title: lbl.stepIssue.kind === 'step_span_stale'
|
|
2195
|
-
? 'Call site changed since verification'
|
|
2196
|
-
: lbl.stepIssue.kind === 'step_site_outside_from'
|
|
2197
|
-
? 'Calls site is outside its source component'
|
|
2198
|
-
: 'Call site not yet verified', style: {
|
|
2123
|
+
return (_jsxs(GraphWithSidebar, { hidden: !sidebarVisible, bodyHidden: !sidebarBodyVisible, header: sidebarHeader, tabs: sidebarTabs, activeTab: diagnosticsTab, onTabChange: (id) => setDiagnosticsTab(id), sidebarBody: sidebarBody, tabListLabel: issuesActive ? 'Diagnostics view' : 'Sidebar view', defaultWidth: persisted.sidebarWidth ?? 450, minWidth: 240, maxWidth: sidebarMaxWidth, persistKey: persistKey, onResizeEnd: () => requestAnimationFrame(() => fitView()), children: [!hideSidebar && description && descriptionOpen && (_jsx(DescriptionOverlay, { description: description, onClose: () => setDescriptionOpen(false) })), _jsxs("div", { style: { flex: 1, position: 'relative', display: 'flex', flexDirection: committedDirection === 'vertical' ? 'row' : 'column', minHeight: 0, minWidth: 0 }, children: [_jsxs("div", { className: layoutFlipping ? LAYOUT_FLIP_CLASS : undefined, style: {
|
|
2124
|
+
position: 'relative',
|
|
2125
|
+
flex: collapseCanvas ? 0 : 1,
|
|
2126
|
+
minHeight: 0,
|
|
2127
|
+
minWidth: 0,
|
|
2128
|
+
height: collapseCanvas ? 0 : undefined,
|
|
2129
|
+
overflow: 'hidden',
|
|
2130
|
+
display: 'flex',
|
|
2131
|
+
flexDirection: 'column',
|
|
2132
|
+
}, children: [showEdgeLabels !== false && (_jsx("div", { style: {
|
|
2133
|
+
position: 'absolute',
|
|
2134
|
+
inset: 0,
|
|
2135
|
+
overflow: 'hidden',
|
|
2136
|
+
pointerEvents: 'none',
|
|
2137
|
+
zIndex: 5,
|
|
2138
|
+
opacity: layoutFlipping ? 0 : 1,
|
|
2139
|
+
transition: `opacity ${LAYOUT_FLIP_EDGE_MS}ms ease`,
|
|
2140
|
+
}, children: edgeLabels.map((lbl) => {
|
|
2141
|
+
const mechanism = lbl.mechanism;
|
|
2142
|
+
const isGraphify = lbl.provenance === 'graphify';
|
|
2143
|
+
const color = edgeColor({ mechanism, provenance: lbl.provenance });
|
|
2144
|
+
// Label chrome stays the crisp rounded box for every edge — graphify
|
|
2145
|
+
// provenance is carried by hue (GRAPHIFY_RELATION_COLOR), the dashed
|
|
2146
|
+
// stroke, and the tooltip, NOT by the "ambiguous" cloud silhouette
|
|
2147
|
+
// (that idiom is reserved for soft authored mechanisms).
|
|
2148
|
+
const verifiable = true;
|
|
2149
|
+
const labelTitle = isGraphify
|
|
2150
|
+
? 'Derived from graphify (static symbol graph)'
|
|
2151
|
+
: MECHANISM_DESCRIPTIONS.find(([m]) => m === mechanism)?.[2] === false
|
|
2152
|
+
? 'Not directly verifiable with graphify'
|
|
2153
|
+
: undefined;
|
|
2154
|
+
const screenX = lbl.midX * viewport.zoom + viewport.x;
|
|
2155
|
+
const screenY = lbl.midY * viewport.zoom + viewport.y;
|
|
2156
|
+
const text = lbl.stepNos?.length
|
|
2157
|
+
? `${lbl.stepNos.map((n) => `${n}:`).join(' ')} ${lbl.mechanism}`
|
|
2158
|
+
: lbl.mechanism;
|
|
2159
|
+
return (_jsxs("div", { "data-edge-label": lbl.id, title: labelTitle, onClick: (e) => {
|
|
2160
|
+
e.stopPropagation();
|
|
2161
|
+
selectEdge(lbl.id);
|
|
2162
|
+
}, style: {
|
|
2163
|
+
position: 'absolute',
|
|
2164
|
+
left: screenX,
|
|
2165
|
+
top: screenY,
|
|
2166
|
+
// Center on the flow-space midpoint, and scale with the graph
|
|
2167
|
+
// (flow-space size): labels shrink as you zoom out instead of
|
|
2168
|
+
// staying fixed-screen-size and dominating the smaller graph.
|
|
2169
|
+
transform: `translate(-50%, -50%) scale(${viewport.zoom})`,
|
|
2170
|
+
transformOrigin: 'center center',
|
|
2171
|
+
display: 'flex',
|
|
2172
|
+
alignItems: 'center',
|
|
2173
|
+
justifyContent: 'center',
|
|
2174
|
+
width: EDGE_LABEL_WIDTH,
|
|
2175
|
+
height: EDGE_LABEL_HEIGHT,
|
|
2176
|
+
boxSizing: 'border-box',
|
|
2177
|
+
padding: '7px 8px',
|
|
2178
|
+
cursor: 'pointer',
|
|
2179
|
+
pointerEvents: 'auto',
|
|
2180
|
+
opacity: lbl.dimmed ? 0.15 : 1,
|
|
2181
|
+
}, children: [verifiable ? (_jsx("span", { "aria-hidden": true, style: {
|
|
2199
2182
|
position: 'absolute',
|
|
2200
|
-
|
|
2201
|
-
bottom: -6,
|
|
2202
|
-
zIndex: 2,
|
|
2203
|
-
display: 'inline-flex',
|
|
2204
|
-
alignItems: 'center',
|
|
2205
|
-
justifyContent: 'center',
|
|
2206
|
-
gap: 3,
|
|
2207
|
-
minWidth: 18,
|
|
2208
|
-
padding: '2px 4px',
|
|
2183
|
+
inset: 0,
|
|
2209
2184
|
borderRadius: 4,
|
|
2210
|
-
border: `
|
|
2211
|
-
background:
|
|
2185
|
+
border: `0.5px solid ${color}`,
|
|
2186
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2187
|
+
pointerEvents: 'none',
|
|
2188
|
+
} })) : (_jsx("svg", { "aria-hidden": true, width: EDGE_LABEL_WIDTH, height: EDGE_LABEL_HEIGHT + EDGE_LABEL_CLOUD_EXTRA_TOP, viewBox: `0 0 ${EDGE_LABEL_WIDTH} ${EDGE_LABEL_HEIGHT + EDGE_LABEL_CLOUD_EXTRA_TOP}`, style: {
|
|
2189
|
+
position: 'absolute',
|
|
2190
|
+
left: 0,
|
|
2191
|
+
top: -EDGE_LABEL_CLOUD_EXTRA_TOP,
|
|
2212
2192
|
pointerEvents: 'none',
|
|
2213
|
-
}, children:
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2193
|
+
}, children: _jsx("path", { d: EDGE_LABEL_CLOUD_PATH, fill: theme.colors.backgroundSecondary ?? theme.colors.background, stroke: hexWithAlpha(color, 0.75), strokeWidth: 1.2, strokeLinejoin: "round" }) })), _jsx("span", { style: {
|
|
2194
|
+
position: 'relative',
|
|
2195
|
+
display: 'block',
|
|
2196
|
+
maxWidth: '100%',
|
|
2197
|
+
overflow: 'hidden',
|
|
2198
|
+
textOverflow: 'ellipsis',
|
|
2199
|
+
whiteSpace: 'nowrap',
|
|
2200
|
+
fontSize: EDGE_LABEL_FONT_SIZE,
|
|
2201
|
+
lineHeight: 1,
|
|
2202
|
+
fontFamily: theme.fonts.monospace,
|
|
2203
|
+
fontWeight: 500,
|
|
2204
|
+
color,
|
|
2205
|
+
}, children: text }), lbl.stepIssue && (() => {
|
|
2206
|
+
const StepIssueIcon = ISSUE_KIND_ICON[lbl.stepIssue.kind];
|
|
2207
|
+
// Match IssueList: error severity = red, info severity = amber
|
|
2208
|
+
const issueColor = lbl.stepIssue.severity === 'error'
|
|
2209
|
+
? (theme.colors.error ?? '#e5534b')
|
|
2210
|
+
: (theme.colors.warning ?? '#d4a017');
|
|
2211
|
+
const badgeBg = theme.colors.backgroundSecondary ?? theme.colors.background;
|
|
2212
|
+
return (_jsxs("span", { "aria-hidden": true, title: lbl.stepIssue.kind === 'step_span_stale'
|
|
2213
|
+
? 'Call site changed since verification'
|
|
2214
|
+
: lbl.stepIssue.kind === 'step_site_outside_from'
|
|
2215
|
+
? 'Calls site is outside its source component'
|
|
2216
|
+
: 'Call site not yet verified', style: {
|
|
2217
|
+
position: 'absolute',
|
|
2218
|
+
right: -7,
|
|
2219
|
+
bottom: -6,
|
|
2220
|
+
zIndex: 2,
|
|
2221
|
+
display: 'inline-flex',
|
|
2222
|
+
alignItems: 'center',
|
|
2223
|
+
justifyContent: 'center',
|
|
2224
|
+
gap: 3,
|
|
2225
|
+
minWidth: 18,
|
|
2226
|
+
padding: '2px 4px',
|
|
2227
|
+
borderRadius: 4,
|
|
2228
|
+
border: `1.5px solid ${issueColor}`,
|
|
2229
|
+
background: badgeBg,
|
|
2230
|
+
pointerEvents: 'none',
|
|
2231
|
+
}, children: [StepIssueIcon && (_jsx(StepIssueIcon, { size: 12, color: issueColor })), lbl.stepIssue.count > 1 && (_jsx("span", { style: {
|
|
2232
|
+
color: issueColor,
|
|
2233
|
+
fontFamily: theme.fonts.monospace,
|
|
2234
|
+
fontSize: 10,
|
|
2235
|
+
fontWeight: 700,
|
|
2236
|
+
lineHeight: 1,
|
|
2237
|
+
}, children: lbl.stepIssue.count }))] }));
|
|
2238
|
+
})()] }, lbl.id));
|
|
2239
|
+
}) })), _jsx(GraphLayerStyle, {}), _jsx(ReactFlow, { nodes: dispNodes, edges: dispEdges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, className: GRAPH_CANVAS_CLASS,
|
|
2240
|
+
// The key above remounts ReactFlow when the node/edge SET changes (a
|
|
2241
|
+
// trail-focus layout, a filtered model). A remount otherwise resets the
|
|
2242
|
+
// viewport to identity — a visible jump to scale 1 before the post-flip
|
|
2243
|
+
// refit. Seed the new instance with the viewport the old one had.
|
|
2244
|
+
defaultViewport: viewport, ...GRAPH_NAV_PROPS, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onEdgeClick: onEdgeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, proOptions: { hideAttribution: true }, onPaneClick: onPaneClick, style: {
|
|
2245
|
+
width: '100%',
|
|
2246
|
+
height: '100%',
|
|
2247
|
+
flex: 1,
|
|
2248
|
+
minHeight: 0,
|
|
2249
|
+
background: theme.colors.background,
|
|
2250
|
+
}, children: _jsx(GraphChrome, {}) }, `${baseNodesKey}-${baseEdgesKey}`), !hideLayoutToggle && (_jsxs("button", { type: "button", onClick: () => changeLayoutDirection(requestedDirection === 'horizontal' ? 'vertical' : 'horizontal'), disabled: layoutFlipping, title: requestedDirection === 'horizontal'
|
|
2251
|
+
? 'Switch to a vertical layout (top-to-bottom)'
|
|
2252
|
+
: 'Switch to a horizontal layout (left-to-right)', "aria-label": requestedDirection === 'horizontal'
|
|
2253
|
+
? 'Switch to vertical layout'
|
|
2254
|
+
: 'Switch to horizontal layout', style: {
|
|
2255
|
+
position: 'absolute',
|
|
2256
|
+
top: 10,
|
|
2257
|
+
right: 10,
|
|
2258
|
+
zIndex: 6,
|
|
2259
|
+
display: 'inline-flex',
|
|
2260
|
+
alignItems: 'center',
|
|
2261
|
+
gap: 5,
|
|
2262
|
+
padding: '4px 9px',
|
|
2263
|
+
border: `1px solid ${theme.colors.border}`,
|
|
2264
|
+
borderRadius: 6,
|
|
2265
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2266
|
+
color: theme.colors.textSecondary,
|
|
2267
|
+
fontFamily: theme.fonts.monospace,
|
|
2268
|
+
fontSize: theme.fontSizes[0],
|
|
2269
|
+
cursor: layoutFlipping ? 'default' : 'pointer',
|
|
2270
|
+
opacity: layoutFlipping ? 0.55 : 1,
|
|
2271
|
+
}, children: [requestedDirection === 'horizontal' ? (_jsx(ArrowDown, { size: 13, "aria-hidden": "true" })) : (_jsx(ArrowRight, { size: 13, "aria-hidden": "true" })), requestedDirection === 'horizontal' ? 'Vertical' : 'Horizontal'] })), unroutedIds.length > 0 && (_jsxs("div", { role: "status", title: `Edges with no routed path (not drawn):\n${unroutedIds.join('\n')}`, style: {
|
|
2272
|
+
position: 'absolute',
|
|
2273
|
+
top: 10,
|
|
2274
|
+
left: 10,
|
|
2275
|
+
zIndex: 6,
|
|
2276
|
+
display: 'inline-flex',
|
|
2277
|
+
alignItems: 'center',
|
|
2278
|
+
gap: 6,
|
|
2279
|
+
padding: '4px 10px',
|
|
2280
|
+
fontSize: theme.fontSizes[0],
|
|
2281
|
+
fontFamily: theme.fonts.body,
|
|
2282
|
+
color: theme.colors.text,
|
|
2283
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2284
|
+
border: `1px solid ${theme.colors.warning ?? '#d4a017'}`,
|
|
2285
|
+
borderRadius: 6,
|
|
2286
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.25)',
|
|
2287
|
+
}, children: [_jsx(Unlink, { size: 13, color: theme.colors.warning ?? '#d4a017', "aria-hidden": true }), unroutedIds.length, " ", unroutedIds.length === 1 ? 'edge' : 'edges', " not drawn"] })), (graphTitle || overlayTrailTitle || overlayTrailStep) && (_jsxs("div", { style: {
|
|
2288
|
+
position: 'absolute',
|
|
2289
|
+
top: 10,
|
|
2290
|
+
left: '50%',
|
|
2291
|
+
transform: 'translateX(-50%)',
|
|
2292
|
+
zIndex: 6,
|
|
2293
|
+
display: 'flex',
|
|
2294
|
+
flexDirection: 'column',
|
|
2295
|
+
alignItems: 'center',
|
|
2296
|
+
gap: 6,
|
|
2297
|
+
maxWidth: '70%',
|
|
2298
|
+
pointerEvents: 'none',
|
|
2299
|
+
}, children: [graphTitle && (_jsx("div", { style: {
|
|
2300
|
+
maxWidth: '100%',
|
|
2301
|
+
overflow: 'hidden',
|
|
2302
|
+
textOverflow: 'ellipsis',
|
|
2303
|
+
whiteSpace: 'nowrap',
|
|
2304
|
+
padding: '6px 18px',
|
|
2305
|
+
fontSize: theme.fontSizes[3],
|
|
2306
|
+
fontWeight: 600,
|
|
2307
|
+
fontFamily: theme.fonts.monospace,
|
|
2308
|
+
color: theme.colors.text,
|
|
2309
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2310
|
+
border: `1px solid ${theme.colors.border}`,
|
|
2311
|
+
borderRadius: 6,
|
|
2312
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.25)',
|
|
2313
|
+
}, children: graphTitle })), overlayTrailTitle && (_jsxs("div", { style: {
|
|
2314
|
+
maxWidth: '100%',
|
|
2315
|
+
minWidth: overlayTrailStep ? 160 : undefined,
|
|
2316
|
+
display: 'flex',
|
|
2317
|
+
flexDirection: 'column',
|
|
2318
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2319
|
+
border: `1px solid ${theme.colors.border}`,
|
|
2320
|
+
borderRadius: 6,
|
|
2321
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.25)',
|
|
2322
|
+
overflow: 'hidden',
|
|
2323
|
+
opacity: 0.95,
|
|
2324
|
+
}, "aria-label": overlayTrailStep
|
|
2325
|
+
? `${overlayTrailTitle}, step ${overlayTrailStep.index} of ${overlayTrailStep.total}`
|
|
2326
|
+
: overlayTrailTitle, children: [_jsx("div", { style: {
|
|
2327
|
+
padding: '5px 14px',
|
|
2328
|
+
fontSize: theme.fontSizes[2] ?? theme.fontSizes[1],
|
|
2329
|
+
fontWeight: 600,
|
|
2330
|
+
fontFamily: theme.fonts.monospace,
|
|
2331
|
+
color: theme.colors.text,
|
|
2332
|
+
overflow: 'hidden',
|
|
2333
|
+
textOverflow: 'ellipsis',
|
|
2334
|
+
whiteSpace: 'nowrap',
|
|
2335
|
+
textAlign: 'center',
|
|
2336
|
+
}, children: overlayTrailTitle }), overlayTrailStep && overlayTrailStep.total > 0 && (_jsx("div", { style: {
|
|
2337
|
+
display: 'flex',
|
|
2338
|
+
gap: 3,
|
|
2339
|
+
padding: '0 6px 5px',
|
|
2340
|
+
}, "aria-hidden": "true", children: Array.from({ length: overlayTrailStep.total }, (_, i) => {
|
|
2341
|
+
const n = i + 1;
|
|
2342
|
+
const active = n === overlayTrailStep.index;
|
|
2343
|
+
const done = n < overlayTrailStep.index;
|
|
2344
|
+
return (_jsx("span", { style: {
|
|
2345
|
+
flex: 1,
|
|
2346
|
+
height: 2,
|
|
2347
|
+
borderRadius: 1,
|
|
2348
|
+
background: active
|
|
2349
|
+
? (theme.colors.accent ?? theme.colors.primary ?? theme.colors.text)
|
|
2350
|
+
: done
|
|
2351
|
+
? (theme.colors.textSecondary ?? theme.colors.text)
|
|
2352
|
+
: (theme.colors.border ?? 'rgba(127,127,127,0.45)'),
|
|
2353
|
+
opacity: active ? 1 : done ? 0.75 : 0.4,
|
|
2354
|
+
transition: 'opacity 120ms ease, background 120ms ease',
|
|
2355
|
+
} }, n));
|
|
2356
|
+
}) }))] })), overlayTrailStep?.annotation && (_jsx("div", { style: {
|
|
2357
|
+
maxWidth: '100%',
|
|
2358
|
+
padding: '6px 14px',
|
|
2359
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
2360
|
+
border: `1px solid ${theme.colors.border}`,
|
|
2361
|
+
borderRadius: 6,
|
|
2362
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.25)',
|
|
2363
|
+
textAlign: 'center',
|
|
2364
|
+
fontSize: theme.fontSizes[0],
|
|
2365
|
+
fontFamily: theme.fonts.body,
|
|
2366
|
+
color: theme.colors.textMuted ?? theme.colors.textSecondary,
|
|
2367
|
+
lineHeight: 1.35,
|
|
2368
|
+
}, children: overlayTrailStep.annotation }))] })), selected && (_jsx("div", { style: {
|
|
2369
|
+
position: 'absolute',
|
|
2370
|
+
top: 10,
|
|
2371
|
+
right: 10,
|
|
2372
|
+
zIndex: 8,
|
|
2373
|
+
width: 'min(560px, 70%)',
|
|
2374
|
+
maxHeight: '46%',
|
|
2375
|
+
overflowY: 'auto',
|
|
2376
|
+
background: theme.colors.background,
|
|
2377
|
+
border: `1px solid ${theme.colors.border}`,
|
|
2378
|
+
borderRadius: 8,
|
|
2379
|
+
boxShadow: '0 8px 24px rgba(0,0,0,0.35)',
|
|
2380
|
+
}, children: _jsx(ComponentDeclaration, { component: selected, onOpenFile: onOpenDeclarationFile, onRelatedSelect: resolveRelatedComponent, onInspectSymbol: onInspectSymbol
|
|
2381
|
+
? (symbol, ref) => onInspectSymbol({
|
|
2382
|
+
purl: selected.purl,
|
|
2383
|
+
file: selected.file,
|
|
2384
|
+
symbol,
|
|
2385
|
+
ref,
|
|
2386
|
+
})
|
|
2387
|
+
: undefined, verification: componentVerification, fileOpen: drawerTarget?.kind === 'file' &&
|
|
2388
|
+
!!selected.file &&
|
|
2389
|
+
selected.file === drawerTarget.file, declarationOpen: drawerTarget?.kind === 'file' &&
|
|
2390
|
+
drawerTarget.startLine != null &&
|
|
2391
|
+
!!selected.file &&
|
|
2392
|
+
selected.file === drawerTarget.file &&
|
|
2393
|
+
selected.declarationSpan?.startLine === drawerTarget.startLine }) })), committedDirection === 'vertical' && fileOverlayView] }), _jsx(FileDrawer, { title: drawerTitle, onClose: closeDrawer, placement: committedDirection === 'vertical' ? 'left' : 'bottom', onResizeEnd: () => requestAnimationFrame(() => fitView()), fillHeight: drawerFillHeight, suppressEscape: fileOverlayOpen, hidden: hideDrawer, progress: drawerProgress, children: drawerTarget?.kind === 'trail' &&
|
|
2394
|
+
focusedTrail &&
|
|
2395
|
+
renderTrailViewer ? (_jsx(TrailDrawerContent, { render: renderTrailDrawerContent, trail: focusedTrail, stepIndex: drawerTarget.stepIndex, onOpenFile: onOpenFileFromTrail, resolveSymbol: resolveTrailSymbol, onSymbolClick: openConstructDeclaration, onVisibleStepChange: setVisibleStepIndex })) : drawerTarget?.kind === 'file' ? (_jsx(FileDrawerContent, { render: renderDrawerContent, file: drawerTarget.file, startLine: drawerTarget.startLine, endLine: drawerTarget.endLine })) : null }), committedDirection !== 'vertical' && fileOverlayView, _jsx(GraphLayoutCover, { revealed: layoutReady || layoutFlipping }), canvasOverlay, liveEvents ? _jsx(MaintainLivePanel, { ...liveEvents }) : null] })] }));
|
|
2378
2396
|
}
|
|
2379
2397
|
export function SubsystemComponentGraph(props) {
|
|
2380
2398
|
const { theme } = useTheme();
|
|
@@ -2389,6 +2407,7 @@ export function SubsystemComponentGraph(props) {
|
|
|
2389
2407
|
const sidebarScope = useMemo(() => buildTrailSidebarScope(props.components, props.trails, props.issues, sidebarTrailId), [props.components, props.trails, props.issues, sidebarTrailId]);
|
|
2390
2408
|
const fileCount = sidebarScope.treePaths.entries.length;
|
|
2391
2409
|
const trailViewLabel = sidebarScope.trail ? 'Trail' : 'Trails';
|
|
2410
|
+
const trailCount = props.trails?.length ?? 0;
|
|
2392
2411
|
const hasFiles = fileCount > 0 || sidebarScope.trail != null;
|
|
2393
2412
|
const sidebarDiagnostic = sidebarScope.trail ? {
|
|
2394
2413
|
...props.diagnostic,
|
|
@@ -2398,17 +2417,21 @@ export function SubsystemComponentGraph(props) {
|
|
|
2398
2417
|
fixableCount: sidebarScope.issues.filter((issue) => issue.fix != null).length,
|
|
2399
2418
|
title: undefined,
|
|
2400
2419
|
} : props.diagnostic ?? { status: 'unknown', issueCount: props.issues?.length };
|
|
2420
|
+
const hasIssues = (props.issues != null
|
|
2421
|
+
? sidebarScope.issues.length
|
|
2422
|
+
: sidebarDiagnostic.issueCount ?? 0) > 0;
|
|
2401
2423
|
useEffect(() => {
|
|
2402
2424
|
if (sidebarTrailId != null && !sidebarScope.trail)
|
|
2403
2425
|
setSidebarTrailId(null);
|
|
2404
2426
|
}, [sidebarTrailId, sidebarScope.trail]);
|
|
2405
2427
|
const [diagnosticsOpen, setDiagnosticsOpen] = useState(props.showIssues ?? (props.issues?.length ?? 0) > 0);
|
|
2406
|
-
const
|
|
2428
|
+
const issuesRequested = props.showIssues ?? diagnosticsOpen;
|
|
2429
|
+
const issuesActive = hasIssues && issuesRequested;
|
|
2407
2430
|
const filesActive = filesOpen && hasFiles && !issuesActive;
|
|
2408
2431
|
const selectSidebarView = (view) => {
|
|
2409
2432
|
const nextIssuesActive = view === 'issues';
|
|
2410
2433
|
setFilesOpen(view === 'files');
|
|
2411
|
-
if (nextIssuesActive !==
|
|
2434
|
+
if (nextIssuesActive !== issuesRequested) {
|
|
2412
2435
|
if (props.showIssues === undefined)
|
|
2413
2436
|
setDiagnosticsOpen(nextIssuesActive);
|
|
2414
2437
|
props.diagnostic?.onToggle?.();
|
|
@@ -2420,7 +2443,7 @@ export function SubsystemComponentGraph(props) {
|
|
|
2420
2443
|
justifyContent: 'center',
|
|
2421
2444
|
gap: 4,
|
|
2422
2445
|
height: 28,
|
|
2423
|
-
padding: '4px
|
|
2446
|
+
padding: '4px 16px',
|
|
2424
2447
|
fontFamily: theme.fonts.monospace,
|
|
2425
2448
|
fontSize: theme.fontSizes[0],
|
|
2426
2449
|
border: 'none',
|
|
@@ -2488,6 +2511,6 @@ export function SubsystemComponentGraph(props) {
|
|
|
2488
2511
|
padding: 2,
|
|
2489
2512
|
border: `1px solid ${theme.colors.border}`,
|
|
2490
2513
|
borderRadius: 6,
|
|
2491
|
-
}, children: [_jsxs("button", { type: "button", "aria-label":
|
|
2514
|
+
}, children: [_jsxs("button", { type: "button", "aria-label": sidebarScope.trail ? 'Trail' : `Trails (${trailCount} ${trailCount === 1 ? 'trail' : 'trails'})`, "aria-pressed": !filesActive && !issuesActive, onClick: () => selectSidebarView('trails'), style: viewButtonStyle(!filesActive && !issuesActive), children: [_jsx(Route, { size: 14, "aria-hidden": true }), _jsx("span", { children: trailViewLabel }), !sidebarScope.trail && _jsx("span", { style: { fontWeight: 600, marginLeft: 4 }, children: trailCount })] }), hasFiles && (_jsxs("button", { type: "button", "aria-label": `Files (${fileCount} files)`, title: "Show files", "aria-pressed": filesActive, onClick: () => selectSidebarView('files'), style: viewButtonStyle(filesActive), children: [_jsx(Files, { size: 14, "aria-hidden": true }), _jsx("span", { children: "Files" }), _jsx("span", { style: { fontWeight: 600, marginLeft: 4 }, children: fileCount })] })), hasIssues && (_jsx(SubsystemDiagnosticToggle, { ...sidebarDiagnostic, labelText: "Issues", segmented: true, active: issuesActive, onToggle: () => selectSidebarView('issues') }))] })] })), _jsx("div", { ref: wrapRef, style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: constructsOnly ? (_jsx(ConstructsCatalog, { components: props.components, onSelect: props.onSelect, title: props.title, hideSidebar: props.hideSidebar, description: props.description, descriptionOpen: props.descriptionOpen, onDescriptionOpenChange: props.onDescriptionOpenChange, diagnostic: props.diagnostic, sidebarExtra: props.sidebarExtra, sidebarAfterDescription: props.sidebarAfterDescription, renderFileViewer: props.renderFileViewer, onFileSelect: props.onFileSelect, componentVerification: props.componentVerification, onInspectSymbol: props.onInspectSymbol })) : (_jsx(ReactFlowProvider, { children: _jsx(Inner, { ...props, showIssues: issuesActive, filesActive: filesActive, measured: size, sidebarScope: sidebarScope, onSidebarTrailChange: setSidebarTrailId }) })) })] }));
|
|
2492
2515
|
}
|
|
2493
2516
|
//# sourceMappingURL=SubsystemComponentGraph.js.map
|