@liveblocks/react-flow 3.16.0-flow1 → 3.16.0-flow2

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/flow.js CHANGED
@@ -1,140 +1,74 @@
1
- import { shallow, LiveObject, LiveMap, Signal } from '@liveblocks/core';
2
- import { useStorage, useMutation } from '@liveblocks/react';
3
- import { useInitial, useSignal, useSuspendUntilStorageReady } from '@liveblocks/react/_private';
1
+ import { LiveObject, LiveMap, kInternal } from '@liveblocks/core';
2
+ import { useHistory, useStorage, useMutation } from '@liveblocks/react';
3
+ import { useInitial, useSuspendUntilStorageReady } from '@liveblocks/react/_private';
4
4
  import { addEdge } from '@xyflow/react';
5
- import { useRef, useState, useMemo, useEffect } from 'react';
5
+ import { useMemo, useEffect } from 'react';
6
+ import { NODE_BASE_CONFIG, EDGE_BASE_CONFIG, DEFAULT_STORAGE_KEY } from './constants.js';
7
+ import { toLiveblocksInternalNode, toLiveblocksInternalEdge } from './helpers.js';
6
8
 
7
- const DEFAULT_STORAGE_KEY = "flow";
8
- const NODE_LOCAL_KEYS = [
9
- "selected",
10
- "dragging",
11
- "measured",
12
- "resizing"
13
- ];
14
- const EDGE_LOCAL_KEYS = ["selected"];
15
9
  const EMPTY_ARRAY = [];
