@principal-ai/principal-view-react 0.6.9 → 0.6.11

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.
Files changed (64) hide show
  1. package/README.md +2 -5
  2. package/dist/components/ConfigurationSelector.js +4 -2
  3. package/dist/components/ConfigurationSelector.js.map +1 -1
  4. package/dist/components/EdgeInfoPanel.d.ts.map +1 -1
  5. package/dist/components/EdgeInfoPanel.js +43 -13
  6. package/dist/components/EdgeInfoPanel.js.map +1 -1
  7. package/dist/components/GraphRenderer.d.ts.map +1 -1
  8. package/dist/components/GraphRenderer.js +135 -82
  9. package/dist/components/GraphRenderer.js.map +1 -1
  10. package/dist/components/NodeInfoPanel.d.ts.map +1 -1
  11. package/dist/components/NodeInfoPanel.js +143 -45
  12. package/dist/components/NodeInfoPanel.js.map +1 -1
  13. package/dist/edges/CustomEdge.d.ts.map +1 -1
  14. package/dist/edges/CustomEdge.js +2 -2
  15. package/dist/edges/CustomEdge.js.map +1 -1
  16. package/dist/edges/GenericEdge.d.ts.map +1 -1
  17. package/dist/edges/GenericEdge.js +2 -2
  18. package/dist/edges/GenericEdge.js.map +1 -1
  19. package/dist/hooks/usePathBasedEvents.d.ts +1 -1
  20. package/dist/hooks/usePathBasedEvents.d.ts.map +1 -1
  21. package/dist/hooks/usePathBasedEvents.js +9 -9
  22. package/dist/hooks/usePathBasedEvents.js.map +1 -1
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/nodes/CustomNode.d.ts.map +1 -1
  27. package/dist/nodes/CustomNode.js +61 -44
  28. package/dist/nodes/CustomNode.js.map +1 -1
  29. package/dist/nodes/GenericNode.d.ts.map +1 -1
  30. package/dist/nodes/GenericNode.js.map +1 -1
  31. package/dist/utils/animationMapping.d.ts.map +1 -1
  32. package/dist/utils/animationMapping.js +12 -12
  33. package/dist/utils/animationMapping.js.map +1 -1
  34. package/dist/utils/graphConverter.d.ts.map +1 -1
  35. package/dist/utils/graphConverter.js +23 -17
  36. package/dist/utils/graphConverter.js.map +1 -1
  37. package/dist/utils/iconResolver.d.ts.map +1 -1
  38. package/dist/utils/iconResolver.js +1 -1
  39. package/dist/utils/iconResolver.js.map +1 -1
  40. package/package.json +2 -1
  41. package/src/components/ConfigurationSelector.tsx +5 -5
  42. package/src/components/EdgeInfoPanel.tsx +79 -37
  43. package/src/components/GraphRenderer.tsx +528 -364
  44. package/src/components/NodeInfoPanel.tsx +209 -86
  45. package/src/edges/CustomEdge.tsx +6 -4
  46. package/src/edges/GenericEdge.tsx +2 -6
  47. package/src/hooks/usePathBasedEvents.ts +54 -45
  48. package/src/index.ts +11 -2
  49. package/src/nodes/CustomNode.tsx +132 -106
  50. package/src/nodes/GenericNode.tsx +4 -3
  51. package/src/stories/AnimationWorkshop.stories.tsx +131 -12
  52. package/src/stories/CanvasNodeTypes.stories.tsx +898 -0
  53. package/src/stories/ColorPriority.stories.tsx +20 -10
  54. package/src/stories/EventDrivenAnimations.stories.tsx +8 -0
  55. package/src/stories/EventLog.stories.tsx +1 -1
  56. package/src/stories/GraphRenderer.stories.tsx +23 -10
  57. package/src/stories/IndustryThemes.stories.tsx +481 -0
  58. package/src/stories/MultiConfig.stories.tsx +8 -0
  59. package/src/stories/MultiDirectionalConnections.stories.tsx +8 -0
  60. package/src/stories/NodeFieldsAudit.stories.tsx +124 -37
  61. package/src/stories/NodeShapes.stories.tsx +73 -59
  62. package/src/utils/animationMapping.ts +19 -23
  63. package/src/utils/graphConverter.ts +35 -19
  64. package/src/utils/iconResolver.tsx +5 -1
