@principal-ai/subsystems-react 0.44.4 → 0.45.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/README.md +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/pierre/{PierreWalkthroughCodeView.d.ts → PierreTrailCodeView.d.ts} +11 -11
- package/dist/pierre/PierreTrailCodeView.d.ts.map +1 -0
- package/dist/pierre/{PierreWalkthroughCodeView.js → PierreTrailCodeView.js} +36 -36
- package/dist/pierre/PierreTrailCodeView.js.map +1 -0
- package/dist/pierre/index.d.ts +2 -2
- package/dist/pierre/index.d.ts.map +1 -1
- package/dist/pierre/index.js +1 -1
- package/dist/pierre/index.js.map +1 -1
- package/dist/stories/Subsystem/AggregateGraph/aggregateViewFixture.d.ts.map +1 -1
- package/dist/stories/Subsystem/AggregateGraph/aggregateViewFixture.js +1 -1
- package/dist/stories/Subsystem/AggregateGraph/aggregateViewFixture.js.map +1 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js +1 -1
- package/dist/stories/Subsystem/C4Graph/c4Fixture.js.map +1 -1
- package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts +9 -9
- package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -1
- package/dist/stories/Subsystem/ComponentGraph/fixtures.js +12 -12
- package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -1
- package/dist/subsystem/C4Graph.d.ts +2 -2
- package/dist/subsystem/C4Graph.js +2 -2
- package/dist/subsystem/ConstructsCatalog.d.ts +1 -1
- package/dist/subsystem/ConstructsCatalog.js +1 -1
- package/dist/subsystem/DiagnosticToggle.d.ts +1 -1
- package/dist/subsystem/DiagnosticToggle.js +1 -1
- package/dist/subsystem/FileDrawer.d.ts +2 -2
- package/dist/subsystem/FileDrawer.js +2 -2
- package/dist/subsystem/IssueList.d.ts +6 -6
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +9 -9
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemAggregateGraph.d.ts +3 -3
- package/dist/subsystem/SubsystemAggregateGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemAggregateGraph.js +2 -2
- package/dist/subsystem/SubsystemComponentGraph.d.ts +45 -45
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +284 -277
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/SubsystemModelTransition.d.ts +10 -10
- package/dist/subsystem/SubsystemModelTransition.d.ts.map +1 -1
- package/dist/subsystem/SubsystemModelTransition.js +42 -42
- package/dist/subsystem/SubsystemModelTransition.js.map +1 -1
- package/dist/subsystem/TrailsPanel.d.ts +55 -0
- package/dist/subsystem/TrailsPanel.d.ts.map +1 -0
- package/dist/subsystem/{WalkthroughsPanel.js → TrailsPanel.js} +51 -51
- package/dist/subsystem/TrailsPanel.js.map +1 -0
- package/dist/subsystem/declarationRef.d.ts +1 -1
- package/dist/subsystem/declarationRef.d.ts.map +1 -1
- package/dist/subsystem/model.d.ts +40 -40
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +17 -17
- package/dist/subsystem/model.js.map +1 -1
- package/dist/subsystem/nodes.d.ts +1 -1
- package/dist/subsystem/nodes.js +1 -1
- package/dist/subsystem/toC4.d.ts +2 -2
- package/dist/subsystem/toC4.d.ts.map +1 -1
- package/dist/subsystem/toC4.js +2 -2
- package/dist/subsystem/toC4.js.map +1 -1
- package/dist/subsystem/trailBrief.d.ts +18 -0
- package/dist/subsystem/trailBrief.d.ts.map +1 -0
- package/dist/subsystem/{walkthroughBrief.js → trailBrief.js} +8 -8
- package/dist/subsystem/trailBrief.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +15 -15
- package/src/pierre/{PierreWalkthroughCodeView.tsx → PierreTrailCodeView.tsx} +56 -56
- package/src/pierre/index.ts +2 -2
- package/src/stories/Pierre/CodeView.stories.tsx +3 -3
- package/src/stories/Subsystem/AggregateGraph/AggregateFrameGraph.stories.tsx +1 -1
- package/src/stories/Subsystem/AggregateGraph/aggregateViewFixture.ts +1 -1
- package/src/stories/Subsystem/C4Graph/c4Fixture.ts +1 -1
- package/src/stories/Subsystem/ComponentDeclarationAudit.stories.tsx +8 -8
- package/src/stories/Subsystem/ComponentGraph/AnimatedProgression.stories.tsx +13 -13
- package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +2 -2
- package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +5 -5
- package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +8 -8
- package/src/stories/Subsystem/ComponentGraph/CustomEntities.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +6 -6
- package/src/stories/Subsystem/ComponentGraph/EdgeViews.stories.tsx +12 -12
- package/src/stories/Subsystem/ComponentGraph/Flows.stories.tsx +36 -36
- package/src/stories/Subsystem/ComponentGraph/FrameworkStereotype.stories.tsx +7 -7
- package/src/stories/Subsystem/ComponentGraph/GraphTitle.stories.tsx +4 -4
- package/src/stories/Subsystem/ComponentGraph/IssueOverlay.stories.tsx +8 -8
- package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +4 -4
- package/src/stories/Subsystem/ComponentGraph/ModuleBadges.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/Modules.stories.tsx +5 -5
- package/src/stories/Subsystem/ComponentGraph/Packages.stories.tsx +6 -6
- package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/Proposed.stories.tsx +4 -4
- package/src/stories/Subsystem/ComponentGraph/{ProposedWalkthroughs.stories.tsx → ProposedTrails.stories.tsx} +9 -9
- package/src/stories/Subsystem/ComponentGraph/Reorder.stories.tsx +19 -19
- package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +21 -21
- package/src/stories/Subsystem/ComponentGraph/{WalkthroughAutoplay.stories.tsx → TrailAutoplay.stories.tsx} +22 -22
- package/src/stories/Subsystem/ComponentGraph/WorkspacePackageFrames.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/fixtures.ts +19 -19
- package/src/subsystem/C4Graph.tsx +2 -2
- package/src/subsystem/ConstructsCatalog.tsx +1 -1
- package/src/subsystem/DiagnosticToggle.tsx +1 -1
- package/src/subsystem/FileDrawer.tsx +2 -2
- package/src/subsystem/IssueList.focus.test.tsx +4 -4
- package/src/subsystem/IssueList.icon.test.tsx +3 -3
- package/src/subsystem/IssueList.tsx +14 -14
- package/src/subsystem/SubsystemAggregateGraph.tsx +3 -3
- package/src/subsystem/SubsystemComponentGraph.tsx +377 -371
- package/src/subsystem/SubsystemModelTransition.tsx +61 -61
- package/src/subsystem/{WalkthroughsPanel.test.tsx → TrailsPanel.test.tsx} +16 -16
- package/src/subsystem/{WalkthroughsPanel.tsx → TrailsPanel.tsx} +81 -81
- package/src/subsystem/declarationRef.ts +1 -1
- package/src/subsystem/formatDeclaration.test.ts +6 -6
- package/src/subsystem/model.test.ts +25 -25
- package/src/subsystem/model.ts +51 -51
- package/src/subsystem/nodes.tsx +1 -1
- package/src/subsystem/toC4.test.ts +1 -1
- package/src/subsystem/toC4.ts +3 -3
- package/src/subsystem/{walkthroughBrief.test.ts → trailBrief.test.ts} +10 -10
- package/src/subsystem/{walkthroughBrief.ts → trailBrief.ts} +8 -8
- package/dist/pierre/PierreWalkthroughCodeView.d.ts.map +0 -1
- package/dist/pierre/PierreWalkthroughCodeView.js.map +0 -1
- package/dist/subsystem/WalkthroughsPanel.d.ts +0 -55
- package/dist/subsystem/WalkthroughsPanel.d.ts.map +0 -1
- package/dist/subsystem/WalkthroughsPanel.js.map +0 -1
- package/dist/subsystem/walkthroughBrief.d.ts +0 -18
- package/dist/subsystem/walkthroughBrief.d.ts.map +0 -1
- package/dist/subsystem/walkthroughBrief.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* PierreTrailCodeView — multi-file step snippets via `@pierre/diffs` CodeView.
|
|
3
3
|
*
|
|
4
|
-
* Renders one sliced window per
|
|
4
|
+
* Renders one sliced window per trail step in a single virtualized
|
|
5
5
|
* scroll; when `stepIndex` changes, scrolls that step's site line into view
|
|
6
6
|
* and highlights it via CodeView `selectedLines` (same mechanism as
|
|
7
7
|
* `PierreSnippetView`).
|
|
@@ -31,12 +31,12 @@ type CodeViewLineSelection = {
|
|
|
31
31
|
id: string;
|
|
32
32
|
range: { start: number; end: number };
|
|
33
33
|
};
|
|
34
|
-
/** Metadata carried on a
|
|
35
|
-
type
|
|
34
|
+
/** Metadata carried on a trail step's line annotation. */
|
|
35
|
+
type TrailStepAnnotation = { text: string };
|
|
36
36
|
import { useTheme } from '@principal-ade/industry-theme';
|
|
37
37
|
import type {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
SubsystemTrail,
|
|
39
|
+
SubsystemTrailStep,
|
|
40
40
|
} from '../subsystem/model';
|
|
41
41
|
import type { SubsystemOpenFileOptions } from '../subsystem/declarationRef';
|
|
42
42
|
import { buildPierreOptions, PIERRE_FILE_STYLE } from './pierreBackground';
|
|
@@ -51,15 +51,15 @@ import {
|
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* A token the user clicked or hovered inside a step's snippet. `stepIndex` is
|
|
54
|
-
* the zero-based index of the
|
|
54
|
+
* the zero-based index of the trail step whose snippet it sits in, so a
|
|
55
55
|
* host can resolve the token against that step's construct endpoints.
|
|
56
56
|
*/
|
|
57
|
-
export interface
|
|
57
|
+
export interface TrailSymbolQuery {
|
|
58
58
|
stepIndex: number;
|
|
59
59
|
tokenText: string;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** Ctx item id → step index, for CodeView's `
|
|
62
|
+
/** Ctx item id → step index, for CodeView's `trailId:index` item ids. */
|
|
63
63
|
function stepIndexFromItemContext(context: unknown): number | null {
|
|
64
64
|
const id = (context as { item?: { id?: string } } | undefined)?.item?.id;
|
|
65
65
|
if (id == null) return null;
|
|
@@ -76,8 +76,8 @@ function paintSymbolToken(el: HTMLElement | undefined, active: boolean): void {
|
|
|
76
76
|
el.style.textUnderlineOffset = active ? '2px' : '';
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export interface
|
|
80
|
-
|
|
79
|
+
export interface PierreTrailCodeViewProps {
|
|
80
|
+
trail: SubsystemTrail;
|
|
81
81
|
/** Focused step; `null` shows all snippets without scrolling to a step. */
|
|
82
82
|
stepIndex: number | null;
|
|
83
83
|
/** Read a step site; `purl` names the seam site's repo for checkout resolution. */
|
|
@@ -99,9 +99,9 @@ export interface PierreWalkthroughCodeViewProps {
|
|
|
99
99
|
* construct this flow touches. When both this and `onSymbolClick` are set,
|
|
100
100
|
* matching tokens read as clickable (pointer + dotted underline).
|
|
101
101
|
*/
|
|
102
|
-
resolveSymbol?: (query:
|
|
102
|
+
resolveSymbol?: (query: TrailSymbolQuery) => string | null;
|
|
103
103
|
/** Fired when a token resolved by `resolveSymbol` is clicked. */
|
|
104
|
-
onSymbolClick?: (symbol: string, query:
|
|
104
|
+
onSymbolClick?: (symbol: string, query: TrailSymbolQuery) => void;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
type FileLoadState =
|
|
@@ -113,18 +113,18 @@ type FileLoadState =
|
|
|
113
113
|
unavailable: Map<string, string>;
|
|
114
114
|
};
|
|
115
115
|
|
|
116
|
-
function stepItemId(
|
|
117
|
-
return `${
|
|
116
|
+
function stepItemId(trailId: string, index: number): string {
|
|
117
|
+
return `${trailId}:${index}`;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/** Stable key for a step's file within a repo (mirrors `pathsKey`). */
|
|
121
|
-
function siteKey(step: Pick<
|
|
121
|
+
function siteKey(step: Pick<SubsystemTrailStep, 'purl' | 'file'>): string {
|
|
122
122
|
return `${step.purl}\0${step.file}`;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/** Notice shown in place of a snippet whose file the host couldn't read. */
|
|
126
126
|
function unavailableNotice(
|
|
127
|
-
step:
|
|
127
|
+
step: SubsystemTrailStep,
|
|
128
128
|
error: string,
|
|
129
129
|
proposed: boolean,
|
|
130
130
|
): string {
|
|
@@ -186,8 +186,8 @@ function OpenFileHeaderButton({
|
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
export function
|
|
190
|
-
|
|
189
|
+
export function PierreTrailCodeView({
|
|
190
|
+
trail,
|
|
191
191
|
stepIndex,
|
|
192
192
|
readFile,
|
|
193
193
|
contextLines = 8,
|
|
@@ -196,7 +196,7 @@ export function PierreWalkthroughCodeView({
|
|
|
196
196
|
proposedAliases,
|
|
197
197
|
resolveSymbol,
|
|
198
198
|
onSymbolClick,
|
|
199
|
-
}:
|
|
199
|
+
}: PierreTrailCodeViewProps) {
|
|
200
200
|
const { theme, mode } = useTheme();
|
|
201
201
|
const viewRef = useRef<CodeViewHandle<undefined>>(null);
|
|
202
202
|
const [load, setLoad] = useState<FileLoadState>({ status: 'loading' });
|
|
@@ -208,28 +208,28 @@ export function PierreWalkthroughCodeView({
|
|
|
208
208
|
const onSymbolClickRef = useRef(onSymbolClick);
|
|
209
209
|
onSymbolClickRef.current = onSymbolClick;
|
|
210
210
|
|
|
211
|
-
// A
|
|
211
|
+
// A step onto a proposed component is planned work; label its missing file
|
|
212
212
|
// accordingly instead of showing a bare "not found".
|
|
213
213
|
const isProposedStep = useCallback(
|
|
214
|
-
(step:
|
|
214
|
+
(step: SubsystemTrailStep): boolean =>
|
|
215
215
|
proposedAliases != null &&
|
|
216
216
|
(proposedAliases.has(step.from) || proposedAliases.has(step.to)),
|
|
217
217
|
[proposedAliases],
|
|
218
218
|
);
|
|
219
219
|
|
|
220
220
|
const pathsKey = useMemo(() => {
|
|
221
|
-
const keys = [...new Set(
|
|
221
|
+
const keys = [...new Set(trail.steps.map((s) => siteKey(s)))];
|
|
222
222
|
keys.sort();
|
|
223
223
|
return keys.join('\0');
|
|
224
|
-
}, [
|
|
224
|
+
}, [trail.steps]);
|
|
225
225
|
|
|
226
226
|
// Load each site independently: one unreadable step (a proposed seam whose
|
|
227
|
-
// file isn't implemented yet) must not blank the whole
|
|
227
|
+
// file isn't implemented yet) must not blank the whole trail. Failures
|
|
228
228
|
// are kept per-path and rendered as inline placeholders below.
|
|
229
229
|
useEffect(() => {
|
|
230
230
|
let cancelled = false;
|
|
231
231
|
setLoad({ status: 'loading' });
|
|
232
|
-
const sites = [...new Map(
|
|
232
|
+
const sites = [...new Map(trail.steps.map((s) => [siteKey(s), s])).values()];
|
|
233
233
|
void Promise.all(
|
|
234
234
|
sites.map(async (step) => {
|
|
235
235
|
const key = siteKey(step);
|
|
@@ -257,11 +257,11 @@ export function PierreWalkthroughCodeView({
|
|
|
257
257
|
return () => {
|
|
258
258
|
cancelled = true;
|
|
259
259
|
};
|
|
260
|
-
}, [
|
|
260
|
+
}, [trail.id, pathsKey, readFile]);
|
|
261
261
|
|
|
262
262
|
const slices = useMemo((): SnippetSlice[] => {
|
|
263
263
|
if (load.status !== 'ready') return [];
|
|
264
|
-
return
|
|
264
|
+
return trail.steps.map((step) => {
|
|
265
265
|
const key = siteKey(step);
|
|
266
266
|
const failure = load.unavailable.get(key);
|
|
267
267
|
if (failure != null) {
|
|
@@ -278,11 +278,11 @@ export function PierreWalkthroughCodeView({
|
|
|
278
278
|
step.line,
|
|
279
279
|
);
|
|
280
280
|
});
|
|
281
|
-
}, [load,
|
|
281
|
+
}, [load, trail.steps, contextLines, isProposedStep]);
|
|
282
282
|
|
|
283
|
-
const items = useMemo((): CodeViewItem<
|
|
283
|
+
const items = useMemo((): CodeViewItem<TrailStepAnnotation>[] => {
|
|
284
284
|
if (load.status !== 'ready' || slices.length === 0) return [];
|
|
285
|
-
return
|
|
285
|
+
return trail.steps.map((step, index) => {
|
|
286
286
|
const slice = slices[index]!;
|
|
287
287
|
const focus = slice.focusOffset;
|
|
288
288
|
const key = siteKey(step);
|
|
@@ -290,7 +290,7 @@ export function PierreWalkthroughCodeView({
|
|
|
290
290
|
// The placeholder line already carries the reason, so it replaces any
|
|
291
291
|
// authored annotation rather than stacking with it.
|
|
292
292
|
const annotations:
|
|
293
|
-
| LineAnnotation<
|
|
293
|
+
| LineAnnotation<TrailStepAnnotation>[]
|
|
294
294
|
| undefined =
|
|
295
295
|
failure == null &&
|
|
296
296
|
step.annotation != null &&
|
|
@@ -304,7 +304,7 @@ export function PierreWalkthroughCodeView({
|
|
|
304
304
|
]
|
|
305
305
|
: undefined;
|
|
306
306
|
return {
|
|
307
|
-
id: stepItemId(
|
|
307
|
+
id: stepItemId(trail.id, index),
|
|
308
308
|
type: 'file' as const,
|
|
309
309
|
version: 1,
|
|
310
310
|
annotations,
|
|
@@ -312,11 +312,11 @@ export function PierreWalkthroughCodeView({
|
|
|
312
312
|
name: step.file,
|
|
313
313
|
contents: slice.contents,
|
|
314
314
|
lang: pierreLangForPath(step.file),
|
|
315
|
-
cacheKey: `${
|
|
315
|
+
cacheKey: `${trail.id}:${index}:${step.file}:${step.line}:${slice.sliceStart}-${slice.sliceEnd}${failure != null ? ':unavailable' : ''}`,
|
|
316
316
|
},
|
|
317
317
|
};
|
|
318
318
|
});
|
|
319
|
-
}, [load, slices,
|
|
319
|
+
}, [load, slices, trail.id, trail.steps, isProposedStep]);
|
|
320
320
|
|
|
321
321
|
const selectedLines = useMemo((): CodeViewLineSelection | null => {
|
|
322
322
|
if (stepIndex == null || stepIndex < 0 || stepIndex >= slices.length) {
|
|
@@ -325,18 +325,18 @@ export function PierreWalkthroughCodeView({
|
|
|
325
325
|
const focus = slices[stepIndex]?.focusOffset;
|
|
326
326
|
if (focus == null) return null;
|
|
327
327
|
return {
|
|
328
|
-
id: stepItemId(
|
|
328
|
+
id: stepItemId(trail.id, stepIndex),
|
|
329
329
|
range: { start: focus, end: focus },
|
|
330
330
|
};
|
|
331
|
-
}, [stepIndex, slices,
|
|
331
|
+
}, [stepIndex, slices, trail.id]);
|
|
332
332
|
|
|
333
333
|
const sliceStartByItemId = useMemo(() => {
|
|
334
334
|
const map = new Map<string, number>();
|
|
335
335
|
for (let i = 0; i < slices.length; i++) {
|
|
336
|
-
map.set(stepItemId(
|
|
336
|
+
map.set(stepItemId(trail.id, i), slices[i]!.sliceStart);
|
|
337
337
|
}
|
|
338
338
|
return map;
|
|
339
|
-
}, [slices,
|
|
339
|
+
}, [slices, trail.id]);
|
|
340
340
|
|
|
341
341
|
const onPostRender = useCallback(
|
|
342
342
|
(
|
|
@@ -357,7 +357,7 @@ export function PierreWalkthroughCodeView({
|
|
|
357
357
|
const renderHeaderPrefix = useMemo(() => {
|
|
358
358
|
return (item: CodeViewItem) => {
|
|
359
359
|
const index = Number.parseInt(item.id.split(':').pop() ?? '', 10);
|
|
360
|
-
if (!
|
|
360
|
+
if (!trail.steps[index]) return null;
|
|
361
361
|
return (
|
|
362
362
|
<span
|
|
363
363
|
style={{
|
|
@@ -371,12 +371,12 @@ export function PierreWalkthroughCodeView({
|
|
|
371
371
|
</span>
|
|
372
372
|
);
|
|
373
373
|
};
|
|
374
|
-
}, [
|
|
374
|
+
}, [trail.steps, theme]);
|
|
375
375
|
|
|
376
376
|
const renderHeaderMetadata = useMemo(() => {
|
|
377
377
|
return (item: CodeViewItem) => {
|
|
378
378
|
const index = Number.parseInt(item.id.split(':').pop() ?? '', 10);
|
|
379
|
-
const step =
|
|
379
|
+
const step = trail.steps[index];
|
|
380
380
|
if (!step) return null;
|
|
381
381
|
// Unreadable sites have nothing to open — say so instead of offering a
|
|
382
382
|
// button that would only fail again in the full-file overlay.
|
|
@@ -413,17 +413,17 @@ export function PierreWalkthroughCodeView({
|
|
|
413
413
|
</span>
|
|
414
414
|
);
|
|
415
415
|
};
|
|
416
|
-
}, [
|
|
416
|
+
}, [trail.steps, theme, onOpenFile, load]);
|
|
417
417
|
|
|
418
418
|
const renderAnnotation = useMemo(() => {
|
|
419
419
|
return (
|
|
420
420
|
annotation:
|
|
421
|
-
| LineAnnotation<
|
|
422
|
-
| DiffLineAnnotation<
|
|
423
|
-
item: CodeViewItem<
|
|
421
|
+
| LineAnnotation<TrailStepAnnotation>
|
|
422
|
+
| DiffLineAnnotation<TrailStepAnnotation>,
|
|
423
|
+
item: CodeViewItem<TrailStepAnnotation>,
|
|
424
424
|
) => {
|
|
425
425
|
const index = Number.parseInt(item.id.split(':').pop() ?? '', 10);
|
|
426
|
-
const step =
|
|
426
|
+
const step = trail.steps[index];
|
|
427
427
|
const text = annotation.metadata?.text;
|
|
428
428
|
if (!text || !step) return null;
|
|
429
429
|
return (
|
|
@@ -441,7 +441,7 @@ export function PierreWalkthroughCodeView({
|
|
|
441
441
|
</span>
|
|
442
442
|
);
|
|
443
443
|
};
|
|
444
|
-
}, [
|
|
444
|
+
}, [trail.steps, theme]);
|
|
445
445
|
|
|
446
446
|
const onLineClick = useCallback(
|
|
447
447
|
(
|
|
@@ -453,12 +453,12 @@ export function PierreWalkthroughCodeView({
|
|
|
453
453
|
const id = context?.item?.id;
|
|
454
454
|
if (id == null) return;
|
|
455
455
|
const index = Number.parseInt(id.split(':').pop() ?? '', 10);
|
|
456
|
-
const step =
|
|
456
|
+
const step = trail.steps[index];
|
|
457
457
|
if (!step) return;
|
|
458
458
|
if (load.status === 'ready' && load.unavailable.has(siteKey(step))) return;
|
|
459
459
|
onOpenFile(step.file, { startLine: step.line, fullFile: true });
|
|
460
460
|
},
|
|
461
|
-
[onOpenFile,
|
|
461
|
+
[onOpenFile, trail.steps, load],
|
|
462
462
|
);
|
|
463
463
|
|
|
464
464
|
// Per-token interactions for construct navigation. Only wired when the host
|
|
@@ -469,7 +469,7 @@ export function PierreWalkthroughCodeView({
|
|
|
469
469
|
const resolveAt = (
|
|
470
470
|
props: TokenEventBase,
|
|
471
471
|
context: unknown,
|
|
472
|
-
): { symbol: string; query:
|
|
472
|
+
): { symbol: string; query: TrailSymbolQuery } | null => {
|
|
473
473
|
const stepIndex = stepIndexFromItemContext(context);
|
|
474
474
|
const tokenText = props?.tokenText;
|
|
475
475
|
if (stepIndex == null || !tokenText) return null;
|
|
@@ -507,10 +507,10 @@ export function PierreWalkthroughCodeView({
|
|
|
507
507
|
|
|
508
508
|
useEffect(() => {
|
|
509
509
|
if (load.status !== 'ready' || stepIndex == null) return;
|
|
510
|
-
if (stepIndex < 0 || stepIndex >=
|
|
510
|
+
if (stepIndex < 0 || stepIndex >= trail.steps.length) return;
|
|
511
511
|
const focus = slices[stepIndex]?.focusOffset;
|
|
512
512
|
if (focus == null) return;
|
|
513
|
-
const id = stepItemId(
|
|
513
|
+
const id = stepItemId(trail.id, stepIndex);
|
|
514
514
|
const t = window.setTimeout(() => {
|
|
515
515
|
viewRef.current?.scrollTo({
|
|
516
516
|
type: 'line',
|
|
@@ -523,8 +523,8 @@ export function PierreWalkthroughCodeView({
|
|
|
523
523
|
}, [
|
|
524
524
|
load.status,
|
|
525
525
|
stepIndex,
|
|
526
|
-
|
|
527
|
-
|
|
526
|
+
trail.id,
|
|
527
|
+
trail.steps.length,
|
|
528
528
|
slices,
|
|
529
529
|
items.length,
|
|
530
530
|
]);
|
|
@@ -539,7 +539,7 @@ export function PierreWalkthroughCodeView({
|
|
|
539
539
|
if (items.length === 0) {
|
|
540
540
|
return (
|
|
541
541
|
<div style={{ padding: 16, color: theme.colors.textSecondary }}>
|
|
542
|
-
No steps in this
|
|
542
|
+
No steps in this trail.
|
|
543
543
|
</div>
|
|
544
544
|
);
|
|
545
545
|
}
|
package/src/pierre/index.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { PierreFileView } from './PierreFileView';
|
|
|
2
2
|
export type { PierreFileViewProps } from './PierreFileView';
|
|
3
3
|
export { PierreSnippetView } from './PierreSnippetView';
|
|
4
4
|
export type { PierreSnippetViewProps } from './PierreSnippetView';
|
|
5
|
-
export {
|
|
6
|
-
export type {
|
|
5
|
+
export { PierreTrailCodeView } from './PierreTrailCodeView';
|
|
6
|
+
export type { PierreTrailCodeViewProps } from './PierreTrailCodeView';
|
|
7
7
|
export { remapSnippetLineNumbers, sliceSnippetWindow } from './sliceSnippet';
|
|
8
8
|
export type { SnippetSlice } from './sliceSnippet';
|
|
9
9
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Demo: Pierre CodeView with snippets from different files.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Trails want many short windows across files in one scroll —
|
|
5
5
|
* CodeView is the Pierre primitive for that (virtualized list of file items).
|
|
6
6
|
*/
|
|
7
7
|
import React, { useMemo, useRef } from 'react';
|
|
@@ -54,7 +54,7 @@ const SNIPPETS: SnippetSpec[] = [
|
|
|
54
54
|
startLine: 216,
|
|
55
55
|
endLine: 250,
|
|
56
56
|
focusLine: 216,
|
|
57
|
-
label: '3 ·
|
|
57
|
+
label: '3 · Trail types',
|
|
58
58
|
},
|
|
59
59
|
];
|
|
60
60
|
|
|
@@ -159,7 +159,7 @@ function MultiFileSnippetsDemo() {
|
|
|
159
159
|
}}
|
|
160
160
|
>
|
|
161
161
|
<div style={{ fontSize: 13, fontWeight: 600, marginBottom: 4 }}>
|
|
162
|
-
|
|
162
|
+
Trail steps
|
|
163
163
|
</div>
|
|
164
164
|
<div style={{ fontSize: 12, color: theme.colors.textSecondary, marginBottom: 8 }}>
|
|
165
165
|
Click a step to scroll + highlight its site line.
|
|
@@ -29,7 +29,7 @@ export default meta;
|
|
|
29
29
|
type Story = StoryObj<typeof meta>;
|
|
30
30
|
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
|
-
// Frame-level aggregate: process/module boxes with deduped
|
|
32
|
+
// Frame-level aggregate: process/module boxes with deduped trail flows.
|
|
33
33
|
// Same stack as the component graph (React Flow + ELK), purpose-built nodes.
|
|
34
34
|
// Hover highlights the neighborhood; click selects and lists members.
|
|
35
35
|
// ---------------------------------------------------------------------------
|