@xyflow/vue 2.0.0-next.2 → 2.0.0-next.4

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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createPropsRestProxy, createTextVNode, createVNode, defineComponent, effectScope, getCurrentInstance, h, inject, isMemoSame, isRef, markRaw, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeMount, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, provide, reactive, renderList, renderSlot, resolveComponent, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toRef, toRefs, toValue, unref, useAttrs, useId, useModel, useSlots, watch, watchEffect, withCtx } from "vue";
2
- import { ConnectionLineType, ConnectionLineType as ConnectionLineType$1, ConnectionMode, ConnectionMode as ConnectionMode$1, PanOnScrollMode, PanOnScrollMode as PanOnScrollMode$1, Position, Position as Position$1, ResizeControlVariant, ResizeControlVariant as ResizeControlVariant$2, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, adoptUserNodes, areConnectionMapsEqual, areSetsEqual, calcAutoPan, clamp, clampPosition, clampPositionToParent, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierEdgeCenter as getBezierEdgeCenter$1, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfBoxes, getBoundsOfRects, getBoundsOfRects as getBoundsOfRects$1, getConnectedEdges, getConnectedEdges as getConnectedEdges$1, getConnectionStatus, getDimensions, getEdgeId, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHandlePosition, getHostForElement, getIncomers, getMarkerId, getMarkerId as getMarkerId$1, getNodeDimensions, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getNodesInside as getNodesInside$1, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, handleExpandParent, infiniteExtent, isCoordinateExtent, isEdgeBase, isEdgeBase as isEdgeBase$1, isEdgeVisible, isInternalNodeBase, isInternalNodeBase as isInternalNodeBase$1, isMacOs, isMacOs as isMacOs$1, isMouseEvent, isNodeBase, isNodeBase as isNodeBase$1, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, oppositePosition, panBy, pointToRendererPoint, pointToRendererPoint as pointToRendererPoint$1, rendererPointToPoint, rendererPointToPoint as rendererPointToPoint$1, updateAbsolutePositions } from "@xyflow/system";
2
+ import { ConnectionLineType, ConnectionLineType as ConnectionLineType$1, ConnectionMode, ConnectionMode as ConnectionMode$1, PanOnScrollMode, PanOnScrollMode as PanOnScrollMode$1, Position, Position as Position$1, ResizeControlVariant, ResizeControlVariant as ResizeControlVariant$2, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, adoptUserNodes, areConnectionMapsEqual, areSetsEqual, calcAutoPan, calculateNodePosition, clamp, clampPosition, clampPositionToParent, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierEdgeCenter as getBezierEdgeCenter$1, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfBoxes, getBoundsOfRects, getBoundsOfRects as getBoundsOfRects$1, getConnectedEdges, getConnectedEdges as getConnectedEdges$1, getConnectionStatus, getDimensions, getEdgeId, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHandlePosition, getHostForElement, getIncomers, getMarkerId, getMarkerId as getMarkerId$1, getNodeDimensions, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getNodesInside as getNodesInside$1, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, handleExpandParent, infiniteExtent, isCoordinateExtent, isEdgeBase, isEdgeBase as isEdgeBase$1, isEdgeVisible, isInternalNodeBase, isInternalNodeBase as isInternalNodeBase$1, isMacOs, isMacOs as isMacOs$1, isMouseEvent, isNodeBase, isNodeBase as isNodeBase$1, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, oppositePosition, panBy, pointToRendererPoint, pointToRendererPoint as pointToRendererPoint$1, rendererPointToPoint, rendererPointToPoint as rendererPointToPoint$1, snapPosition, updateAbsolutePositions } from "@xyflow/system";
3
3
  import { onKeyStroke, until, useEventListener } from "@vueuse/core";
4
4
  //#region src/context/index.ts
5
5
  /** the curated instance (`useVueFlow()`) */
