@liveblocks/react-flow 0.0.0 → 3.16.0-flow1
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/README.md +6 -0
- package/dist/cursors.cjs +148 -0
- package/dist/cursors.cjs.map +1 -0
- package/dist/cursors.js +146 -0
- package/dist/cursors.js.map +1 -0
- package/dist/flow.cjs +332 -0
- package/dist/flow.cjs.map +1 -0
- package/dist/flow.js +328 -0
- package/dist/flow.js.map +1 -0
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +150 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/suspense.cjs +13 -0
- package/dist/suspense.cjs.map +1 -0
- package/dist/suspense.d.cts +149 -0
- package/dist/suspense.d.ts +149 -0
- package/dist/suspense.js +7 -0
- package/dist/suspense.js.map +1 -0
- package/dist/version.cjs +10 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +116 -2
- package/src/styles/index.css +12 -0
- package/styles.css +1 -0
- package/styles.css.d.cts +1 -0
- package/styles.css.d.ts +1 -0
- package/styles.css.map +1 -0
- package/suspense/README.md +5 -0
- package/suspense/package.json +4 -0
- package/index.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.cjs","sources":["../src/flow.ts"],"sourcesContent":["import {\n type DistributiveOmit,\n type JsonObject,\n LiveMap,\n LiveObject,\n type LsonObject,\n type Resolve,\n shallow,\n Signal,\n type ToImmutable,\n} from \"@liveblocks/core\";\nimport { useMutation, useStorage } from \"@liveblocks/react\";\nimport {\n useInitial,\n useSignal,\n useSuspendUntilStorageReady,\n} from \"@liveblocks/react/_private\";\nimport {\n addEdge as defaultAddEdge,\n type Connection,\n type Edge,\n type EdgeChange,\n type Node,\n type NodeChange,\n type OnConnect,\n type OnEdgesChange,\n type OnNodesChange,\n} from \"@xyflow/react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nconst DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow `Node` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst NODE_LOCAL_KEYS = [\n \"selected\",\n \"dragging\",\n \"measured\",\n \"resizing\",\n] as const satisfies (keyof Node)[number][];\n\n// React Flow `Edge` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst EDGE_LOCAL_KEYS = [\"selected\"] as const satisfies (keyof Edge)[number][];\n\nconst EMPTY_ARRAY = [] as unknown[];\n\nexport type SerializableNode = Node<JsonObject>;\nexport type SerializableEdge = Edge<JsonObject>;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Node`.\n *\n * It doesn't include local-only properties.\n * The entire node and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksNode<TNode extends SerializableNode = SerializableNode> =\n LiveObject<\n DistributiveOmit<TNode, (typeof NODE_LOCAL_KEYS)[number] | \"data\"> & {\n data: LiveObject<TNode[\"data\"]>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Edge`.\n *\n * It doesn't include local-only properties.\n * The entire edge and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksEdge<TEdge extends SerializableEdge = SerializableEdge> =\n LiveObject<\n DistributiveOmit<TEdge, (typeof EDGE_LOCAL_KEYS)[number] | \"data\"> & {\n data?: LiveObject<NonNullable<TEdge[\"data\"]>>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow diagram made of nodes and edges.\n *\n * Nodes and edges are stored as `LiveMap`s keyed by their IDs, enabling\n * fine-grained conflict-free updates from multiple clients simultaneously.\n */\nexport type LiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = LiveObject<{\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n}>;\n\ntype LocalNodes = Partial<Record<(typeof NODE_LOCAL_KEYS)[number], unknown>>;\ntype LocalEdges = Partial<Record<(typeof EDGE_LOCAL_KEYS)[number], unknown>>;\n\ntype UseLiveblocksFlowResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Resolve<\n (\n | {\n nodes: null;\n edges: null;\n isLoading: true;\n }\n | {\n nodes: TNode[];\n edges: TEdge[];\n isLoading: false;\n }\n ) & {\n onNodesChange: OnNodesChange<TNode>;\n onEdgesChange: OnEdgesChange<TEdge>;\n onConnect: OnConnect;\n }\n>;\n\ntype LiveblocksFlowSuspenseResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Extract<UseLiveblocksFlowResult<TNode, TEdge>, { isLoading: false }>;\n\ntype UseLiveblocksFlowOptions<\n TNode extends SerializableNode,\n TEdge extends SerializableEdge,\n> = {\n /**\n * The initial React Flow nodes and edges.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * initial: {\n * nodes: [\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ],\n * edges: [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ],\n * },\n * });\n * ```\n *\n * This is equivalent to setting `initialStorage` on `RoomProvider`.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow([\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ], [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ]),\n * }}\n * />\n * ```\n */\n initial?: {\n nodes?: TNode[];\n edges?: TEdge[];\n };\n\n /**\n * The key used to store the React Flow diagram in Liveblocks Storage.\n *\n * Defaults to `\"flow\"`.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * storageKey: \"myDiagram\",\n * });\n * ```\n */\n storageKey?: string;\n};\n\nfunction pick<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Partial<Record<K, unknown>> {\n const result: Partial<Record<K, unknown>> = {};\n\n for (const key of keys) {\n const value = (from as Record<PropertyKey, unknown>)[key];\n\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction omit<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Omit<T, Extract<K, keyof T>> {\n const result = { ...from } as Partial<T>;\n\n for (const key of keys) {\n delete (result as Record<PropertyKey, unknown>)[key];\n }\n\n return result as Omit<T, Extract<K, keyof T>>;\n}\n\nfunction reconcile<T extends { id: string }>(cache: Map<string, T>, next: T) {\n const previous = cache.get(next.id);\n\n if (previous && shallow(previous, next)) {\n return previous;\n }\n\n cache.set(next.id, next);\n\n return next;\n}\n\nfunction merge<T extends { id: string }, L extends object>(\n cache: Map<string, T>,\n remote: ReadonlyMap<string, T>,\n local: Map<string, L>\n): T[] {\n // Prune cached items that were deleted remotely.\n for (const id of cache.keys()) {\n if (!remote.has(id)) {\n cache.delete(id);\n }\n }\n\n // Prune local items that were deleted remotely.\n for (const id of local.keys()) {\n if (!remote.has(id)) {\n local.delete(id);\n }\n }\n\n // Reconcile remote and local items.\n return Array.from(remote.values(), (item) => {\n const localItem = local.get(item.id);\n\n return reconcile(\n cache,\n localItem ? (Object.assign({}, item, localItem) as T) : item\n );\n });\n}\n\nfunction updateLocalState<T extends object>(\n map: Map<string, T>,\n key: string,\n changes: T\n): boolean {\n const next: Record<string, unknown> = {};\n\n for (const change in changes) {\n const value = (changes as Record<string, unknown>)[change];\n\n // `false` values aren't stored.\n if (value !== undefined && value !== false) {\n next[change] = value;\n }\n }\n\n if (Object.keys(next).length > 0) {\n map.set(key, next as T);\n\n return true;\n } else {\n const hasItem = map.has(key);\n map.delete(key);\n\n return hasItem;\n }\n}\n\n// Converts a React Flow `Node` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction nodeToStorage<TNode extends SerializableNode>(\n node: TNode\n): LiveblocksNode<TNode> {\n const { data, ...rest } = omit(node, NODE_LOCAL_KEYS) as TNode;\n\n return new LiveObject({\n ...(rest as LsonObject),\n data: new LiveObject(data as LsonObject),\n }) as LiveblocksNode<TNode>;\n}\n\n// Converts a React Flow `Edge` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction edgeToStorage<TEdge extends SerializableEdge>(\n edge: TEdge\n): LiveblocksEdge<TEdge> {\n const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS) as TEdge;\n\n return new LiveObject({\n ...(rest as LsonObject),\n\n // `data` is optional on edges.\n data: data === undefined ? undefined : new LiveObject(data as LsonObject),\n }) as LiveblocksEdge<TEdge>;\n}\n\n// Similar to React Flow's `applyNodeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-node-changes\nfunction applyNodeChanges<TNode extends SerializableNode>(args: {\n changes: NodeChange<TNode>[];\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n nextLocal: Map<string, Partial<LocalNodes>>;\n nodeCache: Map<string, TNode>;\n}): boolean {\n const { changes, nodes, nextLocal, nodeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n nodes.set(change.item.id, nodeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, NODE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n nodes.delete(change.id);\n nodeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"position\": {\n const node = nodes.get(change.id);\n\n if (!node || !change.position) {\n break;\n }\n\n const previous = node.get(\"position\") as TNode[\"position\"] | undefined;\n\n if (\n previous?.x !== change.position.x ||\n previous?.y !== change.position.y\n ) {\n node.set(\"position\", change.position);\n }\n\n if (change.dragging !== undefined) {\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n dragging: change.dragging,\n });\n hasLocalChanged = true;\n }\n\n break;\n }\n\n case \"dimensions\": {\n const node = nodes.get(change.id);\n const patch: Partial<LocalNodes> = {\n ...nextLocal.get(change.id),\n };\n\n if (\n node &&\n change.dimensions !== undefined &&\n change.setAttributes !== undefined\n ) {\n if (\n change.setAttributes === true ||\n change.setAttributes === \"width\"\n ) {\n node.set(\"width\", change.dimensions.width);\n }\n\n if (\n change.setAttributes === true ||\n change.setAttributes === \"height\"\n ) {\n node.set(\"height\", change.dimensions.height);\n }\n }\n\n if (change.dimensions !== undefined) {\n patch.measured = change.dimensions;\n }\n\n if (change.resizing !== undefined) {\n patch.resizing = change.resizing;\n }\n\n updateLocalState(nextLocal, change.id, patch);\n hasLocalChanged = true;\n break;\n }\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n// Similar to React Flow's `applyEdgeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-edge-changes\nfunction applyEdgeChanges<TEdge extends SerializableEdge>(args: {\n changes: EdgeChange<TEdge>[];\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n nextLocal: Map<string, Partial<LocalEdges>>;\n edgeCache: Map<string, TEdge>;\n}): boolean {\n const { changes, edges, nextLocal, edgeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n edges.set(change.item.id, edgeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, EDGE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n edges.delete(change.id);\n edgeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n/**\n * Creates a Liveblocks Storage representation of a React Flow diagram from nodes and edges.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow(initialNodes, initialEdges),\n * }}\n * />\n * ```\n */\nexport function createLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(nodes: TNode[] = [], edges: TEdge[] = []): LiveblocksFlow<TNode, TEdge> {\n return new LiveObject({\n nodes: new LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),\n edges: new LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)])),\n }) as LiveblocksFlow<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect, isLoading } = useLiveblocksFlow();\n *\n * if (isLoading) {\n * return <div>Loading…</div>\n * }\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<UseLiveblocksFlowResult<TNode, TEdge>> {\n type TFlow = LiveblocksFlow<TNode, TEdge>;\n type TImmutableFlow = ToImmutable<LiveblocksFlow<TNode, TEdge>>;\n\n const isStorageLoaded = useStorage(() => true) ?? false;\n\n // These options are not reactive, only their initial values are used.\n const frozenOptions = useInitial({\n initial: options.initial,\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n });\n\n // Used to reconcile state changes with stable object references when the changes\n // are shallowly equal, preventing React Flow from re-rendering unchanged nodes and edges.\n const nodeCache = useRef<Map<string, TNode>>(new Map());\n const edgeCache = useRef<Map<string, TEdge>>(new Map());\n\n // Local-only state lives in signals.\n const [localNodesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalNodes>>())\n );\n const [localEdgesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalEdges>>())\n );\n const localNodes = useSignal(localNodesΣ);\n const localEdges = useSignal(localEdgesΣ);\n\n // Remote state lives in Liveblocks Storage.\n const remoteNodesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.nodes ?? null) as ReadonlyMap<string, TNode> | null;\n });\n const remoteEdgesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.edges ?? null) as ReadonlyMap<string, TEdge> | null;\n });\n\n // Merge remote and local layers to get the final state.\n const nodes = useMemo(\n () =>\n remoteNodesMap\n ? merge(nodeCache.current, remoteNodesMap, localNodes)\n : null,\n [remoteNodesMap, localNodes]\n );\n const edges = useMemo(\n () =>\n remoteEdgesMap\n ? merge(edgeCache.current, remoteEdgesMap, localEdges)\n : null,\n [remoteEdgesMap, localEdges]\n );\n\n const onNodesChange = useMutation(\n ({ storage }, changes: NodeChange<TNode>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localNodesΣ.get());\n const hasLocalChanged = applyNodeChanges({\n changes,\n nodes: flow.get(\"nodes\"),\n nextLocal,\n nodeCache: nodeCache.current,\n });\n\n if (hasLocalChanged) {\n localNodesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onEdgesChange = useMutation(\n ({ storage }, changes: EdgeChange<TEdge>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localEdgesΣ.get());\n const hasLocalChanged = applyEdgeChanges({\n changes,\n edges: flow.get(\"edges\"),\n nextLocal,\n edgeCache: edgeCache.current,\n });\n\n if (hasLocalChanged) {\n localEdgesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onConnect = useMutation(({ storage }, connection: Connection) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const edges = flow.get(\"edges\");\n\n // Check for duplicate connections.\n for (const edge of edges.values()) {\n if (\n edge.get(\"source\") === connection.source &&\n edge.get(\"target\") === connection.target &&\n (edge.get(\"sourceHandle\") ?? null) ===\n (connection.sourceHandle ?? null) &&\n (edge.get(\"targetHandle\") ?? null) === (connection.targetHandle ?? null)\n ) {\n return;\n }\n }\n\n // Delegate to React Flow's own `addEdge` helper for consistent default\n // edge ID generation, passing an empty array since de-duplication is\n // already handled above.\n const [newEdge] = defaultAddEdge(connection, [] as TEdge[]);\n\n if (!newEdge) {\n return;\n }\n\n edges.set(newEdge.id, edgeToStorage(newEdge));\n }, []);\n\n const setInitialStorage = useMutation(({ storage }) => {\n // Similarly to `initialStorage` on `Client.enterRoom` and `RoomProvider`, we only\n // initialize Storage if it doesn't already exist.\n if (storage.get(frozenOptions.storageKey) !== undefined) {\n return;\n }\n\n const { nodes: initialNodes = [], edges: initialEdges = [] } =\n frozenOptions.initial ?? {};\n\n storage.set(\n frozenOptions.storageKey,\n createLiveblocksFlow(initialNodes, initialEdges)\n );\n }, []);\n\n useEffect(() => {\n if (isStorageLoaded) {\n setInitialStorage();\n }\n }, [isStorageLoaded, setInitialStorage]);\n\n return {\n nodes,\n edges,\n isLoading: !isStorageLoaded,\n onNodesChange,\n onEdgesChange,\n onConnect,\n } as UseLiveblocksFlowResult<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useLiveblocksFlow();\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlowSuspense<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<LiveblocksFlowSuspenseResult<TNode, TEdge>> {\n const result = useLiveblocksFlow<TNode, TEdge>(options);\n\n useSuspendUntilStorageReady();\n\n return {\n ...result,\n nodes: result.nodes ?? (EMPTY_ARRAY as TNode[]),\n edges: result.edges ?? (EMPTY_ARRAY as TEdge[]),\n isLoading: false,\n };\n}\n"],"names":["shallow","LiveObject","LiveMap","useStorage","useInitial","useRef","useState","Signal","useSignal","useMemo","useMutation","edges","defaultAddEdge","useEffect","useSuspendUntilStorageReady"],"mappings":"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"}
|
package/dist/flow.js
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { shallow, LiveObject, LiveMap, Signal } from '@liveblocks/core';
|
|
2
|
+
import { useStorage, useMutation } from '@liveblocks/react';
|
|
3
|
+
import { useInitial, useSignal, useSuspendUntilStorageReady } from '@liveblocks/react/_private';
|
|
4
|
+
import { addEdge } from '@xyflow/react';
|
|
5
|
+
import { useRef, useState, useMemo, useEffect } from 'react';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_STORAGE_KEY = "flow";
|
|
8
|
+
const NODE_LOCAL_KEYS = [
|
|
9
|
+
"selected",
|
|
10
|
+
"dragging",
|
|
11
|
+
"measured",
|
|
12
|
+
"resizing"
|
|
13
|
+
];
|
|
14
|
+
const EDGE_LOCAL_KEYS = ["selected"];
|
|
15
|
+
const EMPTY_ARRAY = [];
|
|
16
|
+
function pick(from, keys) {
|
|
17
|
+
const result = {};
|
|
18
|
+
for (const key of keys) {
|
|
19
|
+
const value = from[key];
|
|
20
|
+
if (value !== void 0 && value !== null) {
|
|
21
|
+
result[key] = value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
function omit(from, keys) {
|
|
27
|
+
const result = { ...from };
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
delete result[key];
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function reconcile(cache, next) {
|
|
34
|
+
const previous = cache.get(next.id);
|
|
35
|
+
if (previous && shallow(previous, next)) {
|
|
36
|
+
return previous;
|
|
37
|
+
}
|
|
38
|
+
cache.set(next.id, next);
|
|
39
|
+
return next;
|
|
40
|
+
}
|
|
41
|
+
function merge(cache, remote, local) {
|
|
42
|
+
for (const id of cache.keys()) {
|
|
43
|
+
if (!remote.has(id)) {
|
|
44
|
+
cache.delete(id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const id of local.keys()) {
|
|
48
|
+
if (!remote.has(id)) {
|
|
49
|
+
local.delete(id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return Array.from(remote.values(), (item) => {
|
|
53
|
+
const localItem = local.get(item.id);
|
|
54
|
+
return reconcile(
|
|
55
|
+
cache,
|
|
56
|
+
localItem ? Object.assign({}, item, localItem) : item
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function updateLocalState(map, key, changes) {
|
|
61
|
+
const next = {};
|
|
62
|
+
for (const change in changes) {
|
|
63
|
+
const value = changes[change];
|
|
64
|
+
if (value !== void 0 && value !== false) {
|
|
65
|
+
next[change] = value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (Object.keys(next).length > 0) {
|
|
69
|
+
map.set(key, next);
|
|
70
|
+
return true;
|
|
71
|
+
} else {
|
|
72
|
+
const hasItem = map.has(key);
|
|
73
|
+
map.delete(key);
|
|
74
|
+
return hasItem;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function nodeToStorage(node) {
|
|
78
|
+
const { data, ...rest } = omit(node, NODE_LOCAL_KEYS);
|
|
79
|
+
return new LiveObject({
|
|
80
|
+
...rest,
|
|
81
|
+
data: new LiveObject(data)
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function edgeToStorage(edge) {
|
|
85
|
+
const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS);
|
|
86
|
+
return new LiveObject({
|
|
87
|
+
...rest,
|
|
88
|
+
// `data` is optional on edges.
|
|
89
|
+
data: data === void 0 ? void 0 : new LiveObject(data)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function applyNodeChanges(args) {
|
|
93
|
+
const { changes, nodes, nextLocal, nodeCache } = args;
|
|
94
|
+
let hasLocalChanged = false;
|
|
95
|
+
for (const change of changes) {
|
|
96
|
+
switch (change.type) {
|
|
97
|
+
case "add":
|
|
98
|
+
case "replace":
|
|
99
|
+
nodes.set(change.item.id, nodeToStorage(change.item));
|
|
100
|
+
if (updateLocalState(
|
|
101
|
+
nextLocal,
|
|
102
|
+
change.item.id,
|
|
103
|
+
pick(change.item, NODE_LOCAL_KEYS)
|
|
104
|
+
)) {
|
|
105
|
+
hasLocalChanged = true;
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
case "remove":
|
|
109
|
+
nodes.delete(change.id);
|
|
110
|
+
nodeCache.delete(change.id);
|
|
111
|
+
nextLocal.delete(change.id);
|
|
112
|
+
hasLocalChanged = true;
|
|
113
|
+
break;
|
|
114
|
+
case "position": {
|
|
115
|
+
const node = nodes.get(change.id);
|
|
116
|
+
if (!node || !change.position) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
const previous = node.get("position");
|
|
120
|
+
if (previous?.x !== change.position.x || previous?.y !== change.position.y) {
|
|
121
|
+
node.set("position", change.position);
|
|
122
|
+
}
|
|
123
|
+
if (change.dragging !== void 0) {
|
|
124
|
+
updateLocalState(nextLocal, change.id, {
|
|
125
|
+
...nextLocal.get(change.id),
|
|
126
|
+
dragging: change.dragging
|
|
127
|
+
});
|
|
128
|
+
hasLocalChanged = true;
|
|
129
|
+
}
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case "dimensions": {
|
|
133
|
+
const node = nodes.get(change.id);
|
|
134
|
+
const patch = {
|
|
135
|
+
...nextLocal.get(change.id)
|
|
136
|
+
};
|
|
137
|
+
if (node && change.dimensions !== void 0 && change.setAttributes !== void 0) {
|
|
138
|
+
if (change.setAttributes === true || change.setAttributes === "width") {
|
|
139
|
+
node.set("width", change.dimensions.width);
|
|
140
|
+
}
|
|
141
|
+
if (change.setAttributes === true || change.setAttributes === "height") {
|
|
142
|
+
node.set("height", change.dimensions.height);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (change.dimensions !== void 0) {
|
|
146
|
+
patch.measured = change.dimensions;
|
|
147
|
+
}
|
|
148
|
+
if (change.resizing !== void 0) {
|
|
149
|
+
patch.resizing = change.resizing;
|
|
150
|
+
}
|
|
151
|
+
updateLocalState(nextLocal, change.id, patch);
|
|
152
|
+
hasLocalChanged = true;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "select":
|
|
156
|
+
updateLocalState(nextLocal, change.id, {
|
|
157
|
+
...nextLocal.get(change.id),
|
|
158
|
+
selected: change.selected
|
|
159
|
+
});
|
|
160
|
+
hasLocalChanged = true;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return hasLocalChanged;
|
|
165
|
+
}
|
|
166
|
+
function applyEdgeChanges(args) {
|
|
167
|
+
const { changes, edges, nextLocal, edgeCache } = args;
|
|
168
|
+
let hasLocalChanged = false;
|
|
169
|
+
for (const change of changes) {
|
|
170
|
+
switch (change.type) {
|
|
171
|
+
case "add":
|
|
172
|
+
case "replace":
|
|
173
|
+
edges.set(change.item.id, edgeToStorage(change.item));
|
|
174
|
+
if (updateLocalState(
|
|
175
|
+
nextLocal,
|
|
176
|
+
change.item.id,
|
|
177
|
+
pick(change.item, EDGE_LOCAL_KEYS)
|
|
178
|
+
)) {
|
|
179
|
+
hasLocalChanged = true;
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
case "remove":
|
|
183
|
+
edges.delete(change.id);
|
|
184
|
+
edgeCache.delete(change.id);
|
|
185
|
+
nextLocal.delete(change.id);
|
|
186
|
+
hasLocalChanged = true;
|
|
187
|
+
break;
|
|
188
|
+
case "select":
|
|
189
|
+
updateLocalState(nextLocal, change.id, {
|
|
190
|
+
...nextLocal.get(change.id),
|
|
191
|
+
selected: change.selected
|
|
192
|
+
});
|
|
193
|
+
hasLocalChanged = true;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return hasLocalChanged;
|
|
198
|
+
}
|
|
199
|
+
function createLiveblocksFlow(nodes = [], edges = []) {
|
|
200
|
+
return new LiveObject({
|
|
201
|
+
nodes: new LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),
|
|
202
|
+
edges: new LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)]))
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
function useLiveblocksFlow(options = {}) {
|
|
206
|
+
const isStorageLoaded = useStorage(() => true) ?? false;
|
|
207
|
+
const frozenOptions = useInitial({
|
|
208
|
+
initial: options.initial,
|
|
209
|
+
storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY
|
|
210
|
+
});
|
|
211
|
+
const nodeCache = useRef(/* @__PURE__ */ new Map());
|
|
212
|
+
const edgeCache = useRef(/* @__PURE__ */ new Map());
|
|
213
|
+
const [localNodes\u03A3] = useState(
|
|
214
|
+
() => new Signal(/* @__PURE__ */ new Map())
|
|
215
|
+
);
|
|
216
|
+
const [localEdges\u03A3] = useState(
|
|
217
|
+
() => new Signal(/* @__PURE__ */ new Map())
|
|
218
|
+
);
|
|
219
|
+
const localNodes = useSignal(localNodes\u03A3);
|
|
220
|
+
const localEdges = useSignal(localEdges\u03A3);
|
|
221
|
+
const remoteNodesMap = useStorage((storage) => {
|
|
222
|
+
const flow = storage[frozenOptions.storageKey];
|
|
223
|
+
return flow?.nodes ?? null;
|
|
224
|
+
});
|
|
225
|
+
const remoteEdgesMap = useStorage((storage) => {
|
|
226
|
+
const flow = storage[frozenOptions.storageKey];
|
|
227
|
+
return flow?.edges ?? null;
|
|
228
|
+
});
|
|
229
|
+
const nodes = useMemo(
|
|
230
|
+
() => remoteNodesMap ? merge(nodeCache.current, remoteNodesMap, localNodes) : null,
|
|
231
|
+
[remoteNodesMap, localNodes]
|
|
232
|
+
);
|
|
233
|
+
const edges = useMemo(
|
|
234
|
+
() => remoteEdgesMap ? merge(edgeCache.current, remoteEdgesMap, localEdges) : null,
|
|
235
|
+
[remoteEdgesMap, localEdges]
|
|
236
|
+
);
|
|
237
|
+
const onNodesChange = useMutation(
|
|
238
|
+
({ storage }, changes) => {
|
|
239
|
+
const flow = storage.get(frozenOptions.storageKey);
|
|
240
|
+
if (!flow) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const nextLocal = new Map(localNodes\u03A3.get());
|
|
244
|
+
const hasLocalChanged = applyNodeChanges({
|
|
245
|
+
changes,
|
|
246
|
+
nodes: flow.get("nodes"),
|
|
247
|
+
nextLocal,
|
|
248
|
+
nodeCache: nodeCache.current
|
|
249
|
+
});
|
|
250
|
+
if (hasLocalChanged) {
|
|
251
|
+
localNodes\u03A3.set(nextLocal);
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
[]
|
|
255
|
+
);
|
|
256
|
+
const onEdgesChange = useMutation(
|
|
257
|
+
({ storage }, changes) => {
|
|
258
|
+
const flow = storage.get(frozenOptions.storageKey);
|
|
259
|
+
if (!flow) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const nextLocal = new Map(localEdges\u03A3.get());
|
|
263
|
+
const hasLocalChanged = applyEdgeChanges({
|
|
264
|
+
changes,
|
|
265
|
+
edges: flow.get("edges"),
|
|
266
|
+
nextLocal,
|
|
267
|
+
edgeCache: edgeCache.current
|
|
268
|
+
});
|
|
269
|
+
if (hasLocalChanged) {
|
|
270
|
+
localEdges\u03A3.set(nextLocal);
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
[]
|
|
274
|
+
);
|
|
275
|
+
const onConnect = useMutation(({ storage }, connection) => {
|
|
276
|
+
const flow = storage.get(frozenOptions.storageKey);
|
|
277
|
+
if (!flow) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const edges2 = flow.get("edges");
|
|
281
|
+
for (const edge of edges2.values()) {
|
|
282
|
+
if (edge.get("source") === connection.source && edge.get("target") === connection.target && (edge.get("sourceHandle") ?? null) === (connection.sourceHandle ?? null) && (edge.get("targetHandle") ?? null) === (connection.targetHandle ?? null)) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const [newEdge] = addEdge(connection, []);
|
|
287
|
+
if (!newEdge) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
edges2.set(newEdge.id, edgeToStorage(newEdge));
|
|
291
|
+
}, []);
|
|
292
|
+
const setInitialStorage = useMutation(({ storage }) => {
|
|
293
|
+
if (storage.get(frozenOptions.storageKey) !== void 0) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const { nodes: initialNodes = [], edges: initialEdges = [] } = frozenOptions.initial ?? {};
|
|
297
|
+
storage.set(
|
|
298
|
+
frozenOptions.storageKey,
|
|
299
|
+
createLiveblocksFlow(initialNodes, initialEdges)
|
|
300
|
+
);
|
|
301
|
+
}, []);
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
if (isStorageLoaded) {
|
|
304
|
+
setInitialStorage();
|
|
305
|
+
}
|
|
306
|
+
}, [isStorageLoaded, setInitialStorage]);
|
|
307
|
+
return {
|
|
308
|
+
nodes,
|
|
309
|
+
edges,
|
|
310
|
+
isLoading: !isStorageLoaded,
|
|
311
|
+
onNodesChange,
|
|
312
|
+
onEdgesChange,
|
|
313
|
+
onConnect
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function useLiveblocksFlowSuspense(options = {}) {
|
|
317
|
+
const result = useLiveblocksFlow(options);
|
|
318
|
+
useSuspendUntilStorageReady();
|
|
319
|
+
return {
|
|
320
|
+
...result,
|
|
321
|
+
nodes: result.nodes ?? EMPTY_ARRAY,
|
|
322
|
+
edges: result.edges ?? EMPTY_ARRAY,
|
|
323
|
+
isLoading: false
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export { createLiveblocksFlow, useLiveblocksFlow, useLiveblocksFlowSuspense };
|
|
328
|
+
//# sourceMappingURL=flow.js.map
|
package/dist/flow.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sources":["../src/flow.ts"],"sourcesContent":["import {\n type DistributiveOmit,\n type JsonObject,\n LiveMap,\n LiveObject,\n type LsonObject,\n type Resolve,\n shallow,\n Signal,\n type ToImmutable,\n} from \"@liveblocks/core\";\nimport { useMutation, useStorage } from \"@liveblocks/react\";\nimport {\n useInitial,\n useSignal,\n useSuspendUntilStorageReady,\n} from \"@liveblocks/react/_private\";\nimport {\n addEdge as defaultAddEdge,\n type Connection,\n type Edge,\n type EdgeChange,\n type Node,\n type NodeChange,\n type OnConnect,\n type OnEdgesChange,\n type OnNodesChange,\n} from \"@xyflow/react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nconst DEFAULT_STORAGE_KEY = \"flow\";\n\n// React Flow `Node` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst NODE_LOCAL_KEYS = [\n \"selected\",\n \"dragging\",\n \"measured\",\n \"resizing\",\n] as const satisfies (keyof Node)[number][];\n\n// React Flow `Edge` properties that are purely ephemeral and local to each client\n// instead of being written to Liveblocks Storage.\nconst EDGE_LOCAL_KEYS = [\"selected\"] as const satisfies (keyof Edge)[number][];\n\nconst EMPTY_ARRAY = [] as unknown[];\n\nexport type SerializableNode = Node<JsonObject>;\nexport type SerializableEdge = Edge<JsonObject>;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Node`.\n *\n * It doesn't include local-only properties.\n * The entire node and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksNode<TNode extends SerializableNode = SerializableNode> =\n LiveObject<\n DistributiveOmit<TNode, (typeof NODE_LOCAL_KEYS)[number] | \"data\"> & {\n data: LiveObject<TNode[\"data\"]>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow `Edge`.\n *\n * It doesn't include local-only properties.\n * The entire edge and its `data` property are both stored as `LiveObject`s.\n */\nexport type LiveblocksEdge<TEdge extends SerializableEdge = SerializableEdge> =\n LiveObject<\n DistributiveOmit<TEdge, (typeof EDGE_LOCAL_KEYS)[number] | \"data\"> & {\n data?: LiveObject<NonNullable<TEdge[\"data\"]>>;\n } & LsonObject\n >;\n\n/**\n * The Liveblocks Storage representation of a React Flow diagram made of nodes and edges.\n *\n * Nodes and edges are stored as `LiveMap`s keyed by their IDs, enabling\n * fine-grained conflict-free updates from multiple clients simultaneously.\n */\nexport type LiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = LiveObject<{\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n}>;\n\ntype LocalNodes = Partial<Record<(typeof NODE_LOCAL_KEYS)[number], unknown>>;\ntype LocalEdges = Partial<Record<(typeof EDGE_LOCAL_KEYS)[number], unknown>>;\n\ntype UseLiveblocksFlowResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Resolve<\n (\n | {\n nodes: null;\n edges: null;\n isLoading: true;\n }\n | {\n nodes: TNode[];\n edges: TEdge[];\n isLoading: false;\n }\n ) & {\n onNodesChange: OnNodesChange<TNode>;\n onEdgesChange: OnEdgesChange<TEdge>;\n onConnect: OnConnect;\n }\n>;\n\ntype LiveblocksFlowSuspenseResult<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n> = Extract<UseLiveblocksFlowResult<TNode, TEdge>, { isLoading: false }>;\n\ntype UseLiveblocksFlowOptions<\n TNode extends SerializableNode,\n TEdge extends SerializableEdge,\n> = {\n /**\n * The initial React Flow nodes and edges.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * initial: {\n * nodes: [\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ],\n * edges: [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ],\n * },\n * });\n * ```\n *\n * This is equivalent to setting `initialStorage` on `RoomProvider`.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow([\n * { id: \"1\", position: { x: 0, y: 0 }, data: { label: \"Node 1\" } },\n * { id: \"2\", position: { x: 0, y: 100 }, data: { label: \"Node 2\" } },\n * ], [\n * { id: \"1-2\", source: \"1\", target: \"2\" },\n * ]),\n * }}\n * />\n * ```\n */\n initial?: {\n nodes?: TNode[];\n edges?: TEdge[];\n };\n\n /**\n * The key used to store the React Flow diagram in Liveblocks Storage.\n *\n * Defaults to `\"flow\"`.\n *\n * @example\n * ```tsx\n * const { ... } = useLiveblocksFlow({\n * storageKey: \"myDiagram\",\n * });\n * ```\n */\n storageKey?: string;\n};\n\nfunction pick<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Partial<Record<K, unknown>> {\n const result: Partial<Record<K, unknown>> = {};\n\n for (const key of keys) {\n const value = (from as Record<PropertyKey, unknown>)[key];\n\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction omit<T extends object, K extends PropertyKey>(\n from: T,\n keys: readonly K[]\n): Omit<T, Extract<K, keyof T>> {\n const result = { ...from } as Partial<T>;\n\n for (const key of keys) {\n delete (result as Record<PropertyKey, unknown>)[key];\n }\n\n return result as Omit<T, Extract<K, keyof T>>;\n}\n\nfunction reconcile<T extends { id: string }>(cache: Map<string, T>, next: T) {\n const previous = cache.get(next.id);\n\n if (previous && shallow(previous, next)) {\n return previous;\n }\n\n cache.set(next.id, next);\n\n return next;\n}\n\nfunction merge<T extends { id: string }, L extends object>(\n cache: Map<string, T>,\n remote: ReadonlyMap<string, T>,\n local: Map<string, L>\n): T[] {\n // Prune cached items that were deleted remotely.\n for (const id of cache.keys()) {\n if (!remote.has(id)) {\n cache.delete(id);\n }\n }\n\n // Prune local items that were deleted remotely.\n for (const id of local.keys()) {\n if (!remote.has(id)) {\n local.delete(id);\n }\n }\n\n // Reconcile remote and local items.\n return Array.from(remote.values(), (item) => {\n const localItem = local.get(item.id);\n\n return reconcile(\n cache,\n localItem ? (Object.assign({}, item, localItem) as T) : item\n );\n });\n}\n\nfunction updateLocalState<T extends object>(\n map: Map<string, T>,\n key: string,\n changes: T\n): boolean {\n const next: Record<string, unknown> = {};\n\n for (const change in changes) {\n const value = (changes as Record<string, unknown>)[change];\n\n // `false` values aren't stored.\n if (value !== undefined && value !== false) {\n next[change] = value;\n }\n }\n\n if (Object.keys(next).length > 0) {\n map.set(key, next as T);\n\n return true;\n } else {\n const hasItem = map.has(key);\n map.delete(key);\n\n return hasItem;\n }\n}\n\n// Converts a React Flow `Node` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction nodeToStorage<TNode extends SerializableNode>(\n node: TNode\n): LiveblocksNode<TNode> {\n const { data, ...rest } = omit(node, NODE_LOCAL_KEYS) as TNode;\n\n return new LiveObject({\n ...(rest as LsonObject),\n data: new LiveObject(data as LsonObject),\n }) as LiveblocksNode<TNode>;\n}\n\n// Converts a React Flow `Edge` into a Liveblocks Storage version, omitting\n// the fields that must stay local to each client.\nfunction edgeToStorage<TEdge extends SerializableEdge>(\n edge: TEdge\n): LiveblocksEdge<TEdge> {\n const { data, ...rest } = omit(edge, EDGE_LOCAL_KEYS) as TEdge;\n\n return new LiveObject({\n ...(rest as LsonObject),\n\n // `data` is optional on edges.\n data: data === undefined ? undefined : new LiveObject(data as LsonObject),\n }) as LiveblocksEdge<TEdge>;\n}\n\n// Similar to React Flow's `applyNodeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-node-changes\nfunction applyNodeChanges<TNode extends SerializableNode>(args: {\n changes: NodeChange<TNode>[];\n nodes: LiveMap<string, LiveblocksNode<TNode>>;\n nextLocal: Map<string, Partial<LocalNodes>>;\n nodeCache: Map<string, TNode>;\n}): boolean {\n const { changes, nodes, nextLocal, nodeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n nodes.set(change.item.id, nodeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, NODE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n nodes.delete(change.id);\n nodeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"position\": {\n const node = nodes.get(change.id);\n\n if (!node || !change.position) {\n break;\n }\n\n const previous = node.get(\"position\") as TNode[\"position\"] | undefined;\n\n if (\n previous?.x !== change.position.x ||\n previous?.y !== change.position.y\n ) {\n node.set(\"position\", change.position);\n }\n\n if (change.dragging !== undefined) {\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n dragging: change.dragging,\n });\n hasLocalChanged = true;\n }\n\n break;\n }\n\n case \"dimensions\": {\n const node = nodes.get(change.id);\n const patch: Partial<LocalNodes> = {\n ...nextLocal.get(change.id),\n };\n\n if (\n node &&\n change.dimensions !== undefined &&\n change.setAttributes !== undefined\n ) {\n if (\n change.setAttributes === true ||\n change.setAttributes === \"width\"\n ) {\n node.set(\"width\", change.dimensions.width);\n }\n\n if (\n change.setAttributes === true ||\n change.setAttributes === \"height\"\n ) {\n node.set(\"height\", change.dimensions.height);\n }\n }\n\n if (change.dimensions !== undefined) {\n patch.measured = change.dimensions;\n }\n\n if (change.resizing !== undefined) {\n patch.resizing = change.resizing;\n }\n\n updateLocalState(nextLocal, change.id, patch);\n hasLocalChanged = true;\n break;\n }\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n// Similar to React Flow's `applyEdgeChanges()`, but with a split between local\n// and remote changes.\n// https://reactflow.dev/api-reference/utils/apply-edge-changes\nfunction applyEdgeChanges<TEdge extends SerializableEdge>(args: {\n changes: EdgeChange<TEdge>[];\n edges: LiveMap<string, LiveblocksEdge<TEdge>>;\n nextLocal: Map<string, Partial<LocalEdges>>;\n edgeCache: Map<string, TEdge>;\n}): boolean {\n const { changes, edges, nextLocal, edgeCache } = args;\n\n let hasLocalChanged = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n case \"replace\":\n edges.set(change.item.id, edgeToStorage(change.item));\n if (\n updateLocalState(\n nextLocal,\n change.item.id,\n pick(change.item, EDGE_LOCAL_KEYS)\n )\n ) {\n hasLocalChanged = true;\n }\n break;\n\n case \"remove\":\n edges.delete(change.id);\n edgeCache.delete(change.id);\n nextLocal.delete(change.id);\n hasLocalChanged = true;\n break;\n\n case \"select\":\n updateLocalState(nextLocal, change.id, {\n ...nextLocal.get(change.id),\n selected: change.selected,\n });\n hasLocalChanged = true;\n break;\n }\n }\n\n return hasLocalChanged;\n}\n\n/**\n * Creates a Liveblocks Storage representation of a React Flow diagram from nodes and edges.\n *\n * @example\n * ```tsx\n * <RoomProvider\n * initialStorage={{\n * flow: createLiveblocksFlow(initialNodes, initialEdges),\n * }}\n * />\n * ```\n */\nexport function createLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(nodes: TNode[] = [], edges: TEdge[] = []): LiveblocksFlow<TNode, TEdge> {\n return new LiveObject({\n nodes: new LiveMap(nodes.map((node) => [node.id, nodeToStorage(node)])),\n edges: new LiveMap(edges.map((edge) => [edge.id, edgeToStorage(edge)])),\n }) as LiveblocksFlow<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect, isLoading } = useLiveblocksFlow();\n *\n * if (isLoading) {\n * return <div>Loading…</div>\n * }\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlow<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<UseLiveblocksFlowResult<TNode, TEdge>> {\n type TFlow = LiveblocksFlow<TNode, TEdge>;\n type TImmutableFlow = ToImmutable<LiveblocksFlow<TNode, TEdge>>;\n\n const isStorageLoaded = useStorage(() => true) ?? false;\n\n // These options are not reactive, only their initial values are used.\n const frozenOptions = useInitial({\n initial: options.initial,\n storageKey: options.storageKey ?? DEFAULT_STORAGE_KEY,\n });\n\n // Used to reconcile state changes with stable object references when the changes\n // are shallowly equal, preventing React Flow from re-rendering unchanged nodes and edges.\n const nodeCache = useRef<Map<string, TNode>>(new Map());\n const edgeCache = useRef<Map<string, TEdge>>(new Map());\n\n // Local-only state lives in signals.\n const [localNodesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalNodes>>())\n );\n const [localEdgesΣ] = useState(\n () => new Signal(new Map<string, Partial<LocalEdges>>())\n );\n const localNodes = useSignal(localNodesΣ);\n const localEdges = useSignal(localEdgesΣ);\n\n // Remote state lives in Liveblocks Storage.\n const remoteNodesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.nodes ?? null) as ReadonlyMap<string, TNode> | null;\n });\n const remoteEdgesMap = useStorage((storage) => {\n const flow = storage[frozenOptions.storageKey] as\n | TImmutableFlow\n | undefined;\n\n return (flow?.edges ?? null) as ReadonlyMap<string, TEdge> | null;\n });\n\n // Merge remote and local layers to get the final state.\n const nodes = useMemo(\n () =>\n remoteNodesMap\n ? merge(nodeCache.current, remoteNodesMap, localNodes)\n : null,\n [remoteNodesMap, localNodes]\n );\n const edges = useMemo(\n () =>\n remoteEdgesMap\n ? merge(edgeCache.current, remoteEdgesMap, localEdges)\n : null,\n [remoteEdgesMap, localEdges]\n );\n\n const onNodesChange = useMutation(\n ({ storage }, changes: NodeChange<TNode>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localNodesΣ.get());\n const hasLocalChanged = applyNodeChanges({\n changes,\n nodes: flow.get(\"nodes\"),\n nextLocal,\n nodeCache: nodeCache.current,\n });\n\n if (hasLocalChanged) {\n localNodesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onEdgesChange = useMutation(\n ({ storage }, changes: EdgeChange<TEdge>[]) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const nextLocal = new Map(localEdgesΣ.get());\n const hasLocalChanged = applyEdgeChanges({\n changes,\n edges: flow.get(\"edges\"),\n nextLocal,\n edgeCache: edgeCache.current,\n });\n\n if (hasLocalChanged) {\n localEdgesΣ.set(nextLocal);\n }\n },\n []\n );\n\n const onConnect = useMutation(({ storage }, connection: Connection) => {\n const flow = storage.get(frozenOptions.storageKey) as TFlow | undefined;\n\n if (!flow) {\n return;\n }\n\n const edges = flow.get(\"edges\");\n\n // Check for duplicate connections.\n for (const edge of edges.values()) {\n if (\n edge.get(\"source\") === connection.source &&\n edge.get(\"target\") === connection.target &&\n (edge.get(\"sourceHandle\") ?? null) ===\n (connection.sourceHandle ?? null) &&\n (edge.get(\"targetHandle\") ?? null) === (connection.targetHandle ?? null)\n ) {\n return;\n }\n }\n\n // Delegate to React Flow's own `addEdge` helper for consistent default\n // edge ID generation, passing an empty array since de-duplication is\n // already handled above.\n const [newEdge] = defaultAddEdge(connection, [] as TEdge[]);\n\n if (!newEdge) {\n return;\n }\n\n edges.set(newEdge.id, edgeToStorage(newEdge));\n }, []);\n\n const setInitialStorage = useMutation(({ storage }) => {\n // Similarly to `initialStorage` on `Client.enterRoom` and `RoomProvider`, we only\n // initialize Storage if it doesn't already exist.\n if (storage.get(frozenOptions.storageKey) !== undefined) {\n return;\n }\n\n const { nodes: initialNodes = [], edges: initialEdges = [] } =\n frozenOptions.initial ?? {};\n\n storage.set(\n frozenOptions.storageKey,\n createLiveblocksFlow(initialNodes, initialEdges)\n );\n }, []);\n\n useEffect(() => {\n if (isStorageLoaded) {\n setInitialStorage();\n }\n }, [isStorageLoaded, setInitialStorage]);\n\n return {\n nodes,\n edges,\n isLoading: !isStorageLoaded,\n onNodesChange,\n onEdgesChange,\n onConnect,\n } as UseLiveblocksFlowResult<TNode, TEdge>;\n}\n\n/**\n * Returns a controlled React Flow state backed by Liveblocks Storage.\n *\n * @example\n * ```tsx\n * const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useLiveblocksFlow();\n *\n * return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;\n * ```\n */\nexport function useLiveblocksFlowSuspense<\n TNode extends SerializableNode = SerializableNode,\n TEdge extends SerializableEdge = SerializableEdge,\n>(\n options: UseLiveblocksFlowOptions<TNode, TEdge> = {}\n): Resolve<LiveblocksFlowSuspenseResult<TNode, TEdge>> {\n const result = useLiveblocksFlow<TNode, TEdge>(options);\n\n useSuspendUntilStorageReady();\n\n return {\n ...result,\n nodes: result.nodes ?? (EMPTY_ARRAY as TNode[]),\n edges: result.edges ?? (EMPTY_ARRAY as TEdge[]),\n isLoading: false,\n };\n}\n"],"names":["edges","defaultAddEdge"],"mappings":"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"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@liveblocks/core');
|
|
4
|
+
var version = require('./version.cjs');
|
|
5
|
+
var cursors = require('./cursors.cjs');
|
|
6
|
+
var flow = require('./flow.cjs');
|
|
7
|
+
|
|
8
|
+
core.detectDupes(version.PKG_NAME, version.PKG_VERSION, version.PKG_FORMAT);
|
|
9
|
+
|
|
10
|
+
exports.Cursors = cursors.Cursors;
|
|
11
|
+
exports.createLiveblocksFlow = flow.createLiveblocksFlow;
|
|
12
|
+
exports.useLiveblocksFlow = flow.useLiveblocksFlow;
|
|
13
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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 { Cursors } from \"./cursors\";\nexport type { LiveblocksEdge, LiveblocksFlow, LiveblocksNode } from \"./flow\";\nexport { createLiveblocksFlow, useLiveblocksFlow } from \"./flow\";\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;AAIAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;;"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentPropsWithoutRef } from 'react';
|
|
3
|
+
import { LiveObject, DistributiveOmit, LsonObject, LiveMap, Resolve, JsonObject } from '@liveblocks/core';
|
|
4
|
+
import { Node, Edge, OnNodesChange, OnEdgesChange, OnConnect } from '@xyflow/react';
|
|
5
|
+
|
|
6
|
+
interface CursorsProps extends ComponentPropsWithoutRef<"div"> {
|
|
7
|
+
/**
|
|
8
|
+
* The key used to store the cursors in users' Presence.
|
|
9
|
+
*
|
|
10
|
+
* Defaults to `"cursor"`.
|
|
11
|
+
*/
|
|
12
|
+
presenceKey?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Displays other users' cursors inside a React Flow canvas and stores the
|
|
16
|
+
* current user's cursor in Presence as `{ cursor: { x, y } }`.
|
|
17
|
+
*
|
|
18
|
+
* Cursor coordinates are kept in React Flow canvas space, so panning moves
|
|
19
|
+
* them correctly while zooming only affects their position, not their size.
|
|
20
|
+
*/
|
|
21
|
+
declare const Cursors: react.ForwardRefExoticComponent<CursorsProps & react.RefAttributes<HTMLDivElement>>;
|
|
22
|
+
|
|
23
|
+
declare const NODE_LOCAL_KEYS: ["selected", "dragging", "measured", "resizing"];
|
|
24
|
+
declare const EDGE_LOCAL_KEYS: ["selected"];
|
|
25
|
+
type SerializableNode = Node<JsonObject>;
|
|
26
|
+
type SerializableEdge = Edge<JsonObject>;
|
|
27
|
+
/**
|
|
28
|
+
* The Liveblocks Storage representation of a React Flow `Node`.
|
|
29
|
+
*
|
|
30
|
+
* It doesn't include local-only properties.
|
|
31
|
+
* The entire node and its `data` property are both stored as `LiveObject`s.
|
|
32
|
+
*/
|
|
33
|
+
type LiveblocksNode<TNode extends SerializableNode = SerializableNode> = LiveObject<DistributiveOmit<TNode, (typeof NODE_LOCAL_KEYS)[number] | "data"> & {
|
|
34
|
+
data: LiveObject<TNode["data"]>;
|
|
35
|
+
} & LsonObject>;
|
|
36
|
+
/**
|
|
37
|
+
* The Liveblocks Storage representation of a React Flow `Edge`.
|
|
38
|
+
*
|
|
39
|
+
* It doesn't include local-only properties.
|
|
40
|
+
* The entire edge and its `data` property are both stored as `LiveObject`s.
|
|
41
|
+
*/
|
|
42
|
+
type LiveblocksEdge<TEdge extends SerializableEdge = SerializableEdge> = LiveObject<DistributiveOmit<TEdge, (typeof EDGE_LOCAL_KEYS)[number] | "data"> & {
|
|
43
|
+
data?: LiveObject<NonNullable<TEdge["data"]>>;
|
|
44
|
+
} & LsonObject>;
|
|
45
|
+
/**
|
|
46
|
+
* The Liveblocks Storage representation of a React Flow diagram made of nodes and edges.
|
|
47
|
+
*
|
|
48
|
+
* Nodes and edges are stored as `LiveMap`s keyed by their IDs, enabling
|
|
49
|
+
* fine-grained conflict-free updates from multiple clients simultaneously.
|
|
50
|
+
*/
|
|
51
|
+
type LiveblocksFlow<TNode extends SerializableNode = SerializableNode, TEdge extends SerializableEdge = SerializableEdge> = LiveObject<{
|
|
52
|
+
nodes: LiveMap<string, LiveblocksNode<TNode>>;
|
|
53
|
+
edges: LiveMap<string, LiveblocksEdge<TEdge>>;
|
|
54
|
+
}>;
|
|
55
|
+
type UseLiveblocksFlowResult<TNode extends SerializableNode = SerializableNode, TEdge extends SerializableEdge = SerializableEdge> = Resolve<({
|
|
56
|
+
nodes: null;
|
|
57
|
+
edges: null;
|
|
58
|
+
isLoading: true;
|
|
59
|
+
} | {
|
|
60
|
+
nodes: TNode[];
|
|
61
|
+
edges: TEdge[];
|
|
62
|
+
isLoading: false;
|
|
63
|
+
}) & {
|
|
64
|
+
onNodesChange: OnNodesChange<TNode>;
|
|
65
|
+
onEdgesChange: OnEdgesChange<TEdge>;
|
|
66
|
+
onConnect: OnConnect;
|
|
67
|
+
}>;
|
|
68
|
+
type UseLiveblocksFlowOptions<TNode extends SerializableNode, TEdge extends SerializableEdge> = {
|
|
69
|
+
/**
|
|
70
|
+
* The initial React Flow nodes and edges.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```tsx
|
|
74
|
+
* const { ... } = useLiveblocksFlow({
|
|
75
|
+
* initial: {
|
|
76
|
+
* nodes: [
|
|
77
|
+
* { id: "1", position: { x: 0, y: 0 }, data: { label: "Node 1" } },
|
|
78
|
+
* { id: "2", position: { x: 0, y: 100 }, data: { label: "Node 2" } },
|
|
79
|
+
* ],
|
|
80
|
+
* edges: [
|
|
81
|
+
* { id: "1-2", source: "1", target: "2" },
|
|
82
|
+
* ],
|
|
83
|
+
* },
|
|
84
|
+
* });
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* This is equivalent to setting `initialStorage` on `RoomProvider`.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```tsx
|
|
91
|
+
* <RoomProvider
|
|
92
|
+
* initialStorage={{
|
|
93
|
+
* flow: createLiveblocksFlow([
|
|
94
|
+
* { id: "1", position: { x: 0, y: 0 }, data: { label: "Node 1" } },
|
|
95
|
+
* { id: "2", position: { x: 0, y: 100 }, data: { label: "Node 2" } },
|
|
96
|
+
* ], [
|
|
97
|
+
* { id: "1-2", source: "1", target: "2" },
|
|
98
|
+
* ]),
|
|
99
|
+
* }}
|
|
100
|
+
* />
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
initial?: {
|
|
104
|
+
nodes?: TNode[];
|
|
105
|
+
edges?: TEdge[];
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The key used to store the React Flow diagram in Liveblocks Storage.
|
|
109
|
+
*
|
|
110
|
+
* Defaults to `"flow"`.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```tsx
|
|
114
|
+
* const { ... } = useLiveblocksFlow({
|
|
115
|
+
* storageKey: "myDiagram",
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
storageKey?: string;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Creates a Liveblocks Storage representation of a React Flow diagram from nodes and edges.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* <RoomProvider
|
|
127
|
+
* initialStorage={{
|
|
128
|
+
* flow: createLiveblocksFlow(initialNodes, initialEdges),
|
|
129
|
+
* }}
|
|
130
|
+
* />
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
declare function createLiveblocksFlow<TNode extends SerializableNode = SerializableNode, TEdge extends SerializableEdge = SerializableEdge>(nodes?: TNode[], edges?: TEdge[]): LiveblocksFlow<TNode, TEdge>;
|
|
134
|
+
/**
|
|
135
|
+
* Returns a controlled React Flow state backed by Liveblocks Storage.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```tsx
|
|
139
|
+
* const { nodes, edges, onNodesChange, onEdgesChange, onConnect, isLoading } = useLiveblocksFlow();
|
|
140
|
+
*
|
|
141
|
+
* if (isLoading) {
|
|
142
|
+
* return <div>Loading…</div>
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* return <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} />;
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
declare function useLiveblocksFlow<TNode extends SerializableNode = SerializableNode, TEdge extends SerializableEdge = SerializableEdge>(options?: UseLiveblocksFlowOptions<TNode, TEdge>): Resolve<UseLiveblocksFlowResult<TNode, TEdge>>;
|
|
149
|
+
|
|
150
|
+
export { Cursors, LiveblocksEdge, LiveblocksFlow, LiveblocksNode, createLiveblocksFlow, useLiveblocksFlow };
|