{"version":3,"file":"use-link-layout.cjs","sources":["../../../src/hooks/use-link-layout.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react';\nimport { useCellId } from './use-cell-id';\nimport { usePaperStore } from './use-paper';\nimport { getLinkLayout } from '../store/update-layout-state';\nimport type { LinkLayout } from '../types/cell.types';\n\n/**\n * Returns `true` when both layouts are structurally identical. Used to hold\n * the cached `useSyncExternalStore` snapshot stable across `render:done`\n * events that didn't actually change the link's geometry.\n * @param a - first layout (may be undefined)\n * @param b - second layout (may be undefined)\n * @returns whether `a` and `b` describe the same rendered geometry\n */\nfunction isSameLayout(a: LinkLayout | undefined, b: LinkLayout | undefined): boolean {\n  if (a === b) return true;\n  if (!a || !b) return false;\n  return (\n    a.sourceX === b.sourceX &&\n    a.sourceY === b.sourceY &&\n    a.targetX === b.targetX &&\n    a.targetY === b.targetY &&\n    a.d === b.d\n  );\n}\n\n/**\n * Returns the current link's rendered geometry, its source and target endpoint\n * coordinates plus the SVG path string (`{ sourceX, sourceY, targetX, targetY,\n * d }`, where `d` is the path computed by JointJS). Use it to draw custom link\n * decorations, labels, or overlays that need to follow the link's actual route.\n *\n * Geometry is per-paper: the same link can render with different routing on\n * different papers (e.g. the main canvas and a minimap), so the hook reports the\n * geometry on the paper it is mounted under. The value stays in sync, it\n * re-reads after every render pass, covering drags, programmatic position\n * changes, source/target reconnections, and resizes.\n *\n * Call it inside `renderLink` (or a component mounted from one) so the target\n * link id resolves from context. Returns `undefined` only until the link view\n * exists — no paper has mounted yet, or the view is still being created. Once the\n * view appears the value is always defined; it may briefly report zeroed\n * coordinates and an empty path string until JointJS computes the first route.\n * @returns The current link's layout, or `undefined` while no link view exists yet.\n * @experimental Depends on `renderLink`, which is itself experimental.\n * @group Hooks\n * @example\n * ```tsx\n * import { GraphProvider, Paper, useLinkLayout } from '@joint/react';\n *\n * // A badge that tracks the midpoint of the link as it is routed.\n * function LinkMidpointBadge() {\n *   const layout = useLinkLayout();\n *   if (!layout) return null;\n *   const midX = (layout.sourceX + layout.targetX) / 2;\n *   const midY = (layout.sourceY + layout.targetY) / 2;\n *   return <circle cx={midX} cy={midY} r={4} fill=\"tomato\" />;\n * }\n *\n * <GraphProvider>\n *   <Paper renderLink={() => <LinkMidpointBadge />} />\n * </GraphProvider>\n * ```\n */\nexport function useLinkLayout(): LinkLayout | undefined {\n  const id = useCellId();\n  const paperStore = usePaperStore();\n  const paper = paperStore?.paper;\n  const cachedRef = useRef<LinkLayout | undefined>(undefined);\n\n  const subscribe = useCallback(\n    (listener: () => void) => {\n      if (!paper) return () => {};\n      // `render:done` fires after JointJS finishes any render pass — drag\n      // ticks, programmatic position changes, layout recomputes, link\n      // reconnections all produce one. This single subscription covers\n      // every reason link geometry could have updated.\n      paper.on('render:done', listener);\n      return () => {\n        paper.off('render:done', listener);\n      };\n    },\n    [paper]\n  );\n\n  const getSnapshot = useCallback((): LinkLayout | undefined => {\n    if (!paperStore) return undefined;\n    const linkView = paperStore.getLinkView(id);\n    const next = linkView ? getLinkLayout(linkView) : undefined;\n    if (isSameLayout(cachedRef.current, next)) return cachedRef.current;\n    cachedRef.current = next;\n    return next;\n  }, [id, paperStore]);\n\n  return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["useCellId","usePaperStore","useRef","useCallback","getLinkLayout","useSyncExternalStore"],"mappings":"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"}