@@ -21,12 +21,14 @@ let ErrorCode = /* @__PURE__ */ function(ErrorCode) {
21
21
  ErrorCode["NODE_MISSING_PARENT"] = "NODE_MISSING_PARENT";
22
22
  ErrorCode["NODE_TYPE_MISSING"] = "NODE_TYPE_MISSING";
23
23
  ErrorCode["NODE_EXTENT_INVALID"] = "NODE_EXTENT_INVALID";
24
+ ErrorCode["NODE_DUPLICATE_ID"] = "NODE_DUPLICATE_ID";
24
25
  ErrorCode["EDGE_INVALID"] = "EDGE_INVALID";
25
26
  ErrorCode["EDGE_NOT_FOUND"] = "EDGE_NOT_FOUND";
26
27
  ErrorCode["EDGE_SOURCE_MISSING"] = "EDGE_SOURCE_MISSING";
27
28
  ErrorCode["EDGE_TARGET_MISSING"] = "EDGE_TARGET_MISSING";
28
29
  ErrorCode["EDGE_TYPE_MISSING"] = "EDGE_TYPE_MISSING";
29
30
  ErrorCode["EDGE_SOURCE_TARGET_MISSING"] = "EDGE_SOURCE_TARGET_MISSING";
31
+ ErrorCode["EDGE_DUPLICATE_ID"] = "EDGE_DUPLICATE_ID";
30
32
  ErrorCode["USE_VUE_FLOW_OUTSIDE_PROVIDER"] = "USE_VUE_FLOW_OUTSIDE_PROVIDER";
31
33
  return ErrorCode;
32
34
  }({});
@@ -38,11 +40,13 @@ const messages = {
38
40
  ["NODE_MISSING_PARENT"]: (id, parentId) => `Node is missing a parent\nNode id: ${id}\nParent id: ${parentId}`,
39
41
  ["NODE_TYPE_MISSING"]: (type) => `Node type is missing\nType: ${type}`,
40
42
  ["NODE_EXTENT_INVALID"]: (id) => `Only child nodes can use a parent extent\nNode id: ${id}`,
43
+ ["NODE_DUPLICATE_ID"]: (id) => `Node id is not unique — a later node overwrites the earlier one in the lookup\nNode id: ${id}`,
41
44
  ["EDGE_INVALID"]: (id) => `An edge needs a source and a target\nEdge id: ${id}`,
42
45
  ["EDGE_SOURCE_MISSING"]: (id, source) => `Edge source is missing\nEdge id: ${id} \nSource id: ${source}`,
43
46
  ["EDGE_TARGET_MISSING"]: (id, target) => `Edge target is missing\nEdge id: ${id} \nTarget id: ${target}`,
44
47
  ["EDGE_TYPE_MISSING"]: (type) => `Edge type is missing\nType: ${type}`,
45
48
  ["EDGE_SOURCE_TARGET_MISSING"]: (id, source, target) => `Edge source or target is missing\nEdge id: ${id} \nSource id: ${source} \nTarget id: ${target}`,
49
+ ["EDGE_DUPLICATE_ID"]: (id) => `Edge id is not unique — a later edge overwrites the earlier one in the lookup\nEdge id: ${id}`,
46
50
  ["EDGE_NOT_FOUND"]: (id) => `Edge not found\nEdge id: ${id}`,
47
51
  ["USE_VUE_FLOW_OUTSIDE_PROVIDER"]: () => `useVueFlow() was called without a <VueFlow> or <VueFlowProvider> ancestor (or outside a component setup). Render one of them above the call, or wrap your components in <VueFlowProvider> to share a store.`
48
52
  };
@@ -644,39 +648,6 @@ function createExtendedEventHook(defaultHandler) {
644
648
  };
645
649
  }
646
650
  //#endregion
