@principal-ai/subsystems-react 0.37.10 → 0.37.12
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/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/SubsystemComponentGraph.d.ts +13 -0
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +168 -37
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/model.d.ts +21 -0
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +4 -1
- package/dist/subsystem/model.js.map +1 -1
- package/dist/utils/elkLayout.d.ts +12 -0
- package/dist/utils/elkLayout.d.ts.map +1 -1
- package/dist/utils/elkLayout.js +10 -0
- package/dist/utils/elkLayout.js.map +1 -1
- package/package.json +1 -1
- package/src/stories/Subsystem/ComponentGraph/WalkthroughAutoplay.stories.tsx +218 -0
- package/src/subsystem/FileDrawer.tsx +4 -1
- package/src/subsystem/SubsystemComponentGraph.tsx +187 -37
- package/src/subsystem/model.ts +20 -1
- package/src/utils/elkLayout.ts +20 -0
|
@@ -13,7 +13,7 @@ export declare const FILE_DRAWER_HEIGHT_MS = 200;
|
|
|
13
13
|
* footprint so the canvas shrinks while open (nothing covered). Stays mounted
|
|
14
14
|
* so open/close/maximize animate. The header's maximize button (or a
|
|
15
15
|
* double-click) grows it over the whole graph column for whole-file reading. */
|
|
16
|
-
export declare function FileDrawer({ title, onClose, fillHeight, suppressEscape, children, }: {
|
|
16
|
+
export declare function FileDrawer({ title, onClose, fillHeight, suppressEscape, hidden, children, }: {
|
|
17
17
|
/** Drawer chrome title; `null` closes the drawer. */
|
|
18
18
|
title: string | null;
|
|
19
19
|
onClose: () => void;
|
|
@@ -21,6 +21,8 @@ export declare function FileDrawer({ title, onClose, fillHeight, suppressEscape,
|
|
|
21
21
|
fillHeight?: boolean;
|
|
22
22
|
/** Skip Escape handling (e.g. while a full-file overlay is on top). */
|
|
23
23
|
suppressEscape?: boolean;
|
|
24
|
+
/** Suppress the drawer entirely — no spacer, no panel (embeds). */
|
|
25
|
+
hidden?: boolean;
|
|
24
26
|
children?: ReactNode;
|
|
25
27
|
}): import("react").JSX.Element;
|
|
26
28
|
//# sourceMappingURL=FileDrawer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDrawer.d.ts","sourceRoot":"","sources":["../../src/subsystem/FileDrawer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;2EAC2E;AAC3E,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;iFAIiF;AACjF,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,UAAkB,EAClB,cAAsB,EACtB,QAAQ,GACT,EAAE;IACD,qDAAqD;IACrD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BAiJA"}
|
|
1
|
+
{"version":3,"file":"FileDrawer.d.ts","sourceRoot":"","sources":["../../src/subsystem/FileDrawer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;2EAC2E;AAC3E,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;iFAIiF;AACjF,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,UAAkB,EAClB,cAAsB,EACtB,MAAc,EACd,QAAQ,GACT,EAAE;IACD,qDAAqD;IACrD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BAiJA"}
|
|
@@ -16,10 +16,10 @@ export const FILE_DRAWER_HEIGHT_MS = 200;
|
|
|
16
16
|
* footprint so the canvas shrinks while open (nothing covered). Stays mounted
|
|
17
17
|
* so open/close/maximize animate. The header's maximize button (or a
|
|
18
18
|
* double-click) grows it over the whole graph column for whole-file reading. */
|
|
19
|
-
export function FileDrawer({ title, onClose, fillHeight = false, suppressEscape = false, children, }) {
|
|
19
|
+
export function FileDrawer({ title, onClose, fillHeight = false, suppressEscape = false, hidden = false, children, }) {
|
|
20
20
|
const { theme } = useTheme();
|
|
21
21
|
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
22
|
-
const open = title !== null;
|
|
22
|
+
const open = title !== null && !hidden;
|
|
23
23
|
const [closeHover, setCloseHover] = useState(false);
|
|
24
24
|
const [maxHover, setMaxHover] = useState(false);
|
|
25
25
|
// Full-height mode: the maximize button or double-clicking the header.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDrawer.js","sourceRoot":"","sources":["../../src/subsystem/FileDrawer.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAEvD;2EAC2E;AAC3E,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAEzC;;;;iFAIiF;AACjF,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,UAAU,GAAG,KAAK,EAClB,cAAc,GAAG,KAAK,EACtB,QAAQ,
|
|
1
|
+
{"version":3,"file":"FileDrawer.js","sourceRoot":"","sources":["../../src/subsystem/FileDrawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -129,6 +129,12 @@ export interface SubsystemComponentGraphProps {
|
|
|
129
129
|
* @default true
|
|
130
130
|
*/
|
|
131
131
|
zoomOnWalkthroughFocus?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* Duration (ms) of the camera pan/zoom when a walkthrough step or flow is
|
|
134
|
+
* focused. Higher = a slower, more legible flight between steps.
|
|
135
|
+
* @default 300
|
|
136
|
+
*/
|
|
137
|
+
walkthroughFocusDurationMs?: number;
|
|
132
138
|
/**
|
|
133
139
|
* Subsystem title rendered as a non-interactive overlay chip on the graph
|
|
134
140
|
* canvas (top-center). Does not trigger the sidebar — for graph-only
|
|
@@ -197,6 +203,13 @@ export interface SubsystemComponentGraphProps {
|
|
|
197
203
|
* updates it as the focused step changes.
|
|
198
204
|
*/
|
|
199
205
|
renderWalkthroughViewer?: (ctx: WalkthroughViewerContext) => ReactNode;
|
|
206
|
+
/**
|
|
207
|
+
* Suppress the bottom file/walkthrough drawer entirely. Focusing a step then
|
|
208
|
+
* only frames it on the canvas (and dims the rest) without dropping a snippet
|
|
209
|
+
* panel below — for embeds that want the camera to tell the story. Defaults
|
|
210
|
+
* to false.
|
|
211
|
+
*/
|
|
212
|
+
hideDrawer?: boolean;
|
|
200
213
|
/**
|
|
201
214
|
* Legacy component-keyed variant, kept for backward compatibility. When
|
|
202
215
|
* `renderFileViewer` is absent, drawer content resolves via the first
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"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"}
|
|
@@ -120,9 +120,9 @@ const WalkthroughDrawerContent = memo(function WalkthroughDrawerContent({ render
|
|
|
120
120
|
onSymbolClick,
|
|
121
121
|
}) }));
|
|
122
122
|
});
|
|
123
|
-
function Inner({ components, relations, walkthroughs, initialWalkthroughId, onReorderWalkthroughs, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, showSingletonFrames = true, edgeView, title, hideSidebar, walkthroughStepMode = 'focus', autoPlayWalkthroughs = false, walkthroughAutoPlayIntervalMs = WALKTHROUGH_PLAY_PAUSE_MS, zoomOnWalkthroughFocus = true, graphTitle, showWalkthroughTitle = false, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, diagnostic, issues, showIssues, focusIssueCategory, onSelectIssue, onApplyIssueFix, onHoverIssue, renderFileView, renderFileViewer, renderWalkthroughViewer, onFileSelect, componentVerification, onInspectSymbol, boundaryColors, persistKey }) {
|
|
123
|
+
function Inner({ components, relations, walkthroughs, initialWalkthroughId, onReorderWalkthroughs, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, showSingletonFrames = true, edgeView, title, hideSidebar, walkthroughStepMode = 'focus', autoPlayWalkthroughs = false, walkthroughAutoPlayIntervalMs = WALKTHROUGH_PLAY_PAUSE_MS, zoomOnWalkthroughFocus = true, walkthroughFocusDurationMs = 300, graphTitle, showWalkthroughTitle = false, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, diagnostic, issues, showIssues, focusIssueCategory, onSelectIssue, onApplyIssueFix, onHoverIssue, renderFileView, renderFileViewer, renderWalkthroughViewer, onFileSelect, componentVerification, onInspectSymbol, boundaryColors, hideDrawer = false, persistKey }) {
|
|
124
124
|
const { theme } = useTheme();
|
|
125
|
-
const { fitView } = useReactFlow();
|
|
125
|
+
const { fitView, fitBounds } = useReactFlow();
|
|
126
126
|
const viewport = useViewport();
|
|
127
127
|
// Restored once per mount from `localStorage` (see `readViewState`). Each
|
|
128
128
|
// graph is its own tab/mount, so `persistKey` is stable for a mount.
|
|
@@ -131,6 +131,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
131
131
|
const [built, setBuilt] = useState({
|
|
132
132
|
nodes: [],
|
|
133
133
|
edges: [],
|
|
134
|
+
absoluteRects: new Map(),
|
|
134
135
|
});
|
|
135
136
|
const [layoutReady, setLayoutReady] = useState(false);
|
|
136
137
|
const [selected, setSelected] = useState(null);
|
|
@@ -262,15 +263,24 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
262
263
|
return null;
|
|
263
264
|
return walkthroughs.find((t) => t.id === drawerTarget.walkthroughId) ?? null;
|
|
264
265
|
}, [drawerTarget, walkthroughs]);
|
|
266
|
+
// Autoplay focus: a sidebar-less embed has no expanded flow to "open", so
|
|
267
|
+
// branding every step as a selection would hide all other nodes. Instead the
|
|
268
|
+
// autoplay sets this (flow id + step) to frame the hop and dim the rest —
|
|
269
|
+
// same treatment as hover — without hiding anything. Declared before the
|
|
270
|
+
// overlay memos, which read it to title the canvas chip + step bar.
|
|
271
|
+
const [autoPlayFocus, setAutoPlayFocus] = useState(null);
|
|
265
272
|
// Ref mirror of the drawer's walkthrough id so the symbol resolver stays
|
|
266
273
|
// stable across graph re-renders (the drawer is memoized on callback identity).
|
|
267
274
|
const drawerWalkthroughIdRef = useRef(null);
|
|
268
275
|
drawerWalkthroughIdRef.current = focusedWalkthrough?.id ?? null;
|
|
269
|
-
// Walkthrough shown on the canvas title chip (focus
|
|
276
|
+
// Walkthrough shown on the canvas title chip (focus, hover highlight, or
|
|
277
|
+
// autoplay focus).
|
|
270
278
|
const overlayWalkthroughTitle = useMemo(() => {
|
|
271
279
|
if (!showWalkthroughTitle || !walkthroughs?.length)
|
|
272
280
|
return null;
|
|
273
|
-
const id = focusedWalkthroughId ??
|
|
281
|
+
const id = focusedWalkthroughId ??
|
|
282
|
+
autoPlayFocus?.walkthroughId ??
|
|
283
|
+
hoveredWalkthroughStep?.walkthroughId;
|
|
274
284
|
if (!id)
|
|
275
285
|
return null;
|
|
276
286
|
return walkthroughs.find((t) => t.id === id)?.title ?? null;
|
|
@@ -278,17 +288,24 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
278
288
|
showWalkthroughTitle,
|
|
279
289
|
walkthroughs,
|
|
280
290
|
focusedWalkthroughId,
|
|
291
|
+
autoPlayFocus,
|
|
281
292
|
hoveredWalkthroughStep,
|
|
282
293
|
]);
|
|
283
294
|
// Active step for the bottom-of-title progress + annotation chip.
|
|
284
295
|
const overlayWalkthroughStep = useMemo(() => {
|
|
285
296
|
if (!showWalkthroughTitle || !walkthroughs?.length)
|
|
286
297
|
return null;
|
|
287
|
-
const tlId = focusedWalkthroughId ??
|
|
298
|
+
const tlId = focusedWalkthroughId ??
|
|
299
|
+
autoPlayFocus?.walkthroughId ??
|
|
300
|
+
hoveredWalkthroughStep?.walkthroughId ??
|
|
301
|
+
null;
|
|
288
302
|
let stepIndex = null;
|
|
289
303
|
if (focusedWalkthroughId != null) {
|
|
290
304
|
stepIndex = focusedStepIndex;
|
|
291
305
|
}
|
|
306
|
+
else if (autoPlayFocus != null) {
|
|
307
|
+
stepIndex = autoPlayFocus.stepIndex;
|
|
308
|
+
}
|
|
292
309
|
else if (hoveredWalkthroughStep != null) {
|
|
293
310
|
stepIndex = hoveredWalkthroughStep.stepIndex;
|
|
294
311
|
}
|
|
@@ -308,6 +325,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
308
325
|
walkthroughs,
|
|
309
326
|
focusedWalkthroughId,
|
|
310
327
|
focusedStepIndex,
|
|
328
|
+
autoPlayFocus,
|
|
311
329
|
hoveredWalkthroughStep,
|
|
312
330
|
]);
|
|
313
331
|
const drawerTitle = useMemo(() => {
|
|
@@ -369,7 +387,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
369
387
|
showEdgeLabels,
|
|
370
388
|
showSingletonFrames,
|
|
371
389
|
})
|
|
372
|
-
.then(({ nodes, edges: e }) => {
|
|
390
|
+
.then(({ nodes, edges: e, absoluteRects }) => {
|
|
373
391
|
if (!alive)
|
|
374
392
|
return;
|
|
375
393
|
// Prune dims for removed leaves; keep measurements for stable ids so a
|
|
@@ -379,7 +397,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
379
397
|
if (!leafIds.has(id))
|
|
380
398
|
measuredDimsRef.current.delete(id);
|
|
381
399
|
}
|
|
382
|
-
setBuilt({ nodes, edges: e });
|
|
400
|
+
setBuilt({ nodes, edges: e, absoluteRects });
|
|
383
401
|
setLayoutReady(false);
|
|
384
402
|
})
|
|
385
403
|
.catch((err) => {
|
|
@@ -387,7 +405,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
387
405
|
if (!alive)
|
|
388
406
|
return;
|
|
389
407
|
// Reveal the cover even on failure so the UI is not stuck forever.
|
|
390
|
-
setBuilt({ nodes: [], edges: [] });
|
|
408
|
+
setBuilt({ nodes: [], edges: [], absoluteRects: new Map() });
|
|
391
409
|
setLayoutReady(true);
|
|
392
410
|
});
|
|
393
411
|
return () => { alive = false; };
|
|
@@ -419,10 +437,10 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
419
437
|
const measuredHeights = new Map(leafNodes.map((n) => [n.id, dims.get(n.id).height]));
|
|
420
438
|
const gen = ++pass2GenRef.current;
|
|
421
439
|
void buildSubsystemGraph({ components, relations, walkthroughs }, { maxNodeWidth, showEdgeLabels, measuredWidths, measuredHeights, showSingletonFrames })
|
|
422
|
-
.then(({ nodes, edges: e }) => {
|
|
440
|
+
.then(({ nodes, edges: e, absoluteRects }) => {
|
|
423
441
|
if (gen !== pass2GenRef.current)
|
|
424
442
|
return;
|
|
425
|
-
setBuilt({ nodes, edges: e });
|
|
443
|
+
setBuilt({ nodes, edges: e, absoluteRects });
|
|
426
444
|
setLayoutReady(true);
|
|
427
445
|
})
|
|
428
446
|
.catch((err) => {
|
|
@@ -519,6 +537,11 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
519
537
|
// Edge ids in walkthrough focus (an active flow's edge set, or a single
|
|
520
538
|
// step's edge). Used to frame the camera. `null` = no walkthrough focus.
|
|
521
539
|
const focusEdgeIds = useMemo(() => {
|
|
540
|
+
if (autoPlayFocus) {
|
|
541
|
+
const tl = walkthroughs?.find((t) => t.id === autoPlayFocus.walkthroughId);
|
|
542
|
+
const step = tl?.steps[autoPlayFocus.stepIndex];
|
|
543
|
+
return step ? new Set([walkthroughStepGraphEdgeId(step)]) : null;
|
|
544
|
+
}
|
|
522
545
|
if (focusedWalkthroughId == null || !walkthroughs)
|
|
523
546
|
return null;
|
|
524
547
|
const tl = walkthroughs.find((t) => t.id === focusedWalkthroughId);
|
|
@@ -529,7 +552,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
529
552
|
return step ? new Set([walkthroughStepGraphEdgeId(step)]) : null;
|
|
530
553
|
}
|
|
531
554
|
return new Set(tl.steps.map((s) => walkthroughStepGraphEdgeId(s)));
|
|
532
|
-
}, [walkthroughs, focusedWalkthroughId, focusedStepIndex]);
|
|
555
|
+
}, [walkthroughs, focusedWalkthroughId, focusedStepIndex, autoPlayFocus]);
|
|
533
556
|
// 1-based step numbers per edge of the active flow (focused or
|
|
534
557
|
// hover/autoplay-highlighted). An edge can appear in more than one step.
|
|
535
558
|
const selectedFlowStepNos = useMemo(() => {
|
|
@@ -589,15 +612,21 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
589
612
|
// selected + hovered participants. Whole-flow focus (or no focus) keeps
|
|
590
613
|
// the old hover-replace preview so a step hover still dims the rest.
|
|
591
614
|
const previewEdgeIds = useMemo(() => {
|
|
615
|
+
// Autoplay drives focus without a hover, so its hop is the preview set.
|
|
616
|
+
if (autoPlayFocus)
|
|
617
|
+
return focusEdgeIds;
|
|
592
618
|
if (!hoverEdgeIds)
|
|
593
619
|
return null;
|
|
620
|
+
// While hovering with a *step* already selected, brighten the union of
|
|
621
|
+
// selected + hovered participants; whole-flow focus keeps the old
|
|
622
|
+
// hover-replace preview so a step hover still dims the rest.
|
|
594
623
|
if (focusedStepIndex == null || !focusEdgeIds)
|
|
595
624
|
return hoverEdgeIds;
|
|
596
625
|
const ids = new Set(hoverEdgeIds);
|
|
597
626
|
for (const id of focusEdgeIds)
|
|
598
627
|
ids.add(id);
|
|
599
628
|
return ids;
|
|
600
|
-
}, [hoverEdgeIds, focusEdgeIds, focusedStepIndex]);
|
|
629
|
+
}, [hoverEdgeIds, focusEdgeIds, focusedStepIndex, autoPlayFocus]);
|
|
601
630
|
const previewNodeIds = useMemo(() => endpointsOf(previewEdgeIds),
|
|
602
631
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
603
632
|
[baseEdges, previewEdgeIds]);
|
|
@@ -633,22 +662,26 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
633
662
|
// While a step/flow is hovered, selected + hovered participants stay
|
|
634
663
|
// bright; everything else among the currently-visible (opened-walkthrough)
|
|
635
664
|
// nodes is dimmed. Nodes outside the opened-walkthrough set stay hidden.
|
|
665
|
+
// Exception: with no expanded flow at all (a sidebar-less embed), there is
|
|
666
|
+
// nothing to hide toward — everything shows, and focus/hover only dims.
|
|
667
|
+
const noOpenedFlow = openedEdgeIds == null;
|
|
636
668
|
return xyflowNodesBase.map((n) => {
|
|
637
669
|
// Boundary frames follow their members: hidden when no member is
|
|
638
670
|
// visible, dimmed when members are dimmed. Never selectable.
|
|
639
671
|
if (n.type === 'subsystem-group') {
|
|
640
672
|
const region = n.data?.region;
|
|
641
673
|
const memberAliases = region?.memberAliases ?? [];
|
|
674
|
+
// Hover/autoplay dim-only: never hide a frame (see the node branch).
|
|
642
675
|
const vis = flowElementVisibility({
|
|
643
676
|
inOpened: memberAliases.some((alias) => openedNodeIds?.has(alias) === true),
|
|
644
677
|
inSelected: memberAliases.some((alias) => brightNodeIds?.has(alias) === true),
|
|
645
678
|
anyOpened: openedNodeIds != null,
|
|
646
|
-
anySelected: brightNodeIds != null,
|
|
679
|
+
anySelected: brightNodeIds != null || previewNodeIds != null,
|
|
647
680
|
});
|
|
648
681
|
const dimmed = previewNodeIds
|
|
649
682
|
? vis.hidden || !memberAliases.some((alias) => previewNodeIds.has(alias))
|
|
650
683
|
: vis.dimmed;
|
|
651
|
-
const hidden = vis.hidden;
|
|
684
|
+
const hidden = noOpenedFlow ? false : vis.hidden;
|
|
652
685
|
// Host override wins over the library's derived frame color.
|
|
653
686
|
const color = region?.key != null ? boundaryColors?.[region.key] : undefined;
|
|
654
687
|
return {
|
|
@@ -664,15 +697,19 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
664
697
|
}
|
|
665
698
|
const comp = n.data?.component;
|
|
666
699
|
const fileMatch = fileMatchForNode(comp?.file, openFile, focusNodeIds?.has(n.id) === true);
|
|
700
|
+
// Hover/autoplay is a dim-only signal: never hide non-participants (there
|
|
701
|
+
// may be no "opened" flow to reveal them, e.g. a sidebar-less autoplay
|
|
702
|
+
// embed), only dim them. Bases selection on the focused step, not the
|
|
703
|
+
// hover preview, so hovering doesn't strip the frame's `isSelected`.
|
|
667
704
|
const isSelected = selected?.alias !== undefined && comp?.alias === selected.alias;
|
|
668
705
|
const vis = flowElementVisibility({
|
|
669
706
|
inOpened: openedNodeIds?.has(n.id) === true,
|
|
670
707
|
inSelected: brightNodeIds?.has(n.id) === true,
|
|
671
708
|
anyOpened: openedNodeIds != null,
|
|
672
|
-
anySelected: brightNodeIds != null,
|
|
709
|
+
anySelected: brightNodeIds != null || previewNodeIds != null,
|
|
673
710
|
});
|
|
674
711
|
const dimmed = previewNodeIds ? (vis.hidden || !previewNodeIds.has(n.id)) : vis.dimmed;
|
|
675
|
-
const hidden = vis.hidden;
|
|
712
|
+
const hidden = noOpenedFlow ? false : vis.hidden;
|
|
676
713
|
if (fileMatch === undefined && !isSelected && !dimmed) {
|
|
677
714
|
const { fileMatch: _f, isSelected: _s, dimmed: _d, ...rest } = n.data;
|
|
678
715
|
return { ...n, hidden, data: rest };
|
|
@@ -911,28 +948,73 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
911
948
|
window.addEventListener('keydown', onKey);
|
|
912
949
|
return () => window.removeEventListener('keydown', onKey);
|
|
913
950
|
}, [fileOverlayOpen, closeFileOverlay]);
|
|
914
|
-
// Camera helper shared by the walkthrough interactions
|
|
915
|
-
// edges' endpoint
|
|
916
|
-
//
|
|
917
|
-
//
|
|
951
|
+
// Camera helper shared by the walkthrough interactions. Fits the union of
|
|
952
|
+
// the focused edges' endpoint rects AND their routed waypoints — the edge
|
|
953
|
+
// carries its full polyline (`elkPathPoints`, absolute flow coords), so the
|
|
954
|
+
// frame is the line the hop actually traces. That keeps a hop whose route
|
|
955
|
+
// bulges out around intervening nodes from being clipped at the viewport
|
|
956
|
+
// edge, and it is the edge's own geometry doing the guiding, not fudge
|
|
957
|
+
// padding.
|
|
918
958
|
const fitFocusBounds = useCallback((ids) => {
|
|
919
959
|
if (!zoomOnWalkthroughFocus)
|
|
920
960
|
return;
|
|
921
961
|
const nodeIds = new Set();
|
|
962
|
+
const points = [];
|
|
922
963
|
for (const e of baseEdges) {
|
|
923
964
|
if (!ids.has(e.id))
|
|
924
965
|
continue;
|
|
925
966
|
nodeIds.add(e.source);
|
|
926
967
|
nodeIds.add(e.target);
|
|
968
|
+
const pts = e.data
|
|
969
|
+
?.elkPathPoints;
|
|
970
|
+
if (pts?.length)
|
|
971
|
+
points.push(...pts);
|
|
927
972
|
}
|
|
928
973
|
if (nodeIds.size === 0)
|
|
929
974
|
return;
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
975
|
+
// Box the focused edge(s): endpoint node rects UNION the routed line's
|
|
976
|
+
// waypoints. Both come from the layout in absolute flow coords, so no
|
|
977
|
+
// coordinate-space mixing (React Flow's grouped child `position`s are
|
|
978
|
+
// parent-relative and would skew the box).
|
|
979
|
+
const rects = built.absoluteRects;
|
|
980
|
+
let minX = Infinity;
|
|
981
|
+
let minY = Infinity;
|
|
982
|
+
let maxX = -Infinity;
|
|
983
|
+
let maxY = -Infinity;
|
|
984
|
+
for (const id of nodeIds) {
|
|
985
|
+
const r = rects.get(id);
|
|
986
|
+
if (!r)
|
|
987
|
+
continue;
|
|
988
|
+
minX = Math.min(minX, r.x);
|
|
989
|
+
minY = Math.min(minY, r.y);
|
|
990
|
+
maxX = Math.max(maxX, r.x + r.width);
|
|
991
|
+
maxY = Math.max(maxY, r.y + r.height);
|
|
992
|
+
}
|
|
993
|
+
for (const p of points) {
|
|
994
|
+
minX = Math.min(minX, p.x);
|
|
995
|
+
minY = Math.min(minY, p.y);
|
|
996
|
+
maxX = Math.max(maxX, p.x);
|
|
997
|
+
maxY = Math.max(maxY, p.y);
|
|
998
|
+
}
|
|
999
|
+
if (!Number.isFinite(minX) || !Number.isFinite(minY))
|
|
1000
|
+
return;
|
|
1001
|
+
const bounds = {
|
|
1002
|
+
x: minX,
|
|
1003
|
+
y: minY,
|
|
1004
|
+
width: Math.max(1, maxX - minX),
|
|
1005
|
+
height: Math.max(1, maxY - minY),
|
|
1006
|
+
};
|
|
1007
|
+
fitBounds(bounds, {
|
|
1008
|
+
padding: 0.15,
|
|
1009
|
+
duration: walkthroughFocusDurationMs,
|
|
934
1010
|
});
|
|
935
|
-
}, [
|
|
1011
|
+
}, [
|
|
1012
|
+
baseEdges,
|
|
1013
|
+
built.absoluteRects,
|
|
1014
|
+
fitBounds,
|
|
1015
|
+
zoomOnWalkthroughFocus,
|
|
1016
|
+
walkthroughFocusDurationMs,
|
|
1017
|
+
]);
|
|
936
1018
|
// Zoom back out to the full diagram after the last expanded walkthrough
|
|
937
1019
|
// closes (visibility restores non-flow nodes that were hidden).
|
|
938
1020
|
const fitOverview = useCallback(() => {
|
|
@@ -1097,9 +1179,11 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
1097
1179
|
prevPreviewEdgeIdsRef.current = previewEdgeIds;
|
|
1098
1180
|
if (!zoomOnWalkthroughFocus || walkthroughStepMode === 'dim')
|
|
1099
1181
|
return;
|
|
1100
|
-
// Camera follows hover only when a specific step is already focused
|
|
1101
|
-
|
|
1182
|
+
// Camera follows hover only when a specific step is already focused (or
|
|
1183
|
+
// autoplay is driving an auto-focus).
|
|
1184
|
+
if (!autoPlayFocus && (focusedWalkthroughId == null || focusedStepIndex == null)) {
|
|
1102
1185
|
return;
|
|
1186
|
+
}
|
|
1103
1187
|
if (previewEdgeIds) {
|
|
1104
1188
|
fitFocusBounds(previewEdgeIds);
|
|
1105
1189
|
return;
|
|
@@ -1112,46 +1196,93 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
1112
1196
|
focusEdgeIds,
|
|
1113
1197
|
focusedWalkthroughId,
|
|
1114
1198
|
focusedStepIndex,
|
|
1199
|
+
autoPlayFocus,
|
|
1115
1200
|
fitFocusBounds,
|
|
1116
1201
|
zoomOnWalkthroughFocus,
|
|
1117
1202
|
walkthroughStepMode,
|
|
1118
1203
|
]);
|
|
1119
|
-
// Graph-only embeds: cycle walkthrough steps
|
|
1204
|
+
// Graph-only embeds: cycle walkthrough steps. In `focus` mode each step is
|
|
1205
|
+
// selected (camera frames it via fitFocusBounds) and, when a walkthrough
|
|
1206
|
+
// viewer is supplied, its snippet drawer opens; in `dim` mode it only
|
|
1207
|
+
// dim-highlights the step (hover-style) with no camera move.
|
|
1120
1208
|
useEffect(() => {
|
|
1121
|
-
if (!autoPlayWalkthroughs ||
|
|
1209
|
+
if (!autoPlayWalkthroughs || walkthroughs == null || walkthroughs.length === 0)
|
|
1210
|
+
return;
|
|
1211
|
+
if (!layoutReady)
|
|
1122
1212
|
return;
|
|
1123
1213
|
const playable = walkthroughs.filter((tl) => tl.steps.length > 0);
|
|
1124
1214
|
if (playable.length === 0)
|
|
1125
1215
|
return;
|
|
1216
|
+
// Only run the cycles that can actually be shown in the current edge view.
|
|
1217
|
+
const inView = playable.filter((tl) => tl.steps.some((s) => resolvedEdgeView === 'relations'
|
|
1218
|
+
? isRelationMechanism(s.mechanism)
|
|
1219
|
+
: isWalkthroughMechanism(s.mechanism)));
|
|
1220
|
+
if (inView.length === 0)
|
|
1221
|
+
return;
|
|
1222
|
+
const cyc = inView;
|
|
1126
1223
|
let cancelled = false;
|
|
1127
1224
|
let tlIdx = 0;
|
|
1128
1225
|
let stepIdx = 0;
|
|
1129
1226
|
let timer = null;
|
|
1130
1227
|
const interval = Math.max(400, walkthroughAutoPlayIntervalMs);
|
|
1228
|
+
const focusMode = walkthroughStepMode !== 'dim';
|
|
1229
|
+
let cleanup = () => { };
|
|
1131
1230
|
const tick = () => {
|
|
1132
1231
|
if (cancelled)
|
|
1133
1232
|
return;
|
|
1134
|
-
const tl =
|
|
1233
|
+
const tl = cyc[tlIdx];
|
|
1135
1234
|
setSelected(null);
|
|
1136
1235
|
setSelectedEdgeId(null);
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1236
|
+
if (focusMode) {
|
|
1237
|
+
setHoveredWalkthroughStep(null);
|
|
1238
|
+
setFocusedWalkthroughId(null);
|
|
1239
|
+
setFocusedStepIndex(null);
|
|
1240
|
+
setAutoPlayFocus({ walkthroughId: tl.id, stepIndex: stepIdx });
|
|
1241
|
+
if (!hideDrawer) {
|
|
1242
|
+
const step = tl.steps[stepIdx];
|
|
1243
|
+
if (step) {
|
|
1244
|
+
if (renderWalkthroughViewer) {
|
|
1245
|
+
setDrawerTarget({ kind: 'walkthrough', walkthroughId: tl.id, stepIndex: stepIdx });
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
setDrawerTarget({ kind: 'file', file: step.file, startLine: step.line });
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
else {
|
|
1254
|
+
setAutoPlayFocus(null);
|
|
1255
|
+
setFocusedWalkthroughId(null);
|
|
1256
|
+
setFocusedStepIndex(null);
|
|
1257
|
+
setHoveredWalkthroughStep({ walkthroughId: tl.id, stepIndex: stepIdx });
|
|
1258
|
+
}
|
|
1140
1259
|
stepIdx += 1;
|
|
1141
1260
|
if (stepIdx >= tl.steps.length) {
|
|
1142
1261
|
stepIdx = 0;
|
|
1143
|
-
tlIdx = (tlIdx + 1) %
|
|
1262
|
+
tlIdx = (tlIdx + 1) % cyc.length;
|
|
1144
1263
|
}
|
|
1145
1264
|
timer = window.setTimeout(tick, interval);
|
|
1146
1265
|
};
|
|
1147
1266
|
tick();
|
|
1148
|
-
|
|
1267
|
+
cleanup = () => {
|
|
1149
1268
|
cancelled = true;
|
|
1150
1269
|
if (timer != null)
|
|
1151
1270
|
window.clearTimeout(timer);
|
|
1152
1271
|
setHoveredWalkthroughStep(null);
|
|
1272
|
+
setFocusedWalkthroughId(null);
|
|
1273
|
+
setFocusedStepIndex(null);
|
|
1274
|
+
setAutoPlayFocus(null);
|
|
1153
1275
|
};
|
|
1154
|
-
|
|
1276
|
+
return cleanup;
|
|
1277
|
+
}, [
|
|
1278
|
+
autoPlayWalkthroughs,
|
|
1279
|
+
walkthroughs,
|
|
1280
|
+
walkthroughAutoPlayIntervalMs,
|
|
1281
|
+
layoutReady,
|
|
1282
|
+
walkthroughStepMode,
|
|
1283
|
+
renderWalkthroughViewer,
|
|
1284
|
+
hideDrawer,
|
|
1285
|
+
]);
|
|
1155
1286
|
// Arrow keys step through the focused walkthrough once a step is active
|
|
1156
1287
|
// (sidebar click or drawer open). Ignores typing targets and chords.
|
|
1157
1288
|
useEffect(() => {
|
|
@@ -1606,7 +1737,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
1606
1737
|
drawerTarget.startLine != null &&
|
|
1607
1738
|
!!selected.file &&
|
|
1608
1739
|
selected.file === drawerTarget.file &&
|
|
1609
|
-
selected.declarationRef?.startLine === drawerTarget.startLine }) }))] }), _jsx(FileDrawer, { title: drawerTitle, onClose: closeDrawer, fillHeight: drawerFillHeight, suppressEscape: fileOverlayOpen, children: drawerTarget?.kind === 'walkthrough' &&
|
|
1740
|
+
selected.declarationRef?.startLine === drawerTarget.startLine }) }))] }), _jsx(FileDrawer, { title: drawerTitle, onClose: closeDrawer, fillHeight: drawerFillHeight, suppressEscape: fileOverlayOpen, hidden: hideDrawer, children: drawerTarget?.kind === 'walkthrough' &&
|
|
1610
1741
|
focusedWalkthrough &&
|
|
1611
1742
|
renderWalkthroughViewer ? (_jsx(WalkthroughDrawerContent, { render: renderWalkthroughDrawerContent, walkthrough: focusedWalkthrough, stepIndex: drawerTarget.stepIndex, onOpenFile: onOpenFileFromWalkthrough, proposedAliases: proposedAliases, resolveSymbol: resolveWalkthroughSymbol, onSymbolClick: openConstructDeclaration })) : drawerTarget?.kind === 'file' ? (_jsx(FileDrawerContent, { render: renderDrawerContent, file: drawerTarget.file, startLine: drawerTarget.startLine })) : null }), fileOverlay && (_jsxs("div", { style: {
|
|
1612
1743
|
position: 'absolute',
|