@principal-ai/principal-view-react 0.16.32 → 0.16.34

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 CHANGED
@@ -51,5 +51,9 @@ export type { JsonValue, GraphifyFileType, GraphifyConfidence, GraphifyNodeType,
51
51
  export type { GraphifyAnchorResolution, SubsystemGraphifyAnchor, GraphifyMethodInfo, GraphifyPropertyInfo, GraphifyParamInfo, GraphifyCallInfo, GraphifyReferenceInfo, GraphifyImportInfo, GraphifyClassDetail, GraphifyFunctionDetail, GraphifyTypeDetail, GraphifyModuleDetail, GraphifyExternalDetail, GraphifyComponentDetail, GraphifyEdgeRef, } from './graphify';
52
52
  export { SubsystemComponentGraph } from './subsystem/SubsystemComponentGraph';
53
53
  export type { SubsystemComponentGraphProps } from './subsystem/SubsystemComponentGraph';
54
+ export { SubsystemFileTree } from './subsystem/SubsystemFileTree';
55
+ export type { SubsystemFileTreeProps } from './subsystem/SubsystemFileTree';
56
+ export { GraphLayoutCover } from './subsystem/GraphLayoutCover';
57
+ export type { GraphLayoutCoverProps } from './subsystem/GraphLayoutCover';
54
58
  export type { SubsystemComponent, SubsystemComponentEdge, SubsystemGraphDocument, SubsystemComponentKind, SubsystemEdgeMechanism, } from './subsystem/model';
55
59
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -37,4 +37,6 @@ export { PipelineView, useStateView } from './components/state-view';
37
37
  export { SessionEventFeed, SessionEventFeedGrouped, } from './components/session-events';
38
38
  // Subsystem component graph
39
39
  export { SubsystemComponentGraph } from './subsystem/SubsystemComponentGraph';
40
+ export { SubsystemFileTree } from './subsystem/SubsystemFileTree';
41
+ export { GraphLayoutCover } from './subsystem/GraphLayoutCover';
40
42
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsBH,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAQ3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAS9D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAOnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAG3E,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,8BAA8B;AAC9B,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,2BAA2B;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,mBAAmB;AACnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGvG,4DAA4D;AAC5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG1E,6EAA6E;AAC7E,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAsChC,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAmCrE,sEAAsE;AACtE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAsCrC,4BAA4B;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsBH,oBAAoB;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAQ3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAS9D,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAOnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAG3E,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,8BAA8B;AAC9B,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,2BAA2B;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,mBAAmB;AACnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGvG,4DAA4D;AAC5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG1E,6EAA6E;AAC7E,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAsChC,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAmCrE,sEAAsE;AACtE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AAsCrC,4BAA4B;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAE9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * GraphLayoutCover — opaque overlay that hides a graph's startup sequence
3
+ * (initial measurement render, layout swap, camera settle animation).
4
+ *
5
+ * Must sit inside a `position: relative` ancestor sized to the canvas; it
6
+ * covers exactly that box. Renders covered from mount and fades out
7
+ * `holdMs` after `revealed` flips true, then stays transparent until the
8
+ * next `revealed → false` reset.
9
+ */
10
+ export interface GraphLayoutCoverProps {
11
+ /** True once the final layout is ready and the camera has settled. */
12
+ revealed: boolean;
13
+ /** How long to stay fully opaque after `revealed`. @default 650 */
14
+ holdMs?: number;
15
+ /** Label shown while covered. @default 'Laying out graph…' */
16
+ label?: string;
17
+ }
18
+ export declare function GraphLayoutCover({ revealed, holdMs, label, }: GraphLayoutCoverProps): import("react/jsx-runtime").JSX.Element;
19
+ //# sourceMappingURL=GraphLayoutCover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphLayoutCover.d.ts","sourceRoot":"","sources":["../../src/subsystem/GraphLayoutCover.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,MAAY,EACZ,KAA2B,GAC5B,EAAE,qBAAqB,2CA0CvB"}
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * GraphLayoutCover — opaque overlay that hides a graph's startup sequence
4
+ * (initial measurement render, layout swap, camera settle animation).
5
+ *
6
+ * Must sit inside a `position: relative` ancestor sized to the canvas; it
7
+ * covers exactly that box. Renders covered from mount and fades out
8
+ * `holdMs` after `revealed` flips true, then stays transparent until the
9
+ * next `revealed → false` reset.
10
+ */
11
+ import { useEffect, useState } from 'react';
12
+ import { useTheme } from '@principal-ade/industry-theme';
13
+ export function GraphLayoutCover({ revealed, holdMs = 650, label = 'Laying out graph…', }) {
14
+ const { theme } = useTheme();
15
+ const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
16
+ const [coverUp, setCoverUp] = useState(true);
17
+ useEffect(() => {
18
+ if (!revealed) {
19
+ setCoverUp(true);
20
+ return;
21
+ }
22
+ const t = setTimeout(() => setCoverUp(false), holdMs);
23
+ return () => clearTimeout(t);
24
+ }, [revealed, holdMs]);
25
+ return (_jsx("div", { style: {
26
+ position: 'absolute',
27
+ inset: 0,
28
+ zIndex: 15,
29
+ background: theme.colors.background,
30
+ display: 'flex',
31
+ alignItems: 'center',
32
+ justifyContent: 'center',
33
+ opacity: coverUp ? 1 : 0,
34
+ transition: 'opacity 200ms ease',
35
+ pointerEvents: 'none',
36
+ }, children: coverUp && (_jsx("span", { style: {
37
+ color: muted,
38
+ fontFamily: theme.fonts.monospace,
39
+ fontSize: theme.fontSizes[0],
40
+ }, children: label })) }));
41
+ }
42
+ //# sourceMappingURL=GraphLayoutCover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphLayoutCover.js","sourceRoot":"","sources":["../../src/subsystem/GraphLayoutCover.tsx"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAWzD,MAAM,UAAU,gBAAgB,CAAC,EAC/B,QAAQ,EACR,MAAM,GAAG,GAAG,EACZ,KAAK,GAAG,mBAAmB,GACL;IACtB,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;IACnE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,EAAE;YACb,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO;SACR;QACD,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;QACtD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAEvB,OAAO,CACL,cACE,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,EAAE;YACV,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;YACnC,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxB,UAAU,EAAE,oBAAoB;YAChC,aAAa,EAAE,MAAM;SACtB,YAEA,OAAO,IAAI,CACV,eACE,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK;gBACZ,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS;gBACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;aAC7B,YAEA,KAAK,GACD,CACR,GACG,CACP,CAAC;AACJ,CAAC"}
@@ -24,6 +24,9 @@ export interface SubsystemComponentGraphProps {
24
24
  maxNodeWidth?: number;
25
25
  /** Show edge labels (mechanism names) on the graph. @default true */
26
26
  showEdgeLabels?: boolean;
27
+ /** Show the click-to-open file chip under each component name.
28
+ * @default true */
29
+ showFileBadges?: boolean;
27
30
  /** Subsystem title displayed in the sidebar. */
28
31
  title?: string;
29
32
  /** Markdown description rendered in the sidebar. */
@@ -35,11 +38,23 @@ export interface SubsystemComponentGraphProps {
35
38
  /** Rendered in the sidebar under the description (e.g. selection inspector). */
36
39
  sidebarAfterDescription?: ReactNode;
37
40
  /**
38
- * Rendered inside the selected-component detail panel when the component
39
- * has a `file`. Host-injected reader/renderer so this package stays free
40
- * of fs and code-view dependencies.
41
+ * Host-injected reader/renderer for the bottom file drawer, keyed by
42
+ * repo-root-relative path. Opening happens on node click (component with a
43
+ * `file`) and sidebar file-tree click. Keeps this package free of fs and
44
+ * code-view dependencies.
45
+ */
46
+ renderFileViewer?: (file: string) => ReactNode;
47
+ /**
48
+ * Legacy component-keyed variant, kept for backward compatibility. When
49
+ * `renderFileViewer` is absent, drawer content resolves via the first
50
+ * component whose `file` matches the opened path.
41
51
  */
42
52
  renderFileView?: (component: SubsystemComponent) => ReactNode;
53
+ /**
54
+ * Called when a file in the sidebar file tree is clicked (repo-root-relative
55
+ * path). The tree is derived from the components' `file` values.
56
+ */
57
+ onFileSelect?: (file: string) => void;
43
58
  }
44
59
  export declare function SubsystemComponentGraph(props: SubsystemComponentGraphProps): import("react/jsx-runtime").JSX.Element;
45
60
  //# sourceMappingURL=SubsystemComponentGraph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAiC,SAAS,EAAE,MAAM,OAAO,CAAC;AAoBtE,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EAExB,MAAM,SAAS,CAAC;AAuBjB,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtD;kFAC8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,gFAAgF;IAChF,uBAAuB,CAAC,EAAE,SAAS,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,SAAS,CAAC;CAC/D;AAwkBD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,2CAsC1E"}
1
+ {"version":3,"file":"SubsystemComponentGraph.d.ts","sourceRoot":"","sources":["../../src/subsystem/SubsystemComponentGraph.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAiC,SAAS,EAAE,MAAM,OAAO,CAAC;AAqBtE,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EAExB,MAAM,SAAS,CAAC;AAyBjB,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACtD;kFAC8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;wBACoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,gFAAgF;IAChF,uBAAuB,CAAC,EAAE,SAAS,CAAC;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IAC/C;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,kBAAkB,KAAK,SAAS,CAAC;IAC9D;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAgxBD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,2CAsC1E"}
@@ -15,9 +15,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
15
15
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
16
16
  import { ReactFlow, ReactFlowProvider, Background, BackgroundVariant, Controls, useReactFlow, useViewport, applyNodeChanges, } from '@xyflow/react';
17
17
  import { useTheme } from '@principal-ade/industry-theme';
18
+ import { X } from 'lucide-react';
18
19
  import { IndustryMarkdownSlide } from 'themed-markdown';
19
20
  import { buildSubsystemGraph, KIND_COLOR, MECHANISM_COLOR, deriveNameFromSymbol, } from './model';
20
21
  import { SubsystemComponentNode, SubsystemEdge, SUBSYSTEM_CALLBACKS } from './nodes';
22
+ import { SubsystemFileTree } from './SubsystemFileTree';
23
+ import { GraphLayoutCover } from './GraphLayoutCover';
21
24
  const MECHANISM_DESCRIPTIONS = [
22
25
  ['imports', 'import statement (code-level dependency)', true],
23
26
  ['imports_from', 'imported by (reverse dependency)', true],
@@ -42,7 +45,7 @@ const nodeTypes = {
42
45
  const edgeTypes = {
43
46
  'subsystem-edge': SubsystemEdge,
44
47
  };
45
- function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, title, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, renderFileView }) {
48
+ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured, maxNodeWidth, showEdgeLabels, showFileBadges, title, description, canvasOverlay, sidebarExtra, sidebarAfterDescription, renderFileView, renderFileViewer, onFileSelect }) {
46
49
  const { theme } = useTheme();
47
50
  const { fitView } = useReactFlow();
48
51
  const viewport = useViewport();
@@ -52,10 +55,17 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
52
55
  });
53
56
  const [layoutReady, setLayoutReady] = useState(false);
54
57
  const [selected, setSelected] = useState(null);
58
+ // File currently shown in the bottom drawer (repo-root-relative path).
59
+ const [openFile, setOpenFile] = useState(null);
60
+ // Component the pointer is over (null on leave) → transient tree highlight.
61
+ const [hoveredComponentId, setHoveredComponentId] = useState(null);
55
62
  // Ref mirror of `selected` so the SUBSYSTEM_CALLBACKS click handler (a
56
63
  // closure over the effect deps) can toggle without a stale value.
57
64
  const selectedRef = useRef(null);
58
65
  selectedRef.current = selected;
66
+ // Ref mirror of `openFile` for the tree-click toggle.
67
+ const openFileRef = useRef(null);
68
+ openFileRef.current = openFile;
59
69
  // Pass 1: build with estimated widths so React Flow can measure the DOM.
60
70
  // The pane stays hidden until Pass 2 completes.
61
71
  useEffect(() => {
@@ -124,6 +134,7 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
124
134
  const comp = components.find((c) => c.id === id);
125
135
  if (comp) {
126
136
  // Clicking the already-selected node unselects it (toggle off).
137
+ // Selection is independent of the file drawer — nodes never open it.
127
138
  if (selectedRef.current?.id === comp.id) {
128
139
  setSelected(null);
129
140
  setSelectedEdgeId(null);
@@ -136,15 +147,35 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
136
147
  };
137
148
  SUBSYSTEM_CALLBACKS.onEdgeSelect = selectEdge;
138
149
  SUBSYSTEM_CALLBACKS.maxNodeWidth = maxNodeWidth;
150
+ SUBSYSTEM_CALLBACKS.onHover = setHoveredComponentId;
139
151
  return () => {
140
152
  SUBSYSTEM_CALLBACKS.onSelect = undefined;
141
153
  SUBSYSTEM_CALLBACKS.onEdgeSelect = undefined;
142
154
  SUBSYSTEM_CALLBACKS.maxNodeWidth = undefined;
155
+ SUBSYSTEM_CALLBACKS.onHover = undefined;
143
156
  };
144
157
  }, [components, onSelect, maxNodeWidth, selectEdge]);
145
158
  const { nodes, edges: convertedEdges } = built;
146
159
  const xyflowNodesBase = nodes;
147
160
  const baseEdges = convertedEdges;
161
+ // While a file is open in the drawer, tag each node with whether its
162
+ // component lives in that file — the node renderer spotlights matches and
163
+ // dims non-matches (mirrors the edge-dimming behavior on selection).
164
+ const dispNodes = useMemo(() => {
165
+ let ns = xyflowNodesBase.map((n) => ({
166
+ ...n,
167
+ data: { ...n.data, showFileBadges },
168
+ }));
169
+ if (!openFile)
170
+ return ns;
171
+ return ns.map((n) => {
172
+ const comp = n.data?.component;
173
+ return {
174
+ ...n,
175
+ data: { ...n.data, fileMatch: comp?.file === openFile },
176
+ };
177
+ });
178
+ }, [xyflowNodesBase, openFile, showFileBadges]);
148
179
  const baseNodesKey = useMemo(() => nodes.map((n) => n.id).sort().join(','), [nodes]);
149
180
  const baseEdgesKey = useMemo(() => convertedEdges.map((e) => e.id).sort().join(','), [convertedEdges]);
150
181
  // When an edge is selected, dim every other edge + its label to focus it.
@@ -172,14 +203,14 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
172
203
  pendingMeasuredRef.current = true;
173
204
  }
174
205
  }
