{
  "version": 3,
  "sources": ["../../src/canvas/cluster-input.ts"],
  "sourcesContent": ["import type { Editor, TLCommentThread, VecLike } from 'tldraw'\nimport type { LeafInput, LeafScreenOffsets } from '../clustering/types'\nimport { anchorPagePoint, impreciseShapePinInset } from './thread-state'\n\n/** The clustering input for the current page's pinned threads. @internal */\nexport interface ClusterInput {\n\t/** One leaf per pinned thread, at its anchor page point. */\n\tleaves: LeafInput[]\n\t/**\n\t * The render offsets of the imprecise pins among the leaves \u2014 those draw tucked into their\n\t * shape by a constant screen-px inset rather than on their anchor, and the clustering prices\n\t * their merges at the visual positions. Undefined when every pin renders on its anchor,\n\t * which guarantees a byte-identical offset-unaware clustering run.\n\t */\n\tscreenOffsets: LeafScreenOffsets | undefined\n}\n\n/** The cluster leaves for the threads pinned on the current page. @internal */\nexport function collectClusterLeaves(\n\teditor: Editor,\n\tthreads: readonly TLCommentThread[],\n\topenThreadId: string | null\n): ClusterInput {\n\tconst pageId = editor.getCurrentPageId()\n\tconst leaves: LeafInput[] = []\n\tlet screenOffsets: Map<string, VecLike> | undefined\n\n\tfor (const thread of threads) {\n\t\tif (thread.id === openThreadId) continue\n\t\tif (thread.pageId !== pageId) continue\n\n\t\tconst point = anchorPagePoint(editor, thread.anchor)\n\t\tif (!point) continue\n\n\t\tleaves.push({\n\t\t\tid: thread.id,\n\t\t\tpoint: { x: point.x, y: point.y },\n\t\t})\n\n\t\tconst inset = impreciseShapePinInset(editor, thread.anchor)\n\t\tif (inset) (screenOffsets ??= new Map()).set(thread.id, inset)\n\t}\n\n\treturn { leaves, screenOffsets }\n}\n\n/**\n * Value equality over everything `computeClusterTable` reads. Keeps the input's identity stable\n * across recomputes that changed nothing, so the O(N\u00B2) rebuild only runs when it has to.\n * @internal\n */\nexport function clusterInputEqual(a: ClusterInput, b: ClusterInput): boolean {\n\tif (a === b) return true\n\treturn (\n\t\tclusterLeavesEqual(a.leaves, b.leaves) && screenOffsetsEqual(a.screenOffsets, b.screenOffsets)\n\t)\n}\n\n/**\n * The same, ignoring everything positional \u2014 anchor points and offset vectors alike. The mid-drag\n * gate: a move defers, but a thread added, removed, or changed precision still rebuilds.\n * @internal\n */\nexport function clusterInputIdsEqual(a: ClusterInput, b: ClusterInput): boolean {\n\tif (a === b) return true\n\treturn (\n\t\tclusterLeafIdsEqual(a.leaves, b.leaves) &&\n\t\tscreenOffsetIdsEqual(a.screenOffsets, b.screenOffsets)\n\t)\n}\n\nfunction screenOffsetsEqual(a: LeafScreenOffsets | undefined, b: LeafScreenOffsets | undefined) {\n\tif (a === b) return true\n\tif (!a || !b) return false\n\tif (a.size !== b.size) return false\n\tfor (const [id, offset] of b) {\n\t\tconst prev = a.get(id)\n\t\tif (!prev || prev.x !== offset.x || prev.y !== offset.y) return false\n\t}\n\treturn true\n}\n\n/** Which leaves carry an offset, ignoring the vectors: a leaf gains or loses one by changing\n *  precision, which is a record change rather than a gesture. */\nfunction screenOffsetIdsEqual(a: LeafScreenOffsets | undefined, b: LeafScreenOffsets | undefined) {\n\tif (a === b) return true\n\tif (!a || !b) return false\n\tif (a.size !== b.size) return false\n\tfor (const id of b.keys()) {\n\t\tif (!a.has(id)) return false\n\t}\n\treturn true\n}\n\n/** Whether two leaf lists have the same threads at the same positions, in the same order. */\nfunction clusterLeavesEqual(a: readonly LeafInput[], b: readonly LeafInput[]): boolean {\n\tif (a === b) return true\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst la = a[i]\n\t\tconst lb = b[i]\n\t\tif (la.id !== lb.id || la.point.x !== lb.point.x || la.point.y !== lb.point.y) return false\n\t}\n\treturn true\n}\n\n/** Whether two leaf lists contain the same thread ids in the same order, ignoring positions. */\nfunction clusterLeafIdsEqual(a: readonly LeafInput[], b: readonly LeafInput[]): boolean {\n\tif (a === b) return true\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i].id !== b[i].id) return false\n\t}\n\treturn true\n}\n"],
  "mappings": "AAEA,SAAS,iBAAiB,8BAA8B;AAgBjD,SAAS,qBACf,QACA,SACA,cACe;AACf,QAAM,SAAS,OAAO,iBAAiB;AACvC,QAAM,SAAsB,CAAC;AAC7B,MAAI;AAEJ,aAAW,UAAU,SAAS;AAC7B,QAAI,OAAO,OAAO,aAAc;AAChC,QAAI,OAAO,WAAW,OAAQ;AAE9B,UAAM,QAAQ,gBAAgB,QAAQ,OAAO,MAAM;AACnD,QAAI,CAAC,MAAO;AAEZ,WAAO,KAAK;AAAA,MACX,IAAI,OAAO;AAAA,MACX,OAAO,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,IACjC,CAAC;AAED,UAAM,QAAQ,uBAAuB,QAAQ,OAAO,MAAM;AAC1D,QAAI,MAAO,EAAC,kBAAkB,oBAAI,IAAI,GAAG,IAAI,OAAO,IAAI,KAAK;AAAA,EAC9D;AAEA,SAAO,EAAE,QAAQ,cAAc;AAChC;AAOO,SAAS,kBAAkB,GAAiB,GAA0B;AAC5E,MAAI,MAAM,EAAG,QAAO;AACpB,SACC,mBAAmB,EAAE,QAAQ,EAAE,MAAM,KAAK,mBAAmB,EAAE,eAAe,EAAE,aAAa;AAE/F;AAOO,SAAS,qBAAqB,GAAiB,GAA0B;AAC/E,MAAI,MAAM,EAAG,QAAO;AACpB,SACC,oBAAoB,EAAE,QAAQ,EAAE,MAAM,KACtC,qBAAqB,EAAE,eAAe,EAAE,aAAa;AAEvD;AAEA,SAAS,mBAAmB,GAAkC,GAAkC;AAC/F,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,aAAW,CAAC,IAAI,MAAM,KAAK,GAAG;AAC7B,UAAM,OAAO,EAAE,IAAI,EAAE;AACrB,QAAI,CAAC,QAAQ,KAAK,MAAM,OAAO,KAAK,KAAK,MAAM,OAAO,EAAG,QAAO;AAAA,EACjE;AACA,SAAO;AACR;AAIA,SAAS,qBAAqB,GAAkC,GAAkC;AACjG,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,aAAW,MAAM,EAAE,KAAK,GAAG;AAC1B,QAAI,CAAC,EAAE,IAAI,EAAE,EAAG,QAAO;AAAA,EACxB;AACA,SAAO;AACR;AAGA,SAAS,mBAAmB,GAAyB,GAAkC;AACtF,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AAClC,UAAM,KAAK,EAAE,CAAC;AACd,UAAM,KAAK,EAAE,CAAC;AACd,QAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM,KAAK,GAAG,MAAM,MAAM,GAAG,MAAM,EAAG,QAAO;AAAA,EACvF;AACA,SAAO;AACR;AAGA,SAAS,oBAAoB,GAAyB,GAAkC;AACvF,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AAClC,QAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAI,QAAO;AAAA,EACjC;AACA,SAAO;AACR;",
  "names": []
}
