@principal-ai/principal-view-react 0.15.1 → 0.15.3

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.
@@ -18,12 +18,19 @@ export interface NodeDimensionChange {
18
18
  height: number;
19
19
  };
20
20
  }
21
+ /** Text change event for tracking inline text edits */
22
+ export interface NodeTextChange {
23
+ nodeId: string;
24
+ text: string;
25
+ }
21
26
  /** All pending changes that can be saved */
22
27
  export interface PendingChanges {
23
28
  /** Node position changes */
24
29
  positionChanges: NodePositionChange[];
25
30
  /** Node dimension changes (from resizing) */
26
31
  dimensionChanges: NodeDimensionChange[];
32
+ /** Text changes for text and group nodes */
33
+ textChanges: NodeTextChange[];
27
34
  /** Node updates (type, data changes) */
28
35
  nodeUpdates: Array<{
29
36
  nodeId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"GraphRenderer.d.ts","sourceRoot":"","sources":["../../src/components/GraphRenderer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GraphRenderer.d.ts","sourceRoot":"","sources":["../../src/components/GraphRenderer.tsx"],"names":[],"mappings":"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"}
@@ -24,6 +24,7 @@ const edgeTypes = { custom: CustomEdge };
24
24
  const createEmptyEditState = () => ({
25
25
  positionChanges: new Map(),
26
26
  dimensionChanges: new Map(),
27
+ textChanges: new Map(),
27
28
  nodeUpdates: new Map(),
28
29
  deletedNodeIds: new Set(),
29
30
  createdEdges: [],
@@ -84,12 +85,14 @@ const CenterIndicator = ({ color }) => {
84
85
  /**
85
86
  * Inner component that uses ReactFlow hooks
86
87
  */
87
- const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges, violations = [], configName: _configName, showMinimap = false, showControls = true, showBackground = true, backgroundVariant = 'lines', backgroundGap, showCenterIndicator = false, showTooltips = true, fitViewDuration = 200, highlightedNodeId, activeNodeIds, events = [], onEventProcessed, editable = false, onPendingChangesChange, onEditStateChange, editStateRef, resetVisualStateRef, undoRedoFunctionsRef, pushHistory, clearHistory, undoFromStack, redoFromStack, onNodeClick: onNodeClickProp, fitViewToNodeIds, fitViewPadding = 0.2, draggableNodeIds, onNodeDragStop: onNodeDragStopProp, onCopy, initialViewport, elkLayout, scenarioEdges, showSequenceLabels = true, }) => {
88
+ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges, violations = [], configName: _configName, showMinimap = false, showControls = true, showBackground = true, backgroundVariant = 'lines', backgroundGap, showCenterIndicator = false, showTooltips = true, fitViewDuration = 200, highlightedNodeId, activeNodeIds, events = [], onEventProcessed, editable = false, onPendingChangesChange, onEditStateChange, editStateRef, resetVisualStateRef, resetTextChangesVersionRef, undoRedoFunctionsRef, pushHistory, clearHistory, undoFromStack, redoFromStack, onNodeClick: onNodeClickProp, fitViewToNodeIds, fitViewPadding = 0.2, draggableNodeIds, onNodeDragStop: onNodeDragStopProp, onCopy, initialViewport, elkLayout, scenarioEdges, showSequenceLabels = true, }) => {
88
89
  const { fitView, fitBounds, getNodes } = useReactFlow();
89
90
  const updateNodeInternals = useUpdateNodeInternals();
90
91
  const { theme } = useTheme();
91
92
  // Track shift key state for tooltip control
92
93
  const [shiftKeyPressed, setShiftKeyPressed] = useState(false);
94
+ // Track text changes version to force re-renders when text is edited
95
+ const [textChangesVersion, setTextChangesVersion] = useState(0);
93
96
  // Track if we're currently processing a node hide operation
94
97
  const hidingNodeRef = useRef(false);
95
98
  // Setup keyboard event listeners for shift key
@@ -218,7 +221,10 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
218
221
  }, [propNodes, draggableNodeIds]);
219
222
  // Always use localNodes for rendering - it syncs with props when structure changes
220
223
  // and receives state_changed event updates. localEdges only used in edit mode.
221
- const nodes = localNodes;
224
+ // Filter out deleted nodes in edit mode
225
+ const nodes = editable
226
+ ? localNodes.filter((node) => !editStateRef.current.deletedNodeIds.has(node.id))
227
+ : localNodes;
222
228
  const edges = editable ? localEdges : propEdges;
223
229
  // Ref to track current xyflow nodes for undo/redo (set later via useEffect)
224
230
  const xyflowNodesRef = useRef([]);
@@ -228,6 +234,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
228
234
  const checkHasChanges = useCallback((state) => {
229
235
  return (state.positionChanges.size > 0 ||
230
236
  state.dimensionChanges.size > 0 ||
237
+ state.textChanges.size > 0 ||
231
238
  state.nodeUpdates.size > 0 ||
232
239
  state.deletedNodeIds.size > 0 ||
233
240
  state.createdEdges.length > 0 ||
@@ -243,6 +250,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
243
250
  console.log('[GraphRenderer] Edit state updated:', {
244
251
  positionChanges: newState.positionChanges.size,
245
252
  dimensionChanges: newState.dimensionChanges.size,
253
+ textChanges: newState.textChanges.size,
246
254
  nodeUpdates: newState.nodeUpdates.size,
247
255
  hasChanges,
248
256
  });
@@ -274,6 +282,61 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
274
282
  return { ...prev, dimensionChanges: newDimensions };
275
283
  });
276
284
  }, [editable, updateEditState, pushHistory]);