647
- //#region src/utils/drag.ts
648
- function getParentExtent(parent) {
649
- if (parent && typeof parent.internals.positionAbsolute.x !== "undefined" && typeof parent.internals.positionAbsolute.y !== "undefined" && typeof parent.measured.width !== "undefined" && typeof parent.measured.height !== "undefined") return [[parent.internals.positionAbsolute.x, parent.internals.positionAbsolute.y], [parent.internals.positionAbsolute.x + parent.measured.width, parent.internals.positionAbsolute.y + parent.measured.height]];
650
- return false;
651
- }
652
- function getExtent(item, triggerError, extent, parent) {
653
- let currentExtent = item.extent || extent;
654
- if (currentExtent === "parent" && !item.expandParent) if (item.parentId && parent && item.measured.width && item.measured.height) {
655
- const parentExtent = getParentExtent(parent);
656
- if (parentExtent) currentExtent = parentExtent;
657
- } else {
658
- triggerError(new VueFlowError("NODE_EXTENT_INVALID", item.id));
659
- currentExtent = extent;
660
- }
661
- else if (Array.isArray(currentExtent)) {
662
- const parentX = parent?.internals.positionAbsolute.x || 0;
663
- const parentY = parent?.internals.positionAbsolute.y || 0;
664
- currentExtent = [[currentExtent[0][0] + parentX, currentExtent[0][1] + parentY], [currentExtent[1][0] + parentX, currentExtent[1][1] + parentY]];
665
- }
666
- return currentExtent === "parent" ? [[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY], [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]] : currentExtent;
667
- }
668
- function calcNextPosition(node, nextPosition, triggerError, nodeExtent, parentNode) {
669
- const measured = getNodeDimensions(node);
670
- const clampedPos = clampPosition(nextPosition, getExtent(node, triggerError, nodeExtent, parentNode), measured);
671
- return {
672
- position: {
673
- x: clampedPos.x - (parentNode?.internals.positionAbsolute.x || 0),
674
- y: clampedPos.y - (parentNode?.internals.positionAbsolute.y || 0)
675
- },
676
- computedPosition: clampedPos
677
- };
678
- }
679
- //#endregion
680
651
  //#region src/utils/edge.ts
