@industry-theme/principal-view-panels 0.12.45 → 0.12.47

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.
@@ -1 +1 @@
1
- {"version":3,"file":"TraceListPanel.d.ts","sourceRoot":"","sources":["../../src/panels/TraceListPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,KAAK,EAAE,wBAAwB,EAAwB,MAAM,UAAU,CAAC;AAkB/E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAqjD7D,CAAC"}
1
+ {"version":3,"file":"TraceListPanel.d.ts","sourceRoot":"","sources":["../../src/panels/TraceListPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,KAAK,EAAE,wBAAwB,EAAwB,MAAM,UAAU,CAAC;AAmB/E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAujD7D,CAAC"}
@@ -86441,6 +86441,11 @@ const NodeTooltip = ({ description, otel, sources, references, visible, nodeRef
86441
86441
  }
86442
86442
  return renderTooltipContent();
86443
86443
  };
86444
+ const GraphEditContext = createContext({});
86445
+ const GraphEditProvider = ({ children: children2, value }) => {
86446
+ return jsx(GraphEditContext.Provider, { value, children: children2 });
86447
+ };
86448
+ const useGraphEdit = () => useContext(GraphEditContext);
86444
86449
  function hexToLightColor(hexColor, lightness = 0.88) {
86445
86450
  const hex2 = hexColor.replace("#", "");
86446
86451
  const r2 = parseInt(hex2.substring(0, 2), 16);
@@ -86455,6 +86460,8 @@ function hexToLightColor(hexColor, lightness = 0.88) {
86455
86460
  const CustomNode = ({ data, selected: selected2, dragging }) => {
86456
86461
  var _a, _b, _c, _d, _e2, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
86457
86462
  const { theme: theme2 } = useTheme();
86463
+ const { onNodeResizeEnd } = useGraphEdit();
86464
+ const nodeId = useNodeId();
86458
86465
  const [isHovered, setIsHovered] = useState(false);
86459
86466
  const nodeRef = useRef(null);
86460
86467
  const nodeProps = data;
@@ -86475,6 +86482,14 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
86475
86482
  // Default to not hidden
86476
86483
  } = nodeProps;
86477
86484
  const nodeOpacity = isHidden ? 0.4 : isActive ? 1 : 0.1;
86485
+ const handleResizeEnd = useCallback((_event, params) => {
86486
+ if (nodeId && onNodeResizeEnd && params.width && params.height) {
86487
+ onNodeResizeEnd(nodeId, {
86488
+ width: Math.round(params.width),
86489
+ height: Math.round(params.height)
86490
+ });
86491
+ }
86492
+ }, [nodeId, onNodeResizeEnd]);
86478
86493
  console.log("[CustomNode] Node data:", {
86479
86494
  name: nodeProps.name,
86480
86495
  nodeDataKeys: nodeData ? Object.keys(nodeData).join(", ") : "undefined",
@@ -86695,12 +86710,16 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
86695
86710
  const eventData = nodeData == null ? void 0 : nodeData.event;
86696
86711
  const eventName = eventData == null ? void 0 : eventData.name;
86697
86712
  const showEventName = eventName && eventName !== displayName;
86713
+ const renderWithDotBreaks = (text2) => {
86714
+ const parts = text2.split(".");
86715
+ return parts.map((part, i) => jsxs("span", { children: [part, i < parts.length - 1 && jsxs(Fragment, { children: [".", jsx("wbr", {})] })] }, i));
86716
+ };
86698
86717
  const renderNameWithEvent = (centered = true) => jsxs("div", { style: { textAlign: centered ? "center" : "left", wordBreak: "break-word" }, children: [jsx("div", { children: displayName }), showEventName && jsx("div", { style: {
86699
86718
  fontSize: theme2.fontSizes[0] * 0.75,
86700
86719
  color: "rgba(0, 0, 0, 0.5)",
86701
86720
  marginTop: "2px",
86702
86721
  fontFamily: theme2.fonts.monospace
86703
- }, children: eventName })] });
86722
+ }, children: renderWithDotBreaks(eventName) })] });
86704
86723
  const icon = nodeData.icon || state && (((_e2 = nodeDataStates == null ? void 0 : nodeDataStates[state]) == null ? void 0 : _e2.icon) || ((_g = (_f = typeDefinition.states) == null ? void 0 : _f[state]) == null ? void 0 : _g.icon)) || typeDefinition.icon;
