@xyflow/system 0.0.65 → 0.0.67

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
@@ -448,7 +448,7 @@ function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin =
448
448
  const parentNode = node.parentId ? nodeLookup.get(node.parentId) : undefined;
449
449
  const { x: parentX, y: parentY } = parentNode ? parentNode.internals.positionAbsolute : { x: 0, y: 0 };
450
450
  const origin = node.origin ?? nodeOrigin;
451
- let extent = nodeExtent;
451
+ let extent = node.extent || nodeExtent;
452
452
  if (node.extent === 'parent' && !node.expandParent) {
453
453
  if (!parentNode) {
454
454
  onError?.('005', errorMessages['error005']());
@@ -1160,7 +1160,7 @@ const distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y
1160
1160
  * With this function we try to mimic an orthogonal edge routing behaviour
1161
1161
  * It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges
1162
1162
  */
1163
- function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) {
1163
+ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, stepPosition, }) {
1164
1164
  const sourceDir = handleDirections[sourcePosition];
1165
1165
  const targetDir = handleDirections[targetPosition];
1166
1166
  const sourceGapped = { x: source.x + sourceDir.x * offset, y: source.y + sourceDir.y * offset };
@@ -1176,7 +1176,7 @@ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPos
1176
1176
  let centerX, centerY;
1177
1177
  const sourceGapOffset = { x: 0, y: 0 };
1178
1178
  const targetGapOffset = { x: 0, y: 0 };
1179
- const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
1179
+ const [, , defaultOffsetX, defaultOffsetY] = getEdgeCenter({
1180
1180
  sourceX: source.x,
1181
1181
  sourceY: source.y,
1182
1182
  targetX: target.x,
@@ -1184,8 +1184,16 @@ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPos
1184
1184
  });
1185
1185
  // opposite handle positions, default case
1186
1186
  if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
1187
- centerX = center.x ?? defaultCenterX;
1188
- centerY = center.y ?? defaultCenterY;
1187
+ if (dirAccessor === 'x') {
1188
+ // Primary direction is horizontal, so stepPosition affects X coordinate
1189
+ centerX = center.x ?? (sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition);
1190
+ centerY = center.y ?? (sourceGapped.y + targetGapped.y) / 2;
1191
+ }
1192
+ else {
1193
+ // Primary direction is vertical, so stepPosition affects Y coordinate
1194
+ centerX = center.x ?? (sourceGapped.x + targetGapped.x) / 2;
1195
+ centerY = center.y ?? (sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition);
1196
+ }
1189
1197
  /*
1190
1198
  * --->
1191
1199
  * |
@@ -1318,7 +1326,7 @@ function getBend(a, b, c, size) {
1318
1326
  * ```
1319
1327
  * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
1320
1328
  */
1321
- function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) {
1329
+ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, stepPosition = 0.5, }) {
1322
1330
  const [points, labelX, labelY, offsetX, offsetY] = getPoints({
1323
1331
  source: { x: sourceX, y: sourceY },
1324
1332
  sourcePosition,
@@ -1326,6 +1334,7 @@ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom,
1326
1334
  targetPosition,
1327
1335
  center: { x: centerX, y: centerY },
1328
1336
  offset,
1337
+ stepPosition,
1329
1338
  });
1330
1339
  const path = points.reduce((res, p, i) => {
1331
1340
  let segment = '';
@@ -1955,6 +1964,25 @@ function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true,
1955
1964
  nodesFromDragItems,
1956
1965
  ];
1957
1966
  }
1967
+ /**
1968
+ * If a selection is being dragged we want to apply the same snap offset to all nodes in the selection.
1969
+ * This function calculates the snap offset based on the first node in the selection.
1970
+ */
1971
+ function calculateSnapOffset({ dragItems, snapGrid, x, y, }) {
1972
+ const refDragItem = dragItems.values().next().value;
1973
+ if (!refDragItem) {
1974
+ return null;
1975
+ }
1976
+ const refPos = {
1977
+ x: x - refDragItem.distance.x,
1978
+ y: y - refDragItem.distance.y,
1979
+ };
1980
+ const refPosSnapped = snapPosition(refPos, snapGrid);
1981
+ return {
1982
+ x: refPosSnapped.x - refPos.x,
1983
+ y: refPosSnapped.y - refPos.y,
1984
+ };
1985
+ }
1958
1986
 
1959
1987
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1960
1988
  function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop, }) {
@@ -1968,39 +1996,43 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1968
1996
  let d3Selection = null;
1969
1997
  let abortDrag = false; // prevents unintentional dragging on multitouch
1970
1998
  let nodePositionsChanged = false;
1999
+ // we store the last drag event to be able to use it in the update function
2000
+ let dragEvent = null;
1971
2001
  // public functions
1972
2002
  function update({ noDragClassName, handleSelector, domNode, isSelectable, nodeId, nodeClickDistance = 0, }) {
1973
2003
  d3Selection = select(domNode);
1974
- function updateNodes({ x, y }, dragEvent) {
2004
+ function updateNodes({ x, y }) {
1975
2005
  const { nodeLookup, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onNodeDrag, onSelectionDrag, onError, updateNodePositions, } = getStoreItems();
1976
2006
  lastPos = { x, y };
1977
2007
  let hasChange = false;
1978
- let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };
1979
- if (dragItems.size > 1 && nodeExtent) {
1980
- const rect = getInternalNodesBounds(dragItems);
1981
- nodesBox = rectToBox(rect);
1982
- }
2008
+ const isMultiDrag = dragItems.size > 1;
2009
+ const nodesBox = isMultiDrag && nodeExtent ? rectToBox(getInternalNodesBounds(dragItems)) : null;
2010
+ const multiDragSnapOffset = isMultiDrag && snapToGrid
2011
+ ? calculateSnapOffset({
2012
+ dragItems,
2013
+ snapGrid,
2014
+ x,
2015
+ y,
2016
+ })
2017
+ : null;
1983
2018
  for (const [id, dragItem] of dragItems) {
2019
+ /*
2020
+ * if the node is not in the nodeLookup anymore, it was probably deleted while dragging
2021
+ */
1984
2022
  if (!nodeLookup.has(id)) {
1985
- /*
1986
- * if the node is not in the nodeLookup anymore, it was probably deleted while dragging
1987
- * and we don't need to update it anymore
1988
- */
1989
2023
  continue;
1990
2024
  }
1991
2025
  let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
1992
2026
  if (snapToGrid) {
1993
- nextPosition = snapPosition(nextPosition, snapGrid);
2027
+ nextPosition = multiDragSnapOffset
2028
+ ? {
2029
+ x: nextPosition.x + multiDragSnapOffset.x,
2030
+ y: nextPosition.y + multiDragSnapOffset.y,
2031
+ }
2032
+ : snapPosition(nextPosition, snapGrid);
1994
2033
  }
1995
- /*
1996
- * if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
1997
- * based on its position so that the node stays at it's position relative to the selection.
1998
- */
1999
- let adjustedNodeExtent = [
2000
- [nodeExtent[0][0], nodeExtent[0][1]],
2001
- [nodeExtent[1][0], nodeExtent[1][1]],
2002
- ];
2003
- if (dragItems.size > 1 && nodeExtent && !dragItem.extent) {
2034
+ let adjustedNodeExtent = null;
2035
+ if (isMultiDrag && nodeExtent && !dragItem.extent && nodesBox) {
2004
2036
  const { positionAbsolute } = dragItem.internals;
2005
2037
  const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
2006
2038
  const x2 = positionAbsolute.x + dragItem.measured.width - nodesBox.x2 + nodeExtent[1][0];
@@ -2015,7 +2047,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2015
2047
  nodeId: id,
2016
2048
  nextPosition,
2017
2049
  nodeLookup,
2018
- nodeExtent: adjustedNodeExtent,
2050
+ nodeExtent: adjustedNodeExtent ? adjustedNodeExtent : nodeExtent,
2019
2051
  nodeOrigin,
2020
2052
  onError,
2021
2053
  });
@@ -2057,7 +2089,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2057
2089
  lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2];
2058
2090
  lastPos.y = (lastPos.y ?? 0) - yMovement / transform[2];
2059
2091
  if (await panBy({ x: xMovement, y: yMovement })) {
2060
- updateNodes(lastPos, null);
2092
+ updateNodes(lastPos);
2061
2093
  }
2062
2094
  }
2063
2095
  autoPanId = requestAnimationFrame(autoPan);
@@ -2097,6 +2129,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2097
2129
  containerBounds = domNode?.getBoundingClientRect() || null;
2098
2130
  abortDrag = false;
2099
2131
  nodePositionsChanged = false;
2132
+ dragEvent = event.sourceEvent;
2100
2133
  if (nodeDragThreshold === 0) {
2101
2134
  startDrag(event);
2102
2135
  }
@@ -2107,6 +2140,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2107
2140
  .on('drag', (event) => {
2108
2141
  const { autoPanOnNodeDrag, transform, snapGrid, snapToGrid, nodeDragThreshold, nodeLookup } = getStoreItems();
2109
2142
  const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
2143
+ dragEvent = event.sourceEvent;
2110
2144
  if ((event.sourceEvent.type === 'touchmove' && event.sourceEvent.touches.length > 1) ||
2111
2145
  // if user deletes a node while dragging, we need to abort the drag to prevent errors
2112
2146
  (nodeId && !nodeLookup.has(nodeId))) {
@@ -2129,9 +2163,8 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2129
2163
  }
2130
2164
  // skip events without movement
2131
2165
  if ((lastPos.x !== pointerPos.xSnapped || lastPos.y !== pointerPos.ySnapped) && dragItems && dragStarted) {
2132
- // dragEvent = event.sourceEvent as MouseEvent;
2133
2166
  mousePosition = getEventPosition(event.sourceEvent, containerBounds);
2134
- updateNodes(pointerPos, event.sourceEvent);
2167
+ updateNodes(pointerPos);
2135
2168
  }
2136
2169
  })
2137
2170
  .on('end', (event) => {
@@ -2274,14 +2307,13 @@ function isConnectionValid(isInsideConnectionRadius, isHandleValid) {
2274
2307
  }
2275
2308
 
2276
2309
  const alwaysValid = () => true;
2277
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onReconnectEnd, updateConnection, getTransform, getFromHandle, autoPanSpeed, dragThreshold = 1, }) {
2310
+ function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onReconnectEnd, updateConnection, getTransform, getFromHandle, autoPanSpeed, dragThreshold = 1, handleDomNode, }) {
2278
2311
  // when xyflow is used inside a shadow root we can't use document
2279
2312
  const doc = getHostForElement(event.target);
2280
2313
  let autoPanId = 0;
2281
2314
  let closestHandle;
2282
2315
  const { x, y } = getEventPosition(event);
2283
- const clickedHandle = doc?.elementFromPoint(x, y);
2284
- const handleType = getHandleType(edgeUpdaterType, clickedHandle);
2316
+ const handleType = getHandleType(edgeUpdaterType, handleDomNode);
2285
2317
  const containerBounds = domNode?.getBoundingClientRect();
2286
2318
  let connectionStarted = false;
2287
2319
  if (!containerBounds || !handleType) {
@@ -2295,7 +2327,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2295
2327
  let autoPanStarted = false;
2296
2328
  let connection = null;
2297
2329
  let isValid = false;
2298
- let handleDomNode = null;
2330
+ let resultHandleDomNode = null;
2299
2331
  // when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas
2300
2332
  function autoPan() {
2301
2333
  if (!autoPanOnConnect || !containerBounds) {
@@ -2368,7 +2400,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2368
2400
  flowId,
2369
2401
  nodeLookup,
2370
2402
  });
2371
- handleDomNode = result.handleDomNode;
2403
+ resultHandleDomNode = result.handleDomNode;
2372
2404
  connection = result.connection;
2373
2405
  isValid = isConnectionValid(!!closestHandle, result.isValid);
2374
2406
  const newConnection = {
@@ -2402,7 +2434,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2402
2434
  }
2403
2435
  function onPointerUp(event) {
2404
2436
  if (connectionStarted) {
2405
- if ((closestHandle || handleDomNode) && connection && isValid) {
2437
+ if ((closestHandle || resultHandleDomNode) && connection && isValid) {
2406
2438
  onConnect?.(connection);
2407
2439
  }
2408
2440
  /*
@@ -2425,7 +2457,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2425
2457
  autoPanStarted = false;
2426
2458
  isValid = false;
2427
2459
  connection = null;
2428
- handleDomNode = null;
2460
+ resultHandleDomNode = null;
2429
2461
  doc.removeEventListener('mousemove', onPointerMove);
2430
2462
  doc.removeEventListener('mouseup', onPointerUp);
2431
2463
  doc.removeEventListener('touchmove', onPointerMove);
@@ -2489,17 +2521,18 @@ const XYHandle = {
2489
2521
 
2490
2522
  function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
2491
2523
  const selection = select(domNode);
2492
- function update({ translateExtent, width, height, zoomStep = 10, pannable = true, zoomable = true, inversePan = false, }) {
2524
+ function update({ translateExtent, width, height, zoomStep = 1, pannable = true, zoomable = true, inversePan = false, }) {
2493
2525
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2494
2526
  const zoomHandler = (event) => {
2495
- const transform = getTransform();
2496
2527
  if (event.sourceEvent.type !== 'wheel' || !panZoom) {
2497
2528
  return;
2498
2529
  }
2530
+ const transform = getTransform();
2531
+ const factor = event.sourceEvent.ctrlKey && isMacOs() ? 10 : 1;
2499
2532
  const pinchDelta = -event.sourceEvent.deltaY *
2500
2533
  (event.sourceEvent.deltaMode === 1 ? 0.05 : event.sourceEvent.deltaMode ? 1 : 0.002) *
2501
2534
  zoomStep;
2502
- const nextZoom = transform[2] * Math.pow(2, pinchDelta);
2535
+ const nextZoom = transform[2] * Math.pow(2, pinchDelta * factor);
2503
2536
  panZoom.scaleTo(nextZoom);
2504
2537
  };
2505
2538
  let panStart = [0, 0];
@@ -448,7 +448,7 @@ function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin =
448
448
  const parentNode = node.parentId ? nodeLookup.get(node.parentId) : undefined;
449
449
  const { x: parentX, y: parentY } = parentNode ? parentNode.internals.positionAbsolute : { x: 0, y: 0 };
450
450
  const origin = node.origin ?? nodeOrigin;
451
- let extent = nodeExtent;
451
+ let extent = node.extent || nodeExtent;
452
452
  if (node.extent === 'parent' && !node.expandParent) {
453
453
  if (!parentNode) {
454
454
  onError?.('005', errorMessages['error005']());
@@ -1160,7 +1160,7 @@ const distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y
1160
1160
  * With this function we try to mimic an orthogonal edge routing behaviour
1161
1161
  * It's not as good as a real orthogonal edge routing, but it's faster and good enough as a default for step and smooth step edges
1162
1162
  */
1163
- function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) {
1163
+ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, stepPosition, }) {
1164
1164
  const sourceDir = handleDirections[sourcePosition];
1165
1165
  const targetDir = handleDirections[targetPosition];
1166
1166
  const sourceGapped = { x: source.x + sourceDir.x * offset, y: source.y + sourceDir.y * offset };
@@ -1176,7 +1176,7 @@ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPos
1176
1176
  let centerX, centerY;
1177
1177
  const sourceGapOffset = { x: 0, y: 0 };
1178
1178
  const targetGapOffset = { x: 0, y: 0 };
1179
- const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
1179
+ const [, , defaultOffsetX, defaultOffsetY] = getEdgeCenter({
1180
1180
  sourceX: source.x,
1181
1181
  sourceY: source.y,
1182
1182
  targetX: target.x,
@@ -1184,8 +1184,16 @@ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPos
1184
1184
  });
1185
1185
  // opposite handle positions, default case
1186
1186
  if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
1187
- centerX = center.x ?? defaultCenterX;
1188
- centerY = center.y ?? defaultCenterY;
1187
+ if (dirAccessor === 'x') {
1188
+ // Primary direction is horizontal, so stepPosition affects X coordinate
1189
+ centerX = center.x ?? (sourceGapped.x + (targetGapped.x - sourceGapped.x) * stepPosition);
1190
+ centerY = center.y ?? (sourceGapped.y + targetGapped.y) / 2;
1191
+ }
1192
+ else {
1193
+ // Primary direction is vertical, so stepPosition affects Y coordinate
1194
+ centerX = center.x ?? (sourceGapped.x + targetGapped.x) / 2;
1195
+ centerY = center.y ?? (sourceGapped.y + (targetGapped.y - sourceGapped.y) * stepPosition);
1196
+ }
1189
1197
  /*
1190
1198
  * --->
1191
1199
  * |
@@ -1318,7 +1326,7 @@ function getBend(a, b, c, size) {
1318
1326
  * ```
1319
1327
  * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
1320
1328
  */
1321
- function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) {
1329
+ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, stepPosition = 0.5, }) {
1322
1330
  const [points, labelX, labelY, offsetX, offsetY] = getPoints({
1323
1331
  source: { x: sourceX, y: sourceY },
1324
1332
  sourcePosition,
@@ -1326,6 +1334,7 @@ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom,
1326
1334
  targetPosition,
1327
1335
  center: { x: centerX, y: centerY },
1328
1336
  offset,
1337
+ stepPosition,
1329
1338
  });
1330
1339
  const path = points.reduce((res, p, i) => {
1331
1340
  let segment = '';
@@ -1955,6 +1964,25 @@ function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true,
1955
1964
  nodesFromDragItems,
1956
1965
  ];
1957
1966
  }
1967
+ /**
1968
+ * If a selection is being dragged we want to apply the same snap offset to all nodes in the selection.
1969
+ * This function calculates the snap offset based on the first node in the selection.
1970
+ */
1971
+ function calculateSnapOffset({ dragItems, snapGrid, x, y, }) {
1972
+ const refDragItem = dragItems.values().next().value;
1973
+ if (!refDragItem) {
1974
+ return null;
1975
+ }
1976
+ const refPos = {
1977
+ x: x - refDragItem.distance.x,
1978
+ y: y - refDragItem.distance.y,
1979
+ };
1980
+ const refPosSnapped = snapPosition(refPos, snapGrid);
1981
+ return {
1982
+ x: refPosSnapped.x - refPos.x,
1983
+ y: refPosSnapped.y - refPos.y,
1984
+ };
1985
+ }
1958
1986
 
1959
1987
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1960
1988
  function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop, }) {
@@ -1968,39 +1996,43 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1968
1996
  let d3Selection = null;
1969
1997
  let abortDrag = false; // prevents unintentional dragging on multitouch
1970
1998
  let nodePositionsChanged = false;
1999
+ // we store the last drag event to be able to use it in the update function
2000
+ let dragEvent = null;
1971
2001
  // public functions
1972
2002
  function update({ noDragClassName, handleSelector, domNode, isSelectable, nodeId, nodeClickDistance = 0, }) {
1973
2003
  d3Selection = select(domNode);
1974
- function updateNodes({ x, y }, dragEvent) {
2004
+ function updateNodes({ x, y }) {
1975
2005
  const { nodeLookup, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onNodeDrag, onSelectionDrag, onError, updateNodePositions, } = getStoreItems();
1976
2006
  lastPos = { x, y };
1977
2007
  let hasChange = false;
1978
- let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };
1979
- if (dragItems.size > 1 && nodeExtent) {
1980
- const rect = getInternalNodesBounds(dragItems);
1981
- nodesBox = rectToBox(rect);
1982
- }
2008
+ const isMultiDrag = dragItems.size > 1;
2009
+ const nodesBox = isMultiDrag && nodeExtent ? rectToBox(getInternalNodesBounds(dragItems)) : null;
2010
+ const multiDragSnapOffset = isMultiDrag && snapToGrid
2011
+ ? calculateSnapOffset({
2012
+ dragItems,
2013
+ snapGrid,
2014
+ x,
2015
+ y,
2016
+ })
2017
+ : null;
1983
2018
  for (const [id, dragItem] of dragItems) {
2019
+ /*
2020
+ * if the node is not in the nodeLookup anymore, it was probably deleted while dragging
2021
+ */
1984
2022
  if (!nodeLookup.has(id)) {
1985
- /*
1986
- * if the node is not in the nodeLookup anymore, it was probably deleted while dragging
1987
- * and we don't need to update it anymore
1988
- */
1989
2023
  continue;
1990
2024
  }
1991
2025
  let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
1992
2026
  if (snapToGrid) {
1993
- nextPosition = snapPosition(nextPosition, snapGrid);
2027
+ nextPosition = multiDragSnapOffset
2028
+ ? {
2029
+ x: nextPosition.x + multiDragSnapOffset.x,
2030
+ y: nextPosition.y + multiDragSnapOffset.y,
2031
+ }
2032
+ : snapPosition(nextPosition, snapGrid);
1994
2033
  }
1995
- /*
1996
- * if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
1997
- * based on its position so that the node stays at it's position relative to the selection.
1998
- */
1999
- let adjustedNodeExtent = [
2000
- [nodeExtent[0][0], nodeExtent[0][1]],
2001
- [nodeExtent[1][0], nodeExtent[1][1]],
2002
- ];
2003
- if (dragItems.size > 1 && nodeExtent && !dragItem.extent) {
2034
+ let adjustedNodeExtent = null;
2035
+ if (isMultiDrag && nodeExtent && !dragItem.extent && nodesBox) {
2004
2036
  const { positionAbsolute } = dragItem.internals;
2005
2037
  const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
2006
2038
  const x2 = positionAbsolute.x + dragItem.measured.width - nodesBox.x2 + nodeExtent[1][0];
@@ -2015,7 +2047,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2015
2047
  nodeId: id,
2016
2048
  nextPosition,
2017
2049
  nodeLookup,
2018
- nodeExtent: adjustedNodeExtent,
2050
+ nodeExtent: adjustedNodeExtent ? adjustedNodeExtent : nodeExtent,
2019
2051
  nodeOrigin,
2020
2052
  onError,
2021
2053
  });
@@ -2057,7 +2089,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2057
2089
  lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2];
2058
2090
  lastPos.y = (lastPos.y ?? 0) - yMovement / transform[2];
2059
2091
  if (await panBy({ x: xMovement, y: yMovement })) {
2060
- updateNodes(lastPos, null);
2092
+ updateNodes(lastPos);
2061
2093
  }
2062
2094
  }
2063
2095
  autoPanId = requestAnimationFrame(autoPan);
@@ -2097,6 +2129,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2097
2129
  containerBounds = domNode?.getBoundingClientRect() || null;
2098
2130
  abortDrag = false;
2099
2131
  nodePositionsChanged = false;
2132
+ dragEvent = event.sourceEvent;
2100
2133
  if (nodeDragThreshold === 0) {
2101
2134
  startDrag(event);
2102
2135
  }
@@ -2107,6 +2140,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2107
2140
  .on('drag', (event) => {
2108
2141
  const { autoPanOnNodeDrag, transform, snapGrid, snapToGrid, nodeDragThreshold, nodeLookup } = getStoreItems();
2109
2142
  const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
2143
+ dragEvent = event.sourceEvent;
2110
2144
  if ((event.sourceEvent.type === 'touchmove' && event.sourceEvent.touches.length > 1) ||
2111
2145
  // if user deletes a node while dragging, we need to abort the drag to prevent errors
2112
2146
  (nodeId && !nodeLookup.has(nodeId))) {
@@ -2129,9 +2163,8 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
2129
2163
  }
2130
2164
  // skip events without movement
2131
2165
  if ((lastPos.x !== pointerPos.xSnapped || lastPos.y !== pointerPos.ySnapped) && dragItems && dragStarted) {
2132
- // dragEvent = event.sourceEvent as MouseEvent;
2133
2166
  mousePosition = getEventPosition(event.sourceEvent, containerBounds);
2134
- updateNodes(pointerPos, event.sourceEvent);
2167
+ updateNodes(pointerPos);
2135
2168
  }
2136
2169
  })
2137
2170
  .on('end', (event) => {
@@ -2274,14 +2307,13 @@ function isConnectionValid(isInsideConnectionRadius, isHandleValid) {
2274
2307
  }
2275
2308
 
2276
2309
  const alwaysValid = () => true;
2277
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onReconnectEnd, updateConnection, getTransform, getFromHandle, autoPanSpeed, dragThreshold = 1, }) {
2310
+ function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onReconnectEnd, updateConnection, getTransform, getFromHandle, autoPanSpeed, dragThreshold = 1, handleDomNode, }) {
2278
2311
  // when xyflow is used inside a shadow root we can't use document
2279
2312
  const doc = getHostForElement(event.target);
2280
2313
  let autoPanId = 0;
2281
2314
  let closestHandle;
2282
2315
  const { x, y } = getEventPosition(event);
2283
- const clickedHandle = doc?.elementFromPoint(x, y);
2284
- const handleType = getHandleType(edgeUpdaterType, clickedHandle);
2316
+ const handleType = getHandleType(edgeUpdaterType, handleDomNode);
2285
2317
  const containerBounds = domNode?.getBoundingClientRect();
2286
2318
  let connectionStarted = false;
2287
2319
  if (!containerBounds || !handleType) {
@@ -2295,7 +2327,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2295
2327
  let autoPanStarted = false;
2296
2328
  let connection = null;
2297
2329
  let isValid = false;
2298
- let handleDomNode = null;
2330
+ let resultHandleDomNode = null;
2299
2331
  // when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas
2300
2332
  function autoPan() {
2301
2333
  if (!autoPanOnConnect || !containerBounds) {
@@ -2368,7 +2400,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2368
2400
  flowId,
2369
2401
  nodeLookup,
2370
2402
  });
2371
- handleDomNode = result.handleDomNode;
2403
+ resultHandleDomNode = result.handleDomNode;
2372
2404
  connection = result.connection;
2373
2405
  isValid = isConnectionValid(!!closestHandle, result.isValid);
2374
2406
  const newConnection = {
@@ -2402,7 +2434,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2402
2434
  }
2403
2435
  function onPointerUp(event) {
2404
2436
  if (connectionStarted) {
2405
- if ((closestHandle || handleDomNode) && connection && isValid) {
2437
+ if ((closestHandle || resultHandleDomNode) && connection && isValid) {
2406
2438
  onConnect?.(connection);
2407
2439
  }
2408
2440
  /*
@@ -2425,7 +2457,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2425
2457
  autoPanStarted = false;
2426
2458
  isValid = false;
2427
2459
  connection = null;
2428
- handleDomNode = null;
2460
+ resultHandleDomNode = null;
2429
2461
  doc.removeEventListener('mousemove', onPointerMove);
2430
2462
  doc.removeEventListener('mouseup', onPointerUp);
2431
2463
  doc.removeEventListener('touchmove', onPointerMove);
@@ -2489,17 +2521,18 @@ const XYHandle = {
2489
2521
 
2490
2522
  function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
2491
2523
  const selection = select(domNode);
2492
- function update({ translateExtent, width, height, zoomStep = 10, pannable = true, zoomable = true, inversePan = false, }) {
2524
+ function update({ translateExtent, width, height, zoomStep = 1, pannable = true, zoomable = true, inversePan = false, }) {
2493
2525
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2494
2526
  const zoomHandler = (event) => {
2495
- const transform = getTransform();
2496
2527
  if (event.sourceEvent.type !== 'wheel' || !panZoom) {
2497
2528
  return;
2498
2529
  }
2530
+ const transform = getTransform();
2531
+ const factor = event.sourceEvent.ctrlKey && isMacOs() ? 10 : 1;
2499
2532
  const pinchDelta = -event.sourceEvent.deltaY *
2500
2533
  (event.sourceEvent.deltaMode === 1 ? 0.05 : event.sourceEvent.deltaMode ? 1 : 0.002) *
2501
2534
  zoomStep;
2502
- const nextZoom = transform[2] * Math.pow(2, pinchDelta);
2535
+ const nextZoom = transform[2] * Math.pow(2, pinchDelta * factor);
2503
2536
  panZoom.scaleTo(nextZoom);
2504
2537
  };
2505
2538
  let panStart = [0, 0];
@@ -40,6 +40,7 @@ export type EdgeBase<EdgeData extends Record<string, unknown> = Record<string, u
40
40
  export type SmoothStepPathOptions = {
41
41
  offset?: number;
42
42
  borderRadius?: number;
43
+ stepPosition?: number;
43
44
  };
44
45
  export type StepPathOptions = {
45
46
  offset?: number;
@@ -76,8 +77,8 @@ export declare enum ConnectionLineType {
76
77
  * @public
77
78
  */
78
79
  export type EdgeMarker = {
79
- type: MarkerType;
80
- color?: string;
80
+ type: MarkerType | `${MarkerType}`;
81
+ color?: string | null;
81
82
  width?: number;
82
83
  height?: number;
83
84
  markerUnits?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/types/edges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/types/edges.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,7 @@
1
1
  import type { Position, IsValidConnection } from '.';
2
+ /**
3
+ * @inline
4
+ */
2
5
  export type HandleType = 'source' | 'target';
3
6
  export type Handle = {
4
7
  id?: string | null;
@@ -14,14 +17,13 @@ export type HandleProps = {
14
17
  /**
15
18
  * Type of the handle.
16
19
  * @default "source"
17
- * @example HandleType.Source, HandleType.Target
18
20
  */
19
21
  type: HandleType;
20
22
  /**
21
23
  * The position of the handle relative to the node. In a horizontal flow source handles are
22
24
  * typically `Position.Right` and in a vertical flow they are typically `Position.Top`.
23
25
  * @default Position.Top
24
- * @example Position.TopLeft, Position.TopRight, Position.BottomLeft, Position.BottomRight
26
+ * @example Position.Top, Position.Right, Position.Bottom, Position.Left
25
27
  */
26
28
  position: Position;
27
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/types/handles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,GAAG,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/types/handles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,GAAG,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,EAAE,QAAQ,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC"}
@@ -24,6 +24,12 @@ export interface GetSmoothStepPathParams {
24
24
  centerY?: number;
25
25
  /** @default 20 */
26
26
  offset?: number;
27
+ /**
28
+ * Controls where the bend occurs along the path.
29
+ * 0 = at source, 1 = at target, 0.5 = midpoint
30
+ * @default 0.5
31
+ */
32
+ stepPosition?: number;
27
33
  }
28
34
  /**
29
35
  * The `getSmoothStepPath` util returns everything you need to render a stepped path
@@ -56,5 +62,5 @@ export interface GetSmoothStepPathParams {
56
62
  * ```
57
63
  * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
58
64
  */
59
- export declare function getSmoothStepPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, borderRadius, centerX, centerY, offset, }: GetSmoothStepPathParams): [path: string, labelX: number, labelY: number, offsetX: number, offsetY: number];
65
+ export declare function getSmoothStepPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, borderRadius, centerX, centerY, offset, stepPosition, }: GetSmoothStepPathParams): [path: string, labelX: number, labelY: number, offsetX: number, offsetY: number];
60
66
  //# sourceMappingURL=smoothstep-edge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"smoothstep-edge.d.ts","sourceRoot":"","sources":["../../../src/utils/edges/smoothstep-edge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAmB,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,iBAAiB;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwLD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,OAAO,EACP,cAAgC,EAChC,OAAO,EACP,OAAO,EACP,cAA6B,EAC7B,YAAgB,EAChB,OAAO,EACP,OAAO,EACP,MAAW,GACZ,EAAE,uBAAuB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAyB5G"}
1
+ {"version":3,"file":"smoothstep-edge.d.ts","sourceRoot":"","sources":["../../../src/utils/edges/smoothstep-edge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAmB,MAAM,aAAa,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,iBAAiB;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,OAAO,EACP,cAAgC,EAChC,OAAO,EACP,OAAO,EACP,cAA6B,EAC7B,YAAgB,EAChB,OAAO,EACP,OAAO,EACP,MAAW,EACX,YAAkB,GACnB,EAAE,uBAAuB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CA0B5G"}
@@ -2,7 +2,7 @@ import type { EdgeBase, EdgeMarkerType, MarkerProps } from '../types';
2
2
  export declare function getMarkerId(marker: EdgeMarkerType | undefined, id?: string | null): string;
3
3
  export declare function createMarkerIds(edges: EdgeBase[], { id, defaultColor, defaultMarkerStart, defaultMarkerEnd, }: {
4
4
  id?: string | null;
5
- defaultColor?: string;
5
+ defaultColor?: string | null;
6
6
  defaultMarkerStart?: EdgeMarkerType;
7
7
  defaultMarkerEnd?: EdgeMarkerType;
8
8
  }): MarkerProps[];
@@ -1 +1 @@
1
- {"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/utils/marker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAc,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAElF,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAe1F;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,EACE,EAAE,EACF,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,gBAAgB,CAAC,EAAE,cAAc,CAAC;CACnC,iBAmBF"}
1
+ {"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/utils/marker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAc,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAElF,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAe1F;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,EACE,EAAE,EACF,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,gBAAgB,CAAC,EAAE,cAAc,CAAC;CACnC,iBAmBF"}