@principal-ai/subsystems-react 0.23.4 → 0.24.1
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 +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/subsystem/ComponentDeclaration.d.ts +3 -1
- package/dist/subsystem/ComponentDeclaration.d.ts.map +1 -1
- package/dist/subsystem/ComponentDeclaration.js +2 -2
- package/dist/subsystem/ComponentDeclaration.js.map +1 -1
- package/dist/subsystem/ConstructsCatalog.d.ts +30 -0
- package/dist/subsystem/ConstructsCatalog.d.ts.map +1 -0
- package/dist/subsystem/ConstructsCatalog.js +349 -0
- package/dist/subsystem/ConstructsCatalog.js.map +1 -0
- package/dist/subsystem/DiagnosticToggle.d.ts +46 -0
- package/dist/subsystem/DiagnosticToggle.d.ts.map +1 -0
- package/dist/subsystem/DiagnosticToggle.js +95 -0
- package/dist/subsystem/DiagnosticToggle.js.map +1 -0
- package/dist/subsystem/IssueList.d.ts +102 -0
- package/dist/subsystem/IssueList.d.ts.map +1 -0
- package/dist/subsystem/IssueList.js +282 -0
- package/dist/subsystem/IssueList.js.map +1 -0
- package/dist/subsystem/SubsystemComponentGraph.d.ts +40 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +103 -65
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/model.d.ts +32 -2
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +47 -0
- package/dist/subsystem/model.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +42 -0
- package/src/stories/Subsystem/ComponentGraph/Constructs.stories.tsx +287 -0
- package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +138 -0
- package/src/stories/Subsystem/ComponentGraph/EdgeViews.stories.tsx +159 -0
- package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +130 -0
- package/src/subsystem/ComponentDeclaration.tsx +4 -1
- package/src/subsystem/ConstructsCatalog.tsx +644 -0
- package/src/subsystem/DiagnosticToggle.tsx +160 -0
- package/src/subsystem/IssueList.tsx +488 -0
- package/src/subsystem/SubsystemComponentGraph.tsx +156 -42
- package/src/subsystem/model.test.ts +34 -0
- package/src/subsystem/model.ts +72 -2
|
@@ -7,13 +7,18 @@
|
|
|
7
7
|
* inside one labeled boundary frame; nodes without one sit outside every
|
|
8
8
|
* boundary. Clicking a component invokes `onSelect`.
|
|
9
9
|
*
|
|
10
|
+
* When the model has components but no topology or walkthrough edges, the
|
|
11
|
+
* canvas is a constructs catalog (list + signature) instead of a graph.
|
|
12
|
+
*
|
|
10
13
|
* This is a focused fork of the package's `GraphRenderer` pipeline (same ELK
|
|
11
14
|
* edge routing, delayed fitView, Background/Controls/MiniMap, node/edge type
|
|
12
15
|
* injection, onNodeClick) adapted to the subsystem model — read-only.
|
|
13
16
|
*/
|
|
14
17
|
import type { ReactNode } from 'react';
|
|
15
|
-
import { type SubsystemComponentEdge, type SubsystemComponent, type SubsystemRelation, type SubsystemWalkthrough } from './model';
|
|
18
|
+
import { type SubsystemComponentEdge, type SubsystemComponent, type SubsystemEdgeView, type SubsystemRelation, type SubsystemWalkthrough } from './model';
|
|
16
19
|
import type { SubsystemOpenFileOptions } from './declarationRef';
|
|
20
|
+
import { type SubsystemDiagnostic } from './DiagnosticToggle';
|
|
21
|
+
import { type SubsystemIssue } from './IssueList';
|
|
17
22
|
import type { ComponentVerificationState } from './ComponentDeclaration';
|
|
18
23
|
/** Context passed to `renderWalkthroughViewer` when a flow/step is focused. */
|
|
19
24
|
export interface WalkthroughViewerContext {
|
|
@@ -45,6 +50,17 @@ export interface SubsystemComponentGraphProps {
|
|
|
45
50
|
maxNodeWidth?: number;
|
|
46
51
|
/** Show edge labels (mechanism names) on the graph. @default true */
|
|
47
52
|
showEdgeLabels?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Which edge vocabulary the canvas draws. The relation and walkthrough
|
|
55
|
+
* vocabularies are disjoint, so a graph carrying both shows one or the
|
|
56
|
+
* other — never both. Edges outside the view are hidden (labels go too).
|
|
57
|
+
* - `relations`: topology relation edges (`imports`, `extends`, …)
|
|
58
|
+
* - `walkthroughs`: walkthrough hop edges (`calls`, `feeds`, …), including
|
|
59
|
+
* step numbers when a flow is focused/hovered
|
|
60
|
+
* Defaults to `walkthroughs` when the model has walkthroughs but no
|
|
61
|
+
* relations (e.g. flow-only models), otherwise `relations`.
|
|
62
|
+
*/
|
|
63
|
+
edgeView?: SubsystemEdgeView;
|
|
48
64
|
/** Subsystem title displayed in the sidebar. */
|
|
49
65
|
title?: string;
|
|
50
66
|
/**
|
|
@@ -92,6 +108,29 @@ export interface SubsystemComponentGraphProps {
|
|
|
92
108
|
sidebarExtra?: ReactNode;
|
|
93
109
|
/** Rendered in the sidebar under the description (e.g. selection inspector). */
|
|
94
110
|
sidebarAfterDescription?: ReactNode;
|
|
111
|
+
/**
|
|
112
|
+
* Diagnostics status chip in the sidebar title row (beside the description
|
|
113
|
+
* toggle). Shows the last verification pass's state as an icon color + count;
|
|
114
|
+
* `onOpen` opens the full report. Omit to hide the chip.
|
|
115
|
+
*/
|
|
116
|
+
diagnostic?: SubsystemDiagnostic;
|
|
117
|
+
/**
|
|
118
|
+
* Verification issues for this graph (audit findings). When diagnostics are
|
|
119
|
+
* active (see `showIssues`) the sidebar's bottom panel becomes the issue
|
|
120
|
+
* list instead of the file tree / walkthroughs.
|
|
121
|
+
*/
|
|
122
|
+
issues?: SubsystemIssue[];
|
|
123
|
+
/**
|
|
124
|
+
* Force the sidebar into diagnostics mode. Defaults to `true` whenever
|
|
125
|
+
* `issues` is non-empty (and nothing else has been forced).
|
|
126
|
+
*/
|
|
127
|
+
showIssues?: boolean;
|
|
128
|
+
/** Click an issue — focus its target on the graph / open detail. */
|
|
129
|
+
onSelectIssue?: (issue: SubsystemIssue) => void;
|
|
130
|
+
/** Apply an issue's deterministic fix. */
|
|
131
|
+
onApplyIssueFix?: (issue: SubsystemIssue) => void;
|
|
132
|
+
/** Hover an issue — transiently highlight its target (null on leave). */
|
|
133
|
+
onHoverIssue?: (issue: SubsystemIssue | null) => void;
|
|
95
134
|
/**
|
|
96
135
|
* Host-injected reader/renderer for the bottom file drawer, keyed by
|
|
97
136
|
* repo-root-relative path. Opening happens on declaration/file-tree clicks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,9 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
8
8
|
* inside one labeled boundary frame; nodes without one sit outside every
|
|
9
9
|
* boundary. Clicking a component invokes `onSelect`.
|
|
10
10
|
*
|
|
11
|
+
* When the model has components but no topology or walkthrough edges, the
|
|
12
|
+
* canvas is a constructs catalog (list + signature) instead of a graph.
|
|
13
|
+
*
|
|
11
14
|
* This is a focused fork of the package's `GraphRenderer` pipeline (same ELK
|
|
12
15
|
* edge routing, delayed fitView, Background/Controls/MiniMap, node/edge type
|
|
13
16
|
* injection, onNodeClick) adapted to the subsystem model — read-only.
|
|
@@ -17,8 +20,11 @@ import { ReactFlow, ReactFlowProvider, Background, BackgroundVariant, Controls,
|
|
|
17
20
|
import { useTheme } from '@principal-ade/industry-theme';
|
|
18
21
|
import { ChevronDown, ChevronUp, Pause, Play, X } from 'lucide-react';
|
|
19
22
|
import { IndustryMarkdownSlide } from 'themed-markdown';
|
|
20
|
-
import { buildSubsystemGraph, deriveGraphEdges, MECHANISM_COLOR, MECHANISM_DESCRIPTIONS, subsystemGraphLayoutKey, walkthroughStepGraphEdgeId, } from './model';
|
|
23
|
+
import { buildSubsystemGraph, deriveGraphEdges, isConstructsOnlyModel, isRelationMechanism, isWalkthroughMechanism, MECHANISM_COLOR, MECHANISM_DESCRIPTIONS, subsystemGraphLayoutKey, walkthroughStepGraphEdgeId, } from './model';
|
|
24
|
+
import { ConstructsCatalog } from './ConstructsCatalog';
|
|
21
25
|
import { SubsystemComponentNode, SubsystemGroupNode, SubsystemEdge, SUBSYSTEM_CALLBACKS, hexWithAlpha, EDGE_DIM_ALPHA, fileMatchForNode, flowElementVisibility } from './nodes';
|
|
26
|
+
import { SubsystemDiagnosticToggle } from './DiagnosticToggle';
|
|
27
|
+
import { SubsystemIssueList } from './IssueList';
|
|
22
28
|
import { SubsystemFileTree } from './SubsystemFileTree';
|
|
23
29
|
import { GraphLayoutCover } from './GraphLayoutCover';
|
|
24
30
|
import { ComponentDeclaration } from './ComponentDeclaration';
|
|
@@ -69,11 +75,17 @@ function FileOverlayCloseButton({ onClose }) {
|
|
|
69
75
|
const WalkthroughDrawerContent = memo(function WalkthroughDrawerContent({ render, walkthrough, stepIndex, onOpenFile, }) {
|
|
70
76
|
return _jsx(_Fragment, { children: render({ walkthrough, stepIndex, onOpenFile }) });
|
|
71
77
|
});
|
|
72
|
-
function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, title, hideSidebar, walkthroughStepMode = 'focus', autoPlayWalkthroughs = false, walkthroughAutoPlayIntervalMs = WALKTHROUGH_PLAY_PAUSE_MS, zoomOnWalkthroughFocus = true, graphTitle, showWalkthroughTitle = false, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, renderFileView, renderFileViewer, renderWalkthroughViewer, onFileSelect, onVerifyComponent, componentVerification }) {
|
|
78
|
+
function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, edgeView, title, hideSidebar, walkthroughStepMode = 'focus', autoPlayWalkthroughs = false, walkthroughAutoPlayIntervalMs = WALKTHROUGH_PLAY_PAUSE_MS, zoomOnWalkthroughFocus = true, graphTitle, showWalkthroughTitle = false, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, diagnostic, issues, showIssues, onSelectIssue, onApplyIssueFix, onHoverIssue, renderFileView, renderFileViewer, renderWalkthroughViewer, onFileSelect, onVerifyComponent, componentVerification }) {
|
|
73
79
|
const { theme } = useTheme();
|
|
74
80
|
const { fitView } = useReactFlow();
|
|
75
81
|
const viewport = useViewport();
|
|
76
82
|
const graphEdges = useMemo(() => deriveGraphEdges({ relations, walkthroughs }), [relations, walkthroughs]);
|
|
83
|
+
// One edge vocabulary at a time. When the caller doesn't pick, follow the
|
|
84
|
+
// model: a flow-only graph defaults to walkthrough edges rather than empty.
|
|
85
|
+
const resolvedEdgeView = edgeView ??
|
|
86
|
+
(relations.length === 0 && (walkthroughs?.length ?? 0) > 0
|
|
87
|
+
? 'walkthroughs'
|
|
88
|
+
: 'relations');
|
|
77
89
|
const [built, setBuilt] = useState({
|
|
78
90
|
nodes: [],
|
|
79
91
|
edges: [],
|
|
@@ -597,6 +609,13 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
597
609
|
markerEnd: nextMarker,
|
|
598
610
|
};
|
|
599
611
|
};
|
|
612
|
+
// Edges outside the selected view are hidden entirely (labels included).
|
|
613
|
+
const edgeInView = (e) => {
|
|
614
|
+
const mechanism = e.data?.mechanism ?? 'imports';
|
|
615
|
+
return resolvedEdgeView === 'relations'
|
|
616
|
+
? isRelationMechanism(mechanism)
|
|
617
|
+
: isWalkthroughMechanism(mechanism);
|
|
618
|
+
};
|
|
600
619
|
if (openedEdgeIds || focusEdgeIds || previewEdgeIds) {
|
|
601
620
|
return baseEdges.map((e) => {
|
|
602
621
|
const vis = flowElementVisibility({
|
|
@@ -606,14 +625,18 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
606
625
|
anySelected: focusEdgeIds != null,
|
|
607
626
|
});
|
|
608
627
|
const dimmed = previewEdgeIds ? vis.hidden || !previewEdgeIds.has(e.id) : vis.dimmed;
|
|
609
|
-
const hidden = vis.hidden;
|
|
628
|
+
const hidden = vis.hidden || !edgeInView(e);
|
|
610
629
|
return { ...paint(e, dimmed), hidden };
|
|
611
630
|
});
|
|
612
631
|
}
|
|
613
|
-
if (
|
|
614
|
-
return baseEdges
|
|
615
|
-
|
|
616
|
-
|
|
632
|
+
if (selectedEdgeId) {
|
|
633
|
+
return baseEdges.map((e) => ({
|
|
634
|
+
...paint(e, e.id !== selectedEdgeId),
|
|
635
|
+
hidden: !edgeInView(e),
|
|
636
|
+
}));
|
|
637
|
+
}
|
|
638
|
+
return baseEdges.map((e) => ({ ...e, hidden: !edgeInView(e) }));
|
|
639
|
+
}, [baseEdges, selectedEdgeId, openedEdgeIds, focusEdgeIds, previewEdgeIds, resolvedEdgeView]);
|
|
617
640
|
const onNodesChange = useCallback((changes) => {
|
|
618
641
|
// Capture dimension changes (React Flow's measurement callback).
|
|
619
642
|
// Group parents are ELK-sized — ignore their measurements.
|
|
@@ -673,6 +696,10 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
673
696
|
// own owner-avatar header. Clicking a header collapses that repo's tree.
|
|
674
697
|
const repoGroups = useMemo(() => buildRepoGroups(components), [components]);
|
|
675
698
|
const hasWalkthroughs = useMemo(() => (walkthroughs?.length ?? 0) > 0, [walkthroughs]);
|
|
699
|
+
// Diagnostics mode: the bottom panel shows the issue list instead of the
|
|
700
|
+
// file tree / walkthroughs. Explicit `showIssues` wins; otherwise any issues
|
|
701
|
+
// present turn it on.
|
|
702
|
+
const issuesActive = showIssues ?? (issues?.length ?? 0) > 0;
|
|
676
703
|
const [collapsedRepos, setCollapsedRepos] = useState(new Set());
|
|
677
704
|
const toggleRepoCollapsed = useCallback((key) => {
|
|
678
705
|
setCollapsedRepos((prev) => {
|
|
@@ -1052,9 +1079,7 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1052
1079
|
if (e.hidden)
|
|
1053
1080
|
return false;
|
|
1054
1081
|
const d = e?.data;
|
|
1055
|
-
|
|
1056
|
-
return false;
|
|
1057
|
-
return true;
|
|
1082
|
+
return !d?.dimmed;
|
|
1058
1083
|
})
|
|
1059
1084
|
.map((e) => {
|
|
1060
1085
|
const d = e.data;
|
|
@@ -1097,7 +1122,7 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1097
1122
|
const walkthroughViewerRef = useRef(renderWalkthroughViewer);
|
|
1098
1123
|
walkthroughViewerRef.current = renderWalkthroughViewer;
|
|
1099
1124
|
const renderWalkthroughDrawerContent = useCallback((ctx) => walkthroughViewerRef.current?.(ctx) ?? null, []);
|
|
1100
|
-
return (_jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'row', userSelect: sidebarDrag ? 'none' : undefined }, children: [!hideSidebar && (title || description || sidebarExtra || sidebarAfterDescription || treeFilePaths.length > 0 || hasWalkthroughs) && (_jsxs("div", { style: {
|
|
1125
|
+
return (_jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'row', userSelect: sidebarDrag ? 'none' : undefined }, children: [!hideSidebar && (title || description || diagnostic || issuesActive || sidebarExtra || sidebarAfterDescription || treeFilePaths.length > 0 || hasWalkthroughs) && (_jsxs("div", { style: {
|
|
1101
1126
|
width: sidebarWidth,
|
|
1102
1127
|
minWidth: sidebarWidth,
|
|
1103
1128
|
borderRight: `1px solid ${theme.colors.border}`,
|
|
@@ -1113,7 +1138,7 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1113
1138
|
display: 'flex',
|
|
1114
1139
|
flexDirection: 'column',
|
|
1115
1140
|
gap: 12,
|
|
1116
|
-
}, children: [sidebarExtra, (title || description) && (_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', gap: 8 }, children: [title && (_jsx("h2", { style: {
|
|
1141
|
+
}, children: [sidebarExtra, (title || description || diagnostic) && (_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', gap: 8 }, children: [title && (_jsx("h2", { style: {
|
|
1117
1142
|
margin: 0,
|
|
1118
1143
|
flex: 1,
|
|
1119
1144
|
minWidth: 0,
|
|
@@ -1121,21 +1146,29 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1121
1146
|
fontWeight: 600,
|
|
1122
1147
|
color: theme.colors.text,
|
|
1123
1148
|
fontFamily: theme.fonts.monospace,
|
|
1124
|
-
}, children: title })),
|
|
1125
|
-
display: '
|
|
1149
|
+
}, children: title })), _jsxs("div", { style: {
|
|
1150
|
+
display: 'flex',
|
|
1126
1151
|
alignItems: 'center',
|
|
1127
|
-
|
|
1152
|
+
gap: 4,
|
|
1128
1153
|
flexShrink: 0,
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1154
|
+
// Title's flex:1 already pushes this cluster right; without a
|
|
1155
|
+
// title, keep the actions flush right instead of flush-left.
|
|
1156
|
+
marginLeft: title ? undefined : 'auto',
|
|
1157
|
+
}, children: [diagnostic && _jsx(SubsystemDiagnosticToggle, { ...diagnostic }), description && (_jsx("button", { type: "button", "aria-expanded": descriptionVisible, "aria-label": descriptionVisible ? 'Hide description' : 'Show description', title: descriptionVisible ? 'Hide description' : 'Show description', onMouseEnter: () => setDescToggleHover(true), onMouseLeave: () => setDescToggleHover(false), onClick: () => setDescriptionVisible((v) => !v), style: {
|
|
1158
|
+
display: 'inline-flex',
|
|
1159
|
+
alignItems: 'center',
|
|
1160
|
+
justifyContent: 'center',
|
|
1161
|
+
flexShrink: 0,
|
|
1162
|
+
width: 22,
|
|
1163
|
+
height: 22,
|
|
1164
|
+
padding: 0,
|
|
1165
|
+
border: 'none',
|
|
1166
|
+
borderRadius: 4,
|
|
1167
|
+
background: descToggleHover ? theme.colors.border : 'transparent',
|
|
1168
|
+
color: descToggleHover ? theme.colors.text : (theme.colors.textMuted ?? theme.colors.textSecondary),
|
|
1169
|
+
cursor: 'pointer',
|
|
1170
|
+
transition: 'background 120ms ease, color 120ms ease',
|
|
1171
|
+
}, children: descriptionVisible ? _jsx(ChevronUp, { size: 14 }) : _jsx(ChevronDown, { size: 14 }) }))] })] })), description && descriptionVisible && (_jsx("div", { style: { fontSize: theme.fontSizes[0], lineHeight: 1.5 }, children: _jsx(IndustryMarkdownSlide, { content: description, slideIdPrefix: "subsystem-desc", slideIndex: 0, isVisible: true, theme: theme, disableScroll: true, disableBasePadding: true, fontSizeScale: 0.9, enableKeyboardScrolling: false, autoFocusOnVisible: false }) })), sidebarAfterDescription] }), (treeFilePaths.length > 0 || hasWalkthroughs || issuesActive) && (_jsx("div", { style: {
|
|
1139
1172
|
...(showDesc ? { height: '50%' } : { flex: 1, minHeight: 0 }),
|
|
1140
1173
|
minHeight: 160,
|
|
1141
1174
|
flexShrink: 0,
|
|
@@ -1143,46 +1176,46 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1143
1176
|
display: 'flex',
|
|
1144
1177
|
flexDirection: 'column',
|
|
1145
1178
|
overflow: 'hidden',
|
|
1146
|
-
}, children: [hasWalkthroughs && (_jsx("div", { role: "tablist", "aria-label": "Sidebar view", style: {
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1179
|
+
}, children: issuesActive ? (_jsx(SubsystemIssueList, { issues: issues ?? [], onSelectIssue: onSelectIssue, onApplyFix: onApplyIssueFix, onHoverIssue: onHoverIssue })) : (_jsxs(_Fragment, { children: [hasWalkthroughs && (_jsx("div", { role: "tablist", "aria-label": "Sidebar view", style: {
|
|
1180
|
+
display: 'flex',
|
|
1181
|
+
width: '100%',
|
|
1182
|
+
flexShrink: 0,
|
|
1183
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
1184
|
+
background: theme.colors.backgroundSecondary ?? theme.colors.background,
|
|
1185
|
+
}, children: ['walkthroughs', 'files'].map((view) => (_jsx("button", { type: "button", role: "tab", "aria-selected": sidebarView === view, onClick: () => setSidebarView(view), style: {
|
|
1186
|
+
flex: 1,
|
|
1187
|
+
minWidth: 0,
|
|
1188
|
+
padding: '8px 8px',
|
|
1189
|
+
border: 'none',
|
|
1190
|
+
borderRadius: 0,
|
|
1191
|
+
background: sidebarView === view ? theme.colors.background : 'transparent',
|
|
1192
|
+
color: sidebarView === view
|
|
1193
|
+
? theme.colors.text
|
|
1194
|
+
: theme.colors.textSecondary,
|
|
1195
|
+
fontSize: theme.fontSizes[1],
|
|
1196
|
+
fontFamily: theme.fonts.monospace,
|
|
1197
|
+
textTransform: 'capitalize',
|
|
1198
|
+
cursor: 'pointer',
|
|
1199
|
+
}, children: view === 'walkthroughs' ? 'Walkthroughs' : 'Files' }, view))) })), sidebarView === 'walkthroughs' && walkthroughs && walkthroughs.length > 0 ? (_jsx("div", { style: {
|
|
1153
1200
|
flex: 1,
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
? { stepIndex: focusedStepIndex }
|
|
1173
|
-
: hoveredWalkthroughStep?.walkthroughId === tl.id
|
|
1174
|
-
? { stepIndex: hoveredWalkthroughStep.stepIndex }
|
|
1175
|
-
: null, onToggleCollapsed: toggleWalkthroughCollapsed, onFocusFlow: focusWalkthroughEdges, onClearFocus: clearWalkthroughFocus, onFocusStep: focusWalkthroughStep, onHoverStep: (tl, i) => setHoveredWalkthroughStep({ walkthroughId: tl.id, stepIndex: i }), onHoverFlow: (tl) => setHoveredWalkthroughStep({ walkthroughId: tl.id, stepIndex: null }), onLeaveStep: () => setHoveredWalkthroughStep(null) }, tl.id))) })) : treeFilePaths.length > 0 ? (_jsx(_Fragment, { children: repoGroups.groups.map((group, i) => {
|
|
1176
|
-
const groupKey = group.repoKey ?? '__no-repo__';
|
|
1177
|
-
const collapsed = collapsedRepos.has(groupKey);
|
|
1178
|
-
return (_jsxs("div", { style: {
|
|
1179
|
-
flex: collapsed ? '0 0 auto' : 1,
|
|
1180
|
-
minHeight: collapsed ? 0 : undefined,
|
|
1181
|
-
display: 'flex',
|
|
1182
|
-
flexDirection: 'column',
|
|
1183
|
-
borderTop: i > 0 ? `1px solid ${theme.colors.border}` : undefined,
|
|
1184
|
-
}, children: [repoGroups.multiRepo && (_jsx(RepoGroupHeader, { group: group, collapsed: collapsed, onToggle: () => toggleRepoCollapsed(groupKey) })), !collapsed && (_jsx(SubsystemFileTree, { files: group.entries.map((e) => e.displayPath), selectedFile: selected?.file ?? openFile, hoveredFile: hoveredFile, onSelectFile: onTreeSelectFile, headerless: repoGroups.multiRepo }))] }, groupKey));
|
|
1185
|
-
}) })) : null] }))] })), !hideSidebar && (title || description || sidebarExtra || sidebarAfterDescription || treeFilePaths.length > 0 || hasWalkthroughs) && (_jsx("div", { onMouseDown: onSidebarResizeStart, "aria-label": "Resize sidebar", title: "Drag to resize", style: {
|
|
1201
|
+
minHeight: 0,
|
|
1202
|
+
overflowY: 'auto',
|
|
1203
|
+
padding: '0 0 12px',
|
|
1204
|
+
}, children: walkthroughs.map((tl) => (_jsx(WalkthroughFlow, { walkthrough: tl, collapsed: !expandedWalkthroughs.has(tl.id), active: focusedWalkthroughId === tl.id
|
|
1205
|
+
? { stepIndex: focusedStepIndex }
|
|
1206
|
+
: hoveredWalkthroughStep?.walkthroughId === tl.id
|
|
1207
|
+
? { stepIndex: hoveredWalkthroughStep.stepIndex }
|
|
1208
|
+
: null, onToggleCollapsed: toggleWalkthroughCollapsed, onFocusFlow: focusWalkthroughEdges, onClearFocus: clearWalkthroughFocus, onFocusStep: focusWalkthroughStep, onHoverStep: (tl, i) => setHoveredWalkthroughStep({ walkthroughId: tl.id, stepIndex: i }), onHoverFlow: (tl) => setHoveredWalkthroughStep({ walkthroughId: tl.id, stepIndex: null }), onLeaveStep: () => setHoveredWalkthroughStep(null) }, tl.id))) })) : treeFilePaths.length > 0 ? (_jsx(_Fragment, { children: repoGroups.groups.map((group, i) => {
|
|
1209
|
+
const groupKey = group.repoKey ?? '__no-repo__';
|
|
1210
|
+
const collapsed = collapsedRepos.has(groupKey);
|
|
1211
|
+
return (_jsxs("div", { style: {
|
|
1212
|
+
flex: collapsed ? '0 0 auto' : 1,
|
|
1213
|
+
minHeight: collapsed ? 0 : undefined,
|
|
1214
|
+
display: 'flex',
|
|
1215
|
+
flexDirection: 'column',
|
|
1216
|
+
borderTop: i > 0 ? `1px solid ${theme.colors.border}` : undefined,
|
|
1217
|
+
}, children: [repoGroups.multiRepo && (_jsx(RepoGroupHeader, { group: group, collapsed: collapsed, onToggle: () => toggleRepoCollapsed(groupKey) })), !collapsed && (_jsx(SubsystemFileTree, { files: group.entries.map((e) => e.displayPath), selectedFile: selected?.file ?? openFile, hoveredFile: hoveredFile, onSelectFile: onTreeSelectFile, headerless: repoGroups.multiRepo }))] }, groupKey));
|
|
1218
|
+
}) })) : null] })) }))] })), !hideSidebar && (title || description || diagnostic || issuesActive || sidebarExtra || sidebarAfterDescription || treeFilePaths.length > 0 || hasWalkthroughs) && (_jsx("div", { onMouseDown: onSidebarResizeStart, "aria-label": "Resize sidebar", title: "Drag to resize", style: {
|
|
1186
1219
|
width: 3,
|
|
1187
1220
|
flexShrink: 0,
|
|
1188
1221
|
cursor: 'col-resize',
|
|
@@ -1640,6 +1673,11 @@ export function SubsystemComponentGraph(props) {
|
|
|
1640
1673
|
ro.observe(el);
|
|
1641
1674
|
return () => ro.disconnect();
|
|
1642
1675
|
}, []);
|
|
1676
|
+
const constructsOnly = isConstructsOnlyModel({
|
|
1677
|
+
components: props.components,
|
|
1678
|
+
relations: props.relations,
|
|
1679
|
+
walkthroughs: props.walkthroughs,
|
|
1680
|
+
});
|
|
1643
1681
|
return (_jsx("div", { ref: wrapRef, style: {
|
|
1644
1682
|
position: 'relative',
|
|
1645
1683
|
width: '100%',
|
|
@@ -1647,6 +1685,6 @@ export function SubsystemComponentGraph(props) {
|
|
|
1647
1685
|
minHeight: 0,
|
|
1648
1686
|
display: 'flex',
|
|
1649
1687
|
flexDirection: 'column',
|
|
1650
|
-
}, children: _jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsx(ReactFlowProvider, { children: _jsx(Inner, { ...props, measured: size }) }) }) }));
|
|
1688
|
+
}, children: _jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: constructsOnly ? (_jsx(ConstructsCatalog, { components: props.components, onSelect: props.onSelect, title: props.title, hideSidebar: props.hideSidebar, description: props.description, diagnostic: props.diagnostic, sidebarExtra: props.sidebarExtra, sidebarAfterDescription: props.sidebarAfterDescription, renderFileViewer: props.renderFileViewer, renderFileView: props.renderFileView, onFileSelect: props.onFileSelect, onVerifyComponent: props.onVerifyComponent, componentVerification: props.componentVerification })) : (_jsx(ReactFlowProvider, { children: _jsx(Inner, { ...props, measured: size }) })) }) }));
|
|
1651
1689
|
}
|
|
1652
1690
|
//# sourceMappingURL=SubsystemComponentGraph.js.map
|