@@ -13,7 +13,7 @@ import type { LogLevel } from '@principal-ai/principal-view-core';
13
13
  export interface NodeAnimation {
14
14
  type: 'pulse' | 'flash' | 'shake' | 'entry';
15
15
  duration: number;
16
- intensity?: number; // 0-1 scale
16
+ intensity?: number; // 0-1 scale
17
17
  color?: string;
18
18
  }
19
19
 
@@ -43,7 +43,7 @@ export function logLevelToNodeAnimation(level: LogLevel): NodeAnimation {
43
43
  type: 'pulse',
44
44
  duration: 800,
45
45
  intensity: 0.3,
46
- color: '#94a3b8' // slate-400
46
+ color: '#94a3b8', // slate-400
47
47
  };
48
48
 
49
49
  case 'info':
@@ -51,7 +51,7 @@ export function logLevelToNodeAnimation(level: LogLevel): NodeAnimation {
51
51
  type: 'pulse',
52
52
  duration: 1000,
53
53
  intensity: 0.5,
54
- color: '#3b82f6' // blue-500
54
+ color: '#3b82f6', // blue-500
55
55
  };
56
56
 
57
57
  case 'warn':
@@ -59,7 +59,7 @@ export function logLevelToNodeAnimation(level: LogLevel): NodeAnimation {
59
59
  type: 'pulse',
60
60
  duration: 1200,
61
61
  intensity: 1.0,
62
- color: '#f59e0b' // amber-500
62
+ color: '#f59e0b', // amber-500
63
63
  };
64
64
 
65
65
  case 'error':
@@ -67,7 +67,7 @@ export function logLevelToNodeAnimation(level: LogLevel): NodeAnimation {
67
67
  type: 'flash', // More dramatic animation for errors
68
68
  duration: 1500,
69
69
  intensity: 1.0,
70
- color: '#ef4444' // red-500
70
+ color: '#ef4444', // red-500
71
71
  };
72
72
  }
73
73
  }