86705
86724
  const getAnimationClass = () => {
86706
86725
  switch (animationType) {
@@ -86884,7 +86903,7 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
86884
86903
  }
86885
86904
  return offsetStyle;
86886
86905
  };
86887
- return jsxs(Fragment, { children: [editable && jsx(NodeResizer, { color: strokeColor, isVisible: selected2, minWidth, minHeight, keepAspectRatio, handleStyle: {
86906
+ return jsxs(Fragment, { children: [editable && jsx(NodeResizer, { color: strokeColor, isVisible: selected2, minWidth, minHeight, keepAspectRatio, onResizeEnd: handleResizeEnd, handleStyle: {
86888
86907
  width: 8,
86889
86908
  height: 8,
86890
86909
  borderRadius: 2,
@@ -87298,6 +87317,56 @@ function convertToXYFlowEdges(edges, configuration, violations = []) {
87298
87317
  };
87299
87318
  });
87300
87319
  }
87320
+ const MAX_HISTORY_SIZE = 50;
87321
+ function useUndoRedo() {
87322
+ const undoStackRef = useRef([]);
87323
+ const redoStackRef = useRef([]);
87324
+ const [canUndo, setCanUndo] = useState(false);
87325
+ const [canRedo, setCanRedo] = useState(false);
87326
+ const updateCanStates = useCallback(() => {
87327
+ setCanUndo(undoStackRef.current.length > 0);
87328
+ setCanRedo(redoStackRef.current.length > 0);
87329
+ }, []);
87330
+ const pushHistory = useCallback((entries) => {
87331
+ if (entries.length === 0)
87332
+ return;
87333
+ undoStackRef.current.push(entries);
87334
+ if (undoStackRef.current.length > MAX_HISTORY_SIZE) {
87335
+ undoStackRef.current.shift();
87336
+ }
87337
+ redoStackRef.current = [];
87338
+ updateCanStates();
87339
+ }, [updateCanStates]);
87340
+ const undo = useCallback(() => {
87341
+ const batch = undoStackRef.current.pop();
87342
+ if (!batch)
87343
+ return null;
87344
+ redoStackRef.current.push(batch);
87345
+ updateCanStates();
87346
+ return batch;
87347
+ }, [updateCanStates]);
87348
+ const redo = useCallback(() => {
87349
+ const batch = redoStackRef.current.pop();
87350
+ if (!batch)
87351
+ return null;
87352
+ undoStackRef.current.push(batch);
87353
+ updateCanStates();
87354
+ return batch;
87355
+ }, [updateCanStates]);
87356
+ const clearHistory = useCallback(() => {
87357
+ undoStackRef.current = [];
87358
+ redoStackRef.current = [];
87359
+ updateCanStates();
87360
+ }, [updateCanStates]);
87361
+ return {
87362
+ canUndo,
87363
+ canRedo,
87364
+ undo,
87365
+ redo,
87366
+ pushHistory,
87367
+ clearHistory
87368
+ };
87369
+ }
87301
87370
  const TooltipPortalContext = createContext(null);
87302
87371
  const nodeTypes = { custom: CustomNode };
87303
87372
  const edgeTypes = { custom: CustomEdge };
@@ -87347,7 +87416,7 @@ const CenterIndicator = ({ color: color2 }) => {
87347
87416
  zIndex: 5
87348
87417
  }, children: [jsx("line", { x1: screenX, y1: screenY - size, x2: screenX, y2: screenY + size, stroke: color2, strokeWidth, opacity: 0.7 }), jsx("line", { x1: screenX - size, y1: screenY, x2: screenX + size, y2: screenY, stroke: color2, strokeWidth, opacity: 0.7 }), jsx("circle", { cx: screenX, cy: screenY, r: 3, fill: color2, opacity: 0.7 })] });
87349
87418
  };
87350
- 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, onNodeClick: onNodeClickProp, fitViewToNodeIds, fitViewPadding = 0.2, draggableNodeIds, onNodeDragStop: onNodeDragStopProp, onCopy }) => {
87419
+ 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 }) => {
87351
87420
  const { fitView: fitView2, fitBounds, getNodes } = useReactFlow();
87352
87421
  const updateNodeInternals2 = useUpdateNodeInternals();
87353
87422
  const { theme: theme2 } = useTheme();
@@ -87418,6 +87487,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87418
87487
  onEditStateChange == null ? void 0 : onEditStateChange(editStateRef.current);
87419
87488
  onPendingChangesChange == null ? void 0 : onPendingChangesChange(false);
87420
87489
  setAnimationState({ nodeAnimations: {}, edgeAnimations: {} });
87490
+ clearHistory();
87421
87491
  }
87422
87492
  }, [propNodes, propEdges, editStateRef, onEditStateChange, onPendingChangesChange]);
87423
87493
  const propNodesRef = useRef(propNodes);
@@ -87431,6 +87501,8 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87431
87501
  }, [propNodes, draggableNodeIds]);
