@principal-ai/subsystems-react 0.28.5 → 0.28.7
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/ConstructsCatalog.d.ts.map +1 -1
- package/dist/subsystem/ConstructsCatalog.js +1 -0
- package/dist/subsystem/ConstructsCatalog.js.map +1 -1
- package/dist/subsystem/FileDrawer.d.ts +5 -4
- package/dist/subsystem/FileDrawer.d.ts.map +1 -1
- package/dist/subsystem/FileDrawer.js +89 -54
- package/dist/subsystem/FileDrawer.js.map +1 -1
- package/dist/subsystem/IssueList.d.ts +12 -1
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +37 -11
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts +7 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +3 -3
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/package.json +1 -1
- package/src/subsystem/ConstructsCatalog.tsx +1 -0
- package/src/subsystem/FileDrawer.tsx +130 -70
- package/src/subsystem/IssueList.tsx +66 -9
- package/src/subsystem/SubsystemComponentGraph.tsx +13 -2
|
@@ -11,11 +11,17 @@
|
|
|
11
11
|
* (e.g. focus the node on the graph, or apply the fix in the report).
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { useState } from 'react';
|
|
14
|
+
import { useEffect, useState } from 'react';
|
|
15
|
+
import type { LucideIcon } from 'lucide-react';
|
|
15
16
|
import {
|
|
16
17
|
ChevronDown,
|
|
17
18
|
ChevronRight,
|
|
18
19
|
CircleCheck,
|
|
20
|
+
Component,
|
|
21
|
+
FolderGit2,
|
|
22
|
+
Network,
|
|
23
|
+
Route,
|
|
24
|
+
Server,
|
|
19
25
|
Wrench,
|
|
20
26
|
} from 'lucide-react';
|
|
21
27
|
import { useTheme } from '@principal-ade/industry-theme';
|
|
@@ -50,6 +56,18 @@ export const SUBSYSTEM_ISSUE_CATEGORIES: SubsystemIssueCategory[] = [
|
|
|
50
56
|
'walkthrough',
|
|
51
57
|
];
|
|
52
58
|
|
|
59
|
+
/** Per-category header icon — mirrors the Maintainer tab's lane icons. */
|
|
60
|
+
export const SUBSYSTEM_ISSUE_CATEGORY_ICON: Record<
|
|
61
|
+
SubsystemIssueCategory,
|
|
62
|
+
LucideIcon
|
|
63
|
+
> = {
|
|
64
|
+
repo: FolderGit2,
|
|
65
|
+
construct: Component,
|
|
66
|
+
'static-topology': Network,
|
|
67
|
+
'runtime-topology': Server,
|
|
68
|
+
walkthrough: Route,
|
|
69
|
+
};
|
|
70
|
+
|
|
53
71
|
export const SUBSYSTEM_ISSUE_CATEGORY_LABEL: Record<
|
|
54
72
|
SubsystemIssueCategory,
|
|
55
73
|
string
|
|
@@ -306,11 +324,11 @@ export function groupIssuesByCategory(
|
|
|
306
324
|
|
|
307
325
|
function severityColor(
|
|
308
326
|
severity: SubsystemIssueSeverity,
|
|
309
|
-
colors: { error: string; info: string },
|
|
310
|
-
muted: string,
|
|
327
|
+
colors: { error: string; info: string; warning: string },
|
|
311
328
|
): string {
|
|
312
329
|
if (severity === 'error') return colors.error ?? '#e5534b';
|
|
313
|
-
|
|
330
|
+
// `info` severity = unconfirmed findings; amber, matching the lane icons.
|
|
331
|
+
return colors.warning ?? '#d4a017';
|
|
314
332
|
}
|
|
315
333
|
|
|
316
334
|
const TARGET_KIND_LABEL: Record<SubsystemIssueTargetKind, string> = {
|
|
@@ -342,7 +360,7 @@ export function SubsystemIssueCard({
|
|
|
342
360
|
const [expanded, setExpanded] = useState(false);
|
|
343
361
|
const showDetail = expanded;
|
|
344
362
|
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
345
|
-
const color = severityColor(issue.severity, theme.colors
|
|
363
|
+
const color = severityColor(issue.severity, theme.colors);
|
|
346
364
|
const activate = () => {
|
|
347
365
|
setExpanded((v) => !v);
|
|
348
366
|
onSelect?.(issue);
|
|
@@ -481,6 +499,14 @@ export interface SubsystemIssueListProps {
|
|
|
481
499
|
onSelectIssue?: (issue: SubsystemIssue) => void;
|
|
482
500
|
onApplyFix?: (issue: SubsystemIssue) => void;
|
|
483
501
|
onHoverIssue?: (issue: SubsystemIssue | null) => void;
|
|
502
|
+
/**
|
|
503
|
+
* Land the list focused on one verification layer: that category starts
|
|
504
|
+
* expanded and every other category starts collapsed. Used when the list is
|
|
505
|
+
* opened from a lane-specific entry point (e.g. the Maintainer tab's lane
|
|
506
|
+
* badges) so the caller's intent — "show me this layer's findings" — is
|
|
507
|
+
* honoured without an extra click.
|
|
508
|
+
*/
|
|
509
|
+
focusCategory?: SubsystemIssueCategory;
|
|
484
510
|
}
|
|
485
511
|
|
|
486
512
|
export function SubsystemIssueList({
|
|
@@ -488,15 +514,32 @@ export function SubsystemIssueList({
|
|
|
488
514
|
onSelectIssue,
|
|
489
515
|
onApplyFix,
|
|
490
516
|
onHoverIssue,
|
|
517
|
+
focusCategory,
|
|
491
518
|
}: SubsystemIssueListProps) {
|
|
492
519
|
const { theme } = useTheme();
|
|
493
520
|
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
494
521
|
const categories = groupIssuesByCategory(issues);
|
|
495
|
-
// Collapsed categories (by id). Everything starts expanded
|
|
522
|
+
// Collapsed categories (by id). Everything starts expanded, unless the list
|
|
523
|
+
// was opened focused on a single layer — then every other layer starts
|
|
524
|
+
// collapsed so the focused category's findings are what you land on.
|
|
496
525
|
const [collapsed, setCollapsed] = useState<Set<SubsystemIssueCategory>>(
|
|
497
|
-
() =>
|
|
526
|
+
() =>
|
|
527
|
+
focusCategory
|
|
528
|
+
? new Set(
|
|
529
|
+
SUBSYSTEM_ISSUE_CATEGORIES.filter((c) => c !== focusCategory),
|
|
530
|
+
)
|
|
531
|
+
: new Set(),
|
|
498
532
|
);
|
|
499
533
|
const [hovered, setHovered] = useState<SubsystemIssueCategory | null>(null);
|
|
534
|
+
// Re-apply the focus when it changes on an already-mounted list (e.g. the
|
|
535
|
+
// host switches which lane the open model is focused on).
|
|
536
|
+
useEffect(() => {
|
|
537
|
+
setCollapsed(
|
|
538
|
+
focusCategory
|
|
539
|
+
? new Set(SUBSYSTEM_ISSUE_CATEGORIES.filter((c) => c !== focusCategory))
|
|
540
|
+
: new Set(),
|
|
541
|
+
);
|
|
542
|
+
}, [focusCategory]);
|
|
500
543
|
const toggleCollapsed = (category: SubsystemIssueCategory) => {
|
|
501
544
|
setCollapsed((prev) => {
|
|
502
545
|
const next = new Set(prev);
|
|
@@ -513,7 +556,7 @@ export function SubsystemIssueList({
|
|
|
513
556
|
// the header, no count, no cards.
|
|
514
557
|
const clean = category.count === 0;
|
|
515
558
|
const accent = category.severity
|
|
516
|
-
? severityColor(category.severity, theme.colors
|
|
559
|
+
? severityColor(category.severity, theme.colors)
|
|
517
560
|
: theme.colors.success;
|
|
518
561
|
const isCollapsed = collapsed.has(category.category);
|
|
519
562
|
const isHovered = hovered === category.category;
|
|
@@ -550,6 +593,20 @@ export function SubsystemIssueList({
|
|
|
550
593
|
fontFamily: theme.fonts.body,
|
|
551
594
|
}}
|
|
552
595
|
>
|
|
596
|
+
{(() => {
|
|
597
|
+
const Icon = SUBSYSTEM_ISSUE_CATEGORY_ICON[category.category];
|
|
598
|
+
if (Icon) {
|
|
599
|
+
return (
|
|
600
|
+
<Icon
|
|
601
|
+
size={13}
|
|
602
|
+
color={accent}
|
|
603
|
+
style={{ flexShrink: 0 }}
|
|
604
|
+
aria-hidden="true"
|
|
605
|
+
/>
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
return null;
|
|
609
|
+
})()}
|
|
553
610
|
<span
|
|
554
611
|
style={{
|
|
555
612
|
flex: 1,
|
|
@@ -573,7 +630,7 @@ export function SubsystemIssueList({
|
|
|
573
630
|
fontFamily: theme.fonts.monospace,
|
|
574
631
|
fontSize: theme.fontSizes[0],
|
|
575
632
|
fontWeight: 600,
|
|
576
|
-
color:
|
|
633
|
+
color: muted,
|
|
577
634
|
flexShrink: 0,
|
|
578
635
|
}}
|
|
579
636
|
>
|
|
@@ -55,7 +55,11 @@ import { ConstructsCatalog } from './ConstructsCatalog';
|
|
|
55
55
|
import type { SubsystemOpenFileOptions } from './declarationRef';
|
|
56
56
|
import { SubsystemComponentNode, SubsystemGroupNode, SubsystemEdge, SUBSYSTEM_CALLBACKS, hexWithAlpha, EDGE_DIM_ALPHA, fileMatchForNode, flowElementVisibility } from './nodes';
|
|
57
57
|
import { SubsystemDiagnosticToggle, type SubsystemDiagnostic } from './DiagnosticToggle';
|
|
58
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
SubsystemIssueList,
|
|
60
|
+
type SubsystemIssue,
|
|
61
|
+
type SubsystemIssueCategory,
|
|
62
|
+
} from './IssueList';
|
|
59
63
|
import { SubsystemFileTree } from './SubsystemFileTree';
|
|
60
64
|
import { GraphLayoutCover } from './GraphLayoutCover';
|
|
61
65
|
import { GRAPH_NAV_PROPS, GraphChrome } from './graphChrome';
|
|
@@ -246,6 +250,12 @@ export interface SubsystemComponentGraphProps {
|
|
|
246
250
|
* diagnostics on iff `issues` is non-empty, and the title-row chip toggles it.
|
|
247
251
|
*/
|
|
248
252
|
showIssues?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* When the issues list is active, land it focused on this verification
|
|
255
|
+
* layer: that category expands, the rest start collapsed. Optional — the
|
|
256
|
+
* plain issues view expands everything.
|
|
257
|
+
*/
|
|
258
|
+
focusIssueCategory?: SubsystemIssueCategory;
|
|
249
259
|
/** Click an issue — focus its target on the graph / open detail. */
|
|
250
260
|
onSelectIssue?: (issue: SubsystemIssue) => void;
|
|
251
261
|
/** Apply an issue's deterministic fix. */
|
|
@@ -375,7 +385,7 @@ interface InnerProps extends SubsystemComponentGraphProps {
|
|
|
375
385
|
measured: { w: number; h: number } | null;
|
|
376
386
|
}
|
|
377
387
|
|
|
378
|
-
function Inner({ components, relations, walkthroughs, initialWalkthroughId, onReorderWalkthroughs, 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, persistKey }: InnerProps) {
|
|
388
|
+
function Inner({ components, relations, walkthroughs, initialWalkthroughId, onReorderWalkthroughs, 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, focusIssueCategory, onSelectIssue, onApplyIssueFix, onHoverIssue, renderFileView, renderFileViewer, renderWalkthroughViewer, onFileSelect, onVerifyComponent, componentVerification, persistKey }: InnerProps) {
|
|
379
389
|
const { theme } = useTheme();
|
|
380
390
|
const { fitView } = useReactFlow();
|
|
381
391
|
const viewport = useViewport();
|
|
@@ -1738,6 +1748,7 @@ function Inner({ components, relations, walkthroughs, initialWalkthroughId, onRe
|
|
|
1738
1748
|
{issuesActive ? (
|
|
1739
1749
|
<SubsystemIssueList
|
|
1740
1750
|
issues={issues ?? []}
|
|
1751
|
+
focusCategory={focusIssueCategory}
|
|
1741
1752
|
onSelectIssue={onSelectIssue}
|
|
1742
1753
|
onApplyFix={onApplyIssueFix}
|
|
1743
1754
|
onHoverIssue={onHoverIssue}
|