@cyvest/cyvest-vis 3.2.0 → 4.1.0

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/README.md CHANGED
@@ -1,14 +1,17 @@
1
1
  # @cyvest/cyvest-vis
2
2
 
3
- React components for visualizing Cyvest investigations using XYFlow + D3 layouts.
3
+ React components for visualizing Cyvest investigations using React Flow + D3 force layouts.
4
4
 
5
- ## What it does
5
+ ## Features
6
6
 
7
- - Renders observables, relationships, checks, and containers as an interactive graph.
8
- - Uses `@cyvest/cyvest-js` helpers for level colors, graph data, and schema-safe types.
9
- - Ships CJS, ESM, and type definitions for React 18+ projects.
7
+ - **Two visualization modes**: Observables graph (force-directed) and Investigation graph (hierarchical Dagre layout)
8
+ - **Interactive force simulation**: Drag nodes, adjust forces in real-time
9
+ - **Professional SVG icons**: Clean icons for all observable types (IPs, domains, emails, files, threats, etc.)
10
+ - **Level-aware styling**: Nodes colored by security level (SAFE, INFORMATIVE, SUSPICIOUS, MALICIOUS)
11
+ - **Responsive design**: Works at any size with zoom, pan, and minimap controls
12
+ - Uses `@cyvest/cyvest-js` for types, colors, and graph data extraction
10
13
 
11
- ## Install & build
14
+ ## Installation
12
15
 
13
16
  ```bash
14
17
  pnpm install # from repo root
@@ -23,20 +26,129 @@ pnpm --filter @cyvest/cyvest-vis test
23
26
 
24
27
  ## Usage
25
28
 
29
+ ### Basic Usage
30
+
26
31
  ```tsx
27
32
  import { CyvestGraph } from "@cyvest/cyvest-vis";
28
33
  import type { CyvestInvestigation } from "@cyvest/cyvest-js";
29
34
 