285
+ // Handler for node text change - called from CustomNode via context
286
+ const handleNodeTextChange = useCallback((nodeId, text) => {
287
+ if (!editable)
288
+ return;
289
+ // Capture before text for undo
290
+ // For text nodes, the text is in the canvas node's 'text' field
291
+ // For group nodes, it's in the 'label' field
292
+ // We need to look at the original canvas to get the before value
293
+ const beforeText = editStateRef.current.textChanges.get(nodeId) ?? '';
294
+ // Push to history
295
+ pushHistory([
296
+ {
297
+ type: 'text',
298
+ nodeId,
299
+ before: beforeText,
300
+ after: text,
301
+ },
302
+ ]);
303
+ updateEditState((prev) => {
304
+ const newTextChanges = new Map(prev.textChanges);
305
+ newTextChanges.set(nodeId, text);
306
+ return { ...prev, textChanges: newTextChanges };
307
+ });
308
+ // Force re-render by incrementing version
309
+ setTextChangesVersion((v) => v + 1);
310
+ }, [editable, updateEditState, pushHistory]);
311
+ // Handler for deleting selected nodes (Delete/Backspace key)
312
+ const handleDeleteSelectedNodes = useCallback(() => {
313
+ if (!editable || selectedNodeIds.size === 0)
314
+ return;
315
+ const nodesToDelete = Array.from(selectedNodeIds);
316
+ const historyEntries = [];
317
+ // Build history entries for each deleted node
318
+ for (const nodeId of nodesToDelete) {
319
+ const node = localNodes.find((n) => n.id === nodeId);
320
+ if (!node)
321
+ continue;
322
+ historyEntries.push({
323
+ type: 'nodeDelete',
324
+ nodeId,
325
+ nodeData: node,
326
+ });
327
+ }
328
+ // Push all deletions as a single batch
329
+ if (historyEntries.length > 0) {
330
+ pushHistory(historyEntries);
331
+ updateEditState((prev) => {
332
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
333
+ nodesToDelete.forEach((id) => newDeletedNodeIds.add(id));
334
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
335
+ });
336
+ // Clear selection after deletion
337
+ setSelectedNodeIds(new Set());
338
+ }
339
+ }, [editable, selectedNodeIds, localNodes, pushHistory, updateEditState]);
277
340
  // Handle toggling node hidden state (Cmd/Ctrl+click)
278
341
  // This is exposed via context so CustomNode can call it on mousedown
279
342
  // (mousedown works in edit mode where click is intercepted by drag handling)
@@ -340,9 +403,10 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
340
403
  // Memoize the context value to prevent unnecessary re-renders
341
404
  const graphEditContextValue = useMemo(() => ({
342
405
  onNodeResizeEnd: handleNodeResizeEnd,
406
+ onNodeTextChange: handleNodeTextChange,
343
407
  onToggleNodeHidden: handleToggleNodeHidden,
344
408
  onHideUnconnectedNodes: handleHideUnconnectedNodes,
345
- }), [handleNodeResizeEnd, handleToggleNodeHidden, handleHideUnconnectedNodes]);
409
+ }), [handleNodeResizeEnd, handleNodeTextChange, handleToggleNodeHidden, handleHideUnconnectedNodes]);
346
410
  // ============================================
347
411
  // ALIGNMENT GUIDES
348
412
  // ============================================
@@ -887,6 +951,8 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
887
951
  const animation = animationState.nodeAnimations[node.id];