87432
87502
  const nodes = localNodes;
87433
87503
  const edges = editable ? localEdges : propEdges;
87504
+ const xyflowNodesRef = useRef([]);
87505
+ const dragStartPositionsRef = useRef(/* @__PURE__ */ new Map());
87434
87506
  const checkHasChanges = useCallback((state) => {
87435
87507
  return state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0;
87436
87508
  }, []);
@@ -87441,6 +87513,28 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87441
87513
  onEditStateChange == null ? void 0 : onEditStateChange(newState);
87442
87514
  onPendingChangesChange == null ? void 0 : onPendingChangesChange(hasChanges);
87443
87515
  }, [editStateRef, onEditStateChange, onPendingChangesChange, checkHasChanges]);
87516
+ const handleNodeResizeEnd = useCallback((nodeId, dimensions) => {
87517
+ if (!editable)
87518
+ return;
87519
+ const currentNode = xyflowNodesRef.current.find((n) => n.id === nodeId);
87520
+ const beforeDimensions = currentNode ? { width: currentNode.width ?? 0, height: currentNode.height ?? 0 } : { width: 0, height: 0 };
87521
+ pushHistory([
87522
+ {
87523
+ type: "dimension",
87524
+ nodeId,
87525
+ before: beforeDimensions,
87526
+ after: dimensions
87527
+ }
87528
+ ]);
87529
+ updateEditState((prev) => {
87530
+ const newDimensions = new Map(prev.dimensionChanges);
87531
+ newDimensions.set(nodeId, dimensions);
87532
+ return { ...prev, dimensionChanges: newDimensions };
87533
+ });
87534
+ }, [editable, updateEditState, pushHistory]);
87535
+ const graphEditContextValue = useMemo(() => ({
87536
+ onNodeResizeEnd: handleNodeResizeEnd
87537
+ }), [handleNodeResizeEnd]);
87444
87538
  const detectAlignmentGuides = useCallback((draggingNodeId, nodes2) => {
87445
87539
  const threshold = 5;
87446
87540
  const guides = [];
@@ -87633,18 +87727,25 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87633
87727
  }, [editable]);
87634
87728
  const createEdge = useCallback((from, to, type2, sourceHandle, targetHandle) => {
87635
87729
  const edgeId = `${from}-${to}-${type2}-${Date.now()}`;
87730
+ const now2 = Date.now();
87636
87731
  const newEdge = {
87637
87732
  id: edgeId,
87638
87733
  type: type2,
87639
87734
  from,
87640
87735
  to,
87641
87736
  data: {},
87642
- createdAt: Date.now(),
87643
- updatedAt: Date.now(),
87737
+ createdAt: now2,
87738
+ updatedAt: now2,
87644
87739
  sourceHandle,
87645
87740
  targetHandle
87646
87741
  };
87647
87742
  setLocalEdges((prev) => [...prev, newEdge]);
87743
+ pushHistory([
87744
+ {
87745
+ type: "edgeCreate",
87746
+ edge: newEdge
87747
+ }
87748
+ ]);
87648
87749
  updateEditState((prev) => ({
87649
87750
  ...prev,
87650
87751
  createdEdges: [
@@ -87652,7 +87753,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87652
87753
  { id: edgeId, from, to, type: type2, sourceHandle, targetHandle }
87653
87754
  ]
87654
87755
  }));
87655
- }, [updateEditState]);
87756
+ }, [updateEditState, pushHistory]);
87656
87757
  const handleConnect = useCallback((connection) => {
87657
87758
  if (!editable || !connection.source || !connection.target)
87658
87759
  return;
@@ -87918,6 +88019,9 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87918
88019
  return edges.map((e) => e.id).sort().join(",");
87919
88020
  }, [edges]);