@@ -75,10 +75,7 @@ export function logLevelToNodeAnimation(level: LogLevel): NodeAnimation {
75
75
  /**
76
76
  * Map component action to node animation (Milestone 2)
77
77
  */
78
- export function actionToNodeAnimation(
79
- _action: string,
80
- state?: string
81
- ): NodeAnimation {
78
+ export function actionToNodeAnimation(_action: string, state?: string): NodeAnimation {
82
79
  // Default mapping - can be overridden by configuration
83
80
  switch (state) {
84
81
  case 'acquired':
@@ -88,7 +85,7 @@ export function actionToNodeAnimation(
88
85
  type: 'pulse',
89
86
  duration: 1000,
90
87
  intensity: 0.8,
91
- color: '#22c55e' // green-500
88
+ color: '#22c55e', // green-500
92
89
  };
93
90
 
94
91
  case 'waiting':
@@ -97,7 +94,7 @@ export function actionToNodeAnimation(
97
94
  type: 'pulse',
98
95
  duration: 1500,
99
96
  intensity: 0.5,
100
- color: '#eab308' // yellow-500
97
+ color: '#eab308', // yellow-500
101
98
  };
102
99
 
103
100
  case 'error':
@@ -106,7 +103,7 @@ export function actionToNodeAnimation(
106
103
  type: 'shake',
107
104
  duration: 600,
108
105
  intensity: 1.0,
109
- color: '#ef4444' // red-500
106
+ color: '#ef4444', // red-500
110
107
  };
111
108
 
112
109
  case 'completed':
@@ -115,7 +112,7 @@ export function actionToNodeAnimation(
115
112
  type: 'flash',
116
113
  duration: 800,
117
114
  intensity: 0.7,
118
- color: '#22c55e' // green-500
115
+ color: '#22c55e', // green-500
119
116
  };
120
117
 
121
118
  default:
@@ -124,7 +121,7 @@ export function actionToNodeAnimation(
124
121
  type: 'pulse',
125
122
  duration: 1000,
126
123
  intensity: 0.6,
127
- color: '#3b82f6' // blue-500
124
+ color: '#3b82f6', // blue-500
128
125
  };
129
126
  }
130
127
  }
@@ -132,16 +129,15 @@ export function actionToNodeAnimation(
132
129
  /**
133
130
  * Get animation config for edge based on action (Milestone 2)
134
131
  */
135
- export function actionToEdgeAnimation(
136
- _action: string,
137
- edgeConfig?: EdgeAnimation
138
- ): EdgeAnimation {
132
+ export function actionToEdgeAnimation(_action: string, edgeConfig?: EdgeAnimation): EdgeAnimation {
139
133
  // Use edge config if provided, otherwise default
140
- return edgeConfig || {
141
- type: 'flow',
142
- duration: 2000,
143
- direction: 'forward'
144
- };
134
+ return (
135
+ edgeConfig || {
136
+ type: 'flow',
137
+ duration: 2000,
138
+ direction: 'forward',
139
+ }
140
+ );
145
141
  }
146
142
 
147
143
  /**
@@ -1,5 +1,10 @@
1
1
  import { MarkerType, type Node, type Edge } from '@xyflow/react';
2
- import type { NodeState, EdgeState, GraphConfiguration, Violation } from '@principal-ai/principal-view-core';
2
+ import type {
3
+ NodeState,
4
+ EdgeState,
5
+ GraphConfiguration,
6
+ Violation,
7
+ } from '@principal-ai/principal-view-core';
3
8
  import type { CustomNodeData } from '../nodes/CustomNode';
4
9
  import type { CustomEdgeData } from '../edges/CustomEdge';
5
10
 
@@ -19,14 +24,19 @@ export function convertToXYFlowNodes(
19
24
  console.warn(`Node type "${node.type}" not found in configuration for node "${node.id}"`);
20
25
  }
21
26
 
22
- const hasViolations = violations.some(v => v.context?.nodeId === node.id);
27
+ const hasViolations = violations.some((v) => v.context?.nodeId === node.id);
28
+
29
+ // Groups should render behind other nodes and edges
30
+ const isGroup = node.data?.canvasType === 'group';
23
31
 
24
32
  return {
25
33
  id: node.id,
26
34
  type: 'custom',
27
35
  position: node.position || { x: 0, y: 0 },
36
+ // Groups have lower zIndex to render behind edges
37
+ zIndex: isGroup ? -1 : undefined,
28
38
  data: {
29
- name: (node.data.name as string) || node.id,
39
+ name: node.name || node.id,
30
40
  typeDefinition,
31
41
  state: node.state,
32
42
  hasViolations,
@@ -58,18 +68,21 @@ export function convertToXYFlowEdges(
58
68
  console.warn(`Edge type "${edge.type}" not found in configuration for edge "${edge.id}"`);
59
69
  }
60
70
 
61
- const hasViolations = violations.some(v => v.context?.edgeId === edge.id);
71
+ const hasViolations = violations.some((v) => v.context?.edgeId === edge.id);
62
72
  const edgeWithHandles = edge as EdgeStateWithHandles;
63
73
 
64
74
  // Add arrow marker if edge type is directed
65
75
  // Color priority: edge data color > type definition color > default
66
76
  const edgeColor = edge.data?.color as string | undefined;
67
- const markerEnd = typeDefinition?.directed !== false ? {
68
- type: MarkerType.ArrowClosed,
69
- color: edgeColor || typeDefinition?.color || '#888',
70
- width: 20,
71
- height: 20,
72
- } : undefined;
77
+ const markerEnd =
78
+ typeDefinition?.directed !== false
79
+ ? {
80
+ type: MarkerType.ArrowClosed,
81
+ color: edgeColor || typeDefinition?.color || '#888',
82
+ width: 20,
83
+ height: 20,
84
+ }
85
+ : undefined;
73
86
 
74
87
  return {
75
88
  id: edge.id,
@@ -98,7 +111,7 @@ export function autoLayoutNodes<T extends Record<string, unknown>>(
98
111
  layoutType: 'hierarchical' | 'force-directed' | 'circular' | 'manual' = 'hierarchical'
99
112
  ): Node<T>[] {
100
113
  // Skip if all nodes have positions
101
- const hasPositions = nodes.every(n => n.position.x !== 0 || n.position.y !== 0);
114
+ const hasPositions = nodes.every((n) => n.position.x !== 0 || n.position.y !== 0);
102
115
  if (hasPositions || layoutType === 'manual') {
103
116
  return nodes;
104
117
  }
@@ -120,17 +133,20 @@ export function autoLayoutNodes<T extends Record<string, unknown>>(
120
133
  /**
121
134
  * Simple hierarchical layout algorithm
122
135
  */
123
- function applyHierarchicalLayout<T extends Record<string, unknown>>(nodes: Node<T>[], edges: Edge[]): Node<T>[] {
136
+ function applyHierarchicalLayout<T extends Record<string, unknown>>(
137
+ nodes: Node<T>[],
138
+ edges: Edge[]
139
+ ): Node<T>[] {
124
140
  // Build adjacency list
125
141
  const adjacency = new Map<string, string[]>();
126
142
  const inDegree = new Map<string, number>();
127
143
 
128
- nodes.forEach(node => {
144
+ nodes.forEach((node) => {
129
145
  adjacency.set(node.id, []);
130
146
  inDegree.set(node.id, 0);
131
147
  });
132
148
 
133
- edges.forEach(edge => {
149
+ edges.forEach((edge) => {
134
150
  const targets = adjacency.get(edge.source) || [];
135
151
  targets.push(edge.target);
136
152
  adjacency.set(edge.source, targets);
@@ -160,7 +176,7 @@ function applyHierarchicalLayout<T extends Record<string, unknown>>(nodes: Node<
160
176
  visited.add(nodeId);
161
177
 
162
178
  const neighbors = adjacency.get(nodeId) || [];
163
- neighbors.forEach(neighbor => {
179
+ neighbors.forEach((neighbor) => {
164
180
  const degree = inDegree.get(neighbor)! - 1;
165
181
  inDegree.set(neighbor, degree);
166
182
  if (degree === 0 && !visited.has(neighbor)) {
@@ -175,7 +191,7 @@ function applyHierarchicalLayout<T extends Record<string, unknown>>(nodes: Node<
175
191
  }
176
192
 
177
193
  // Handle any remaining nodes (cycles or disconnected)
178
- const remainingNodes = nodes.filter(n => !visited.has(n.id)).map(n => n.id);
194
+ const remainingNodes = nodes.filter((n) => !visited.has(n.id)).map((n) => n.id);
179
195
  if (remainingNodes.length > 0) {
180
196
  layers.push(remainingNodes);
181
197
  }
@@ -184,8 +200,8 @@ function applyHierarchicalLayout<T extends Record<string, unknown>>(nodes: Node<
184
200
  const LAYER_HEIGHT = 150;
185
201
  const NODE_WIDTH = 200;
186
202
 
187
- return nodes.map(node => {
188
- const layerIndex = layers.findIndex(layer => layer.includes(node.id));
203
+ return nodes.map((node) => {
204
+ const layerIndex = layers.findIndex((layer) => layer.includes(node.id));
189
205
  const layer = layers[layerIndex] || [];
190
206
  const positionInLayer = layer.indexOf(node.id);
191
207
  const layerWidth = layer.length * NODE_WIDTH;
@@ -193,7 +209,7 @@ function applyHierarchicalLayout<T extends Record<string, unknown>>(nodes: Node<
193
209
  return {
194
210
  ...node,
195
211
  position: {
196
- x: (positionInLayer * NODE_WIDTH) + (NODE_WIDTH / 2) - (layerWidth / 2),
212
+ x: positionInLayer * NODE_WIDTH + NODE_WIDTH / 2 - layerWidth / 2,
197
213
  y: layerIndex * LAYER_HEIGHT,
198
214
  },
199
215
  };
@@ -38,7 +38,11 @@ export function resolveIcon(icon?: string, size: number = 20, className?: string
38
38
  }
39
39
 
40
40
  // Fall back to rendering as text (emoji or unicode)
41
- return <span className={className} style={{ fontSize: `${size}px` }}>{icon}</span>;
41
+ return (
42
+ <span className={className} style={{ fontSize: `${size}px` }}>
43
+ {icon}
44
+ </span>
45
+ );
42
46
  }
43
47
 
44
48
  /**