175
- const result = applyNodeChanges(changes, xyflowNodesBase);
206
+ const result = applyNodeChanges(changes, dispNodes);
176
207
  // After applying changes, check if we should trigger pass 2.
177
208
  if (pendingMeasuredRef.current) {
178
209
  // Use microtask so the state update from applyNodeChanges commits first.
179
210
  queueMicrotask(() => triggerPass2());
180
211
  }
181
212
  return result;
182
- }, [xyflowNodesBase, triggerPass2]);
213
+ }, [dispNodes, triggerPass2]);
183
214
  const onEdgesChange = useCallback((_changes) => dispEdges, [dispEdges]);
184
215
  useEffect(() => {
185
216
  const t = setTimeout(() => {
@@ -187,11 +218,36 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
187
218
  }, 200);
188
219
  return () => clearTimeout(t);
189
220
  }, [baseNodesKey, baseEdgesKey, fitView]);
221
+ // When the file drawer opens/closes the canvas resizes — reframe once the
222
+ // height transition settles: onto the matching (spotlit) nodes while a file
223
+ // is open, back to the whole graph when it closes.
224
+ const prevOpenFileRef = useRef(null);
225
+ useEffect(() => {
226
+ const prev = prevOpenFileRef.current;
227
+ prevOpenFileRef.current = openFile;
228
+ if (!layoutReady || prev === openFile)
229
+ return;
230
+ const t = setTimeout(() => {
231
+ if (openFile) {
232
+ const ids = xyflowNodesBase
233
+ .filter((n) => n.data?.component?.file === openFile)
234
+ .map((n) => ({ id: n.id }));
235
+ if (ids.length > 0) {
236
+ fitView({ nodes: ids, padding: 0.35, minZoom: 0.05, maxZoom: 2, duration: 250 });
237
+ }
238
+ }
239
+ else {
240
+ fitView({ padding: 0.1, includeHiddenNodes: false, minZoom: 0.05, maxZoom: 2, duration: 250 });
241
+ }
242
+ }, 230);
243
+ return () => clearTimeout(t);
244
+ }, [openFile, layoutReady, xyflowNodesBase, fitView]);
190
245
  const onNodeClick = useCallback((_e, node) => {
191
246
  const comp = node.data?.component;
192
247
  setSelectedEdgeId(null);
193
248
  if (node.type === 'subsystem-component' && comp) {
194
249
  // Clicking the already-selected node unselects it (toggle off).
250
+ // Selection is independent of the file drawer — nodes never open it.
195
251
  if (selected?.id === comp.id) {
196
252
  setSelected(null);
197
253
  return;
@@ -209,6 +265,16 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
209
265
  setSelected(null);
210
266
  setSelectedEdgeId(null);
211
267
  }, []);
268
+ // Sidebar file-tree click → toggle in the bottom drawer (+ host hook only
269
+ // when opening, so hosts don't see close events).
270
+ const onTreeSelectFile = useCallback((file) => {
271
+ if (openFileRef.current === file) {
272
+ setOpenFile(null);
273
+ return;
274
+ }
275
+ setOpenFile(file);
276
+ onFileSelect?.(file);
277
+ }, [onFileSelect]);
212
278
  // Edge label data for the overlay (rendered OUTSIDE ReactFlow so the pane
213
279
  // doesn't intercept pointer events). Uses ELK-computed label midpoints from
214
280
  // the actual edge path (not node-center approximations).
@@ -228,30 +294,58 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
228
294
  return new Set(edgeLabels.map((l) => l.mechanism));
229
295
  }, [edgeLabels]);