16
- function pick(from, keys) {
17
- const result = {};
18
- for (const key of keys) {
19
- const value = from[key];
20
- if (value !== void 0 && value !== null) {
21
- result[key] = value;
22
- }
10
+ function mergeAndBuildDataConfigCache(base, data) {
11
+ if (!data)
12
+ return () => base;
13
+ const dataFallback = data["*"];
14
+ const fallback = dataFallback ? { ...base, data: dataFallback } : base;
15
+ const cache = /* @__PURE__ */ new Map();
16
+ for (const type in data) {
17
+ if (type === "*")
18
+ continue;
19
+ const specific = data[type];
20
+ if (!specific)
21
+ continue;
22
+ const dataConfig = { ...dataFallback, ...specific };
23
+ cache.set(type, { ...base, data: dataConfig });
23
24
  }
24
- return result;
25
+ return (type) => cache.get(type) || fallback;
25
26
  }
26
- function omit(from, keys) {
27
- const result = { ...from };
28
- for (const key of keys) {
29
- delete result[key];
30
- }
31
- return result;
27
+ function buildNodeConfigCache(nodeDataConfig) {
28
+ return mergeAndBuildDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);
32
29
  }
33
- function reconcile(cache, next) {
34
- const previous = cache.get(next.id);
35
- if (previous && shallow(previous, next)) {
36
- return previous;
37
- }
38
- cache.set(next.id, next);
39
- return next;
40
- }
41
- function merge(cache, remote, local) {
42
- for (const id of cache.keys()) {
43
- if (!remote.has(id)) {
44
- cache.delete(id);
45
- }
46
- }
47
- for (const id of local.keys()) {
48
- if (!remote.has(id)) {
49
- local.delete(id);
50
- }
51
- }
52
- return Array.from(remote.values(), (item) => {
53
- const localItem = local.get(item.id);
54
- return reconcile(
55
- cache,
56
- localItem ? Object.assign({}, item, localItem) : item
57
- );
58
- });
30
+ function buildEdgeConfigCache(edgeDataConfig) {
31
+ return mergeAndBuildDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);
59
32
  }
60
- function updateLocalState(map, key, changes) {
61
- const next = {};
62
- for (const change in changes) {
63
- const value = changes[change];
64
- if (value !== void 0 && value !== false) {
65
- next[change] = value;
66
- }
67
- }
68
- if (Object.keys(next).length > 0) {
69
- map.set(key, next);
70
- return true;
71
- } else {
72
- const hasItem = map.has(key);
73
- map.delete(key);
74
- return hasItem;
75
- }
76
- }
77
- function nodeToStorage(node) {
78
- const { data, ...rest } = omit(node, NODE_LOCAL_KEYS);
79
- return new LiveObject({
80
- ...rest,
81
- data: new LiveObject(data)
82
- });
83
- }
84
- function edgeToStorage(edge) {
85
- const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS);
86
- return new LiveObject({
87
- ...rest,
88
- // `data` is optional on edges.
89
- data: data === void 0 ? void 0 : new LiveObject(data)
90
- });
91
- }
92
- function applyNodeChanges(args) {
93
- const { changes, nodes, nextLocal, nodeCache } = args;
94
- let hasLocalChanged = false;
33
+ function applyNodeChanges(changes, nodes, history, getNodeSyncConfig) {
95
34
  for (const change of changes) {
96
35
  switch (change.type) {
97
36
  case "add":
98
- case "replace":
99
- nodes.set(change.item.id, nodeToStorage(change.item));
100
- if (updateLocalState(
101
- nextLocal,
102
- change.item.id,
103
- pick(change.item, NODE_LOCAL_KEYS)
104
- )) {
105
- hasLocalChanged = true;
37
+ case "replace": {
38
+ const config = getNodeSyncConfig(change.item.type);
39
+ const existing = nodes.get(change.item.id);
40
+ if (existing) {
41
+ existing.reconcile(change.item, config);
42
+ } else {
43
+ nodes.set(
44
+ change.item.id,
45
+ toLiveblocksInternalNode(change.item, config)
46
+ );
106
47
  }
107
48
  break;
108
- case "remove":
109
- nodes.delete(change.id);
110
- nodeCache.delete(change.id);
111
- nextLocal.delete(change.id);
112
- hasLocalChanged = true;
113
- break;
49
+ }
114
50
  case "position": {
115
51
  const node = nodes.get(change.id);
116
- if (!node || !change.position) {
52
+ if (!node || !change.position)
117
53
  break;
118
- }
119
- const previous = node.get("position");
120
- if (previous?.x !== change.position.x || previous?.y !== change.position.y) {
54
+ if (change.position !== void 0) {
121
55
  node.set("position", change.position);
122
56
  }
123
57
  if (change.dragging !== void 0) {
124
- updateLocalState(nextLocal, change.id, {
125
- ...nextLocal.get(change.id),
126
- dragging: change.dragging
127
- });
128
- hasLocalChanged = true;
58
+ if (change.dragging) {
59
+ history.pause();
60
+ } else {
61
+ history.resume();
62
+ }
63
+ node.setLocal("dragging", change.dragging);
129
64
  }
130
65
  break;
131
66
  }
132
67
  case "dimensions": {
133
68
  const node = nodes.get(change.id);
134
- const patch = {
135
- ...nextLocal.get(change.id)
136
- };
137
- if (node && change.dimensions !== void 0 && change.setAttributes !== void 0) {
69
+ if (!node)
70
+ break;
71
+ if (change.dimensions !== void 0 && change.setAttributes !== void 0) {
138
72
  if (change.setAttributes === true || change.setAttributes === "width") {
139
73
  node.set("width", change.dimensions.width);
140
74
  }
@@ -143,115 +77,100 @@ function applyNodeChanges(args) {
143
77
  }
144
78
  }
145
79
  if (change.dimensions !== void 0) {
146
- patch.measured = change.dimensions;
80
+ node.setLocal("measured", change.dimensions);
147
81
  }
148
82
  if (change.resizing !== void 0) {
149
- patch.resizing = change.resizing;
83
+ if (change.resizing) {
84
+ history.pause();
85
+ } else {
86
+ history.resume();
87
+ }
88
+ node.setLocal("resizing", change.resizing);
150
89
  }
151
- updateLocalState(nextLocal, change.id, patch);
152
- hasLocalChanged = true;
153
90
  break;
154
91
  }
155
- case "select":
156
- updateLocalState(nextLocal, change.id, {
157
- ...nextLocal.get(change.id),
158
- selected: change.selected
159
- });
160
- hasLocalChanged = true;
92
+ case "select": {
93
+ const node = nodes.get(change.id);
94
+ if (!node)
95
+ break;
96
+ node.setLocal("selected", change.selected);
97
+ break;
98
+ }
99
+ case "remove":
161
100
  break;
162
101
  }
163
102
  }
164
- return hasLocalChanged;
165
103
  }
166
- function applyEdgeChanges(args) {
167
- const { changes, edges, nextLocal, edgeCache } = args;
168
- let hasLocalChanged = false;
104
+ function applyEdgeChanges(changes, edges, getEdgeSyncConfig) {
169
105
  for (const change of changes) {
170
106
  switch (change.type) {
171
- case "add":
172
- case "replace":
173
- edges.set(change.item.id, edgeToStorage(change.item));
174
- if (updateLocalState(
175
- nextLocal,
107
+ case "add": {
108
+ const config = getEdgeSyncConfig(change.item.type);
109
+ edges.set(
176
110
  change.item.id,
177
- pick(change.item, EDGE_LOCAL_KEYS)
178
- )) {
179
- hasLocalChanged = true;
180
- }
111
+ toLiveblocksInternalEdge(change.item, config)
112
+ );
181
113
  break;
182
- case "remove":
183
- edges.delete(change.id);
184
- edgeCache.delete(change.id);
185
- nextLocal.delete(change.id);
186
- hasLocalChanged = true;
114
+ }
115
+ case "replace": {
116
+ const config = getEdgeSyncConfig(change.item.type);
117
+ const existing = edges.get(change.item.id);
118
+ if (existing) {
119
+ existing.reconcile(change.item, config);
120
+ } else {
121
+ edges.set(
122
+ change.item.id,
123
+ toLiveblocksInternalEdge(change.item, config)
124
+ );
125
+ }
187
126
  break;
127
+ }
188
128
  case "select":
189
- updateLocalState(nextLocal, change.id, {
190
- ...nextLocal.get(change.id),
191
- selected: change.selected
192
- });
193
- hasLocalChanged = true;
129
+ {
130
+ const edge = edges.get(change.id);
131
+ if (!edge)
132
+ break;
133
+ edge.setLocal("selected", change.selected);
134
+ }
135
+ break;
136
+ case "remove":
194
137
  break;
195
138
  }
196
139
  }
197
- return hasLocalChanged;
198
- }
199
- function createLiveblocksFlow(nodes = [], edges = []) {
200
- return new LiveObject({
201
- nodes: new LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),
202
- edges: new LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)]))
203
- });
204
140
  }
205
141
  function useLiveblocksFlow(options = {}) {
142
+ const history = useHistory();
206
143
  const isStorageLoaded = useStorage(() => true) ?? false;
207
144
  const frozenOptions = useInitial({
208
- initial: options.initial,
209
- storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY
145
+ nodes: options.nodes,
146
+ edges: options.edges,
147
+ storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,
148
+ suspense: options.suspense ?? false
210
149
  });
211
- const nodeCache = useRef(/* @__PURE__ */ new Map());
212
- const edgeCache = useRef(/* @__PURE__ */ new Map());
213
- const [localNodes\u03A3] = useState(
214
- () => new Signal(/* @__PURE__ */ new Map())
150
+ const [getNodeSyncConfig, getEdgeSyncConfig] = useMemo(
151
+ () => [
152
+ buildNodeConfigCache(frozenOptions.nodes?.sync),
153
+ buildEdgeConfigCache(frozenOptions.edges?.sync)
154
+ ],
155
+ [frozenOptions]
215
156
  );
216
- const [localEdges\u03A3] = useState(
217
- () => new Signal(/* @__PURE__ */ new Map())
218
- );
219
- const localNodes = useSignal(localNodes\u03A3);
220
- const localEdges = useSignal(localEdges\u03A3);
221
- const remoteNodesMap = useStorage((storage) => {
157
+ const nodes = useStorage((storage) => {
222
158
  const flow = storage[frozenOptions.storageKey];
223
- return flow?.nodes ?? null;
159
+ return flow?.nodes ? [...flow.nodes.values()] : null;
224
160
  });
225
- const remoteEdgesMap = useStorage((storage) => {
161
+ const edges = useStorage((storage) => {
226
162
  const flow = storage[frozenOptions.storageKey];
227
- return flow?.edges ?? null;
163
+ return flow?.edges ? [...flow.edges.values()] : null;
228
164
  });
229
- const nodes = useMemo(
230
- () => remoteNodesMap ? merge(nodeCache.current, remoteNodesMap, localNodes) : null,
231
- [remoteNodesMap, localNodes]
232
- );
233
- const edges = useMemo(
234
- () => remoteEdgesMap ? merge(edgeCache.current, remoteEdgesMap, localEdges) : null,
235
- [remoteEdgesMap, localEdges]
236
- );
237
165
  const onNodesChange = useMutation(
238
166
  ({ storage }, changes) => {
239
167
  const flow = storage.get(frozenOptions.storageKey);
240
168
  if (!flow) {
241
169
  return;
242
170
  }
243
- const nextLocal = new Map(localNodes\u03A3.get());
244
- const hasLocalChanged = applyNodeChanges({
245
- changes,
246
- nodes: flow.get("nodes"),
247
- nextLocal,
248
- nodeCache: nodeCache.current
249
- });
250
- if (hasLocalChanged) {
251
- localNodes\u03A3.set(nextLocal);
252
- }
171
+ applyNodeChanges(changes, flow.get("nodes"), history, getNodeSyncConfig);
253
172
  },
254
- []
173
+ [history, frozenOptions, getNodeSyncConfig]
255
174
  );
256
175
  const onEdgesChange = useMutation(
257
176
  ({ storage }, changes) => {
@@ -259,70 +178,90 @@ function useLiveblocksFlow(options = {}) {
259
178
  if (!flow) {
260
179
  return;
261
180
  }
262
- const nextLocal = new Map(localEdges\u03A3.get());
263
- const hasLocalChanged = applyEdgeChanges({
264
- changes,
265
- edges: flow.get("edges"),
266
- nextLocal,
267
- edgeCache: edgeCache.current
268
- });
269
- if (hasLocalChanged) {
270
- localEdges\u03A3.set(nextLocal);
181
+ applyEdgeChanges(changes, flow.get("edges"), getEdgeSyncConfig);
182
+ },
183
+ [frozenOptions, getEdgeSyncConfig]
184
+ );
185
+ const onConnect = useMutation(
186
+ ({ storage }, connection) => {
187
+ const flow = storage.get(frozenOptions.storageKey);
188
+ if (!flow) {
189
+ return;
190
+ }
191
+ const [newEdge] = addEdge(connection, []);
192
+ if (!newEdge) {
193
+ return;
271
194
  }
195
+ const edges2 = flow.get("edges");
196
+ const config = getEdgeSyncConfig(newEdge.type);
197
+ edges2.set(newEdge.id, toLiveblocksInternalEdge(newEdge, config));
272
198
  },
273
- []
199
+ [frozenOptions.storageKey, getEdgeSyncConfig]
274
200
  );
275
- const onConnect = useMutation(({ storage }, connection) => {
276
- const flow = storage.get(frozenOptions.storageKey);
277
- if (!flow) {
278
- return;
279
- }
280
- const edges2 = flow.get("edges");
281
- for (const edge of edges2.values()) {
282
- if (edge.get("source") === connection.source && edge.get("target") === connection.target && (edge.get("sourceHandle") ?? null) === (connection.sourceHandle ?? null) && (edge.get("targetHandle") ?? null) === (connection.targetHandle ?? null)) {
201
+ const onDelete = useMutation(
202
+ ({ storage }, params) => {
203
+ const flow = storage.get(frozenOptions.storageKey);
204
+ if (!flow) {
283
205
  return;
284
206
  }
285
- }
286
- const [newEdge] = addEdge(connection, []);
287
- if (!newEdge) {
288
- return;
289
- }
290
- edges2.set(newEdge.id, edgeToStorage(newEdge));
291
- }, []);
292
- const setInitialStorage = useMutation(({ storage }) => {
293
- if (storage.get(frozenOptions.storageKey) !== void 0) {
294
- return;
295
- }
296
- const { nodes: initialNodes = [], edges: initialEdges = [] } = frozenOptions.initial ?? {};
297
- storage.set(
298
- frozenOptions.storageKey,
299
- createLiveblocksFlow(initialNodes, initialEdges)
300
- );
301
- }, []);
207
+ const nodesMap = flow.get("nodes");
208
+ const edgesMap = flow.get("edges");
209
+ for (const edge of params.edges) {
210
+ edgesMap.delete(edge.id);
211
+ }
212
+ for (const node of params.nodes) {
213
+ nodesMap.delete(node.id);
214
+ }
215
+ },
216
+ [frozenOptions.storageKey]
217
+ );
218
+ const setInitialStorage = useMutation(
219
+ ({ storage }) => {
220
+ if (storage.get(frozenOptions.storageKey) !== void 0) {
221
+ return;
222
+ }
223
+ const initialNodes = frozenOptions.nodes?.initial ?? [];
224
+ const initialEdges = frozenOptions.edges?.initial ?? [];
225
+ storage.set(
226
+ frozenOptions.storageKey,
227
+ new LiveObject({
228
+ nodes: new LiveMap(
229
+ initialNodes.map((node) => [
230
+ node.id,
231
+ toLiveblocksInternalNode(node, getNodeSyncConfig(node.type))
232
+ ])
233
+ ),
234
+ edges: new LiveMap(
235
+ initialEdges.map((edge) => [
236
+ edge.id,
237
+ toLiveblocksInternalEdge(edge, getEdgeSyncConfig(edge.type))
238
+ ])
239
+ )
240
+ })
241
+ );
242
+ },
243
+ [frozenOptions, getNodeSyncConfig, getEdgeSyncConfig]
244
+ );
302
245
  useEffect(() => {
303
246
  if (isStorageLoaded) {
304
- setInitialStorage();
247
+ history[kInternal].withoutHistory(() => {
248
+ setInitialStorage();
249
+ });
305
250
  }
306
- }, [isStorageLoaded, setInitialStorage]);
251
+ }, [isStorageLoaded, setInitialStorage, history]);
252
+ if (frozenOptions.suspense) {
253
+ useSuspendUntilStorageReady();
254
+ }
307
255
  return {
308
- nodes,
309
- edges,
310
- isLoading: !isStorageLoaded,
256
+ nodes: frozenOptions.suspense ? nodes ?? EMPTY_ARRAY : nodes,
257
+ edges: frozenOptions.suspense ? edges ?? EMPTY_ARRAY : edges,
258
+ isLoading: frozenOptions.suspense ? false : !isStorageLoaded,
311
259
  onNodesChange,
312
260
  onEdgesChange,
313
- onConnect
314
- };
315
- }
316
- function useLiveblocksFlowSuspense(options = {}) {
317
- const result = useLiveblocksFlow(options);
318
- useSuspendUntilStorageReady();
319
- return {
320
- ...result,
321
- nodes: result.nodes ?? EMPTY_ARRAY,
322
- edges: result.edges ?? EMPTY_ARRAY,
323
- isLoading: false
261
+ onConnect,
262
+ onDelete
324
263
  };
325
264
  }
326
265
 
327
- export { createLiveblocksFlow, useLiveblocksFlow, useLiveblocksFlowSuspense };
266
+ export { useLiveblocksFlow };
328
267
  //# sourceMappingURL=flow.js.map
package/dist/flow.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"flow.js","sources":["../src/flow.ts"],"sourcesContent":["import {\n type DistributiveOmit,\n type JsonObject,\n LiveMap,\n LiveObject,\n type LsonObject,\n type Resolve,\n shallow,\n Signal,\n type ToImmutable,\n} from \"@liveblocks/core\";\nimport { useMutation, useStorage } from \"@liveblocks/react\";\nimport {\n useInitial,\n useSignal,\n useSuspendUntilStorageReady,\n} from \"@liveblocks/react/_private\";\nimport {\n addEdge as defaultAddEdge,\n type Connection,\n type Edge,\n type EdgeChange,\n type Node,\n type NodeChange,\n type OnConnect,\n type OnEdgesChange,\n type OnNodesChange,\n} from \"@xyflow/react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nconst DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow `Node` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst NODE_LOCAL_KEYS = [\n \"selected\",\n \"dragging\",\n \"measured\",\n \"resizing\",\n] as const satisfies (keyof Node)[number][];\n\n// React Flow `Edge` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst EDGE_LOCAL_KEYS = [\"selected\"] as const satisfies (keyof Edge)[number][];\n\nconst EMPTY_ARRAY = [] as unknown[];\n\nexport type SerializableNode = Node<JsonObject>;\nexport type SerializableEdge = Edge<JsonObject>;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Node`.\n *\n * It doesn't include local-only properties.\n * The entire node and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksNode<TNode extends SerializableNode = SerializableNode> =\n LiveObject<\n DistributiveOmit<TNode, (typeof NODE_LOCAL_KEYS)[number] | \"data\"> & {\n data: LiveObject<TNode[\"data\"]>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Edge`.\n *\n * It doesn't include local-only properties.\n * The entire edge and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksEdge<TEdge extends SerializableEdge = SerializableEdge> =\n LiveObject<\n DistributiveOmit<TEdge, (typeof EDGE_LOCAL_KEYS)[number] | \"data\"> & {\n data?: LiveObject<NonNullable<TEdge[\"data\"]>>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow diagram made of nodes and edges.\n *\n * Nodes and edges are stored as `LiveMap`s keyed by their IDs, enabling\n * fine-grained conflict-free updates from multiple clients simultaneously.\n */\nexport type LiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = LiveObject<{\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n}>;\n\ntype LocalNodes = Partial<Record<(typeof NODE_LOCAL_KEYS)[number], unknown>>;\ntype LocalEdges = Partial<Record<(typeof EDGE_LOCAL_KEYS)[number], unknown>>;\n\ntype UseLiveblocksFlowResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Resolve<\n (\n | {\n nodes: null;\n edges: null;\n isLoading: true;\n }\n | {\n nodes: TNode[];\n edges: TEdge[];\n isLoading: false;\n }\n ) & {\n onNodesChange: OnNodesChange<TNode>;\n onEdgesChange: OnEdgesChange<TEdge>;\n onConnect: OnConnect;\n }\n>;\n\ntype LiveblocksFlowSuspenseResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Extract<UseLiveblocksFlowResult<TNode, TEdge>, { isLoading: false }>;\n\ntype UseLiveblocksFlowOptions<\n TNode extends SerializableNode,\n TEdge extends SerializableEdge,\n> = {\n /**\n * The initial React Flow nodes and edges.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * initial: {\n * nodes: [\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ],\n * edges: [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ],\n * },\n * });\n * ```\n *\n * This is equivalent to setting `initialStorage` on `RoomProvider`.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow([\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ], [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ]),\n * }}\n * />\n * ```\n */\n initial?: {\n nodes?: TNode[];\n edges?: TEdge[];\n };\n\n /**\n * The key used to store the React Flow diagram in Liveblocks Storage.\n *\n * Defaults to `\"flow\"`.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * storageKey: \"myDiagram\",\n * });\n * ```\n */\n storageKey?: string;\n};\n\nfunction pick<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Partial<Record<K, unknown>> {\n const result: Partial<Record<K, unknown>> = {};\n\n for (const key of keys) {\n const value = (from as Record<PropertyKey, unknown>)[key];\n\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction omit<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Omit<T, Extract<K, keyof T>> {\n const result = { ...from } as Partial<T>;\n\n for (const key of keys) {\n delete (result as Record<PropertyKey, unknown>)[key];\n }\n\n return result as Omit<T, Extract<K, keyof T>>;\n}\n\nfunction reconcile<T extends { id: string }>(cache: Map<string, T>, next: T) {\n const previous = cache.get(next.id);\n\n if (previous && shallow(previous, next)) {\n return previous;\n }\n\n cache.set(next.id, next);\n\n return next;\n}\n\nfunction merge<T extends { id: string }, L extends object>(\n cache: Map<string, T>,\n remote: ReadonlyMap<string, T>,\n local: Map<string, L>\n): T[] {\n // Prune cached items that were deleted remotely.\n for (const id of cache.keys()) {\n if (!remote.has(id)) {\n cache.delete(id);\n }\n }\n\n // Prune local items that were deleted remotely.\n for (const id of local.keys()) {\n if (!remote.has(id)) {\n local.delete(id);\n }\n }\n\n // Reconcile remote and local items.\n return Array.from(remote.values(), (item) => {\n const localItem = local.get(item.id);\n\n return reconcile(\n cache,\n localItem ? (Object.assign({}, item, localItem) as T) : item\n );\n });\n}\n\nfunction updateLocalState<T extends object>(\n map: Map<string, T>,\n key: string,\n changes: T\n): boolean {\n const next: Record<string, unknown> = {};\n\n for (const change in changes) {\n const value = (changes as Record<string, unknown>)[change];\n\n // `false` values aren't stored.\n if (value !== undefined && value !== false) {\n next[change] = value;\n }\n }\n\n if (Object.keys(next).length > 0) {\n map.set(key, next as T);\n\n return true;\n } else {\n const hasItem = map.has(key);\n map.delete(key);\n\n return hasItem;\n }\n}\n\n// Converts a React Flow `Node` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction nodeToStorage<TNode extends SerializableNode>(\n node: TNode\n): LiveblocksNode<TNode> {\n const { data, ...rest } = omit(node, NODE_LOCAL_KEYS) as TNode;\n\n return new LiveObject({\n ...(rest as LsonObject),\n data: new LiveObject(data as LsonObject),\n }) as LiveblocksNode<TNode>;\n}\n\n// Converts a React Flow `Edge` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction edgeToStorage<TEdge extends SerializableEdge>(\n edge: TEdge\n): LiveblocksEdge<TEdge> {\n const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS) as TEdge;\n\n return new LiveObject({\n ...(rest as LsonObject),\n\n // `data` is optional on edges.\n data: data === undefined ? undefined : new LiveObject(data as LsonObject),\n }) as LiveblocksEdge<TEdge>;\n}\n\n// Similar to React Flow's `applyNodeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-node-changes\nfunction applyNodeChanges<TNode extends SerializableNode>(args: {\n changes: NodeChange<TNode>[];\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n nextLocal: Map<string, Partial<LocalNodes>>;\n nodeCache: Map<string, TNode>;\n}): boolean {\n const { changes, nodes, nextLocal, nodeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n nodes.set(change.item.id, nodeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, NODE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n nodes.delete(change.id);\n nodeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"position\": {\n const node = nodes.get(change.id);\n\n if (!node || !change.position) {\n break;\n }\n\n const previous = node.get(\"position\") as TNode[\"position\"] | undefined;\n\n if (\n previous?.x !== change.position.x ||\n previous?.y !== change.position.y\n ) {\n node.set(\"position\", change.position);\n }\n\n if (change.dragging !== undefined) {\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n dragging: change.dragging,\n });\n hasLocalChanged = true;\n }\n\n break;\n }\n\n case \"dimensions\": {\n const node = nodes.get(change.id);\n const patch: Partial<LocalNodes> = {\n ...nextLocal.get(change.id),\n };\n\n if (\n node &&\n change.dimensions !== undefined &&\n change.setAttributes !== undefined\n ) {\n if (\n change.setAttributes === true ||\n change.setAttributes === \"width\"\n ) {\n node.set(\"width\", change.dimensions.width);\n }\n\n if (\n change.setAttributes === true ||\n change.setAttributes === \"height\"\n ) {\n node.set(\"height\", change.dimensions.height);\n }\n }\n\n if (change.dimensions !== undefined) {\n patch.measured = change.dimensions;\n }\n\n if (change.resizing !== undefined) {\n patch.resizing = change.resizing;\n }\n\n updateLocalState(nextLocal, change.id, patch);\n hasLocalChanged = true;\n break;\n }\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n// Similar to React Flow's `applyEdgeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-edge-changes\nfunction applyEdgeChanges<TEdge extends SerializableEdge>(args: {\n changes: EdgeChange<TEdge>[];\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n nextLocal: Map<string, Partial<LocalEdges>>;\n edgeCache: Map<string, TEdge>;\n}): boolean {\n const { changes, edges, nextLocal, edgeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n edges.set(change.item.id, edgeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, EDGE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n edges.delete(change.id);\n edgeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n/**\n * Creates a Liveblocks Storage representation of a React Flow diagram from nodes and edges.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow(initialNodes, initialEdges),\n * }}\n * />\n * ```\n */\nexport function createLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(nodes: TNode[] = [], edges: TEdge[] = []): LiveblocksFlow<TNode, TEdge> {\n return new LiveObject({\n nodes: new LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),\n edges: new LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)])),\n }) as LiveblocksFlow<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect, isLoading } = useLiveblocksFlow();\n *\n * if (isLoading) {\n * return <div>Loading…</div>\n * }\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<UseLiveblocksFlowResult<TNode, TEdge>> {\n type TFlow = LiveblocksFlow<TNode, TEdge>;\n type TImmutableFlow = ToImmutable<LiveblocksFlow<TNode, TEdge>>;\n\n const isStorageLoaded = useStorage(() => true) ?? false;\n\n // These options are not reactive, only their initial values are used.\n const frozenOptions = useInitial({\n initial: options.initial,\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n });\n\n // Used to reconcile state changes with stable object references when the changes\n // are shallowly equal, preventing React Flow from re-rendering unchanged nodes and edges.\n const nodeCache = useRef<Map<string, TNode>>(new Map());\n const edgeCache = useRef<Map<string, TEdge>>(new Map());\n\n // Local-only state lives in signals.\n const [localNodesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalNodes>>())\n );\n const [localEdgesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalEdges>>())\n );\n const localNodes = useSignal(localNodesΣ);\n const localEdges = useSignal(localEdgesΣ);\n\n // Remote state lives in Liveblocks Storage.\n const remoteNodesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.nodes ?? null) as ReadonlyMap<string, TNode> | null;\n });\n const remoteEdgesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.edges ?? null) as ReadonlyMap<string, TEdge> | null;\n });\n\n // Merge remote and local layers to get the final state.\n const nodes = useMemo(\n () =>\n remoteNodesMap\n ? merge(nodeCache.current, remoteNodesMap, localNodes)\n : null,\n [remoteNodesMap, localNodes]\n );\n const edges = useMemo(\n () =>\n remoteEdgesMap\n ? merge(edgeCache.current, remoteEdgesMap, localEdges)\n : null,\n [remoteEdgesMap, localEdges]\n );\n\n const onNodesChange = useMutation(\n ({ storage }, changes: NodeChange<TNode>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localNodesΣ.get());\n const hasLocalChanged = applyNodeChanges({\n changes,\n nodes: flow.get(\"nodes\"),\n nextLocal,\n nodeCache: nodeCache.current,\n });\n\n if (hasLocalChanged) {\n localNodesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onEdgesChange = useMutation(\n ({ storage }, changes: EdgeChange<TEdge>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localEdgesΣ.get());\n const hasLocalChanged = applyEdgeChanges({\n changes,\n edges: flow.get(\"edges\"),\n nextLocal,\n edgeCache: edgeCache.current,\n });\n\n if (hasLocalChanged) {\n localEdgesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onConnect = useMutation(({ storage }, connection: Connection) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const edges = flow.get(\"edges\");\n\n // Check for duplicate connections.\n for (const edge of edges.values()) {\n if (\n edge.get(\"source\") === connection.source &&\n edge.get(\"target\") === connection.target &&\n (edge.get(\"sourceHandle\") ?? null) ===\n (connection.sourceHandle ?? null) &&\n (edge.get(\"targetHandle\") ?? null) === (connection.targetHandle ?? null)\n ) {\n return;\n }\n }\n\n // Delegate to React Flow's own `addEdge` helper for consistent default\n // edge ID generation, passing an empty array since de-duplication is\n // already handled above.\n const [newEdge] = defaultAddEdge(connection, [] as TEdge[]);\n\n if (!newEdge) {\n return;\n }\n\n edges.set(newEdge.id, edgeToStorage(newEdge));\n }, []);\n\n const setInitialStorage = useMutation(({ storage }) => {\n // Similarly to `initialStorage` on `Client.enterRoom` and `RoomProvider`, we only\n // initialize Storage if it doesn't already exist.\n if (storage.get(frozenOptions.storageKey) !== undefined) {\n return;\n }\n\n const { nodes: initialNodes = [], edges: initialEdges = [] } =\n frozenOptions.initial ?? {};\n\n storage.set(\n frozenOptions.storageKey,\n createLiveblocksFlow(initialNodes, initialEdges)\n );\n }, []);\n\n useEffect(() => {\n if (isStorageLoaded) {\n setInitialStorage();\n }\n }, [isStorageLoaded, setInitialStorage]);\n\n return {\n nodes,\n edges,\n isLoading: !isStorageLoaded,\n onNodesChange,\n onEdgesChange,\n onConnect,\n } as UseLiveblocksFlowResult<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useLiveblocksFlow();\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlowSuspense<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<LiveblocksFlowSuspenseResult<TNode, TEdge>> {\n const result = useLiveblocksFlow<TNode, TEdge>(options);\n\n useSuspendUntilStorageReady();\n\n return {\n ...result,\n nodes: result.nodes ?? (EMPTY_ARRAY as TNode[]),\n edges: result.edges ?? (EMPTY_ARRAY as TEdge[]),\n isLoading: false,\n };\n}\n"],"names":["edges","defaultAddEdge"],"mappings":"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"}
1
+ {"version":3,"file":"flow.js","sources":["../src/flow.ts"],"sourcesContent":["import type {\n History,\n JsonObject,\n Resolve,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport { kInternal, LiveMap, LiveObject } from \"@liveblocks/core\";\nimport { useHistory, useMutation, useStorage } from \"@liveblocks/react\";\nimport {\n useInitial,\n useSuspendUntilStorageReady,\n} from \"@liveblocks/react/_private\";\nimport type {\n BuiltInEdge,\n BuiltInNode,\n Connection,\n Edge,\n EdgeChange,\n Node,\n NodeChange,\n OnConnect,\n OnDelete,\n OnEdgesChange,\n OnNodesChange,\n} from \"@xyflow/react\";\nimport { addEdge as defaultAddEdge } from \"@xyflow/react\";\nimport { useEffect, useMemo } from \"react\";\n\nimport {\n DEFAULT_STORAGE_KEY,\n EDGE_BASE_CONFIG,\n NODE_BASE_CONFIG,\n} from \"./constants\";\nimport { toLiveblocksInternalEdge, toLiveblocksInternalNode } from \"./helpers\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksEdge,\n InternalLiveblocksFlow,\n InternalLiveblocksNode,\n NodeSyncConfig,\n SyncConfig,\n} from \"./types\";\n\nconst EMPTY_ARRAY = [] as unknown[];\n\ntype UseLiveblocksFlowResult<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> = Resolve<\n (\n | {\n nodes: null;\n edges: null;\n isLoading: true;\n }\n | {\n nodes: N[];\n edges: E[];\n isLoading: false;\n }\n ) & {\n onNodesChange: OnNodesChange<N>;\n onEdgesChange: OnEdgesChange<E>;\n onConnect: OnConnect;\n onDelete: OnDelete<N, E>;\n }\n>;\n\ntype LiveblocksFlowSuspenseResult<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> = Extract<UseLiveblocksFlowResult<N, E>, { isLoading: false }>;\n\nfunction mergeAndBuildDataConfigCache(\n base: SyncConfig,\n data?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n if (!data) return () => base;\n\n const dataFallback = data[\"*\"];\n const fallback = dataFallback ? { ...base, data: dataFallback } : base;\n\n // Pre-compute full node/edge sync configs for all explicitly declared types\n const cache = new Map<string | undefined, SyncConfig>();\n for (const type in data) {\n if (type === \"*\") continue;\n const specific = data[type];\n if (!specific) continue;\n const dataConfig: SyncConfig = { ...dataFallback, ...specific };\n cache.set(type, { ...base, data: dataConfig });\n }\n\n return (type) => cache.get(type) || fallback;\n}\n\nfunction buildNodeConfigCache<N extends Node>(\n /** The user-provided node data sync configuration, if any. */\n nodeDataConfig?: NodeSyncConfig<N>\n): (type: string | undefined) => SyncConfig {\n return mergeAndBuildDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);\n}\n\nfunction buildEdgeConfigCache<E extends Edge>(\n /** The user-provided edge data sync configuration, if any. */\n edgeDataConfig?: EdgeSyncConfig<E>\n): (type: string | undefined) => SyncConfig {\n return mergeAndBuildDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);\n}\n\ntype UseLiveblocksFlowOptions<N extends Node, E extends Edge> = {\n nodes?: {\n /**\n * The initial React Flow nodes.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * nodes: {\n * initial: [\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ],\n * },\n * });\n * ```\n */\n initial?: N[];\n /**\n * Per-type sync configuration for node data keys.\n *\n * Use `\"*\"` as a fallback for all node types. Type-specific entries are\n * deep-merged on top of `\"*\"`, with explicitly named keys taking\n * precedence.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * nodes: {\n * sync: {\n * // Fallback for all node types\n * \"*\": { label: false },\n *\n * // Override for \"custom\" nodes\n * \"custom\": { color: false },\n * },\n * },\n * });\n * ```\n */\n // XXX Improve the example + match public documentation\n sync?: NodeSyncConfig<N>;\n };\n\n edges?: {\n initial?: E[];\n /**\n * Per-type sync configuration for edge data keys.\n *\n * Use `\"*\"` as a fallback for all edge types. Type-specific entries are\n * deep-merged on top of `\"*\"`, with explicitly named keys taking\n * precedence.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * edges: {\n * sync: {\n * // Fallback for all node types\n * \"*\": { floating: false },\n * },\n * },\n * });\n * ```\n */\n // XXX Improve the example + match public documentation\n sync?: EdgeSyncConfig<E>;\n };\n\n /**\n * The key used to store the React Flow diagram in Liveblocks Storage.\n * Defaults to `\"flow\"`.\n */\n storageKey?: string;\n\n /**\n * When true, suspends until Storage is ready (use a React `Suspense`\n * boundary). Then `nodes` and `edges` are always arrays and `isLoading` is\n * always false.\n */\n suspense?: boolean;\n};\n\n// Similar to React Flow's `applyNodeChanges()`, but writes local-only\n// properties via `setLocal()` / `delete()` on the LiveObject directly.\n// https://reactflow.dev/api-reference/utils/apply-node-changes\nfunction applyNodeChanges<N extends Node>(\n changes: NodeChange<N>[],\n nodes: LiveMap<string, InternalLiveblocksNode>,\n history: History,\n getNodeSyncConfig: (nodeType: string | undefined) => SyncConfig\n): void {\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\": {\n const config = getNodeSyncConfig(change.item.type);\n const existing = nodes.get(change.item.id);\n if (existing) {\n existing.reconcile(change.item as unknown as JsonObject, config);\n } else {\n nodes.set(\n change.item.id,\n toLiveblocksInternalNode(change.item, config)\n );\n }\n break;\n }\n\n case \"position\": {\n const node = nodes.get(change.id);\n if (!node || !change.position) break;\n\n if (change.position !== undefined) {\n node.set(\"position\", change.position);\n }\n\n if (change.dragging !== undefined) {\n if (change.dragging) {\n history.pause();\n } else {\n history.resume();\n }\n node.setLocal(\"dragging\", change.dragging);\n }\n break;\n }\n\n case \"dimensions\": {\n const node = nodes.get(change.id);\n if (!node) break;\n\n if (\n change.dimensions !== undefined &&\n change.setAttributes !== undefined\n ) {\n if (\n change.setAttributes === true ||\n change.setAttributes === \"width\"\n ) {\n node.set(\"width\", change.dimensions.width);\n }\n\n if (\n change.setAttributes === true ||\n change.setAttributes === \"height\"\n ) {\n node.set(\"height\", change.dimensions.height);\n }\n }\n\n if (change.dimensions !== undefined) {\n node.setLocal(\"measured\", change.dimensions);\n }\n\n if (change.resizing !== undefined) {\n if (change.resizing) {\n history.pause();\n } else {\n history.resume();\n }\n node.setLocal(\"resizing\", change.resizing);\n }\n\n break;\n }\n\n case \"select\": {\n const node = nodes.get(change.id);\n if (!node) break;\n\n node.setLocal(\"selected\", change.selected);\n break;\n }\n\n case \"remove\":\n // Removals are handled by onDelete for atomic undo\n break;\n }\n }\n}\n\n// Similar to React Flow's `applyEdgeChanges()`, but writes local-only\n// properties via `setLocal()` / `delete()` on the LiveObject directly.\n// https://reactflow.dev/api-reference/utils/apply-edge-changes\nfunction applyEdgeChanges<E extends Edge>(\n changes: EdgeChange<E>[],\n edges: LiveMap<string, InternalLiveblocksEdge>,\n getEdgeSyncConfig: (type: string | undefined) => SyncConfig\n): void {\n for (const change of changes) {\n switch (change.type) {\n case \"add\": {\n const config = getEdgeSyncConfig(change.item.type);\n edges.set(\n change.item.id,\n toLiveblocksInternalEdge(change.item, config)\n );\n break;\n }\n\n case \"replace\": {\n const config = getEdgeSyncConfig(change.item.type);\n const existing = edges.get(change.item.id);\n if (existing) {\n existing.reconcile(change.item as unknown as JsonObject, config);\n } else {\n edges.set(\n change.item.id,\n toLiveblocksInternalEdge(change.item, config)\n );\n }\n break;\n }\n\n case \"select\":\n {\n const edge = edges.get(change.id);\n if (!edge) break;\n edge.setLocal(\"selected\", change.selected);\n }\n break;\n\n case \"remove\":\n // Removals are handled by onDelete for atomic undo\n break;\n }\n }\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect, onDelete, isLoading } = useLiveblocksFlow();\n *\n * if (isLoading) {\n * return <div>Loading…</div>\n * }\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} onDelete={onDelete} />;\n * ```\n * Pass `{ suspense: true }` to suspend until Storage is ready, `nodes` and `edges` will never be `null`.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect, onDelete } =\n * useLiveblocksFlow({ suspense: true });\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} onDelete={onDelete} />;\n * ```\n */\nexport function useLiveblocksFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options?: UseLiveblocksFlowOptions<N, E> & { suspense?: false }\n): Resolve<UseLiveblocksFlowResult<N, E>>;\nexport function useLiveblocksFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: UseLiveblocksFlowOptions<N, E> & { suspense: true }\n): Resolve<LiveblocksFlowSuspenseResult<N, E>>;\nexport function useLiveblocksFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: UseLiveblocksFlowOptions<N, E> = {}\n): Resolve<UseLiveblocksFlowResult<N, E> | LiveblocksFlowSuspenseResult<N, E>> {\n const history = useHistory();\n const isStorageLoaded = useStorage(() => true) ?? false;\n\n // These options are not reactive, only their initial values are used.\n const frozenOptions = useInitial({\n nodes: options.nodes,\n edges: options.edges,\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n suspense: options.suspense ?? false,\n });\n\n // Pre-compute sync config caches once (not on every render)\n const [getNodeSyncConfig, getEdgeSyncConfig] = useMemo(\n () =>\n [\n buildNodeConfigCache(frozenOptions.nodes?.sync),\n buildEdgeConfigCache(frozenOptions.edges?.sync),\n ] as const,\n [frozenOptions]\n );\n\n // Storage already includes local overlays via toImmutable(), so no\n // separate local layer is needed. Individual node/edge immutable references\n // are already stable (only change when the underlying LiveObject changes).\n const nodes = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | ToImmutable<InternalLiveblocksFlow>\n | undefined;\n return flow?.nodes ? ([...flow.nodes.values()] as unknown as N[]) : null;\n });\n const edges = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | ToImmutable<InternalLiveblocksFlow>\n | undefined;\n return flow?.edges ? ([...flow.edges.values()] as unknown as E[]) : null;\n });\n\n const onNodesChange = useMutation(\n ({ storage }, changes: NodeChange<N>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as\n | InternalLiveblocksFlow\n | undefined;\n if (!flow) {\n return;\n }\n\n applyNodeChanges(changes, flow.get(\"nodes\"), history, getNodeSyncConfig);\n },\n [history, frozenOptions, getNodeSyncConfig]\n );\n\n const onEdgesChange = useMutation(\n ({ storage }, changes: EdgeChange<E>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as\n | InternalLiveblocksFlow\n | undefined;\n if (!flow) {\n return;\n }\n\n applyEdgeChanges(changes, flow.get(\"edges\"), getEdgeSyncConfig);\n },\n [frozenOptions, getEdgeSyncConfig]\n );\n\n const onConnect = useMutation(\n ({ storage }, connection: Connection) => {\n const flow = storage.get(frozenOptions.storageKey) as\n | InternalLiveblocksFlow\n | undefined;\n if (!flow) {\n return;\n }\n\n // Delegate to React Flow's own `addEdge` helper for consistent default\n // edge ID generation, passing an empty array since de-duplication is\n // already handled above.\n const [newEdge] = defaultAddEdge(connection, [] as E[]);\n if (!newEdge) {\n return;\n }\n\n const edges = flow.get(\"edges\");\n const config = getEdgeSyncConfig(newEdge.type);\n edges.set(newEdge.id, toLiveblocksInternalEdge(newEdge, config));\n },\n [frozenOptions.storageKey, getEdgeSyncConfig]\n );\n\n const onDelete = useMutation(\n ({ storage }, params: { nodes: N[]; edges: E[] }) => {\n const flow = storage.get(frozenOptions.storageKey) as\n | InternalLiveblocksFlow\n | undefined;\n if (!flow) {\n return;\n }\n\n const nodesMap = flow.get(\"nodes\");\n const edgesMap = flow.get(\"edges\");\n\n for (const edge of params.edges) {\n edgesMap.delete(edge.id);\n }\n\n for (const node of params.nodes) {\n nodesMap.delete(node.id);\n }\n },\n [frozenOptions.storageKey]\n );\n\n const setInitialStorage = useMutation(\n ({ storage }) => {\n // Similarly to `initialStorage` on `Client.enterRoom` and `RoomProvider`, we only\n // initialize Storage if it doesn't already exist.\n if (storage.get(frozenOptions.storageKey) !== undefined) {\n return;\n }\n\n const initialNodes = frozenOptions.nodes?.initial ?? [];\n const initialEdges = frozenOptions.edges?.initial ?? [];\n\n storage.set(\n frozenOptions.storageKey,\n new LiveObject({\n nodes: new LiveMap(\n initialNodes.map((node) => [\n node.id,\n toLiveblocksInternalNode(node, getNodeSyncConfig(node.type)),\n ])\n ),\n edges: new LiveMap(\n initialEdges.map((edge) => [\n edge.id,\n toLiveblocksInternalEdge(edge, getEdgeSyncConfig(edge.type)),\n ])\n ),\n })\n );\n },\n [frozenOptions, getNodeSyncConfig, getEdgeSyncConfig]\n );\n\n useEffect(() => {\n if (isStorageLoaded) {\n history[kInternal].withoutHistory(() => {\n setInitialStorage();\n });\n }\n }, [isStorageLoaded, setInitialStorage, history]);\n\n if (frozenOptions.suspense) {\n // eslint-disable-next-line react-hooks/rules-of-hooks -- `suspense` is frozen so this branch is stable\n useSuspendUntilStorageReady();\n }\n\n return {\n nodes: frozenOptions.suspense ? (nodes ?? (EMPTY_ARRAY as N[])) : nodes,\n edges: frozenOptions.suspense ? (edges ?? (EMPTY_ARRAY as E[])) : edges,\n isLoading: frozenOptions.suspense ? false : !isStorageLoaded,\n onNodesChange,\n onEdgesChange,\n onConnect,\n onDelete,\n } as UseLiveblocksFlowResult<N, E> | LiveblocksFlowSuspenseResult<N, E>;\n}\n"],"names":["defaultAddEdge","edges"],"mappings":"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"}