@liveblocks/react-flow 3.18.0 → 3.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/flow.cjs +1 -1
- package/dist/lib/flow.cjs.map +1 -1
- package/dist/lib/flow.js +2 -2
- package/dist/lib/flow.js.map +1 -1
- package/dist/lib/version.cjs +1 -1
- package/dist/lib/version.js +1 -1
- package/package.json +6 -6
package/dist/lib/flow.cjs
CHANGED
package/dist/lib/flow.cjs.map
CHANGED
|
@@ -1 +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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"}
|
|
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 { 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.disable(() => {\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","useSuspendUntilStorageReady"],"mappings":"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"}
|
package/dist/lib/flow.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LiveObject, LiveMap
|
|
1
|
+
import { LiveObject, LiveMap } from '@liveblocks/core';
|
|
2
2
|
import { useStorage, useHistory, useMutation } from '@liveblocks/react';
|
|
3
3
|
import { useInitial, useSuspendUntilStorageReady } from '@liveblocks/react/_private';
|
|
4
4
|
import { addEdge } from '@xyflow/react';
|
|
@@ -233,7 +233,7 @@ function useLiveblocksFlow(options = {}) {
|
|
|
233
233
|
);
|
|
234
234
|
useEffect(() => {
|
|
235
235
|
if (isStorageLoaded) {
|
|
236
|
-
history
|
|
236
|
+
history.disable(() => {
|
|
237
237
|
setInitialStorage();
|
|
238
238
|
});
|
|
239
239
|
}
|
package/dist/lib/flow.js.map
CHANGED
|
@@ -1 +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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"}
|
|
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 { 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.disable(() => {\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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"}
|
package/dist/lib/version.cjs
CHANGED
|
@@ -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.
|
|
4
|
+
const PKG_VERSION = typeof "3.18.2" === "string" && "3.18.2";
|
|
5
5
|
const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
|
|
6
6
|
|
|
7
7
|
exports.PKG_FORMAT = PKG_FORMAT;
|
package/dist/lib/version.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PKG_NAME = "@liveblocks/react-flow";
|
|
2
|
-
const PKG_VERSION = typeof "3.18.
|
|
2
|
+
const PKG_VERSION = typeof "3.18.2" === "string" && "3.18.2";
|
|
3
3
|
const PKG_FORMAT = typeof TSUP_FORMAT === "string" && TSUP_FORMAT;
|
|
4
4
|
|
|
5
5
|
export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react-flow",
|
|
3
|
-
"version": "3.18.
|
|
3
|
+
"version": "3.18.2",
|
|
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.",
|
|
@@ -59,14 +59,14 @@
|
|
|
59
59
|
"lint": "eslint src/ && stylelint src/styles/",
|
|
60
60
|
"test": "npx liveblocks dev -p 1154 -c 'vitest run --coverage'",
|
|
61
61
|
"test:ci": "vitest run",
|
|
62
|
-
"test:types": "
|
|
62
|
+
"test:types": "vitest run --config ./vitest.config.typecheck.ts",
|
|
63
63
|
"test:watch": "vitest"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@liveblocks/client": "3.18.
|
|
67
|
-
"@liveblocks/core": "3.18.
|
|
68
|
-
"@liveblocks/react": "3.18.
|
|
69
|
-
"@liveblocks/react-ui": "3.18.
|
|
66
|
+
"@liveblocks/client": "3.18.2",
|
|
67
|
+
"@liveblocks/core": "3.18.2",
|
|
68
|
+
"@liveblocks/react": "3.18.2",
|
|
69
|
+
"@liveblocks/react-ui": "3.18.2"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@xyflow/react": "^12",
|