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

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.cjs CHANGED
@@ -5,138 +5,72 @@ var react = require('@liveblocks/react');
5
5
  var _private = require('@liveblocks/react/_private');
6
6
  var react$2 = require('@xyflow/react');
7
7
  var react$1 = require('react');
8
+ var constants = require('./constants.cjs');
9
+ var helpers = require('./helpers.cjs');
8
10
 
9
- const DEFAULT_STORAGE_KEY = "flow";
10
- const NODE_LOCAL_KEYS = [
11
- "selected",
12
- "dragging",
13
- "measured",
14
- "resizing"
15
- ];
16
- const EDGE_LOCAL_KEYS = ["selected"];
17
11
  const EMPTY_ARRAY = [];
18
- function pick(from, keys) {
19
- const result = {};
20
- for (const key of keys) {
21
- const value = from[key];
22
- if (value !== void 0 && value !== null) {
23
- result[key] = value;
24
- }
12
+ function mergeAndBuildDataConfigCache(base, data) {
13
+ if (!data)
14
+ return () => base;
15
+ const dataFallback = data["*"];
16
+ const fallback = dataFallback ? { ...base, data: dataFallback } : base;
17
+ const cache = /* @__PURE__ */ new Map();
18
+ for (const type in data) {
19
+ if (type === "*")
20
+ continue;
21
+ const specific = data[type];
22
+ if (!specific)
23
+ continue;
24
+ const dataConfig = { ...dataFallback, ...specific };
25
+ cache.set(type, { ...base, data: dataConfig });
25
26
  }
26
- return result;
27
+ return (type) => cache.get(type) || fallback;
27
28
  }
28
- function omit(from, keys) {
29
- const result = { ...from };
30
- for (const key of keys) {
31
- delete result[key];
32
- }
33
- return result;
29
+ function buildNodeConfigCache(nodeDataConfig) {
30
+ return mergeAndBuildDataConfigCache(constants.NODE_BASE_CONFIG, nodeDataConfig);
34
31
  }
35
- function reconcile(cache, next) {
36
- const previous = cache.get(next.id);
37
- if (previous && core.shallow(previous, next)) {
38
- return previous;
39
- }
40
- cache.set(next.id, next);
41
- return next;
42
- }
43
- function merge(cache, remote, local) {
44
- for (const id of cache.keys()) {
45
- if (!remote.has(id)) {
46
- cache.delete(id);
47
- }
48
- }
49
- for (const id of local.keys()) {
50
- if (!remote.has(id)) {
51
- local.delete(id);
52
- }
53
- }
54
- return Array.from(remote.values(), (item) => {
55
- const localItem = local.get(item.id);
56
- return reconcile(
57
- cache,
58
- localItem ? Object.assign({}, item, localItem) : item
59
- );
60
- });
61
- }
62
- function updateLocalState(map, key, changes) {
63
- const next = {};
64
- for (const change in changes) {
65
- const value = changes[change];
66
- if (value !== void 0 && value !== false) {
67
- next[change] = value;
68
- }
69
- }
70
- if (Object.keys(next).length > 0) {
71
- map.set(key, next);
72
- return true;
73
- } else {
74
- const hasItem = map.has(key);
75
- map.delete(key);
76
- return hasItem;
77
- }
78
- }
79
- function nodeToStorage(node) {
80
- const { data, ...rest } = omit(node, NODE_LOCAL_KEYS);
81
- return new core.LiveObject({
82
- ...rest,
83
- data: new core.LiveObject(data)
84
- });
85
- }
86
- function edgeToStorage(edge) {
87
- const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS);
88
- return new core.LiveObject({
89
- ...rest,
90
- // `data` is optional on edges.
91
- data: data === void 0 ? void 0 : new core.LiveObject(data)
92
- });
32
+ function buildEdgeConfigCache(edgeDataConfig) {
33
+ return mergeAndBuildDataConfigCache(constants.EDGE_BASE_CONFIG, edgeDataConfig);
93
34
  }
94
- function applyNodeChanges(args) {
95
- const { changes, nodes, nextLocal, nodeCache } = args;
96
- let hasLocalChanged = false;
35
+ function applyNodeChanges(changes, nodes, history, getNodeSyncConfig) {
97
36
  for (const change of changes) {
98
37
  switch (change.type) {
99
38
  case "add":
100
- case "replace":
101
- nodes.set(change.item.id, nodeToStorage(change.item));
102
- if (updateLocalState(
103
- nextLocal,
104
- change.item.id,
105
- pick(change.item, NODE_LOCAL_KEYS)
106
- )) {
107
- hasLocalChanged = true;
39
+ case "replace": {
40
+ const config = getNodeSyncConfig(change.item.type);
41
+ const existing = nodes.get(change.item.id);
42
+ if (existing) {
43
+ existing.reconcile(change.item, config);
44
+ } else {
45
+ nodes.set(
46
+ change.item.id,
47
+ helpers.toLiveblocksInternalNode(change.item, config)
48
+ );
108
49
  }
109
50
  break;
110
- case "remove":
111
- nodes.delete(change.id);
112
- nodeCache.delete(change.id);
113
- nextLocal.delete(change.id);
114
- hasLocalChanged = true;
115
- break;
51
+ }
116
52
  case "position": {
117
53
  const node = nodes.get(change.id);
118
- if (!node || !change.position) {
54
+ if (!node || !change.position)
119
55
  break;
120
- }
121
- const previous = node.get("position");
122
- if (previous?.x !== change.position.x || previous?.y !== change.position.y) {
56
+ if (change.position !== void 0) {
123
57
  node.set("position", change.position);
124
58
  }
125
59
  if (change.dragging !== void 0) {
126
- updateLocalState(nextLocal, change.id, {
127
- ...nextLocal.get(change.id),
128
- dragging: change.dragging
129
- });
130
- hasLocalChanged = true;
60
+ if (change.dragging) {
61
+ history.pause();
62
+ } else {
63
+ history.resume();
64
+ }
65
+ node.setLocal("dragging", change.dragging);
131
66
  }
132
67
  break;
133
68
  }
134
69
  case "dimensions": {
135
70
  const node = nodes.get(change.id);
136
- const patch = {
137
- ...nextLocal.get(change.id)
138
- };
139
- if (node && change.dimensions !== void 0 && change.setAttributes !== void 0) {
71
+ if (!node)
72
+ break;
73
+ if (change.dimensions !== void 0 && change.setAttributes !== void 0) {
140
74
  if (change.setAttributes === true || change.setAttributes === "width") {
141
75
  node.set("width", change.dimensions.width);
142
76
  }
@@ -145,115 +79,92 @@ function applyNodeChanges(args) {
145
79
  }
146
80
  }
147
81
  if (change.dimensions !== void 0) {
148
- patch.measured = change.dimensions;
82
+ node.setLocal("measured", change.dimensions);
149
83
  }
150
84
  if (change.resizing !== void 0) {
151
- patch.resizing = change.resizing;
85
+ if (change.resizing) {
86
+ history.pause();
87
+ } else {
88
+ history.resume();
89
+ }
90
+ node.setLocal("resizing", change.resizing);
152
91
  }
153
- updateLocalState(nextLocal, change.id, patch);
154
- hasLocalChanged = true;
155
92
  break;
156
93
  }
157
- case "select":
158
- updateLocalState(nextLocal, change.id, {
159
- ...nextLocal.get(change.id),
160
- selected: change.selected
161
- });
162
- hasLocalChanged = true;
94
+ case "select": {
95
+ const node = nodes.get(change.id);
96
+ if (!node)
97
+ break;
98
+ node.setLocal("selected", change.selected);
99
+ break;
100
+ }
101
+ case "remove":
163
102
  break;
164
103
  }
165
104
  }
166
- return hasLocalChanged;
167
105
  }
168
- function applyEdgeChanges(args) {
169
- const { changes, edges, nextLocal, edgeCache } = args;
170
- let hasLocalChanged = false;
106
+ function applyEdgeChanges(changes, edges, getEdgeSyncConfig) {
171
107
  for (const change of changes) {
172
108
  switch (change.type) {
173
109
  case "add":
174
- case "replace":
175
- edges.set(change.item.id, edgeToStorage(change.item));
176
- if (updateLocalState(
177
- nextLocal,
178
- change.item.id,
179
- pick(change.item, EDGE_LOCAL_KEYS)
180
- )) {
181
- hasLocalChanged = true;
110
+ case "replace": {
111
+ const config = getEdgeSyncConfig(change.item.type);
112
+ const existing = edges.get(change.item.id);
113
+ if (existing) {
114
+ existing.reconcile(change.item, config);
115
+ } else {
116
+ edges.set(
117
+ change.item.id,
118
+ helpers.toLiveblocksInternalEdge(change.item, config)
119
+ );
182
120
  }
183
121
  break;
184
- case "remove":
185
- edges.delete(change.id);
186
- edgeCache.delete(change.id);
187
- nextLocal.delete(change.id);
188
- hasLocalChanged = true;
122
+ }
123
+ case "select": {
124
+ const edge = edges.get(change.id);
125
+ if (!edge)
126
+ break;
127
+ edge.setLocal("selected", change.selected);
189
128
  break;
190
- case "select":
191
- updateLocalState(nextLocal, change.id, {
192
- ...nextLocal.get(change.id),
193
- selected: change.selected
194
- });
195
- hasLocalChanged = true;
129
+ }
130
+ case "remove":
196
131
  break;
197
132
  }
198
133
  }
199
- return hasLocalChanged;
200
- }
201
- function createLiveblocksFlow(nodes = [], edges = []) {
202
- return new core.LiveObject({
203
- nodes: new core.LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),
204
- edges: new core.LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)]))
205
- });
206
134
  }
207
135
  function useLiveblocksFlow(options = {}) {
136
+ const history = react.useHistory();
208
137
  const isStorageLoaded = react.useStorage(() => true) ?? false;
209
138
  const frozenOptions = _private.useInitial({
210
- initial: options.initial,
211
- storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY
139
+ nodes: options.nodes,
140
+ edges: options.edges,
141
+ storageKey: options.storageKey ?? constants.DEFAULT_STORAGE_KEY,
142
+ suspense: options.suspense ?? false
212
143
  });
213
- const nodeCache = react$1.useRef(/* @__PURE__ */ new Map());
214
- const edgeCache = react$1.useRef(/* @__PURE__ */ new Map());
215
- const [localNodes\u03A3] = react$1.useState(
216
- () => new core.Signal(/* @__PURE__ */ new Map())
217
- );
218
- const [localEdges\u03A3] = react$1.useState(
219
- () => new core.Signal(/* @__PURE__ */ new Map())
144
+ const [getNodeSyncConfig, getEdgeSyncConfig] = react$1.useMemo(
145
+ () => [
146
+ buildNodeConfigCache(frozenOptions.nodes?.sync),
147
+ buildEdgeConfigCache(frozenOptions.edges?.sync)
148
+ ],
149
+ [frozenOptions]
220
150
  );
221
- const localNodes = _private.useSignal(localNodes\u03A3);
222
- const localEdges = _private.useSignal(localEdges\u03A3);
223
- const remoteNodesMap = react.useStorage((storage) => {
151
+ const nodes = react.useStorage((storage) => {
224
152
  const flow = storage[frozenOptions.storageKey];
225
- return flow?.nodes ?? null;
153
+ return flow?.nodes ? [...flow.nodes.values()] : null;
226
154
  });
227
- const remoteEdgesMap = react.useStorage((storage) => {
155
+ const edges = react.useStorage((storage) => {
228
156
  const flow = storage[frozenOptions.storageKey];
229
- return flow?.edges ?? null;
157
+ return flow?.edges ? [...flow.edges.values()] : null;
230
158
  });
231
- const nodes = react$1.useMemo(
232
- () => remoteNodesMap ? merge(nodeCache.current, remoteNodesMap, localNodes) : null,
233
- [remoteNodesMap, localNodes]
234
- );
235
- const edges = react$1.useMemo(
236
- () => remoteEdgesMap ? merge(edgeCache.current, remoteEdgesMap, localEdges) : null,
237
- [remoteEdgesMap, localEdges]
238
- );
239
159
  const onNodesChange = react.useMutation(
240
160
  ({ storage }, changes) => {
241
161
  const flow = storage.get(frozenOptions.storageKey);
242
162
  if (!flow) {
243
163
  return;
244
164
  }
245
- const nextLocal = new Map(localNodes\u03A3.get());
246
- const hasLocalChanged = applyNodeChanges({
247
- changes,
248
- nodes: flow.get("nodes"),
249
- nextLocal,
250
- nodeCache: nodeCache.current
251
- });
252
- if (hasLocalChanged) {
253
- localNodes\u03A3.set(nextLocal);
254
- }
165
+ applyNodeChanges(changes, flow.get("nodes"), history, getNodeSyncConfig);
255
166
  },
256
- []
167
+ [history, frozenOptions, getNodeSyncConfig]
257
168
  );
258
169
  const onEdgesChange = react.useMutation(
259
170
  ({ storage }, changes) => {
@@ -261,72 +172,90 @@ function useLiveblocksFlow(options = {}) {
261
172
  if (!flow) {
262
173
  return;
263
174
  }
264
- const nextLocal = new Map(localEdges\u03A3.get());
265
- const hasLocalChanged = applyEdgeChanges({
266
- changes,
267
- edges: flow.get("edges"),
268
- nextLocal,
269
- edgeCache: edgeCache.current
270
- });
271
- if (hasLocalChanged) {
272
- localEdges\u03A3.set(nextLocal);
175
+ applyEdgeChanges(changes, flow.get("edges"), getEdgeSyncConfig);
176
+ },
177
+ [frozenOptions, getEdgeSyncConfig]
178
+ );
179
+ const onConnect = react.useMutation(
180
+ ({ storage }, connection) => {
181
+ const flow = storage.get(frozenOptions.storageKey);
182
+ if (!flow) {
183
+ return;
273
184
  }
185
+ const [newEdge] = react$2.addEdge(connection, []);
186
+ if (!newEdge) {
187
+ return;
188
+ }
189
+ const edges2 = flow.get("edges");
190
+ const config = getEdgeSyncConfig(newEdge.type);
191
+ edges2.set(newEdge.id, helpers.toLiveblocksInternalEdge(newEdge, config));
274
192
  },
275
- []
193
+ [frozenOptions.storageKey, getEdgeSyncConfig]
276
194
  );
277
- const onConnect = react.useMutation(({ storage }, connection) => {
278
- const flow = storage.get(frozenOptions.storageKey);
279
- if (!flow) {
280
- return;
281
- }
282
- const edges2 = flow.get("edges");
283
- for (const edge of edges2.values()) {
284
- 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)) {
195
+ const onDelete = react.useMutation(
196
+ ({ storage }, params) => {
197
+ const flow = storage.get(frozenOptions.storageKey);
198
+ if (!flow) {
285
199
  return;
286
200
  }
287
- }
288
- const [newEdge] = react$2.addEdge(connection, []);
289
- if (!newEdge) {
290
- return;
291
- }
292
- edges2.set(newEdge.id, edgeToStorage(newEdge));
293
- }, []);
294
- const setInitialStorage = react.useMutation(({ storage }) => {
295
- if (storage.get(frozenOptions.storageKey) !== void 0) {
296
- return;
297
- }
298
- const { nodes: initialNodes = [], edges: initialEdges = [] } = frozenOptions.initial ?? {};
299
- storage.set(
300
- frozenOptions.storageKey,
301
- createLiveblocksFlow(initialNodes, initialEdges)
302
- );
303
- }, []);
201
+ const nodesMap = flow.get("nodes");
202
+ const edgesMap = flow.get("edges");
203
+ for (const edge of params.edges) {
204
+ edgesMap.delete(edge.id);
205
+ }
206
+ for (const node of params.nodes) {
207
+ nodesMap.delete(node.id);
208
+ }
209
+ },
210
+ [frozenOptions.storageKey]
211
+ );
212
+ const setInitialStorage = react.useMutation(
213
+ ({ storage }) => {
214
+ if (storage.get(frozenOptions.storageKey) !== void 0) {
215
+ return;
216
+ }
217
+ const initialNodes = frozenOptions.nodes?.initial ?? [];
218
+ const initialEdges = frozenOptions.edges?.initial ?? [];
219
+ storage.set(
220
+ frozenOptions.storageKey,
221
+ new core.LiveObject({
222
+ nodes: new core.LiveMap(
223
+ initialNodes.map((node) => [
224
+ node.id,
225
+ helpers.toLiveblocksInternalNode(node, getNodeSyncConfig(node.type))
226
+ ])
227
+ ),
228
+ edges: new core.LiveMap(
229
+ initialEdges.map((edge) => [
230
+ edge.id,
231
+ helpers.toLiveblocksInternalEdge(edge, getEdgeSyncConfig(edge.type))
232
+ ])
233
+ )
234
+ })
235
+ );
236
+ },
237
+ [frozenOptions, getNodeSyncConfig, getEdgeSyncConfig]
238
+ );
304
239
  react$1.useEffect(() => {
305
240
  if (isStorageLoaded) {
306
- setInitialStorage();
241
+ history[core.kInternal].withoutHistory(() => {
242
+ setInitialStorage();
243
+ });
307
244
  }
308
- }, [isStorageLoaded, setInitialStorage]);
245
+ }, [isStorageLoaded, setInitialStorage, history]);
246
+ if (frozenOptions.suspense) {
247
+ _private.useSuspendUntilStorageReady();
248
+ }
309
249
  return {
310
- nodes,
311
- edges,
312
- isLoading: !isStorageLoaded,
250
+ nodes: frozenOptions.suspense ? nodes ?? EMPTY_ARRAY : nodes,
251
+ edges: frozenOptions.suspense ? edges ?? EMPTY_ARRAY : edges,
252
+ isLoading: frozenOptions.suspense ? false : !isStorageLoaded,
313
253
  onNodesChange,
314
254
  onEdgesChange,
315
- onConnect
316
- };
317
- }
318
- function useLiveblocksFlowSuspense(options = {}) {
319
- const result = useLiveblocksFlow(options);
320
- _private.useSuspendUntilStorageReady();
321
- return {
322
- ...result,
323
- nodes: result.nodes ?? EMPTY_ARRAY,
324
- edges: result.edges ?? EMPTY_ARRAY,
325
- isLoading: false
255
+ onConnect,
256
+ onDelete
326
257
  };
327
258
  }
328
259
 
329
- exports.createLiveblocksFlow = createLiveblocksFlow;
330
260
  exports.useLiveblocksFlow = useLiveblocksFlow;
331
- exports.useLiveblocksFlowSuspense = useLiveblocksFlowSuspense;
332
261
  //# sourceMappingURL=flow.cjs.map
package/dist/flow.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"flow.cjs","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":["shallow","LiveObject","LiveMap","useStorage","useInitial","useRef","useState","Signal","useSignal","useMemo","useMutation","edges","defaultAddEdge","useEffect","useSuspendUntilStorageReady"],"mappings":"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"}
1
+ {"version":3,"file":"flow.cjs","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 * \"*\": {\n * label: false, // Don't sync node.data.label\n * },\n *\n * // Override for node.type === 'myCustomNode'\n * // This will also not sync `myCustomNode.data.label` (because of the fallback above)\n * myCustomNode: {\n * showPreview: false, // Don't sync myCustomNode.data.showPreview\n * },\n * },\n * },\n * });\n * ```\n */\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 edge types\n * \"*\": {\n * hovered: false, // Don't sync edge.data.hovered\n * },\n *\n * // Override for edge.type === 'myCustomEdge'\n * // This will also not sync `myCustomEdge.data.hovered` (because of the fallback above)\n * myCustomEdge: {\n * isHighlighted: false, // Don't sync myCustomEdge.data.isHighlighted\n * },\n * },\n * },\n * });\n * ```\n */\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 // Must match NODE_BASE_CONFIG's `dragging: false`\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 // Must match NODE_BASE_CONFIG's `measured: false`\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 // Must match NODE_BASE_CONFIG's `resizing: false`\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 // Must match NODE_BASE_CONFIG's `selected: false`\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 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 const edge = edges.get(change.id);\n if (!edge) break;\n // Must match EDGE_BASE_CONFIG's `selected: false`\n edge.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/**\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":["NODE_BASE_CONFIG","EDGE_BASE_CONFIG","toLiveblocksInternalNode","toLiveblocksInternalEdge","useHistory","useStorage","useInitial","DEFAULT_STORAGE_KEY","useMemo","useMutation","defaultAddEdge","edges","LiveObject","LiveMap","useEffect","kInternal","useSuspendUntilStorageReady"],"mappings":"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"}