@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
@@ -10,14 +10,14 @@ import type {
10
10
  ComponentActivityEvent,
11
11
  ComponentActionEvent,
12
12
  EdgeAnimationEvent,
13
- PathBasedEvent
13
+ PathBasedEvent,
14
14
  } from '@principal-ai/principal-view-core';
15
15
  import {
16
16
  logLevelToNodeAnimation,
17
17
  actionToNodeAnimation,
18
18
  actionToEdgeAnimation,
19
19
  type NodeAnimation,
20
- type EdgeAnimation
20
+ type EdgeAnimation,
21
21
  } from '../utils/animationMapping';
22
22
 
23
23
  /**
@@ -52,53 +52,62 @@ export function usePathBasedEvents({
52
52
  events,
53
53
  callbacks,
54
54
  onEventProcessed,
55
- minLogLevel = 'info'
55
+ minLogLevel = 'info',
56
56
  }: UsePathBasedEventsOptions): void {
57
57
  const { onNodeAnimation, onEdgeAnimation } = callbacks;
58
58
 
59
59
  // Process component activity events (Milestone 1)
60
- const processActivityEvent = useCallback((event: ComponentActivityEvent) => {
61
- // Map log level to animation
62
- const animation = logLevelToNodeAnimation(event.level);
63
-
64
- // Trigger node animation
65
- onNodeAnimation(event.componentId, {
66
- ...animation,
67
- timestamp: event.timestamp
68
- });
69
-
70
- onEventProcessed?.(event);
71
- }, [onNodeAnimation, onEventProcessed]);
60
+ const processActivityEvent = useCallback(
61
+ (event: ComponentActivityEvent) => {
62
+ // Map log level to animation
63
+ const animation = logLevelToNodeAnimation(event.level);
64
+
65
+ // Trigger node animation
66
+ onNodeAnimation(event.componentId, {
67
+ ...animation,
68
+ timestamp: event.timestamp,
69
+ });
70
+
71
+ onEventProcessed?.(event);
72
+ },
73
+ [onNodeAnimation, onEventProcessed]
74
+ );
72
75
 
73
76
  // Process component action events (Milestone 2)
74
- const processActionEvent = useCallback((event: ComponentActionEvent) => {
75
- // Map action/state to animation
76
- const animation = actionToNodeAnimation(event.action, event.state);
77
-
78
- // Trigger node animation
79
- onNodeAnimation(event.componentId, {
80
- ...animation,
81
- timestamp: event.timestamp
82
- });
83
-
84
- onEventProcessed?.(event);
85
- }, [onNodeAnimation, onEventProcessed]);
77
+ const processActionEvent = useCallback(
78
+ (event: ComponentActionEvent) => {
79
+ // Map action/state to animation
80
+ const animation = actionToNodeAnimation(event.action, event.state);
81
+
82
+ // Trigger node animation
83
+ onNodeAnimation(event.componentId, {
84
+ ...animation,
85
+ timestamp: event.timestamp,
86
+ });
87
+
88
+ onEventProcessed?.(event);
89
+ },
90
+ [onNodeAnimation, onEventProcessed]
91
+ );
86
92
 
87
93
  // Process edge animation events (Milestone 2)
88
- const processEdgeAnimationEvent = useCallback((event: EdgeAnimationEvent) => {
89
- const animation = actionToEdgeAnimation(event.triggeredBy?.action || 'unknown', {
90
- type: event.animation,
91
- duration: event.duration,
92
- direction: event.direction
93
- });
94
-
95
- onEdgeAnimation(event.edgeId, {
96
- ...animation,
97
- timestamp: event.timestamp
98
- });
99
-
100
- onEventProcessed?.(event);
101
- }, [onEdgeAnimation, onEventProcessed]);
94
+ const processEdgeAnimationEvent = useCallback(
95
+ (event: EdgeAnimationEvent) => {
96
+ const animation = actionToEdgeAnimation(event.triggeredBy?.action || 'unknown', {
97
+ type: event.animation,
98
+ duration: event.duration,
99
+ direction: event.direction,
100
+ });
101
+
102
+ onEdgeAnimation(event.edgeId, {
103
+ ...animation,
104
+ timestamp: event.timestamp,
105
+ });
106
+
107
+ onEventProcessed?.(event);
108
+ },
109
+ [onEdgeAnimation, onEventProcessed]
110
+ );
102
111
 
103
112
  // Process events when they change
104
113
  useEffect(() => {
@@ -149,7 +158,7 @@ export function processBatchEvents(
149
158
  const animation = logLevelToNodeAnimation(event.level);
150
159
  callbacks.onNodeAnimation(event.componentId, {
151
160
  ...animation,
152
- timestamp: event.timestamp
161
+ timestamp: event.timestamp,
153
162
  });
154
163
  }
155
164
  break;
@@ -159,7 +168,7 @@ export function processBatchEvents(
159
168
  const animation = actionToNodeAnimation(event.action, event.state);
160
169
  callbacks.onNodeAnimation(event.componentId, {
161
170
  ...animation,
162
- timestamp: event.timestamp
171
+ timestamp: event.timestamp,
163
172
  });
164
173
  }
165
174
  break;
@@ -169,11 +178,11 @@ export function processBatchEvents(
169
178
  const animation = actionToEdgeAnimation(event.triggeredBy?.action || 'unknown', {
170
179
  type: event.animation,
171
180
  duration: event.duration,
172
- direction: event.direction
181
+ direction: event.direction,
173
182
  });
174
183
  callbacks.onEdgeAnimation(event.edgeId, {
175
184
  ...animation,
176
- timestamp: event.timestamp
185
+ timestamp: event.timestamp,
177
186
  });
178
187
  }
179
188
  break;
package/src/index.ts CHANGED
@@ -30,7 +30,12 @@ export type {
30
30
 
31
31
  // Export components
32
32
  export { GraphRenderer } from './components/GraphRenderer';
33
- export type { GraphRendererProps, GraphRendererHandle, NodePositionChange, PendingChanges } from './components/GraphRenderer';
33
+ export type {
34
+ GraphRendererProps,
35
+ GraphRendererHandle,
36
+ NodePositionChange,
37
+ PendingChanges,
38
+ } from './components/GraphRenderer';
34
39
 
35
40
  export { EventLog } from './components/EventLog';
36
41
  export type { EventLogProps } from './components/EventLog';
@@ -61,7 +66,11 @@ export { CustomEdge } from './edges/CustomEdge';
61
66
  export type { CustomEdgeData } from './edges/CustomEdge';
62
67
 
63
68
  // Export utilities
64
- export { convertToXYFlowNodes, convertToXYFlowEdges, autoLayoutNodes } from './utils/graphConverter';
69
+ export {
70
+ convertToXYFlowNodes,
71
+ convertToXYFlowEdges,
72
+ autoLayoutNodes,
73
+ } from './utils/graphConverter';
65
74
  export type { EdgeStateWithHandles } from './utils/graphConverter';
66
75
  export { Icon, resolveIcon } from './utils/iconResolver';
67
76
  export type { IconProps } from './utils/iconResolver';
@@ -37,9 +37,7 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
37
37
  if (!typeDefinition) {
38
38
  return (
39
39
  <div style={{ padding: '10px', border: '2px solid red', borderRadius: '4px' }}>
40
- <div style={{ fontSize: '12px', color: 'red' }}>
41
- Error: Missing node type definition
42
- </div>
40
+ <div style={{ fontSize: '12px', color: 'red' }}>Error: Missing node type definition</div>
43
41
  </div>
44
42
  );
45
43
  }
@@ -49,8 +47,11 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
49
47
  const nodeDataColor = nodeData.color as string | undefined;
50
48
  const baseColor = nodeDataColor || typeDefinition.color || '#888';
51
49
  // Check node's own states first (from pv.states), then fall back to type definition states
52
- const nodeDataStates = nodeData.states as Record<string, { color?: string; label?: string; icon?: string }> | undefined;
53
- const stateColor = state && (nodeDataStates?.[state]?.color || typeDefinition.states?.[state]?.color);
50
+ const nodeDataStates = nodeData.states as
51
+ | Record<string, { color?: string; label?: string; icon?: string }>
52
+ | undefined;
53
+ const stateColor =
54
+ state && (nodeDataStates?.[state]?.color || typeDefinition.states?.[state]?.color);
54
55
  const fillColor = stateColor || baseColor;
55
56
 
56
57
  // Get stroke color - priority: node data stroke > type definition stroke > fill color
@@ -64,9 +65,10 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
64
65
  const displayName = nodeProps.name;
65
66
 
66
67
  // Icon priority: node data override > state icon (node data states first) > type definition icon
67
- const icon = (nodeData.icon as string)
68
- || (state && (nodeDataStates?.[state]?.icon || typeDefinition.states?.[state]?.icon))
69
- || typeDefinition.icon;
68
+ const icon =
69
+ (nodeData.icon as string) ||
70
+ (state && (nodeDataStates?.[state]?.icon || typeDefinition.states?.[state]?.icon)) ||
71
+ typeDefinition.icon;
70
72
 
71
73
  // Get animation class based on type
72
74
  const getAnimationClass = () => {
@@ -86,11 +88,14 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
86
88
 
87
89
  const animationClass = getAnimationClass();
88
90
 
91
+ // Check if this is a group node
92
+ const isGroup = nodeData.canvasType === 'group';
93
+
89
94
  // Shape-specific styles
90
95
  const getShapeStyles = () => {
91
96
  const baseStyles = {
92
97
  padding: '12px 16px',
93
- backgroundColor: 'white',
98
+ backgroundColor: isGroup ? 'rgba(255, 255, 255, 0.7)' : 'white',
94
99
  color: '#000',
95
100
  border: `2px solid ${hasViolations ? '#D0021B' : strokeColor}`,
96
101
  fontSize: '12px',
@@ -100,7 +105,7 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
100
105
  display: 'flex',
101
106
  flexDirection: 'column' as const,
102
107
  alignItems: 'center',
103
- justifyContent: 'center',
108
+ justifyContent: isGroup ? 'flex-start' : 'center',
104
109
  gap: '4px',
105
110
  boxShadow: selected ? `0 0 0 2px ${strokeColor}` : '0 2px 4px rgba(0,0,0,0.1)',
106
111
  transition: 'all 0.2s ease',
@@ -156,47 +161,53 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
156
161
  // Hexagon with gentle diagonals
157
162
  const hexagonClipPath = 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)';
158
163
  const hexagonBorderWidth = 2;
159
- const hexagonBorderStyle: React.CSSProperties = isHexagon ? {
160
- position: 'relative',
161
- clipPath: hexagonClipPath,
162
- backgroundColor: hasViolations ? '#D0021B' : strokeColor,
163
- width: typeDefinition.size?.width || 120,
164
- height: typeDefinition.size?.height || 120,
165
- boxShadow: selected ? `0 0 0 2px ${strokeColor}` : '0 2px 4px rgba(0,0,0,0.1)',
166
- transition: 'all 0.2s ease',
167
- } : {};
164
+ const hexagonBorderStyle: React.CSSProperties = isHexagon
165
+ ? {
166
+ position: 'relative',
167
+ clipPath: hexagonClipPath,
168
+ backgroundColor: hasViolations ? '#D0021B' : strokeColor,
169
+ width: typeDefinition.size?.width || 120,
170
+ height: typeDefinition.size?.height || 120,
171
+ boxShadow: selected ? `0 0 0 2px ${strokeColor}` : '0 2px 4px rgba(0,0,0,0.1)',
172
+ transition: 'all 0.2s ease',
173
+ }
174
+ : {};
168
175
 
169
176
  // Hexagon inner fill styles (white background inset from border)
170
- const hexagonInnerStyle: React.CSSProperties = isHexagon ? {
171
- position: 'absolute',
172
- top: hexagonBorderWidth,
173
- left: hexagonBorderWidth,
174
- right: hexagonBorderWidth,
175
- bottom: hexagonBorderWidth,
176
- clipPath: hexagonClipPath,
177
- backgroundColor: 'white',
178
- color: '#000',
179
- display: 'flex',
180
- flexDirection: 'column',
181
- alignItems: 'center',
182
- justifyContent: 'center',
183
- fontSize: '12px',
184
- fontWeight: 500,
185
- gap: '4px',
186
- } : {};
177
+ const hexagonInnerStyle: React.CSSProperties = isHexagon
178
+ ? {
179
+ position: 'absolute',
180
+ top: hexagonBorderWidth,
181
+ left: hexagonBorderWidth,
182
+ right: hexagonBorderWidth,
183
+ bottom: hexagonBorderWidth,
184
+ clipPath: hexagonClipPath,
185
+ backgroundColor: 'white',
186
+ color: '#000',
187
+ display: 'flex',
188
+ flexDirection: 'column',
189
+ alignItems: 'center',
190
+ justifyContent: 'center',
191
+ fontSize: '12px',
192
+ fontWeight: 500,
193
+ gap: '4px',
194
+ }
195
+ : {};
187
196
 
188
197
  // Handle styles - larger and more visible in edit mode
189
- const baseHandleStyle = editable ? {
190
- background: color,
191
- width: 12,
192
- height: 12,
193
- border: '2px solid white',
194
- boxShadow: '0 0 0 1px ' + color,
195
- } : {
196
- background: color,
197
- width: 8,
198
- height: 8,
199
- };
198
+ const baseHandleStyle = editable
199
+ ? {
200
+ background: color,
201
+ width: 12,
202
+ height: 12,
203
+ border: '2px solid white',
204
+ boxShadow: '0 0 0 1px ' + color,
205
+ }
206
+ : {
207
+ background: color,
208
+ width: 8,
209
+ height: 8,
210
+ };
200
211
 
201
212
  // Diamond handles need to be offset to reach the tips of the rotated shape
202
213
  // A 45° rotated square has tips at ~41% beyond the original edges
@@ -235,51 +246,42 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
235
246
  return (
236
247
  <>
237
248
  {/* Input handles - multiple connection points */}
