@principal-ai/subsystems-react 0.55.2 → 0.56.0
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/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/pierre/PierreFileView.js +3 -3
- package/dist/pierre/PierreFileView.js.map +1 -1
- package/dist/pierre/PierreTrailCodeView.d.ts +1 -6
- package/dist/pierre/PierreTrailCodeView.d.ts.map +1 -1
- package/dist/pierre/PierreTrailCodeView.js +21 -18
- package/dist/pierre/PierreTrailCodeView.js.map +1 -1
- package/dist/pierre/fileAvailability.d.ts +4 -7
- package/dist/pierre/fileAvailability.d.ts.map +1 -1
- package/dist/pierre/fileAvailability.js +5 -10
- package/dist/pierre/fileAvailability.js.map +1 -1
- package/dist/subsystem/C4Graph.d.ts.map +1 -1
- package/dist/subsystem/C4Graph.js +1 -1
- package/dist/subsystem/C4Graph.js.map +1 -1
- package/dist/subsystem/DecorationPanel.d.ts +37 -0
- package/dist/subsystem/DecorationPanel.d.ts.map +1 -0
- package/dist/subsystem/DecorationPanel.js +147 -0
- package/dist/subsystem/DecorationPanel.js.map +1 -0
- package/dist/subsystem/FileDrawer.d.ts +3 -1
- package/dist/subsystem/FileDrawer.d.ts.map +1 -1
- package/dist/subsystem/FileDrawer.js +2 -2
- package/dist/subsystem/FileDrawer.js.map +1 -1
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +26 -0
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts +9 -5
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +37 -47
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/TrailStackBreadcrumb.d.ts +21 -0
- package/dist/subsystem/TrailStackBreadcrumb.d.ts.map +1 -0
- package/dist/subsystem/TrailStackBreadcrumb.js +77 -0
- package/dist/subsystem/TrailStackBreadcrumb.js.map +1 -0
- package/dist/subsystem/TrailStepsNav.d.ts +4 -3
- package/dist/subsystem/TrailStepsNav.d.ts.map +1 -1
- package/dist/subsystem/TrailStepsNav.js +13 -16
- package/dist/subsystem/TrailStepsNav.js.map +1 -1
- package/dist/subsystem/TrailsPanel.d.ts +9 -7
- package/dist/subsystem/TrailsPanel.d.ts.map +1 -1
- package/dist/subsystem/TrailsPanel.js +126 -76
- package/dist/subsystem/TrailsPanel.js.map +1 -1
- package/dist/subsystem/decoration.d.ts +112 -0
- package/dist/subsystem/decoration.d.ts.map +1 -0
- package/dist/subsystem/decoration.js +54 -0
- package/dist/subsystem/decoration.js.map +1 -0
- package/dist/subsystem/model.d.ts +5 -18
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +3 -11
- package/dist/subsystem/model.js.map +1 -1
- package/dist/subsystem/nodes.d.ts.map +1 -1
- package/dist/subsystem/nodes.js +17 -24
- package/dist/subsystem/nodes.js.map +1 -1
- package/dist/subsystem/stepEmphasis.d.ts +78 -0
- package/dist/subsystem/stepEmphasis.d.ts.map +1 -0
- package/dist/subsystem/stepEmphasis.js +89 -0
- package/dist/subsystem/stepEmphasis.js.map +1 -0
- package/dist/subsystem/trailBrief.d.ts.map +1 -1
- package/dist/subsystem/trailBrief.js +20 -0
- package/dist/subsystem/trailBrief.js.map +1 -1
- package/dist/subsystem/trailStack.d.ts +53 -0
- package/dist/subsystem/trailStack.d.ts.map +1 -0
- package/dist/subsystem/trailStack.js +154 -0
- package/dist/subsystem/trailStack.js.map +1 -0
- package/dist/subsystem/trailStepDisplay.d.ts +38 -0
- package/dist/subsystem/trailStepDisplay.d.ts.map +1 -0
- package/dist/subsystem/trailStepDisplay.js +41 -0
- package/dist/subsystem/trailStepDisplay.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +47 -1
- package/src/pierre/PierreFileView.tsx +3 -3
- package/src/pierre/PierreTrailCodeView.tsx +25 -28
- package/src/pierre/fileAvailability.test.ts +0 -6
- package/src/pierre/fileAvailability.ts +5 -13
- package/src/stories/Canvases/Subsystem/Deprecated.stories.tsx +3 -17
- package/src/stories/Canvases/Subsystem/NodeAnatomy.stories.tsx +3 -31
- package/src/stories/Canvases/Subsystem/StepEmphasis.stories.tsx +528 -0
- package/src/stories/Canvases/Subsystem/Trails.stories.tsx +0 -187
- package/src/stories/Components/DecorationPanel.stories.tsx +160 -0
- package/src/subsystem/C4Graph.tsx +0 -1
- package/src/subsystem/DecorationPanel.test.tsx +128 -0
- package/src/subsystem/DecorationPanel.tsx +334 -0
- package/src/subsystem/FileDrawer.tsx +6 -0
- package/src/subsystem/IssueList.tsx +26 -0
- package/src/subsystem/SubsystemComponentGraph.tsx +68 -65
- package/src/subsystem/TrailStackBreadcrumb.test.tsx +109 -0
- package/src/subsystem/TrailStackBreadcrumb.tsx +172 -0
- package/src/subsystem/TrailStepsNav.test.tsx +35 -0
- package/src/subsystem/TrailStepsNav.tsx +18 -19
- package/src/subsystem/TrailsPanel.test.tsx +149 -0
- package/src/subsystem/TrailsPanel.tsx +165 -39
- package/src/subsystem/decoration.test.ts +72 -0
- package/src/subsystem/decoration.ts +151 -0
- package/src/subsystem/model.test.ts +7 -22
- package/src/subsystem/model.ts +6 -20
- package/src/subsystem/nodes.tsx +19 -28
- package/src/subsystem/stepEmphasis.test.ts +110 -0
- package/src/subsystem/stepEmphasis.ts +151 -0
- package/src/subsystem/trailBrief.test.ts +29 -0
- package/src/subsystem/trailBrief.ts +20 -0
- package/src/subsystem/trailStack.test.ts +133 -0
- package/src/subsystem/trailStack.ts +229 -0
- package/src/subsystem/trailStepDisplay.ts +68 -0
- package/src/stories/Canvases/Subsystem/Proposed.stories.tsx +0 -256
- package/src/stories/Canvases/Subsystem/ProposedTrails.stories.tsx +0 -184
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DecorationPanel — the reading surface for one `SubsystemDecoration`.
|
|
3
|
+
*
|
|
4
|
+
* A decoration is an additive, unverified layer over one or more subsystem
|
|
5
|
+
* models: markdown prose, an ordered list of trails (each naming its own
|
|
6
|
+
* model), and optional draft structure. This panel is the container's own
|
|
7
|
+
* surface — it deliberately does not render the graph. Selecting a trail (or
|
|
8
|
+
* a draft component) is handed back to the host, which decides whether to
|
|
9
|
+
* focus a model, open a tab, or overlay the draft.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here writes: the first prototype is read-only plus an on/off toggle.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { CSSProperties } from 'react';
|
|
15
|
+
import { useTheme } from '@principal-ade/industry-theme';
|
|
16
|
+
import { Box, Eye, EyeOff, Network, Route, Sparkles } from 'lucide-react';
|
|
17
|
+
import { IndustryMarkdownSlide } from 'themed-markdown';
|
|
18
|
+
import {
|
|
19
|
+
decorationTrailId,
|
|
20
|
+
groupDecorationTrailsByModel,
|
|
21
|
+
type DecorationDraftComponent,
|
|
22
|
+
type DecorationTrailRef,
|
|
23
|
+
type SubsystemDecoration,
|
|
24
|
+
} from './decoration';
|
|
25
|
+
|
|
26
|
+
export interface DecorationPanelTrailMeta {
|
|
27
|
+
title: string;
|
|
28
|
+
stepCount?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface DecorationPanelProps {
|
|
32
|
+
decoration: SubsystemDecoration;
|
|
33
|
+
/** Whether the decoration overlay is currently on. */
|
|
34
|
+
active: boolean;
|
|
35
|
+
onToggleActive: (active: boolean) => void;
|
|
36
|
+
/** Click a trail row. The host focuses the owning model/trail. */
|
|
37
|
+
onSelectTrail?: (ref: DecorationTrailRef) => void;
|
|
38
|
+
/** Click a draft component. Omit to render the draft list read-only. */
|
|
39
|
+
onSelectDraftComponent?: (component: DecorationDraftComponent) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a base trail's display title/step count from its owning model.
|
|
42
|
+
* Draft trails carry their content inline and need no resolver.
|
|
43
|
+
*/
|
|
44
|
+
resolveTrail?: (ref: DecorationTrailRef) => DecorationPanelTrailMeta | undefined;
|
|
45
|
+
/** Friendly model names, keyed by `modelId`. Falls back to the id. */
|
|
46
|
+
modelLabels?: ReadonlyMap<string, string>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function DecorationPanel({
|
|
50
|
+
decoration,
|
|
51
|
+
active,
|
|
52
|
+
onToggleActive,
|
|
53
|
+
onSelectTrail,
|
|
54
|
+
onSelectDraftComponent,
|
|
55
|
+
resolveTrail,
|
|
56
|
+
modelLabels,
|
|
57
|
+
}: DecorationPanelProps) {
|
|
58
|
+
const { theme } = useTheme();
|
|
59
|
+
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
60
|
+
const secondary = theme.colors.textSecondary ?? muted;
|
|
61
|
+
const warning = theme.colors.warning ?? secondary;
|
|
62
|
+
const accent = theme.colors.accent ?? theme.colors.primary ?? theme.colors.text;
|
|
63
|
+
const groups = groupDecorationTrailsByModel(decoration.trails);
|
|
64
|
+
const draftComponents = decoration.draft?.components ?? [];
|
|
65
|
+
const draftEdges = decoration.draft?.edges ?? [];
|
|
66
|
+
const sectionLabel: CSSProperties = {
|
|
67
|
+
fontFamily: theme.fonts.monospace,
|
|
68
|
+
fontSize: theme.fontSizes[0],
|
|
69
|
+
fontWeight: theme.fontWeights.semibold,
|
|
70
|
+
letterSpacing: '0.06em',
|
|
71
|
+
textTransform: 'uppercase',
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
style={{
|
|
77
|
+
display: 'flex',
|
|
78
|
+
flexDirection: 'column',
|
|
79
|
+
width: '100%',
|
|
80
|
+
height: '100%',
|
|
81
|
+
minHeight: 0,
|
|
82
|
+
background: theme.colors.background,
|
|
83
|
+
color: theme.colors.text,
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<header
|
|
87
|
+
style={{
|
|
88
|
+
flexShrink: 0,
|
|
89
|
+
padding: '14px 16px 10px',
|
|
90
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
91
|
+
}}
|
|
92
|
+
>
|
|
93
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
94
|
+
<Sparkles size={15} strokeWidth={2} color={accent} aria-hidden />
|
|
95
|
+
<h2
|
|
96
|
+
style={{
|
|
97
|
+
flex: 1,
|
|
98
|
+
minWidth: 0,
|
|
99
|
+
margin: 0,
|
|
100
|
+
overflowWrap: 'anywhere',
|
|
101
|
+
fontFamily: theme.fonts.monospace,
|
|
102
|
+
fontSize: theme.fontSizes[2],
|
|
103
|
+
fontWeight: theme.fontWeights.semibold,
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{decoration.title}
|
|
107
|
+
</h2>
|
|
108
|
+
<button
|
|
109
|
+
type="button"
|
|
110
|
+
aria-pressed={active}
|
|
111
|
+
aria-label={active ? 'Turn decoration off' : 'Turn decoration on'}
|
|
112
|
+
title={active ? 'Turn decoration off' : 'Turn decoration on'}
|
|
113
|
+
onClick={() => onToggleActive(!active)}
|
|
114
|
+
style={{
|
|
115
|
+
display: 'inline-flex',
|
|
116
|
+
alignItems: 'center',
|
|
117
|
+
gap: 4,
|
|
118
|
+
flexShrink: 0,
|
|
119
|
+
padding: '3px 8px',
|
|
120
|
+
borderRadius: 4,
|
|
121
|
+
border: `1px solid ${active ? accent : theme.colors.border}`,
|
|
122
|
+
background: active ? `${accent}18` : 'transparent',
|
|
123
|
+
color: active ? accent : muted,
|
|
124
|
+
fontFamily: theme.fonts.monospace,
|
|
125
|
+
fontSize: theme.fontSizes[0],
|
|
126
|
+
cursor: 'pointer',
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
{active ? <Eye size={12} strokeWidth={2} /> : <EyeOff size={12} strokeWidth={2} />}
|
|
130
|
+
{active ? 'On' : 'Off'}
|
|
131
|
+
</button>
|
|
132
|
+
</div>
|
|
133
|
+
</header>
|
|
134
|
+
|
|
135
|
+
<div style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '12px 16px 18px' }}>
|
|
136
|
+
{decoration.description && (
|
|
137
|
+
<div style={{ fontSize: theme.fontSizes[1], lineHeight: theme.lineHeights.body }}>
|
|
138
|
+
<IndustryMarkdownSlide
|
|
139
|
+
content={decoration.description}
|
|
140
|
+
slideIdPrefix={`decoration-${decoration.id}`}
|
|
141
|
+
slideIndex={0}
|
|
142
|
+
isVisible={true}
|
|
143
|
+
theme={theme}
|
|
144
|
+
disableScroll={true}
|
|
145
|
+
disableBasePadding
|
|
146
|
+
enableKeyboardScrolling={false}
|
|
147
|
+
autoFocusOnVisible={false}
|
|
148
|
+
/>
|
|
149
|
+
</div>
|
|
150
|
+
)}
|
|
151
|
+
|
|
152
|
+
<section
|
|
153
|
+
style={{
|
|
154
|
+
marginTop: 16,
|
|
155
|
+
paddingTop: 14,
|
|
156
|
+
borderTop: `1px solid ${theme.colors.border}`,
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
<div style={{ ...sectionLabel, color: secondary }}>
|
|
160
|
+
Trails · {decoration.trails.length}
|
|
161
|
+
</div>
|
|
162
|
+
{groups.map((group) => (
|
|
163
|
+
<div key={group.modelId}>
|
|
164
|
+
<div
|
|
165
|
+
style={{
|
|
166
|
+
display: 'flex',
|
|
167
|
+
alignItems: 'center',
|
|
168
|
+
gap: 6,
|
|
169
|
+
margin: '12px 0 3px',
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<Network size={14} strokeWidth={2} color={secondary} aria-hidden />
|
|
173
|
+
<span
|
|
174
|
+
style={{
|
|
175
|
+
minWidth: 0,
|
|
176
|
+
overflow: 'hidden',
|
|
177
|
+
textOverflow: 'ellipsis',
|
|
178
|
+
whiteSpace: 'nowrap',
|
|
179
|
+
fontFamily: theme.fonts.monospace,
|
|
180
|
+
fontSize: theme.fontSizes[1],
|
|
181
|
+
fontWeight: theme.fontWeights.semibold,
|
|
182
|
+
color: theme.colors.text,
|
|
183
|
+
}}
|
|
184
|
+
>
|
|
185
|
+
{modelLabels?.get(group.modelId) ?? group.modelId}
|
|
186
|
+
</span>
|
|
187
|
+
</div>
|
|
188
|
+
{group.trails.map((ref) => {
|
|
189
|
+
const meta = resolveTrail?.(ref);
|
|
190
|
+
const title =
|
|
191
|
+
meta?.title ??
|
|
192
|
+
(ref.kind === 'draft' ? ref.trail.title : ref.trailId);
|
|
193
|
+
const stepCount =
|
|
194
|
+
meta?.stepCount ??
|
|
195
|
+
(ref.kind === 'draft' ? ref.trail.steps.length : undefined);
|
|
196
|
+
return (
|
|
197
|
+
<button
|
|
198
|
+
key={decorationTrailId(ref)}
|
|
199
|
+
type="button"
|
|
200
|
+
onClick={() => onSelectTrail?.(ref)}
|
|
201
|
+
style={{
|
|
202
|
+
display: 'flex',
|
|
203
|
+
alignItems: 'center',
|
|
204
|
+
gap: 8,
|
|
205
|
+
width: '100%',
|
|
206
|
+
minWidth: 0,
|
|
207
|
+
padding: '6px 6px 6px 0',
|
|
208
|
+
border: 'none',
|
|
209
|
+
borderRadius: 4,
|
|
210
|
+
background: 'transparent',
|
|
211
|
+
color: theme.colors.text,
|
|
212
|
+
textAlign: 'left',
|
|
213
|
+
cursor: onSelectTrail ? 'pointer' : 'default',
|
|
214
|
+
}}
|
|
215
|
+
>
|
|
216
|
+
<Route size={13} strokeWidth={2} color={muted} aria-hidden />
|
|
217
|
+
<span
|
|
218
|
+
style={{
|
|
219
|
+
flex: 1,
|
|
220
|
+
minWidth: 0,
|
|
221
|
+
overflow: 'hidden',
|
|
222
|
+
textOverflow: 'ellipsis',
|
|
223
|
+
whiteSpace: 'nowrap',
|
|
224
|
+
fontFamily: theme.fonts.monospace,
|
|
225
|
+
fontSize: theme.fontSizes[1],
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
{title}
|
|
229
|
+
</span>
|
|
230
|
+
{ref.kind === 'draft' && (
|
|
231
|
+
<span
|
|
232
|
+
style={{
|
|
233
|
+
flexShrink: 0,
|
|
234
|
+
padding: '1px 5px',
|
|
235
|
+
borderRadius: 3,
|
|
236
|
+
border: `1px solid ${warning}`,
|
|
237
|
+
color: warning,
|
|
238
|
+
fontFamily: theme.fonts.monospace,
|
|
239
|
+
fontSize: theme.fontSizes[0],
|
|
240
|
+
}}
|
|
241
|
+
>
|
|
242
|
+
draft
|
|
243
|
+
</span>
|
|
244
|
+
)}
|
|
245
|
+
{stepCount != null && (
|
|
246
|
+
<span
|
|
247
|
+
style={{
|
|
248
|
+
flexShrink: 0,
|
|
249
|
+
fontFamily: theme.fonts.monospace,
|
|
250
|
+
fontSize: theme.fontSizes[0],
|
|
251
|
+
color: secondary,
|
|
252
|
+
}}
|
|
253
|
+
>
|
|
254
|
+
{stepCount}
|
|
255
|
+
</span>
|
|
256
|
+
)}
|
|
257
|
+
</button>
|
|
258
|
+
);
|
|
259
|
+
})}
|
|
260
|
+
</div>
|
|
261
|
+
))}
|
|
262
|
+
</section>
|
|
263
|
+
|
|
264
|
+
{(draftComponents.length > 0 || draftEdges.length > 0) && (
|
|
265
|
+
<section style={{ marginTop: 18 }}>
|
|
266
|
+
<div style={{ ...sectionLabel, color: secondary }}>
|
|
267
|
+
Draft structure · not verified
|
|
268
|
+
</div>
|
|
269
|
+
{draftComponents.map((component) => (
|
|
270
|
+
<button
|
|
271
|
+
key={component.alias}
|
|
272
|
+
type="button"
|
|
273
|
+
onClick={() => onSelectDraftComponent?.(component)}
|
|
274
|
+
style={{
|
|
275
|
+
display: 'flex',
|
|
276
|
+
alignItems: 'center',
|
|
277
|
+
gap: 8,
|
|
278
|
+
width: '100%',
|
|
279
|
+
minWidth: 0,
|
|
280
|
+
padding: '6px 6px 6px 0',
|
|
281
|
+
border: 'none',
|
|
282
|
+
borderRadius: 4,
|
|
283
|
+
background: 'transparent',
|
|
284
|
+
color: theme.colors.text,
|
|
285
|
+
textAlign: 'left',
|
|
286
|
+
cursor: onSelectDraftComponent ? 'pointer' : 'default',
|
|
287
|
+
}}
|
|
288
|
+
>
|
|
289
|
+
<Box size={13} strokeWidth={2} color={muted} aria-hidden />
|
|
290
|
+
<span
|
|
291
|
+
style={{
|
|
292
|
+
flex: 1,
|
|
293
|
+
minWidth: 0,
|
|
294
|
+
overflow: 'hidden',
|
|
295
|
+
textOverflow: 'ellipsis',
|
|
296
|
+
whiteSpace: 'nowrap',
|
|
297
|
+
fontFamily: theme.fonts.monospace,
|
|
298
|
+
fontSize: theme.fontSizes[1],
|
|
299
|
+
}}
|
|
300
|
+
>
|
|
301
|
+
{component.name}
|
|
302
|
+
</span>
|
|
303
|
+
{component.construct && (
|
|
304
|
+
<span
|
|
305
|
+
style={{
|
|
306
|
+
flexShrink: 0,
|
|
307
|
+
fontFamily: theme.fonts.monospace,
|
|
308
|
+
fontSize: theme.fontSizes[0],
|
|
309
|
+
color: secondary,
|
|
310
|
+
}}
|
|
311
|
+
>
|
|
312
|
+
{component.construct}
|
|
313
|
+
</span>
|
|
314
|
+
)}
|
|
315
|
+
</button>
|
|
316
|
+
))}
|
|
317
|
+
{draftEdges.length > 0 && (
|
|
318
|
+
<div
|
|
319
|
+
style={{
|
|
320
|
+
marginTop: 4,
|
|
321
|
+
fontFamily: theme.fonts.monospace,
|
|
322
|
+
fontSize: theme.fontSizes[0],
|
|
323
|
+
color: secondary,
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
326
|
+
+ {draftEdges.length} draft edge{draftEdges.length === 1 ? '' : 's'}
|
|
327
|
+
</div>
|
|
328
|
+
)}
|
|
329
|
+
</section>
|
|
330
|
+
)}
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
@@ -26,6 +26,7 @@ export function FileDrawer({
|
|
|
26
26
|
suppressEscape = false,
|
|
27
27
|
hidden = false,
|
|
28
28
|
progress = null,
|
|
29
|
+
subheader = null,
|
|
29
30
|
children,
|
|
30
31
|
}: {
|
|
31
32
|
/** Drawer chrome title; `null` closes the drawer. */
|
|
@@ -43,6 +44,8 @@ export function FileDrawer({
|
|
|
43
44
|
* content with no position (a single file).
|
|
44
45
|
*/
|
|
45
46
|
progress?: { index: number; total: number } | null;
|
|
47
|
+
/** Optional chrome row below the title (e.g. the trail call stack). */
|
|
48
|
+
subheader?: ReactNode;
|
|
46
49
|
children?: ReactNode;
|
|
47
50
|
}) {
|
|
48
51
|
const { theme } = useTheme();
|
|
@@ -223,6 +226,9 @@ export function FileDrawer({
|
|
|
223
226
|
</button>
|
|
224
227
|
</div>
|
|
225
228
|
</div>
|
|
229
|
+
{subheader != null && open && (
|
|
230
|
+
<div style={{ flexShrink: 0, minHeight: 0 }}>{subheader}</div>
|
|
231
|
+
)}
|
|
226
232
|
<div style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
|
|
227
233
|
{children}
|
|
228
234
|
</div>
|
|
@@ -123,6 +123,12 @@ const KIND_CATEGORY: Record<string, SubsystemIssueCategory> = {
|
|
|
123
123
|
trail: 'trail',
|
|
124
124
|
step_span_unconfirmed: 'trail',
|
|
125
125
|
step_span_stale: 'trail',
|
|
126
|
+
step_site_outside_from: 'trail',
|
|
127
|
+
step_site_unconfirmed: 'trail',
|
|
128
|
+
step_site_mismatch: 'trail',
|
|
129
|
+
step_site_stale: 'trail',
|
|
130
|
+
step_target_mismatch: 'trail',
|
|
131
|
+
step_target_stale: 'trail',
|
|
126
132
|
};
|
|
127
133
|
|
|
128
134
|
/**
|
|
@@ -198,6 +204,14 @@ export const ISSUE_KIND_ICON: Record<string, LucideIcon> = {
|
|
|
198
204
|
construct_span_stale: FileCodeCorner,
|
|
199
205
|
step_span_unconfirmed: FileCodeCorner,
|
|
200
206
|
step_span_stale: FileCodeCorner,
|
|
207
|
+
// A `calls` edge whose site does not live in the source component — the
|
|
208
|
+
// mechanism and the code are disagreeing, so a broken-link glyph.
|
|
209
|
+
step_site_outside_from: Link2Off,
|
|
210
|
+
step_site_unconfirmed: FileCodeCorner,
|
|
211
|
+
step_site_mismatch: Link2Off,
|
|
212
|
+
step_site_stale: FileCodeCorner,
|
|
213
|
+
step_target_mismatch: Link2Off,
|
|
214
|
+
step_target_stale: FileCodeCorner,
|
|
201
215
|
};
|
|
202
216
|
|
|
203
217
|
/**
|
|
@@ -288,6 +302,12 @@ const KIND_LABEL: Record<string, string> = {
|
|
|
288
302
|
trail: 'Step issue',
|
|
289
303
|
step_span_unconfirmed: 'Step span not captured',
|
|
290
304
|
step_span_stale: 'Step span changed',
|
|
305
|
+
step_site_outside_from: 'Calls site outside source',
|
|
306
|
+
step_site_unconfirmed: 'Site construct not captured',
|
|
307
|
+
step_site_mismatch: 'Site construct mismatch',
|
|
308
|
+
step_site_stale: 'Site construct changed',
|
|
309
|
+
step_target_mismatch: 'Target construct mismatch',
|
|
310
|
+
step_target_stale: 'Target construct changed',
|
|
291
311
|
};
|
|
292
312
|
|
|
293
313
|
/** Label for an issue's kind. Explicit `kindLabel` wins; unknown kinds humanize. */
|
|
@@ -329,6 +349,12 @@ const KIND_ORDER: Record<string, number> = {
|
|
|
329
349
|
trail: 40,
|
|
330
350
|
step_span_unconfirmed: 41,
|
|
331
351
|
step_span_stale: 42,
|
|
352
|
+
step_site_outside_from: 43,
|
|
353
|
+
step_site_unconfirmed: 44,
|
|
354
|
+
step_site_mismatch: 45,
|
|
355
|
+
step_site_stale: 46,
|
|
356
|
+
step_target_mismatch: 47,
|
|
357
|
+
step_target_stale: 48,
|
|
332
358
|
};
|
|
333
359
|
|
|
334
360
|
const KIND_ORDER_FALLBACK = 100;
|