30
- export function InvestigationView({ investigation }: { investigation: CyvestInvestigation }) {
35
+ function InvestigationView({ investigation }: { investigation: CyvestInvestigation }) {
31
36
  return (
32
37
  <CyvestGraph
33
38
  investigation={investigation}
34
- height={520}
39
+ height={600}
35
40
  showViewToggle
36
- onNodeClick={(id) => console.log("Selected", id)}
41
+ onNodeClick={(id) => console.log("Selected:", id)}
37
42
  />
38
43
  );
39
44
  }
40
45
  ```
41
46
 
42
- Props include `height`, `width`, `showViewToggle`, `onNodeClick`, and optional control over zoom/pan behaviour. See `src/components` for more advanced hooks and utilities.
47
+ ### Components
48
+
49
+ #### `CyvestGraph`
50
+
51
+ Main component with toggle between Observables and Investigation views.
52
+
53
+ ```tsx
54
+ <CyvestGraph
55
+ investigation={investigation}
56
+ height={600}
57
+ width="100%"
58
+ initialView="observables" // or "investigation"
59
+ showViewToggle={true}
60
+ onNodeClick={(nodeId) => {}}
61
+ />
62
+ ```
63
+
64
+ #### `ObservablesGraph`
65
+
66
+ Force-directed graph showing all observables and their relationships.
67
+
68
+ ```tsx
69
+ import { ObservablesGraph } from "@cyvest/cyvest-vis";
70
+
71
+ <ObservablesGraph
72
+ investigation={investigation}
73
+ height={600}
74
+ width="100%"
75
+ showControls={true} // Show force layout controls
76
+ forceConfig={{
77
+ chargeStrength: -200,
78
+ linkDistance: 80,
79
+ collisionRadius: 45,
80
+ }}
81
+ onNodeClick={(nodeId) => {}}
82
+ onNodeDoubleClick={(nodeId) => {}}
83
+ />
84
+ ```
85
+
86
+ #### `InvestigationGraph`
87
+
88
+ Hierarchical graph showing root → containers → checks structure.
89
+
90
+ ```tsx
91
+ import { InvestigationGraph } from "@cyvest/cyvest-vis";
92
+
93
+ <InvestigationGraph
94
+ investigation={investigation}
95
+ height={600}
96
+ width="100%"
97
+ onNodeClick={(nodeId, nodeType) => {
98
+ // nodeType: "root" | "check" | "container"
99
+ }}
100
+ />
101
+ ```
102
+
103
+ ### Custom Icons
104
+
105
+ Access icon components for custom UIs:
106
+
107
+ ```tsx
108
+ import { getObservableIcon, getInvestigationIcon, GlobeIcon, MailIcon } from "@cyvest/cyvest-vis";
109
+
110
+ // Get icon by observable type
111
+ const Icon = getObservableIcon("ipv4-addr"); // Returns GlobeIcon
112
+ <Icon size={24} color="#3b82f6" />
113
+
114
+ // Or use icons directly
115
+ <GlobeIcon size={16} color="currentColor" />
116
+ <MailIcon size={16} color="#ef4444" />
117
+ ```
118
+
119
+ Available icons: `GlobeIcon`, `DomainIcon`, `LinkIcon`, `MailIcon`, `EnvelopeIcon`, `FileIcon`, `HashIcon`, `UserIcon`, `IdCardIcon`, `GearIcon`, `AppIcon`, `RegistryIcon`, `ThreatActorIcon`, `BugIcon`, `SwordIcon`, `TargetIcon`, `AlertIcon`, `FlaskIcon`, `CertificateIcon`, `WifiIcon`, `WorldIcon`, `QuestionIcon`, `CheckIcon`, `BoxIcon`, `CrosshairIcon`
120
+
121
+ ## Types
122
+
123
+ ```tsx
124
+ import type {
125
+ CyvestGraphProps,
126
+ ObservablesGraphProps,
127
+ InvestigationGraphProps,
128
+ ForceLayoutConfig,
129
+ ObservableNodeData,
130
+ InvestigationNodeData,
131
+ InvestigationNodeType,
132
+ } from "@cyvest/cyvest-vis";
133
+ ```
134
+
135
+ ### Force Layout Configuration
136
+
137
+ ```tsx
138
+ interface ForceLayoutConfig {
139
+ chargeStrength: number; // Repulsion strength (default: -200)
140
+ linkDistance: number; // Target link distance (default: 80)
141
+ centerStrength: number; // Center pull strength (default: 0.05)
142
+ collisionRadius: number; // Node collision radius (default: 45)
143
+ iterations: number; // Iterations for static layout (default: 300)
144
+ }
145
+ ```
146
+
147
+ ## Peer Dependencies
148
+
149
+ - React 19+
150
+ - React DOM 19+
151
+
152
+ ## License
153
+
154
+ See repository root for license information.
package/dist/index.d.mts CHANGED
@@ -1,21 +1,121 @@
1
1
  import React from 'react';
2
2
  import * as _cyvest_cyvest_js from '@cyvest/cyvest-js';
3
+ import { Level } from '@cyvest/cyvest-js';
3
4
 
5
+ /**
6
+ * Shape types for observable nodes.
7
+ * In the current design, all non-root nodes are circles.
8
+ */
9
+ type ObservableShape = "circle" | "rectangle";
10
+ /**
11
+ * Data attached to observable graph nodes.
12
+ */
13
+ interface ObservableNodeData extends Record<string, unknown> {
14
+ /** Display label (may be truncated) */
15
+ label: string;
16
+ /** Full observable value */
17
+ fullValue: string;
18
+ /** Observable type (e.g., "domain-name", "ipv4-addr") */
19
+ observableType: string;
20
+ /** Security level */
21
+ level: Level;
22
+ /** Numeric score */
23
+ score: number;
24
+ /** Shape for this node type */
25
+ shape: ObservableShape;
26
+ /** Whether this is the root observable */
27
+ isRoot: boolean;
28
+ /** Whether the observable is whitelisted */
29
+ whitelisted: boolean;
30
+ /** Whether the observable is internal */
31
+ internal: boolean;
32
+ }
33
+ /**
34
+ * Data attached to observable graph edges.
35
+ */
36
+ interface ObservableEdgeData extends Record<string, unknown> {
37
+ /** Relationship type (e.g., "related-to") */
38
+ relationshipType: string;
39
+ /** Whether this is a bidirectional relationship */
40
+ bidirectional: boolean;
41
+ }
42
+ /**
43
+ * Node types for the investigation graph view.
44
+ */
45
+ type InvestigationNodeType = "root" | "check" | "container";
46
+ /**
47
+ * Data attached to investigation graph nodes.
48
+ */
49
+ interface InvestigationNodeData extends Record<string, unknown> {
50
+ /** Display label */
51
+ label: string;
52
+ /** Node type (root, check, or container) */
53
+ nodeType: InvestigationNodeType;
54
+ /** Security level */
55
+ level: Level;
56
+ /** Numeric score */
57
+ score: number;
58
+ /** Description (for checks) */
59
+ description?: string;
60
+ /** Path (for containers) */
61
+ path?: string;
62
+ }
4
63
  /**
5
64
  * Configuration options for d3-force layout.
6
65
  */
7
66
  interface ForceLayoutConfig {
8
- /** Strength of the charge force (repulsion). Default: -300 */
67
+ /** Strength of the charge force (repulsion). Default: -200 */
9
68
  chargeStrength: number;
10
- /** Target distance between linked nodes. Default: 100 */
69
+ /** Target distance between linked nodes. Default: 80 */
11
70
  linkDistance: number;
12
- /** Strength of the centering force. Default: 0.1 */
71
+ /** Strength of the centering force. Default: 0.05 */
13
72
  centerStrength: number;
14
- /** Strength of the collision force. Default: 30 */
73
+ /** Radius for collision detection. Default: 40 */
15
74
  collisionRadius: number;
16
- /** Number of simulation iterations. Default: 300 */
75
+ /** Number of simulation iterations (for static layout). Default: 300 */
17
76
  iterations: number;
18
77
  }
78
+ /**
79
+ * Default force layout configuration.
80
+ * Tuned for good visual separation and smooth animations.
81
+ */
82
+ declare const DEFAULT_FORCE_CONFIG: ForceLayoutConfig;
83
+ /**
84
+ * Props for the ObservablesGraph component.
85
+ */
86
+ interface ObservablesGraphProps {
87
+ /** The Cyvest investigation to visualize */
88
+ investigation: _cyvest_cyvest_js.CyvestInvestigation;
89
+ /** Height of the graph container */
90
+ height?: number | string;
91
+ /** Width of the graph container */
92
+ width?: number | string;
93
+ /** Force layout configuration */
94
+ forceConfig?: Partial<ForceLayoutConfig>;
95
+ /** Callback when a node is clicked */
96
+ onNodeClick?: (nodeId: string) => void;
97
+ /** Callback when a node is double-clicked */
98
+ onNodeDoubleClick?: (nodeId: string) => void;
99
+ /** Custom class name for the container */
100
+ className?: string;
101
+ /** Whether to show the force controls panel */
102
+ showControls?: boolean;
103
+ }
104
+ /**
105
+ * Props for the InvestigationGraph component.
106
+ */
107
+ interface InvestigationGraphProps {
108
+ /** The Cyvest investigation to visualize */
109
+ investigation: _cyvest_cyvest_js.CyvestInvestigation;
110
+ /** Height of the graph container */
111
+ height?: number | string;
112
+ /** Width of the graph container */
113
+ width?: number | string;
114
+ /** Callback when a node is clicked */
115
+ onNodeClick?: (nodeId: string, nodeType: InvestigationNodeType) => void;
116
+ /** Custom class name for the container */
117
+ className?: string;
118
+ }
19
119
  /**
20
120
  * Props for the CyvestGraph component (combined view).
21
121
  */
@@ -45,4 +145,54 @@ interface CyvestGraphProps {
45
145
  */
46
146
  declare const CyvestGraph: React.FC<CyvestGraphProps>;
47
147
 
48
- export { CyvestGraph, type CyvestGraphProps, type ForceLayoutConfig };
148
+ /**
149
+ * ObservablesGraph component - displays observables as a force-directed graph.
150
+ * Uses iterative d3-force simulation for smooth, interactive layout.
151
+ */
152
+
153
+ /**
154
+ * ObservablesGraph component.
155
+ * Displays all observables from an investigation as a force-directed graph.
156
+ * Wraps the inner component with ReactFlowProvider for hook access.
157
+ */
158
+ declare const ObservablesGraph: React.FC<ObservablesGraphProps>;
159
+
160
+ /**
161
+ * InvestigationGraph component - displays investigation structure with Dagre layout.
162
+ * Shows root observable, checks, and containers in a hierarchical view.
163
+ */
164
+
165
+ /**
166
+ * InvestigationGraph component.
167
+ * Displays investigation structure with horizontal Dagre layout.
168
+ */
169
+ declare const InvestigationGraph: React.FC<InvestigationGraphProps>;
170
+
171
+ /**
172
+ * Professional SVG icons for the visualization components.
173
+ * Hand-crafted icons optimized for small sizes and clear recognition.
174
+ */
175
+
176
+ interface IconProps {
177
+ size?: number;
178
+ color?: string;
179
+ className?: string;
180
+ }
181
+ /**
182
+ * Map observable types to icon components
183
+ */
184
+ declare const OBSERVABLE_ICON_MAP: Record<string, React.FC<IconProps>>;
185
+ /**
186
+ * Map investigation node types to icons
187
+ */
188
+ declare const INVESTIGATION_ICON_MAP: Record<string, React.FC<IconProps>>;
189
+ /**
190
+ * Get the icon component for an observable type.
191
+ */
192
+ declare function getObservableIcon(observableType: string): React.FC<IconProps>;
193
+ /**
194
+ * Get the icon component for an investigation node type.
195
+ */
196
+ declare function getInvestigationIcon(nodeType: string): React.FC<IconProps>;
197
+
198
+ export { CyvestGraph, type CyvestGraphProps, DEFAULT_FORCE_CONFIG, type ForceLayoutConfig, INVESTIGATION_ICON_MAP, type IconProps, InvestigationGraph, type InvestigationGraphProps, type InvestigationNodeData, type InvestigationNodeType, OBSERVABLE_ICON_MAP, type ObservableEdgeData, type ObservableNodeData, type ObservableShape, ObservablesGraph, type ObservablesGraphProps, getInvestigationIcon, getObservableIcon };
package/dist/index.d.ts CHANGED
@@ -1,21 +1,121 @@
1
1
  import React from 'react';
2
2
  import * as _cyvest_cyvest_js from '@cyvest/cyvest-js';
3
+ import { Level } from '@cyvest/cyvest-js';
3
4
 
5
+ /**
6
+ * Shape types for observable nodes.
7
+ * In the current design, all non-root nodes are circles.
8
+ */
9
+ type ObservableShape = "circle" | "rectangle";
10
+ /**
11
+ * Data attached to observable graph nodes.
12
+ */
13
+ interface ObservableNodeData extends Record<string, unknown> {
14
+ /** Display label (may be truncated) */
15
+ label: string;
16
+ /** Full observable value */
17
+ fullValue: string;
18
+ /** Observable type (e.g., "domain-name", "ipv4-addr") */
19
+ observableType: string;
20
+ /** Security level */
21
+ level: Level;
22
+ /** Numeric score */
23
+ score: number;
24
+ /** Shape for this node type */
25
+ shape: ObservableShape;
26
+ /** Whether this is the root observable */
27
+ isRoot: boolean;
28
+ /** Whether the observable is whitelisted */
29
+ whitelisted: boolean;
30
+ /** Whether the observable is internal */
31
+ internal: boolean;
32
+ }
33
+ /**
34
+ * Data attached to observable graph edges.
35
+ */
36
+ interface ObservableEdgeData extends Record<string, unknown> {
37
+ /** Relationship type (e.g., "related-to") */
38
+ relationshipType: string;
39
+ /** Whether this is a bidirectional relationship */
40
+ bidirectional: boolean;
41
+ }
42
+ /**
43
+ * Node types for the investigation graph view.
44
+ */
45
+ type InvestigationNodeType = "root" | "check" | "container";
46
+ /**
47
+ * Data attached to investigation graph nodes.
48
+ */
49
+ interface InvestigationNodeData extends Record<string, unknown> {
50
+ /** Display label */
51
+ label: string;
52
+ /** Node type (root, check, or container) */
53
+ nodeType: InvestigationNodeType;
54
+ /** Security level */
55
+ level: Level;
56
+ /** Numeric score */
57
+ score: number;
58
+ /** Description (for checks) */
59
+ description?: string;
60
+ /** Path (for containers) */
61
+ path?: string;
62
+ }
4
63
  /**
5
64
  * Configuration options for d3-force layout.
6
65
  */
7
66
  interface ForceLayoutConfig {
8
- /** Strength of the charge force (repulsion). Default: -300 */
67
+ /** Strength of the charge force (repulsion). Default: -200 */
9
68
  chargeStrength: number;
10
- /** Target distance between linked nodes. Default: 100 */
69
+ /** Target distance between linked nodes. Default: 80 */
11
70
  linkDistance: number;
12
- /** Strength of the centering force. Default: 0.1 */
71
+ /** Strength of the centering force. Default: 0.05 */
13
72
  centerStrength: number;
14
- /** Strength of the collision force. Default: 30 */
73
+ /** Radius for collision detection. Default: 40 */
15
74
  collisionRadius: number;
16
- /** Number of simulation iterations. Default: 300 */
75
+ /** Number of simulation iterations (for static layout). Default: 300 */
17
76
  iterations: number;
18
77
  }
78
+ /**
79
+ * Default force layout configuration.
80
+ * Tuned for good visual separation and smooth animations.
81
+ */
82
+ declare const DEFAULT_FORCE_CONFIG: ForceLayoutConfig;
83
+ /**
84
+ * Props for the ObservablesGraph component.
85
+ */
86
+ interface ObservablesGraphProps {
87
+ /** The Cyvest investigation to visualize */
88
+ investigation: _cyvest_cyvest_js.CyvestInvestigation;
89
+ /** Height of the graph container */
90
+ height?: number | string;
91
+ /** Width of the graph container */
92
+ width?: number | string;
93
+ /** Force layout configuration */
94
+ forceConfig?: Partial<ForceLayoutConfig>;
95
+ /** Callback when a node is clicked */
96
+ onNodeClick?: (nodeId: string) => void;
97
+ /** Callback when a node is double-clicked */
98
+ onNodeDoubleClick?: (nodeId: string) => void;
99
+ /** Custom class name for the container */
100
+ className?: string;
101
+ /** Whether to show the force controls panel */
102
+ showControls?: boolean;
103
+ }
104
+ /**
105
+ * Props for the InvestigationGraph component.
106
+ */
107
+ interface InvestigationGraphProps {
108
+ /** The Cyvest investigation to visualize */
109
+ investigation: _cyvest_cyvest_js.CyvestInvestigation;
110
+ /** Height of the graph container */
111
+ height?: number | string;
112
+ /** Width of the graph container */
113
+ width?: number | string;
114
+ /** Callback when a node is clicked */
115
+ onNodeClick?: (nodeId: string, nodeType: InvestigationNodeType) => void;
116
+ /** Custom class name for the container */
117
+ className?: string;
118
+ }
19
119
  /**
20
120
  * Props for the CyvestGraph component (combined view).
21
121
  */
@@ -45,4 +145,54 @@ interface CyvestGraphProps {
45
145
  */
46
146
  declare const CyvestGraph: React.FC<CyvestGraphProps>;
47
147
 
48
- export { CyvestGraph, type CyvestGraphProps, type ForceLayoutConfig };
148
+ /**
149
+ * ObservablesGraph component - displays observables as a force-directed graph.
150
+ * Uses iterative d3-force simulation for smooth, interactive layout.
151
+ */
152
+
153
+ /**
154
+ * ObservablesGraph component.
155
+ * Displays all observables from an investigation as a force-directed graph.
156
+ * Wraps the inner component with ReactFlowProvider for hook access.
157
+ */
158
+ declare const ObservablesGraph: React.FC<ObservablesGraphProps>;
159
+
160
+ /**
161
+ * InvestigationGraph component - displays investigation structure with Dagre layout.
162
+ * Shows root observable, checks, and containers in a hierarchical view.
163
+ */
164
+
165
+ /**
166
+ * InvestigationGraph component.
167
+ * Displays investigation structure with horizontal Dagre layout.
168
+ */
169
+ declare const InvestigationGraph: React.FC<InvestigationGraphProps>;
170
+
171
+ /**
172
+ * Professional SVG icons for the visualization components.
173
+ * Hand-crafted icons optimized for small sizes and clear recognition.
174
+ */
175
+
176
+ interface IconProps {
177
+ size?: number;
178
+ color?: string;
179
+ className?: string;
180
+ }
181
+ /**
182
+ * Map observable types to icon components
183
+ */
184
+ declare const OBSERVABLE_ICON_MAP: Record<string, React.FC<IconProps>>;
185
+ /**
186
+ * Map investigation node types to icons
187
+ */
188
+ declare const INVESTIGATION_ICON_MAP: Record<string, React.FC<IconProps>>;
189
+ /**
190
+ * Get the icon component for an observable type.
191
+ */
192
+ declare function getObservableIcon(observableType: string): React.FC<IconProps>;
193
+ /**
194
+ * Get the icon component for an investigation node type.
195
+ */
196
+ declare function getInvestigationIcon(nodeType: string): React.FC<IconProps>;
197
+
198
+ export { CyvestGraph, type CyvestGraphProps, DEFAULT_FORCE_CONFIG, type ForceLayoutConfig, INVESTIGATION_ICON_MAP, type IconProps, InvestigationGraph, type InvestigationGraphProps, type InvestigationNodeData, type InvestigationNodeType, OBSERVABLE_ICON_MAP, type ObservableEdgeData, type ObservableNodeData, type ObservableShape, ObservablesGraph, type ObservablesGraphProps, getInvestigationIcon, getObservableIcon };