@railtownai/railtracks-visualizer 0.0.37 → 0.0.39

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/esm/index.js CHANGED
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import React__default, { memo, useMemo, useState, useCallback, forwardRef, createContext, useContext, useRef, useLayoutEffect, useEffect, createElement } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import * as ReactDOM from 'react-dom';
5
- import ReactDOM__default, { createPortal } from 'react-dom';
5
+ import ReactDOM__default from 'react-dom';
6
6
  import CountUp from 'react-countup';
7
7
 
8
8
  function cc(names) {
@@ -5986,7 +5986,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5986
5986
  return (!event.ctrlKey || isWheelEvent) && buttonAllowed;
5987
5987
  };
5988
5988
  }
5989
- function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExtent, viewport, onPanZoom, onPanZoomStart, onPanZoomEnd, onDraggingChange }) {
5989
+ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPanZoom, onPanZoomStart, onPanZoomEnd, onDraggingChange }) {
5990
5990
  const zoomPanValues = {
5991
5991
  isZoomingOrPanning: false,
5992
5992
  usedRightMouseButton: false,
@@ -5998,7 +5998,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
5998
5998
  isPanScrolling: false
5999
5999
  };
6000
6000
  const bbox = domNode.getBoundingClientRect();
6001
- const d3ZoomInstance = zoom().clickDistance(!isNumeric(paneClickDistance) || paneClickDistance < 0 ? 0 : paneClickDistance).scaleExtent([
6001
+ const d3ZoomInstance = zoom().scaleExtent([
6002
6002
  minZoom,
6003
6003
  maxZoom
6004
6004
  ]).translateExtent(translateExtent);
@@ -6029,11 +6029,12 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
6029
6029
  return Promise.resolve(false);
6030
6030
  }
6031
6031
  // public functions
6032
- function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange, connectionInProgress }) {
6032
+ function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange, connectionInProgress, paneClickDistance, selectionOnDrag }) {
6033
6033
  if (userSelectionActive && !zoomPanValues.isZoomingOrPanning) {
6034
6034
  destroy();
6035
6035
  }
6036
6036
  const isPanOnScroll = panOnScroll && !zoomActivationKeyPressed && !userSelectionActive;
6037
+ d3ZoomInstance.clickDistance(selectionOnDrag ? Infinity : !isNumeric(paneClickDistance) || paneClickDistance < 0 ? 0 : paneClickDistance);
6037
6038
  const wheelHandler = isPanOnScroll ? createPanOnScrollHandler({
6038
6039
  zoomPanValues,
6039
6040
  noWheelClassName,
@@ -7315,7 +7316,6 @@ const reactFlowFieldsToTrack = [
7315
7316
  'onBeforeDelete',
7316
7317
  'debug',
7317
7318
  'autoPanSpeed',
7318
- 'paneClickDistance',
7319
7319
  'ariaLabelConfig'
7320
7320
  ];
7321
7321
  // rfId doesn't exist in ReactFlowProps, but it's one of the fields we want to update
@@ -7331,8 +7331,7 @@ const selector$l = (s)=>({
7331
7331
  setTranslateExtent: s.setTranslateExtent,
7332
7332
  setNodeExtent: s.setNodeExtent,
7333
7333
  reset: s.reset,
7334
- setDefaultNodesAndEdges: s.setDefaultNodesAndEdges,
7335
- setPaneClickDistance: s.setPaneClickDistance
7334
+ setDefaultNodesAndEdges: s.setDefaultNodesAndEdges
7336
7335
  });
7337
7336
  const initPrevValues = {
7338
7337
  /*
@@ -7345,11 +7344,10 @@ const initPrevValues = {
7345
7344
  maxZoom: 2,
7346
7345
  elementsSelectable: true,
7347
7346
  noPanClassName: 'nopan',
7348
- rfId: '1',
7349
- paneClickDistance: 0
7347
+ rfId: '1'
7350
7348
  };
7351
7349
  function StoreUpdater(props) {
7352
- const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, setPaneClickDistance } = useStore(selector$l, shallow$1);
7350
+ const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges } = useStore(selector$l, shallow$1);
7353
7351
  const store = useStoreApi();
7354
7352
  useEffect(()=>{
7355
7353
  setDefaultNodesAndEdges(props.defaultNodes, props.defaultEdges);
@@ -7373,7 +7371,6 @@ function StoreUpdater(props) {
7373
7371
  else if (fieldName === 'maxZoom') setMaxZoom(fieldValue);
7374
7372
  else if (fieldName === 'translateExtent') setTranslateExtent(fieldValue);
7375
7373
  else if (fieldName === 'nodeExtent') setNodeExtent(fieldValue);
7376
- else if (fieldName === 'paneClickDistance') setPaneClickDistance(fieldValue);
7377
7374
  else if (fieldName === 'ariaLabelConfig') store.setState({
7378
7375
  ariaLabelConfig: mergeAriaLabelConfig(fieldValue)
7379
7376
  });
@@ -8435,7 +8432,7 @@ const selector$j = (s)=>({
8435
8432
  lib: s.lib,
8436
8433
  connectionInProgress: s.connection.inProgress
8437
8434
  });
8438
- function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, paneClickDistance }) {
8435
+ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, paneClickDistance, selectionOnDrag }) {
8439
8436
  const store = useStoreApi();
8440
8437
  const zoomPane = useRef(null);
8441
8438
  const { userSelectionActive, lib, connectionInProgress } = useStore(selector$j, shallow$1);
@@ -8465,7 +8462,6 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8465
8462
  maxZoom,
8466
8463
  translateExtent,
8467
8464
  viewport: defaultViewport,
8468
- paneClickDistance,
8469
8465
  onDraggingChange: (paneDragging)=>store.setState({
8470
8466
  paneDragging
8471
8467
  }),
@@ -8517,7 +8513,9 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8517
8513
  noWheelClassName,
8518
8514
  lib,
8519
8515
  onTransformChange,
8520
- connectionInProgress
8516
+ connectionInProgress,
8517
+ selectionOnDrag,
8518
+ paneClickDistance
8521
8519
  });
8522
8520
  }, [
8523
8521
  onPaneContextMenu,
@@ -8535,7 +8533,9 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8535
8533
  noWheelClassName,
8536
8534
  lib,
8537
8535
  onTransformChange,
8538
- connectionInProgress
8536
+ connectionInProgress,
8537
+ selectionOnDrag,
8538
+ paneClickDistance
8539
8539
  ]);
8540
8540
  return jsx("div", {
8541
8541
  className: "react-flow__renderer",
@@ -8577,17 +8577,16 @@ const selector$h = (s)=>({
8577
8577
  connectionInProgress: s.connection.inProgress,
8578
8578
  dragging: s.paneDragging
8579
8579
  });
8580
- function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.Full, panOnDrag, selectionOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children }) {
8580
+ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.Full, panOnDrag, paneClickDistance, selectionOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children }) {
8581
8581
  const store = useStoreApi();
8582
8582
  const { userSelectionActive, elementsSelectable, dragging, connectionInProgress } = useStore(selector$h, shallow$1);
8583
- const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
8583
+ const isSelectionEnabled = elementsSelectable && (isSelecting || userSelectionActive);
8584
8584
  const container = useRef(null);
8585
8585
  const containerBounds = useRef();
8586
8586
  const selectedNodeIds = useRef(new Set());
8587
8587
  const selectedEdgeIds = useRef(new Set());
8588
8588
  // Used to prevent click events when the user lets go of the selectionKey during a selection
8589
8589
  const selectionInProgress = useRef(false);
8590
- const selectionStarted = useRef(false);
8591
8590
  const onClick = (event)=>{
8592
8591
  // We prevent click events when the user let go of the selectionKey during a selection
8593
8592
  // We also prevent click events when a connection is in progress
@@ -8610,29 +8609,27 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8610
8609
  };
8611
8610
  const onWheel = onPaneScroll ? (event)=>onPaneScroll(event) : undefined;
8612
8611
  const onClickCapture = (event)=>{
8613
- const isSelectionOnDragActive = selectionOnDrag && container.current === event.target || !selectionOnDrag || selectionKeyPressed;
8614
- if (!isSelectionOnDragActive) {
8615
- return;
8612
+ if (selectionInProgress.current) {
8613
+ event.stopPropagation();
8614
+ selectionInProgress.current = false;
8616
8615
  }
8617
- event.stopPropagation();
8618
8616
  };
8619
8617
  // We are using capture here in order to prevent other pointer events
8620
8618
  // to be able to create a selection above a node or an edge
8621
8619
  const onPointerDownCapture = (event)=>{
8622
- const { resetSelectedElements, domNode } = store.getState();
8620
+ const { domNode } = store.getState();
8623
8621
  containerBounds.current = domNode?.getBoundingClientRect();
8624
- const isNoKeyEvent = event.target !== container.current && !!event.target.closest('.nokey');
8625
- const isSelectionActive = selectionOnDrag && container.current === event.target || !selectionOnDrag || selectionKeyPressed;
8626
- if (!elementsSelectable || !isSelecting || event.button !== 0 || !containerBounds.current || isNoKeyEvent || !isSelectionActive || !event.isPrimary) {
8622
+ if (!containerBounds.current) return;
8623
+ const eventTargetIsContainer = event.target === container.current;
8624
+ // if a child element has the 'nokey' class, we don't want to swallow the event and don't start a selection
8625
+ const isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest('.nokey');
8626
+ const isSelectionActive = selectionOnDrag && eventTargetIsContainer || selectionKeyPressed;
8627
+ if (isNoKeyEvent || !isSelecting || !isSelectionActive || event.button !== 0 || !event.isPrimary) {
8627
8628
  return;
8628
8629
  }
8629
- event.stopPropagation();
8630
- event.preventDefault();
8631
8630
  event.target?.setPointerCapture?.(event.pointerId);
8632
- selectionStarted.current = true;
8633
8631
  selectionInProgress.current = false;
8634
8632
  const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
8635
- resetSelectedElements();
8636
8633
  store.setState({
8637
8634
  userSelectionRect: {
8638
8635
  width: 0,
@@ -8643,16 +8640,28 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8643
8640
  y
8644
8641
  }
8645
8642
  });
8646
- onSelectionStart?.(event);
8643
+ if (!eventTargetIsContainer) {
8644
+ event.stopPropagation();
8645
+ event.preventDefault();
8646
+ }
8647
8647
  };
8648
8648
  const onPointerMove = (event)=>{
8649
- const { userSelectionRect, transform, nodeLookup, edgeLookup, connectionLookup, triggerNodeChanges, triggerEdgeChanges, defaultEdgeOptions } = store.getState();
8649
+ const { userSelectionRect, transform, nodeLookup, edgeLookup, connectionLookup, triggerNodeChanges, triggerEdgeChanges, defaultEdgeOptions, resetSelectedElements } = store.getState();
8650
8650
  if (!containerBounds.current || !userSelectionRect) {
8651
8651
  return;
8652
8652
  }
8653
- selectionInProgress.current = true;
8654
8653
  const { x: mouseX, y: mouseY } = getEventPosition(event.nativeEvent, containerBounds.current);
8655
8654
  const { startX, startY } = userSelectionRect;
8655
+ if (!selectionInProgress.current) {
8656
+ const requiredDistance = selectionKeyPressed ? 0 : paneClickDistance;
8657
+ const distance = Math.hypot(mouseX - startX, mouseY - startY);
8658
+ if (distance <= requiredDistance) {
8659
+ return;
8660
+ }
8661
+ resetSelectedElements();
8662
+ onSelectionStart?.(event);
8663
+ }
8664
+ selectionInProgress.current = true;
8656
8665
  const nextUserSelectRect = {
8657
8666
  startX,
8658
8667
  startY,
@@ -8692,30 +8701,26 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8692
8701
  });
8693
8702
  };
8694
8703
  const onPointerUp = (event)=>{
8695
- if (event.button !== 0 || !selectionStarted.current) {
8704
+ if (event.button !== 0) {
8696
8705
  return;
8697
8706
  }
8698
8707
  event.target?.releasePointerCapture?.(event.pointerId);
8699
- const { userSelectionRect } = store.getState();
8700
8708
  /*
8701
8709
  * We only want to trigger click functions when in selection mode if
8702
8710
  * the user did not move the mouse.
8703
- */ if (!userSelectionActive && userSelectionRect && event.target === container.current) {
8711
+ */ if (!userSelectionActive && event.target === container.current && store.getState().userSelectionRect) {
8704
8712
  onClick?.(event);
8705
8713
  }
8706
8714
  store.setState({
8707
8715
  userSelectionActive: false,
8708
- userSelectionRect: null,
8709
- nodesSelectionActive: selectedNodeIds.current.size > 0
8716
+ userSelectionRect: null
8710
8717
  });
8711
- onSelectionEnd?.(event);
8712
- /*
8713
- * If the user kept holding the selectionKey during the selection,
8714
- * we need to reset the selectionInProgress, so the next click event is not prevented
8715
- */ if (selectionKeyPressed || selectionOnDrag) {
8716
- selectionInProgress.current = false;
8718
+ if (selectionInProgress.current) {
8719
+ onSelectionEnd?.(event);
8720
+ store.setState({
8721
+ nodesSelectionActive: selectedNodeIds.current.size > 0
8722
+ });
8717
8723
  }
8718
- selectionStarted.current = false;
8719
8724
  };
8720
8725
  const draggable = panOnDrag === true || Array.isArray(panOnDrag) && panOnDrag.includes(0);
8721
8726
  return jsxs("div", {
@@ -8727,14 +8732,14 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8727
8732
  selection: isSelecting
8728
8733
  }
8729
8734
  ]),
8730
- onClick: hasActiveSelection ? undefined : wrapHandler(onClick, container),
8735
+ onClick: isSelectionEnabled ? undefined : wrapHandler(onClick, container),
8731
8736
  onContextMenu: wrapHandler(onContextMenu, container),
8732
8737
  onWheel: wrapHandler(onWheel, container),
8733
- onPointerEnter: hasActiveSelection ? undefined : onPaneMouseEnter,
8734
- onPointerMove: hasActiveSelection ? onPointerMove : onPaneMouseMove,
8735
- onPointerUp: hasActiveSelection ? onPointerUp : undefined,
8736
- onPointerDownCapture: hasActiveSelection ? onPointerDownCapture : undefined,
8737
- onClickCapture: hasActiveSelection ? onClickCapture : undefined,
8738
+ onPointerEnter: isSelectionEnabled ? undefined : onPaneMouseEnter,
8739
+ onPointerMove: isSelectionEnabled ? onPointerMove : onPaneMouseMove,
8740
+ onPointerUp: isSelectionEnabled ? onPointerUp : undefined,
8741
+ onPointerDownCapture: isSelectionEnabled ? onPointerDownCapture : undefined,
8742
+ onClickCapture: isSelectionEnabled ? onClickCapture : undefined,
8738
8743
  onPointerLeave: onPaneMouseLeave,
8739
8744
  ref: container,
8740
8745
  style: containerStyle,
@@ -9284,6 +9289,7 @@ function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPane
9284
9289
  onViewportChange: onViewportChange,
9285
9290
  isControlledViewport: isControlledViewport,
9286
9291
  paneClickDistance: paneClickDistance,
9292
+ selectionOnDrag: _selectionOnDrag,
9287
9293
  children: jsxs(Pane, {
9288
9294
  onSelectionStart: onSelectionStart,
9289
9295
  onSelectionEnd: onSelectionEnd,
@@ -9297,6 +9303,7 @@ function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPane
9297
9303
  isSelecting: !!isSelecting,
9298
9304
  selectionMode: selectionMode,
9299
9305
  selectionKeyPressed: selectionKeyPressed,
9306
+ paneClickDistance: paneClickDistance,
9300
9307
  selectionOnDrag: _selectionOnDrag,
9301
9308
  children: [
9302
9309
  children,
@@ -11379,9 +11386,6 @@ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height,
11379
11386
  translateExtent
11380
11387
  });
11381
11388
  },
11382
- setPaneClickDistance: (clickDistance)=>{
11383
- get().panZoom?.setClickDistance(clickDistance);
11384
- },
11385
11389
  resetSelectedElements: ()=>{
11386
11390
  const { edges, nodes, triggerNodeChanges, triggerEdgeChanges, elementsSelectable } = get();
11387
11391
  if (!elementsSelectable) {
@@ -11710,7 +11714,6 @@ function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTy
11710
11714
  nodeDragThreshold: nodeDragThreshold,
11711
11715
  connectionDragThreshold: connectionDragThreshold,
11712
11716
  onBeforeDelete: onBeforeDelete,
11713
- paneClickDistance: paneClickDistance,
11714
11717
  debug: debug,
11715
11718
  ariaLabelConfig: ariaLabelConfig
11716
11719
  }),
@@ -12676,7 +12679,7 @@ var css_248z = "/* this gets exported as style.css and can be used for the defau
12676
12679
  styleInject(css_248z);
12677
12680
 
12678
12681
  /**
12679
- * @license lucide-react v0.546.0 - ISC
12682
+ * @license lucide-react v0.553.0 - ISC
12680
12683
  *
12681
12684
  * This source code is licensed under the ISC license.
12682
12685
  * See the LICENSE file in the root directory of this source tree.
@@ -12698,7 +12701,7 @@ const hasA11yProp = (props)=>{
12698
12701
  };
12699
12702
 
12700
12703
  /**
12701
- * @license lucide-react v0.546.0 - ISC
12704
+ * @license lucide-react v0.553.0 - ISC
12702
12705
  *
12703
12706
  * This source code is licensed under the ISC license.
12704
12707
  * See the LICENSE file in the root directory of this source tree.
@@ -14465,24 +14468,16 @@ const Edge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPo
14465
14468
  const [isHovered, setIsHovered] = useState(false);
14466
14469
  const { theme } = useTheme();
14467
14470
  const themeColors = theme.colors;
14468
- // Function to determine stroke color based on edge state and theme
14471
+ // Function to determine stroke color based on edge status and theme
14469
14472
  const getStrokeColor = ()=>{
14470
- const state = data?.details?.state;
14471
14473
  const status = data?.details?.status;
14472
- const output = data?.details?.output;
14474
+ data?.details?.output;
14473
14475
  // Check for error indicators
14474
- const hasError = state === "Error" || status === "Error" || typeof output === "string" && output.includes("ERROR:");
14476
+ const hasError = status === "Failed";
14475
14477
  if (hasError) {
14476
14478
  return themeColors.destructive;
14477
14479
  }
14478
- switch(state){
14479
- case "Open":
14480
- return themeColors.mutedForeground;
14481
- case "Completed":
14482
- return themeColors.mutedForeground;
14483
- default:
14484
- return themeColors.mutedForeground;
14485
- }
14480
+ return themeColors.mutedForeground;
14486
14481
  };
14487
14482
  const [edgePath] = useMemo(()=>{
14488
14483
  return getSmoothStepPath({
@@ -15781,6 +15776,8 @@ const Label$1 = styled.span`
15781
15776
  `;
15782
15777
  const Value$1 = styled.span`
15783
15778
  font-size: 0.75rem;
15779
+ overflow-wrap: break-word;
15780
+ word-wrap: break-word;
15784
15781
  color: ${(props)=>props.themeColors.primary};
15785
15782
  `;
15786
15783
  const EmptyIndicator = styled.span`
@@ -15800,8 +15797,8 @@ const TreeContainer = styled.div`
15800
15797
  `;
15801
15798
  const TreeScrollContainer = styled.div`
15802
15799
  width: 100%;
15803
- max-height: 16rem;
15804
15800
  overflow-y: auto;
15801
+ max-height: 16rem;
15805
15802
  padding: 0.5rem;
15806
15803
  `;
15807
15804
  const NoDataMessage = styled.div`
@@ -15822,7 +15819,8 @@ const SimpleValueContainer = styled.div`
15822
15819
  border: 1px solid ${(props)=>props.themeColors.border};
15823
15820
  font-size: 0.75rem;
15824
15821
  color: ${(props)=>props.themeColors.foreground};
15825
- word-break: break-all;
15822
+ overflow-wrap: break-word;
15823
+ word-wrap: break-word;
15826
15824
  `;
15827
15825
  styled.div`
15828
15826
  width: 100%;
@@ -15842,6 +15840,8 @@ const SimpleValueLabel = styled.span`
15842
15840
  `;
15843
15841
  const SimpleValueText = styled.span`
15844
15842
  color: ${(props)=>props.themeColors.foreground};
15843
+ word-wrap: break-word;
15844
+ overflow-wrap: break-word;
15845
15845
  font-size: 0.875rem;
15846
15846
  `;
15847
15847
  const EmptyStateContainer = styled.div`
@@ -16011,6 +16011,8 @@ const JsonTreeViewer = ({ data, maxDepth = 4, initialExpanded = false, expanded
16011
16011
  })()));
16012
16012
  };
16013
16013
 
16014
+ const NODE_MAX_WIDTH = 500;
16015
+
16014
16016
  const OutputRenderer = ({ data })=>{
16015
16017
  const [isExpanded, setIsExpanded] = useState(false);
16016
16018
  const contentType = detectContentType(data);
@@ -16019,20 +16021,26 @@ const OutputRenderer = ({ data })=>{
16019
16021
  };
16020
16022
  switch(contentType){
16021
16023
  case "string":
16022
- return /*#__PURE__*/ React__default.createElement(OutputScrollableContent, null, /*#__PURE__*/ React__default.createElement(ExpandableTextarea, {
16024
+ return /*#__PURE__*/ React__default.createElement(OutputScrollableContent, {
16025
+ className: "agent-node-scrollable"
16026
+ }, /*#__PURE__*/ React__default.createElement(ExpandableTextarea, {
16023
16027
  label: "Output",
16024
16028
  content: data.content,
16025
16029
  isExpanded: isExpanded,
16026
16030
  onToggle: handleToggle
16027
16031
  }));
16028
16032
  case "toolResponse":
16029
- return /*#__PURE__*/ React__default.createElement(OutputScrollableContent, null, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, "Output - Tool Response"), /*#__PURE__*/ React__default.createElement(JsonTreeViewer, {
16033
+ return /*#__PURE__*/ React__default.createElement(OutputScrollableContent, {
16034
+ className: "agent-node-scrollable"
16035
+ }, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, "Output - Tool Response"), /*#__PURE__*/ React__default.createElement(JsonTreeViewer, {
16030
16036
  data: data,
16031
16037
  expanded: true
16032
16038
  }));
16033
16039
  case "toolCallList":
16034
16040
  const formattedCode = formatToolCalls(data.content);
16035
- return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(OutputScrollableContent, null, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, /*#__PURE__*/ React__default.createElement("span", null, "Output - Tool Calls"), /*#__PURE__*/ React__default.createElement("span", {
16041
+ return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(OutputScrollableContent, {
16042
+ className: "agent-node-scrollable"
16043
+ }, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, /*#__PURE__*/ React__default.createElement("span", null, "Output - Tool Calls"), /*#__PURE__*/ React__default.createElement("span", {
16036
16044
  style: {
16037
16045
  display: "flex",
16038
16046
  alignItems: "center",
@@ -16047,7 +16055,7 @@ const OutputRenderer = ({ data })=>{
16047
16055
  })));
16048
16056
  case "other":
16049
16057
  default:
16050
- return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(OutputScrollableContent, null, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, "Output"), /*#__PURE__*/ React__default.createElement(JsonTreeViewer, {
16058
+ return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(OutputScrollableContent, null, /*#__PURE__*/ React__default.createElement(NodeSubHeader, null, "Output - JSON"), /*#__PURE__*/ React__default.createElement(JsonTreeViewer, {
16051
16059
  data: data,
16052
16060
  expanded: true
16053
16061
  })));
@@ -16070,12 +16078,13 @@ const NodeSubHeader = styled.span`
16070
16078
  `;
16071
16079
  const OutputScrollableContent = styled.div`
16072
16080
  width: 100%;
16081
+ max-width: ${NODE_MAX_WIDTH}px;
16073
16082
  display: flex;
16074
16083
  flex-direction: column;
16084
+ align-items: stretch;
16075
16085
  padding-bottom: 0.5rem;
16086
+ padding-right: 2px;
16076
16087
  gap: 0.5rem;
16077
- max-height: 200px;
16078
- overflow-y: auto;
16079
16088
  `;
16080
16089
 
16081
16090
  function _objectWithoutPropertiesLoose(r, e) {
@@ -16387,7 +16396,9 @@ const InputArrayRenderer = ({ input })=>{
16387
16396
  }
16388
16397
  }, /*#__PURE__*/ React__default.createElement(MessageSquare, {
16389
16398
  size: 12
16390
- }), input.length)), /*#__PURE__*/ React__default.createElement(InputArrayScrollableContent, null, input.map((item, index)=>/*#__PURE__*/ React__default.createElement(InputItem, {
16399
+ }), input.length)), /*#__PURE__*/ React__default.createElement(InputArrayScrollableContent, {
16400
+ className: "agent-node-scrollable"
16401
+ }, input.map((item, index)=>/*#__PURE__*/ React__default.createElement(InputItem, {
16391
16402
  key: index
16392
16403
  }, /*#__PURE__*/ React__default.createElement(InputItemHeader, null, /*#__PURE__*/ React__default.createElement(InputItemLabel, null, getRoleEmoji(item.role), " ", getRoleDisplayName(item.role))), /*#__PURE__*/ React__default.createElement(InputItemTextarea, {
16393
16404
  onClick: (e)=>{
@@ -16399,7 +16410,8 @@ const InputArrayRenderer = ({ input })=>{
16399
16410
  border: `1px solid ${themeColors.border}`,
16400
16411
  backgroundColor: themeColors.muted,
16401
16412
  color: themeColors.foreground
16402
- }
16413
+ },
16414
+ className: "agent-node-scrollable"
16403
16415
  })))));
16404
16416
  };
16405
16417
  // Styled components
@@ -16414,6 +16426,7 @@ const InputArrayScrollableContent = styled.div`
16414
16426
  display: flex;
16415
16427
  flex-direction: column;
16416
16428
  padding-bottom: 0.5rem;
16429
+ padding-right: 2px;
16417
16430
  gap: 0.5rem;
16418
16431
  max-height: 200px;
16419
16432
  overflow-y: auto;
@@ -16543,12 +16556,7 @@ const getNodeIcon$1 = (nodeType, modelProvider)=>{
16543
16556
  }
16544
16557
  return "🤖";
16545
16558
  };
16546
- const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16547
- const [position, setPosition] = useState({
16548
- top: 0,
16549
- left: 0,
16550
- arrowPosition: "right"
16551
- });
16559
+ const NodeDetailsPopover = ({ isVisible, onClose, nodeData })=>{
16552
16560
  const [selectedRowIndex, setSelectedRowIndex] = useState(null);
16553
16561
  const [selectedLlmDetails, setSelectedLlmDetails] = useState(null);
16554
16562
  // Default to last row (total/aggregate) when popover opens (only on first open)
@@ -16573,54 +16581,6 @@ const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16573
16581
  setSelectedLlmDetails(nodeData.details.internals.llm_details[nodeData.details.internals.llm_details.length]);
16574
16582
  }
16575
16583
  };
16576
- // Calculate popover position based on trigger element
16577
- useEffect(()=>{
16578
- if (isVisible && triggerRef.current) {
16579
- const rect = triggerRef.current.getBoundingClientRect();
16580
- const viewportWidth = window.innerWidth;
16581
- const viewportHeight = window.innerHeight;
16582
- const popoverWidth = DEFAULT_POPOVER_WIDTH; // Match the width from styled component
16583
- const popoverHeight = DEFAULT_POPOVER_HEIGHT; // Approximate max height
16584
- const gap = 12; // Gap between node and popover
16585
- // Check if the rect is valid (has non-zero dimensions and is in viewport)
16586
- const isValidRect = rect.width > 0 && rect.height > 0 && rect.top >= 0 && rect.left >= 0;
16587
- if (isValidRect) {
16588
- // Normal positioning logic for ReactFlow
16589
- let left = rect.right + gap;
16590
- let top = rect.top;
16591
- let arrowPosition = "right"; // Arrow points right (popover is to the right)
16592
- // If popover would go off-screen, position it to the left of the node
16593
- if (left + popoverWidth > viewportWidth) {
16594
- left = rect.left - popoverWidth - gap;
16595
- arrowPosition = "left"; // Arrow points left (popover is to the left)
16596
- }
16597
- // Ensure popover doesn't go off the top or bottom of the viewport
16598
- if (top < 0) {
16599
- top = 20; // Small margin from top
16600
- } else if (top + popoverHeight > viewportHeight) {
16601
- top = viewportHeight - popoverHeight - 20; // Small margin from bottom
16602
- }
16603
- setPosition({
16604
- top,
16605
- left,
16606
- arrowPosition
16607
- });
16608
- } else {
16609
- // Fallback positioning for isolated environments (like Storybook)
16610
- // Center the popover in the viewport
16611
- const centerLeft = Math.max(20, (viewportWidth - popoverWidth) / 2);
16612
- const centerTop = Math.max(20, (viewportHeight - popoverHeight) / 2);
16613
- setPosition({
16614
- top: centerTop,
16615
- left: centerLeft,
16616
- arrowPosition: "none" // No arrow in fallback mode
16617
- });
16618
- }
16619
- }
16620
- }, [
16621
- isVisible,
16622
- triggerRef
16623
- ]);
16624
16584
  // Handle ESC key to close popover
16625
16585
  useEffect(()=>{
16626
16586
  const handleEscKey = (event)=>{
@@ -16646,7 +16606,7 @@ const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16646
16606
  // Handle click outside to close popover
16647
16607
  useEffect(()=>{
16648
16608
  const handleClickOutside = (event)=>{
16649
- if (isVisible && triggerRef.current && !triggerRef.current.contains(event.target) && !event.target.closest("[data-popover-content]")) {
16609
+ if (isVisible && !event.target.closest("[data-popover-content]") && !event.target.closest(".react-flow__node")) {
16650
16610
  onClose();
16651
16611
  }
16652
16612
  };
@@ -16656,8 +16616,7 @@ const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16656
16616
  }
16657
16617
  }, [
16658
16618
  isVisible,
16659
- onClose,
16660
- triggerRef
16619
+ onClose
16661
16620
  ]);
16662
16621
  if (!isVisible) return null;
16663
16622
  const llOverviewDetails = getOverviewLlmDetails(nodeData.details?.internals?.llm_details || []);
@@ -16665,16 +16624,14 @@ const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16665
16624
  const totalInputTokens = sumTotalInputTokens(nodeData.details?.internals?.llm_details || []);
16666
16625
  const totalOutputTokens = sumTotalOutputTokens(nodeData.details?.internals?.llm_details || []);
16667
16626
  const totalLatency = sumTotalLatency(nodeData.details?.internals?.llm_details || []);
16668
- const popoverContent = /*#__PURE__*/ React__default.createElement(PopoverPortal, {
16669
- style: {
16670
- top: position.top,
16671
- left: position.left
16672
- }
16673
- }, /*#__PURE__*/ React__default.createElement(PopoverContent, {
16627
+ const popoverContent = /*#__PURE__*/ React__default.createElement(PopoverPortal, null, /*#__PURE__*/ React__default.createElement(PopoverContent, {
16674
16628
  "data-popover-content": true,
16675
- $arrowPosition: position.arrowPosition
16629
+ $arrowPosition: "left"
16676
16630
  }, /*#__PURE__*/ React__default.createElement(PopoverHeader, null, /*#__PURE__*/ React__default.createElement(PopoverTitle, null, /*#__PURE__*/ React__default.createElement(NodeIcon$3, null, getNodeIcon$1(nodeData.nodeType || "Agent", llOverviewDetails?.model_provider)), /*#__PURE__*/ React__default.createElement("span", null, nodeData.label, " Details")), /*#__PURE__*/ React__default.createElement(PopoverHeaderButtons, null, /*#__PURE__*/ React__default.createElement(CloseButton, {
16677
- onClick: onClose
16631
+ onClick: (e)=>{
16632
+ e.stopPropagation();
16633
+ onClose();
16634
+ }
16678
16635
  }, /*#__PURE__*/ React__default.createElement(X, {
16679
16636
  size: 16
16680
16637
  })))), /*#__PURE__*/ React__default.createElement(PopoverBody, null, llOverviewDetails && /*#__PURE__*/ React__default.createElement(Section, null, /*#__PURE__*/ React__default.createElement(InfoGrid, null, (()=>{
@@ -16818,14 +16775,20 @@ const NodeDetailsPopover = ({ isVisible, onClose, nodeData, triggerRef })=>{
16818
16775
  }), /*#__PURE__*/ React__default.createElement(OutputRenderer, {
16819
16776
  data: selectedLlmDetails.output
16820
16777
  })) : null))));
16821
- // Use React Portal to render outside of ReactFlow container
16822
- return /*#__PURE__*/ createPortal(popoverContent, document.body);
16778
+ return popoverContent;
16823
16779
  };
16824
16780
  // Styled components
16825
16781
  const PopoverPortal = styled.div`
16826
- position: fixed;
16782
+ position: absolute;
16783
+ left: calc(100% + 12px);
16784
+ top: 0;
16827
16785
  z-index: 99999;
16828
- pointer-events: none;
16786
+
16787
+ /* Position to the left of the node if there's not enough space on the right */
16788
+ @media (max-width: 768px) {
16789
+ left: auto;
16790
+ right: calc(100% + 12px);
16791
+ }
16829
16792
  `;
16830
16793
  const PopoverContent = styled.div`
16831
16794
  width: ${DEFAULT_POPOVER_WIDTH}px;
@@ -16861,7 +16824,7 @@ const PopoverContent = styled.div`
16861
16824
  height: 0;
16862
16825
  border-top: 6px solid transparent;
16863
16826
  border-bottom: 6px solid transparent;
16864
- ${props.$arrowPosition === "right" ? `
16827
+ ${props.$arrowPosition === "left" ? `
16865
16828
  left: -6px;
16866
16829
  border-right: 6px solid ${props.theme?.colors?.border || "hsl(214.3 31.8% 91.4%)"};
16867
16830
  ` : `
@@ -16878,7 +16841,7 @@ const PopoverContent = styled.div`
16878
16841
  height: 0;
16879
16842
  border-top: 6px solid transparent;
16880
16843
  border-bottom: 6px solid transparent;
16881
- ${props.$arrowPosition === "right" ? `
16844
+ ${props.$arrowPosition === "left" ? `
16882
16845
  left: -5px;
16883
16846
  border-right: 6px solid ${props.theme?.colors?.background || "hsl(0 0% 100%)"};
16884
16847
  ` : `
@@ -16959,7 +16922,7 @@ const PopoverHeaderButtons = styled.div`
16959
16922
  display: flex;
16960
16923
  align-items: center;
16961
16924
  gap: 0.5rem;
16962
- justify-content: flex-start;
16925
+ justify-content: flex-end;
16963
16926
  `;
16964
16927
  const CloseButton = styled.button`
16965
16928
  display: flex;
@@ -16973,6 +16936,8 @@ const CloseButton = styled.button`
16973
16936
  color: ${(props)=>props.theme?.colors?.mutedForeground || "hsl(215.4 16.3% 46.9%)"};
16974
16937
  cursor: pointer;
16975
16938
  transition: all 0.2s ease-in-out;
16939
+ pointer-events: auto;
16940
+ flex-shrink: 0;
16976
16941
 
16977
16942
  &:hover {
16978
16943
  background-color: ${(props)=>props.theme?.colors?.muted || "hsl(210 40% 96%)"};
@@ -16983,9 +16948,13 @@ const CloseButton = styled.button`
16983
16948
  outline: 2px solid ${(props)=>props.theme?.colors?.primary || "hsl(221.2 83.2% 53.3%)"};
16984
16949
  outline-offset: 2px;
16985
16950
  }
16951
+
16952
+ &:active {
16953
+ transform: scale(0.95);
16954
+ }
16986
16955
  `;
16987
16956
  const PopoverBody = styled.div`
16988
- max-height: 500px;
16957
+ max-height: 400px; /* Reduced by 100px to account for PopoverHeader and spacing */
16989
16958
  overflow-y: auto;
16990
16959
  padding: 1rem;
16991
16960
  display: flex;
@@ -16998,6 +16967,7 @@ const Section = styled.div`
16998
16967
  gap: 0.75rem;
16999
16968
  `;
17000
16969
  const FadingSection = styled(Section)`
16970
+ overflow-y: auto; /* Base style: enables scrolling after animation completes */
17001
16971
  animation:
17002
16972
  expandHeight 300ms ease-out,
17003
16973
  fadeInContent 200ms ease-in-out 200ms both;
@@ -17008,8 +16978,8 @@ const FadingSection = styled(Section)`
17008
16978
  overflow: hidden;
17009
16979
  }
17010
16980
  to {
17011
- max-height: 500px; /* Adjust based on expected content height */
17012
- overflow: visible;
16981
+ max-height: 350px; /* Reduced to fit within PopoverBody (400px) accounting for padding and gaps */
16982
+ overflow: hidden; /* Keep hidden during animation, base overflow-y: auto takes effect after */
17013
16983
  }
17014
16984
  }
17015
16985
 
@@ -17118,7 +17088,7 @@ const AgentNode = ({ data, id, onInspect })=>{
17118
17088
  return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(NodeContainer$2, {
17119
17089
  ref: nodeRef,
17120
17090
  onClick: handleNodeClick,
17121
- className: "nowheel"
17091
+ className: "nowheel agent-node"
17122
17092
  }, hasIncomingEdges && /*#__PURE__*/ React__default.createElement(Handle$1, {
17123
17093
  type: "target",
17124
17094
  position: Position.Top,
@@ -17151,15 +17121,14 @@ const AgentNode = ({ data, id, onInspect })=>{
17151
17121
  cursor: "default"
17152
17122
  },
17153
17123
  isConnectable: false
17154
- })), /*#__PURE__*/ React__default.createElement(NodeDetailsPopover, {
17124
+ }), /*#__PURE__*/ React__default.createElement(NodeDetailsPopover, {
17155
17125
  isVisible: isPopoverOpen,
17156
17126
  onClose: handleClosePopover,
17157
17127
  nodeData: {
17158
17128
  ...data,
17159
17129
  id: id
17160
- },
17161
- triggerRef: nodeRef
17162
- }));
17130
+ }
17131
+ })));
17163
17132
  };
17164
17133
  // Styled components
17165
17134
  const NodeContainer$2 = styled.div`
@@ -17168,9 +17137,9 @@ const NodeContainer$2 = styled.div`
17168
17137
  border: 2px solid ${(props)=>props.theme?.colors?.border || "hsl(214.3 31.8% 91.4%)"};
17169
17138
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
17170
17139
  min-width: 300px;
17140
+ max-width: ${NODE_MAX_WIDTH}px;
17171
17141
  transition: all 0.2s ease-in-out;
17172
17142
  position: relative;
17173
- cursor: pointer;
17174
17143
 
17175
17144
  &:hover {
17176
17145
  border-color: ${(props)=>props.theme?.colors?.primary || "hsl(221.2 83.2% 53.3%)"};
@@ -17351,15 +17320,15 @@ const ToolNode = ({ data, id, onInspect })=>{
17351
17320
  nodeData = {
17352
17321
  ...baseData,
17353
17322
  input: {
17354
- args: data.edgeDetails[0]?.input_args,
17355
- kwargs: data.edgeDetails[0]?.input_kwargs
17323
+ ...data.edgeDetails[0]?.input_kwargs
17356
17324
  },
17357
17325
  output: data.edgeDetails[0]?.output,
17358
17326
  status: data.edgeDetails[0]?.status
17359
17327
  };
17360
17328
  }
17361
17329
  return /*#__PURE__*/ React__default.createElement(NodeContainer, {
17362
- onClick: handleNodeClick
17330
+ onClick: handleNodeClick,
17331
+ className: "nowheel"
17363
17332
  }, hasIncomingEdges && /*#__PURE__*/ React__default.createElement(Handle$1, {
17364
17333
  type: "target",
17365
17334
  position: Position.Top,
@@ -17400,6 +17369,7 @@ const NodeContainer = styled.div`
17400
17369
  border: 2px solid ${(props)=>props.theme?.colors?.border || "hsl(214.3 31.8% 91.4%)"};
17401
17370
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
17402
17371
  min-width: 300px;
17372
+ max-width: ${NODE_MAX_WIDTH}px;
17403
17373
  transition: all 0.2s ease-in-out;
17404
17374
  position: relative;
17405
17375
  cursor: pointer;
@@ -20671,7 +20641,7 @@ const AgenticFlowVisualizer = ({ flowData: propFlowData, width = "100dvw", heigh
20671
20641
  ]);
20672
20642
  // Pan to specific node when panToNodeId prop is provided
20673
20643
  useEffect(()=>{
20674
- if (!panToNodeId || !reactFlowInstance || disableAutoFit || nodes.length === 0) {
20644
+ if (!panToNodeId || !reactFlowInstance || nodes.length === 0) {
20675
20645
  return;
20676
20646
  }
20677
20647
  // Check if the specified node ID exists in the current nodes array
@@ -20696,7 +20666,6 @@ const AgenticFlowVisualizer = ({ flowData: propFlowData, width = "100dvw", heigh
20696
20666
  }, [
20697
20667
  panToNodeId,
20698
20668
  reactFlowInstance,
20699
- disableAutoFit,
20700
20669
  nodes,
20701
20670
  defaultAutoFitDuration,
20702
20671
  defaultAutoFitDelay,
@@ -20710,8 +20679,6 @@ const AgenticFlowVisualizer = ({ flowData: propFlowData, width = "100dvw", heigh
20710
20679
  minWidth: "800px",
20711
20680
  minHeight: "600px",
20712
20681
  boxSizing: "border-box",
20713
- border: `1px solid ${themeColors.border}`,
20714
- borderRadius: "8px",
20715
20682
  overflow: "hidden",
20716
20683
  position: "relative",
20717
20684
  background: themeColors.background
@@ -20832,6 +20799,7 @@ const AgenticFlowVisualizer = ({ flowData: propFlowData, width = "100dvw", heigh
20832
20799
  colorMode: isDarkMode ? "dark" : "light",
20833
20800
  nodes: nodesState,
20834
20801
  edges: edgesState,
20802
+ minZoom: 0.2,
20835
20803
  onNodesChange: onNodesChange,
20836
20804
  onEdgesChange: onEdgesChange,
20837
20805
  onConnect: onConnect,
@@ -20862,6 +20830,7 @@ const AgenticFlowVisualizer = ({ flowData: propFlowData, width = "100dvw", heigh
20862
20830
  }, /*#__PURE__*/ React__default.createElement(Background, {
20863
20831
  variant: BackgroundVariant.Dots,
20864
20832
  color: themeColors.mutedBorder,
20833
+ bgColor: themeColors.background,
20865
20834
  size: 3
20866
20835
  })), /*#__PURE__*/ React__default.createElement("style", null, `
20867
20836
  .react-flow__edge-label {
@@ -24567,7 +24536,9 @@ var ScrollDownButton = SelectScrollDownButton$1;
24567
24536
  var Separator = SelectSeparator$1;
24568
24537
 
24569
24538
  const Select = Root2;
24570
- const SelectValue = Value;
24539
+ const SelectValue = styled(Value)`
24540
+ font-family: inherit;
24541
+ `;
24571
24542
  const SelectTrigger = styled(Trigger)`
24572
24543
  display: flex;
24573
24544
  height: 2.5rem;
@@ -24597,6 +24568,7 @@ const SelectTrigger = styled(Trigger)`
24597
24568
  }
24598
24569
 
24599
24570
  &[data-placeholder] {
24571
+ font-family: inherit;
24600
24572
  color: ${(props)=>props.$theme.colors.mutedForeground};
24601
24573
  }
24602
24574
  `;