@principal-ai/subsystems-react 0.56.12 → 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/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +289 -271
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/package.json +1 -1
- package/src/stories/Canvases/C4/C4Draft.stories.tsx +238 -0
- 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/SubsystemComponentGraph.sidebar.test.tsx +10 -3
- package/src/subsystem/SubsystemComponentGraph.tsx +44 -12
|
@@ -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.
|
|
@@ -2057,7 +2059,23 @@ 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
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);
|
|
@@ -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();
|