@railtownai/railtracks-visualizer 0.0.34 → 0.0.37

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/README.md CHANGED
@@ -70,4 +70,4 @@ See [LICENSE](LICENSE)
70
70
 
71
71
  ## 📞 Support
72
72
 
73
- For issues and questions, please open an issue on GitHub.
73
+ For issues and questions, please [open an issue on GitHub](https://github.com/RailtownAI/railtracks-visualizer/issues).
package/dist/cjs/index.js CHANGED
@@ -3358,27 +3358,25 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [
3358
3358
  * Determines a bounding box that contains all given nodes in an array
3359
3359
  * @internal
3360
3360
  */ const getInternalNodesBounds = (nodeLookup, params = {})=>{
3361
- if (nodeLookup.size === 0) {
3362
- return {
3363
- x: 0,
3364
- y: 0,
3365
- width: 0,
3366
- height: 0
3367
- };
3368
- }
3369
3361
  let box = {
3370
3362
  x: Infinity,
3371
3363
  y: Infinity,
3372
3364
  x2: -Infinity,
3373
3365
  y2: -Infinity
3374
3366
  };
3367
+ let hasVisibleNodes = false;
3375
3368
  nodeLookup.forEach((node)=>{
3376
3369
  if (params.filter === undefined || params.filter(node)) {
3377
- const nodeBox = nodeToBox(node);
3378
- box = getBoundsOfBoxes(box, nodeBox);
3370
+ box = getBoundsOfBoxes(box, nodeToBox(node));
3371
+ hasVisibleNodes = true;
3379
3372
  }
3380
3373
  });
3381
- return boxToRect(box);
3374
+ return hasVisibleNodes ? boxToRect(box) : {
3375
+ x: 0,
3376
+ y: 0,
3377
+ width: 0,
3378
+ height: 0
3379
+ };
3382
3380
  };
3383
3381
  const getNodesInside = (nodes, rect, [tx, ty, tScale] = [
3384
3382
  0,
@@ -4123,7 +4121,7 @@ function getEdgeCenter({ sourceX, sourceY, targetX, targetY }) {
4123
4121
  return zIndex;
4124
4122
  }
4125
4123
  const edgeZ = elevateOnSelect && selected ? 1000 : 0;
4126
- const nodeZ = Math.max(sourceNode.parentId ? sourceNode.internals.z : 0, targetNode.parentId ? targetNode.internals.z : 0);
4124
+ const nodeZ = Math.max(sourceNode.parentId || elevateOnSelect && sourceNode.selected ? sourceNode.internals.z : 0, targetNode.parentId || elevateOnSelect && targetNode.selected ? targetNode.internals.z : 0);
4127
4125
  return edgeZ + nodeZ;
4128
4126
  }
4129
4127
  function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
@@ -4639,6 +4637,8 @@ function createMarkerIds(edges, { id, defaultColor, defaultMarkerStart, defaultM
4639
4637
  return markers;
4640
4638
  }, []).sort((a, b)=>a.id.localeCompare(b.id));
4641
4639
  }
4640
+ const SELECTED_NODE_Z = 1000;
4641
+ const ROOT_PARENT_Z_INCREMENT = 10;
4642
4642
  const defaultOptions = {
4643
4643
  nodeOrigin: [
4644
4644
  0,
@@ -4677,11 +4677,42 @@ function updateAbsolutePositions(nodeLookup, parentLookup, options) {
4677
4677
  }
4678
4678
  }
4679
4679
  }
4680
+ function parseHandles(userNode, internalNode) {
4681
+ if (!userNode.handles) {
4682
+ return !userNode.measured ? undefined : internalNode?.internals.handleBounds;
4683
+ }
4684
+ const source = [];
4685
+ const target = [];
4686
+ for (const handle of userNode.handles){
4687
+ const handleBounds = {
4688
+ id: handle.id,
4689
+ width: handle.width ?? 1,
4690
+ height: handle.height ?? 1,
4691
+ nodeId: userNode.id,
4692
+ x: handle.x,
4693
+ y: handle.y,
4694
+ position: handle.position,
4695
+ type: handle.type
4696
+ };
4697
+ if (handle.type === 'source') {
4698
+ source.push(handleBounds);
4699
+ } else if (handle.type === 'target') {
4700
+ target.push(handleBounds);
4701
+ }
4702
+ }
4703
+ return {
4704
+ source,
4705
+ target
4706
+ };
4707
+ }
4680
4708
  function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4681
4709
  const _options = mergeObjects(adoptUserNodesDefaultOptions, options);
4710
+ let rootParentIndex = {
4711
+ i: -1
4712
+ };
4682
4713
  let nodesInitialized = nodes.length > 0;
4683
4714
  const tmpLookup = new Map(nodeLookup);
4684
- const selectedNodeZ = _options?.elevateNodesOnSelect ? 1000 : 0;
4715
+ const selectedNodeZ = _options?.elevateNodesOnSelect ? SELECTED_NODE_Z : 0;
4685
4716
  nodeLookup.clear();
4686
4717
  parentLookup.clear();
4687
4718
  for (const userNode of nodes){
@@ -4702,7 +4733,7 @@ function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4702
4733
  internals: {
4703
4734
  positionAbsolute: clampedPosition,
4704
4735
  // if user re-initializes the node or removes `measured` for whatever reason, we reset the handleBounds so that the node gets re-measured
4705
- handleBounds: !userNode.measured ? undefined : internalNode?.internals.handleBounds,
4736
+ handleBounds: parseHandles(userNode, internalNode),
4706
4737
  z: calculateZ(userNode, selectedNodeZ),
4707
4738
  userNode
4708
4739
  }
@@ -4713,7 +4744,7 @@ function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4713
4744
  nodesInitialized = false;
4714
4745
  }
4715
4746
  if (userNode.parentId) {
4716
- updateChildNode(internalNode, nodeLookup, parentLookup, options);
4747
+ updateChildNode(internalNode, nodeLookup, parentLookup, options, rootParentIndex);
4717
4748
  }
4718
4749
  }
4719
4750
  return nodesInitialized;
@@ -4736,7 +4767,7 @@ function updateParentLookup(node, parentLookup) {
4736
4767
  }
4737
4768
  /**
4738
4769
  * Updates positionAbsolute and zIndex of a child node and the parentLookup.
4739
- */ function updateChildNode(node, nodeLookup, parentLookup, options) {
4770
+ */ function updateChildNode(node, nodeLookup, parentLookup, options, rootParentIndex) {
4740
4771
  const { elevateNodesOnSelect, nodeOrigin, nodeExtent } = mergeObjects(defaultOptions, options);
4741
4772
  const parentId = node.parentId;
4742
4773
  const parentNode = nodeLookup.get(parentId);
@@ -4745,7 +4776,16 @@ function updateParentLookup(node, parentLookup) {
4745
4776
  return;
4746
4777
  }
4747
4778
  updateParentLookup(node, parentLookup);
4748
- const selectedNodeZ = elevateNodesOnSelect ? 1000 : 0;
4779
+ // We just want to set the rootParentIndex for the first child
4780
+ if (rootParentIndex && !parentNode.parentId && parentNode.internals.rootParentIndex === undefined) {
4781
+ parentNode.internals.rootParentIndex = ++rootParentIndex.i;
4782
+ parentNode.internals.z = parentNode.internals.z + rootParentIndex.i * ROOT_PARENT_Z_INCREMENT;
4783
+ }
4784
+ // But we need to update rootParentIndex.i also when parent has not been updated
4785
+ if (rootParentIndex && parentNode.internals.rootParentIndex !== undefined) {
4786
+ rootParentIndex.i = parentNode.internals.rootParentIndex;
4787
+ }
4788
+ const selectedNodeZ = elevateNodesOnSelect ? SELECTED_NODE_Z : 0;
4749
4789
  const { x, y, z } = calculateChildXYZ(node, parentNode, nodeOrigin, nodeExtent, selectedNodeZ);
4750
4790
  const { positionAbsolute } = node.internals;
4751
4791
  const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
@@ -5319,8 +5359,10 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
5319
5359
  autoPan();
5320
5360
  }
5321
5361
  if (!dragStarted) {
5322
- const x = pointerPos.xSnapped - (lastPos.x ?? 0);
5323
- const y = pointerPos.ySnapped - (lastPos.y ?? 0);
5362
+ // Calculate distance in client coordinates for consistent drag threshold behavior across zoom levels
5363
+ const currentMousePosition = getEventPosition(event.sourceEvent, containerBounds);
5364
+ const x = currentMousePosition.x - mousePosition.x;
5365
+ const y = currentMousePosition.y - mousePosition.y;
5324
5366
  const distance = Math.sqrt(x * x + y * y);
5325
5367
  if (distance > nodeDragThreshold) {
5326
5368
  startDrag(event);
@@ -5604,6 +5646,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
5604
5646
  previousConnection = newConnection;
5605
5647
  }
5606
5648
  function onPointerUp(event) {
5649
+ // Prevent multi-touch aborting connection
5650
+ if ('touches' in event && event.touches.length > 0) {
5651
+ return;
5652
+ }
5607
5653
  if (connectionStarted) {
5608
5654
  if ((closestHandle || resultHandleDomNode) && connection && isValid) {
5609
5655
  onConnect?.(connection);
@@ -5761,8 +5807,7 @@ function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
5761
5807
  pointer
5762
5808
  };
5763
5809
  }
5764
- /* eslint-disable @typescript-eslint/no-explicit-any */ const viewChanged = (prevViewport, eventViewport)=>prevViewport.x !== eventViewport.x || prevViewport.y !== eventViewport.y || prevViewport.zoom !== eventViewport.k;
5765
- const transformToViewport = (transform)=>({
5810
+ /* eslint-disable @typescript-eslint/no-explicit-any */ const transformToViewport = (transform)=>({
5766
5811
  x: transform.x,
5767
5812
  y: transform.y,
5768
5813
  zoom: transform.k
@@ -5786,6 +5831,9 @@ const wheelDelta = (event)=>{
5786
5831
  function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection, d3Zoom, panOnScrollMode, panOnScrollSpeed, zoomOnPinch, onPanZoomStart, onPanZoom, onPanZoomEnd }) {
5787
5832
  return (event)=>{
5788
5833
  if (isWrappedWithClass(event, noWheelClassName)) {
5834
+ if (event.ctrlKey) {
5835
+ event.preventDefault(); // stop native page zoom for pinch zooming
5836
+ }
5789
5837
  return false;
5790
5838
  }
5791
5839
  event.preventDefault();
@@ -5824,8 +5872,7 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
5824
5872
  */ if (!zoomPanValues.isPanScrolling) {
5825
5873
  zoomPanValues.isPanScrolling = true;
5826
5874
  onPanZoomStart?.(event, nextViewport);
5827
- }
5828
- if (zoomPanValues.isPanScrolling) {
5875
+ } else {
5829
5876
  onPanZoom?.(event, nextViewport);
5830
5877
  zoomPanValues.panScrollTimeout = setTimeout(()=>{
5831
5878
  onPanZoomEnd?.(event, nextViewport);
@@ -5895,7 +5942,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5895
5942
  }
5896
5943
  zoomPanValues.usedRightMouseButton = false;
5897
5944
  onDraggingChange(false);
5898
- if (onPanZoomEnd && viewChanged(zoomPanValues.prevViewport, event.transform)) {
5945
+ if (onPanZoomEnd) {
5899
5946
  const viewport = transformToViewport(event.transform);
5900
5947
  zoomPanValues.prevViewport = viewport;
5901
5948
  clearTimeout(zoomPanValues.timerId);
@@ -5906,10 +5953,11 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5906
5953
  }
5907
5954
  };
5908
5955
  }
5909
- /* eslint-disable @typescript-eslint/no-explicit-any */ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib }) {
5956
+ /* eslint-disable @typescript-eslint/no-explicit-any */ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib, connectionInProgress }) {
5910
5957
  return (event)=>{
5911
5958
  const zoomScroll = zoomActivationKeyPressed || zoomOnScroll;
5912
5959
  const pinchZoom = zoomOnPinch && event.ctrlKey;
5960
+ const isWheelEvent = event.type === 'wheel';
5913
5961
  if (event.button === 1 && event.type === 'mousedown' && (isWrappedWithClass(event, `${lib}-flow__node`) || isWrappedWithClass(event, `${lib}-flow__edge`))) {
5914
5962
  return true;
5915
5963
  }
@@ -5921,15 +5969,19 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5921
5969
  if (userSelectionActive) {
5922
5970
  return false;
5923
5971
  }
5972
+ // we want to disable pinch-zooming while making a connection
5973
+ if (connectionInProgress && !isWheelEvent) {
5974
+ return false;
5975
+ }
5924
5976
  // if the target element is inside an element with the nowheel class, we prevent zooming
5925
- if (isWrappedWithClass(event, noWheelClassName) && event.type === 'wheel') {
5977
+ if (isWrappedWithClass(event, noWheelClassName) && isWheelEvent) {
5926
5978
  return false;
5927
5979
  }
5928
5980
  // if the target element is inside an element with the nopan class, we prevent panning
5929
- if (isWrappedWithClass(event, noPanClassName) && (event.type !== 'wheel' || panOnScroll && event.type === 'wheel' && !zoomActivationKeyPressed)) {
5981
+ if (isWrappedWithClass(event, noPanClassName) && (!isWheelEvent || panOnScroll && isWheelEvent && !zoomActivationKeyPressed)) {
5930
5982
  return false;
5931
5983
  }
5932
- if (!zoomOnPinch && event.ctrlKey && event.type === 'wheel') {
5984
+ if (!zoomOnPinch && event.ctrlKey && isWheelEvent) {
5933
5985
  return false;
5934
5986
  }
5935
5987
  if (!zoomOnPinch && event.type === 'touchstart' && event.touches?.length > 1) {
@@ -5937,7 +5989,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5937
5989
  return false;
5938
5990
  }
5939
5991
  // when there is no scroll handling enabled, we prevent all wheel events
5940
- if (!zoomScroll && !panOnScroll && !pinchZoom && event.type === 'wheel') {
5992
+ if (!zoomScroll && !panOnScroll && !pinchZoom && isWheelEvent) {
5941
5993
  return false;
5942
5994
  }
5943
5995
  // if the pane is not movable, we prevent dragging it with mousestart or touchstart
@@ -5951,7 +6003,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5951
6003
  // We only allow right clicks if pan on drag is set to right click
5952
6004
  const buttonAllowed = Array.isArray(panOnDrag) && panOnDrag.includes(event.button) || !event.button || event.button <= 1;
5953
6005
  // default filter for d3-zoom
5954
- return (!event.ctrlKey || event.type === 'wheel') && buttonAllowed;
6006
+ return (!event.ctrlKey || isWheelEvent) && buttonAllowed;
5955
6007
  };
5956
6008
  }
5957
6009
  function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExtent, viewport, onPanZoom, onPanZoomStart, onPanZoomEnd, onDraggingChange }) {
@@ -5959,10 +6011,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
5959
6011
  isZoomingOrPanning: false,
5960
6012
  usedRightMouseButton: false,
5961
6013
  prevViewport: {
5962
- x: 0,
5963
- y: 0,
5964
- zoom: 0
5965
- },
6014
+ },
5966
6015
  mouseButton: 0,
5967
6016
  timerId: undefined,
5968
6017
  panScrollTimeout: undefined,
@@ -6000,7 +6049,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
6000
6049
  return Promise.resolve(false);
6001
6050
  }
6002
6051
  // public functions
6003
- function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange }) {
6052
+ function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange, connectionInProgress }) {
6004
6053
  if (userSelectionActive && !zoomPanValues.isZoomingOrPanning) {
6005
6054
  destroy();
6006
6055
  }
@@ -6062,7 +6111,8 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
6062
6111
  userSelectionActive,
6063
6112
  noPanClassName,
6064
6113
  noWheelClassName,
6065
- lib
6114
+ lib,
6115
+ connectionInProgress
6066
6116
  });
6067
6117
  d3ZoomInstance.filter(filter);
6068
6118
  /*
@@ -6408,6 +6458,17 @@ function nodeToChildExtent(child, parent, nodeOrigin) {
6408
6458
  }
6409
6459
  function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6410
6460
  const selection = select(domNode);
6461
+ let params = {
6462
+ controlDirection: getControlDirection('bottom-right'),
6463
+ boundaries: {
6464
+ minWidth: 0,
6465
+ minHeight: 0,
6466
+ maxWidth: Number.MAX_VALUE,
6467
+ maxHeight: Number.MAX_VALUE
6468
+ },
6469
+ resizeDirection: undefined,
6470
+ keepAspectRatio: false
6471
+ };
6411
6472
  function update({ controlPosition, boundaries, keepAspectRatio, resizeDirection, onResizeStart, onResize, onResizeEnd, shouldResize }) {
6412
6473
  let prevValues = {
6413
6474
  ...initPrevValues$1
@@ -6415,13 +6476,20 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6415
6476
  let startValues = {
6416
6477
  ...initStartValues
6417
6478
  };
6418
- const controlDirection = getControlDirection(controlPosition);
6479
+ params = {
6480
+ boundaries,
6481
+ resizeDirection,
6482
+ keepAspectRatio,
6483
+ controlDirection: getControlDirection(controlPosition)
6484
+ };
6419
6485
  let node = undefined;
6420
6486
  let containerBounds = null;
6421
6487
  let childNodes = [];
6422
6488
  let parentNode = undefined; // Needed to fix expandParent
6423
6489
  let parentExtent = undefined;
6424
6490
  let childExtent = undefined;
6491
+ // we only want to trigger onResizeEnd if onResize was actually called
6492
+ let resizeDetected = false;
6425
6493
  const dragHandler = drag().on('start', (event)=>{
6426
6494
  const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, paneDomNode } = getStoreItems();
6427
6495
  node = nodeLookup.get(nodeId);
@@ -6503,7 +6571,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6503
6571
  const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
6504
6572
  const change = {};
6505
6573
  const nodeOrigin = node.origin ?? storeNodeOrigin;
6506
- const { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent);
6574
+ const { width, height, x, y } = getDimensionsAfterResize(startValues, params.controlDirection, pointerPosition, params.boundaries, params.keepAspectRatio, nodeOrigin, parentExtent, childExtent);
6507
6575
  const isWidthChange = width !== prevWidth;
6508
6576
  const isHeightChange = height !== prevHeight;
6509
6577
  const isXPosChange = x !== prevX && isWidthChange;
@@ -6532,8 +6600,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6532
6600
  }
6533
6601
  }
6534
6602
  if (isWidthChange || isHeightChange) {
6535
- change.width = isWidthChange && (!resizeDirection || resizeDirection === 'horizontal') ? width : prevValues.width;
6536
- change.height = isHeightChange && (!resizeDirection || resizeDirection === 'vertical') ? height : prevValues.height;
6603
+ change.width = isWidthChange && (!params.resizeDirection || params.resizeDirection === 'horizontal') ? width : prevValues.width;
6604
+ change.height = isHeightChange && (!params.resizeDirection || params.resizeDirection === 'vertical') ? height : prevValues.height;
6537
6605
  prevValues.width = change.width;
6538
6606
  prevValues.height = change.height;
6539
6607
  }
@@ -6555,8 +6623,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6555
6623
  prevWidth,
6556
6624
  height: prevValues.height,
6557
6625
  prevHeight,
6558
- affectsX: controlDirection.affectsX,
6559
- affectsY: controlDirection.affectsY
6626
+ affectsX: params.controlDirection.affectsX,
6627
+ affectsY: params.controlDirection.affectsY
6560
6628
  });
6561
6629
  const nextValues = {
6562
6630
  ...prevValues,
@@ -6566,15 +6634,20 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6566
6634
  if (callResize === false) {
6567
6635
  return;
6568
6636
  }
6637
+ resizeDetected = true;
6569
6638
  onResize?.(event, nextValues);
6570
6639
  onChange(change, childChanges);
6571
6640
  }).on('end', (event)=>{
6641
+ if (!resizeDetected) {
6642
+ return;
6643
+ }
6572
6644
  onResizeEnd?.(event, {
6573
6645
  ...prevValues
6574
6646
  });
6575
6647
  onEnd?.({
6576
6648
  ...prevValues
6577
6649
  });
6650
+ resizeDetected = false;
6578
6651
  });
6579
6652
  selection.call(dragHandler);
6580
6653
  }
@@ -8195,7 +8268,11 @@ const selector$k = (s)=>!!s.panZoom;
8195
8268
  deletedEdges: matchingEdges
8196
8269
  };
8197
8270
  },
8198
- getIntersectingNodes: (nodeOrRect, partially = true, nodes)=>{
8271
+ /**
8272
+ * Partial is defined as "the 2 nodes/areas are intersecting partially".
8273
+ * If a is contained in b or b is contained in a, they are both
8274
+ * considered fully intersecting.
8275
+ */ getIntersectingNodes: (nodeOrRect, partially = true, nodes)=>{
8199
8276
  const isRect = isRectObject(nodeOrRect);
8200
8277
  const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
8201
8278
  const hasNodesOption = nodes !== undefined;
@@ -8221,7 +8298,7 @@ const selector$k = (s)=>!!s.panZoom;
8221
8298
  }
8222
8299
  const overlappingArea = getOverlappingArea(nodeRect, area);
8223
8300
  const partiallyVisible = partially && overlappingArea > 0;
8224
- return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
8301
+ return partiallyVisible || overlappingArea >= area.width * area.height || overlappingArea >= nodeRect.width * nodeRect.height;
8225
8302
  },
8226
8303
  updateNode,
8227
8304
  updateNodeData: (id, dataUpdate, options = {
@@ -8340,7 +8417,7 @@ const win$1 = typeof window !== 'undefined' ? window : undefined;
8340
8417
  const store = useStoreApi();
8341
8418
  React.useEffect(()=>{
8342
8419
  const updateDimensions = ()=>{
8343
- if (!domNode.current) {
8420
+ if (!domNode.current || !(domNode.current.checkVisibility?.() ?? true)) {
8344
8421
  return false;
8345
8422
  }
8346
8423
  const size = getDimensions$1(domNode.current);
@@ -8375,12 +8452,13 @@ const containerStyle = {
8375
8452
  };
8376
8453
  const selector$j = (s)=>({
8377
8454
  userSelectionActive: s.userSelectionActive,
8378
- lib: s.lib
8455
+ lib: s.lib,
8456
+ connectionInProgress: s.connection.inProgress
8379
8457
  });
8380
8458
  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 }) {
8381
8459
  const store = useStoreApi();
8382
8460
  const zoomPane = React.useRef(null);
8383
- const { userSelectionActive, lib } = useStore(selector$j, shallow$1);
8461
+ const { userSelectionActive, lib, connectionInProgress } = useStore(selector$j, shallow$1);
8384
8462
  const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode);
8385
8463
  const panZoom = React.useRef();
8386
8464
  useResizeHandler(zoomPane);
@@ -8458,7 +8536,8 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8458
8536
  userSelectionActive,
8459
8537
  noWheelClassName,
8460
8538
  lib,
8461
- onTransformChange
8539
+ onTransformChange,
8540
+ connectionInProgress
8462
8541
  });
8463
8542
  }, [
8464
8543
  onPaneContextMenu,
@@ -8475,7 +8554,8 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8475
8554
  userSelectionActive,
8476
8555
  noWheelClassName,
8477
8556
  lib,
8478
- onTransformChange
8557
+ onTransformChange,
8558
+ connectionInProgress
8479
8559
  ]);
8480
8560
  return jsxRuntime.jsx("div", {
8481
8561
  className: "react-flow__renderer",
@@ -8549,12 +8629,25 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8549
8629
  onPaneContextMenu?.(event);
8550
8630
  };
8551
8631
  const onWheel = onPaneScroll ? (event)=>onPaneScroll(event) : undefined;
8552
- const onPointerDown = (event)=>{
8632
+ const onClickCapture = (event)=>{
8633
+ const isSelectionOnDragActive = selectionOnDrag && container.current === event.target || !selectionOnDrag || selectionKeyPressed;
8634
+ if (!isSelectionOnDragActive) {
8635
+ return;
8636
+ }
8637
+ event.stopPropagation();
8638
+ };
8639
+ // We are using capture here in order to prevent other pointer events
8640
+ // to be able to create a selection above a node or an edge
8641
+ const onPointerDownCapture = (event)=>{
8553
8642
  const { resetSelectedElements, domNode } = store.getState();
8554
8643
  containerBounds.current = domNode?.getBoundingClientRect();
8555
- if (!elementsSelectable || !isSelecting || event.button !== 0 || event.target !== container.current || !containerBounds.current) {
8644
+ const isNoKeyEvent = event.target !== container.current && !!event.target.closest('.nokey');
8645
+ const isSelectionActive = selectionOnDrag && container.current === event.target || !selectionOnDrag || selectionKeyPressed;
8646
+ if (!elementsSelectable || !isSelecting || event.button !== 0 || !containerBounds.current || isNoKeyEvent || !isSelectionActive || !event.isPrimary) {
8556
8647
  return;
8557
8648
  }
8649
+ event.stopPropagation();
8650
+ event.preventDefault();
8558
8651
  event.target?.setPointerCapture?.(event.pointerId);
8559
8652
  selectionStarted.current = true;
8560
8653
  selectionInProgress.current = false;
@@ -8658,9 +8751,10 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8658
8751
  onContextMenu: wrapHandler(onContextMenu, container),
8659
8752
  onWheel: wrapHandler(onWheel, container),
8660
8753
  onPointerEnter: hasActiveSelection ? undefined : onPaneMouseEnter,
8661
- onPointerDown: hasActiveSelection ? onPointerDown : onPaneMouseMove,
8662
8754
  onPointerMove: hasActiveSelection ? onPointerMove : onPaneMouseMove,
8663
8755
  onPointerUp: hasActiveSelection ? onPointerUp : undefined,
8756
+ onPointerDownCapture: hasActiveSelection ? onPointerDownCapture : undefined,
8757
+ onClickCapture: hasActiveSelection ? onClickCapture : undefined,
8664
8758
  onPointerLeave: onPaneMouseLeave,
8665
8759
  ref: container,
8666
8760
  style: containerStyle,
@@ -9549,6 +9643,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
9549
9643
  })
9550
9644
  });
9551
9645
  }
9646
+ var NodeWrapper$1 = React.memo(NodeWrapper);
9552
9647
  const selector$b = (s)=>({
9553
9648
  nodesDraggable: s.nodesDraggable,
9554
9649
  nodesConnectable: s.nodesConnectable,
@@ -9588,7 +9683,7 @@ function NodeRendererComponent(props) {
9588
9683
  * moved into `NodeComponentWrapper`. This ensures they are
9589
9684
  * memorized – so if `NodeRenderer` *has* to rerender, it only
9590
9685
  * needs to regenerate the list of nodes, nothing else.
9591
- */ jsxRuntime.jsx(NodeWrapper, {
9686
+ */ jsxRuntime.jsx(NodeWrapper$1, {
9592
9687
  id: nodeId,
9593
9688
  nodeTypes: props.nodeTypes,
9594
9689
  nodeExtent: props.nodeExtent,
@@ -10582,6 +10677,7 @@ function EdgeWrapper({ id, edgesFocusable, edgesReconnectable, elementsSelectabl
10582
10677
  })
10583
10678
  });
10584
10679
  }
10680
+ var EdgeWrapper$1 = React.memo(EdgeWrapper);
10585
10681
  const selector$a = (s)=>({
10586
10682
  edgesFocusable: s.edgesFocusable,
10587
10683
  edgesReconnectable: s.edgesReconnectable,
@@ -10600,7 +10696,7 @@ function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements,
10600
10696
  rfId: rfId
10601
10697
  }),
10602
10698
  edgeIds.map((id)=>{
10603
- return jsxRuntime.jsx(EdgeWrapper, {
10699
+ return jsxRuntime.jsx(EdgeWrapper$1, {
10604
10700
  id: id,
10605
10701
  edgesFocusable: edgesFocusable,
10606
10702
  edgesReconnectable: edgesReconnectable,
@@ -10985,8 +11081,8 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
10985
11081
  }
10986
11082
  return {
10987
11083
  rfId: '1',
10988
- width: 0,
10989
- height: 0,
11084
+ width: width ?? 0,
11085
+ height: height ?? 0,
10990
11086
  transform,
10991
11087
  nodes: storeNodes,
10992
11088
  nodesInitialized,
@@ -12600,7 +12696,7 @@ var css_248z = "/* this gets exported as style.css and can be used for the defau
12600
12696
  styleInject(css_248z);
12601
12697
 
12602
12698
  /**
12603
- * @license lucide-react v0.542.0 - ISC
12699
+ * @license lucide-react v0.546.0 - ISC
12604
12700
  *
12605
12701
  * This source code is licensed under the ISC license.
12606
12702
  * See the LICENSE file in the root directory of this source tree.
@@ -12622,7 +12718,7 @@ const hasA11yProp = (props)=>{
12622
12718
  };
12623
12719
 
12624
12720
  /**
12625
- * @license lucide-react v0.542.0 - ISC
12721
+ * @license lucide-react v0.546.0 - ISC
12626
12722
  *
12627
12723
  * This source code is licensed under the ISC license.
12628
12724
  * See the LICENSE file in the root directory of this source tree.
@@ -19632,7 +19728,7 @@ var correctTargets = function(parent, targets) {
19632
19728
  };
19633
19729
 
19634
19730
  var DIALOG_NAME = "Dialog";
19635
- var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
19731
+ var [createDialogContext] = createContextScope(DIALOG_NAME);
19636
19732
  var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
19637
19733
  var Dialog = (props)=>{
19638
19734
  const { __scopeDialog, children, open: openProp, defaultOpen, onOpenChange, modal = true } = props;
@@ -23372,7 +23468,7 @@ var SELECTION_KEYS = [
23372
23468
  ];
23373
23469
  var SELECT_NAME = "Select";
23374
23470
  var [Collection, useCollection, createCollectionScope] = createCollection(SELECT_NAME);
23375
- var [createSelectContext, createSelectScope] = createContextScope(SELECT_NAME, [
23471
+ var [createSelectContext] = createContextScope(SELECT_NAME, [
23376
23472
  createCollectionScope,
23377
23473
  createPopperScope
23378
23474
  ]);
@@ -24888,7 +24984,7 @@ const FileSelector = ({ files, currentFile, onFileSelect, onRefresh, loading = f
24888
24984
  };
24889
24985
 
24890
24986
  var CHECKBOX_NAME = "Checkbox";
24891
- var [createCheckboxContext, createCheckboxScope] = createContextScope(CHECKBOX_NAME);
24987
+ var [createCheckboxContext] = createContextScope(CHECKBOX_NAME);
24892
24988
  var [CheckboxProviderImpl, useCheckboxContext] = createCheckboxContext(CHECKBOX_NAME);
24893
24989
  function CheckboxProvider(props) {
24894
24990
  const { __scopeCheckbox, checked: checkedProp, children, defaultChecked, disabled, form, name, onCheckedChange, required, value = "on", // @ts-expect-error
package/dist/esm/index.js CHANGED
@@ -3338,27 +3338,25 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [
3338
3338
  * Determines a bounding box that contains all given nodes in an array
3339
3339
  * @internal
3340
3340
  */ const getInternalNodesBounds = (nodeLookup, params = {})=>{
3341
- if (nodeLookup.size === 0) {
3342
- return {
3343
- x: 0,
3344
- y: 0,
3345
- width: 0,
3346
- height: 0
3347
- };
3348
- }
3349
3341
  let box = {
3350
3342
  x: Infinity,
3351
3343
  y: Infinity,
3352
3344
  x2: -Infinity,
3353
3345
  y2: -Infinity
3354
3346
  };
3347
+ let hasVisibleNodes = false;
3355
3348
  nodeLookup.forEach((node)=>{
3356
3349
  if (params.filter === undefined || params.filter(node)) {
3357
- const nodeBox = nodeToBox(node);
3358
- box = getBoundsOfBoxes(box, nodeBox);
3350
+ box = getBoundsOfBoxes(box, nodeToBox(node));
3351
+ hasVisibleNodes = true;
3359
3352
  }
3360
3353
  });
3361
- return boxToRect(box);
3354
+ return hasVisibleNodes ? boxToRect(box) : {
3355
+ x: 0,
3356
+ y: 0,
3357
+ width: 0,
3358
+ height: 0
3359
+ };
3362
3360
  };
3363
3361
  const getNodesInside = (nodes, rect, [tx, ty, tScale] = [
3364
3362
  0,
@@ -4103,7 +4101,7 @@ function getEdgeCenter({ sourceX, sourceY, targetX, targetY }) {
4103
4101
  return zIndex;
4104
4102
  }
4105
4103
  const edgeZ = elevateOnSelect && selected ? 1000 : 0;
4106
- const nodeZ = Math.max(sourceNode.parentId ? sourceNode.internals.z : 0, targetNode.parentId ? targetNode.internals.z : 0);
4104
+ const nodeZ = Math.max(sourceNode.parentId || elevateOnSelect && sourceNode.selected ? sourceNode.internals.z : 0, targetNode.parentId || elevateOnSelect && targetNode.selected ? targetNode.internals.z : 0);
4107
4105
  return edgeZ + nodeZ;
4108
4106
  }
4109
4107
  function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
@@ -4619,6 +4617,8 @@ function createMarkerIds(edges, { id, defaultColor, defaultMarkerStart, defaultM
4619
4617
  return markers;
4620
4618
  }, []).sort((a, b)=>a.id.localeCompare(b.id));
4621
4619
  }
4620
+ const SELECTED_NODE_Z = 1000;
4621
+ const ROOT_PARENT_Z_INCREMENT = 10;
4622
4622
  const defaultOptions = {
4623
4623
  nodeOrigin: [
4624
4624
  0,
@@ -4657,11 +4657,42 @@ function updateAbsolutePositions(nodeLookup, parentLookup, options) {
4657
4657
  }
4658
4658
  }
4659
4659
  }
4660
+ function parseHandles(userNode, internalNode) {
4661
+ if (!userNode.handles) {
4662
+ return !userNode.measured ? undefined : internalNode?.internals.handleBounds;
4663
+ }
4664
+ const source = [];
4665
+ const target = [];
4666
+ for (const handle of userNode.handles){
4667
+ const handleBounds = {
4668
+ id: handle.id,
4669
+ width: handle.width ?? 1,
4670
+ height: handle.height ?? 1,
4671
+ nodeId: userNode.id,
4672
+ x: handle.x,
4673
+ y: handle.y,
4674
+ position: handle.position,
4675
+ type: handle.type
4676
+ };
4677
+ if (handle.type === 'source') {
4678
+ source.push(handleBounds);
4679
+ } else if (handle.type === 'target') {
4680
+ target.push(handleBounds);
4681
+ }
4682
+ }
4683
+ return {
4684
+ source,
4685
+ target
4686
+ };
4687
+ }
4660
4688
  function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4661
4689
  const _options = mergeObjects(adoptUserNodesDefaultOptions, options);
4690
+ let rootParentIndex = {
4691
+ i: -1
4692
+ };
4662
4693
  let nodesInitialized = nodes.length > 0;
4663
4694
  const tmpLookup = new Map(nodeLookup);
4664
- const selectedNodeZ = _options?.elevateNodesOnSelect ? 1000 : 0;
4695
+ const selectedNodeZ = _options?.elevateNodesOnSelect ? SELECTED_NODE_Z : 0;
4665
4696
  nodeLookup.clear();
4666
4697
  parentLookup.clear();
4667
4698
  for (const userNode of nodes){
@@ -4682,7 +4713,7 @@ function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4682
4713
  internals: {
4683
4714
  positionAbsolute: clampedPosition,
4684
4715
  // if user re-initializes the node or removes `measured` for whatever reason, we reset the handleBounds so that the node gets re-measured
4685
- handleBounds: !userNode.measured ? undefined : internalNode?.internals.handleBounds,
4716
+ handleBounds: parseHandles(userNode, internalNode),
4686
4717
  z: calculateZ(userNode, selectedNodeZ),
4687
4718
  userNode
4688
4719
  }
@@ -4693,7 +4724,7 @@ function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
4693
4724
  nodesInitialized = false;
4694
4725
  }
4695
4726
  if (userNode.parentId) {
4696
- updateChildNode(internalNode, nodeLookup, parentLookup, options);
4727
+ updateChildNode(internalNode, nodeLookup, parentLookup, options, rootParentIndex);
4697
4728
  }
4698
4729
  }
4699
4730
  return nodesInitialized;
@@ -4716,7 +4747,7 @@ function updateParentLookup(node, parentLookup) {
4716
4747
  }
4717
4748
  /**
4718
4749
  * Updates positionAbsolute and zIndex of a child node and the parentLookup.
4719
- */ function updateChildNode(node, nodeLookup, parentLookup, options) {
4750
+ */ function updateChildNode(node, nodeLookup, parentLookup, options, rootParentIndex) {
4720
4751
  const { elevateNodesOnSelect, nodeOrigin, nodeExtent } = mergeObjects(defaultOptions, options);
4721
4752
  const parentId = node.parentId;
4722
4753
  const parentNode = nodeLookup.get(parentId);
@@ -4725,7 +4756,16 @@ function updateParentLookup(node, parentLookup) {
4725
4756
  return;
4726
4757
  }
4727
4758
  updateParentLookup(node, parentLookup);
4728
- const selectedNodeZ = elevateNodesOnSelect ? 1000 : 0;
4759
+ // We just want to set the rootParentIndex for the first child
4760
+ if (rootParentIndex && !parentNode.parentId && parentNode.internals.rootParentIndex === undefined) {
4761
+ parentNode.internals.rootParentIndex = ++rootParentIndex.i;
4762
+ parentNode.internals.z = parentNode.internals.z + rootParentIndex.i * ROOT_PARENT_Z_INCREMENT;
4763
+ }
4764
+ // But we need to update rootParentIndex.i also when parent has not been updated
4765
+ if (rootParentIndex && parentNode.internals.rootParentIndex !== undefined) {
4766
+ rootParentIndex.i = parentNode.internals.rootParentIndex;
4767
+ }
4768
+ const selectedNodeZ = elevateNodesOnSelect ? SELECTED_NODE_Z : 0;
4729
4769
  const { x, y, z } = calculateChildXYZ(node, parentNode, nodeOrigin, nodeExtent, selectedNodeZ);
4730
4770
  const { positionAbsolute } = node.internals;
4731
4771
  const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
@@ -5299,8 +5339,10 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
5299
5339
  autoPan();
5300
5340
  }
5301
5341
  if (!dragStarted) {
5302
- const x = pointerPos.xSnapped - (lastPos.x ?? 0);
5303
- const y = pointerPos.ySnapped - (lastPos.y ?? 0);
5342
+ // Calculate distance in client coordinates for consistent drag threshold behavior across zoom levels
5343
+ const currentMousePosition = getEventPosition(event.sourceEvent, containerBounds);
5344
+ const x = currentMousePosition.x - mousePosition.x;
5345
+ const y = currentMousePosition.y - mousePosition.y;
5304
5346
  const distance = Math.sqrt(x * x + y * y);
5305
5347
  if (distance > nodeDragThreshold) {
5306
5348
  startDrag(event);
@@ -5584,6 +5626,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
5584
5626
  previousConnection = newConnection;
5585
5627
  }
5586
5628
  function onPointerUp(event) {
5629
+ // Prevent multi-touch aborting connection
5630
+ if ('touches' in event && event.touches.length > 0) {
5631
+ return;
5632
+ }
5587
5633
  if (connectionStarted) {
5588
5634
  if ((closestHandle || resultHandleDomNode) && connection && isValid) {
5589
5635
  onConnect?.(connection);
@@ -5741,8 +5787,7 @@ function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
5741
5787
  pointer
5742
5788
  };
5743
5789
  }
5744
- /* eslint-disable @typescript-eslint/no-explicit-any */ const viewChanged = (prevViewport, eventViewport)=>prevViewport.x !== eventViewport.x || prevViewport.y !== eventViewport.y || prevViewport.zoom !== eventViewport.k;
5745
- const transformToViewport = (transform)=>({
5790
+ /* eslint-disable @typescript-eslint/no-explicit-any */ const transformToViewport = (transform)=>({
5746
5791
  x: transform.x,
5747
5792
  y: transform.y,
5748
5793
  zoom: transform.k
@@ -5766,6 +5811,9 @@ const wheelDelta = (event)=>{
5766
5811
  function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection, d3Zoom, panOnScrollMode, panOnScrollSpeed, zoomOnPinch, onPanZoomStart, onPanZoom, onPanZoomEnd }) {
5767
5812
  return (event)=>{
5768
5813
  if (isWrappedWithClass(event, noWheelClassName)) {
5814
+ if (event.ctrlKey) {
5815
+ event.preventDefault(); // stop native page zoom for pinch zooming
5816
+ }
5769
5817
  return false;
5770
5818
  }
5771
5819
  event.preventDefault();
@@ -5804,8 +5852,7 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
5804
5852
  */ if (!zoomPanValues.isPanScrolling) {
5805
5853
  zoomPanValues.isPanScrolling = true;
5806
5854
  onPanZoomStart?.(event, nextViewport);
5807
- }
5808
- if (zoomPanValues.isPanScrolling) {
5855
+ } else {
5809
5856
  onPanZoom?.(event, nextViewport);
5810
5857
  zoomPanValues.panScrollTimeout = setTimeout(()=>{
5811
5858
  onPanZoomEnd?.(event, nextViewport);
@@ -5875,7 +5922,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5875
5922
  }
5876
5923
  zoomPanValues.usedRightMouseButton = false;
5877
5924
  onDraggingChange(false);
5878
- if (onPanZoomEnd && viewChanged(zoomPanValues.prevViewport, event.transform)) {
5925
+ if (onPanZoomEnd) {
5879
5926
  const viewport = transformToViewport(event.transform);
5880
5927
  zoomPanValues.prevViewport = viewport;
5881
5928
  clearTimeout(zoomPanValues.timerId);
@@ -5886,10 +5933,11 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5886
5933
  }
5887
5934
  };
5888
5935
  }
5889
- /* eslint-disable @typescript-eslint/no-explicit-any */ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib }) {
5936
+ /* eslint-disable @typescript-eslint/no-explicit-any */ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib, connectionInProgress }) {
5890
5937
  return (event)=>{
5891
5938
  const zoomScroll = zoomActivationKeyPressed || zoomOnScroll;
5892
5939
  const pinchZoom = zoomOnPinch && event.ctrlKey;
5940
+ const isWheelEvent = event.type === 'wheel';
5893
5941
  if (event.button === 1 && event.type === 'mousedown' && (isWrappedWithClass(event, `${lib}-flow__node`) || isWrappedWithClass(event, `${lib}-flow__edge`))) {
5894
5942
  return true;
5895
5943
  }
@@ -5901,15 +5949,19 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5901
5949
  if (userSelectionActive) {
5902
5950
  return false;
5903
5951
  }
5952
+ // we want to disable pinch-zooming while making a connection
5953
+ if (connectionInProgress && !isWheelEvent) {
5954
+ return false;
5955
+ }
5904
5956
  // if the target element is inside an element with the nowheel class, we prevent zooming
5905
- if (isWrappedWithClass(event, noWheelClassName) && event.type === 'wheel') {
5957
+ if (isWrappedWithClass(event, noWheelClassName) && isWheelEvent) {
5906
5958
  return false;
5907
5959
  }
5908
5960
  // if the target element is inside an element with the nopan class, we prevent panning
5909
- if (isWrappedWithClass(event, noPanClassName) && (event.type !== 'wheel' || panOnScroll && event.type === 'wheel' && !zoomActivationKeyPressed)) {
5961
+ if (isWrappedWithClass(event, noPanClassName) && (!isWheelEvent || panOnScroll && isWheelEvent && !zoomActivationKeyPressed)) {
5910
5962
  return false;
5911
5963
  }
5912
- if (!zoomOnPinch && event.ctrlKey && event.type === 'wheel') {
5964
+ if (!zoomOnPinch && event.ctrlKey && isWheelEvent) {
5913
5965
  return false;
5914
5966
  }
5915
5967
  if (!zoomOnPinch && event.type === 'touchstart' && event.touches?.length > 1) {
@@ -5917,7 +5969,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5917
5969
  return false;
5918
5970
  }
5919
5971
  // when there is no scroll handling enabled, we prevent all wheel events
5920
- if (!zoomScroll && !panOnScroll && !pinchZoom && event.type === 'wheel') {
5972
+ if (!zoomScroll && !panOnScroll && !pinchZoom && isWheelEvent) {
5921
5973
  return false;
5922
5974
  }
5923
5975
  // if the pane is not movable, we prevent dragging it with mousestart or touchstart
@@ -5931,7 +5983,7 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
5931
5983
  // We only allow right clicks if pan on drag is set to right click
5932
5984
  const buttonAllowed = Array.isArray(panOnDrag) && panOnDrag.includes(event.button) || !event.button || event.button <= 1;
5933
5985
  // default filter for d3-zoom
5934
- return (!event.ctrlKey || event.type === 'wheel') && buttonAllowed;
5986
+ return (!event.ctrlKey || isWheelEvent) && buttonAllowed;
5935
5987
  };
5936
5988
  }
5937
5989
  function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExtent, viewport, onPanZoom, onPanZoomStart, onPanZoomEnd, onDraggingChange }) {
@@ -5939,10 +5991,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
5939
5991
  isZoomingOrPanning: false,
5940
5992
  usedRightMouseButton: false,
5941
5993
  prevViewport: {
5942
- x: 0,
5943
- y: 0,
5944
- zoom: 0
5945
- },
5994
+ },
5946
5995
  mouseButton: 0,
5947
5996
  timerId: undefined,
5948
5997
  panScrollTimeout: undefined,
@@ -5980,7 +6029,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
5980
6029
  return Promise.resolve(false);
5981
6030
  }
5982
6031
  // public functions
5983
- function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange }) {
6032
+ function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange, connectionInProgress }) {
5984
6033
  if (userSelectionActive && !zoomPanValues.isZoomingOrPanning) {
5985
6034
  destroy();
5986
6035
  }
@@ -6042,7 +6091,8 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
6042
6091
  userSelectionActive,
6043
6092
  noPanClassName,
6044
6093
  noWheelClassName,
6045
- lib
6094
+ lib,
6095
+ connectionInProgress
6046
6096
  });
6047
6097
  d3ZoomInstance.filter(filter);
6048
6098
  /*
@@ -6388,6 +6438,17 @@ function nodeToChildExtent(child, parent, nodeOrigin) {
6388
6438
  }
6389
6439
  function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6390
6440
  const selection = select(domNode);
6441
+ let params = {
6442
+ controlDirection: getControlDirection('bottom-right'),
6443
+ boundaries: {
6444
+ minWidth: 0,
6445
+ minHeight: 0,
6446
+ maxWidth: Number.MAX_VALUE,
6447
+ maxHeight: Number.MAX_VALUE
6448
+ },
6449
+ resizeDirection: undefined,
6450
+ keepAspectRatio: false
6451
+ };
6391
6452
  function update({ controlPosition, boundaries, keepAspectRatio, resizeDirection, onResizeStart, onResize, onResizeEnd, shouldResize }) {
6392
6453
  let prevValues = {
6393
6454
  ...initPrevValues$1
@@ -6395,13 +6456,20 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6395
6456
  let startValues = {
6396
6457
  ...initStartValues
6397
6458
  };
6398
- const controlDirection = getControlDirection(controlPosition);
6459
+ params = {
6460
+ boundaries,
6461
+ resizeDirection,
6462
+ keepAspectRatio,
6463
+ controlDirection: getControlDirection(controlPosition)
6464
+ };
6399
6465
  let node = undefined;
6400
6466
  let containerBounds = null;
6401
6467
  let childNodes = [];
6402
6468
  let parentNode = undefined; // Needed to fix expandParent
6403
6469
  let parentExtent = undefined;
6404
6470
  let childExtent = undefined;
6471
+ // we only want to trigger onResizeEnd if onResize was actually called
6472
+ let resizeDetected = false;
6405
6473
  const dragHandler = drag().on('start', (event)=>{
6406
6474
  const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, paneDomNode } = getStoreItems();
6407
6475
  node = nodeLookup.get(nodeId);
@@ -6483,7 +6551,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6483
6551
  const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
6484
6552
  const change = {};
6485
6553
  const nodeOrigin = node.origin ?? storeNodeOrigin;
6486
- const { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent);
6554
+ const { width, height, x, y } = getDimensionsAfterResize(startValues, params.controlDirection, pointerPosition, params.boundaries, params.keepAspectRatio, nodeOrigin, parentExtent, childExtent);
6487
6555
  const isWidthChange = width !== prevWidth;
6488
6556
  const isHeightChange = height !== prevHeight;
6489
6557
  const isXPosChange = x !== prevX && isWidthChange;
@@ -6512,8 +6580,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6512
6580
  }
6513
6581
  }
6514
6582
  if (isWidthChange || isHeightChange) {
6515
- change.width = isWidthChange && (!resizeDirection || resizeDirection === 'horizontal') ? width : prevValues.width;
6516
- change.height = isHeightChange && (!resizeDirection || resizeDirection === 'vertical') ? height : prevValues.height;
6583
+ change.width = isWidthChange && (!params.resizeDirection || params.resizeDirection === 'horizontal') ? width : prevValues.width;
6584
+ change.height = isHeightChange && (!params.resizeDirection || params.resizeDirection === 'vertical') ? height : prevValues.height;
6517
6585
  prevValues.width = change.width;
6518
6586
  prevValues.height = change.height;
6519
6587
  }
@@ -6535,8 +6603,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6535
6603
  prevWidth,
6536
6604
  height: prevValues.height,
6537
6605
  prevHeight,
6538
- affectsX: controlDirection.affectsX,
6539
- affectsY: controlDirection.affectsY
6606
+ affectsX: params.controlDirection.affectsX,
6607
+ affectsY: params.controlDirection.affectsY
6540
6608
  });
6541
6609
  const nextValues = {
6542
6610
  ...prevValues,
@@ -6546,15 +6614,20 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
6546
6614
  if (callResize === false) {
6547
6615
  return;
6548
6616
  }
6617
+ resizeDetected = true;
6549
6618
  onResize?.(event, nextValues);
6550
6619
  onChange(change, childChanges);
6551
6620
  }).on('end', (event)=>{
6621
+ if (!resizeDetected) {
6622
+ return;
6623
+ }
6552
6624
  onResizeEnd?.(event, {
6553
6625
  ...prevValues
6554
6626
  });
6555
6627
  onEnd?.({
6556
6628
  ...prevValues
6557
6629
  });
6630
+ resizeDetected = false;
6558
6631
  });
6559
6632
  selection.call(dragHandler);
6560
6633
  }
@@ -8175,7 +8248,11 @@ const selector$k = (s)=>!!s.panZoom;
8175
8248
  deletedEdges: matchingEdges
8176
8249
  };
8177
8250
  },
8178
- getIntersectingNodes: (nodeOrRect, partially = true, nodes)=>{
8251
+ /**
8252
+ * Partial is defined as "the 2 nodes/areas are intersecting partially".
8253
+ * If a is contained in b or b is contained in a, they are both
8254
+ * considered fully intersecting.
8255
+ */ getIntersectingNodes: (nodeOrRect, partially = true, nodes)=>{
8179
8256
  const isRect = isRectObject(nodeOrRect);
8180
8257
  const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
8181
8258
  const hasNodesOption = nodes !== undefined;
@@ -8201,7 +8278,7 @@ const selector$k = (s)=>!!s.panZoom;
8201
8278
  }
8202
8279
  const overlappingArea = getOverlappingArea(nodeRect, area);
8203
8280
  const partiallyVisible = partially && overlappingArea > 0;
8204
- return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
8281
+ return partiallyVisible || overlappingArea >= area.width * area.height || overlappingArea >= nodeRect.width * nodeRect.height;
8205
8282
  },
8206
8283
  updateNode,
8207
8284
  updateNodeData: (id, dataUpdate, options = {
@@ -8320,7 +8397,7 @@ const win$1 = typeof window !== 'undefined' ? window : undefined;
8320
8397
  const store = useStoreApi();
8321
8398
  useEffect(()=>{
8322
8399
  const updateDimensions = ()=>{
8323
- if (!domNode.current) {
8400
+ if (!domNode.current || !(domNode.current.checkVisibility?.() ?? true)) {
8324
8401
  return false;
8325
8402
  }
8326
8403
  const size = getDimensions$1(domNode.current);
@@ -8355,12 +8432,13 @@ const containerStyle = {
8355
8432
  };
8356
8433
  const selector$j = (s)=>({
8357
8434
  userSelectionActive: s.userSelectionActive,
8358
- lib: s.lib
8435
+ lib: s.lib,
8436
+ connectionInProgress: s.connection.inProgress
8359
8437
  });
8360
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 }) {
8361
8439
  const store = useStoreApi();
8362
8440
  const zoomPane = useRef(null);
8363
- const { userSelectionActive, lib } = useStore(selector$j, shallow$1);
8441
+ const { userSelectionActive, lib, connectionInProgress } = useStore(selector$j, shallow$1);
8364
8442
  const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode);
8365
8443
  const panZoom = useRef();
8366
8444
  useResizeHandler(zoomPane);
@@ -8438,7 +8516,8 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8438
8516
  userSelectionActive,
8439
8517
  noWheelClassName,
8440
8518
  lib,
8441
- onTransformChange
8519
+ onTransformChange,
8520
+ connectionInProgress
8442
8521
  });
8443
8522
  }, [
8444
8523
  onPaneContextMenu,
@@ -8455,7 +8534,8 @@ function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
8455
8534
  userSelectionActive,
8456
8535
  noWheelClassName,
8457
8536
  lib,
8458
- onTransformChange
8537
+ onTransformChange,
8538
+ connectionInProgress
8459
8539
  ]);
8460
8540
  return jsx("div", {
8461
8541
  className: "react-flow__renderer",
@@ -8529,12 +8609,25 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8529
8609
  onPaneContextMenu?.(event);
8530
8610
  };
8531
8611
  const onWheel = onPaneScroll ? (event)=>onPaneScroll(event) : undefined;
8532
- const onPointerDown = (event)=>{
8612
+ const onClickCapture = (event)=>{
8613
+ const isSelectionOnDragActive = selectionOnDrag && container.current === event.target || !selectionOnDrag || selectionKeyPressed;
8614
+ if (!isSelectionOnDragActive) {
8615
+ return;
8616
+ }
8617
+ event.stopPropagation();
8618
+ };
8619
+ // We are using capture here in order to prevent other pointer events
8620
+ // to be able to create a selection above a node or an edge
8621
+ const onPointerDownCapture = (event)=>{
8533
8622
  const { resetSelectedElements, domNode } = store.getState();
8534
8623
  containerBounds.current = domNode?.getBoundingClientRect();
8535
- if (!elementsSelectable || !isSelecting || event.button !== 0 || event.target !== container.current || !containerBounds.current) {
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) {
8536
8627
  return;
8537
8628
  }
8629
+ event.stopPropagation();
8630
+ event.preventDefault();
8538
8631
  event.target?.setPointerCapture?.(event.pointerId);
8539
8632
  selectionStarted.current = true;
8540
8633
  selectionInProgress.current = false;
@@ -8638,9 +8731,10 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
8638
8731
  onContextMenu: wrapHandler(onContextMenu, container),
8639
8732
  onWheel: wrapHandler(onWheel, container),
8640
8733
  onPointerEnter: hasActiveSelection ? undefined : onPaneMouseEnter,
8641
- onPointerDown: hasActiveSelection ? onPointerDown : onPaneMouseMove,
8642
8734
  onPointerMove: hasActiveSelection ? onPointerMove : onPaneMouseMove,
8643
8735
  onPointerUp: hasActiveSelection ? onPointerUp : undefined,
8736
+ onPointerDownCapture: hasActiveSelection ? onPointerDownCapture : undefined,
8737
+ onClickCapture: hasActiveSelection ? onClickCapture : undefined,
8644
8738
  onPointerLeave: onPaneMouseLeave,
8645
8739
  ref: container,
8646
8740
  style: containerStyle,
@@ -9529,6 +9623,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
9529
9623
  })
9530
9624
  });
9531
9625
  }
9626
+ var NodeWrapper$1 = memo(NodeWrapper);
9532
9627
  const selector$b = (s)=>({
9533
9628
  nodesDraggable: s.nodesDraggable,
9534
9629
  nodesConnectable: s.nodesConnectable,
@@ -9568,7 +9663,7 @@ function NodeRendererComponent(props) {
9568
9663
  * moved into `NodeComponentWrapper`. This ensures they are
9569
9664
  * memorized – so if `NodeRenderer` *has* to rerender, it only
9570
9665
  * needs to regenerate the list of nodes, nothing else.
9571
- */ jsx(NodeWrapper, {
9666
+ */ jsx(NodeWrapper$1, {
9572
9667
  id: nodeId,
9573
9668
  nodeTypes: props.nodeTypes,
9574
9669
  nodeExtent: props.nodeExtent,
@@ -10562,6 +10657,7 @@ function EdgeWrapper({ id, edgesFocusable, edgesReconnectable, elementsSelectabl
10562
10657
  })
10563
10658
  });
10564
10659
  }
10660
+ var EdgeWrapper$1 = memo(EdgeWrapper);
10565
10661
  const selector$a = (s)=>({
10566
10662
  edgesFocusable: s.edgesFocusable,
10567
10663
  edgesReconnectable: s.edgesReconnectable,
@@ -10580,7 +10676,7 @@ function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements,
10580
10676
  rfId: rfId
10581
10677
  }),
10582
10678
  edgeIds.map((id)=>{
10583
- return jsx(EdgeWrapper, {
10679
+ return jsx(EdgeWrapper$1, {
10584
10680
  id: id,
10585
10681
  edgesFocusable: edgesFocusable,
10586
10682
  edgesReconnectable: edgesReconnectable,
@@ -10965,8 +11061,8 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
10965
11061
  }
10966
11062
  return {
10967
11063
  rfId: '1',
10968
- width: 0,
10969
- height: 0,
11064
+ width: width ?? 0,
11065
+ height: height ?? 0,
10970
11066
  transform,
10971
11067
  nodes: storeNodes,
10972
11068
  nodesInitialized,
@@ -12580,7 +12676,7 @@ var css_248z = "/* this gets exported as style.css and can be used for the defau
12580
12676
  styleInject(css_248z);
12581
12677
 
12582
12678
  /**
12583
- * @license lucide-react v0.542.0 - ISC
12679
+ * @license lucide-react v0.546.0 - ISC
12584
12680
  *
12585
12681
  * This source code is licensed under the ISC license.
12586
12682
  * See the LICENSE file in the root directory of this source tree.
@@ -12602,7 +12698,7 @@ const hasA11yProp = (props)=>{
12602
12698
  };
12603
12699
 
12604
12700
  /**
12605
- * @license lucide-react v0.542.0 - ISC
12701
+ * @license lucide-react v0.546.0 - ISC
12606
12702
  *
12607
12703
  * This source code is licensed under the ISC license.
12608
12704
  * See the LICENSE file in the root directory of this source tree.
@@ -19612,7 +19708,7 @@ var correctTargets = function(parent, targets) {
19612
19708
  };
19613
19709
 
19614
19710
  var DIALOG_NAME = "Dialog";
19615
- var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
19711
+ var [createDialogContext] = createContextScope(DIALOG_NAME);
19616
19712
  var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
19617
19713
  var Dialog = (props)=>{
19618
19714
  const { __scopeDialog, children, open: openProp, defaultOpen, onOpenChange, modal = true } = props;
@@ -23352,7 +23448,7 @@ var SELECTION_KEYS = [
23352
23448
  ];
23353
23449
  var SELECT_NAME = "Select";
23354
23450
  var [Collection, useCollection, createCollectionScope] = createCollection(SELECT_NAME);
23355
- var [createSelectContext, createSelectScope] = createContextScope(SELECT_NAME, [
23451
+ var [createSelectContext] = createContextScope(SELECT_NAME, [
23356
23452
  createCollectionScope,
23357
23453
  createPopperScope
23358
23454
  ]);
@@ -24868,7 +24964,7 @@ const FileSelector = ({ files, currentFile, onFileSelect, onRefresh, loading = f
24868
24964
  };
24869
24965
 
24870
24966
  var CHECKBOX_NAME = "Checkbox";
24871
- var [createCheckboxContext, createCheckboxScope] = createContextScope(CHECKBOX_NAME);
24967
+ var [createCheckboxContext] = createContextScope(CHECKBOX_NAME);
24872
24968
  var [CheckboxProviderImpl, useCheckboxContext] = createCheckboxContext(CHECKBOX_NAME);
24873
24969
  function CheckboxProvider(props) {
24874
24970
  const { __scopeCheckbox, checked: checkedProp, children, defaultChecked, disabled, form, name, onCheckedChange, required, value = "on", // @ts-expect-error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@railtownai/railtracks-visualizer",
3
- "version": "0.0.34",
3
+ "version": "0.0.37",
4
4
  "license": "MIT",
5
5
  "author": "Railtown AI",
6
6
  "description": "A visualizer for RailTracks agentic flows",
@@ -20,6 +20,9 @@
20
20
  "README.md",
21
21
  "package.json"
22
22
  ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
23
26
  "repository": {
24
27
  "type": "git",
25
28
  "url": "git+https://github.com/railtownai/railtracks-visualizer.git"
@@ -37,15 +40,15 @@
37
40
  "react-dom": "^18.3.1"
38
41
  },
39
42
  "dependencies": {
40
- "@ant-design/plots": "2.6.4",
43
+ "@ant-design/plots": "2.6.5",
41
44
  "@emotion/react": "11.14.0",
42
45
  "@emotion/styled": "11.14.1",
43
46
  "@radix-ui/react-checkbox": "1.3.3",
44
47
  "@radix-ui/react-dialog": "1.1.15",
45
48
  "@radix-ui/react-select": "2.2.6",
46
- "@railtownai/railtracks-timeline": "latest",
47
- "@xyflow/react": "12.8.4",
48
- "lucide-react": "0.542.0",
49
+ "@railtownai/railtracks-timeline": "0.0.15",
50
+ "@xyflow/react": "12.9.0",
51
+ "lucide-react": "0.546.0",
49
52
  "moment": "2.30.1",
50
53
  "react-countup": "6.5.3",
51
54
  "react-textarea-autosize": "8.5.9",
@@ -68,44 +71,44 @@
68
71
  "storybook:preview": "npx http-server ./storybook-static",
69
72
  "test:ui": "vitest --ui",
70
73
  "test": "vitest run --silent",
71
- "up": "ncu -u -x react -x react-dom -x @types/react -x @types/react-dom && npm install"
74
+ "up": "ncu -u -x react -x react-dom -x @types/react -x @types/react-dom"
72
75
  },
73
76
  "devDependencies": {
74
77
  "@chromatic-com/storybook": "4.1.1",
75
- "@rollup/plugin-commonjs": "28.0.6",
78
+ "@rollup/plugin-commonjs": "28.0.8",
76
79
  "@rollup/plugin-json": "6.1.0",
77
- "@rollup/plugin-node-resolve": "16.0.1",
80
+ "@rollup/plugin-node-resolve": "16.0.3",
78
81
  "@rollup/plugin-swc": "0.4.0",
79
82
  "@rollup/plugin-terser": "0.4.4",
80
- "@storybook/addon-a11y": "9.1.10",
81
- "@storybook/addon-docs": "9.1.10",
82
- "@storybook/addon-onboarding": "9.1.10",
83
- "@storybook/addon-vitest": "9.1.10",
84
- "@storybook/react-vite": "9.1.10",
85
- "@testing-library/jest-dom": "6.8.0",
83
+ "@storybook/addon-a11y": "9.1.13",
84
+ "@storybook/addon-docs": "9.1.13",
85
+ "@storybook/addon-onboarding": "9.1.13",
86
+ "@storybook/addon-vitest": "9.1.13",
87
+ "@storybook/react-vite": "9.1.13",
88
+ "@testing-library/jest-dom": "6.9.1",
86
89
  "@testing-library/react": "16.3.0",
87
90
  "@testing-library/user-event": "14.6.1",
88
- "@types/node": "24.3.1",
91
+ "@types/node": "24.9.0",
89
92
  "@types/react": "18.2.79",
90
93
  "@types/react-dom": "18.2.25",
91
- "@vitejs/plugin-react-swc": "4.0.1",
94
+ "@vitejs/plugin-react-swc": "4.1.0",
92
95
  "@vitest/browser": "3.2.4",
93
96
  "@vitest/coverage-v8": "3.2.4",
94
97
  "class-variance-authority": "0.7.1",
95
98
  "clsx": "2.1.1",
96
- "cross-env": "^10.0.0",
99
+ "cross-env": "^10.1.0",
97
100
  "gh-pages": "6.3.0",
98
- "jsdom": "26.1.0",
101
+ "jsdom": "27.0.1",
99
102
  "license-checker": "25.0.1",
100
- "npm-check-updates": "18.1.0",
101
- "playwright": "^1.55.0",
103
+ "npm-check-updates": "19.1.1",
104
+ "playwright": "^1.56.1",
102
105
  "prettier": "3.6.2",
103
- "rollup": "4.50.1",
106
+ "rollup": "4.52.5",
104
107
  "rollup-plugin-postcss": "4.0.2",
105
- "storybook": "9.1.10",
108
+ "storybook": "9.1.13",
106
109
  "tslib": "2.8.1",
107
- "typescript": "5.9.2",
108
- "vite": "7.1.5",
110
+ "typescript": "5.9.3",
111
+ "vite": "7.1.11",
109
112
  "vitest": "3.2.4"
110
113
  },
111
114
  "prettier": {