888
952
  // Apply any pending position changes
889
953
  const pendingPosition = editStateRef.current.positionChanges.get(node.id);
954
+ // Apply any pending text changes
955
+ const pendingText = editStateRef.current.textChanges.get(node.id);
890
956
  // Allow specific nodes to be draggable even when not in edit mode
891
957
  const isDraggable = editable || draggableNodeIds?.has(node.id);
892
958
  // When draggableNodeIds is provided, we need to explicitly control each node's draggability
@@ -908,6 +974,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
908
974
  data: {
909
975
  ...node.data,
910
976
  editable,
977
+ pendingText,
911
978
  tooltipsEnabled: showTooltips,
912
979
  shiftKeyPressed,
913
980
  isHighlighted: highlightedNodeId === node.id,
@@ -922,7 +989,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
922
989
  },
923
990
  };
924
991
  });
925
- }, [localNodes, configuration, violations, animationState.nodeAnimations, editable, showTooltips, highlightedNodeId, activeNodeIds, editStateRef, shiftKeyPressed, selectedNodeIds, hiddenNodeIds, draggableNodeIds]);
992
+ }, [localNodes, configuration, violations, animationState.nodeAnimations, editable, showTooltips, highlightedNodeId, activeNodeIds, editStateRef, shiftKeyPressed, selectedNodeIds, hiddenNodeIds, draggableNodeIds, textChangesVersion]);
926
993
  const baseNodesKey = useMemo(() => {
927
994
  return nodes
928
995
  .map((n) => n.id)
@@ -977,6 +1044,22 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
977
1044
  data: { ...n.data, isHidden: hiddenNodeIds.has(n.id) },
978
1045
  })));
979
1046
  }, [editable, hiddenNodeIds]);
1047
+ // Sync pending text changes to local nodes when textChangesVersion changes (edit mode only)
1048
+ const prevTextChangesVersionRef = useRef(textChangesVersion);
1049
+ useEffect(() => {
1050
+ if (!editable)
1051
+ return;
1052
+ if (prevTextChangesVersionRef.current === textChangesVersion)
1053
+ return;
1054
+ prevTextChangesVersionRef.current = textChangesVersion;
1055
+ setXyflowLocalNodes((nodes) => nodes.map((n) => {
1056
+ const pendingText = editStateRef.current.textChanges.get(n.id);
1057
+ return {
1058
+ ...n,
1059
+ data: { ...n.data, pendingText },
1060
+ };
1061
+ }));
1062
+ }, [editable, textChangesVersion]);
980
1063
  // Also sync when entering edit mode or when base nodes change content
981
1064
  const prevEditableRef = useRef(editable);
982
1065
  useEffect(() => {
@@ -1068,6 +1151,25 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
1068
1151
  return { ...prev, dimensionChanges: newDimensions };
1069
1152
  });
1070
1153
  break;
1154
+ case 'text':
1155
+ // Restore previous text
1156
+ // Update edit state
1157
+ updateEditState((prev) => {
1158
+ const newTextChanges = new Map(prev.textChanges);
1159
+ newTextChanges.set(entry.nodeId, entry.before);
1160
+ return { ...prev, textChanges: newTextChanges };
1161
+ });
1162
+ // Force re-render
1163
+ setTextChangesVersion((v) => v + 1);
1164
+ break;
1165
+ case 'nodeDelete':
1166
+ // Restore the deleted node
1167
+ updateEditState((prev) => {
1168
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
1169
+ newDeletedNodeIds.delete(entry.nodeId);
1170
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
1171
+ });
1172
+ break;
1071
1173
  case 'edgeCreate':
1072
1174
  // Remove the created edge
1073
1175
  setLocalEdges((edges) => edges.filter((e) => e.id !== entry.edge.id));
@@ -1121,6 +1223,25 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
1121
1223
  return { ...prev, dimensionChanges: newDimensions };
1122
1224
  });
1123
1225
  break;
1226
+ case 'text':
1227
+ // Apply new text
1228
+ // Update edit state
1229
+ updateEditState((prev) => {
1230
+ const newTextChanges = new Map(prev.textChanges);
1231
+ newTextChanges.set(entry.nodeId, entry.after);
1232
+ return { ...prev, textChanges: newTextChanges };
1233
+ });
1234
+ // Force re-render
1235
+ setTextChangesVersion((v) => v + 1);
1236
+ break;
1237
+ case 'nodeDelete':
1238
+ // Re-delete the node
1239
+ updateEditState((prev) => {
1240
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
1241
+ newDeletedNodeIds.add(entry.nodeId);
1242
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
1243
+ });
1244
+ break;
1124
1245
  case 'edgeCreate':