238
- <Handle
239
- type="target"
240
- position={Position.Top}
241
- id="top"
242
- style={getHandleStyle('top')}
243
- />
244
- <Handle
245
- type="target"
246
- position={Position.Left}
247
- id="left"
248
- style={getHandleStyle('left')}
249
- />
250
- <Handle
251
- type="target"
252
- position={Position.Right}
253
- id="right"
254
- style={getHandleStyle('right')}
255
- />
249
+ <Handle type="target" position={Position.Top} id="top" style={getHandleStyle('top')} />
250
+ <Handle type="target" position={Position.Left} id="left" style={getHandleStyle('left')} />
251
+ <Handle type="target" position={Position.Right} id="right" style={getHandleStyle('right')} />
256
252
 
257
253
  {/* Hexagon needs a wrapper for proper border rendering */}
258
254
  {isHexagon ? (
259
255
  <div style={hexagonBorderStyle} className={animationClass}>
260
256
  <div style={hexagonInnerStyle}>
261
- {icon && <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>{resolveIcon(icon, 20)}</div>}
262
- <div style={{ textAlign: 'center', wordBreak: 'break-word' }}>
263
- {displayName}
264
- </div>
257
+ {icon && (
258
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
259
+ {resolveIcon(icon, 20)}
260
+ </div>
261
+ )}
262
+ <div style={{ textAlign: 'center', wordBreak: 'break-word' }}>{displayName}</div>
265
263
  {state && (
266
- <div style={{
267
- fontSize: '10px',
268
- backgroundColor: color,
269
- color: 'white',
270
- padding: '2px 6px',
271
- borderRadius: '4px',
272
- textAlign: 'center',
273
- }}>
264
+ <div
265
+ style={{
266
+ fontSize: '10px',
267
+ backgroundColor: color,
268
+ color: 'white',
269
+ padding: '2px 6px',
270
+ borderRadius: '4px',
271
+ textAlign: 'center',
272
+ }}
273
+ >
274
274
  {nodeDataStates?.[state]?.label || typeDefinition.states?.[state]?.label || state}
275
275
  </div>
276
276
  )}
277
277
  {hasViolations && (
278
- <div style={{
279
- fontSize: '10px',
280
- color: '#D0021B',
281
- fontWeight: 'bold',
282
- }}>
278
+ <div
279
+ style={{
280
+ fontSize: '10px',
281
+ color: '#D0021B',
282
+ fontWeight: 'bold',
283
+ }}
284
+ >
283
285
  ⚠️
284
286
  </div>
285
287
  )}
@@ -288,29 +290,58 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
288
290
  ) : (
289
291
  <div style={getShapeStyles()} className={animationClass}>
290
292
  {/* Inner content (rotated back if diamond) */}
291
- <div style={isDiamond ? { transform: 'rotate(-45deg)' } : {}}>
292
- {icon && <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>{resolveIcon(icon, 20)}</div>}
293
- <div style={{ textAlign: 'center', wordBreak: 'break-word' }}>
294
- {displayName}
295
- </div>
293
+ <div
294
+ style={{
295
+ ...(isDiamond ? { transform: 'rotate(-45deg)' } : {}),
296
+ ...(isGroup ? { width: '100%' } : {}),
297
+ }}
298
+ >
299
+ {/* Groups: icon and text inline, centered */}
300
+ {isGroup ? (
301
+ <div
302
+ style={{
303
+ display: 'flex',
304
+ alignItems: 'center',
305
+ justifyContent: 'center',
306
+ gap: '6px',
307
+ width: '100%',
308
+ }}
309
+ >
310
+ {icon && resolveIcon(icon, 18)}
311
+ <div style={{ wordBreak: 'break-word' }}>{displayName}</div>
312
+ </div>
313
+ ) : (
314
+ <>
315
+ {icon && (
316
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
317
+ {resolveIcon(icon, 20)}
318
+ </div>
319
+ )}
320
+ <div style={{ textAlign: 'center', wordBreak: 'break-word' }}>{displayName}</div>
321
+ </>
322
+ )}
296
323
  {state && (
297
- <div style={{
298
- fontSize: '10px',
299
- backgroundColor: color,
300
- color: 'white',
301
- padding: '2px 6px',
302
- borderRadius: '4px',
303
- textAlign: 'center',
304
- }}>
324
+ <div
325
+ style={{
326
+ fontSize: '10px',
327
+ backgroundColor: color,
328
+ color: 'white',
329
+ padding: '2px 6px',
330
+ borderRadius: '4px',
331
+ textAlign: 'center',
332
+ }}
333
+ >
305
334
  {nodeDataStates?.[state]?.label || typeDefinition.states?.[state]?.label || state}
306
335
  </div>
307
336
  )}
308
337
  {hasViolations && (
309
- <div style={{
310
- fontSize: '10px',
311
- color: '#D0021B',
312
- fontWeight: 'bold',
313
- }}>
338
+ <div
339
+ style={{
340
+ fontSize: '10px',
341
+ color: '#D0021B',
342
+ fontWeight: 'bold',
343
+ }}
344
+ >
314
345
  ⚠️
315
346
  </div>
316
347
  )}
@@ -325,12 +356,7 @@ export const CustomNode: React.FC<NodeProps<any>> = ({ data, selected }) => {
325
356
  id="bottom"
326
357
  style={getHandleStyle('bottom')}
327
358
  />
328
- <Handle
329
- type="source"
330
- position={Position.Left}
331
- id="left-out"
332
- style={getHandleStyle('left')}
333
- />
359
+ <Handle type="source" position={Position.Left} id="left-out" style={getHandleStyle('left')} />
334
360
  <Handle
335
361
  type="source"
336
362
  position={Position.Right}
@@ -29,9 +29,10 @@ export const GenericNode: React.FC<GenericNodeProps> = ({
29
29
  hasViolations,
30
30
  }) => {
31
31
  // Get color based on state or default
32
- const color = state && typeDefinition.states?.[state]?.color
33
- ? typeDefinition.states[state].color
34
- : typeDefinition.color || '#888';
32
+ const color =
33
+ state && typeDefinition.states?.[state]?.color
34
+ ? typeDefinition.states[state].color
35
+ : typeDefinition.color || '#888';
35
36
 
36
37
  return (
37
38
  <div