{
  "version": 3,
  "sources": ["../../../src/lib/overlays/CollaboratorHintOverlayUtil.ts"],
  "sourcesContent": ["import { OverlayUtil, TLOverlay, Vec, clamp } from '@tldraw/editor'\n\n/** @public */\nexport interface TLCollaboratorHintOverlay extends TLOverlay {\n\tprops: {\n\t\t/** Clamped point on viewport edge, in page coordinates */\n\t\tx: number\n\t\ty: number\n\t\t/** Rotation angle pointing toward the collaborator's actual cursor */\n\t\trotation: number\n\t\tcolor: string\n\t}\n}\n\n// Lazy-init a Path2D for the hint arrow shape to avoid per-frame path building\nlet _arrowPath: Path2D | null = null\nfunction getArrowPath() {\n\tif (!_arrowPath) {\n\t\t// Matches the path drawn via: M -2,-5 2,0 -2,5 Z\n\t\t_arrowPath = new Path2D('M -2 -5 L 2 0 L -2 5 Z')\n\t}\n\treturn _arrowPath!\n}\n\n/**\n * Overlay util for off-screen collaborator cursor hints.\n * Shows a small directional arrow at the viewport edge pointing toward the collaborator.\n *\n * @public\n */\nexport class CollaboratorHintOverlayUtil extends OverlayUtil<TLCollaboratorHintOverlay> {\n\tstatic override type = 'collaborator_hint'\n\toverride options = { zIndex: 900, lineWidth: 3, viewportPadding: 5 }\n\n\toverride isActive(): boolean {\n\t\tconst viewport = this.editor.getViewportPageBounds()\n\t\tconst zoom = this.editor.getZoomLevel()\n\t\treturn this.editor.getVisibleCollaboratorsOnCurrentPage().some((presence) => {\n\t\t\tconst { cursor } = presence\n\t\t\tif (!cursor) return false\n\t\t\treturn !this._isCursorInViewport(cursor, viewport, zoom)\n\t\t})\n\t}\n\n\toverride getOverlays(): TLCollaboratorHintOverlay[] {\n\t\tconst overlays: TLCollaboratorHintOverlay[] = []\n\t\tconst viewport = this.editor.getViewportPageBounds()\n\t\tconst zoom = this.editor.getZoomLevel()\n\n\t\tfor (const presence of this.editor.getVisibleCollaboratorsOnCurrentPage()) {\n\t\t\tconst { cursor, color, userId } = presence\n\t\t\tif (!cursor) continue\n\t\t\tif (this._isCursorInViewport(cursor, viewport, zoom)) continue\n\n\t\t\tconst pad = this.options.viewportPadding / zoom\n\t\t\tconst x = clamp(cursor.x, viewport.minX + pad, viewport.maxX - pad)\n\t\t\tconst y = clamp(cursor.y, viewport.minY + pad, viewport.maxY - pad)\n\t\t\tconst rotation = Vec.Angle(viewport.center, cursor)\n\n\t\t\toverlays.push({\n\t\t\t\tid: `collaborator_hint:${userId}`,\n\t\t\t\ttype: 'collaborator_hint',\n\t\t\t\tprops: { x, y, rotation, color },\n\t\t\t})\n\t\t}\n\t\treturn overlays\n\t}\n\n\toverride render(ctx: CanvasRenderingContext2D, overlays: TLCollaboratorHintOverlay[]): void {\n\t\tconst zoom = this.editor.getZoomLevel()\n\t\tconst scale = 1 / zoom\n\n\t\tfor (const overlay of overlays) {\n\t\t\tconst { x, y, rotation, color } = overlay.props\n\n\t\t\tctx.save()\n\t\t\tctx.translate(x, y)\n\t\t\tctx.scale(scale, scale)\n\t\t\tctx.rotate(rotation)\n\n\t\t\tconst path = getArrowPath()\n\n\t\t\t// Outline stroke (white background for contrast)\n\t\t\tctx.lineWidth = this.options.lineWidth\n\t\t\t// Canvas doesn't support CSS vars in strokeStyle; use white\n\t\t\tctx.strokeStyle = '#ffffff'\n\t\t\tctx.stroke(path)\n\n\t\t\t// Fill with collaborator color\n\t\t\tctx.fillStyle = color\n\t\t\tctx.fill(path)\n\n\t\t\tctx.restore()\n\t\t}\n\t}\n\n\t/** @internal */\n\tprivate _isCursorInViewport(\n\t\tcursor: { x: number; y: number },\n\t\tviewport: { minX: number; minY: number; maxX: number; maxY: number },\n\t\tzoom: number\n\t): boolean {\n\t\treturn !(\n\t\t\tcursor.x < viewport.minX - 12 / zoom ||\n\t\t\tcursor.y < viewport.minY - 16 / zoom ||\n\t\t\tcursor.x > viewport.maxX - 12 / zoom ||\n\t\t\tcursor.y > viewport.maxY - 16 / zoom\n\t\t)\n\t}\n}\n"],
  "mappings": "AAAA,SAAS,aAAwB,KAAK,aAAa;AAenD,IAAI,aAA4B;AAChC,SAAS,eAAe;AACvB,MAAI,CAAC,YAAY;AAEhB,iBAAa,IAAI,OAAO,wBAAwB;AAAA,EACjD;AACA,SAAO;AACR;AAQO,MAAM,oCAAoC,YAAuC;AAAA,EACvF,OAAgB,OAAO;AAAA,EACd,UAAU,EAAE,QAAQ,KAAK,WAAW,GAAG,iBAAiB,EAAE;AAAA,EAE1D,WAAoB;AAC5B,UAAM,WAAW,KAAK,OAAO,sBAAsB;AACnD,UAAM,OAAO,KAAK,OAAO,aAAa;AACtC,WAAO,KAAK,OAAO,qCAAqC,EAAE,KAAK,CAAC,aAAa;AAC5E,YAAM,EAAE,OAAO,IAAI;AACnB,UAAI,CAAC,OAAQ,QAAO;AACpB,aAAO,CAAC,KAAK,oBAAoB,QAAQ,UAAU,IAAI;AAAA,IACxD,CAAC;AAAA,EACF;AAAA,EAES,cAA2C;AACnD,UAAM,WAAwC,CAAC;AAC/C,UAAM,WAAW,KAAK,OAAO,sBAAsB;AACnD,UAAM,OAAO,KAAK,OAAO,aAAa;AAEtC,eAAW,YAAY,KAAK,OAAO,qCAAqC,GAAG;AAC1E,YAAM,EAAE,QAAQ,OAAO,OAAO,IAAI;AAClC,UAAI,CAAC,OAAQ;AACb,UAAI,KAAK,oBAAoB,QAAQ,UAAU,IAAI,EAAG;AAEtD,YAAM,MAAM,KAAK,QAAQ,kBAAkB;AAC3C,YAAM,IAAI,MAAM,OAAO,GAAG,SAAS,OAAO,KAAK,SAAS,OAAO,GAAG;AAClE,YAAM,IAAI,MAAM,OAAO,GAAG,SAAS,OAAO,KAAK,SAAS,OAAO,GAAG;AAClE,YAAM,WAAW,IAAI,MAAM,SAAS,QAAQ,MAAM;AAElD,eAAS,KAAK;AAAA,QACb,IAAI,qBAAqB,MAAM;AAAA,QAC/B,MAAM;AAAA,QACN,OAAO,EAAE,GAAG,GAAG,UAAU,MAAM;AAAA,MAChC,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AAAA,EAES,OAAO,KAA+B,UAA6C;AAC3F,UAAM,OAAO,KAAK,OAAO,aAAa;AACtC,UAAM,QAAQ,IAAI;AAElB,eAAW,WAAW,UAAU;AAC/B,YAAM,EAAE,GAAG,GAAG,UAAU,MAAM,IAAI,QAAQ;AAE1C,UAAI,KAAK;AACT,UAAI,UAAU,GAAG,CAAC;AAClB,UAAI,MAAM,OAAO,KAAK;AACtB,UAAI,OAAO,QAAQ;AAEnB,YAAM,OAAO,aAAa;AAG1B,UAAI,YAAY,KAAK,QAAQ;AAE7B,UAAI,cAAc;AAClB,UAAI,OAAO,IAAI;AAGf,UAAI,YAAY;AAChB,UAAI,KAAK,IAAI;AAEb,UAAI,QAAQ;AAAA,IACb;AAAA,EACD;AAAA;AAAA,EAGQ,oBACP,QACA,UACA,MACU;AACV,WAAO,EACN,OAAO,IAAI,SAAS,OAAO,KAAK,QAChC,OAAO,IAAI,SAAS,OAAO,KAAK,QAChC,OAAO,IAAI,SAAS,OAAO,KAAK,QAChC,OAAO,IAAI,SAAS,OAAO,KAAK;AAAA,EAElC;AACD;",
  "names": []
}