87920
88021
  const [xyflowLocalNodes, setXyflowLocalNodes] = useState(xyflowNodesBase);
88022
+ useEffect(() => {
88023
+ xyflowNodesRef.current = xyflowLocalNodes;
88024
+ }, [xyflowLocalNodes]);
87921
88025
  const prevBaseNodesKeyRef = useRef(baseNodesKey);
87922
88026
  useEffect(() => {
87923
88027
  if (prevBaseNodesKeyRef.current !== baseNodesKey) {
@@ -87979,6 +88083,128 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
87979
88083
  onNodeDragStopProp(node2.id, node2.position);
87980
88084
  }
87981
88085
  }, [onNodeDragStopProp]);
88086
+ const applyUndo = useCallback(() => {
88087
+ const batch = undoFromStack();
88088
+ if (!batch)
88089
+ return;
88090
+ for (const entry of batch.slice().reverse()) {
88091
+ switch (entry.type) {
88092
+ case "position":
88093
+ setXyflowLocalNodes((nodes2) => nodes2.map((n) => n.id === entry.nodeId ? { ...n, position: entry.before } : n));
88094
+ updateEditState((prev) => {
88095
+ const newPositions = new Map(prev.positionChanges);
88096
+ newPositions.set(entry.nodeId, entry.before);
88097
+ return { ...prev, positionChanges: newPositions };
88098
+ });
88099
+ break;
88100
+ case "dimension":
88101
+ setXyflowLocalNodes((nodes2) => nodes2.map((n) => n.id === entry.nodeId ? { ...n, width: entry.before.width, height: entry.before.height } : n));
88102
+ updateEditState((prev) => {
88103
+ const newDimensions = new Map(prev.dimensionChanges);
88104
+ newDimensions.set(entry.nodeId, entry.before);
88105
+ return { ...prev, dimensionChanges: newDimensions };
88106
+ });
88107
+ break;
88108
+ case "edgeCreate":
88109
+ setLocalEdges((edges2) => edges2.filter((e) => e.id !== entry.edge.id));
88110
+ updateEditState((prev) => ({
88111
+ ...prev,
88112
+ createdEdges: prev.createdEdges.filter((e) => e.id !== entry.edge.id)
88113
+ }));
88114
+ break;
88115
+ case "edgeDelete":
88116
+ setLocalEdges((edges2) => [...edges2, entry.edge]);
88117
+ updateEditState((prev) => ({
88118
+ ...prev,
88119
+ deletedEdges: prev.deletedEdges.filter((e) => e.id !== entry.edge.id)
88120
+ }));
88121
+ break;
88122
+ }
88123
+ }
88124
+ }, [undoFromStack, updateEditState]);
88125
+ const applyRedo = useCallback(() => {
88126
+ const batch = redoFromStack();
88127
+ if (!batch)
88128
+ return;
88129
+ for (const entry of batch) {
88130
+ switch (entry.type) {
88131
+ case "position":
88132
+ setXyflowLocalNodes((nodes2) => nodes2.map((n) => n.id === entry.nodeId ? { ...n, position: entry.after } : n));
88133
+ updateEditState((prev) => {
88134
+ const newPositions = new Map(prev.positionChanges);
88135
+ newPositions.set(entry.nodeId, entry.after);
88136
+ return { ...prev, positionChanges: newPositions };
88137
+ });
88138
+ break;
88139
+ case "dimension":
88140
+ setXyflowLocalNodes((nodes2) => nodes2.map((n) => n.id === entry.nodeId ? { ...n, width: entry.after.width, height: entry.after.height } : n));
88141
+ updateEditState((prev) => {
88142
+ const newDimensions = new Map(prev.dimensionChanges);
88143
+ newDimensions.set(entry.nodeId, entry.after);
88144
+ return { ...prev, dimensionChanges: newDimensions };
88145
+ });
88146
+ break;
88147
+ case "edgeCreate":
88148
+ setLocalEdges((edges2) => [...edges2, entry.edge]);
88149
+ updateEditState((prev) => ({
88150
+ ...prev,
88151
+ createdEdges: [
88152
+ ...prev.createdEdges,
88153
+ {
88154
+ id: entry.edge.id,
88155
+ from: entry.edge.from,
88156
+ to: entry.edge.to,
88157
+ type: entry.edge.type,
88158
+ sourceHandle: entry.edge.sourceHandle,
88159
+ targetHandle: entry.edge.targetHandle
88160
+ }
88161
+ ]
88162
+ }));
88163
+ break;
88164
+ case "edgeDelete":
88165
+ setLocalEdges((edges2) => edges2.filter((e) => e.id !== entry.edge.id));
88166
+ updateEditState((prev) => ({
88167
+ ...prev,
88168
+ deletedEdges: [
88169
+ ...prev.deletedEdges,
88170
+ {
88171
+ id: entry.edge.id,
88172
+ from: entry.edge.from,
88173
+ to: entry.edge.to,
88174
+ type: entry.edge.type
88175
+ }
88176
+ ]
88177
+ }));
88178
+ break;
88179
+ }
88180
+ }
88181
+ }, [redoFromStack, updateEditState]);
88182
+ useEffect(() => {
88183
+ if (!editable)
88184
+ return;
88185
+ const handleKeyDown = (e) => {
88186
+ if ((e.metaKey || e.ctrlKey) && e.key === "z") {
88187
+ e.preventDefault();
88188
+ if (e.shiftKey) {
88189
+ applyRedo();
88190
+ } else {
88191
+ applyUndo();
88192
+ }
88193
+ }
88194
+ if (e.ctrlKey && e.key === "y") {
88195
+ e.preventDefault();
88196
+ applyRedo();
88197
+ }
88198
+ };
88199
+ window.addEventListener("keydown", handleKeyDown);
88200
+ return () => window.removeEventListener("keydown", handleKeyDown);
88201
+ }, [editable, applyUndo, applyRedo]);
88202
+ useEffect(() => {
88203
+ undoRedoFunctionsRef.current = {
88204
+ applyUndo,
88205
+ applyRedo
88206
+ };
88207
+ }, [applyUndo, applyRedo, undoRedoFunctionsRef]);
87982
88208
  const handleNodesChange = useCallback((changes) => {
87983
88209
  const hasDraggableNodes2 = draggableNodeIds && draggableNodeIds.size > 0;
87984
88210
  if (!editable && !hasDraggableNodes2)
@@ -88023,23 +88249,35 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
88023
88249
  }));
