@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.
- package/dist/components/GraphRenderer.d.ts +7 -0
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +154 -7
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/contexts/GraphEditContext.d.ts +2 -0
- package/dist/contexts/GraphEditContext.d.ts.map +1 -1
- package/dist/contexts/GraphEditContext.js.map +1 -1
- package/dist/hooks/useUndoRedo.d.ts +5 -0
- package/dist/hooks/useUndoRedo.d.ts.map +1 -1
- package/dist/hooks/useUndoRedo.js.map +1 -1
- package/dist/nodes/CustomNode.d.ts +1 -0
- package/dist/nodes/CustomNode.d.ts.map +1 -1
- package/dist/nodes/CustomNode.js +84 -6
- package/dist/nodes/CustomNode.js.map +1 -1
- package/package.json +1 -1
- package/src/components/GraphRenderer.tsx +187 -5
- package/src/contexts/GraphEditContext.tsx +2 -0
- package/src/hooks/useUndoRedo.ts +6 -0
- package/src/nodes/CustomNode.tsx +111 -4
|
@@ -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":"AAAA,OAAO,KASN,MAAM,OAAO,CAAC;AAsBf,OAAO,KAAK,EAIV,SAAS,EACT,UAAU,EAIV,cAAc,EACd,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;AA2B3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAGxE,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,wDAAwD;AACxD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wDAAwD;AACxD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,6CAA6C;IAC7C,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IACxC,wCAAwC;IACxC,WAAW,EAAE,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAC;KAC5D,CAAC,CAAC;IACH,uBAAuB;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0EAA0E;IAC1E,YAAY,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,mEAAmE;IACnE,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,oCAAoC;IACpC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,iBAAiB,EAAE,MAAM,cAAc,CAAC;IACxC,8CAA8C;IAC9C,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,OAAO,CAAC;IACjC,mDAAmD;IACnD,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,mDAAmD;IACnD,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,kCAAkC;IAClC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,4CAA4C;AAC5C,UAAU,sBAAsB;IAC9B,uCAAuC;IACvC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAEzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEhC,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,iCAAiC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAE/C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,sDAAsD;IACtD,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAE/C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvD;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAEhE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEnC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE/B;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAE9E;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAE7C;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,SAAS,CAAC,EAAE;QACV;;;WAGG;QACH,OAAO,EAAE,OAAO,CAAC;QACjB;;;;;WAKG;QACH,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;QACrD;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB;;;WAGG;QACH,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC,CAAC;IAEH;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAE9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,+BAA+B;IAC/B,MAAM,EAAE,cAAc,CAAC;IAEvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAE7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC;IAE9B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;
|
|
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
|
-
|
|
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
|