@principal-ai/subsystems-react 0.42.0 → 0.43.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 +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.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 +6 -9
- package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -1
- package/dist/stories/Subsystem/ComponentGraph/fixtures.js +15 -50
- package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -1
- package/dist/subsystem/C4Graph.d.ts +2 -3
- package/dist/subsystem/C4Graph.d.ts.map +1 -1
- package/dist/subsystem/C4Graph.js +2 -3
- package/dist/subsystem/C4Graph.js.map +1 -1
- package/dist/subsystem/IssueList.d.ts +5 -5
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +9 -18
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts +16 -12
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +99 -113
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/SubsystemFileTree.d.ts +5 -5
- package/dist/subsystem/SubsystemFileTree.d.ts.map +1 -1
- package/dist/subsystem/SubsystemFileTree.js +13 -49
- package/dist/subsystem/SubsystemFileTree.js.map +1 -1
- package/dist/subsystem/model.d.ts +67 -53
- package/dist/subsystem/model.d.ts.map +1 -1
- package/dist/subsystem/model.js +305 -55
- package/dist/subsystem/model.js.map +1 -1
- package/dist/subsystem/nodes.d.ts.map +1 -1
- package/dist/subsystem/nodes.js +11 -4
- package/dist/subsystem/nodes.js.map +1 -1
- package/dist/subsystem/toC4.d.ts +4 -4
- package/dist/subsystem/toC4.d.ts.map +1 -1
- package/dist/subsystem/toC4.js +3 -7
- package/dist/subsystem/toC4.js.map +1 -1
- package/dist/utils/elkLayout.d.ts.map +1 -1
- package/dist/utils/elkLayout.js +7 -0
- package/dist/utils/elkLayout.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +0 -4
- package/src/stories/Subsystem/AgentsPanel.stories.tsx +3 -5
- package/src/stories/Subsystem/C4Graph/C4Container.stories.tsx +1 -4
- package/src/stories/Subsystem/C4Graph/c4Fixture.ts +1 -1
- package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +2 -4
- package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +8 -8
- package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +19 -19
- package/src/stories/Subsystem/ComponentGraph/Constructs.stories.tsx +0 -1
- package/src/stories/Subsystem/ComponentGraph/CustomEntities.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +0 -2
- package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +2 -6
- package/src/stories/Subsystem/ComponentGraph/EdgeViews.stories.tsx +21 -21
- package/src/stories/Subsystem/ComponentGraph/Flows.stories.tsx +0 -3
- package/src/stories/Subsystem/ComponentGraph/FrameworkStereotype.stories.tsx +30 -32
- package/src/stories/Subsystem/ComponentGraph/GraphTitle.stories.tsx +4 -4
- package/src/stories/Subsystem/ComponentGraph/IssueOverlay.stories.tsx +1 -26
- package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +3 -25
- package/src/stories/Subsystem/ComponentGraph/ModuleBadges.stories.tsx +7 -8
- package/src/stories/Subsystem/ComponentGraph/ModulePathNesting.stories.tsx +116 -0
- package/src/stories/Subsystem/ComponentGraph/Modules.stories.tsx +9 -11
- package/src/stories/Subsystem/ComponentGraph/Packages.stories.tsx +3 -6
- package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +3 -3
- package/src/stories/Subsystem/ComponentGraph/Proposed.stories.tsx +8 -6
- package/src/stories/Subsystem/ComponentGraph/ProposedWalkthroughs.stories.tsx +0 -1
- package/src/stories/Subsystem/ComponentGraph/Reorder.stories.tsx +0 -1
- package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +26 -28
- package/src/stories/Subsystem/ComponentGraph/WalkthroughAutoplay.stories.tsx +0 -1
- package/src/stories/Subsystem/ComponentGraph/WorkspacePackageFrames.stories.tsx +2 -3
- package/src/stories/Subsystem/ComponentGraph/fixtures.ts +18 -58
- package/src/stories/Subsystem/EgoGraph/EgoGraph.stories.tsx +0 -2
- package/src/subsystem/C4Graph.tsx +2 -3
- package/src/subsystem/IssueList.tsx +12 -22
- package/src/subsystem/SubsystemComponentGraph.tsx +117 -135
- package/src/subsystem/SubsystemFileTree.tsx +17 -50
- package/src/subsystem/model.test.ts +155 -24
- package/src/subsystem/model.ts +352 -108
- package/src/subsystem/nodes.tsx +13 -3
- package/src/subsystem/toC4.test.ts +5 -12
- package/src/subsystem/toC4.ts +5 -9
- package/src/utils/elkLayout.ts +10 -0
package/src/subsystem/nodes.tsx
CHANGED
|
@@ -33,6 +33,8 @@ import {
|
|
|
33
33
|
moduleBadgeHoverLabel,
|
|
34
34
|
moduleBadgeWidth,
|
|
35
35
|
packageColor,
|
|
36
|
+
FOLDER_FRAME_COLOR,
|
|
37
|
+
isFolderFrame,
|
|
36
38
|
type SubsystemGraphNodeData,
|
|
37
39
|
type SubsystemGroupNodeData,
|
|
38
40
|
type SubsystemGraphEdge,
|
|
@@ -445,8 +447,14 @@ export function SubsystemGroupNode(props: NodeProps<Node<SubsystemGroupNodeData,
|
|
|
445
447
|
selected?: boolean;
|
|
446
448
|
};
|
|
447
449
|
const region = data.region;
|
|
448
|
-
// Explicit host override wins over the derived
|
|
449
|
-
|
|
450
|
+
// Explicit host override wins over the derived frame color. Folder frames
|
|
451
|
+
// (directory, or a module whose key names a folder) share one neutral hue;
|
|
452
|
+
// everything else hashes per key.
|
|
453
|
+
const color =
|
|
454
|
+
data.color ??
|
|
455
|
+
(isFolderFrame(region ?? undefined)
|
|
456
|
+
? FOLDER_FRAME_COLOR
|
|
457
|
+
: packageColor(region?.key ?? 'process'));
|
|
450
458
|
const dimmed = data.dimmed === true;
|
|
451
459
|
const hidden = (data as { hidden?: boolean }).hidden === true;
|
|
452
460
|
// Label is the region identity alone (path / process key / owner/name).
|
|
@@ -454,7 +462,9 @@ export function SubsystemGroupNode(props: NodeProps<Node<SubsystemGroupNodeData,
|
|
|
454
462
|
// — don't prefix `module ·` / `package ·` or the path reads twice.
|
|
455
463
|
const label = region?.label ?? '';
|
|
456
464
|
const [expandedLabel, setExpandedLabel] = useState<string | null>(null);
|
|
457
|
-
|
|
465
|
+
// Directory frames (path-derived nesting) render like modules — dashed,
|
|
466
|
+
// collapsible path badge.
|
|
467
|
+
const isModule = region?.kind === 'module' || region?.kind === 'directory';
|
|
458
468
|
const isProcess = region?.kind === 'process';
|
|
459
469
|
const expanded = isModule && expandedLabel === label;
|
|
460
470
|
const availableBadgeWidth = Math.max(0, (width ?? 400) - MODULE_BADGE_INSET * 2 - 4);
|
|
@@ -18,17 +18,12 @@ const doc: SubsystemModelDocument = {
|
|
|
18
18
|
{ alias: 'x', name: 'Gist API', construct: 'external', file: '', purl: 'external:api.github.com/gists' },
|
|
19
19
|
{ alias: 'agent', name: 'Maintenance agent', construct: 'custom_entity', file: '', purl: 'external' },
|
|
20
20
|
],
|
|
21
|
-
relations: [
|
|
22
|
-
{ id: 'r1', from: 'a', to: 'b', relationType: 'method' }, // intra p1
|
|
23
|
-
{ id: 'r2', from: 'a', to: 'c', relationType: 'method' },
|
|
24
|
-
{ id: 'r3', from: 'b', to: 'c', relationType: 'method' },
|
|
25
|
-
{ id: 'r4', from: 'a', to: 'x', relationType: 'method' },
|
|
26
|
-
],
|
|
27
21
|
walkthroughs: [
|
|
28
22
|
{
|
|
29
23
|
id: 'w1',
|
|
30
24
|
title: 'flow',
|
|
31
25
|
steps: [
|
|
26
|
+
{ from: 'a', to: 'b', mechanism: 'calls', file: 'src/a.ts', line: 1, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
|
|
32
27
|
{ from: 'b', to: 'c', mechanism: 'calls', file: 'src/b.ts', line: 1, purl: `${REPO}#src/b.ts`, symbol: 'Beta' },
|
|
33
28
|
{ from: 'a', to: 'c', mechanism: 'calls', file: 'src/a.ts', line: 2, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
|
|
34
29
|
{ from: 'a', to: 'agent', mechanism: 'calls', file: 'src/a.ts', line: 3, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
|
|
@@ -77,18 +72,16 @@ describe('container view', () => {
|
|
|
77
72
|
expect(model.groups[0]!.memberIds.sort()).toEqual(['container:p1', 'container:p2']);
|
|
78
73
|
});
|
|
79
74
|
|
|
80
|
-
test('edges roll up
|
|
75
|
+
test('flow edges roll up to containers; only flow edges exist', () => {
|
|
81
76
|
const byId = Object.fromEntries(model.edges.map((e) => [e.id, e]));
|
|
82
77
|
// a->b is intra-p1 — dropped.
|
|
83
78
|
expect(model.edges.some((e) => e.source === e.target)).toBe(false);
|
|
84
|
-
const rel = byId['relationship:container:p1\u0000container:p2']!;
|
|
85
|
-
expect(rel.kind).toBe('relationship');
|
|
86
|
-
expect(rel.count).toBe(2); // r2 + r3
|
|
87
79
|
const flow = byId['flow:container:p1\u0000container:p2']!;
|
|
80
|
+
expect(flow.kind).toBe('flow');
|
|
88
81
|
expect(flow.count).toBe(2); // a->c + b->c
|
|
89
|
-
expect(byId['relationship:container:p1\u0000external:external:api.github.com/gists']).toBeDefined();
|
|
90
82
|
expect(byId['flow:container:p1\u0000actor:agent']).toBeDefined();
|
|
91
|
-
expect(model.edges).
|
|
83
|
+
expect(model.edges.every((e) => e.kind === 'flow')).toBe(true);
|
|
84
|
+
expect(model.edges).toHaveLength(2);
|
|
92
85
|
});
|
|
93
86
|
});
|
|
94
87
|
|
package/src/subsystem/toC4.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* toC4 — project a subsystem-model (or a composition of them) onto C4 levels.
|
|
3
3
|
*
|
|
4
4
|
* The stored document is flat: `components[]` carry `process` (runtime unit),
|
|
5
|
-
* `purl` (repo/package), `construct`, `role`, `module`, plus `
|
|
6
|
-
* (
|
|
5
|
+
* `purl` (repo/package), `construct`, `role`, `module`, plus `walkthroughs[]`
|
|
6
|
+
* (dynamic). C4 wants a hierarchy above the
|
|
7
7
|
* component — system → container → component — with externals and actors
|
|
8
8
|
* outside it. This module derives that hierarchy without inventing data:
|
|
9
9
|
*
|
|
@@ -59,12 +59,12 @@ export interface C4Group {
|
|
|
59
59
|
memberIds: string[];
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** A rolled-up collaboration
|
|
62
|
+
/** A rolled-up collaboration — a walkthrough flow between owners. */
|
|
63
63
|
export interface C4Edge {
|
|
64
64
|
id: string;
|
|
65
65
|
source: string;
|
|
66
66
|
target: string;
|
|
67
|
-
kind: '
|
|
67
|
+
kind: 'flow';
|
|
68
68
|
label: string;
|
|
69
69
|
mechanisms: string[];
|
|
70
70
|
count: number;
|
|
@@ -234,7 +234,6 @@ export function toC4(doc: SubsystemModelDocument, options: ToC4Options = {}): C4
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
// --- Edges: roll each endpoint up to its owner at this view -------------
|
|
237
|
-
const relEdges = new Map<string, C4Edge>();
|
|
238
237
|
const flowEdges = new Map<string, C4Edge>();
|
|
239
238
|
|
|
240
239
|
const addEdge = (
|
|
@@ -255,16 +254,13 @@ export function toC4(doc: SubsystemModelDocument, options: ToC4Options = {}): C4
|
|
|
255
254
|
if (!edge.mechanisms.includes(mechanism)) edge.mechanisms.push(mechanism);
|
|
256
255
|
};
|
|
257
256
|
|
|
258
|
-
for (const r of doc.relations ?? []) {
|
|
259
|
-
addEdge(relEdges, ownerOf.get(r.from), ownerOf.get(r.to), 'relationship', r.relationType);
|
|
260
|
-
}
|
|
261
257
|
for (const w of doc.walkthroughs ?? []) {
|
|
262
258
|
for (const s of w.steps ?? []) {
|
|
263
259
|
addEdge(flowEdges, ownerOf.get(s.from), ownerOf.get(s.to), 'flow', s.mechanism);
|
|
264
260
|
}
|
|
265
261
|
}
|
|
266
262
|
|
|
267
|
-
const edges = [...
|
|
263
|
+
const edges = [...flowEdges.values()];
|
|
268
264
|
for (const e of edges) e.label = [...e.mechanisms].sort().join(' + ');
|
|
269
265
|
|
|
270
266
|
return {
|
package/src/utils/elkLayout.ts
CHANGED
|
@@ -759,6 +759,16 @@ export async function computeElkLayout(
|
|
|
759
759
|
if (parentId && builtGroups.has(parentId)) continue; // nested inside parent
|
|
760
760
|
elkParents.push(node);
|
|
761
761
|
}
|
|
762
|
+
// Order root-level compounds by model order (the caller's `groups` array), so
|
|
763
|
+
// disconnected sibling frames lay out deterministically — e.g. `app/book`
|
|
764
|
+
// before `lib`. Without this, planCompoundGroups' bottom-up build order
|
|
765
|
+
// decides placement.
|
|
766
|
+
const groupOrder = new Map(groupDefs.map((g, i) => [g.id, i]));
|
|
767
|
+
elkParents.sort(
|
|
768
|
+
(a, b) =>
|
|
769
|
+
(groupOrder.get(a.id) ?? Number.MAX_SAFE_INTEGER) -
|
|
770
|
+
(groupOrder.get(b.id) ?? Number.MAX_SAFE_INTEGER),
|
|
771
|
+
);
|
|
762
772
|
|
|
763
773
|
// Create ELK graph
|
|
764
774
|
const rootOptions = getElkOptions(options);
|