88024
88250
  });
88025
88251
  }
88026
- const positionChanges = changes.filter((change) => change.type === "position" && "position" in change && change.position !== void 0 && "dragging" in change && change.dragging === false);
88027
- const dimensionChanges = changes.filter((change) => change.type === "dimensions" && "dimensions" in change && change.dimensions !== void 0 && "resizing" in change && change.resizing === false);
88028
- if (dimensionChanges.length > 0) {
88029
- updateEditState((prev) => {
88030
- const newDimensions = new Map(prev.dimensionChanges);
88031
- for (const change of dimensionChanges) {
88032
- if (change.dimensions) {
88033
- newDimensions.set(change.id, {
88034
- width: Math.round(change.dimensions.width),
88035
- height: Math.round(change.dimensions.height)
88036
- });
88037
- }
88252
+ const dragStartChanges = changes.filter((change) => change.type === "position" && "id" in change && "dragging" in change && change.dragging === true);
88253
+ for (const change of dragStartChanges) {
88254
+ if (!dragStartPositionsRef.current.has(change.id)) {
88255
+ const currentNode = xyflowNodesRef.current.find((n) => n.id === change.id);
88256
+ if (currentNode) {
88257
+ dragStartPositionsRef.current.set(change.id, {
88258
+ x: currentNode.position.x,
88259
+ y: currentNode.position.y
88260
+ });
88038
88261
  }
88039
- return { ...prev, dimensionChanges: newDimensions };
88040
- });
88262
+ }
88041
88263
  }
88264
+ const positionChanges = changes.filter((change) => change.type === "position" && "id" in change && "position" in change && change.position !== void 0 && "dragging" in change && change.dragging === false);
88042
88265
  if (positionChanges.length > 0) {
88266
+ const historyEntries = [];
88267
+ for (const change of positionChanges) {
88268
+ const beforePos = dragStartPositionsRef.current.get(change.id) ?? { x: 0, y: 0 };
88269
+ historyEntries.push({
88270
+ type: "position",
88271
+ nodeId: change.id,
88272
+ before: beforePos,
88273
+ after: {
88274
+ x: Math.round(change.position.x),
88275
+ y: Math.round(change.position.y)
88276
+ }
88277
+ });
88278
+ dragStartPositionsRef.current.delete(change.id);
88279
+ }
88280
+ pushHistory(historyEntries);
88043
88281
  updateEditState((prev) => {
88044
88282
  const newPositions = new Map(prev.positionChanges);
88045
88283
  for (const change of positionChanges) {
@@ -88051,7 +88289,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
88051
88289
  return { ...prev, positionChanges: newPositions };
88052
88290
  });
88053
88291
  }
88054
- }, [editable, updateEditState, selectedNodeIds, draggableNodeIds]);
88292
+ }, [editable, updateEditState, selectedNodeIds, draggableNodeIds, pushHistory]);
88055
88293
  const xyflowEdgesBase = useMemo(() => {
88056
88294
  const converted = convertToXYFlowEdges(edges, configuration, violations);
88057
88295
  const filtered = converted.filter((edge) => {
@@ -88104,6 +88342,13 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
88104
88342
  setXyflowLocalEdges(xyflowEdgesBase);
88105
88343
  }
88106
88344
  }, [baseEdgesKey, xyflowEdgesBase]);
88345
+ useEffect(() => {
88346
+ resetVisualStateRef.current = () => {
88347
+ setXyflowLocalNodes(xyflowNodesBase);
88348
+ setXyflowLocalEdges(xyflowEdgesBase);
88349
+ onPendingChangesChange == null ? void 0 : onPendingChangesChange(false);
88350
+ };
88351
+ }, [xyflowNodesBase, xyflowEdgesBase, onPendingChangesChange]);
88107
88352
  const xyflowEdges = editable ? xyflowLocalEdges : xyflowEdgesBase;
88108
88353
  const handleEdgesChange = useCallback((changes) => {
88109
88354
  if (!editable)
@@ -88159,7 +88404,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
88159
88404
  }, 150);
88160
88405
  return () => clearTimeout(timeoutId);
88161
88406
  }, [fitViewToNodeIdsKey, fitViewToNodeIds, fitViewPadding, fitView2, fitViewDuration, getNodes, fitBounds]);