1125
1246
  // Re-create the edge
1126
1247
  setLocalEdges((edges) => [...edges, entry.edge]);
@@ -1160,7 +1281,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
1160
1281
  }
1161
1282
  }
1162
1283
  }, [redoFromStack, updateEditState]);
1163
- // Keyboard shortcuts for undo/redo
1284
+ // Keyboard shortcuts for undo/redo and delete
1164
1285
  useEffect(() => {
1165
1286
  if (!editable)
1166
1287
  return;
@@ -1181,10 +1302,20 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
1181
1302
  e.preventDefault();
1182
1303
  applyRedo();
1183
1304
  }
1305
+ // Delete or Backspace to delete selected nodes
1306
+ if (e.key === 'Delete' || e.key === 'Backspace') {
1307
+ // Only delete if not editing text (check if active element is an input/textarea)
1308
+ const activeElement = document.activeElement;
1309
+ const isEditingText = activeElement?.tagName === 'INPUT' || activeElement?.tagName === 'TEXTAREA';
1310
+ if (!isEditingText) {
1311
+ e.preventDefault();
1312
+ handleDeleteSelectedNodes();
1313
+ }
1314
+ }
1184
1315
  };
1185
1316
  window.addEventListener('keydown', handleKeyDown);
1186
1317
  return () => window.removeEventListener('keydown', handleKeyDown);
1187
- }, [editable, applyUndo, applyRedo]);
1318
+ }, [editable, applyUndo, applyRedo, handleDeleteSelectedNodes]);
1188
1319
  // Set undo/redo functions in ref for outer component access
1189
1320
  useEffect(() => {
1190
1321
  undoRedoFunctionsRef.current = {
@@ -1443,6 +1574,12 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
1443
1574
  onPendingChangesChange?.(false);
1444
1575
  };
1445
1576
  }, [xyflowNodesBase, xyflowEdgesWithElk, onPendingChangesChange]);
1577
+ // Set the reset text changes version function for use by resetEditState
1578
+ useEffect(() => {
1579
+ resetTextChangesVersionRef.current = () => {
1580
+ setTextChangesVersion(0);
1581
+ };
1582
+ }, []);
1446
1583
  // Use local edges in edit mode, base edges otherwise
1447
1584
  const xyflowEdges = editable ? xyflowLocalEdges : xyflowEdgesWithElk;
1448
1585
  // Handle edge changes (selection, reconnection, etc.)