230
296
  const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
231
- return (_jsxs("div", { style: { visibility: layoutReady ? 'visible' : 'hidden', width: '100%', height: '100%', display: 'flex', flexDirection: 'row' }, children: [(title || description || usedMechanisms.size > 0 || sidebarExtra || sidebarAfterDescription) && (_jsxs("div", { style: {
232
- width: 280,
233
- minWidth: 280,
297
+ // Unique source files across components sidebar file tree.
298
+ const files = useMemo(() => Array.from(new Set(components.map((c) => c.file).filter(Boolean))).sort(), [components]);
299
+ // The hovered node's file (null when not hovering / file-less component).
300
+ const hoveredFile = useMemo(() => {
301
+ if (!hoveredComponentId)
302
+ return null;
303
+ return components.find((c) => c.id === hoveredComponentId)?.file ?? null;
304
+ }, [components, hoveredComponentId]);
305
+ // Drawer content renderer: prefer the path-keyed viewer; fall back to the
306
+ // legacy component-keyed one via a file → first-component lookup.
307
+ const fileViewer = useMemo(() => {
308
+ if (renderFileViewer)
309
+ return renderFileViewer;
310
+ if (renderFileView) {
311
+ const byFile = new Map(components.filter((c) => c.file).map((c) => [c.file, c]));
312
+ return (file) => {
313
+ const comp = byFile.get(file);
314
+ return comp ? renderFileView(comp) : null;
315
+ };
316
+ }
317
+ return undefined;
318
+ }, [renderFileViewer, renderFileView, components]);
319
+ return (_jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'row' }, children: [(title || description || usedMechanisms.size > 0 || sidebarExtra || sidebarAfterDescription || files.length > 0) && (_jsxs("div", { style: {
320
+ width: 340,
321
+ minWidth: 340,
234
322
  borderRight: `1px solid ${theme.colors.border}`,
235
323
  background: theme.colors.backgroundSecondary ?? theme.colors.background,
236
- padding: '16px',
237
- overflowY: 'auto',
238
324
  display: 'flex',
239
325
  flexDirection: 'column',
240
- gap: 12,
241
- }, children: [sidebarExtra, title && (_jsx("h2", { style: {
242
- margin: 0,
243
- fontSize: theme.fontSizes[2],
244
- fontWeight: 600,
245
- color: theme.colors.text,
246
- fontFamily: theme.fonts.heading,
247
- }, children: title })), description && (_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, fontSizeScale: 0.9, enableKeyboardScrolling: false, autoFocusOnVisible: false }) })), sidebarAfterDescription, usedMechanisms.size > 0 && (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx("span", { style: { fontSize: theme.fontSizes[0] * 0.8, fontFamily: theme.fonts.monospace, textTransform: 'uppercase', color: muted, fontWeight: 600 }, children: "Edge Legend" }), MECHANISM_DESCRIPTIONS.filter(([m]) => usedMechanisms.has(m)).map(([mechanism, desc, verifiable]) => (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: theme.fontSizes[0] }, children: [_jsx("span", { style: {
248
- width: 8,
249
- height: 8,
250
- borderRadius: verifiable ? '50%' : '30% 70% 70% 30% / 30% 30% 70% 70%',
251
- background: MECHANISM_COLOR[mechanism],
252
- border: verifiable ? 'none' : `1px dashed ${MECHANISM_COLOR[mechanism]}`,
253
- flexShrink: 0,
254
- } }), _jsx("span", { style: { fontFamily: theme.fonts.monospace, color: MECHANISM_COLOR[mechanism], fontWeight: 500 }, children: mechanism }), _jsx("span", { style: { color: muted }, children: desc })] }, mechanism)))] }))] })), _jsxs("div", { style: { flex: 1, position: 'relative', display: 'flex', flexDirection: 'column', minHeight: 0 }, children: [showEdgeLabels !== false && (_jsx("div", { style: {
326
+ overflow: 'hidden',
327
+ }, children: [_jsxs("div", { style: {
328
+ flex: 1,
329
+ minHeight: 0,
330
+ overflowY: 'auto',
331
+ padding: '16px',
332
+ display: 'flex',
333
+ flexDirection: 'column',
334
+ gap: 12,
335
+ }, children: [sidebarExtra, title && (_jsx("h2", { style: {
336
+ margin: 0,
337
+ fontSize: theme.fontSizes[2],
338
+ fontWeight: 600,
339
+ color: theme.colors.text,
340
+ fontFamily: theme.fonts.heading,
341
+ }, children: title })), description && (_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, fontSizeScale: 0.9, enableKeyboardScrolling: false, autoFocusOnVisible: false }) })), sidebarAfterDescription, usedMechanisms.size > 0 && (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsx("span", { style: { fontSize: theme.fontSizes[0] * 0.8, fontFamily: theme.fonts.monospace, textTransform: 'uppercase', color: muted, fontWeight: 600 }, children: "Edge Legend" }), MECHANISM_DESCRIPTIONS.filter(([m]) => usedMechanisms.has(m)).map(([mechanism, desc, verifiable]) => (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: theme.fontSizes[0] }, children: [_jsx("span", { style: {
342
+ width: 8,
343
+ height: 8,
344
+ borderRadius: verifiable ? '50%' : '30% 70% 70% 30% / 30% 30% 70% 70%',
345
+ background: MECHANISM_COLOR[mechanism],
346
+ border: verifiable ? 'none' : `1px dashed ${MECHANISM_COLOR[mechanism]}`,
347
+ flexShrink: 0,
348
+ } }), _jsx("span", { style: { fontFamily: theme.fonts.monospace, color: MECHANISM_COLOR[mechanism], fontWeight: 500 }, children: mechanism }), _jsx("span", { style: { color: muted }, children: desc })] }, mechanism)))] }))] }), files.length > 0 && (_jsx(SubsystemFileTree, { files: files, selectedFile: selected?.file ?? openFile, hoveredFile: hoveredFile, onSelectFile: onTreeSelectFile }))] })), _jsxs("div", { style: { flex: 1, position: 'relative', display: 'flex', flexDirection: 'column', minHeight: 0 }, children: [showEdgeLabels !== false && (_jsx("div", { style: {
255
349
  position: 'absolute',
256
350
  inset: 0,
257
351
  overflow: 'hidden',
@@ -283,17 +377,18 @@ function Inner({ components, edges, onSelect, onEdgeSelect, measured: _measured,
283
377
  opacity: lbl.dimmed ? 0.15 : 1,
284
378
  whiteSpace: 'nowrap',
285
379
  }, children: lbl.mechanism }, lbl.id));
286
- }) })), _jsxs(ReactFlow, { nodes: xyflowNodesBase, edges: dispEdges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, minZoom: 0.05, maxZoom: 4, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, proOptions: { hideAttribution: true }, nodesDraggable: false, elementsSelectable: true, selectNodesOnDrag: false, nodesConnectable: false, edgesReconnectable: false, onPaneClick: onPaneClick, panOnDrag: true, panOnScroll: true, zoomOnScroll: false, zoomOnPinch: true, zoomOnDoubleClick: false, style: {
380
+ }) })), _jsxs(ReactFlow, { nodes: dispNodes, edges: dispEdges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, minZoom: 0.05, maxZoom: 4, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, proOptions: { hideAttribution: true }, nodesDraggable: false, elementsSelectable: true, selectNodesOnDrag: false, nodesConnectable: false, edgesReconnectable: false, onPaneClick: onPaneClick, panOnDrag: true, panOnScroll: true, zoomOnScroll: false, zoomOnPinch: true, zoomOnDoubleClick: false, style: {
287
381
  width: '100%',
288
382
  height: '100%',
289
383
  flex: 1,
290
384
  minHeight: 0,
291
385
  background: theme.colors.background,
292
- }, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 16, size: 1 }), _jsx(Controls, { showZoom: true, showFitView: true, showInteractive: true })] }, `${baseNodesKey}-${baseEdgesKey}`), selected && _jsx(ComponentDetail, { component: selected, renderFileView: renderFileView }), canvasOverlay] })] }));
386
+ }, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 16, size: 1 }), _jsx(Controls, { showZoom: true, showFitView: true, showInteractive: true })] }, `${baseNodesKey}-${baseEdgesKey}`), selected && _jsx(ComponentDetail, { component: selected }), _jsx(FileDrawer, { file: openFile, onClose: () => setOpenFile(null), children: fileViewer && openFile ? fileViewer(openFile) : null }), _jsx(GraphLayoutCover, { revealed: layoutReady }), canvasOverlay] })] }));
293
387
  }