681
652
  function getEdgeHandle(bounds, handleId) {
682
653
  if (!bounds) return null;
@@ -858,12 +829,15 @@ function reconnectEdgeAction(edge, newConnection, prevEdge, shouldReplaceId, tri
858
829
  */
859
830
  function adoptNodes(nodes, nodeLookup, parentLookup, triggerError, options) {
860
831
  const validNodes = [];
832
+ const seenNodeIds = /* @__PURE__ */ new Set();
861
833
  for (let i = 0; i < nodes.length; ++i) {
862
834
  const node = nodes[i];
863
835
  if (!isNode(node)) {
864
836
  triggerError(new VueFlowError("NODE_INVALID", node?.id ?? `[ID UNKNOWN|INDEX ${i}]`));
865
837
  continue;
866
838
  }
839
+ if (seenNodeIds.has(node.id)) triggerError(new VueFlowError("NODE_DUPLICATE_ID", node.id));
840
+ else seenNodeIds.add(node.id);
867
841
  validNodes.push(markRaw(toRaw(node)));
868
842
  }
869
843
  const priorInternals = /* @__PURE__ */ new Map();
@@ -1413,7 +1387,7 @@ function useNode(id) {
1413
1387
  * @internal
1414
1388
  */
1415
1389
  function useUpdateNodePositions() {
1416
- const { getSelectedNodes, updateNodePositions, getInternalNode, emits } = useVueFlow();
1390
+ const { getSelectedNodes, updateNodePositions, getInternalNode } = useVueFlow();
1417
1391
  const store = useStore();
1418
1392
  return (positionDiff, isShiftPressed = false) => {
1419
1393
  const xVelo = store.snapToGrid ? store.snapGrid[0] : 5;
@@ -1425,10 +1399,18 @@ function useUpdateNodePositions() {
1425
1399
  for (const node of getSelectedNodes.value) if (node.draggable || store.nodesDraggable && typeof node.draggable === "undefined") {
1426
1400
  const internalNode = getInternalNode(node.id);
1427
1401
  if (!internalNode) continue;
1428
- const { position } = calcNextPosition(internalNode, {
1402
+ let nextPosition = {
1429
1403
  x: internalNode.internals.positionAbsolute.x + positionDiffX,
1430
1404
  y: internalNode.internals.positionAbsolute.y + positionDiffY
1431
- }, emits.error, store.nodeExtent, node.parentId ? getInternalNode(node.parentId) : void 0);
1405
+ };
1406
+ if (store.snapToGrid) nextPosition = snapPosition(nextPosition, store.snapGrid);
1407
+ const { position, positionAbsolute } = calculateNodePosition({
1408
+ nodeId: node.id,
1409
+ nextPosition,
1410
+ nodeLookup: store.nodeLookup,
1411
+ nodeExtent: store.nodeExtent,
1412
+ nodeOrigin: store.nodeOrigin
1413
+ });
1432
1414
  nodeUpdates.push({
1433
1415
  id: node.id,
1434
1416
  position,
@@ -1437,10 +1419,7 @@ function useUpdateNodePositions() {
1437
1419
  y: positionDiff.y
1438
1420
  },
1439
1421
  measured: getNodeDimensions(internalNode),
1440
- internals: { positionAbsolute: {
1441
- x: internalNode.internals.positionAbsolute.x,
1442
- y: internalNode.internals.positionAbsolute.y
1443
- } }
1422
+ internals: { positionAbsolute }
1444
1423
  });
1445
1424
  }
1446
1425
  updateNodePositions(nodeUpdates, true, false);
@@ -1581,9 +1560,10 @@ function useViewportHelper(state, nodeLookup) {
1581
1560
  /**
1582
1561
  * Two-way bind a `v-model` array ref to the store, identity-in / snapshot-out, with native `watch`.
1583
1562
  *
1584
- * Used only when `<VueFlow>` does NOT own its store (it reuses a `<VueFlowProvider>`'s), so the model
1585
- * refs can't back the store directly. The owned-store path is single-source instead the model refs
1586
- * ARE the store's nodes/edges (see `createStore`'s `StoreSignals` binding), needing no sync here.
1563
+ * Runs for BOTH the owned- and reused-store paths: the store's canonical nodes/edges are always an
1564
+ * internal `shallowRef` (see `createStore`), never the v-model ref, so this is the single place the model
1565
+ * ref is bridged to the store. Both directions flush synchronously so the model ref and the store's
1566
+ * synchronous reads (`getNodes`/`state.nodes`) never disagree within a tick.
1587
1567
  *
1588
1568
  * - **out** (store → model): snapshot on every membership change; element refs are shared, so per-node
1589
1569
  * field mutations surface without a copy.
@@ -1596,24 +1576,29 @@ function syncModelArray(model, storeItems, setItems) {
1596
1576
  watch([storeItems, () => storeItems.value.length], () => {
1597
1577
  lastSnapshot = [...storeItems.value];
1598
1578
  model.value = lastSnapshot;
1599
- }, { immediate: storeItems.value.length > 0 });
1579
+ }, {
1580
+ immediate: storeItems.value.length > 0,
1581
+ flush: "sync"
1582
+ });
1600
1583
  watch([model, () => model.value?.length], ([next]) => {
1601
1584
  if (!Array.isArray(next)) return;
1602
1585
  const nextRaw = toRaw(next);
1603
1586
  if (nextRaw === lastSnapshot) return;
1604
1587
  setItems(nextRaw);
1605
- }, { immediate: true });
1588
+ }, {
1589
+ immediate: true,
1590
+ flush: "sync"
1591
+ });
1606
1592
  }
1607
1593
  /**
1608
1594
  * Watches props and updates the store accordingly
1609
1595
  *
1610
1596
  * @internal
1611
- * @param models v-model refs for nodes/edges (bound only when `ownsStore` is false see {@link syncModelArray})
1597
+ * @param models v-model refs for nodes/edges bridged to the store here (see {@link syncModelArray})
1612
1598
  * @param props the `<VueFlow>` props
1613
1599
  * @param handle the created store handle ({@link VueFlowStoreHandle}) — instance (actions) + reactive state
1614
- * @param ownsStore whether this `<VueFlow>` created the store (then nodes/edges are signal-backed and skipped here)
1615
1600
  */
1616
- function useWatchProps(models, props, handle, ownsStore = false) {
1601
+ function useWatchProps(models, props, handle) {
1617
1602
  const { instance, state } = handle;
1618
1603
  const storeRefs = storeToRefs(state);
1619
1604
  const scope = effectScope(true);
@@ -1717,10 +1702,8 @@ function useWatchProps(models, props, handle, ownsStore = false) {
1717
1702
  }
1718
1703
  };
1719
1704
  const runAll = () => {
1720
- if (!ownsStore) {
1721
- watchNodesValue();
1722
- watchEdgesValue();
1723
- }
1705
+ watchNodesValue();
1706
+ watchEdgesValue();
1724
1707
  watchMinZoom();
1725
1708
  watchMaxZoom();
1726
1709
  watchTranslateExtent();
@@ -1742,7 +1725,8 @@ const _sfc_main$22 = /* @__PURE__ */ defineComponent({
1742
1725
  props: {
1743
1726
  position: {
1744
1727
  type: String,
1745
- required: true
1728
+ required: false,
1729
+ default: "top-left"
1746
1730
  },
1747
1731
  label: {
1748
1732
  type: [String, null],
@@ -3334,14 +3318,16 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3334
3318
  const { nodeLookup, parentLookup } = useStore();
3335
3319
  const { transform, nodeOrigin, snapGrid, snapToGrid, vueFlowRef, noDragClassName } = storeToRefs(useStore());
3336
3320
  const resizeControlRef = shallowRef();
3321
+ const contextNodeId = inject(NodeId, null);
3322
+ const nodeId = toRef(() => typeof props.nodeId === "string" ? props.nodeId : contextNodeId ?? void 0);
3337
3323
  const controlPosition = toRef(() => props.position ?? DefaultPositions[props.variant]);
3338
3324
  const positionClassNames = computed(() => controlPosition.value.split("-"));
3339
3325
  const controlStyle = toRef(() => props.color ? { [StylingProperty[props.variant]]: props.color } : {});
3340
3326
  watchEffect((onCleanup) => {
3341
- if (!resizeControlRef.value || !props.nodeId) return;
3327
+ if (!resizeControlRef.value || !nodeId.value) return;
3342
3328
  const resizerInstance = XYResizer({
3343
3329
  domNode: resizeControlRef.value,
3344
- nodeId: props.nodeId,
3330
+ nodeId: nodeId.value,
3345
3331
  getStoreItems: () => ({
3346
3332
  nodeLookup,
3347
3333
  transform: transform.value,
@@ -3352,7 +3338,7 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3352
3338
  }),
3353
3339
  onChange: (changes, childChanges) => {
3354
3340
  const nodeChanges = [];
3355
- const node = nodeLookup.get(props.nodeId);
3341
+ const node = nodeLookup.get(nodeId.value);
3356
3342
  let nextX = changes.x;
3357
3343
  let nextY = changes.y;
3358
3344
  if (node?.expandParent && node.parentId) {
@@ -3384,14 +3370,14 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3384
3370
  y: nextY ?? node?.position.y ?? 0
3385
3371
  };
3386
3372
  nodeChanges.push({
3387
- id: props.nodeId,
3373
+ id: nodeId.value,
3388
3374
  type: "position",
3389
3375
  position,
3390
3376
  positionAbsolute: position
3391
3377
  });
3392
3378
  }
3393
3379
  if (typeof changes.width !== "undefined" || typeof changes.height !== "undefined") nodeChanges.push({
3394
- id: props.nodeId,
3380
+ id: nodeId.value,
3395
3381
  type: "dimensions",
3396
3382
  setAttributes: true,
3397
3383
  resizing: true,
@@ -3410,7 +3396,7 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3410
3396
  },
3411
3397
  onEnd: ({ width, height }) => {
3412
3398
  triggerEmits.nodesChange([{
3413
- id: props.nodeId,
3399
+ id: nodeId.value,
3414
3400
  type: "dimensions",
3415
3401
  resizing: false,
3416
3402
  dimensions: {
@@ -3461,6 +3447,8 @@ const _sfc_main$14 = /* @__PURE__ */ defineComponent({
3461
3447
  vueFlowRef,
3462
3448
  noDragClassName,
3463
3449
  resizeControlRef,
3450
+ contextNodeId,
3451
+ nodeId,
3464
3452
  controlPosition,
3465
3453
  positionClassNames,
3466
3454
  controlStyle,
@@ -4304,8 +4292,11 @@ function useActions(state, nodeLookup, parentLookup, edgeLookup) {
4304
4292
  */
4305
4293
  function commitEdges(next) {
4306
4294
  const rawEdgeLookup = toRaw(edgeLookup);
4295
+ const seenEdgeIds = /* @__PURE__ */ new Set();
4307
4296
  for (let i = 0; i < next.length; i++) {
4308
4297
  const edge = next[i] = markRaw(toRaw(next[i]));
4298
+ if (seenEdgeIds.has(edge.id)) state.hooks.error.trigger(new VueFlowError("EDGE_DUPLICATE_ID", edge.id));
4299
+ else seenEdgeIds.add(edge.id);
4309
4300
  if (rawEdgeLookup.get(edge.id) !== edge) edgeLookup.set(edge.id, edge);
4310
4301
  }
4311
4302
  if (rawEdgeLookup.size !== next.length) {
@@ -4314,7 +4305,7 @@ function useActions(state, nodeLookup, parentLookup, edgeLookup) {
4314
4305
  for (const id of rawEdgeLookup.keys()) if (!nextIds.has(id)) edgeLookup.delete(id);
4315
4306
  }
4316
4307
  state.edges = next;
4317
- updateConnectionLookup(state.connectionLookup, state.edges);
4308
+ updateConnectionLookup(state.connectionLookup, next);
4318
4309
  }
4319
4310
  /**
4320
4311
  * Recompute parent-aware `internals.positionAbsolute` on the system lookup, then mirror into the
@@ -4989,17 +4980,14 @@ function useGetters(state, nodeLookup) {
4989
4980
  * @internal
4990
4981
  */
4991
4982
  function createVueFlowStore(id, preloadedState, onDestroy, signals) {
4992
- const nodesSignal = signals?.nodes ?? shallowRef([]);
4993
- const edgesSignal = signals?.edges ?? shallowRef([]);
4994
- let lastWriteNodes;
4995
- let lastWriteEdges;
4983
+ const nodesSignal = shallowRef(signals?.nodes?.value ?? []);
4984
+ const edgesSignal = shallowRef(signals?.edges?.value ?? []);
4996
4985
  const emptyNodes = [];
4997
4986
  const emptyEdges = [];
4998
4987
  const state = useState();
4999
4988
  Object.defineProperty(state, "nodes", {
5000
4989
  get: () => nodesSignal.value ?? emptyNodes,
5001
4990
  set: (value) => {
5002
- lastWriteNodes = toRaw(value);
5003
4991
  nodesSignal.value = value;
5004
4992
  },
5005
4993
  enumerable: true,
@@ -5008,7 +4996,6 @@ function createVueFlowStore(id, preloadedState, onDestroy, signals) {
5008
4996
  Object.defineProperty(state, "edges", {
5009
4997
  get: () => edgesSignal.value ?? emptyEdges,
5010
4998
  set: (value) => {
5011
- lastWriteEdges = toRaw(value);
5012
4999
  edgesSignal.value = value;
5013
5000
  },
5014
5001
  enumerable: true,
@@ -5031,14 +5018,6 @@ function createVueFlowStore(id, preloadedState, onDestroy, signals) {
5031
5018
  ...reactiveState,
5032
5019
  ...preloadedState
5033
5020
  });
5034
- if (signals?.nodes) watch(nodesSignal, (next) => {
5035
- const nextRaw = next && toRaw(next);
5036
- if (nextRaw && nextRaw !== lastWriteNodes) actions.setNodes(nextRaw);
5037
- });
5038
- if (signals?.edges) watch(edgesSignal, (next) => {
5039
- const nextRaw = next && toRaw(next);
5040
- if (nextRaw && nextRaw !== lastWriteEdges) actions.setEdges(nextRaw);
5041
- });
5042
5021
  return {
5043
5022
  instance: {
5044
5023
  ...hooksOn,
@@ -5189,7 +5168,7 @@ function useViewportSync(model, state = useStore()) {
5189
5168
  };
5190
5169
  if (sameViewport(viewport, model.value)) return;
5191
5170
  model.value = viewport;
5192
- });
5171
+ }, { flush: "sync" });
5193
5172
  }
5194
5173
  //#endregion
5195
5174
  //#region src/components/ConnectionLine/index.ts
@@ -5222,13 +5201,13 @@ const ConnectionLine = defineComponent({
5222
5201
  }
5223
5202
  const fromHandle = (startHandleId ? handleBounds.find((d) => d.id === startHandleId) : handleBounds[0]) ?? null;
5224
5203
  const fromPosition = fromHandle?.position ?? Position$1.Top;
5225
- const { x: fromX, y: fromY } = getHandlePosition(fromNode.value, fromHandle, fromPosition);
5204
+ const { x: fromX, y: fromY } = getHandlePosition(fromNode.value, fromHandle, fromPosition, true);
5226
5205
  let toHandle = null;
5227
5206
  if (toNode.value) if (connectionMode.value === ConnectionMode$1.Strict) toHandle = toNode.value.internals.handleBounds?.[handleType === "source" ? "target" : "source"]?.find((d) => d.id === connectionEndHandle.value?.id) || null;
5228
5207
  else toHandle = [...toNode.value.internals.handleBounds?.source ?? [], ...toNode.value.internals.handleBounds?.target ?? []].find((d) => d.id === connectionEndHandle.value?.id) || null;
5229
5208
  const toPosition = connectionEndHandle.value?.position ?? (fromPosition ? oppositePosition[fromPosition] : null);
5230
5209
  if (!fromPosition || !toPosition) return null;
5231
- const { x: toX, y: toY } = toHandle && toNode.value ? getHandlePosition(toNode.value, toHandle, toPosition) : pointer.value;
5210
+ const { x: toX, y: toY } = toHandle && toNode.value ? getHandlePosition(toNode.value, toHandle, toPosition, true) : pointer.value;
5232
5211
  const type = connectionLineOptions.value.type ?? ConnectionLineType$1.Bezier;
5233
5212
  let dAttr = "";
5234
5213
  const pathParams = {
@@ -5969,6 +5948,8 @@ const NodeWrapper = defineComponent({
5969
5948
  const getStyle = computed(() => {
5970
5949
  const node = nodeRef.value;
5971
5950
  const styles = { ...node?.style };
5951
+ if (typeof styles.width === "number") styles.width = `${styles.width}px`;
5952
+ if (typeof styles.height === "number") styles.height = `${styles.height}px`;
5972
5953
  const isMeasured = !!node?.internals.handleBounds;
5973
5954
  const width = node?.width ?? (isMeasured ? void 0 : node?.initialWidth);
5974
5955
  const height = node?.height ?? (isMeasured ? void 0 : node?.initialHeight);
@@ -7337,7 +7318,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
7337
7318
  }, props, {
7338
7319
  instance,
7339
7320
  state
7340
- }, ownsStore);
7321
+ });
7341
7322
  useHooks(emit, state.hooks);
7342
7323
  useOnInitHandler(instance);
7343
7324
  useSelectionChange(instance);
@@ -7410,6 +7391,89 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
7410
7391
  }
7411
7392
  var VueFlowProvider_default = /* @__PURE__ */ export_helper_default(_sfc_main, [["render", _sfc_render], ["__file", "/Users/moritz/xyflow/xyflow/packages/vue/src/container/VueFlowProvider/VueFlowProvider.vue"]]);
7412
7393
  //#endregion
7413
- export { Background_default as Background, BaseEdge_default as BaseEdge, BezierEdge, ConnectionLineType, ConnectionMode, ControlButton_default as ControlButton, Controls_default as Controls, EdgeLabelRenderer_default as EdgeLabelRenderer, EdgeText_default as EdgeText, ErrorCode, Handle_default as Handle, MarkerType, MiniMap_default as MiniMap, MiniMapNode_default as MiniMapNode, NodeId as NodeIdInjection, ResizeControl_default as NodeResizeControl, NodeResizer_default as NodeResizer, NodeToolbar_default as NodeToolbar, PanOnScrollMode, Panel_default as Panel, Position, ResizeControlVariant, SelectionMode, SimpleBezierEdge, Slots, SmoothStepEdge, StepEdge, StraightEdge, VueFlow_default as VueFlow, VueFlowError, VueFlow as VueFlowInjection, VueFlowProvider_default as VueFlowProvider, applyChanges, applyEdgeChanges, applyNodeChanges, clamp, connectionExists, defaultEdgeTypes, defaultNodeTypes, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getIncomers, getMarkerId, getNodesBounds, getNodesInside, getOutgoers, getSimpleBezierPath, getSmoothStepPath, getStraightPath, getViewportForBounds, isEdge, isEdgeBase, isErrorOfType, isInternalNode, isInternalNodeBase, isMacOs, isNode, isNodeBase, pointToRendererPoint, rendererPointToPoint, storeToRefs, useConnection, useEdge, useEdgesData, useHandle, useInternalNode, useKeyPress, useNode, useNodeConnections, useNodeId, useNodesData, useNodesInitialized, useStore, useVueFlow };
7394
+ //#region src/utils/prop-of.ts
7395
+ function propOf(required = false) {
7396
+ return {
7397
+ type: null,
7398
+ required
7399
+ };
7400
+ }
7401
+ //#endregion
7402
+ //#region src/props-objects.gen.ts
7403
+ function nodeProps() {
7404
+ return {
7405
+ data: propOf(true),
7406
+ deletable: propOf(true),
7407
+ dragHandle: propOf(),
7408
+ draggable: propOf(true),
7409
+ dragging: propOf(true),
7410
+ height: propOf(),
7411
+ id: propOf(true),
7412
+ isConnectable: propOf(true),
7413
+ parentId: propOf(),
7414
+ positionAbsoluteX: propOf(true),
7415
+ positionAbsoluteY: propOf(true),
7416
+ selectable: propOf(true),
7417
+ selected: propOf(true),
7418
+ sourcePosition: propOf(),
7419
+ targetPosition: propOf(),
7420
+ type: propOf(true),
7421
+ width: propOf(),
7422
+ zIndex: propOf(true)
7423
+ };
7424
+ }
7425
+ function edgeProps() {
7426
+ return {
7427
+ animated: propOf(),
7428
+ curvature: propOf(),
7429
+ data: propOf(),
7430
+ deletable: propOf(),
7431
+ id: propOf(true),
7432
+ interactionWidth: propOf(),
7433
+ label: propOf(),
7434
+ labelBgBorderRadius: propOf(),
7435
+ labelBgPadding: propOf(),
7436
+ labelBgStyle: propOf(),
7437
+ labelShowBg: propOf(),
7438
+ labelStyle: propOf(),
7439
+ markerEnd: propOf(),
7440
+ markerStart: propOf(),
7441
+ reconnectable: propOf(),
7442
+ selectable: propOf(),
7443
+ selected: propOf(),
7444
+ source: propOf(true),
7445
+ sourceHandleId: propOf(),
7446
+ sourcePosition: propOf(true),
7447
+ sourceX: propOf(true),
7448
+ sourceY: propOf(true),
7449
+ style: propOf(),
7450
+ target: propOf(true),
7451
+ targetHandleId: propOf(),
7452
+ targetPosition: propOf(true),
7453
+ targetX: propOf(true),
7454
+ targetY: propOf(true),
7455
+ type: propOf()
7456
+ };
7457
+ }
7458
+ function connectionLineProps() {
7459
+ return {
7460
+ connectionStatus: propOf(true),
7461
+ fromHandle: propOf(true),
7462
+ fromNode: propOf(true),
7463
+ fromPosition: propOf(true),
7464
+ fromX: propOf(true),
7465
+ fromY: propOf(true),
7466
+ markerEnd: propOf(),
7467
+ markerStart: propOf(),
7468
+ pointer: propOf(true),
7469
+ toHandle: propOf(true),
7470
+ toNode: propOf(true),
7471
+ toPosition: propOf(true),
7472
+ toX: propOf(true),
7473
+ toY: propOf(true)
7474
+ };
7475
+ }
7476
+ //#endregion
7477
+ export { Background_default as Background, BaseEdge_default as BaseEdge, BezierEdge, ConnectionLineType, ConnectionMode, ControlButton_default as ControlButton, Controls_default as Controls, EdgeLabelRenderer_default as EdgeLabelRenderer, EdgeText_default as EdgeText, ErrorCode, Handle_default as Handle, MarkerType, MiniMap_default as MiniMap, MiniMapNode_default as MiniMapNode, NodeId as NodeIdInjection, ResizeControl_default as NodeResizeControl, NodeResizer_default as NodeResizer, NodeToolbar_default as NodeToolbar, PanOnScrollMode, Panel_default as Panel, Position, ResizeControlVariant, SelectionMode, SimpleBezierEdge, Slots, SmoothStepEdge, StepEdge, StraightEdge, VueFlow_default as VueFlow, VueFlowError, VueFlow as VueFlowInjection, VueFlowProvider_default as VueFlowProvider, applyChanges, applyEdgeChanges, applyNodeChanges, clamp, connectionExists, connectionLineProps, defaultEdgeTypes, defaultNodeTypes, edgeProps, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getIncomers, getMarkerId, getNodesBounds, getNodesInside, getOutgoers, getSimpleBezierPath, getSmoothStepPath, getStraightPath, getViewportForBounds, isEdge, isEdgeBase, isErrorOfType, isInternalNode, isInternalNodeBase, isMacOs, isNode, isNodeBase, nodeProps, pointToRendererPoint, rendererPointToPoint, storeToRefs, useConnection, useEdge, useEdgesData, useHandle, useInternalNode, useKeyPress, useNode, useNodeConnections, useNodeId, useNodesData, useNodesInitialized, useStore, useVueFlow };
7414
7478
 
7415
7479
  //# sourceMappingURL=index.mjs.map