@@ -1775,6 +1912,8 @@ export const GraphRenderer = forwardRef((props, ref) => {
1775
1912
  const editStateRef = useRef(createEmptyEditState());
1776
1913
  // Ref to hold the reset visual state function - will be set after xyflowLocalNodes is defined
1777
1914
  const resetVisualStateRef = useRef(null);
1915
+ // Ref to hold the reset text changes version function - will be set by inner component
1916
+ const resetTextChangesVersionRef = useRef(null);
1778
1917
  // Undo/redo management
1779
1918
  const { canUndo: canUndoState, canRedo: canRedoState, undo: undoFromStack, redo: redoFromStack, pushHistory, clearHistory, } = useUndoRedo();
1780
1919
  // Ref to hold undo/redo apply functions - will be set by inner component
@@ -1792,6 +1931,10 @@ export const GraphRenderer = forwardRef((props, ref) => {
1792
1931
  nodeId,
1793
1932
  dimensions,
1794
1933
  })),
1934
+ textChanges: Array.from(state.textChanges.entries()).map(([nodeId, text]) => ({
1935
+ nodeId,
1936
+ text,
1937
+ })),
1795
1938
  nodeUpdates: Array.from(state.nodeUpdates.entries()).map(([nodeId, updates]) => ({
1796
1939
  nodeId,
1797
1940
  updates,
@@ -1807,6 +1950,7 @@ export const GraphRenderer = forwardRef((props, ref) => {
1807
1950
  deletedEdges: state.deletedEdges.map((e) => ({ from: e.from, to: e.to, type: e.type })),
1808
1951
  hasChanges: state.positionChanges.size > 0 ||
1809
1952
  state.dimensionChanges.size > 0 ||
1953
+ state.textChanges.size > 0 ||
1810
1954
  state.nodeUpdates.size > 0 ||
1811
1955
  state.deletedNodeIds.size > 0 ||
1812
1956
  state.createdEdges.length > 0 ||
@@ -1815,6 +1959,8 @@ export const GraphRenderer = forwardRef((props, ref) => {
1815
1959
  },
1816
1960
  resetEditState: () => {
1817
1961
  editStateRef.current = createEmptyEditState();
1962
+ // Reset text changes version to trigger re-render
1963
+ resetTextChangesVersionRef.current?.();
1818
1964
  // Also reset visual state (node positions/dimensions) if available
1819
1965
  resetVisualStateRef.current?.();
1820
1966
  // Clear undo/redo history
@@ -1824,6 +1970,7 @@ export const GraphRenderer = forwardRef((props, ref) => {
1824
1970
  const state = editStateRef.current;
1825
1971
  return (state.positionChanges.size > 0 ||
1826
1972
  state.dimensionChanges.size > 0 ||
1973
+ state.textChanges.size > 0 ||
1827
1974
  state.nodeUpdates.size > 0 ||
1828
1975
  state.deletedNodeIds.size > 0 ||
1829
1976
  state.createdEdges.length > 0 ||
@@ -1855,7 +2002,7 @@ export const GraphRenderer = forwardRef((props, ref) => {
1855
2002
  if (isWaitingForViewport) {
1856
2003
  return (_jsx("div", { ref: containerRef, className: className, style: { width, height, position: 'relative' } }));
1857
2004
  }
1858
- return (_jsx("div", { ref: containerRef, className: className, style: { width, height, position: 'relative' }, children: _jsx(TooltipPortalContext.Provider, { value: portalTarget, children: _jsx(ReactFlowProvider, { children: _jsx(GraphRendererInner, { configuration: configuration, nodes: nodes, edges: edges, violations: violations, configName: configName, showMinimap: showMinimap, showControls: showControls, showBackground: showBackground, backgroundVariant: backgroundVariant, backgroundGap: backgroundGap, showCenterIndicator: showCenterIndicator, showTooltips: showTooltips, fitViewDuration: fitViewDuration, highlightedNodeId: highlightedNodeId, activeNodeIds: activeNodeIds, events: events, onEventProcessed: onEventProcessed, editable: editable, onPendingChangesChange: onPendingChangesChange, editStateRef: editStateRef, resetVisualStateRef: resetVisualStateRef, undoRedoFunctionsRef: undoRedoFunctionsRef, pushHistory: pushHistory, clearHistory: clearHistory, undoFromStack: undoFromStack, redoFromStack: redoFromStack, onNodeClick: onNodeClick, fitViewToNodeIds: fitViewToNodeIds, fitViewPadding: fitViewPadding, draggableNodeIds: draggableNodeIds, onNodeDragStop: onNodeDragStop, onCopy: onCopy, initialViewport: initialViewport, elkLayout: elkLayout, scenarioEdges: scenarioEdges, showSequenceLabels: showSequenceLabels }) }) }) }));
2005
+ return (_jsx("div", { ref: containerRef, className: className, style: { width, height, position: 'relative' }, children: _jsx(TooltipPortalContext.Provider, { value: portalTarget, children: _jsx(ReactFlowProvider, { children: _jsx(GraphRendererInner, { configuration: configuration, nodes: nodes, edges: edges, violations: violations, configName: configName, showMinimap: showMinimap, showControls: showControls, showBackground: showBackground, backgroundVariant: backgroundVariant, backgroundGap: backgroundGap, showCenterIndicator: showCenterIndicator, showTooltips: showTooltips, fitViewDuration: fitViewDuration, highlightedNodeId: highlightedNodeId, activeNodeIds: activeNodeIds, events: events, onEventProcessed: onEventProcessed, editable: editable, onPendingChangesChange: onPendingChangesChange, editStateRef: editStateRef, resetVisualStateRef: resetVisualStateRef, resetTextChangesVersionRef: resetTextChangesVersionRef, undoRedoFunctionsRef: undoRedoFunctionsRef, pushHistory: pushHistory, clearHistory: clearHistory, undoFromStack: undoFromStack, redoFromStack: redoFromStack, onNodeClick: onNodeClick, fitViewToNodeIds: fitViewToNodeIds, fitViewPadding: fitViewPadding, draggableNodeIds: draggableNodeIds, onNodeDragStop: onNodeDragStop, onCopy: onCopy, initialViewport: initialViewport, elkLayout: elkLayout, scenarioEdges: scenarioEdges, showSequenceLabels: showSequenceLabels }) }) }) }));
1859
2006
  });
1860
2007
  GraphRenderer.displayName = 'GraphRenderer';
1861
2008
  //# sourceMappingURL=GraphRenderer.js.map