294
388
  /** Detail panel for the selected component — the verifiable identity + sources
295
- * moved off the canvas so nodes stay minimal. */
296
- function ComponentDetail({ component, renderFileView }) {
389
+ * moved off the canvas so nodes stay minimal. File content lives in the
390
+ * bottom FileDrawer, not here. */
391
+ function ComponentDetail({ component }) {
297
392
  const { theme } = useTheme();
298
393
  const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
299
394
  const color = KIND_COLOR[component.kind] ?? '#888';
@@ -330,13 +425,69 @@ function ComponentDetail({ component, renderFileView }) {
330
425
  fontFamily: theme.fonts.monospace,
331
426
  textTransform: 'uppercase',
332
427
  fontSize: theme.fontSizes[0] * 0.8,
333
- }, children: k }), _jsx("span", { style: { color: theme.colors.text, fontFamily: theme.fonts.monospace }, children: v })] }, k))), component.detail && _jsx(GraphifyDetailSections, { detail: component.detail }), renderFileView && component.file && (_jsx("div", { style: {
334
- marginTop: 8,
335
- maxHeight: 320,
336
- overflow: 'auto',
337
- border: `1px solid ${theme.colors.border}`,
338
- borderRadius: 6,
339
- }, children: renderFileView(component) }))] }));
428
+ }, children: k }), _jsx("span", { style: { color: theme.colors.text, fontFamily: theme.fonts.monospace }, children: v })] }, k))), component.detail && _jsx(GraphifyDetailSections, { detail: component.detail })] }));
429
+ }
430
+ /** Bottom panel that slides up from the bottom of the graph area to show a
431
+ * file's contents — opened by node clicks and sidebar file-tree clicks
432
+ * alike. Sits in normal flow (canvas shrinks while open, nothing covered)
433
+ * and animates via height; stays mounted so open/close animates. */
434
+ function FileDrawer({ file, onClose, children, }) {
435
+ const { theme } = useTheme();
436
+ const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
437
+ const open = file !== null;
438
+ useEffect(() => {
439
+ if (!open)
440
+ return;
441
+ const onKey = (e) => {
442
+ if (e.key === 'Escape')
443
+ onClose();
444
+ };
445
+ window.addEventListener('keydown', onKey);
446
+ return () => window.removeEventListener('keydown', onKey);
447
+ }, [open, onClose]);
448
+ return (_jsxs("div", { style: {
449
+ position: 'relative',
450
+ // Above the absolute edge-label overlay (zIndex 5), which spans the
451
+ // whole graph-area container including this panel's slice.
452
+ zIndex: 6,
453
+ flexShrink: 0,
454
+ height: open ? '45%' : 0,
455
+ minHeight: 0,
456
+ overflow: 'hidden',
457
+ display: 'flex',
458
+ flexDirection: 'column',
459
+ background: theme.colors.background,
460
+ borderTop: open ? `1px solid ${theme.colors.border}` : 'none',
461
+ transition: 'height 200ms ease',
462
+ }, children: [_jsxs("div", { style: {
463
+ display: 'flex',
464
+ alignItems: 'center',
465
+ gap: 8,
466
+ padding: '6px 10px',
467
+ borderBottom: `1px solid ${theme.colors.border}`,
468
+ flexShrink: 0,
469
+ }, children: [_jsx("span", { title: file ?? undefined, style: {
470
+ flex: 1,
471
+ minWidth: 0,
472
+ overflow: 'hidden',
473
+ textOverflow: 'ellipsis',
474
+ whiteSpace: 'nowrap',
475
+ fontFamily: theme.fonts.monospace,
476
+ fontSize: theme.fontSizes[0],
477
+ color: muted,
478
+ }, children: file }), _jsx("button", { type: "button", onClick: onClose, "aria-label": "Close file", style: {
479
+ display: 'inline-flex',
480
+ alignItems: 'center',
481
+ justifyContent: 'center',
482
+ width: 22,
483
+ height: 22,
484
+ padding: 0,
485
+ border: 'none',
486
+ borderRadius: 4,
487
+ background: 'transparent',
488
+ color: theme.colors.text,
489
+ cursor: 'pointer',
490
+ }, children: _jsx(X, { size: 14 }) })] }), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: children })] }));
340
491
  }
341
492
  /** Renders the graphify drill-down payload for a component. */
342
493
  function GraphifyDetailSections({ detail }) {