@industry-theme/principal-view-panels 0.12.117 → 0.12.118

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":"CanvasEditorPanel.d.ts","sourceRoot":"","sources":["../../src/panels/CanvasEditorPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAI5D,OAAO,KAAK,EAAqD,gBAAgB,EAAgF,MAAM,mCAAmC,CAAC;AAE3M,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAKxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAuDrE;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,2BAA2B;IACzE;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAE3C;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;OAEG;IACH,gBAAgB,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEnC;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;IAEH;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;;;OAIG;IACH,aAAa,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAuzE9D,CAAC"}
1
+ {"version":3,"file":"CanvasEditorPanel.d.ts","sourceRoot":"","sources":["../../src/panels/CanvasEditorPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAI5D,OAAO,KAAK,EAAqD,gBAAgB,EAAgF,MAAM,mCAAmC,CAAC;AAE3M,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAKxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAwDrE;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,2BAA2B;IACzE;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAE3C;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;OAEG;IACH,gBAAgB,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEnC;;;OAGG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;IAEH;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnC;;;;OAIG;IACH,aAAa,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAE1B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAixE9D,CAAC"}
@@ -87212,10 +87212,13 @@ const CustomNode = (props) => {
87212
87212
  return jsx(OtelBoundaryNode, { ...props });
87213
87213
  }
87214
87214
  const { theme: theme2 } = useTheme();
87215
- const { onNodeResizeEnd, onToggleNodeHidden, onHideUnconnectedNodes } = useGraphEdit();
87215
+ const { onNodeResizeEnd, onNodeTextChange, onToggleNodeHidden, onHideUnconnectedNodes } = useGraphEdit();
87216
87216
  const nodeId = useNodeId();
87217
87217
  const [isHovered, setIsHovered] = useState(false);
87218
+ const [isEditing, setIsEditing] = useState(false);
87219
+ const [editingText, setEditingText] = useState("");
87218
87220
  const nodeRef = useRef(null);
87221
+ const textareaRef = useRef(null);
87219
87222
  const nodeProps = data;
87220
87223
  const {
87221
87224
  typeDefinition,
@@ -87463,7 +87466,7 @@ const CustomNode = (props) => {
87463
87466
  const status = nodeData == null ? void 0 : nodeData.status;
87464
87467
  const strokeColor = baseStrokeColor;
87465
87468
  const color2 = fillColor;
87466
- const displayName = nodeProps.name;
87469
+ const displayName = nodeProps.pendingText ?? nodeProps.name;
87467
87470
  const eventData = nodeData == null ? void 0 : nodeData.event;
87468
87471
  const otelData = nodeData == null ? void 0 : nodeData.otel;
87469
87472
  const boundaryData = nodeData == null ? void 0 : nodeData.boundary;
@@ -87516,6 +87519,42 @@ const CustomNode = (props) => {
87516
87519
  };
87517
87520
  const animationClass = getAnimationClass();
87518
87521
  const isGroup = nodeData.canvasType === "group";
87522
+ const isTextNode = nodeData.canvasType === "text";
87523
+ const isInlineEditable = (isGroup || isTextNode) && editable;
87524
+ const lastClickTimeRef = useRef(0);
87525
+ const handleNodeDoubleClick = useCallback((event) => {
87526
+ if (!isInlineEditable || !nodeId || !onNodeTextChange)
87527
+ return;
87528
+ event.stopPropagation();
87529
+ event.preventDefault();
87530
+ setEditingText(displayName || "");
87531
+ setIsEditing(true);
87532
+ setTimeout(() => {
87533
+ var _a3, _b3;
87534
+ (_a3 = textareaRef.current) == null ? void 0 : _a3.focus();
87535
+ (_b3 = textareaRef.current) == null ? void 0 : _b3.select();
87536
+ }, 0);
87537
+ }, [isInlineEditable, nodeId, onNodeTextChange, displayName]);
87538
+ const handleNodeClick2 = useCallback((event) => {
87539
+ const now2 = Date.now();
87540
+ const timeSinceLastClick = now2 - lastClickTimeRef.current;
87541
+ if (timeSinceLastClick < 300) {
87542
+ handleNodeDoubleClick(event);
87543
+ }
87544
+ lastClickTimeRef.current = now2;
87545
+ }, [handleNodeDoubleClick]);
87546
+ const handleSaveText = useCallback(() => {
87547
+ if (!nodeId || !onNodeTextChange)
87548
+ return;
87549
+ if (editingText !== displayName) {
87550
+ onNodeTextChange(nodeId, editingText);
87551
+ }
87552
+ setIsEditing(false);
87553
+ }, [nodeId, onNodeTextChange, editingText, displayName]);
87554
+ const handleCancelEdit = useCallback(() => {
87555
+ setIsEditing(false);
87556
+ setEditingText("");
87557
+ }, []);
87519
87558
  const getShapeStyles = () => {
87520
87559
  const borderStyle = status === "draft" ? "dotted" : status === "approved" ? "dashed" : "solid";
87521
87560
  const baseStyles = {
@@ -87728,7 +87767,7 @@ const CustomNode = (props) => {
87728
87767
  fontFamily: theme2.fonts.body,
87729
87768
  color: "#D0021B",
87730
87769
  fontWeight: theme2.fontWeights.bold
87731
- }, children: "⚠️" })] }) }), tooltipsEnabled && jsx(NodeTooltip, { description, otel: otelInfo, sources, references, visible: showTooltip, nodeRef })] }) : jsxs("div", { ref: nodeRef, style: { position: "relative", width: "100%", height: "100%" }, onMouseDown: handleMouseDown, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [renderStatusBadge(), isBoundaryNode ? renderBoundaryBadge() : jsxs(Fragment, { children: [renderSourcesBadge(), renderReferencesBadge()] }), jsx("div", { style: getShapeStyles(), className: animationClass, children: jsxs("div", { style: {
87770
+ }, children: "⚠️" })] }) }), tooltipsEnabled && jsx(NodeTooltip, { description, otel: otelInfo, sources, references, visible: showTooltip, nodeRef })] }) : jsxs("div", { ref: nodeRef, style: { position: "relative", width: "100%", height: "100%" }, onMouseDown: handleMouseDown, onClick: handleNodeClick2, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [renderStatusBadge(), isBoundaryNode ? renderBoundaryBadge() : jsxs(Fragment, { children: [renderSourcesBadge(), renderReferencesBadge()] }), jsx("div", { style: getShapeStyles(), className: animationClass, children: jsxs("div", { style: {
87732
87771
  ...isGroup ? { width: "100%" } : {}
87733
87772
  }, children: [isGroup ? jsxs("div", { style: {
87734
87773
  display: "flex",
@@ -87749,7 +87788,40 @@ const CustomNode = (props) => {
87749
87788
  fontFamily: theme2.fonts.body,
87750
87789
  color: "#D0021B",
87751
87790
  fontWeight: theme2.fontWeights.bold
87752
- }, children: "⚠️" })] }) }), tooltipsEnabled && jsx(NodeTooltip, { description, otel: otelInfo, sources, references, visible: showTooltip, nodeRef })] }), jsx(Handle, { type: "source", position: Position.Top, id: "top-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Bottom, id: "bottom-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Left, id: "left-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Right, id: "right-out", style: getHandleStyle() }), jsx("style", { children: `
87791
+ }, children: "⚠️" })] }) }), isEditing && isInlineEditable && jsx("div", { style: {
87792
+ position: "absolute",
87793
+ top: 0,
87794
+ left: 0,
87795
+ width: "100%",
87796
+ height: "100%",
87797
+ zIndex: 1e3,
87798
+ display: "flex",
87799
+ flexDirection: "column",
87800
+ padding: theme2.space[1],
87801
+ boxSizing: "border-box"
87802
+ }, onClick: (e) => e.stopPropagation(), children: jsx("textarea", { ref: textareaRef, value: editingText, onChange: (e) => setEditingText(e.target.value), placeholder: "Enter text...", style: {
87803
+ flex: 1,
87804
+ width: "100%",
87805
+ padding: theme2.space[2],
87806
+ fontSize: theme2.fontSizes[1],
87807
+ fontFamily: theme2.fonts.body,
87808
+ color: theme2.colors.text,
87809
+ backgroundColor: theme2.colors.background,
87810
+ border: `3px solid ${theme2.colors.primary}`,
87811
+ borderRadius: theme2.radii[1],
87812
+ outline: "none",
87813
+ resize: "none",
87814
+ boxSizing: "border-box",
87815
+ boxShadow: "0 8px 24px rgba(0, 0, 0, 0.3)"
87816
+ }, onKeyDown: (e) => {
87817
+ if (e.key === "Enter" && !e.shiftKey) {
87818
+ e.preventDefault();
87819
+ handleSaveText();
87820
+ } else if (e.key === "Escape") {
87821
+ e.preventDefault();
87822
+ handleCancelEdit();
87823
+ }
87824
+ }, onBlur: handleSaveText }) }), tooltipsEnabled && jsx(NodeTooltip, { description, otel: otelInfo, sources, references, visible: showTooltip, nodeRef })] }), jsx(Handle, { type: "source", position: Position.Top, id: "top-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Bottom, id: "bottom-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Left, id: "left-out", style: getHandleStyle() }), jsx(Handle, { type: "source", position: Position.Right, id: "right-out", style: getHandleStyle() }), jsx("style", { children: `
87753
87825
  /* Processing pulse - continuous breathing effect */
87754
87826
  .node-pulse {
87755
87827
  animation: node-pulse ease-in-out infinite;
@@ -180518,6 +180590,7 @@ const edgeTypes = { custom: CustomEdge };
180518
180590
  const createEmptyEditState = () => ({
180519
180591
  positionChanges: /* @__PURE__ */ new Map(),
180520
180592
  dimensionChanges: /* @__PURE__ */ new Map(),
180593
+ textChanges: /* @__PURE__ */ new Map(),
180521
180594
  nodeUpdates: /* @__PURE__ */ new Map(),
180522
180595
  deletedNodeIds: /* @__PURE__ */ new Set(),
180523
180596
  createdEdges: [],
@@ -180561,11 +180634,12 @@ const CenterIndicator = ({ color: color2 }) => {
180561
180634
  zIndex: 5
180562
180635
  }, 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 })] });
180563
180636
  };
180564
- 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 }) => {
180637
+ 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 }) => {
180565
180638
  const { fitView: fitView2, fitBounds, getNodes } = useReactFlow();
180566
180639
  const updateNodeInternals2 = useUpdateNodeInternals();
180567
180640
  const { theme: theme2 } = useTheme();
180568
180641
  const [shiftKeyPressed, setShiftKeyPressed] = useState(false);
180642
+ const [textChangesVersion, setTextChangesVersion] = useState(0);
180569
180643
  const hidingNodeRef = useRef(false);
180570
180644
  useEffect(() => {
180571
180645
  const handleKeyDown = (e) => {
@@ -180644,12 +180718,12 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
180644
180718
  propNodesRef.current = propNodes;
180645
180719
  setLocalNodes(propNodes);
180646
180720
  }, [propNodes, draggableNodeIds]);
180647
- const nodes = localNodes;
180721
+ const nodes = editable ? localNodes.filter((node2) => !editStateRef.current.deletedNodeIds.has(node2.id)) : localNodes;
180648
180722
  const edges = editable ? localEdges : propEdges;
180649
180723
  const xyflowNodesRef = useRef([]);
180650
180724
  const dragStartPositionsRef = useRef(/* @__PURE__ */ new Map());
180651
180725
  const checkHasChanges = useCallback((state) => {
180652
- 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;
180726
+ return state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.textChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0;
180653
180727
  }, []);
180654
180728
  const updateEditState = useCallback((updater) => {
180655
180729
  const newState = updater(editStateRef.current);
@@ -180677,6 +180751,50 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
180677
180751
  return { ...prev, dimensionChanges: newDimensions };
180678
180752
  });
180679
180753
  }, [editable, updateEditState, pushHistory]);
180754
+ const handleNodeTextChange = useCallback((nodeId, text2) => {
180755
+ if (!editable)
180756
+ return;
180757
+ const beforeText = editStateRef.current.textChanges.get(nodeId) ?? "";
180758
+ pushHistory([
180759
+ {
180760
+ type: "text",
180761
+ nodeId,
180762
+ before: beforeText,
180763
+ after: text2
180764
+ }
180765
+ ]);
180766
+ updateEditState((prev) => {
180767
+ const newTextChanges = new Map(prev.textChanges);
180768
+ newTextChanges.set(nodeId, text2);
180769
+ return { ...prev, textChanges: newTextChanges };
180770
+ });
180771
+ setTextChangesVersion((v2) => v2 + 1);
180772
+ }, [editable, updateEditState, pushHistory]);
180773
+ const handleDeleteSelectedNodes = useCallback(() => {
180774
+ if (!editable || selectedNodeIds.size === 0)
180775
+ return;
180776
+ const nodesToDelete = Array.from(selectedNodeIds);
180777
+ const historyEntries = [];
180778
+ for (const nodeId of nodesToDelete) {
180779
+ const node2 = localNodes.find((n) => n.id === nodeId);
180780
+ if (!node2)
180781
+ continue;
180782
+ historyEntries.push({
180783
+ type: "nodeDelete",
180784
+ nodeId,
180785
+ nodeData: node2
180786
+ });
180787
+ }
180788
+ if (historyEntries.length > 0) {
180789
+ pushHistory(historyEntries);
180790
+ updateEditState((prev) => {
180791
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
180792
+ nodesToDelete.forEach((id2) => newDeletedNodeIds.add(id2));
180793
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
180794
+ });
180795
+ setSelectedNodeIds(/* @__PURE__ */ new Set());
180796
+ }
180797
+ }, [editable, selectedNodeIds, localNodes, pushHistory, updateEditState]);
180680
180798
  const handleToggleNodeHidden = useCallback((nodeId) => {
180681
180799
  hidingNodeRef.current = true;
180682
180800
  setHiddenNodeIds((prev) => {
@@ -180725,9 +180843,10 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
180725
180843
  }, [localEdges, localNodes]);
180726
180844
  const graphEditContextValue = useMemo(() => ({
180727
180845
  onNodeResizeEnd: handleNodeResizeEnd,
180846
+ onNodeTextChange: handleNodeTextChange,
180728
180847
  onToggleNodeHidden: handleToggleNodeHidden,
180729
180848
  onHideUnconnectedNodes: handleHideUnconnectedNodes
180730
- }), [handleNodeResizeEnd, handleToggleNodeHidden, handleHideUnconnectedNodes]);
180849
+ }), [handleNodeResizeEnd, handleNodeTextChange, handleToggleNodeHidden, handleHideUnconnectedNodes]);
180731
180850
  const detectAlignmentGuides = useCallback((draggingNodeId, nodes2) => {
180732
180851
  const threshold = 5;
180733
180852
  const guides = [];
@@ -181167,6 +181286,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181167
181286
  var _a2, _b2;
181168
181287
  const animation = animationState.nodeAnimations[node2.id];
181169
181288
  const pendingPosition = editStateRef.current.positionChanges.get(node2.id);
181289
+ const pendingText = editStateRef.current.textChanges.get(node2.id);
181170
181290
  const isDraggable = editable || (draggableNodeIds == null ? void 0 : draggableNodeIds.has(node2.id));
181171
181291
  const hasDraggableNodeIds = draggableNodeIds && draggableNodeIds.size > 0;
181172
181292
  const dataWidth = typeof ((_a2 = node2.data) == null ? void 0 : _a2.width) === "number" ? node2.data.width : void 0;
@@ -181184,6 +181304,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181184
181304
  data: {
181185
181305
  ...node2.data,
181186
181306
  editable,
181307
+ pendingText,
181187
181308
  tooltipsEnabled: showTooltips,
181188
181309
  shiftKeyPressed,
181189
181310
  isHighlighted: highlightedNodeId === node2.id,
@@ -181196,7 +181317,7 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181196
181317
  }
181197
181318
  };
181198
181319
  });
181199
- }, [localNodes, configuration, violations, animationState.nodeAnimations, editable, showTooltips, highlightedNodeId, activeNodeIds, editStateRef, shiftKeyPressed, selectedNodeIds, hiddenNodeIds, draggableNodeIds]);
181320
+ }, [localNodes, configuration, violations, animationState.nodeAnimations, editable, showTooltips, highlightedNodeId, activeNodeIds, editStateRef, shiftKeyPressed, selectedNodeIds, hiddenNodeIds, draggableNodeIds, textChangesVersion]);
181200
181321
  const baseNodesKey = useMemo(() => {
181201
181322
  return nodes.map((n) => n.id).sort().join(",");
181202
181323
  }, [nodes]);
@@ -181238,6 +181359,21 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181238
181359
  data: { ...n.data, isHidden: hiddenNodeIds.has(n.id) }
181239
181360
  })));
181240
181361
  }, [editable, hiddenNodeIds]);
181362
+ const prevTextChangesVersionRef = useRef(textChangesVersion);
181363
+ useEffect(() => {
181364
+ if (!editable)
181365
+ return;
181366
+ if (prevTextChangesVersionRef.current === textChangesVersion)
181367
+ return;
181368
+ prevTextChangesVersionRef.current = textChangesVersion;
181369
+ setXyflowLocalNodes((nodes2) => nodes2.map((n) => {
181370
+ const pendingText = editStateRef.current.textChanges.get(n.id);
181371
+ return {
181372
+ ...n,
181373
+ data: { ...n.data, pendingText }
181374
+ };
181375
+ }));
181376
+ }, [editable, textChangesVersion]);
181241
181377
  const prevEditableRef = useRef(editable);
181242
181378
  useEffect(() => {
181243
181379
  if (editable && !prevEditableRef.current) {
@@ -181302,6 +181438,21 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181302
181438
  return { ...prev, dimensionChanges: newDimensions };
181303
181439
  });
181304
181440
  break;
181441
+ case "text":
181442
+ updateEditState((prev) => {
181443
+ const newTextChanges = new Map(prev.textChanges);
181444
+ newTextChanges.set(entry.nodeId, entry.before);
181445
+ return { ...prev, textChanges: newTextChanges };
181446
+ });
181447
+ setTextChangesVersion((v2) => v2 + 1);
181448
+ break;
181449
+ case "nodeDelete":
181450
+ updateEditState((prev) => {
181451
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
181452
+ newDeletedNodeIds.delete(entry.nodeId);
181453
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
181454
+ });
181455
+ break;
181305
181456
  case "edgeCreate":
181306
181457
  setLocalEdges((edges2) => edges2.filter((e) => e.id !== entry.edge.id));
181307
181458
  updateEditState((prev) => ({
@@ -181341,6 +181492,21 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181341
181492
  return { ...prev, dimensionChanges: newDimensions };
181342
181493
  });
181343
181494
  break;
181495
+ case "text":
181496
+ updateEditState((prev) => {
181497
+ const newTextChanges = new Map(prev.textChanges);
181498
+ newTextChanges.set(entry.nodeId, entry.after);
181499
+ return { ...prev, textChanges: newTextChanges };
181500
+ });
181501
+ setTextChangesVersion((v2) => v2 + 1);
181502
+ break;
181503
+ case "nodeDelete":
181504
+ updateEditState((prev) => {
181505
+ const newDeletedNodeIds = new Set(prev.deletedNodeIds);
181506
+ newDeletedNodeIds.add(entry.nodeId);
181507
+ return { ...prev, deletedNodeIds: newDeletedNodeIds };
181508
+ });
181509
+ break;
181344
181510
  case "edgeCreate":
181345
181511
  setLocalEdges((edges2) => [...edges2, entry.edge]);
181346
181512
  updateEditState((prev) => ({
@@ -181392,10 +181558,18 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181392
181558
  e.preventDefault();
181393
181559
  applyRedo();
181394
181560
  }
181561
+ if (e.key === "Delete" || e.key === "Backspace") {
181562
+ const activeElement = document.activeElement;
181563
+ const isEditingText = (activeElement == null ? void 0 : activeElement.tagName) === "INPUT" || (activeElement == null ? void 0 : activeElement.tagName) === "TEXTAREA";
181564
+ if (!isEditingText) {
181565
+ e.preventDefault();
181566
+ handleDeleteSelectedNodes();
181567
+ }
181568
+ }
181395
181569
  };
181396
181570
  window.addEventListener("keydown", handleKeyDown);
181397
181571
  return () => window.removeEventListener("keydown", handleKeyDown);
181398
- }, [editable, applyUndo, applyRedo]);
181572
+ }, [editable, applyUndo, applyRedo, handleDeleteSelectedNodes]);
181399
181573
  useEffect(() => {
181400
181574
  undoRedoFunctionsRef.current = {
181401
181575
  applyUndo,
@@ -181596,6 +181770,11 @@ const GraphRendererInner = ({ configuration, nodes: propNodes, edges: propEdges,
181596
181770
  onPendingChangesChange == null ? void 0 : onPendingChangesChange(false);
181597
181771
  };
181598
181772
  }, [xyflowNodesBase, xyflowEdgesWithElk, onPendingChangesChange]);
181773
+ useEffect(() => {
181774
+ resetTextChangesVersionRef.current = () => {
181775
+ setTextChangesVersion(0);
181776
+ };
181777
+ }, []);
181599
181778
  const xyflowEdges = editable ? xyflowLocalEdges : xyflowEdgesWithElk;
181600
181779
  const handleEdgesChange = useCallback((changes) => {
181601
181780
  if (!editable)
@@ -181839,6 +182018,7 @@ const GraphRenderer = forwardRef((props, ref) => {
181839
182018
  }, [canvas, containerWidth, containerHeight]);
181840
182019
  const editStateRef = useRef(createEmptyEditState());
181841
182020
  const resetVisualStateRef = useRef(null);
182021
+ const resetTextChangesVersionRef = useRef(null);
181842
182022
  const { canUndo: canUndoState, canRedo: canRedoState, undo: undoFromStack, redo: redoFromStack, pushHistory, clearHistory } = useUndoRedo();
181843
182023
  const undoRedoFunctionsRef = useRef(null);
181844
182024
  useImperativeHandle(ref, () => ({
@@ -181853,6 +182033,10 @@ const GraphRenderer = forwardRef((props, ref) => {
181853
182033
  nodeId,
181854
182034
  dimensions
181855
182035
  })),
182036
+ textChanges: Array.from(state.textChanges.entries()).map(([nodeId, text2]) => ({
182037
+ nodeId,
182038
+ text: text2
182039
+ })),
181856
182040
  nodeUpdates: Array.from(state.nodeUpdates.entries()).map(([nodeId, updates]) => ({
181857
182041
  nodeId,
181858
182042
  updates
@@ -181866,18 +182050,19 @@ const GraphRenderer = forwardRef((props, ref) => {
181866
182050
  targetHandle: e.targetHandle
181867
182051
  })),
181868
182052
  deletedEdges: state.deletedEdges.map((e) => ({ from: e.from, to: e.to, type: e.type })),
181869
- hasChanges: state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0
182053
+ hasChanges: state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.textChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0
181870
182054
  };
181871
182055
  },
181872
182056
  resetEditState: () => {
181873
- var _a2;
182057
+ var _a2, _b2;
181874
182058
  editStateRef.current = createEmptyEditState();
181875
- (_a2 = resetVisualStateRef.current) == null ? void 0 : _a2.call(resetVisualStateRef);
182059
+ (_a2 = resetTextChangesVersionRef.current) == null ? void 0 : _a2.call(resetTextChangesVersionRef);
182060
+ (_b2 = resetVisualStateRef.current) == null ? void 0 : _b2.call(resetVisualStateRef);
181876
182061
  clearHistory();
181877
182062
  },
181878
182063
  hasUnsavedChanges: () => {
181879
182064
  const state = editStateRef.current;
181880
- 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;
182065
+ return state.positionChanges.size > 0 || state.dimensionChanges.size > 0 || state.textChanges.size > 0 || state.nodeUpdates.size > 0 || state.deletedNodeIds.size > 0 || state.createdEdges.length > 0 || state.deletedEdges.length > 0;
181881
182066
  },
181882
182067
  canUndo: () => canUndoState,
181883
182068
  canRedo: () => canRedoState,
@@ -181907,7 +182092,7 @@ const GraphRenderer = forwardRef((props, ref) => {
181907
182092
  if (isWaitingForViewport) {
181908
182093
  return jsx("div", { ref: containerRef, className, style: { width, height, position: "relative" } });
181909
182094
  }
181910
- 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, initialViewport, elkLayout, scenarioEdges, showSequenceLabels }) }) }) });
182095
+ 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, resetTextChangesVersionRef, undoRedoFunctionsRef, pushHistory, clearHistory, undoFromStack, redoFromStack, onNodeClick, fitViewToNodeIds, fitViewPadding, draggableNodeIds, onNodeDragStop, onCopy, initialViewport, elkLayout, scenarioEdges, showSequenceLabels }) }) }) });
181911
182096
  });
181912
182097
  GraphRenderer.displayName = "GraphRenderer";
181913
182098
  function extractNamespace(name2, strategy) {
@@ -190981,7 +191166,8 @@ const CanvasEditorPanel = ({
190981
191166
  colorPickerPosition: null,
190982
191167
  // Text editor state
190983
191168
  editingNodeId: null,
190984
- editingNodeText: ""
191169
+ editingNodeText: "",
191170
+ editingNodeScreenPosition: null
190985
191171
  });
190986
191172
  const observerRef = useRef(null);
190987
191173
  const containerRefCallback = useCallback((node2) => {
@@ -191421,17 +191607,30 @@ const CanvasEditorPanel = ({
191421
191607
  } else if (node2.type === "group" && "label" in node2) {
191422
191608
  currentText = node2.label || "";
191423
191609
  }
191610
+ const nodeElement = document.querySelector(`[data-id="${nodeId}"]`);
191611
+ let screenPosition = null;
191612
+ if (nodeElement) {
191613
+ const rect = nodeElement.getBoundingClientRect();
191614
+ screenPosition = {
191615
+ x: rect.left,
191616
+ y: rect.top,
191617
+ width: rect.width,
191618
+ height: rect.height
191619
+ };
191620
+ }
191424
191621
  setState((prev) => ({
191425
191622
  ...prev,
191426
191623
  editingNodeId: nodeId,
191427
- editingNodeText: currentText
191624
+ editingNodeText: currentText,
191625
+ editingNodeScreenPosition: screenPosition
191428
191626
  }));
191429
191627
  }, [state.canvas, state.isEditMode]);
191430
191628
  const closeTextEditor = useCallback(() => {
191431
191629
  setState((prev) => ({
191432
191630
  ...prev,
191433
191631
  editingNodeId: null,
191434
- editingNodeText: ""
191632
+ editingNodeText: "",
191633
+ editingNodeScreenPosition: null
191435
191634
  }));
191436
191635
  }, []);
191437
191636
  const saveTextEditorChanges = useCallback(() => {
@@ -191462,7 +191661,8 @@ const CanvasEditorPanel = ({
191462
191661
  libraryVersion: prev.libraryVersion + 1,
191463
191662
  hasUnsavedChanges: true,
191464
191663
  editingNodeId: null,
191465
- editingNodeText: ""
191664
+ editingNodeText: "",
191665
+ editingNodeScreenPosition: null
191466
191666
  }));
191467
191667
  }, [state.canvas, state.editingNodeId, state.editingNodeText]);
191468
191668
  const handleTextEditorChange = useCallback((newText) => {
@@ -192648,135 +192848,77 @@ const CanvasEditorPanel = ({
192648
192848
  }
192649
192849
  )
192650
192850
  ] }),
192651
- state.editingNodeId && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
192652
- "div",
192653
- {
192654
- style: {
192655
- position: "fixed",
192656
- top: 0,
192657
- left: 0,
192658
- right: 0,
192659
- bottom: 0,
192660
- backgroundColor: "rgba(0, 0, 0, 0.5)",
192661
- zIndex: 90,
192662
- display: "flex",
192663
- alignItems: "center",
192664
- justifyContent: "center"
192665
- },
192666
- onClick: closeTextEditor,
192667
- children: /* @__PURE__ */ jsxs(
192851
+ state.editingNodeId && state.editingNodeScreenPosition && (() => {
192852
+ const pos = state.editingNodeScreenPosition;
192853
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
192854
+ /* @__PURE__ */ jsx(
192855
+ "div",
192856
+ {
192857
+ style: {
192858
+ position: "fixed",
192859
+ top: 0,
192860
+ left: 0,
192861
+ right: 0,
192862
+ bottom: 0,
192863
+ zIndex: 90
192864
+ },
192865
+ onClick: () => {
192866
+ saveTextEditorChanges();
192867
+ }
192868
+ }
192869
+ ),
192870
+ /* @__PURE__ */ jsx(
192668
192871
  "div",
192669
192872
  {
192670
192873
  style: {
192671
- backgroundColor: theme2.colors.background,
192672
- border: `2px solid ${theme2.colors.primary}`,
192673
- borderRadius: theme2.radii[2],
192674
- padding: theme2.space[4],
192675
- boxShadow: "0 8px 24px rgba(0, 0, 0, 0.3)",
192676
- minWidth: 400,
192677
- maxWidth: 600,
192678
- width: "90%"
192874
+ position: "fixed",
192875
+ left: `${pos.x}px`,
192876
+ top: `${pos.y}px`,
192877
+ width: `${pos.width}px`,
192878
+ height: `${pos.height}px`,
192879
+ zIndex: 100,
192880
+ pointerEvents: "auto"
192679
192881
  },
192680
192882
  onClick: (e) => e.stopPropagation(),
192681
- children: [
192682
- /* @__PURE__ */ jsx("div", { style: {
192683
- marginBottom: theme2.space[3],
192684
- fontSize: theme2.fontSizes[2],
192685
- fontWeight: theme2.fontWeights.semibold,
192686
- color: theme2.colors.text
192687
- }, children: (() => {
192688
- var _a3, _b3;
192689
- const node2 = (_b3 = (_a3 = state.canvas) == null ? void 0 : _a3.nodes) == null ? void 0 : _b3.find((n) => n.id === state.editingNodeId);
192690
- if ((node2 == null ? void 0 : node2.type) === "group") return "Edit Group Label";
192691
- return "Edit Text Node";
192692
- })() }),
192693
- /* @__PURE__ */ jsx(
192694
- "textarea",
192695
- {
192696
- autoFocus: true,
192697
- value: state.editingNodeText,
192698
- onChange: (e) => handleTextEditorChange(e.target.value),
192699
- placeholder: "Enter text...",
192700
- style: {
192701
- width: "100%",
192702
- minHeight: 150,
192703
- padding: theme2.space[2],
192704
- fontSize: theme2.fontSizes[1],
192705
- fontFamily: theme2.fonts.body,
192706
- color: theme2.colors.text,
192707
- backgroundColor: theme2.colors.backgroundSecondary,
192708
- border: `1px solid ${theme2.colors.border}`,
192709
- borderRadius: theme2.radii[1],
192710
- outline: "none",
192711
- resize: "vertical",
192712
- boxSizing: "border-box"
192713
- },
192714
- onKeyDown: (e) => {
192715
- if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
192716
- e.preventDefault();
192717
- saveTextEditorChanges();
192718
- }
192719
- if (e.key === "Escape") {
192720
- e.preventDefault();
192721
- closeTextEditor();
192722
- }
192883
+ children: /* @__PURE__ */ jsx(
192884
+ "textarea",
192885
+ {
192886
+ autoFocus: true,
192887
+ value: state.editingNodeText,
192888
+ onChange: (e) => handleTextEditorChange(e.target.value),
192889
+ placeholder: "Enter text...",
192890
+ style: {
192891
+ width: "100%",
192892
+ height: "100%",
192893
+ padding: theme2.space[2],
192894
+ fontSize: theme2.fontSizes[1],
192895
+ fontFamily: theme2.fonts.body,
192896
+ color: theme2.colors.text,
192897
+ backgroundColor: theme2.colors.background,
192898
+ border: `3px solid ${theme2.colors.primary}`,
192899
+ borderRadius: theme2.radii[1],
192900
+ outline: "none",
192901
+ resize: "none",
192902
+ boxSizing: "border-box",
192903
+ boxShadow: "0 8px 24px rgba(0, 0, 0, 0.3)"
192904
+ },
192905
+ onKeyDown: (e) => {
192906
+ if (e.key === "Enter" && !e.shiftKey) {
192907
+ e.preventDefault();
192908
+ saveTextEditorChanges();
192723
192909
  }
192724
- }
192725
- ),
192726
- /* @__PURE__ */ jsxs("div", { style: {
192727
- marginTop: theme2.space[3],
192728
- display: "flex",
192729
- gap: theme2.space[2],
192730
- justifyContent: "space-between",
192731
- alignItems: "center"
192732
- }, children: [
192733
- /* @__PURE__ */ jsx("div", { style: {
192734
- fontSize: theme2.fontSizes[0],
192735
- color: theme2.colors.textMuted,
192736
- fontStyle: "italic"
192737
- }, children: "⌘+Enter to save • Esc to cancel" }),
192738
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: theme2.space[2] }, children: [
192739
- /* @__PURE__ */ jsx(
192740
- "button",
192741
- {
192742
- onClick: closeTextEditor,
192743
- style: {
192744
- padding: `${theme2.space[2]} ${theme2.space[3]}`,
192745
- fontSize: theme2.fontSizes[1],
192746
- fontFamily: theme2.fonts.body,
192747
- color: theme2.colors.text,
192748
- backgroundColor: theme2.colors.backgroundSecondary,
192749
- border: `1px solid ${theme2.colors.border}`,
192750
- borderRadius: theme2.radii[1],
192751
- cursor: "pointer"
192752
- },
192753
- children: "Cancel"
192754
- }
192755
- ),
192756
- /* @__PURE__ */ jsx(
192757
- "button",
192758
- {
192759
- onClick: saveTextEditorChanges,
192760
- style: {
192761
- padding: `${theme2.space[2]} ${theme2.space[3]}`,
192762
- fontSize: theme2.fontSizes[1],
192763
- fontFamily: theme2.fonts.body,
192764
- color: "white",
192765
- backgroundColor: theme2.colors.primary,
192766
- border: "none",
192767
- borderRadius: theme2.radii[1],
192768
- cursor: "pointer"
192769
- },
192770
- children: "Save"
192771
- }
192772
- )
192773
- ] })
192774
- ] })
192775
- ]
192910
+ if (e.key === "Escape") {
192911
+ e.preventDefault();
192912
+ closeTextEditor();
192913
+ }
192914
+ },
192915
+ onBlur: saveTextEditorChanges
192916
+ }
192917
+ )
192776
192918
  }
192777
192919
  )
192778
- }
192779
- ) }),
192920
+ ] });
192921
+ })(),
192780
192922
  copiedNodesCount !== null && /* @__PURE__ */ jsxs("div", { style: {
192781
192923
  position: "absolute",
192782
192924
  bottom: 16,