@liveblocks/react-flow 3.18.0-rc1 → 3.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@liveblocks/core');
4
- var version = require('./version.cjs');
4
+ var version = require('./lib/version.cjs');
5
5
  var cursors = require('./cursors.cjs');
6
- var flow = require('./flow.cjs');
6
+ var flow = require('./lib/flow.cjs');
7
7
 
8
8
  core.detectDupes(version.PKG_NAME, version.PKG_VERSION, version.PKG_FORMAT);
9
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport type { CursorsCursorProps, CursorsProps } from \"./cursors\";\nexport { Cursors } from \"./cursors\";\nexport { useLiveblocksFlow } from \"./flow\";\nexport type {\n EdgeSyncConfig,\n LiveblocksEdge,\n LiveblocksFlow,\n LiveblocksNode,\n NodeSyncConfig,\n SyncConfig,\n SyncMode,\n} from \"./types\";\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;AAIAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./lib/version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport type { CursorsCursorProps, CursorsProps } from \"./cursors\";\nexport { Cursors } from \"./cursors\";\nexport { useLiveblocksFlow } from \"./lib/flow\";\nexport type {\n EdgeSyncConfig,\n LiveblocksEdge,\n LiveblocksFlow,\n LiveblocksNode,\n NodeSyncConfig,\n SyncConfig,\n SyncMode,\n} from \"./lib/types\";\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;AAIAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;"}
package/dist/index.d.cts CHANGED
@@ -41,6 +41,13 @@ interface CursorsProps extends ComponentPropsWithoutRef<"div"> {
41
41
  */
42
42
  declare const Cursors: react.ForwardRefExoticComponent<CursorsProps & react.RefAttributes<HTMLDivElement>>;
43
43
 
44
+ /**
45
+ * Module with utilities shared between the React Flow frontend and the React
46
+ * Flow Node backend. There are no runtime dependencies on @xyflow/react,
47
+ * react, or any other frontend-specific libraries from this module, and this
48
+ * should stay that way.
49
+ */
50
+
44
51
  declare const NODE_BASE_CONFIG: {
45
52
  readonly selected: false;
46
53
  readonly dragging: false;
package/dist/index.d.ts CHANGED
@@ -41,6 +41,13 @@ interface CursorsProps extends ComponentPropsWithoutRef<"div"> {
41
41
  */
42
42
  declare const Cursors: react.ForwardRefExoticComponent<CursorsProps & react.RefAttributes<HTMLDivElement>>;
43
43
 
44
+ /**
45
+ * Module with utilities shared between the React Flow frontend and the React
46
+ * Flow Node backend. There are no runtime dependencies on @xyflow/react,
47
+ * react, or any other frontend-specific libraries from this module, and this
48
+ * should stay that way.
49
+ */
50
+
44
51
  declare const NODE_BASE_CONFIG: {
45
52
  readonly selected: false;
46
53
  readonly dragging: false;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { detectDupes } from '@liveblocks/core';
2
- import { PKG_NAME, PKG_VERSION, PKG_FORMAT } from './version.js';
2
+ import { PKG_NAME, PKG_VERSION, PKG_FORMAT } from './lib/version.js';
3
3
  export { Cursors } from './cursors.js';
4
- export { useLiveblocksFlow } from './flow.js';
4
+ export { useLiveblocksFlow } from './lib/flow.js';
5
5
 
6
6
  detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport type { CursorsCursorProps, CursorsProps } from \"./cursors\";\nexport { Cursors } from \"./cursors\";\nexport { useLiveblocksFlow } from \"./flow\";\nexport type {\n EdgeSyncConfig,\n LiveblocksEdge,\n LiveblocksFlow,\n LiveblocksNode,\n NodeSyncConfig,\n SyncConfig,\n SyncMode,\n} from \"./types\";\n"],"names":[],"mappings":";;;;;AAIA,WAAY,CAAA,QAAA,EAAU,aAAa,UAAU,CAAA"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./lib/version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport type { CursorsCursorProps, CursorsProps } from \"./cursors\";\nexport { Cursors } from \"./cursors\";\nexport { useLiveblocksFlow } from \"./lib/flow\";\nexport type {\n EdgeSyncConfig,\n LiveblocksEdge,\n LiveblocksFlow,\n LiveblocksNode,\n NodeSyncConfig,\n SyncConfig,\n SyncMode,\n} from \"./lib/types\";\n"],"names":[],"mappings":";;;;;AAIA,WAAY,CAAA,QAAA,EAAU,aAAa,UAAU,CAAA"}
@@ -5,7 +5,7 @@ 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 helpers = require('./helpers.cjs');
8
+ var shared = require('./shared.cjs');
9
9
 
10
10
  const EMPTY_ARRAY = [];
11
11
  function applyNodeChanges(changes, nodes, history, getNodeSyncConfig) {
@@ -20,7 +20,7 @@ function applyNodeChanges(changes, nodes, history, getNodeSyncConfig) {
20
20
  } else {
21
21
  nodes.set(
22
22
  change.item.id,
23
- helpers.toLiveblocksInternalNode(change.item, config)
23
+ shared.toLiveblocksInternalNode(change.item, config)
24
24
  );
25
25
  }
26
26
  break;
@@ -96,7 +96,7 @@ function applyEdgeChanges(changes, edges, getEdgeSyncConfig) {
96
96
  } else {
97
97
  edges.set(
98
98
  change.item.id,
99
- helpers.toLiveblocksInternalEdge(change.item, config)
99
+ shared.toLiveblocksInternalEdge(change.item, config)
100
100
  );
101
101
  }
102
102
  break;
@@ -142,13 +142,13 @@ function useLiveblocksFlow(options = {}) {
142
142
  const frozenOptions = _private.useInitial({
143
143
  nodes: options.nodes,
144
144
  edges: options.edges,
145
- storageKey: options.storageKey ?? helpers.DEFAULT_STORAGE_KEY,
145
+ storageKey: options.storageKey ?? shared.DEFAULT_STORAGE_KEY,
146
146
  suspense: options.suspense ?? false
147
147
  });
148
148
  const [getNodeSyncConfig, getEdgeSyncConfig] = react$1.useMemo(
149
149
  () => [
150
- helpers.buildNodeConfigCache(frozenOptions.nodes?.sync),
151
- helpers.buildEdgeConfigCache(frozenOptions.edges?.sync)
150
+ shared.buildNodeConfigCache(frozenOptions.nodes?.sync),
151
+ shared.buildEdgeConfigCache(frozenOptions.edges?.sync)
152
152
  ],
153
153
  [frozenOptions]
154
154
  );
@@ -185,7 +185,7 @@ function useLiveblocksFlow(options = {}) {
185
185
  }
186
186
  const edges2 = flow.get("edges");
187
187
  const config = getEdgeSyncConfig(newEdge.type);
188
- edges2.set(newEdge.id, helpers.toLiveblocksInternalEdge(newEdge, config));
188
+ edges2.set(newEdge.id, shared.toLiveblocksInternalEdge(newEdge, config));
189
189
  },
190
190
  [frozenOptions.storageKey, getEdgeSyncConfig]
191
191
  );
@@ -219,13 +219,13 @@ function useLiveblocksFlow(options = {}) {
219
219
  nodes: new core.LiveMap(
220
220
  initialNodes.map((node) => [
221
221
  node.id,
222
- helpers.toLiveblocksInternalNode(node, getNodeSyncConfig(node.type))
222
+ shared.toLiveblocksInternalNode(node, getNodeSyncConfig(node.type))
223
223
  ])
224
224
  ),
225
225
  edges: new core.LiveMap(
226
226
  initialEdges.map((edge) => [
227
227
  edge.id,
228
- helpers.toLiveblocksInternalEdge(edge, getEdgeSyncConfig(edge.type))
228
+ shared.toLiveblocksInternalEdge(edge, getEdgeSyncConfig(edge.type))
229
229
  ])
230
230
  )
231
231
  })
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.cjs","sources":["../../src/lib/flow.ts"],"sourcesContent":["import type {\n History,\n JsonObject,\n ReadonlyJsonObject,\n Resolve,\n ToJson,\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 buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./shared\";\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\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * label: false, // Don't sync node.data.label\n * color: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * hovered: false, // Don't sync edge.data.hovered\n * style: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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) break;\n\n // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.dragging === true) {\n history.pause();\n }\n\n if (change.position !== undefined) {\n const prev = node.get(\"position\");\n if (prev?.x !== change.position.x || prev?.y !== change.position.y) {\n node.set(\"position\", change.position);\n }\n }\n\n if (change.dragging !== undefined) {\n if (change.dragging === false) {\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 // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.resizing === true) {\n history.pause();\n }\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 === false) {\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// TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n// in topological order (parents before children), deferring any node with a\n// parentId until its parent has been emitted.\nfunction nodeMapToList<N extends Node>(\n nodesMap: ReadonlyJsonObject | null\n): N[] | null {\n if (nodesMap === null) return null;\n return Object.values(nodesMap) as unknown as N[];\n}\n\nfunction edgeMapToList<E extends Edge>(\n edgesMap: ReadonlyJsonObject | null\n): E[] | null {\n if (edgesMap === null) return null;\n return Object.values(edgesMap) as unknown as E[];\n}\n\nfunction useNodesAndEdges<N extends Node, E extends Edge>(storageKey: string) {\n // Storage already includes local overlays via toJSON(), so no separate local\n // layer is needed. Individual node/edge immutable references are already\n // stable (only change when the underlying LiveObject changes).\n const nodesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.nodes ?? null;\n });\n const edgesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.edges ?? null;\n });\n\n const nodes = useMemo(() => nodeMapToList<N>(nodesMap), [nodesMap]);\n const edges = useMemo(() => edgeMapToList<E>(edgesMap), [edgesMap]);\n return { nodes, edges };\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 const { nodes, edges } = useNodesAndEdges<N, E>(frozenOptions.storageKey);\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":["toLiveblocksInternalNode","toLiveblocksInternalEdge","useStorage","useMemo","useHistory","useInitial","DEFAULT_STORAGE_KEY","buildNodeConfigCache","buildEdgeConfigCache","useMutation","defaultAddEdge","edges","LiveObject","LiveMap","useEffect","kInternal","useSuspendUntilStorageReady"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { useStorage, useHistory, useMutation } from '@liveblocks/react';
3
3
  import { useInitial, useSuspendUntilStorageReady } from '@liveblocks/react/_private';
4
4
  import { addEdge } from '@xyflow/react';
5
5
  import { useMemo, useEffect } from 'react';
6
- import { toLiveblocksInternalNode, toLiveblocksInternalEdge, DEFAULT_STORAGE_KEY, buildNodeConfigCache, buildEdgeConfigCache } from './helpers.js';
6
+ import { toLiveblocksInternalNode, toLiveblocksInternalEdge, DEFAULT_STORAGE_KEY, buildNodeConfigCache, buildEdgeConfigCache } from './shared.js';
7
7
 
8
8
  const EMPTY_ARRAY = [];
9
9
  function applyNodeChanges(changes, nodes, history, getNodeSyncConfig) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sources":["../../src/lib/flow.ts"],"sourcesContent":["import type {\n History,\n JsonObject,\n ReadonlyJsonObject,\n Resolve,\n ToJson,\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 buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./shared\";\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\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * label: false, // Don't sync node.data.label\n * color: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * hovered: false, // Don't sync edge.data.hovered\n * style: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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) break;\n\n // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.dragging === true) {\n history.pause();\n }\n\n if (change.position !== undefined) {\n const prev = node.get(\"position\");\n if (prev?.x !== change.position.x || prev?.y !== change.position.y) {\n node.set(\"position\", change.position);\n }\n }\n\n if (change.dragging !== undefined) {\n if (change.dragging === false) {\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 // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.resizing === true) {\n history.pause();\n }\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 === false) {\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// TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n// in topological order (parents before children), deferring any node with a\n// parentId until its parent has been emitted.\nfunction nodeMapToList<N extends Node>(\n nodesMap: ReadonlyJsonObject | null\n): N[] | null {\n if (nodesMap === null) return null;\n return Object.values(nodesMap) as unknown as N[];\n}\n\nfunction edgeMapToList<E extends Edge>(\n edgesMap: ReadonlyJsonObject | null\n): E[] | null {\n if (edgesMap === null) return null;\n return Object.values(edgesMap) as unknown as E[];\n}\n\nfunction useNodesAndEdges<N extends Node, E extends Edge>(storageKey: string) {\n // Storage already includes local overlays via toJSON(), so no separate local\n // layer is needed. Individual node/edge immutable references are already\n // stable (only change when the underlying LiveObject changes).\n const nodesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.nodes ?? null;\n });\n const edgesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.edges ?? null;\n });\n\n const nodes = useMemo(() => nodeMapToList<N>(nodesMap), [nodesMap]);\n const edges = useMemo(() => edgeMapToList<E>(edgesMap), [edgesMap]);\n return { nodes, edges };\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 const { nodes, edges } = useNodesAndEdges<N, E>(frozenOptions.storageKey);\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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"}
@@ -74,4 +74,4 @@ exports.buildFlowDataConfigCache = buildFlowDataConfigCache;
74
74
  exports.buildNodeConfigCache = buildNodeConfigCache;
75
75
  exports.toLiveblocksInternalEdge = toLiveblocksInternalEdge;
76
76
  exports.toLiveblocksInternalNode = toLiveblocksInternalNode;
77
- //# sourceMappingURL=helpers.cjs.map
77
+ //# sourceMappingURL=shared.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.cjs","sources":["../../src/lib/shared.ts"],"sourcesContent":["/**\n * Module with utilities shared between the React Flow frontend and the React\n * Flow Node backend. There are no runtime dependencies on @xyflow/react,\n * react, or any other frontend-specific libraries from this module, and this\n * should stay that way.\n */\nimport type { JsonObject, SyncConfig, SyncMode } from \"@liveblocks/core\";\nimport { LiveObject } from \"@liveblocks/core\";\nimport type { Edge, Node } from \"@xyflow/react\";\n\nimport type { InternalLiveblocksEdge, InternalLiveblocksNode } from \"./types\";\n\nexport const DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow specific versions of `SyncConfig` that only allow keys that are actually exposed by React Flow.\ntype NodeSyncConfig = { [K in keyof Node]?: SyncMode };\ntype EdgeSyncConfig = { [K in keyof Edge]?: SyncMode };\n\nexport const NODE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n dragging: false,\n measured: false,\n resizing: false,\n\n // Atomic (synced as plain Json)\n position: \"atomic\",\n sourcePosition: \"atomic\",\n targetPosition: \"atomic\",\n extent: \"atomic\",\n origin: \"atomic\",\n handles: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies NodeSyncConfig;\n\nexport const EDGE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n\n // Atomic (synced as plain Json)\n markerStart: \"atomic\",\n markerEnd: \"atomic\",\n label: \"atomic\",\n labelBgPadding: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies EdgeSyncConfig;\n\n/**\n * Merges a base config with per-type user data configs, returning a lookup\n * function that resolves the full SyncConfig for a given type string.\n */\nexport function buildFlowDataConfigCache(\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 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\nexport function buildNodeConfigCache(\n nodeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);\n}\n\nexport function buildEdgeConfigCache(\n edgeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);\n}\n\nexport function toLiveblocksInternalNode<N extends Node>(\n node: N,\n config: SyncConfig\n): InternalLiveblocksNode {\n return LiveObject.from(\n node as unknown as JsonObject,\n config\n ) as InternalLiveblocksNode;\n}\n\nexport function toLiveblocksInternalEdge<E extends Edge>(\n edge: E,\n config: SyncConfig\n): InternalLiveblocksEdge {\n return LiveObject.from(\n edge as unknown as JsonObject,\n config\n ) as InternalLiveblocksEdge;\n}\n"],"names":["LiveObject"],"mappings":";;;;AAYO,MAAM,mBAAsB,GAAA,OAAA;AAM5B,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,QAAU,EAAA,QAAA;AAAA,EACV,cAAgB,EAAA,QAAA;AAAA,EAChB,cAAgB,EAAA,QAAA;AAAA,EAChB,MAAQ,EAAA,QAAA;AAAA,EACR,MAAQ,EAAA,QAAA;AAAA,EACR,OAAS,EAAA,QAAA;AAAA;AAAA;AAIX,EAAA;AAEO,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,WAAa,EAAA,QAAA;AAAA,EACb,SAAW,EAAA,QAAA;AAAA,EACX,KAAO,EAAA,QAAA;AAAA,EACP,cAAgB,EAAA,QAAA;AAAA;AAAA;AAIlB,EAAA;AAMgB,SAAA,wBAAA,CACd,MACA,IAC0C,EAAA;AAC1C,EAAA,IAAI,CAAC,IAAA;AAAM,IAAA,OAAO,MAAM,IAAA,CAAA;AAExB,EAAM,MAAA,YAAA,GAAe,KAAK,GAAG,CAAA,CAAA;AAC7B,EAAA,MAAM,WAAW,YAAe,GAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,cAAiB,GAAA,IAAA,CAAA;AAGlE,EAAM,MAAA,KAAA,uBAAY,GAAoC,EAAA,CAAA;AACtD,EAAA,KAAA,MAAW,QAAQ,IAAM,EAAA;AACvB,IAAA,IAAI,IAAS,KAAA,GAAA;AAAK,MAAA,SAAA;AAClB,IAAM,MAAA,QAAA,GAAW,KAAK,IAAI,CAAA,CAAA;AAC1B,IAAA,IAAI,CAAC,QAAA;AAAU,MAAA,SAAA;AACf,IAAA,MAAM,UAAyB,GAAA,EAAE,GAAG,YAAA,EAAc,GAAG,QAAS,EAAA,CAAA;AAC9D,IAAA,KAAA,CAAM,IAAI,IAAM,EAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,YAAY,CAAA,CAAA;AAAA,GAC/C;AAEA,EAAA,OAAO,CAAC,IAAA,KAAS,KAAM,CAAA,GAAA,CAAI,IAAI,CAAK,IAAA,QAAA,CAAA;AACtC,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAOA,eAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAOA,eAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF;;;;;;;;;;;"}
@@ -65,4 +65,4 @@ function toLiveblocksInternalEdge(edge, config) {
65
65
  }
66
66
 
67
67
  export { DEFAULT_STORAGE_KEY, EDGE_BASE_CONFIG, NODE_BASE_CONFIG, buildEdgeConfigCache, buildFlowDataConfigCache, buildNodeConfigCache, toLiveblocksInternalEdge, toLiveblocksInternalNode };
68
- //# sourceMappingURL=helpers.js.map
68
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sources":["../../src/lib/shared.ts"],"sourcesContent":["/**\n * Module with utilities shared between the React Flow frontend and the React\n * Flow Node backend. There are no runtime dependencies on @xyflow/react,\n * react, or any other frontend-specific libraries from this module, and this\n * should stay that way.\n */\nimport type { JsonObject, SyncConfig, SyncMode } from \"@liveblocks/core\";\nimport { LiveObject } from \"@liveblocks/core\";\nimport type { Edge, Node } from \"@xyflow/react\";\n\nimport type { InternalLiveblocksEdge, InternalLiveblocksNode } from \"./types\";\n\nexport const DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow specific versions of `SyncConfig` that only allow keys that are actually exposed by React Flow.\ntype NodeSyncConfig = { [K in keyof Node]?: SyncMode };\ntype EdgeSyncConfig = { [K in keyof Edge]?: SyncMode };\n\nexport const NODE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n dragging: false,\n measured: false,\n resizing: false,\n\n // Atomic (synced as plain Json)\n position: \"atomic\",\n sourcePosition: \"atomic\",\n targetPosition: \"atomic\",\n extent: \"atomic\",\n origin: \"atomic\",\n handles: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies NodeSyncConfig;\n\nexport const EDGE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n\n // Atomic (synced as plain Json)\n markerStart: \"atomic\",\n markerEnd: \"atomic\",\n label: \"atomic\",\n labelBgPadding: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies EdgeSyncConfig;\n\n/**\n * Merges a base config with per-type user data configs, returning a lookup\n * function that resolves the full SyncConfig for a given type string.\n */\nexport function buildFlowDataConfigCache(\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 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\nexport function buildNodeConfigCache(\n nodeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);\n}\n\nexport function buildEdgeConfigCache(\n edgeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);\n}\n\nexport function toLiveblocksInternalNode<N extends Node>(\n node: N,\n config: SyncConfig\n): InternalLiveblocksNode {\n return LiveObject.from(\n node as unknown as JsonObject,\n config\n ) as InternalLiveblocksNode;\n}\n\nexport function toLiveblocksInternalEdge<E extends Edge>(\n edge: E,\n config: SyncConfig\n): InternalLiveblocksEdge {\n return LiveObject.from(\n edge as unknown as JsonObject,\n config\n ) as InternalLiveblocksEdge;\n}\n"],"names":[],"mappings":";;AAYO,MAAM,mBAAsB,GAAA,OAAA;AAM5B,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,QAAU,EAAA,QAAA;AAAA,EACV,cAAgB,EAAA,QAAA;AAAA,EAChB,cAAgB,EAAA,QAAA;AAAA,EAChB,MAAQ,EAAA,QAAA;AAAA,EACR,MAAQ,EAAA,QAAA;AAAA,EACR,OAAS,EAAA,QAAA;AAAA;AAAA;AAIX,EAAA;AAEO,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,WAAa,EAAA,QAAA;AAAA,EACb,SAAW,EAAA,QAAA;AAAA,EACX,KAAO,EAAA,QAAA;AAAA,EACP,cAAgB,EAAA,QAAA;AAAA;AAAA;AAIlB,EAAA;AAMgB,SAAA,wBAAA,CACd,MACA,IAC0C,EAAA;AAC1C,EAAA,IAAI,CAAC,IAAA;AAAM,IAAA,OAAO,MAAM,IAAA,CAAA;AAExB,EAAM,MAAA,YAAA,GAAe,KAAK,GAAG,CAAA,CAAA;AAC7B,EAAA,MAAM,WAAW,YAAe,GAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,cAAiB,GAAA,IAAA,CAAA;AAGlE,EAAM,MAAA,KAAA,uBAAY,GAAoC,EAAA,CAAA;AACtD,EAAA,KAAA,MAAW,QAAQ,IAAM,EAAA;AACvB,IAAA,IAAI,IAAS,KAAA,GAAA;AAAK,MAAA,SAAA;AAClB,IAAM,MAAA,QAAA,GAAW,KAAK,IAAI,CAAA,CAAA;AAC1B,IAAA,IAAI,CAAC,QAAA;AAAU,MAAA,SAAA;AACf,IAAA,MAAM,UAAyB,GAAA,EAAE,GAAG,YAAA,EAAc,GAAG,QAAS,EAAA,CAAA;AAC9D,IAAA,KAAA,CAAM,IAAI,IAAM,EAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,YAAY,CAAA,CAAA;AAAA,GAC/C;AAEA,EAAA,OAAO,CAAC,IAAA,KAAS,KAAM,CAAA,GAAA,CAAI,IAAI,CAAK,IAAA,QAAA,CAAA;AACtC,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAO,UAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAO,UAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const PKG_NAME = "@liveblocks/react-flow";
4
- const PKG_VERSION = typeof "3.18.0-rc1" === "string" && "3.18.0-rc1";
4
+ const PKG_VERSION = typeof "3.18.0" === "string" && "3.18.0";
5
5
  const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
6
6
 
7
7
  exports.PKG_FORMAT = PKG_FORMAT;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.cjs","sources":["../../src/lib/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,QAAA,KAAgB,QAAY,IAAA,SAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  const PKG_NAME = "@liveblocks/react-flow";
2
- const PKG_VERSION = typeof "3.18.0-rc1" === "string" && "3.18.0-rc1";
2
+ const PKG_VERSION = typeof "3.18.0" === "string" && "3.18.0";
3
3
  const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
4
4
 
5
5
  export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sources":["../../src/lib/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,QAAA,KAAgB,QAAY,IAAA,SAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;"}
package/dist/node.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var core = require('@liveblocks/core');
4
- var helpers = require('./helpers.cjs');
4
+ var shared = require('./lib/shared.cjs');
5
5
 
6
6
  async function mutateFlow(options, callback) {
7
7
  const { client, roomId } = options;
8
- const storageKey = options.storageKey ?? helpers.DEFAULT_STORAGE_KEY;
9
- const getNodeSyncConfig = helpers.buildNodeConfigCache(options.nodes?.sync);
10
- const getEdgeSyncConfig = helpers.buildEdgeConfigCache(options.edges?.sync);
8
+ const storageKey = options.storageKey ?? shared.DEFAULT_STORAGE_KEY;
9
+ const getNodeSyncConfig = shared.buildNodeConfigCache(options.nodes?.sync);
10
+ const getEdgeSyncConfig = shared.buildEdgeConfigCache(options.edges?.sync);
11
11
  const nodeListCache = /* @__PURE__ */ new WeakMap();
12
12
  const edgeListCache = /* @__PURE__ */ new WeakMap();
13
13
  await client.mutateStorage(roomId, async ({ root }) => {
@@ -46,7 +46,7 @@ async function mutateFlow(options, callback) {
46
46
  const existing = nodesLiveMap.get(id);
47
47
  const syncConfig = getNodeSyncConfig(newNode.type);
48
48
  if (!existing) {
49
- nodesLiveMap.set(id, helpers.toLiveblocksInternalNode(newNode, syncConfig));
49
+ nodesLiveMap.set(id, shared.toLiveblocksInternalNode(newNode, syncConfig));
50
50
  } else {
51
51
  existing.reconcile(newNode, syncConfig);
52
52
  }
@@ -55,7 +55,7 @@ async function mutateFlow(options, callback) {
55
55
  const existing = edgesLiveMap.get(id);
56
56
  const syncConfig = getEdgeSyncConfig(newEdge.type);
57
57
  if (!existing) {
58
- edgesLiveMap.set(id, helpers.toLiveblocksInternalEdge(newEdge, syncConfig));
58
+ edgesLiveMap.set(id, shared.toLiveblocksInternalEdge(newEdge, syncConfig));
59
59
  } else {
60
60
  existing.reconcile(newEdge, syncConfig);
61
61
  }
package/dist/node.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.cjs","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./helpers\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n readonly nodes: readonly N[];\n readonly edges: readonly E[];\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n getNode(id: string): N | undefined;\n getEdge(id: string): E | undefined;\n\n addNode(node: N): void;\n addNodes(nodes: N[]): void;\n updateNode(id: string, partial: Partial<N>): void;\n updateNode(id: string, updater: (node: N) => N): void;\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n removeNode(id: string): void;\n removeNodes(ids: string[]): void;\n\n addEdge(edge: E): void;\n addEdges(edges: E[]): void;\n updateEdge(id: string, partial: Partial<E>): void;\n updateEdge(id: string, updater: (edge: E) => E): void;\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n removeEdge(id: string): void;\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a \"Flow document\" (a collection of nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":["DEFAULT_STORAGE_KEY","buildNodeConfigCache","buildEdgeConfigCache","LiveObject","LiveMap","toLiveblocksInternalNode","toLiveblocksInternalEdge"],"mappings":"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"}
1
+ {"version":3,"file":"node.cjs","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./lib/shared\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./lib/types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n /** The current list of nodes. */\n readonly nodes: readonly N[];\n /** The current list of edges. */\n readonly edges: readonly E[];\n /** Returns a plain object snapshot with `nodes` and `edges` arrays. */\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n /** Returns a single node by ID, or `undefined` if not found. */\n getNode(id: string): N | undefined;\n /** Returns a single edge by ID, or `undefined` if not found. */\n getEdge(id: string): E | undefined;\n\n /** Adds a node. If a node with the same ID already exists, it is replaced. */\n addNode(node: N): void;\n /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */\n addNodes(nodes: N[]): void;\n /** Updates a node by merging a partial object. No-op if the node does not exist. */\n updateNode(id: string, partial: Partial<N>): void;\n /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNode(id: string, updater: (node: N) => N): void;\n /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes a node by ID. */\n removeNode(id: string): void;\n /** Removes multiple nodes by ID. */\n removeNodes(ids: string[]): void;\n\n /** Adds an edge. If an edge with the same ID already exists, it is replaced. */\n addEdge(edge: E): void;\n /** Adds multiple edges. Existing edges with the same IDs are replaced. */\n addEdges(edges: E[]): void;\n /** Updates an edge by merging a partial object. No-op if the edge does not exist. */\n updateEdge(id: string, partial: Partial<E>): void;\n /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdge(id: string, updater: (edge: E) => E): void;\n /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes an edge by ID. */\n removeEdge(id: string): void;\n /** Removes multiple edges by ID. */\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a flow (a collection of React Flow nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":["DEFAULT_STORAGE_KEY","buildNodeConfigCache","buildEdgeConfigCache","LiveObject","LiveMap","toLiveblocksInternalNode","toLiveblocksInternalEdge"],"mappings":"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"}
package/dist/node.d.cts CHANGED
@@ -35,33 +35,54 @@ interface MutateFlowOptions<N extends Node = BuiltInNode, E extends Edge = Built
35
35
  };
36
36
  }
37
37
  interface MutableFlow<N extends Node, E extends Edge> {
38
+ /** The current list of nodes. */
38
39
  readonly nodes: readonly N[];
40
+ /** The current list of edges. */
39
41
  readonly edges: readonly E[];
42
+ /** Returns a plain object snapshot with `nodes` and `edges` arrays. */
40
43
  toJSON(): {
41
44
  nodes: readonly N[];
42
45
  edges: readonly E[];
43
46
  };
47
+ /** Returns a single node by ID, or `undefined` if not found. */
44
48
  getNode(id: string): N | undefined;
49
+ /** Returns a single edge by ID, or `undefined` if not found. */
45
50
  getEdge(id: string): E | undefined;
51
+ /** Adds a node. If a node with the same ID already exists, it is replaced. */
46
52
  addNode(node: N): void;
53
+ /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */
47
54
  addNodes(nodes: N[]): void;
55
+ /** Updates a node by merging a partial object. No-op if the node does not exist. */
48
56
  updateNode(id: string, partial: Partial<N>): void;
57
+ /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
49
58
  updateNode(id: string, updater: (node: N) => N): void;
59
+ /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */
50
60
  updateNodeData(id: string, partial: Partial<N["data"]>): void;
61
+ /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
51
62
  updateNodeData<D extends N["data"]>(id: string, updater: (data: D) => D): void;
63
+ /** Removes a node by ID. */
52
64
  removeNode(id: string): void;
65
+ /** Removes multiple nodes by ID. */
53
66
  removeNodes(ids: string[]): void;
67
+ /** Adds an edge. If an edge with the same ID already exists, it is replaced. */
54
68
  addEdge(edge: E): void;
69
+ /** Adds multiple edges. Existing edges with the same IDs are replaced. */
55
70
  addEdges(edges: E[]): void;
71
+ /** Updates an edge by merging a partial object. No-op if the edge does not exist. */
56
72
  updateEdge(id: string, partial: Partial<E>): void;
73
+ /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
57
74
  updateEdge(id: string, updater: (edge: E) => E): void;
75
+ /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */
58
76
  updateEdgeData(id: string, partial: Partial<NonNullable<E["data"]>>): void;
77
+ /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
59
78
  updateEdgeData<D extends E["data"]>(id: string, updater: (data: D) => D): void;
79
+ /** Removes an edge by ID. */
60
80
  removeEdge(id: string): void;
81
+ /** Removes multiple edges by ID. */
61
82
  removeEdges(ids: string[]): void;
62
83
  }
63
84
  /**
64
- * Opens a "Flow document" (a collection of nodes and edges) for reading and
85
+ * Opens a flow (a collection of React Flow nodes and edges) for reading and
65
86
  * mutating, then automatically flushes all changes when the callback
66
87
  * completes.
67
88
  *
package/dist/node.d.ts CHANGED
@@ -35,33 +35,54 @@ interface MutateFlowOptions<N extends Node = BuiltInNode, E extends Edge = Built
35
35
  };
36
36
  }
37
37
  interface MutableFlow<N extends Node, E extends Edge> {
38
+ /** The current list of nodes. */
38
39
  readonly nodes: readonly N[];
40
+ /** The current list of edges. */
39
41
  readonly edges: readonly E[];
42
+ /** Returns a plain object snapshot with `nodes` and `edges` arrays. */
40
43
  toJSON(): {
41
44
  nodes: readonly N[];
42
45
  edges: readonly E[];
43
46
  };
47
+ /** Returns a single node by ID, or `undefined` if not found. */
44
48
  getNode(id: string): N | undefined;
49
+ /** Returns a single edge by ID, or `undefined` if not found. */
45
50
  getEdge(id: string): E | undefined;
51
+ /** Adds a node. If a node with the same ID already exists, it is replaced. */
46
52
  addNode(node: N): void;
53
+ /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */
47
54
  addNodes(nodes: N[]): void;
55
+ /** Updates a node by merging a partial object. No-op if the node does not exist. */
48
56
  updateNode(id: string, partial: Partial<N>): void;
57
+ /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
49
58
  updateNode(id: string, updater: (node: N) => N): void;
59
+ /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */
50
60
  updateNodeData(id: string, partial: Partial<N["data"]>): void;
61
+ /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */
51
62
  updateNodeData<D extends N["data"]>(id: string, updater: (data: D) => D): void;
63
+ /** Removes a node by ID. */
52
64
  removeNode(id: string): void;
65
+ /** Removes multiple nodes by ID. */
53
66
  removeNodes(ids: string[]): void;
67
+ /** Adds an edge. If an edge with the same ID already exists, it is replaced. */
54
68
  addEdge(edge: E): void;
69
+ /** Adds multiple edges. Existing edges with the same IDs are replaced. */
55
70
  addEdges(edges: E[]): void;
71
+ /** Updates an edge by merging a partial object. No-op if the edge does not exist. */
56
72
  updateEdge(id: string, partial: Partial<E>): void;
73
+ /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
57
74
  updateEdge(id: string, updater: (edge: E) => E): void;
75
+ /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */
58
76
  updateEdgeData(id: string, partial: Partial<NonNullable<E["data"]>>): void;
77
+ /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */
59
78
  updateEdgeData<D extends E["data"]>(id: string, updater: (data: D) => D): void;
79
+ /** Removes an edge by ID. */
60
80
  removeEdge(id: string): void;
81
+ /** Removes multiple edges by ID. */
61
82
  removeEdges(ids: string[]): void;
62
83
  }
63
84
  /**
64
- * Opens a "Flow document" (a collection of nodes and edges) for reading and
85
+ * Opens a flow (a collection of React Flow nodes and edges) for reading and
65
86
  * mutating, then automatically flushes all changes when the callback
66
87
  * completes.
67
88
  *
package/dist/node.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { LiveObject, LiveMap } from '@liveblocks/core';
2
- import { DEFAULT_STORAGE_KEY, buildNodeConfigCache, buildEdgeConfigCache, toLiveblocksInternalNode, toLiveblocksInternalEdge } from './helpers.js';
2
+ import { DEFAULT_STORAGE_KEY, buildNodeConfigCache, buildEdgeConfigCache, toLiveblocksInternalNode, toLiveblocksInternalEdge } from './lib/shared.js';
3
3
 
4
4
  async function mutateFlow(options, callback) {
5
5
  const { client, roomId } = options;
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./helpers\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n readonly nodes: readonly N[];\n readonly edges: readonly E[];\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n getNode(id: string): N | undefined;\n getEdge(id: string): E | undefined;\n\n addNode(node: N): void;\n addNodes(nodes: N[]): void;\n updateNode(id: string, partial: Partial<N>): void;\n updateNode(id: string, updater: (node: N) => N): void;\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n removeNode(id: string): void;\n removeNodes(ids: string[]): void;\n\n addEdge(edge: E): void;\n addEdges(edges: E[]): void;\n updateEdge(id: string, partial: Partial<E>): void;\n updateEdge(id: string, updater: (edge: E) => E): void;\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n removeEdge(id: string): void;\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a \"Flow document\" (a collection of nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.js","sources":["../src/node.ts"],"sourcesContent":["import type { JsonObject, LsonObject } from \"@liveblocks/core\";\nimport { LiveMap, LiveObject } from \"@liveblocks/core\";\nimport type { BuiltInEdge, BuiltInNode, Edge, Node } from \"@xyflow/react\";\n\nimport {\n buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} from \"./lib/shared\";\nimport type {\n EdgeSyncConfig,\n InternalLiveblocksFlow,\n NodeSyncConfig,\n} from \"./lib/types\";\n\n/**\n * A minimal interface for the Liveblocks Node client — just the\n * `mutateStorage` method we actually need. This avoids importing\n * `@liveblocks/node` as a dependency.\n */\ninterface ILiveblocksClient {\n mutateStorage(\n roomId: string,\n callback: (context: {\n root: LiveObject<LsonObject>;\n }) => void | Promise<void>\n ): Promise<void>;\n}\n\n/** Options for `mutateFlow()`. */\nexport interface MutateFlowOptions<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n> {\n client: ILiveblocksClient;\n roomId: string;\n storageKey?: string;\n nodes?: { sync?: NodeSyncConfig<N> };\n edges?: { sync?: EdgeSyncConfig<E> };\n}\n\nexport interface MutableFlow<N extends Node, E extends Edge> {\n /** The current list of nodes. */\n readonly nodes: readonly N[];\n /** The current list of edges. */\n readonly edges: readonly E[];\n /** Returns a plain object snapshot with `nodes` and `edges` arrays. */\n toJSON(): {\n nodes: readonly N[];\n edges: readonly E[];\n };\n\n /** Returns a single node by ID, or `undefined` if not found. */\n getNode(id: string): N | undefined;\n /** Returns a single edge by ID, or `undefined` if not found. */\n getEdge(id: string): E | undefined;\n\n /** Adds a node. If a node with the same ID already exists, it is replaced. */\n addNode(node: N): void;\n /** Adds multiple nodes. Existing nodes with the same IDs are replaced. */\n addNodes(nodes: N[]): void;\n /** Updates a node by merging a partial object. No-op if the node does not exist. */\n updateNode(id: string, partial: Partial<N>): void;\n /** Updates a node using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNode(id: string, updater: (node: N) => N): void;\n /** Updates a node's `data` by merging a partial object. No-op if the node does not exist. */\n updateNodeData(id: string, partial: Partial<N[\"data\"]>): void;\n /** Updates a node's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the node does not exist. */\n updateNodeData<D extends N[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes a node by ID. */\n removeNode(id: string): void;\n /** Removes multiple nodes by ID. */\n removeNodes(ids: string[]): void;\n\n /** Adds an edge. If an edge with the same ID already exists, it is replaced. */\n addEdge(edge: E): void;\n /** Adds multiple edges. Existing edges with the same IDs are replaced. */\n addEdges(edges: E[]): void;\n /** Updates an edge by merging a partial object. No-op if the edge does not exist. */\n updateEdge(id: string, partial: Partial<E>): void;\n /** Updates an edge using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdge(id: string, updater: (edge: E) => E): void;\n /** Updates an edge's `data` by merging a partial object. No-op if the edge does not exist. */\n updateEdgeData(id: string, partial: Partial<NonNullable<E[\"data\"]>>): void;\n /** Updates an edge's `data` using an updater function. Always return a new object, never mutate in-place. No-op if the edge does not exist. */\n updateEdgeData<D extends E[\"data\"]>(\n id: string,\n updater: (data: D) => D\n ): void;\n /** Removes an edge by ID. */\n removeEdge(id: string): void;\n /** Removes multiple edges by ID. */\n removeEdges(ids: string[]): void;\n}\n\n/**\n * Opens a flow (a collection of React Flow nodes and edges) for reading and\n * mutating, then automatically flushes all changes when the callback\n * completes.\n *\n * @example\n * ```ts\n * await mutateFlow({ client, roomId: \"my-room\" }, (flow) => {\n * flow.addNode({ id: \"1\", position: { x: 0, y: 0 }, data: {} });\n * flow.updateNodeData(\"1\", { label: \"Hello\" });\n * });\n * ```\n */\nexport async function mutateFlow<\n N extends Node = BuiltInNode,\n E extends Edge = BuiltInEdge,\n>(\n options: MutateFlowOptions<N, E>,\n callback: (flow: MutableFlow<N, E>) => void | Promise<void>\n): Promise<void> {\n const { client, roomId } = options;\n const storageKey = options.storageKey ?? DEFAULT_STORAGE_KEY;\n\n const getNodeSyncConfig = buildNodeConfigCache(options.nodes?.sync);\n const getEdgeSyncConfig = buildEdgeConfigCache(options.edges?.sync);\n\n const nodeListCache = new WeakMap<Record<string, N>, N[]>();\n const edgeListCache = new WeakMap<Record<string, E>, E[]>();\n\n await client.mutateStorage(roomId, async ({ root }) => {\n let flow = root.get(storageKey) as InternalLiveblocksFlow | undefined;\n if (!flow) {\n const newFlow = new LiveObject({\n nodes: new LiveMap(),\n edges: new LiveMap(),\n }) satisfies InternalLiveblocksFlow;\n root.set(storageKey, newFlow);\n flow = newFlow;\n }\n\n const nodesLiveMap = flow.get(\"nodes\");\n const edgesLiveMap = flow.get(\"edges\");\n\n function getNodes(): readonly N[] {\n const nodeMap = nodesLiveMap.toJSON() as unknown as Record<string, N>;\n if (!nodeListCache.has(nodeMap)) {\n // TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n // in topological order (parents before children), deferring any node with a\n // parentId until its parent has been emitted.\n nodeListCache.set(nodeMap, Object.values(nodeMap));\n }\n return nodeListCache.get(nodeMap)!;\n }\n\n function getEdges(): readonly E[] {\n const edgeMap = edgesLiveMap.toJSON() as unknown as Record<string, E>;\n if (!edgeListCache.has(edgeMap)) {\n edgeListCache.set(edgeMap, Object.values(edgeMap));\n }\n return edgeListCache.get(edgeMap)!;\n }\n\n function getNode(id: string) {\n return nodesLiveMap.get(id)?.toJSON() as N | undefined;\n }\n function getEdge(id: string) {\n return edgesLiveMap.get(id)?.toJSON() as E | undefined;\n }\n\n function upsertNode(id: string, newNode: N) {\n const existing = nodesLiveMap.get(id);\n const syncConfig = getNodeSyncConfig(newNode.type);\n if (!existing) {\n nodesLiveMap.set(id, toLiveblocksInternalNode(newNode, syncConfig));\n } else {\n existing.reconcile(newNode as unknown as JsonObject, syncConfig);\n }\n }\n\n function upsertEdge(id: string, newEdge: E) {\n const existing = edgesLiveMap.get(id);\n const syncConfig = getEdgeSyncConfig(newEdge.type);\n if (!existing) {\n edgesLiveMap.set(id, toLiveblocksInternalEdge(newEdge, syncConfig));\n } else {\n existing.reconcile(newEdge as unknown as JsonObject, syncConfig);\n }\n }\n\n const mutableFlow: MutableFlow<N, E> = {\n get nodes() {\n return getNodes();\n },\n get edges() {\n return getEdges();\n },\n toJSON() {\n return { nodes: getNodes(), edges: getEdges() };\n },\n getNode,\n getEdge,\n\n addNode(node: N) {\n upsertNode(node.id, node);\n },\n addNodes(nodes: N[]) {\n for (const node of nodes) {\n mutableFlow.addNode(node);\n }\n },\n updateNode(id: string, partialOrUpdater: Partial<N> | ((node: N) => N)) {\n const oldNode = getNode(id);\n if (!oldNode) return;\n\n let newNode: N;\n if (typeof partialOrUpdater === \"function\") {\n newNode = partialOrUpdater(oldNode);\n } else {\n newNode = { ...oldNode, ...partialOrUpdater };\n }\n return upsertNode(id, newNode);\n },\n updateNodeData(\n id: string,\n partialOrUpdater:\n | Partial<N[\"data\"]>\n | (<D extends N[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateNode(id, (node) => {\n const currData = node.data ?? ({} as N[\"data\"]);\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...node, data: newData };\n });\n },\n removeNode(id: string) {\n nodesLiveMap.delete(id);\n },\n removeNodes(ids: string[]) {\n for (const id of ids) {\n nodesLiveMap.delete(id);\n }\n },\n\n addEdge(edge: E) {\n upsertEdge(edge.id, edge);\n },\n addEdges(edges: E[]) {\n for (const edge of edges) {\n mutableFlow.addEdge(edge);\n }\n },\n updateEdge(id: string, partialOrUpdater: Partial<E> | ((edge: E) => E)) {\n const oldEdge = getEdge(id);\n if (!oldEdge) return;\n\n let newEdge: E;\n if (typeof partialOrUpdater === \"function\") {\n newEdge = partialOrUpdater(oldEdge);\n } else {\n newEdge = { ...oldEdge, ...partialOrUpdater };\n }\n return upsertEdge(id, newEdge);\n },\n updateEdgeData(\n id: string,\n partialOrUpdater:\n | Partial<NonNullable<E[\"data\"]>>\n | (<D extends E[\"data\"]>(data: D) => D)\n ) {\n return mutableFlow.updateEdge(id, (edge) => {\n const currData = edge.data;\n const newData =\n typeof partialOrUpdater === \"function\"\n ? partialOrUpdater(currData)\n : { ...currData, ...partialOrUpdater };\n return { ...edge, data: newData };\n });\n },\n removeEdge(id: string) {\n edgesLiveMap.delete(id);\n },\n removeEdges(ids: string[]) {\n for (const id of ids) {\n edgesLiveMap.delete(id);\n }\n },\n };\n\n await callback(mutableFlow);\n });\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react-flow",
3
- "version": "3.18.0-rc1",
3
+ "version": "3.18.0",
4
4
  "description": "An integration of React Flow to enable collaboration and realtime cursors with Liveblocks.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Liveblocks Inc.",
@@ -63,10 +63,10 @@
63
63
  "test:watch": "vitest"
64
64
  },
65
65
  "dependencies": {
66
- "@liveblocks/client": "3.18.0-rc1",
67
- "@liveblocks/core": "3.18.0-rc1",
68
- "@liveblocks/react": "3.18.0-rc1",
69
- "@liveblocks/react-ui": "3.18.0-rc1"
66
+ "@liveblocks/client": "3.18.0",
67
+ "@liveblocks/core": "3.18.0",
68
+ "@liveblocks/react": "3.18.0",
69
+ "@liveblocks/react-ui": "3.18.0"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@xyflow/react": "^12",
package/dist/flow.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"flow.cjs","sources":["../src/flow.ts"],"sourcesContent":["import type {\n History,\n JsonObject,\n ReadonlyJsonObject,\n Resolve,\n ToJson,\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 buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} 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\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * label: false, // Don't sync node.data.label\n * color: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * hovered: false, // Don't sync edge.data.hovered\n * style: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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) break;\n\n // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.dragging === true) {\n history.pause();\n }\n\n if (change.position !== undefined) {\n const prev = node.get(\"position\");\n if (prev?.x !== change.position.x || prev?.y !== change.position.y) {\n node.set(\"position\", change.position);\n }\n }\n\n if (change.dragging !== undefined) {\n if (change.dragging === false) {\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 // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.resizing === true) {\n history.pause();\n }\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 === false) {\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// TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n// in topological order (parents before children), deferring any node with a\n// parentId until its parent has been emitted.\nfunction nodeMapToList<N extends Node>(\n nodesMap: ReadonlyJsonObject | null\n): N[] | null {\n if (nodesMap === null) return null;\n return Object.values(nodesMap) as unknown as N[];\n}\n\nfunction edgeMapToList<E extends Edge>(\n edgesMap: ReadonlyJsonObject | null\n): E[] | null {\n if (edgesMap === null) return null;\n return Object.values(edgesMap) as unknown as E[];\n}\n\nfunction useNodesAndEdges<N extends Node, E extends Edge>(storageKey: string) {\n // Storage already includes local overlays via toJSON(), so no separate local\n // layer is needed. Individual node/edge immutable references are already\n // stable (only change when the underlying LiveObject changes).\n const nodesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.nodes ?? null;\n });\n const edgesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.edges ?? null;\n });\n\n const nodes = useMemo(() => nodeMapToList<N>(nodesMap), [nodesMap]);\n const edges = useMemo(() => edgeMapToList<E>(edgesMap), [edgesMap]);\n return { nodes, edges };\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 const { nodes, edges } = useNodesAndEdges<N, E>(frozenOptions.storageKey);\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":["toLiveblocksInternalNode","toLiveblocksInternalEdge","useStorage","useMemo","useHistory","useInitial","DEFAULT_STORAGE_KEY","buildNodeConfigCache","buildEdgeConfigCache","useMutation","defaultAddEdge","edges","LiveObject","LiveMap","useEffect","kInternal","useSuspendUntilStorageReady"],"mappings":";;;;;;;;;AA6CA,MAAM,cAAc,EAAC,CAAA;AAqIrB,SAAS,gBACP,CAAA,OAAA,EACA,KACA,EAAA,OAAA,EACA,iBACM,EAAA;AACN,EAAA,KAAA,MAAW,UAAU,OAAS,EAAA;AAC5B,IAAA,QAAQ,OAAO,IAAM;AAAA,MACnB,KAAK,KAAA,CAAA;AAAA,MACL,KAAK,SAAW,EAAA;AACd,QAAA,MAAM,MAAS,GAAA,iBAAA,CAAkB,MAAO,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AACjD,QAAA,MAAM,QAAW,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,KAAK,EAAE,CAAA,CAAA;AACzC,QAAA,IAAI,QAAU,EAAA;AACZ,UAAS,QAAA,CAAA,SAAA,CAAU,MAAO,CAAA,IAAA,EAA+B,MAAM,CAAA,CAAA;AAAA,SAC1D,MAAA;AACL,UAAM,KAAA,CAAA,GAAA;AAAA,YACJ,OAAO,IAAK,CAAA,EAAA;AAAA,YACZA,gCAAA,CAAyB,MAAO,CAAA,IAAA,EAAM,MAAM,CAAA;AAAA,WAC9C,CAAA;AAAA,SACF;AACA,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,UAAY,EAAA;AACf,QAAA,MAAM,IAAO,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAChC,QAAA,IAAI,CAAC,IAAA;AAAM,UAAA,MAAA;AAGX,QAAI,IAAA,MAAA,CAAO,aAAa,IAAM,EAAA;AAC5B,UAAA,OAAA,CAAQ,KAAM,EAAA,CAAA;AAAA,SAChB;AAEA,QAAI,IAAA,MAAA,CAAO,aAAa,KAAW,CAAA,EAAA;AACjC,UAAM,MAAA,IAAA,GAAO,IAAK,CAAA,GAAA,CAAI,UAAU,CAAA,CAAA;AAChC,UAAI,IAAA,IAAA,EAAM,MAAM,MAAO,CAAA,QAAA,CAAS,KAAK,IAAM,EAAA,CAAA,KAAM,MAAO,CAAA,QAAA,CAAS,CAAG,EAAA;AAClE,YAAK,IAAA,CAAA,GAAA,CAAI,UAAY,EAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,WACtC;AAAA,SACF;AAEA,QAAI,IAAA,MAAA,CAAO,aAAa,KAAW,CAAA,EAAA;AACjC,UAAI,IAAA,MAAA,CAAO,aAAa,KAAO,EAAA;AAC7B,YAAA,OAAA,CAAQ,MAAO,EAAA,CAAA;AAAA,WACjB;AAEA,UAAK,IAAA,CAAA,QAAA,CAAS,UAAY,EAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,SAC3C;AACA,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,YAAc,EAAA;AACjB,QAAA,MAAM,IAAO,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAChC,QAAA,IAAI,CAAC,IAAA;AAAM,UAAA,MAAA;AAGX,QAAI,IAAA,MAAA,CAAO,aAAa,IAAM,EAAA;AAC5B,UAAA,OAAA,CAAQ,KAAM,EAAA,CAAA;AAAA,SAChB;AAEA,QAAA,IACE,MAAO,CAAA,UAAA,KAAe,KACtB,CAAA,IAAA,MAAA,CAAO,kBAAkB,KACzB,CAAA,EAAA;AACA,UAAA,IACE,MAAO,CAAA,aAAA,KAAkB,IACzB,IAAA,MAAA,CAAO,kBAAkB,OACzB,EAAA;AACA,YAAA,IAAA,CAAK,GAAI,CAAA,OAAA,EAAS,MAAO,CAAA,UAAA,CAAW,KAAK,CAAA,CAAA;AAAA,WAC3C;AAEA,UAAA,IACE,MAAO,CAAA,aAAA,KAAkB,IACzB,IAAA,MAAA,CAAO,kBAAkB,QACzB,EAAA;AACA,YAAA,IAAA,CAAK,GAAI,CAAA,QAAA,EAAU,MAAO,CAAA,UAAA,CAAW,MAAM,CAAA,CAAA;AAAA,WAC7C;AAAA,SACF;AAEA,QAAI,IAAA,MAAA,CAAO,eAAe,KAAW,CAAA,EAAA;AAEnC,UAAK,IAAA,CAAA,QAAA,CAAS,UAAY,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA;AAAA,SAC7C;AAEA,QAAI,IAAA,MAAA,CAAO,aAAa,KAAW,CAAA,EAAA;AACjC,UAAI,IAAA,MAAA,CAAO,aAAa,KAAO,EAAA;AAC7B,YAAA,OAAA,CAAQ,MAAO,EAAA,CAAA;AAAA,WACjB;AAEA,UAAK,IAAA,CAAA,QAAA,CAAS,UAAY,EAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,SAC3C;AAEA,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,QAAU,EAAA;AACb,QAAA,MAAM,IAAO,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAChC,QAAA,IAAI,CAAC,IAAA;AAAM,UAAA,MAAA;AAGX,QAAK,IAAA,CAAA,QAAA,CAAS,UAAY,EAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AACzC,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,QAAA;AAEH,QAAA,MAAA;AAAA,KACJ;AAAA,GACF;AACF,CAAA;AAKA,SAAS,gBAAA,CACP,OACA,EAAA,KAAA,EACA,iBACM,EAAA;AACN,EAAA,KAAA,MAAW,UAAU,OAAS,EAAA;AAC5B,IAAA,QAAQ,OAAO,IAAM;AAAA,MACnB,KAAK,KAAA,CAAA;AAAA,MACL,KAAK,SAAW,EAAA;AACd,QAAA,MAAM,MAAS,GAAA,iBAAA,CAAkB,MAAO,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AACjD,QAAA,MAAM,QAAW,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,KAAK,EAAE,CAAA,CAAA;AACzC,QAAA,IAAI,QAAU,EAAA;AACZ,UAAS,QAAA,CAAA,SAAA,CAAU,MAAO,CAAA,IAAA,EAA+B,MAAM,CAAA,CAAA;AAAA,SAC1D,MAAA;AACL,UAAM,KAAA,CAAA,GAAA;AAAA,YACJ,OAAO,IAAK,CAAA,EAAA;AAAA,YACZC,gCAAA,CAAyB,MAAO,CAAA,IAAA,EAAM,MAAM,CAAA;AAAA,WAC9C,CAAA;AAAA,SACF;AACA,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,QAAU,EAAA;AACb,QAAA,MAAM,IAAO,GAAA,KAAA,CAAM,GAAI,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAChC,QAAA,IAAI,CAAC,IAAA;AAAM,UAAA,MAAA;AAEX,QAAK,IAAA,CAAA,QAAA,CAAS,UAAY,EAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AACzC,QAAA,MAAA;AAAA,OACF;AAAA,MAEA,KAAK,QAAA;AAEH,QAAA,MAAA;AAAA,KACJ;AAAA,GACF;AACF,CAAA;AAKA,SAAS,cACP,QACY,EAAA;AACZ,EAAA,IAAI,QAAa,KAAA,IAAA;AAAM,IAAO,OAAA,IAAA,CAAA;AAC9B,EAAO,OAAA,MAAA,CAAO,OAAO,QAAQ,CAAA,CAAA;AAC/B,CAAA;AAEA,SAAS,cACP,QACY,EAAA;AACZ,EAAA,IAAI,QAAa,KAAA,IAAA;AAAM,IAAO,OAAA,IAAA,CAAA;AAC9B,EAAO,OAAA,MAAA,CAAO,OAAO,QAAQ,CAAA,CAAA;AAC/B,CAAA;AAEA,SAAS,iBAAiD,UAAoB,EAAA;AAI5E,EAAM,MAAA,QAAA,GAAWC,gBAAW,CAAA,CAAC,OAAY,KAAA;AACvC,IAAM,MAAA,IAAA,GAAO,QAAQ,UAAU,CAAA,CAAA;AAG/B,IAAA,OAAO,MAAM,KAAS,IAAA,IAAA,CAAA;AAAA,GACvB,CAAA,CAAA;AACD,EAAM,MAAA,QAAA,GAAWA,gBAAW,CAAA,CAAC,OAAY,KAAA;AACvC,IAAM,MAAA,IAAA,GAAO,QAAQ,UAAU,CAAA,CAAA;AAG/B,IAAA,OAAO,MAAM,KAAS,IAAA,IAAA,CAAA;AAAA,GACvB,CAAA,CAAA;AAED,EAAM,MAAA,KAAA,GAAQC,gBAAQ,MAAM,aAAA,CAAiB,QAAQ,CAAG,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAClE,EAAM,MAAA,KAAA,GAAQA,gBAAQ,MAAM,aAAA,CAAiB,QAAQ,CAAG,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAClE,EAAO,OAAA,EAAE,OAAO,KAAM,EAAA,CAAA;AACxB,CAAA;AAqCgB,SAAA,iBAAA,CAId,OAA0C,GAAA,EACmC,EAAA;AAC7E,EAAA,MAAM,UAAUC,gBAAW,EAAA,CAAA;AAC3B,EAAA,MAAM,eAAkB,GAAAF,gBAAA,CAAW,MAAM,IAAI,CAAK,IAAA,KAAA,CAAA;AAGlD,EAAA,MAAM,gBAAgBG,mBAAW,CAAA;AAAA,IAC/B,OAAO,OAAQ,CAAA,KAAA;AAAA,IACf,OAAO,OAAQ,CAAA,KAAA;AAAA,IACf,UAAA,EAAY,QAAQ,UAAc,IAAAC,2BAAA;AAAA,IAClC,QAAA,EAAU,QAAQ,QAAY,IAAA,KAAA;AAAA,GAC/B,CAAA,CAAA;AAGD,EAAM,MAAA,CAAC,iBAAmB,EAAA,iBAAiB,CAAI,GAAAH,eAAA;AAAA,IAC7C,MACE;AAAA,MACEI,4BAAA,CAAqB,aAAc,CAAA,KAAA,EAAO,IAAI,CAAA;AAAA,MAC9CC,4BAAA,CAAqB,aAAc,CAAA,KAAA,EAAO,IAAI,CAAA;AAAA,KAChD;AAAA,IACF,CAAC,aAAa,CAAA;AAAA,GAChB,CAAA;AAEA,EAAA,MAAM,EAAE,KAAO,EAAA,KAAA,EAAU,GAAA,gBAAA,CAAuB,cAAc,UAAU,CAAA,CAAA;AAExE,EAAA,MAAM,aAAgB,GAAAC,iBAAA;AAAA,IACpB,CAAC,EAAE,OAAQ,EAAA,EAAG,OAA6B,KAAA;AACzC,MAAA,MAAM,IAAO,GAAA,OAAA,CAAQ,GAAI,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AAGjD,MAAA,IAAI,CAAC,IAAM,EAAA;AACT,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,gBAAA,CAAiB,SAAS,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA,EAAG,SAAS,iBAAiB,CAAA,CAAA;AAAA,KACzE;AAAA,IACA,CAAC,OAAS,EAAA,aAAA,EAAe,iBAAiB,CAAA;AAAA,GAC5C,CAAA;AAEA,EAAA,MAAM,aAAgB,GAAAA,iBAAA;AAAA,IACpB,CAAC,EAAE,OAAQ,EAAA,EAAG,OAA6B,KAAA;AACzC,MAAA,MAAM,IAAO,GAAA,OAAA,CAAQ,GAAI,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AAGjD,MAAA,IAAI,CAAC,IAAM,EAAA;AACT,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,gBAAA,CAAiB,OAAS,EAAA,IAAA,CAAK,GAAI,CAAA,OAAO,GAAG,iBAAiB,CAAA,CAAA;AAAA,KAChE;AAAA,IACA,CAAC,eAAe,iBAAiB,CAAA;AAAA,GACnC,CAAA;AAEA,EAAA,MAAM,SAAY,GAAAA,iBAAA;AAAA,IAChB,CAAC,EAAE,OAAQ,EAAA,EAAG,UAA2B,KAAA;AACvC,MAAA,MAAM,IAAO,GAAA,OAAA,CAAQ,GAAI,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AAGjD,MAAA,IAAI,CAAC,IAAM,EAAA;AACT,QAAA,OAAA;AAAA,OACF;AAKA,MAAA,MAAM,CAAC,OAAO,CAAA,GAAIC,eAAe,CAAA,UAAA,EAAY,EAAS,CAAA,CAAA;AACtD,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAA,OAAA;AAAA,OACF;AAEA,MAAMC,MAAAA,MAAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AAC9B,MAAM,MAAA,MAAA,GAAS,iBAAkB,CAAA,OAAA,CAAQ,IAAI,CAAA,CAAA;AAC7C,MAAAA,OAAM,GAAI,CAAA,OAAA,CAAQ,IAAIV,gCAAyB,CAAA,OAAA,EAAS,MAAM,CAAC,CAAA,CAAA;AAAA,KACjE;AAAA,IACA,CAAC,aAAc,CAAA,UAAA,EAAY,iBAAiB,CAAA;AAAA,GAC9C,CAAA;AAEA,EAAA,MAAM,QAAW,GAAAQ,iBAAA;AAAA,IACf,CAAC,EAAE,OAAQ,EAAA,EAAG,MAAuC,KAAA;AACnD,MAAA,MAAM,IAAO,GAAA,OAAA,CAAQ,GAAI,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AAGjD,MAAA,IAAI,CAAC,IAAM,EAAA;AACT,QAAA,OAAA;AAAA,OACF;AAEA,MAAM,MAAA,QAAA,GAAW,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AACjC,MAAM,MAAA,QAAA,GAAW,IAAK,CAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AAEjC,MAAW,KAAA,MAAA,IAAA,IAAQ,OAAO,KAAO,EAAA;AAC/B,QAAS,QAAA,CAAA,MAAA,CAAO,KAAK,EAAE,CAAA,CAAA;AAAA,OACzB;AAEA,MAAW,KAAA,MAAA,IAAA,IAAQ,OAAO,KAAO,EAAA;AAC/B,QAAS,QAAA,CAAA,MAAA,CAAO,KAAK,EAAE,CAAA,CAAA;AAAA,OACzB;AAAA,KACF;AAAA,IACA,CAAC,cAAc,UAAU,CAAA;AAAA,GAC3B,CAAA;AAEA,EAAA,MAAM,iBAAoB,GAAAA,iBAAA;AAAA,IACxB,CAAC,EAAE,OAAA,EAAc,KAAA;AAGf,MAAA,IAAI,OAAQ,CAAA,GAAA,CAAI,aAAc,CAAA,UAAU,MAAM,KAAW,CAAA,EAAA;AACvD,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,MAAM,YAAe,GAAA,aAAA,CAAc,KAAO,EAAA,OAAA,IAAW,EAAC,CAAA;AACtD,MAAA,MAAM,YAAe,GAAA,aAAA,CAAc,KAAO,EAAA,OAAA,IAAW,EAAC,CAAA;AAEtD,MAAQ,OAAA,CAAA,GAAA;AAAA,QACN,aAAc,CAAA,UAAA;AAAA,QACd,IAAIG,eAAW,CAAA;AAAA,UACb,OAAO,IAAIC,YAAA;AAAA,YACT,YAAA,CAAa,GAAI,CAAA,CAAC,IAAS,KAAA;AAAA,cACzB,IAAK,CAAA,EAAA;AAAA,cACLb,gCAAyB,CAAA,IAAA,EAAM,iBAAkB,CAAA,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,aAC5D,CAAA;AAAA,WACH;AAAA,UACA,OAAO,IAAIa,YAAA;AAAA,YACT,YAAA,CAAa,GAAI,CAAA,CAAC,IAAS,KAAA;AAAA,cACzB,IAAK,CAAA,EAAA;AAAA,cACLZ,gCAAyB,CAAA,IAAA,EAAM,iBAAkB,CAAA,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,aAC5D,CAAA;AAAA,WACH;AAAA,SACD,CAAA;AAAA,OACH,CAAA;AAAA,KACF;AAAA,IACA,CAAC,aAAe,EAAA,iBAAA,EAAmB,iBAAiB,CAAA;AAAA,GACtD,CAAA;AAEA,EAAAa,iBAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAiB,EAAA;AACnB,MAAQ,OAAA,CAAAC,cAAS,CAAE,CAAA,cAAA,CAAe,MAAM;AACtC,QAAkB,iBAAA,EAAA,CAAA;AAAA,OACnB,CAAA,CAAA;AAAA,KACH;AAAA,GACC,EAAA,CAAC,eAAiB,EAAA,iBAAA,EAAmB,OAAO,CAAC,CAAA,CAAA;AAEhD,EAAA,IAAI,cAAc,QAAU,EAAA;AAE1B,IAA4BC,oCAAA,EAAA,CAAA;AAAA,GAC9B;AAEA,EAAO,OAAA;AAAA,IACL,KAAO,EAAA,aAAA,CAAc,QAAY,GAAA,KAAA,IAAU,WAAuB,GAAA,KAAA;AAAA,IAClE,KAAO,EAAA,aAAA,CAAc,QAAY,GAAA,KAAA,IAAU,WAAuB,GAAA,KAAA;AAAA,IAClE,SAAW,EAAA,aAAA,CAAc,QAAW,GAAA,KAAA,GAAQ,CAAC,eAAA;AAAA,IAC7C,aAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,GACF,CAAA;AACF;;;;"}
package/dist/flow.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"flow.js","sources":["../src/flow.ts"],"sourcesContent":["import type {\n History,\n JsonObject,\n ReadonlyJsonObject,\n Resolve,\n ToJson,\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 buildEdgeConfigCache,\n buildNodeConfigCache,\n DEFAULT_STORAGE_KEY,\n toLiveblocksInternalEdge,\n toLiveblocksInternalNode,\n} 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\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * label: false, // Don't sync node.data.label\n * color: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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 * Each key in the config is either:\n * - `false` - Local-only, not synced to other clients\n * - `\"atomic\"` - Synced as a single value (replaced as-a-whole, not patched)\n * - `true` (or absent) - Deep sync (default, objects/arrays are patched)\n * - `{ ... }` - Nested config, applies recursively to sub-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 * \"*\": {\n * hovered: false, // Don't sync edge.data.hovered\n * style: \"atomic\", // Sync as a single value, replaced as-a-whole\n * },\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) break;\n\n // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.dragging === true) {\n history.pause();\n }\n\n if (change.position !== undefined) {\n const prev = node.get(\"position\");\n if (prev?.x !== change.position.x || prev?.y !== change.position.y) {\n node.set(\"position\", change.position);\n }\n }\n\n if (change.dragging !== undefined) {\n if (change.dragging === false) {\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 // Pause before setting the first position change so it doesn't create a separate undo step.\n if (change.resizing === true) {\n history.pause();\n }\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 === false) {\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// TODO (LB-3665): To support sub-nodes, this function will need to emit nodes\n// in topological order (parents before children), deferring any node with a\n// parentId until its parent has been emitted.\nfunction nodeMapToList<N extends Node>(\n nodesMap: ReadonlyJsonObject | null\n): N[] | null {\n if (nodesMap === null) return null;\n return Object.values(nodesMap) as unknown as N[];\n}\n\nfunction edgeMapToList<E extends Edge>(\n edgesMap: ReadonlyJsonObject | null\n): E[] | null {\n if (edgesMap === null) return null;\n return Object.values(edgesMap) as unknown as E[];\n}\n\nfunction useNodesAndEdges<N extends Node, E extends Edge>(storageKey: string) {\n // Storage already includes local overlays via toJSON(), so no separate local\n // layer is needed. Individual node/edge immutable references are already\n // stable (only change when the underlying LiveObject changes).\n const nodesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.nodes ?? null;\n });\n const edgesMap = useStorage((storage) => {\n const flow = storage[storageKey] as\n | ToJson<InternalLiveblocksFlow>\n | undefined;\n return flow?.edges ?? null;\n });\n\n const nodes = useMemo(() => nodeMapToList<N>(nodesMap), [nodesMap]);\n const edges = useMemo(() => edgeMapToList<E>(edgesMap), [edgesMap]);\n return { nodes, edges };\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 const { nodes, edges } = useNodesAndEdges<N, E>(frozenOptions.storageKey);\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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.cjs","sources":["../src/helpers.ts"],"sourcesContent":["import type { JsonObject, SyncConfig, SyncMode } from \"@liveblocks/core\";\nimport { LiveObject } from \"@liveblocks/core\";\nimport type { Edge, Node } from \"@xyflow/react\";\n\nimport type { InternalLiveblocksEdge, InternalLiveblocksNode } from \"./types\";\n\nexport const DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow specific versions of `SyncConfig` that only allow keys that are actually exposed by React Flow.\ntype NodeSyncConfig = { [K in keyof Node]?: SyncMode };\ntype EdgeSyncConfig = { [K in keyof Edge]?: SyncMode };\n\nexport const NODE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n dragging: false,\n measured: false,\n resizing: false,\n\n // Atomic (synced as plain Json)\n position: \"atomic\",\n sourcePosition: \"atomic\",\n targetPosition: \"atomic\",\n extent: \"atomic\",\n origin: \"atomic\",\n handles: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies NodeSyncConfig;\n\nexport const EDGE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n\n // Atomic (synced as plain Json)\n markerStart: \"atomic\",\n markerEnd: \"atomic\",\n label: \"atomic\",\n labelBgPadding: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies EdgeSyncConfig;\n\n/**\n * Merges a base config with per-type user data configs, returning a lookup\n * function that resolves the full SyncConfig for a given type string.\n */\nexport function buildFlowDataConfigCache(\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 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\nexport function buildNodeConfigCache(\n nodeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);\n}\n\nexport function buildEdgeConfigCache(\n edgeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);\n}\n\nexport function toLiveblocksInternalNode<N extends Node>(\n node: N,\n config: SyncConfig\n): InternalLiveblocksNode {\n return LiveObject.from(\n node as unknown as JsonObject,\n config\n ) as InternalLiveblocksNode;\n}\n\nexport function toLiveblocksInternalEdge<E extends Edge>(\n edge: E,\n config: SyncConfig\n): InternalLiveblocksEdge {\n return LiveObject.from(\n edge as unknown as JsonObject,\n config\n ) as InternalLiveblocksEdge;\n}\n"],"names":["LiveObject"],"mappings":";;;;AAMO,MAAM,mBAAsB,GAAA,OAAA;AAM5B,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,QAAU,EAAA,QAAA;AAAA,EACV,cAAgB,EAAA,QAAA;AAAA,EAChB,cAAgB,EAAA,QAAA;AAAA,EAChB,MAAQ,EAAA,QAAA;AAAA,EACR,MAAQ,EAAA,QAAA;AAAA,EACR,OAAS,EAAA,QAAA;AAAA;AAAA;AAIX,EAAA;AAEO,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,WAAa,EAAA,QAAA;AAAA,EACb,SAAW,EAAA,QAAA;AAAA,EACX,KAAO,EAAA,QAAA;AAAA,EACP,cAAgB,EAAA,QAAA;AAAA;AAAA;AAIlB,EAAA;AAMgB,SAAA,wBAAA,CACd,MACA,IAC0C,EAAA;AAC1C,EAAA,IAAI,CAAC,IAAA;AAAM,IAAA,OAAO,MAAM,IAAA,CAAA;AAExB,EAAM,MAAA,YAAA,GAAe,KAAK,GAAG,CAAA,CAAA;AAC7B,EAAA,MAAM,WAAW,YAAe,GAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,cAAiB,GAAA,IAAA,CAAA;AAGlE,EAAM,MAAA,KAAA,uBAAY,GAAoC,EAAA,CAAA;AACtD,EAAA,KAAA,MAAW,QAAQ,IAAM,EAAA;AACvB,IAAA,IAAI,IAAS,KAAA,GAAA;AAAK,MAAA,SAAA;AAClB,IAAM,MAAA,QAAA,GAAW,KAAK,IAAI,CAAA,CAAA;AAC1B,IAAA,IAAI,CAAC,QAAA;AAAU,MAAA,SAAA;AACf,IAAA,MAAM,UAAyB,GAAA,EAAE,GAAG,YAAA,EAAc,GAAG,QAAS,EAAA,CAAA;AAC9D,IAAA,KAAA,CAAM,IAAI,IAAM,EAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,YAAY,CAAA,CAAA;AAAA,GAC/C;AAEA,EAAA,OAAO,CAAC,IAAA,KAAS,KAAM,CAAA,GAAA,CAAI,IAAI,CAAK,IAAA,QAAA,CAAA;AACtC,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAOA,eAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAOA,eAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.js","sources":["../src/helpers.ts"],"sourcesContent":["import type { JsonObject, SyncConfig, SyncMode } from \"@liveblocks/core\";\nimport { LiveObject } from \"@liveblocks/core\";\nimport type { Edge, Node } from \"@xyflow/react\";\n\nimport type { InternalLiveblocksEdge, InternalLiveblocksNode } from \"./types\";\n\nexport const DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow specific versions of `SyncConfig` that only allow keys that are actually exposed by React Flow.\ntype NodeSyncConfig = { [K in keyof Node]?: SyncMode };\ntype EdgeSyncConfig = { [K in keyof Edge]?: SyncMode };\n\nexport const NODE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n dragging: false,\n measured: false,\n resizing: false,\n\n // Atomic (synced as plain Json)\n position: \"atomic\",\n sourcePosition: \"atomic\",\n targetPosition: \"atomic\",\n extent: \"atomic\",\n origin: \"atomic\",\n handles: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies NodeSyncConfig;\n\nexport const EDGE_BASE_CONFIG = {\n // Local-only (not synced)\n selected: false,\n\n // Atomic (synced as plain Json)\n markerStart: \"atomic\",\n markerEnd: \"atomic\",\n label: \"atomic\",\n labelBgPadding: \"atomic\",\n\n // Note: the `data` key is intentionally left out of this base config, as it\n // is expected to be provided by the end user\n} as const satisfies EdgeSyncConfig;\n\n/**\n * Merges a base config with per-type user data configs, returning a lookup\n * function that resolves the full SyncConfig for a given type string.\n */\nexport function buildFlowDataConfigCache(\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 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\nexport function buildNodeConfigCache(\n nodeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(NODE_BASE_CONFIG, nodeDataConfig);\n}\n\nexport function buildEdgeConfigCache(\n edgeDataConfig?: Record<string, SyncConfig | undefined>\n): (type: string | undefined) => SyncConfig {\n return buildFlowDataConfigCache(EDGE_BASE_CONFIG, edgeDataConfig);\n}\n\nexport function toLiveblocksInternalNode<N extends Node>(\n node: N,\n config: SyncConfig\n): InternalLiveblocksNode {\n return LiveObject.from(\n node as unknown as JsonObject,\n config\n ) as InternalLiveblocksNode;\n}\n\nexport function toLiveblocksInternalEdge<E extends Edge>(\n edge: E,\n config: SyncConfig\n): InternalLiveblocksEdge {\n return LiveObject.from(\n edge as unknown as JsonObject,\n config\n ) as InternalLiveblocksEdge;\n}\n"],"names":[],"mappings":";;AAMO,MAAM,mBAAsB,GAAA,OAAA;AAM5B,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA,EACV,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,QAAU,EAAA,QAAA;AAAA,EACV,cAAgB,EAAA,QAAA;AAAA,EAChB,cAAgB,EAAA,QAAA;AAAA,EAChB,MAAQ,EAAA,QAAA;AAAA,EACR,MAAQ,EAAA,QAAA;AAAA,EACR,OAAS,EAAA,QAAA;AAAA;AAAA;AAIX,EAAA;AAEO,MAAM,gBAAmB,GAAA;AAAA;AAAA,EAE9B,QAAU,EAAA,KAAA;AAAA;AAAA,EAGV,WAAa,EAAA,QAAA;AAAA,EACb,SAAW,EAAA,QAAA;AAAA,EACX,KAAO,EAAA,QAAA;AAAA,EACP,cAAgB,EAAA,QAAA;AAAA;AAAA;AAIlB,EAAA;AAMgB,SAAA,wBAAA,CACd,MACA,IAC0C,EAAA;AAC1C,EAAA,IAAI,CAAC,IAAA;AAAM,IAAA,OAAO,MAAM,IAAA,CAAA;AAExB,EAAM,MAAA,YAAA,GAAe,KAAK,GAAG,CAAA,CAAA;AAC7B,EAAA,MAAM,WAAW,YAAe,GAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,cAAiB,GAAA,IAAA,CAAA;AAGlE,EAAM,MAAA,KAAA,uBAAY,GAAoC,EAAA,CAAA;AACtD,EAAA,KAAA,MAAW,QAAQ,IAAM,EAAA;AACvB,IAAA,IAAI,IAAS,KAAA,GAAA;AAAK,MAAA,SAAA;AAClB,IAAM,MAAA,QAAA,GAAW,KAAK,IAAI,CAAA,CAAA;AAC1B,IAAA,IAAI,CAAC,QAAA;AAAU,MAAA,SAAA;AACf,IAAA,MAAM,UAAyB,GAAA,EAAE,GAAG,YAAA,EAAc,GAAG,QAAS,EAAA,CAAA;AAC9D,IAAA,KAAA,CAAM,IAAI,IAAM,EAAA,EAAE,GAAG,IAAM,EAAA,IAAA,EAAM,YAAY,CAAA,CAAA;AAAA,GAC/C;AAEA,EAAA,OAAO,CAAC,IAAA,KAAS,KAAM,CAAA,GAAA,CAAI,IAAI,CAAK,IAAA,QAAA,CAAA;AACtC,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEO,SAAS,qBACd,cAC0C,EAAA;AAC1C,EAAO,OAAA,wBAAA,CAAyB,kBAAkB,cAAc,CAAA,CAAA;AAClE,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAO,UAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,wBAAA,CACd,MACA,MACwB,EAAA;AACxB,EAAA,OAAO,UAAW,CAAA,IAAA;AAAA,IAChB,IAAA;AAAA,IACA,MAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.cjs","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,YAAA,KAAgB,QAAY,IAAA,aAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-flow\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,yBAAA;AACX,MAAA,WAAA,GAAc,OAAO,YAAA,KAAgB,QAAY,IAAA,aAAA;AACjD,MAAA,UAAA,GAAa,OAAO,WAAA,KAAgB,QAAY,IAAA;;;;"}