@lupinum/board-connections 0.1.0 → 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { type Ref } from 'vue';
2
- import { type BoardEngine, type BoardNode } from '@lupinum/board-core';
2
+ import { type BoardEngine, type BoardNode, type CanvasColor } from '@lupinum/board-core';
3
3
  import type { ConnectionNodeHandle } from './hit-testing.js';
4
4
  import type { ConnectionDragState, DragEnd } from './controller.js';
5
5
  import type { BoardEdge, ConnectionEndpointMode, ConnectionsApi, ConnectionsEventMap, CreateNodeForConnectionContext } from './types.js';
@@ -12,8 +12,10 @@ interface ConnectionActionsState {
12
12
  selectedEdgeId: Ref<string | null>;
13
13
  editingEdgeId: Ref<string | null>;
14
14
  labelDraft: Ref<string>;
15
- colorMenuEdgeId: Ref<string | null>;
16
- directionMenuEdgeId: Ref<string | null>;
15
+ openMenu: Ref<{
16
+ kind: 'color' | 'direction';
17
+ edgeId: string;
18
+ } | null>;
17
19
  }
18
20
  interface ConnectionActionsDeps {
19
21
  getEngine(): ConnectionEngine;
@@ -33,7 +35,7 @@ export declare function createConnectionActions(deps: ConnectionActionsDeps): {
33
35
  clearLabel: (edgeId: string) => void;
34
36
  cancelLabelEdit: () => void;
35
37
  setDirectionality: (edgeId: string, direction: "none" | "to" | "both") => void;
36
- applyEdgeColor: (edgeId: string, color: string | undefined) => void;
38
+ applyEdgeColor: (edgeId: string, color: CanvasColor | undefined) => void;
37
39
  resetEndpointAnchor: (edgeId: string, end: DragEnd | "both") => void;
38
40
  deleteEdge: (edgeId: string) => void;
39
41
  commitDrag: (active: ConnectionDragState) => void;
@@ -0,0 +1,25 @@
1
+ import { type ComputedRef, type Ref } from 'vue';
2
+ import type { NodeId } from '@lupinum/board-core';
3
+ import type { useBoardEngine } from '@lupinum/vue-board';
4
+ import { type ConnectionDragState, type DragEnd, type PendingConnectionDrag } from './controller.js';
5
+ import type { AnchorSide } from './types.js';
6
+ import type { ConnectionEngine } from './connection-engine.js';
7
+ import type { EdgeRenderEntry } from './connection-render-state.js';
8
+ import type { createConnectionSelectionState } from './connection-selection.js';
9
+ type BoardContext = ReturnType<typeof useBoardEngine>;
10
+ interface ConnectionDragOptions {
11
+ injected: BoardContext;
12
+ engine: ComputedRef<ConnectionEngine>;
13
+ selection: ReturnType<typeof createConnectionSelectionState>;
14
+ pendingDrag: Ref<PendingConnectionDrag | null>;
15
+ dragState: Ref<ConnectionDragState | null>;
16
+ hotspotThickness: ComputedRef<number>;
17
+ hotspotCornerClearance: ComputedRef<number>;
18
+ commitDrag(active: ConnectionDragState): void;
19
+ }
20
+ /** Own the complete pointer lifecycle for create and reconnect drags. */
21
+ export declare function useConnectionDrag(options: ConnectionDragOptions): {
22
+ beginReconnectDrag: (entry: EdgeRenderEntry, end: DragEnd, event: PointerEvent) => void;
23
+ beginCreateDrag: (nodeId: NodeId, side: AnchorSide, event: PointerEvent) => void;
24
+ };
25
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { BoardEngine } from '@lupinum/board-core';
2
+ import type { ConnectionsApi, ConnectionsEventMap } from './types.js';
3
+ export type ConnectionEngine = BoardEngine<{
4
+ connections: ConnectionsApi;
5
+ }, ConnectionsEventMap>;
6
+ /** Resolve the installed API at the package boundary with an actionable error. */
7
+ export declare function resolveConnectionEngine(engine: BoardEngine): ConnectionEngine;
@@ -0,0 +1,38 @@
1
+ import { type ComputedRef, type Ref } from 'vue';
2
+ import { type BoardNode } from '@lupinum/board-core';
3
+ import type { useBoardEngine } from '@lupinum/vue-board';
4
+ import { resolveEdgeRenderState } from './geometry.js';
5
+ import type { ConnectionDragState } from './controller.js';
6
+ import type { BoardEdge, ConnectionEndpointMode, ConnectionRouting } from './types.js';
7
+ import type { ConnectionEngine } from './connection-engine.js';
8
+ type BoardContext = ReturnType<typeof useBoardEngine>;
9
+ export type EdgeRenderEntry = ReturnType<typeof resolveEdgeRenderState> & {
10
+ edge: BoardEdge;
11
+ };
12
+ interface ConnectionRenderStateOptions {
13
+ injected: BoardContext;
14
+ engine: ComputedRef<ConnectionEngine>;
15
+ routing: () => ConnectionRouting | undefined;
16
+ endpointMode: ComputedRef<ConnectionEndpointMode>;
17
+ selectedEdgeId: Ref<string | null>;
18
+ dragState: Ref<ConnectionDragState | null>;
19
+ }
20
+ /** Own edge subscription, identity-based geometry caching, culling, and preview. */
21
+ export declare function useConnectionRenderState(options: ConnectionRenderStateOptions): {
22
+ entries: ComputedRef<EdgeRenderEntry[]>;
23
+ entryById: ComputedRef<Map<string, EdgeRenderEntry>>;
24
+ preview: ComputedRef<{
25
+ edge: BoardEdge<import("@lupinum/board-core").JsonObject>;
26
+ source: import("./types.js").ResolvedConnectionEndpoint;
27
+ target: import("./types.js").ResolvedConnectionEndpoint;
28
+ route: import("./types.js").ConnectionRoute;
29
+ candidateNode: BoardNode | undefined;
30
+ } | {
31
+ edge: null;
32
+ source: import("./types.js").ResolvedConnectionEndpoint;
33
+ target: import("./types.js").ResolvedConnectionEndpoint;
34
+ route: import("./types.js").ConnectionRoute;
35
+ candidateNode: BoardNode | undefined;
36
+ } | null>;
37
+ };
38
+ export {};
@@ -0,0 +1,33 @@
1
+ import { type ComputedRef, type Ref } from 'vue';
2
+ import type { NodeId } from '@lupinum/board-core';
3
+ import type { useBoardEngine } from '@lupinum/vue-board';
4
+ import { type ConnectionNodeHandle } from './hit-testing.js';
5
+ import type { ConnectionDragState, PendingConnectionDrag } from './controller.js';
6
+ import type { ConnectionEngine } from './connection-engine.js';
7
+ type BoardContext = ReturnType<typeof useBoardEngine>;
8
+ type ConnectionMenu = {
9
+ kind: 'color' | 'direction';
10
+ edgeId: string;
11
+ };
12
+ export declare function createConnectionSelectionState(): {
13
+ hoveredEdgeId: import("vue").ShallowRef<string | null, string | null>;
14
+ hoveredNodeId: import("vue").ShallowRef<NodeId | null, NodeId | null>;
15
+ hoveredNodeHandle: import("vue").ShallowRef<ConnectionNodeHandle | null, ConnectionNodeHandle | null>;
16
+ selectedEdgeId: import("vue").ShallowRef<string | null, string | null>;
17
+ openMenu: import("vue").ShallowRef<ConnectionMenu | null, ConnectionMenu | null>;
18
+ };
19
+ interface ConnectionSelectionEventsOptions {
20
+ injected: BoardContext;
21
+ engine: ComputedRef<ConnectionEngine>;
22
+ state: ReturnType<typeof createConnectionSelectionState>;
23
+ pendingDrag: Ref<PendingConnectionDrag | null>;
24
+ dragState: Ref<ConnectionDragState | null>;
25
+ editingEdgeId: Ref<string | null>;
26
+ hotspotThickness: ComputedRef<number>;
27
+ hotspotCornerClearance: ComputedRef<number>;
28
+ commitLabelEdit(): void;
29
+ deleteEdge(edgeId: string): void;
30
+ }
31
+ /** Bind hover, selection, menus, and keyboard ownership to the exact board root. */
32
+ export declare function useConnectionSelectionEvents(options: ConnectionSelectionEventsOptions): void;
33
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { type VNode } from 'vue';
2
- import type { Point } from '@lupinum/board-core';
2
+ import type { CanvasColor, Point } from '@lupinum/board-core';
3
3
  import type { BoardEdge } from './types.js';
4
4
  export interface ConnectionToolbarOptions {
5
5
  edge: BoardEdge;
@@ -9,7 +9,7 @@ export interface ConnectionToolbarOptions {
9
9
  onDelete: () => void;
10
10
  onToggleColorMenu: () => void;
11
11
  onToggleDirectionMenu: () => void;
12
- onSetColor: (color: string | undefined) => void;
12
+ onSetColor: (color: CanvasColor | undefined) => void;
13
13
  onSetDirectionality: (direction: 'none' | 'to' | 'both') => void;
14
14
  onResetAnchor: (end: 'from' | 'to' | 'both') => void;
15
15
  onClearLabel: () => void;
package/dist/index.d.ts CHANGED
@@ -14,4 +14,4 @@ export { EDGE_COLOR_PRESETS, colorForPreset, presetForColor, resolvePresetColor,
14
14
  /** Types for custom edge colors and preset names. */
15
15
  export type { EdgeColorOption, EdgeColorPreset } from './colors.js';
16
16
  /** Core edge model types and the connections engine API contract. */
17
- export type { AnchorPosition, AnchorSide, BoardEdge, BoardEdgePatch, ConnectionConfig, ConnectionEndpointMode, ConnectionPluginOptions, ConnectionRoute, ConnectionRouteSegment, ConnectionRouting, ConnectionsApi, ConnectionsEventMap, CreateNodeForConnectionContext, EdgeEnd, ResolvedConnectionEndpoint, } from './types.js';
17
+ export type { AnchorPosition, AnchorSide, BoardEdge, BoardEdgeInput, BoardEdgePatch, ConnectionConfig, ConnectionEndpointMode, ConnectionPluginOptions, ConnectionRoute, ConnectionRouteSegment, ConnectionRouting, ConnectionsApi, ConnectionsEventMap, CreateNodeForConnectionContext, EdgeEnd, ResolvedConnectionEndpoint, } from './types.js';
package/dist/index.js CHANGED
@@ -1,96 +1,113 @@
1
- import { asNodeId as S, asEdgeId as C, BoardNotFoundError as h, BoardConflictError as z, BoardInputError as b } from "@lupinum/board-core";
2
- import { defineInternalBoardPlugin as T } from "@lupinum/board-core/internal";
3
- import { e as $ } from "./colors-CI4AZ9tI.js";
4
- import { E as Z, b as L, a as k, c as H, g as J, p as V, r as q, d as K, f as Q, h as W, i as X, j as Y } from "./colors-CI4AZ9tI.js";
5
- const F = "connections", P = /* @__PURE__ */ new Set(["top", "right", "bottom", "left"]);
6
- function w(r, f) {
7
- if (r) {
8
- if (!P.has(r.side))
9
- throw new b(
10
- `Cannot use ${f}: anchor side "${String(r.side)}" is unsupported.`
1
+ import { asNodeId as y, asEdgeId as S, BoardNotFoundError as x, BoardConflictError as U, BoardInputError as N } from "@lupinum/board-core";
2
+ import { defineInternalBoardPlugin as B, readonlyMapView as O, collectJsonObjectExtras as J, freezeJsonObject as T } from "@lupinum/board-core/internal";
3
+ import { e as L } from "./colors-CI4AZ9tI.js";
4
+ import { E as re, b as te, a as ne, c as de, g as se, p as ce, r as fe, d as ie, f as ae, h as le, i as me, j as Ee } from "./colors-CI4AZ9tI.js";
5
+ const Z = "connections", k = /* @__PURE__ */ new Set(["top", "right", "bottom", "left"]), V = /* @__PURE__ */ new Set([
6
+ "id",
7
+ "fromNode",
8
+ "fromSide",
9
+ "fromEnd",
10
+ "toNode",
11
+ "toSide",
12
+ "toEnd",
13
+ "color",
14
+ "label"
15
+ ]);
16
+ function D(o, c) {
17
+ if (o) {
18
+ if (!k.has(o.side))
19
+ throw new N(
20
+ `Cannot use ${c}: anchor side "${String(o.side)}" is unsupported.`
11
21
  );
12
- if (!Number.isFinite(r.offset) || r.offset < 0 || r.offset > 1)
13
- throw new b(
14
- `Cannot use ${f}: anchor offset must be a finite number from 0 to 1.`
22
+ if (!Number.isFinite(o.offset) || o.offset < 0 || o.offset > 1)
23
+ throw new N(
24
+ `Cannot use ${c}: anchor offset must be a finite number from 0 to 1.`
15
25
  );
16
26
  }
17
27
  }
18
- function v(r) {
19
- if (r !== void 0 && !/^[1-6]$/.test(r) && !/^#[0-9a-fA-F]{6}$/.test(r))
20
- throw new b(
21
- `Cannot use edge color "${r}": expected a preset from 1 to 6 or a six-digit hex color.`
28
+ function _(o) {
29
+ if (o !== void 0 && !/^[1-6]$/.test(o) && !/^#[0-9a-fA-F]{6}$/.test(o))
30
+ throw new N(
31
+ `Cannot use edge color "${o}": expected a preset from 1 to 6 or a six-digit hex color.`
22
32
  );
23
33
  }
24
- const _ = {
34
+ const H = {
25
35
  edges: /* @__PURE__ */ new Map(),
26
36
  nextZIndex: 1
27
37
  };
28
- function N(r, f, A) {
29
- switch (f.type) {
38
+ function F(o, c, h) {
39
+ switch (c.type) {
30
40
  case "EDGE_CREATED": {
31
- const a = A ?? new Map(r.edges);
32
- return a.set(f.edge.id, f.edge), {
41
+ const a = h ?? new Map(o.edges);
42
+ return a.set(c.edge.id, c.edge), {
43
+ ...o,
33
44
  edges: a,
34
- nextZIndex: Math.max(r.nextZIndex, f.edge.zIndex + 1)
45
+ nextZIndex: Math.max(o.nextZIndex, c.edge.zIndex + 1)
35
46
  };
36
47
  }
37
48
  case "EDGE_UPDATED": {
38
- const a = A ?? new Map(r.edges);
39
- return a.set(f.id, f.after), { ...r, edges: a };
49
+ const a = h ?? new Map(o.edges);
50
+ return a.set(c.id, c.after), { ...o, edges: a };
40
51
  }
41
52
  case "EDGE_DELETED": {
42
- if (!r.edges.has(f.id)) return r;
43
- const a = A ?? new Map(r.edges);
44
- return a.delete(f.id), { ...r, edges: a };
53
+ if (!o.edges.has(c.id)) return o;
54
+ const a = h ?? new Map(o.edges);
55
+ return a.delete(c.id), { ...o, edges: a };
45
56
  }
46
57
  }
47
58
  }
48
- function m(r) {
49
- return {
50
- ...r,
51
- data: structuredClone(r.data)
52
- };
59
+ function I(o) {
60
+ return o ? Object.freeze({ ...o }) : void 0;
61
+ }
62
+ function M(o) {
63
+ return Object.freeze(o);
64
+ }
65
+ function P(o, c) {
66
+ return o === c || o?.side === c?.side && o?.offset === c?.offset;
53
67
  }
54
- function M(r) {
68
+ function W(o, c) {
55
69
  return {
56
- id: r.id,
57
- fromNode: r.from,
58
- ...r.fromAnchor?.side ? { fromSide: r.fromAnchor.side } : {},
59
- ...r.fromEnd ? { fromEnd: r.fromEnd } : {},
60
- toNode: r.to,
61
- ...r.toAnchor?.side ? { toSide: r.toAnchor.side } : {},
62
- ...r.toEnd ? { toEnd: r.toEnd } : {},
63
- ...r.color ? { color: r.color } : {},
64
- ...r.label ? { label: r.label } : {}
70
+ ...c ?? {},
71
+ id: o.id,
72
+ fromNode: o.from,
73
+ ...o.fromAnchor?.side ? { fromSide: o.fromAnchor.side } : {},
74
+ ...o.fromEnd ? { fromEnd: o.fromEnd } : {},
75
+ toNode: o.to,
76
+ ...o.toAnchor?.side ? { toSide: o.toAnchor.side } : {},
77
+ ...o.toEnd ? { toEnd: o.toEnd } : {},
78
+ ...o.color ? { color: o.color } : {},
79
+ ...o.label ? { label: o.label } : {}
65
80
  };
66
81
  }
67
- function B(r = {}) {
68
- const f = r.routing ?? "bezier", A = r.endpointMode ?? "auto", a = r.defaultArrow ?? "end", y = {
69
- routing: f,
70
- endpointMode: A,
82
+ function Y(o = {}) {
83
+ const c = o.routing ?? "bezier", h = o.endpointMode ?? "auto", a = o.defaultArrow ?? "end", j = {
84
+ routing: c,
85
+ endpointMode: h,
71
86
  defaultArrow: a
72
- }, D = $(a);
73
- return T({
74
- name: F,
87
+ }, v = L(a), w = /* @__PURE__ */ new WeakMap();
88
+ return B({
89
+ name: Z,
75
90
  slice: {
76
- initial: _
91
+ initial: H
77
92
  },
78
- nodeDeleted(d, c) {
93
+ nodeDeleted(d, f) {
79
94
  d.updatePluginState((s) => {
80
95
  const l = new Map(s.edges);
81
96
  for (const [E, n] of l)
82
- (n.from === c || n.to === c) && l.delete(E);
97
+ (n.from === f || n.to === f) && l.delete(E);
83
98
  return l.size === s.edges.size ? s : { ...s, edges: l };
84
99
  });
85
100
  },
86
101
  persistence: {
87
102
  exportDocument(d) {
88
- const c = d.plugins.connections.getEdges();
89
- return c.length === 0 ? {} : {
90
- edges: c.map(M),
91
- "x-vue-board": {
103
+ const f = d.plugins.connections.getEdges();
104
+ return f.length === 0 ? {} : {
105
+ edges: f.map(
106
+ (s) => W(s, w.get(s))
107
+ ),
108
+ "x-lupinum-board": {
92
109
  edges: Object.fromEntries(
93
- c.map((s) => [
110
+ f.map((s) => [
94
111
  s.id,
95
112
  {
96
113
  zIndex: s.zIndex,
@@ -101,130 +118,143 @@ function B(r = {}) {
101
118
  }
102
119
  };
103
120
  },
104
- loadDocument(d, c, s, l) {
121
+ loadDocument(d, f, s, l) {
105
122
  const E = d.plugins.connections;
106
123
  if (s === "replace")
107
124
  for (const n of E.getEdges())
108
125
  E.deleteEdge(n.id);
109
- for (const n of c.edges ?? []) {
110
- const u = S(n.fromNode), x = S(n.toNode), e = l.get(u) ?? u, o = l.get(x) ?? x;
111
- if (!d.hasNode(e) || !d.hasNode(o))
126
+ for (const n of f.edges ?? []) {
127
+ const b = y(n.fromNode), z = y(n.toNode), u = l.get(b) ?? b, A = l.get(z) ?? z;
128
+ if (!d.hasNode(u) || !d.hasNode(A))
112
129
  continue;
113
- const t = c["x-vue-board"]?.edges?.[n.id], i = s === "merge" && E.getEdge(C(n.id)) ? C(crypto.randomUUID()) : C(n.id);
114
- E.createEdge({
115
- id: i,
116
- from: e,
117
- to: o,
130
+ const C = f["x-lupinum-board"]?.edges?.[n.id], e = s === "merge" && E.getEdge(S(n.id)) ? S(crypto.randomUUID()) : S(n.id), r = E.createEdge({
131
+ id: e,
132
+ from: u,
133
+ to: A,
118
134
  ...n.fromSide ? { fromAnchor: { side: n.fromSide, offset: 0.5 } } : {},
119
135
  ...n.toSide ? { toAnchor: { side: n.toSide, offset: 0.5 } } : {},
120
136
  ...n.fromEnd ? { fromEnd: n.fromEnd } : {},
121
137
  ...n.toEnd ? { toEnd: n.toEnd } : {},
122
138
  ...n.color ? { color: n.color } : {},
123
139
  ...n.label ? { label: n.label } : {},
124
- data: t?.data ?? {},
125
- ...t?.zIndex !== void 0 ? { zIndex: t.zIndex } : {}
126
- });
140
+ data: C?.data ?? {},
141
+ ...C?.zIndex !== void 0 ? { zIndex: C.zIndex } : {}
142
+ }), t = J(
143
+ n,
144
+ V,
145
+ `Invalid board document: edge "${n.id}"`
146
+ );
147
+ Object.keys(t).length > 0 && w.set(r, t);
127
148
  }
128
149
  }
129
150
  },
130
151
  install(d) {
131
- const c = () => d.getPluginState();
152
+ const f = () => d.getPluginState();
132
153
  let s = null;
133
- const l = (e) => d.updatePluginState((o) => d.isBatching() ? (o.edges !== s && (s = new Map(o.edges)), N(o, e, s)) : (s = null, N(o, e)));
134
- function E(e, o) {
135
- const t = c().edges.get(e);
154
+ const l = (e) => d.updatePluginState((r) => d.isBatching() ? (r.edges !== s && (s = new Map(r.edges)), F(r, e, s)) : (s = null, F(r, e)));
155
+ function E(e, r) {
156
+ const t = f().edges.get(e);
136
157
  if (!t)
137
- throw new h(
138
- `Cannot ${o} edge: edge "${e}" does not exist.`
158
+ throw new x(
159
+ `Cannot ${r} edge: edge "${e}" does not exist.`
139
160
  );
140
161
  return t;
141
162
  }
142
- const n = {
163
+ let n = f().edges, b = O(n);
164
+ const u = {
165
+ $edges: d.createCommitSubscribable(() => {
166
+ const e = f().edges;
167
+ return e !== n && (n = e, b = O(e)), b;
168
+ }, "connections.$edges"),
143
169
  createEdge(e) {
144
170
  return d.runCommand(
145
171
  "edge:create",
146
172
  [e],
147
173
  () => {
148
174
  if (!d.hasNode(e.from))
149
- throw new h(
175
+ throw new x(
150
176
  `Cannot create edge: source node "${e.from}" does not exist.`
151
177
  );
152
178
  if (!d.hasNode(e.to))
153
- throw new h(
179
+ throw new x(
154
180
  `Cannot create edge: target node "${e.to}" does not exist.`
155
181
  );
156
- const o = c(), t = e.id ?? C(crypto.randomUUID());
157
- if (o.edges.has(t))
158
- throw new z(
182
+ const r = f(), t = e.id ?? S(crypto.randomUUID());
183
+ if (r.edges.has(t))
184
+ throw new U(
159
185
  `Cannot create edge: edge "${t}" already exists.`
160
186
  );
161
- if (w(e.fromAnchor, "fromAnchor"), w(e.toAnchor, "toAnchor"), v(e.color), e.zIndex !== void 0 && !Number.isFinite(e.zIndex))
162
- throw new b(
187
+ if (D(e.fromAnchor, "fromAnchor"), D(e.toAnchor, "toAnchor"), _(e.color), e.zIndex !== void 0 && !Number.isFinite(e.zIndex))
188
+ throw new N(
163
189
  "Cannot create edge: zIndex must be a finite number."
164
190
  );
165
- const i = {
191
+ const m = M({
166
192
  id: t,
167
193
  from: e.from,
168
194
  to: e.to,
169
- fromAnchor: e.fromAnchor,
170
- toAnchor: e.toAnchor,
171
- fromEnd: e.fromEnd ?? D.fromEnd,
172
- toEnd: e.toEnd ?? D.toEnd,
195
+ fromAnchor: I(e.fromAnchor),
196
+ toAnchor: I(e.toAnchor),
197
+ fromEnd: e.fromEnd ?? v.fromEnd,
198
+ toEnd: e.toEnd ?? v.toEnd,
173
199
  label: e.label,
174
200
  color: e.color,
175
- data: structuredClone(e.data ?? {}),
176
- zIndex: e.zIndex ?? o.nextZIndex
177
- };
178
- return l({ type: "EDGE_CREATED", edge: i }), m(i);
201
+ data: T(e.data ?? {}, "edge data"),
202
+ zIndex: e.zIndex ?? r.nextZIndex
203
+ });
204
+ return l({ type: "EDGE_CREATED", edge: m }), m;
179
205
  },
180
206
  { history: "record" }
181
207
  );
182
208
  },
183
- updateEdge(e, o) {
209
+ updateEdge(e, r) {
184
210
  const t = E(e, "update");
185
211
  return d.runCommand(
186
212
  "edge:update",
187
- [e, o],
213
+ [e, r],
188
214
  () => {
189
- const i = "from" in o ? o.from : t.from, g = "to" in o ? o.to : t.to;
190
- if (!i || !d.hasNode(i))
191
- throw new h(
192
- `Cannot update edge: source node "${i}" does not exist.`
215
+ const m = "from" in r ? r.from : t.from, g = "to" in r ? r.to : t.to;
216
+ if (!m || !d.hasNode(m))
217
+ throw new x(
218
+ `Cannot update edge: source node "${m}" does not exist.`
193
219
  );
194
220
  if (!g || !d.hasNode(g))
195
- throw new h(
221
+ throw new x(
196
222
  `Cannot update edge: target node "${g}" does not exist.`
197
223
  );
198
- w(
199
- "fromAnchor" in o ? o.fromAnchor : t.fromAnchor,
224
+ D(
225
+ "fromAnchor" in r ? r.fromAnchor : t.fromAnchor,
200
226
  "fromAnchor"
201
- ), w(
202
- "toAnchor" in o ? o.toAnchor : t.toAnchor,
227
+ ), D(
228
+ "toAnchor" in r ? r.toAnchor : t.toAnchor,
203
229
  "toAnchor"
204
- ), v("color" in o ? o.color : t.color);
205
- const I = {
230
+ ), _("color" in r ? r.color : t.color);
231
+ const R = "fromAnchor" in r ? P(r.fromAnchor, t.fromAnchor) ? t.fromAnchor : I(r.fromAnchor) : t.fromAnchor, p = "toAnchor" in r ? P(r.toAnchor, t.toAnchor) ? t.toAnchor : I(r.toAnchor) : t.toAnchor, G = "data" in r ? r.data === t.data ? t.data : T(r.data ?? {}, "edge data") : t.data, i = M({
206
232
  ...t,
207
- from: i,
233
+ from: m,
208
234
  to: g,
209
- fromAnchor: "fromAnchor" in o ? o.fromAnchor : t.fromAnchor,
210
- toAnchor: "toAnchor" in o ? o.toAnchor : t.toAnchor,
211
- fromEnd: "fromEnd" in o ? o.fromEnd : t.fromEnd,
212
- toEnd: "toEnd" in o ? o.toEnd : t.toEnd,
213
- label: "label" in o ? o.label : t.label,
214
- color: "color" in o ? o.color : t.color,
215
- data: "data" in o ? structuredClone(o.data ?? {}) : structuredClone(t.data)
216
- };
217
- return l({
235
+ fromAnchor: R,
236
+ toAnchor: p,
237
+ fromEnd: "fromEnd" in r ? r.fromEnd : t.fromEnd,
238
+ toEnd: "toEnd" in r ? r.toEnd : t.toEnd,
239
+ label: "label" in r ? r.label : t.label,
240
+ color: "color" in r ? r.color : t.color,
241
+ data: G
242
+ });
243
+ if (i.from === t.from && i.to === t.to && i.fromAnchor === t.fromAnchor && i.toAnchor === t.toAnchor && i.fromEnd === t.fromEnd && i.toEnd === t.toEnd && i.label === t.label && i.color === t.color && i.data === t.data)
244
+ return t;
245
+ l({
218
246
  type: "EDGE_UPDATED",
219
247
  id: e,
220
- after: I
221
- }), m(I);
248
+ after: i
249
+ });
250
+ const $ = w.get(t);
251
+ return $ && w.set(i, $), i;
222
252
  },
223
253
  { history: "record" }
224
254
  );
225
255
  },
226
256
  deleteEdge(e) {
227
- c().edges.get(e) && d.runCommand(
257
+ f().edges.get(e) && d.runCommand(
228
258
  "edge:delete",
229
259
  [e],
230
260
  () => {
@@ -234,65 +264,57 @@ function B(r = {}) {
234
264
  );
235
265
  },
236
266
  getEdge(e) {
237
- const o = c().edges.get(e);
238
- return o ? m(o) : void 0;
267
+ return f().edges.get(e);
239
268
  },
240
269
  getEdges() {
241
- return Array.from(
242
- c().edges.values(),
243
- (e) => m(e)
244
- );
270
+ return Array.from(f().edges.values());
245
271
  },
246
272
  getEdgesFrom(e) {
247
- return n.getEdges().filter((o) => o.from === e);
273
+ return u.getEdges().filter((r) => r.from === e);
248
274
  },
249
275
  getEdgesTo(e) {
250
- return n.getEdges().filter((o) => o.to === e);
276
+ return u.getEdges().filter((r) => r.to === e);
251
277
  },
252
- getEdgesBetween(e, o) {
253
- return n.getEdges().filter((t) => t.from === e && t.to === o);
278
+ getEdgesBetween(e, r) {
279
+ return u.getEdges().filter((t) => t.from === e && t.to === r);
254
280
  },
255
281
  getConfig() {
256
- return d.assertActive(), { ...y };
282
+ return d.assertActive(), { ...j };
257
283
  }
258
284
  };
259
- d.extend("connections", n);
260
- let u = c().edges;
261
- const x = d.projectCommit(() => {
262
- const e = c().edges;
263
- if (e === u) return () => {
285
+ d.extend("connections", u);
286
+ let A = f().edges;
287
+ return d.projectCommit(() => {
288
+ const e = f().edges;
289
+ if (e === A) return () => {
264
290
  };
265
- const o = u;
291
+ const r = A;
266
292
  return () => {
267
- s = null;
268
- for (const [t, i] of e) {
269
- const g = o.get(t);
270
- g ? g !== i && d.emit("edge:updated", m(i), m(g)) : d.emit("edge:created", m(i));
293
+ s = null, A = e;
294
+ for (const [t, m] of e) {
295
+ const g = r.get(t);
296
+ g ? g !== m && d.emit("edge:updated", m, g) : d.emit("edge:created", m);
271
297
  }
272
- for (const [t] of o)
298
+ for (const [t] of r)
273
299
  e.has(t) || d.emit("edge:deleted", t);
274
- u = e;
275
300
  };
276
301
  });
277
- return () => {
278
- x();
279
- };
280
302
  }
281
303
  });
282
304
  }
283
305
  export {
284
- Z as EDGE_COLOR_PRESETS,
285
- L as buildArcRoute,
286
- k as buildConnectionRoute,
287
- H as colorForPreset,
288
- B as connectionsPlugin,
289
- $ as edgeEndsForDirectionality,
290
- J as getVisibleEdges,
291
- V as presetForColor,
292
- q as resolveAnchorPoint,
293
- K as resolveAutoAnchorSide,
294
- Q as resolveConnectionEndpoint,
295
- W as resolveEdgeRenderState,
296
- X as resolveFloatingEndpoint,
297
- Y as resolvePresetColor
306
+ re as EDGE_COLOR_PRESETS,
307
+ te as buildArcRoute,
308
+ ne as buildConnectionRoute,
309
+ de as colorForPreset,
310
+ Y as connectionsPlugin,
311
+ L as edgeEndsForDirectionality,
312
+ se as getVisibleEdges,
313
+ ce as presetForColor,
314
+ fe as resolveAnchorPoint,
315
+ ie as resolveAutoAnchorSide,
316
+ ae as resolveConnectionEndpoint,
317
+ le as resolveEdgeRenderState,
318
+ me as resolveFloatingEndpoint,
319
+ Ee as resolvePresetColor
298
320
  };