88162
- return jsxs(Fragment, { children: [jsxs(index$2, { nodes: xyflowNodes, edges: xyflowEdges, nodeTypes, edgeTypes, minZoom: 0.1, maxZoom: 4, defaultEdgeOptions: { type: "custom" }, onEdgeClick, onNodeClick, onNodeDoubleClick, onNodeDrag: handleNodeDrag, onNodeDragStop: handleNodeDragStop, proOptions: { hideAttribution: true }, nodesDraggable: editable || draggableNodeIds && draggableNodeIds.size > 0, elementsSelectable: editable, selectNodesOnDrag: false, nodesConnectable: editable, edgesReconnectable: editable, reconnectRadius: 25, elevateEdgesOnSelect: true, onNodesChange: handleNodesChange, onEdgesChange: handleEdgesChange, onConnect: handleConnect, onReconnectStart: handleReconnectStart, onReconnect: handleReconnect, onReconnectEnd: handleReconnectEnd, onPaneClick, onSelectionChange: handleSelectionChange, panOnDrag: !editable, panOnScroll: true, zoomOnScroll: false, zoomOnPinch: true, zoomOnDoubleClick: false, selectionOnDrag: false, selectionKeyCode: null, multiSelectionKeyCode: "Shift", children: [showBackground && jsx(Background, { color: backgroundVariant === "dots" ? theme2.colors.border : theme2.colors.textMuted, gap: backgroundGap ?? (backgroundVariant === "dots" ? 16 : 50), size: backgroundVariant === "dots" ? 1 : 0.5, variant: backgroundVariant === "dots" ? BackgroundVariant.Dots : backgroundVariant === "lines" ? BackgroundVariant.Lines : BackgroundVariant.Cross }), showControls && jsx(Controls, { showZoom: true, showFitView: true, showInteractive: true }), showMinimap && jsx(MiniMap, { nodeColor: (node2) => {
88407
+ return jsxs(GraphEditProvider, { value: graphEditContextValue, children: [jsxs(index$2, { nodes: xyflowNodes, edges: xyflowEdges, nodeTypes, edgeTypes, minZoom: 0.1, maxZoom: 4, defaultEdgeOptions: { type: "custom" }, onEdgeClick, onNodeClick, onNodeDoubleClick, onNodeDrag: handleNodeDrag, onNodeDragStop: handleNodeDragStop, proOptions: { hideAttribution: true }, nodesDraggable: editable || draggableNodeIds && draggableNodeIds.size > 0, elementsSelectable: editable, selectNodesOnDrag: false, nodesConnectable: editable, edgesReconnectable: editable, reconnectRadius: 25, elevateEdgesOnSelect: true, onNodesChange: handleNodesChange, onEdgesChange: handleEdgesChange, onConnect: handleConnect, onReconnectStart: handleReconnectStart, onReconnect: handleReconnect, onReconnectEnd: handleReconnectEnd, onPaneClick, onSelectionChange: handleSelectionChange, panOnDrag: !editable, panOnScroll: true, zoomOnScroll: false, zoomOnPinch: true, zoomOnDoubleClick: false, selectionOnDrag: false, selectionKeyCode: null, multiSelectionKeyCode: "Shift", children: [showBackground && jsx(Background, { color: backgroundVariant === "dots" ? theme2.colors.border : theme2.colors.textMuted, gap: backgroundGap ?? (backgroundVariant === "dots" ? 16 : 50), size: backgroundVariant === "dots" ? 1 : 0.5, variant: backgroundVariant === "dots" ? BackgroundVariant.Dots : backgroundVariant === "lines" ? BackgroundVariant.Lines : BackgroundVariant.Cross }), showControls && jsx(Controls, { showZoom: true, showFitView: true, showInteractive: true }), showMinimap && jsx(MiniMap, { nodeColor: (node2) => {
88163
88408
  var _a;
88164
88409
  const nodeData = node2.data;
88165
88410
  return ((_a = nodeData == null ? void 0 : nodeData.typeDefinition) == null ? void 0 : _a.color) || theme2.colors.secondary;
@@ -88329,6 +88574,9 @@ const GraphRenderer = forwardRef((props2, ref) => {
88329
88574
  }, []);
88330
88575
  const canvasData = useCanvasToLegacy(canvas, library);
88331
88576
  const editStateRef = useRef(createEmptyEditState());
88577
+ const resetVisualStateRef = useRef(null);
88578
+ const { canUndo: canUndoState, canRedo: canRedoState, undo: undoFromStack, redo: redoFromStack, pushHistory, clearHistory } = useUndoRedo();
88579
+ const undoRedoFunctionsRef = useRef(null);
88332
88580
  useImperativeHandle(ref, () => ({
88333
88581
  getPendingChanges: () => {
88334
88582
  const state = editStateRef.current;
@@ -88358,13 +88606,26 @@ const GraphRenderer = forwardRef((props2, ref) => {
88358
88606
  };
88359
88607
  },
88360
88608
  resetEditState: () => {
88609
+ var _a;
88361
88610
  editStateRef.current = createEmptyEditState();
88611
+ (_a = resetVisualStateRef.current) == null ? void 0 : _a.call(resetVisualStateRef);
88612
+ clearHistory();
88362
88613
  },
88363
88614
  hasUnsavedChanges: () => {
88364
88615
  const state = editStateRef.current;
88365
88616
  return state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0;
88617
+ },
88618
+ canUndo: () => canUndoState,
88619
+ canRedo: () => canRedoState,
88620
+ undo: () => {
88621
+ var _a;
88622
+ return (_a = undoRedoFunctionsRef.current) == null ? void 0 : _a.applyUndo();
88623
+ },
88624
+ redo: () => {
88625
+ var _a;
88626
+ return (_a = undoRedoFunctionsRef.current) == null ? void 0 : _a.applyRedo();
88366
88627
  }
88367
- }), []);
88628
+ }), [canUndoState, canRedoState, clearHistory]);
88368
88629
  if (!canvasData) {
88369
88630
  return jsx("div", { className, style: {
88370
88631
  width,
@@ -88378,7 +88639,7 @@ const GraphRenderer = forwardRef((props2, ref) => {
88378
88639
  }
88379
88640
  const { configuration, nodes, edges } = canvasData;
88380
88641
  const { violations, configName, showMinimap, showControls, showBackground, backgroundVariant, backgroundGap, showCenterIndicator, showTooltips, fitViewDuration, highlightedNodeId, activeNodeIds, events, onEventProcessed, editable, onPendingChangesChange, onNodeClick, fitViewToNodeIds, fitViewPadding, draggableNodeIds, onNodeDragStop, onCopy } = props2;
88381
- return jsx("div", { ref: containerRef, className, style: { width, height, position: "relative" }, children: jsx(TooltipPortalContext.Provider, { value: portalTarget, children: jsx(ReactFlowProvider, { children: jsx(GraphRendererInner, { configuration, nodes, edges, violations, configName, showMinimap, showControls, showBackground, backgroundVariant, backgroundGap, showCenterIndicator, showTooltips, fitViewDuration, highlightedNodeId, activeNodeIds, events, onEventProcessed, editable, onPendingChangesChange, editStateRef, onNodeClick, fitViewToNodeIds, fitViewPadding, draggableNodeIds, onNodeDragStop, onCopy }) }) }) });
88642
+ return jsx("div", { ref: containerRef, className, style: { width, height, position: "relative" }, children: jsx(TooltipPortalContext.Provider, { value: portalTarget, children: jsx(ReactFlowProvider, { children: jsx(GraphRendererInner, { configuration, nodes, edges, violations, configName, showMinimap, showControls, showBackground, backgroundVariant, backgroundGap, showCenterIndicator, showTooltips, fitViewDuration, highlightedNodeId, activeNodeIds, events, onEventProcessed, editable, onPendingChangesChange, editStateRef, resetVisualStateRef, undoRedoFunctionsRef, pushHistory, clearHistory, undoFromStack, redoFromStack, onNodeClick, fitViewToNodeIds, fitViewPadding, draggableNodeIds, onNodeDragStop, onCopy }) }) }) });
88382
88643
  });
88383
88644
  GraphRenderer.displayName = "GraphRenderer";
88384
88645
  const DEFAULT_NODE_WIDTH = 200;
@@ -102070,10 +102331,11 @@ const TraceListPanel = ({
102070
102331
  const filteredTraces = React__default.useMemo(() => {
102071
102332
  return traces.filter((trace2) => {
102072
102333
  const hasScenarioMatches = trace2.scenarioMatches && trace2.scenarioMatches.length > 0;
102073
- if (traceFilterMode === "known" && !hasScenarioMatches) {
102334
+ const isKnown = isTraceMatched(trace2);
102335
+ if (traceFilterMode === "known" && !isKnown) {
102074
102336
  return false;
102075
102337
  }
102076
- if (traceFilterMode === "unknown" && hasScenarioMatches) {
102338
+ if (traceFilterMode === "unknown" && isKnown) {
102077
102339
  return false;
102078
102340
  }
102079
102341
  if (!hasScenarioMatches) {