@tldraw/editor 4.6.0-canary.677d2249a65a → 4.6.0-canary.69005ef02ce9

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.
Files changed (169) hide show
  1. package/dist-cjs/index.d.ts +20 -0
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/components/LiveCollaborators.js +1 -0
  4. package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
  5. package/dist-cjs/lib/components/MenuClickCapture.js +93 -47
  6. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +7 -0
  8. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +3 -3
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +3 -1
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  11. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
  12. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  13. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +1 -0
  14. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
  15. package/dist-cjs/lib/editor/Editor.js +40 -1
  16. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  17. package/dist-cjs/lib/editor/assets/AssetUtil.js +1 -0
  18. package/dist-cjs/lib/editor/assets/AssetUtil.js.map +1 -1
  19. package/dist-cjs/lib/editor/bindings/BindingUtil.js +1 -0
  20. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
  21. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -0
  22. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +1 -1
  23. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -0
  24. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +1 -1
  25. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -0
  26. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
  27. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -0
  28. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +1 -1
  29. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +2 -0
  30. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +1 -1
  31. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +12 -0
  32. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  33. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -0
  34. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
  35. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -0
  36. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
  37. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +1 -0
  38. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
  39. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -0
  40. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +1 -1
  41. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +1 -0
  42. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +1 -1
  43. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -0
  44. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
  45. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +1 -0
  46. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +1 -1
  47. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -0
  48. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
  49. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +2 -0
  50. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +1 -1
  51. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +1 -0
  52. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  53. package/dist-cjs/lib/editor/tools/StateNode.js +1 -0
  54. package/dist-cjs/lib/editor/tools/StateNode.js.map +1 -1
  55. package/dist-cjs/lib/exports/ExportDelay.js +1 -0
  56. package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
  57. package/dist-cjs/lib/exports/StyleEmbedder.js +1 -0
  58. package/dist-cjs/lib/exports/StyleEmbedder.js.map +1 -1
  59. package/dist-cjs/lib/hooks/useCanvasEvents.js +25 -4
  60. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  61. package/dist-cjs/lib/options.js +2 -0
  62. package/dist-cjs/lib/options.js.map +2 -2
  63. package/dist-cjs/lib/primitives/Vec.js +3 -0
  64. package/dist-cjs/lib/primitives/Vec.js.map +1 -1
  65. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -0
  66. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +1 -1
  67. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -0
  68. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +1 -1
  69. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -0
  70. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
  71. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -0
  72. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +1 -1
  73. package/dist-cjs/lib/utils/EditorAtom.js +2 -0
  74. package/dist-cjs/lib/utils/EditorAtom.js.map +1 -1
  75. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +2 -0
  76. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +1 -1
  77. package/dist-cjs/version.js +3 -3
  78. package/dist-cjs/version.js.map +1 -1
  79. package/dist-esm/index.d.mts +20 -0
  80. package/dist-esm/index.mjs +1 -1
  81. package/dist-esm/lib/components/LiveCollaborators.mjs +1 -0
  82. package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
  83. package/dist-esm/lib/components/MenuClickCapture.mjs +94 -48
  84. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  85. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +7 -0
  86. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +3 -3
  87. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +3 -1
  88. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  89. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
  90. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  91. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +1 -0
  92. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
  93. package/dist-esm/lib/editor/Editor.mjs +41 -2
  94. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  95. package/dist-esm/lib/editor/assets/AssetUtil.mjs +1 -0
  96. package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +1 -1
  97. package/dist-esm/lib/editor/bindings/BindingUtil.mjs +1 -0
  98. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
  99. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -0
  100. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +1 -1
  101. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -0
  102. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +1 -1
  103. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -0
  104. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
  105. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -0
  106. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +1 -1
  107. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +2 -0
  108. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +1 -1
  109. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +12 -0
  110. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  111. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -0
  112. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
  113. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -0
  114. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
  115. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +1 -0
  116. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
  117. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -0
  118. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +1 -1
  119. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +1 -0
  120. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +1 -1
  121. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +1 -0
  122. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
  123. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +1 -0
  124. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +1 -1
  125. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -0
  126. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
  127. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +2 -0
  128. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +1 -1
  129. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +1 -0
  130. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  131. package/dist-esm/lib/editor/tools/StateNode.mjs +1 -0
  132. package/dist-esm/lib/editor/tools/StateNode.mjs.map +1 -1
  133. package/dist-esm/lib/exports/ExportDelay.mjs +1 -0
  134. package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
  135. package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -0
  136. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +1 -1
  137. package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -4
  138. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  139. package/dist-esm/lib/options.mjs +2 -0
  140. package/dist-esm/lib/options.mjs.map +2 -2
  141. package/dist-esm/lib/primitives/Vec.mjs +3 -0
  142. package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
  143. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -0
  144. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +1 -1
  145. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +1 -0
  146. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +1 -1
  147. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -0
  148. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
  149. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -0
  150. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +1 -1
  151. package/dist-esm/lib/utils/EditorAtom.mjs +2 -0
  152. package/dist-esm/lib/utils/EditorAtom.mjs.map +1 -1
  153. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +2 -0
  154. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +1 -1
  155. package/dist-esm/version.mjs +3 -3
  156. package/dist-esm/version.mjs.map +1 -1
  157. package/editor.css +0 -4
  158. package/package.json +7 -7
  159. package/src/lib/components/LiveCollaborators.tsx +8 -2
  160. package/src/lib/components/MenuClickCapture.tsx +124 -64
  161. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +11 -0
  162. package/src/lib/components/default-components/DefaultCanvas.tsx +4 -1
  163. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +2 -2
  164. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +2 -0
  165. package/src/lib/editor/Editor.ts +58 -6
  166. package/src/lib/editor/managers/InputsManager/InputsManager.ts +12 -0
  167. package/src/lib/hooks/useCanvasEvents.ts +40 -3
  168. package/src/lib/options.ts +14 -0
  169. package/src/version.ts +3 -3
@@ -996,6 +996,7 @@ export declare const defaultTldrawOptions: {
996
996
  readonly onBeforePasteFromClipboard: undefined;
997
997
  readonly onClipboardPasteRaw: undefined;
998
998
  readonly quickZoomPreservesScreenBounds: true;
999
+ readonly rightClickPanning: true;
999
1000
  readonly snapThreshold: 8;
1000
1001
  readonly spacebarPanning: true;
1001
1002
  readonly temporaryAssetPreviewLifetimeMs: 180000;
@@ -1004,6 +1005,7 @@ export declare const defaultTldrawOptions: {
1004
1005
  readonly tooltipDelayMs: 700;
1005
1006
  readonly uiCoarseDragDistanceSquared: 625;
1006
1007
  readonly uiDragDistanceSquared: 16;
1008
+ readonly useCanvasIndicators: true;
1007
1009
  readonly zoomToFitPadding: 128;
1008
1010
  };
1009
1011
 
@@ -5067,6 +5069,12 @@ export declare class InputsManager {
5067
5069
  get isPointing(): boolean;
5068
5070
  set isPointing(isPointing: boolean);
5069
5071
  /* Excluded from this release type: setIsPointing */
5072
+ private _isRightPointing;
5073
+ /**
5074
+ * Whether the user is right-click pointing (before drag threshold).
5075
+ */
5076
+ getIsRightPointing(): boolean;
5077
+ /* Excluded from this release type: setIsRightPointing */
5070
5078
  private _isPinching;
5071
5079
  /**
5072
5080
  * Whether the user is pinching.
@@ -7660,6 +7668,12 @@ export declare interface TldrawOptions {
7660
7668
  * When false, the spacebar will not pan the camera.
7661
7669
  */
7662
7670
  readonly spacebarPanning: boolean;
7671
+ /**
7672
+ * Whether to allow right-click + drag to pan the camera. When true, right-click + drag pans the
7673
+ * camera and a static right-click opens the context menu at the release position. When false,
7674
+ * right-click opens the context menu on press (no drag-to-pan).
7675
+ */
7676
+ readonly rightClickPanning: boolean;
7663
7677
  /**
7664
7678
  * The default padding (in pixels) used when zooming to fit content in the viewport.
7665
7679
  * This affects methods like `zoomToFit()`, `zoomToSelection()`, and `zoomToBounds()`.
@@ -7702,6 +7716,12 @@ export declare interface TldrawOptions {
7702
7716
  * viewport's page dimensions regardless of overview zoom changes.
7703
7717
  */
7704
7718
  readonly quickZoomPreservesScreenBounds: boolean;
7719
+ /**
7720
+ * Whether to use 2D canvas rendering for shape indicators. When true (default),
7721
+ * shapes that support it will render indicators on a 2D canvas for better
7722
+ * performance. When false, all indicators use legacy SVG rendering.
7723
+ */
7724
+ readonly useCanvasIndicators: boolean;
7705
7725
  /**
7706
7726
  * Called before content is written to the clipboard during a copy or cut operation.
7707
7727
  * Receives the serialized content (shapes, bindings, assets) and can filter or transform
package/dist-cjs/index.js CHANGED
@@ -389,7 +389,7 @@ var import_uniq = require("./lib/utils/uniq");
389
389
  var import_defaultThemes2 = require("./lib/editor/managers/ThemeManager/defaultThemes");
390
390
  (0, import_utils.registerTldrawLibraryVersion)(
391
391
  "@tldraw/editor",
392
- "4.6.0-canary.677d2249a65a",
392
+ "4.6.0-canary.69005ef02ce9",
393
393
  "cjs"
394
394
  );
395
395
  //# sourceMappingURL=index.js.map
@@ -113,6 +113,7 @@ const Collaborator = (0, import_state_react.track)(function Collaborator2({
113
113
  )) }) : null,
114
114
  CollaboratorShapeIndicator && selectedShapeIds.filter((id) => {
115
115
  if (editor.isShapeHidden(id)) return false;
116
+ if (!editor.options.useCanvasIndicators) return true;
116
117
  const shape = editor.getShape(id);
117
118
  if (!shape) return false;
118
119
  const util = editor.getShapeUtil(shape);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/components/LiveCollaborators.tsx"],
4
- "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { TLInstancePresence } from '@tldraw/tlschema'\nimport { useEffect, useRef, useState } from 'react'\nimport { Editor } from '../editor/Editor'\nimport { useEditorComponents } from '../hooks/EditorComponentsContext'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePeerIds } from '../hooks/usePeerIds'\nimport { usePresence } from '../hooks/usePresence'\nimport {\n\tCollaboratorState,\n\tgetCollaboratorStateFromElapsedTime,\n\tshouldShowCollaborator,\n} from '../utils/collaboratorState'\n\nexport const LiveCollaborators = track(function Collaborators() {\n\tconst peerIds = usePeerIds()\n\treturn peerIds.map((id) => <CollaboratorGuard key={id} collaboratorId={id} />)\n})\n\nconst CollaboratorGuard = track(function CollaboratorGuard({\n\tcollaboratorId,\n}: {\n\tcollaboratorId: string\n}) {\n\tconst editor = useEditor()\n\tconst presence = usePresence(collaboratorId)\n\tconst collaboratorState = useCollaboratorState(editor, presence)\n\n\tif (!(presence && presence.currentPageId === editor.getCurrentPageId())) {\n\t\t// No need to render if we don't have a presence or if they're on a different page\n\t\treturn null\n\t}\n\n\tif (!shouldShowCollaborator(editor, presence, collaboratorState)) {\n\t\treturn null\n\t}\n\n\treturn <Collaborator latestPresence={presence} />\n})\n\nconst Collaborator = track(function Collaborator({\n\tlatestPresence,\n}: {\n\tlatestPresence: TLInstancePresence\n}) {\n\tconst editor = useEditor()\n\n\tconst {\n\t\tCollaboratorBrush,\n\t\tCollaboratorScribble,\n\t\tCollaboratorCursor,\n\t\tCollaboratorHint,\n\t\tCollaboratorShapeIndicator,\n\t} = useEditorComponents()\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst viewportPageBounds = editor.getViewportPageBounds()\n\tconst { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } =\n\t\tlatestPresence\n\n\tif (!cursor) return null\n\n\t// Add a little padding to the top-left of the viewport\n\t// so that the cursor doesn't get cut off\n\tconst isCursorInViewport = !(\n\t\tcursor.x < viewportPageBounds.minX - 12 / zoomLevel ||\n\t\tcursor.y < viewportPageBounds.minY - 16 / zoomLevel ||\n\t\tcursor.x > viewportPageBounds.maxX - 12 / zoomLevel ||\n\t\tcursor.y > viewportPageBounds.maxY - 16 / zoomLevel\n\t)\n\n\treturn (\n\t\t<>\n\t\t\t{brush && CollaboratorBrush ? (\n\t\t\t\t<CollaboratorBrush\n\t\t\t\t\tclassName=\"tl-collaborator__brush\"\n\t\t\t\t\tkey={userId + '_brush'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tbrush={brush}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\topacity={0.1}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{isCursorInViewport && CollaboratorCursor ? (\n\t\t\t\t<CollaboratorCursor\n\t\t\t\t\tclassName=\"tl-collaborator__cursor\"\n\t\t\t\t\tkey={userId + '_cursor'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tname={userName !== 'New User' ? userName : null}\n\t\t\t\t\tchatMessage={chatMessage ?? ''}\n\t\t\t\t/>\n\t\t\t) : CollaboratorHint ? (\n\t\t\t\t<CollaboratorHint\n\t\t\t\t\tclassName=\"tl-collaborator__cursor-hint\"\n\t\t\t\t\tkey={userId + '_cursor_hint'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tviewport={viewportPageBounds}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{CollaboratorScribble && scribbles.length ? (\n\t\t\t\t<>\n\t\t\t\t\t{scribbles.map((scribble) => (\n\t\t\t\t\t\t<CollaboratorScribble\n\t\t\t\t\t\t\tkey={userId + '_scribble_' + scribble.id}\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__scribble\"\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tscribble={scribble}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\t\t\topacity={scribble.color === 'laser' ? 0.5 : 0.1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t{CollaboratorShapeIndicator &&\n\t\t\t\tselectedShapeIds\n\t\t\t\t\t.filter((id) => {\n\t\t\t\t\t\t// Skip hidden shapes\n\t\t\t\t\t\tif (editor.isShapeHidden(id)) return false\n\t\t\t\t\t\t// Only render SVG indicators for shapes that use legacy indicators\n\t\t\t\t\t\t// Canvas-based indicators are handled by CanvasShapeIndicators\n\t\t\t\t\t\tconst shape = editor.getShape(id)\n\t\t\t\t\t\tif (!shape) return false\n\t\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\t\t\t\t\t\treturn util.useLegacyIndicator()\n\t\t\t\t\t})\n\t\t\t\t\t.map((shapeId) => (\n\t\t\t\t\t\t<CollaboratorShapeIndicator\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__shape-indicator\"\n\t\t\t\t\t\t\tkey={userId + '_' + shapeId}\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t</>\n\t)\n})\n\nfunction useCollaboratorState(\n\teditor: Editor,\n\tlatestPresence: TLInstancePresence | null\n): CollaboratorState {\n\tconst rLastActivityTimestamp = useRef(latestPresence?.lastActivityTimestamp ?? -1)\n\n\tconst [state, setState] = useState<CollaboratorState>(() =>\n\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t)\n\n\tuseEffect(() => {\n\t\tconst interval = editor.timers.setInterval(() => {\n\t\t\tsetState(\n\t\t\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t\t\t)\n\t\t}, editor.options.collaboratorCheckIntervalMs)\n\n\t\treturn () => clearInterval(interval)\n\t}, [editor])\n\n\tif (latestPresence) {\n\t\t// We can do this on every render, it's free and cheaper than an effect\n\t\t// remember, there can be lots and lots of cursors moving around all the time\n\t\trLastActivityTimestamp.current = latestPresence.lastActivityTimestamp ?? Infinity\n\t}\n\n\treturn state\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { TLInstancePresence } from '@tldraw/tlschema'\nimport { useEffect, useRef, useState } from 'react'\nimport { Editor } from '../editor/Editor'\nimport { useEditorComponents } from '../hooks/EditorComponentsContext'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePeerIds } from '../hooks/usePeerIds'\nimport { usePresence } from '../hooks/usePresence'\nimport {\n\tCollaboratorState,\n\tgetCollaboratorStateFromElapsedTime,\n\tshouldShowCollaborator,\n} from '../utils/collaboratorState'\n\nexport const LiveCollaborators = track(function Collaborators() {\n\tconst peerIds = usePeerIds()\n\treturn peerIds.map((id) => <CollaboratorGuard key={id} collaboratorId={id} />)\n})\n\nconst CollaboratorGuard = track(function CollaboratorGuard({\n\tcollaboratorId,\n}: {\n\tcollaboratorId: string\n}) {\n\tconst editor = useEditor()\n\tconst presence = usePresence(collaboratorId)\n\tconst collaboratorState = useCollaboratorState(editor, presence)\n\n\tif (!(presence && presence.currentPageId === editor.getCurrentPageId())) {\n\t\t// No need to render if we don't have a presence or if they're on a different page\n\t\treturn null\n\t}\n\n\tif (!shouldShowCollaborator(editor, presence, collaboratorState)) {\n\t\treturn null\n\t}\n\n\treturn <Collaborator latestPresence={presence} />\n})\n\nconst Collaborator = track(function Collaborator({\n\tlatestPresence,\n}: {\n\tlatestPresence: TLInstancePresence\n}) {\n\tconst editor = useEditor()\n\n\tconst {\n\t\tCollaboratorBrush,\n\t\tCollaboratorScribble,\n\t\tCollaboratorCursor,\n\t\tCollaboratorHint,\n\t\tCollaboratorShapeIndicator,\n\t} = useEditorComponents()\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst viewportPageBounds = editor.getViewportPageBounds()\n\tconst { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } =\n\t\tlatestPresence\n\n\tif (!cursor) return null\n\n\t// Add a little padding to the top-left of the viewport\n\t// so that the cursor doesn't get cut off\n\tconst isCursorInViewport = !(\n\t\tcursor.x < viewportPageBounds.minX - 12 / zoomLevel ||\n\t\tcursor.y < viewportPageBounds.minY - 16 / zoomLevel ||\n\t\tcursor.x > viewportPageBounds.maxX - 12 / zoomLevel ||\n\t\tcursor.y > viewportPageBounds.maxY - 16 / zoomLevel\n\t)\n\n\treturn (\n\t\t<>\n\t\t\t{brush && CollaboratorBrush ? (\n\t\t\t\t<CollaboratorBrush\n\t\t\t\t\tclassName=\"tl-collaborator__brush\"\n\t\t\t\t\tkey={userId + '_brush'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tbrush={brush}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\topacity={0.1}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{isCursorInViewport && CollaboratorCursor ? (\n\t\t\t\t<CollaboratorCursor\n\t\t\t\t\tclassName=\"tl-collaborator__cursor\"\n\t\t\t\t\tkey={userId + '_cursor'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tname={userName !== 'New User' ? userName : null}\n\t\t\t\t\tchatMessage={chatMessage ?? ''}\n\t\t\t\t/>\n\t\t\t) : CollaboratorHint ? (\n\t\t\t\t<CollaboratorHint\n\t\t\t\t\tclassName=\"tl-collaborator__cursor-hint\"\n\t\t\t\t\tkey={userId + '_cursor_hint'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tviewport={viewportPageBounds}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{CollaboratorScribble && scribbles.length ? (\n\t\t\t\t<>\n\t\t\t\t\t{scribbles.map((scribble) => (\n\t\t\t\t\t\t<CollaboratorScribble\n\t\t\t\t\t\t\tkey={userId + '_scribble_' + scribble.id}\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__scribble\"\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tscribble={scribble}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\t\t\topacity={scribble.color === 'laser' ? 0.5 : 0.1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t{CollaboratorShapeIndicator &&\n\t\t\t\tselectedShapeIds\n\t\t\t\t\t.filter((id) => {\n\t\t\t\t\t\t// Skip hidden shapes\n\t\t\t\t\t\tif (editor.isShapeHidden(id)) return false\n\t\t\t\t\t\t// When canvas indicators are disabled, render SVG indicators for\n\t\t\t\t\t\t// every selected shape. Otherwise shapes that opt into the canvas\n\t\t\t\t\t\t// path via useLegacyIndicator() === false would never get a\n\t\t\t\t\t\t// collaborator indicator drawn.\n\t\t\t\t\t\tif (!editor.options.useCanvasIndicators) return true\n\t\t\t\t\t\t// Otherwise, only render SVG indicators for shapes that opt in to\n\t\t\t\t\t\t// the legacy path \u2014 canvas-based indicators are handled by\n\t\t\t\t\t\t// CanvasShapeIndicators.\n\t\t\t\t\t\tconst shape = editor.getShape(id)\n\t\t\t\t\t\tif (!shape) return false\n\t\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\t\t\t\t\t\treturn util.useLegacyIndicator()\n\t\t\t\t\t})\n\t\t\t\t\t.map((shapeId) => (\n\t\t\t\t\t\t<CollaboratorShapeIndicator\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__shape-indicator\"\n\t\t\t\t\t\t\tkey={userId + '_' + shapeId}\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t</>\n\t)\n})\n\nfunction useCollaboratorState(\n\teditor: Editor,\n\tlatestPresence: TLInstancePresence | null\n): CollaboratorState {\n\tconst rLastActivityTimestamp = useRef(latestPresence?.lastActivityTimestamp ?? -1)\n\n\tconst [state, setState] = useState<CollaboratorState>(() =>\n\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t)\n\n\tuseEffect(() => {\n\t\tconst interval = editor.timers.setInterval(() => {\n\t\t\tsetState(\n\t\t\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t\t\t)\n\t\t}, editor.options.collaboratorCheckIntervalMs)\n\n\t\treturn () => clearInterval(interval)\n\t}, [editor])\n\n\tif (latestPresence) {\n\t\t// We can do this on every render, it's free and cheaper than an effect\n\t\t// remember, there can be lots and lots of cursors moving around all the time\n\t\trLastActivityTimestamp.current = latestPresence.lastActivityTimestamp ?? Infinity\n\t}\n\n\treturn state\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["CollaboratorGuard", "Collaborator"]
7
7
  }
@@ -24,9 +24,11 @@ module.exports = __toCommonJS(MenuClickCapture_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_state_react = require("@tldraw/state-react");
26
26
  var import_react = require("react");
27
+ var import_react_dom = require("react-dom");
27
28
  var import_useCanvasEvents = require("../hooks/useCanvasEvents");
28
29
  var import_useEditor = require("../hooks/useEditor");
29
30
  var import_Vec = require("../primitives/Vec");
31
+ var import_dom = require("../utils/dom");
30
32
  var import_getPointerInfo = require("../utils/getPointerInfo");
31
33
  function MenuClickCapture() {
32
34
  const editor = (0, import_useEditor.useEditor)();
@@ -37,81 +39,125 @@ function MenuClickCapture() {
37
39
  const rPointerState = (0, import_react.useRef)({
38
40
  isDown: false,
39
41
  isDragging: false,
42
+ button: 0,
40
43
  start: new import_Vec.Vec()
41
44
  });
45
+ const rCancelContextMenuSwallow = (0, import_react.useRef)(null);
46
+ (0, import_react.useEffect)(
47
+ () => () => {
48
+ rCancelContextMenuSwallow.current?.();
49
+ rCancelContextMenuSwallow.current = null;
50
+ },
51
+ []
52
+ );
53
+ const swallowNextNativeContextMenu = (0, import_react.useCallback)(() => {
54
+ rCancelContextMenuSwallow.current?.();
55
+ const doc = editor.getContainerDocument();
56
+ const onContextMenu = (event) => {
57
+ if (!event.isTrusted) return;
58
+ rCancelContextMenuSwallow.current?.();
59
+ rCancelContextMenuSwallow.current = null;
60
+ event.preventDefault();
61
+ event.stopImmediatePropagation();
62
+ };
63
+ const cancel = () => doc.removeEventListener("contextmenu", onContextMenu, true);
64
+ rCancelContextMenuSwallow.current = cancel;
65
+ doc.addEventListener("contextmenu", onContextMenu, true);
66
+ doc.defaultView?.setTimeout(() => {
67
+ if (rCancelContextMenuSwallow.current === cancel) {
68
+ cancel();
69
+ rCancelContextMenuSwallow.current = null;
70
+ }
71
+ }, 0);
72
+ }, [editor]);
42
73
  const handlePointerDown = (0, import_react.useCallback)(
43
74
  (e) => {
44
- if (e.button === 0) {
45
- setIsPointing(true);
46
- rPointerState.current = {
47
- isDown: true,
48
- isDragging: false,
49
- start: new import_Vec.Vec(e.clientX, e.clientY)
50
- };
51
- rDidAPointerDownAndDragWhileMenuWasOpen.current = false;
52
- }
75
+ if (e.button !== 0 && e.button !== 2) return;
76
+ (0, import_react_dom.flushSync)(() => setIsPointing(true));
77
+ (0, import_dom.setPointerCapture)(e.currentTarget, e);
78
+ rPointerState.current = {
79
+ isDown: true,
80
+ isDragging: false,
81
+ button: e.button,
82
+ start: new import_Vec.Vec(e.clientX, e.clientY)
83
+ };
53
84
  if (e.button === 2) {
54
- const ownerDocument = editor.getContainerDocument();
55
- ownerDocument.addEventListener(
56
- "contextmenu",
57
- (event) => {
58
- event.preventDefault();
59
- event.stopImmediatePropagation();
60
- },
61
- { capture: true, once: true }
62
- );
85
+ if (!editor.options.rightClickPanning) {
86
+ swallowNextNativeContextMenu();
87
+ editor.menus.clearOpenMenus();
88
+ return;
89
+ }
90
+ const canvas = editor.getContainer().querySelector(".tl-canvas") ?? e.currentTarget;
91
+ canvasEvents.onPointerDown?.({ ...e, currentTarget: canvas });
92
+ swallowNextNativeContextMenu();
93
+ return;
63
94
  }
64
95
  editor.menus.clearOpenMenus();
65
96
  },
66
- [editor]
97
+ [canvasEvents, editor, swallowNextNativeContextMenu]
67
98
  );
68
- const rDidAPointerDownAndDragWhileMenuWasOpen = (0, import_react.useRef)(false);
69
99
  const handlePointerMove = (0, import_react.useCallback)(
70
100
  (e) => {
71
- if (!rPointerState.current.isDown) return;
72
- const { x, y } = rPointerState.current.start;
73
- if (!rDidAPointerDownAndDragWhileMenuWasOpen.current) {
74
- if (
75
- // We're pointing, but are we dragging?
76
- import_Vec.Vec.Dist2(rPointerState.current.start, new import_Vec.Vec(e.clientX, e.clientY)) > editor.options.dragDistanceSquared
77
- ) {
78
- rDidAPointerDownAndDragWhileMenuWasOpen.current = true;
79
- rPointerState.current = {
80
- ...rPointerState.current,
81
- isDown: true,
82
- isDragging: true
83
- };
84
- canvasEvents.onPointerDown?.({
85
- ...e,
86
- clientX: x,
87
- clientY: y,
88
- button: 0
89
- });
101
+ const state = rPointerState.current;
102
+ if (!state.isDown) return;
103
+ if (state.button !== 2 && !state.isDragging) {
104
+ if (import_Vec.Vec.Dist2(state.start, new import_Vec.Vec(e.clientX, e.clientY)) <= editor.options.dragDistanceSquared) {
105
+ return;
90
106
  }
91
- }
92
- if (rDidAPointerDownAndDragWhileMenuWasOpen.current) {
107
+ state.isDragging = true;
93
108
  editor.dispatch({
94
109
  type: "pointer",
95
110
  target: "canvas",
96
- name: "pointer_move",
97
- ...(0, import_getPointerInfo.getPointerInfo)(editor, e)
111
+ name: "pointer_down",
112
+ ...(0, import_getPointerInfo.getPointerInfo)(editor, { ...e, clientX: state.start.x, clientY: state.start.y })
98
113
  });
99
114
  }
115
+ editor.dispatch({
116
+ type: "pointer",
117
+ target: "canvas",
118
+ name: "pointer_move",
119
+ ...(0, import_getPointerInfo.getPointerInfo)(editor, e)
120
+ });
100
121
  },
101
- [canvasEvents, editor]
122
+ [editor]
102
123
  );
103
124
  const handlePointerUp = (0, import_react.useCallback)(
104
125
  (e) => {
105
- canvasEvents.onPointerUp?.(e);
126
+ const isStaticRightClick = e.button === 2 && !rPointerState.current.isDragging;
127
+ editor.dispatch({
128
+ type: "pointer",
129
+ target: "canvas",
130
+ name: "pointer_up",
131
+ ...(0, import_getPointerInfo.getPointerInfo)(editor, e)
132
+ });
133
+ if (isStaticRightClick && editor.options.rightClickPanning) {
134
+ const canvas = editor.getContainer().querySelector(".tl-canvas");
135
+ const trigger = canvas?.parentElement ?? e.currentTarget;
136
+ editor.timers.requestAnimationFrame(() => {
137
+ trigger.dispatchEvent(
138
+ new PointerEvent("contextmenu", {
139
+ bubbles: true,
140
+ clientX: e.clientX,
141
+ clientY: e.clientY,
142
+ button: 2,
143
+ buttons: 0,
144
+ pointerId: e.pointerId,
145
+ pointerType: e.pointerType,
146
+ isPrimary: e.isPrimary
147
+ })
148
+ );
149
+ });
150
+ }
151
+ (0, import_dom.releasePointerCapture)(e.currentTarget, e);
106
152
  setIsPointing(false);
107
153
  rPointerState.current = {
108
154
  isDown: false,
109
155
  isDragging: false,
156
+ button: 0,
110
157
  start: new import_Vec.Vec(e.clientX, e.clientY)
111
158
  };
112
- rDidAPointerDownAndDragWhileMenuWasOpen.current = false;
113
159
  },
114
- [canvasEvents]
160
+ [editor]
115
161
  );
116
162
  return showElement && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
117
163
  "div",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/components/MenuClickCapture.tsx"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { PointerEvent, useCallback, useRef, useState } from 'react'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\nimport { getPointerInfo } from '../utils/getPointerInfo'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\t// Whether any menus are open\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Whether we're pointing or not\u2014keep this component visible if we're pointing\n\tconst [isPointing, setIsPointing] = useState(false)\n\n\tconst showElement = isMenuOpen || isPointing\n\n\t// Get the same events that we use on the canvas\n\tconst canvasEvents = useCanvasEvents()\n\n\t// Keep track of the pointer state\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tstart: new Vec(),\n\t})\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tif (e.button === 0) {\n\t\t\t\tsetIsPointing(true)\n\t\t\t\trPointerState.current = {\n\t\t\t\t\tisDown: true,\n\t\t\t\t\tisDragging: false,\n\t\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t\t}\n\t\t\t\trDidAPointerDownAndDragWhileMenuWasOpen.current = false\n\t\t\t}\n\t\t\tif (e.button === 2) {\n\t\t\t\t// Swallow the contextmenu event that follows this right-click pointerdown.\n\t\t\t\t// clearOpenMenus() below triggers a synchronous render that unmounts this\n\t\t\t\t// component, so our React onContextMenu handler won't be around to catch it.\n\t\t\t\t// Without this, the contextmenu event reaches the Radix Trigger and briefly\n\t\t\t\t// opens a new context menu (which then immediately dismisses \u2014 causing a flash).\n\t\t\t\tconst ownerDocument = editor.getContainerDocument()\n\t\t\t\townerDocument.addEventListener(\n\t\t\t\t\t'contextmenu',\n\t\t\t\t\t(event) => {\n\t\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\t\tevent.stopImmediatePropagation()\n\t\t\t\t\t},\n\t\t\t\t\t{ capture: true, once: true }\n\t\t\t\t)\n\t\t\t}\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst rDidAPointerDownAndDragWhileMenuWasOpen = useRef(false)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Do nothing unless we're pointing\n\t\t\tif (!rPointerState.current.isDown) return\n\n\t\t\t// call the onPointerDown with the original pointer position\n\t\t\tconst { x, y } = rPointerState.current.start\n\n\t\t\tif (!rDidAPointerDownAndDragWhileMenuWasOpen.current) {\n\t\t\t\tif (\n\t\t\t\t\t// We're pointing, but are we dragging?\n\t\t\t\t\tVec.Dist2(rPointerState.current.start, new Vec(e.clientX, e.clientY)) >\n\t\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t\t) {\n\t\t\t\t\trDidAPointerDownAndDragWhileMenuWasOpen.current = true\n\t\t\t\t\t// Wehaddaeventitsadrag\n\t\t\t\t\trPointerState.current = {\n\t\t\t\t\t\t...rPointerState.current,\n\t\t\t\t\t\tisDown: true,\n\t\t\t\t\t\tisDragging: true,\n\t\t\t\t\t}\n\t\t\t\t\tcanvasEvents.onPointerDown?.({\n\t\t\t\t\t\t...e,\n\t\t\t\t\t\tclientX: x,\n\t\t\t\t\t\tclientY: y,\n\t\t\t\t\t\tbutton: 0,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (rDidAPointerDownAndDragWhileMenuWasOpen.current) {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\t[canvasEvents, editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\t// Run the pointer up\n\t\t\tcanvasEvents.onPointerUp?.(e)\n\t\t\t// Then turn off pointing\n\t\t\tsetIsPointing(false)\n\t\t\t// Reset the pointer state\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t\trDidAPointerDownAndDragWhileMenuWasOpen.current = false\n\t\t},\n\t\t[canvasEvents]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t\tonContextMenu={(e) => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport { type PointerEvent, useCallback, useEffect, useRef, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { useCanvasEvents } from '../hooks/useCanvasEvents'\nimport { useEditor } from '../hooks/useEditor'\nimport { Vec } from '../primitives/Vec'\nimport { releasePointerCapture, setPointerCapture } from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\n\n/**\n * When a menu is open, this component prevents the user from interacting with the canvas.\n *\n * @public @react\n */\nexport function MenuClickCapture() {\n\tconst editor = useEditor()\n\n\tconst isMenuOpen = useValue('is menu open', () => editor.menus.hasAnyOpenMenus(), [editor])\n\n\t// Keep this component mounted while the pointer is down so pointerup/move still\n\t// land here after a synchronous clearOpenMenus() flips isMenuOpen to false.\n\tconst [isPointing, setIsPointing] = useState(false)\n\tconst showElement = isMenuOpen || isPointing\n\n\tconst canvasEvents = useCanvasEvents()\n\n\tconst rPointerState = useRef({\n\t\tisDown: false,\n\t\tisDragging: false,\n\t\tbutton: 0,\n\t\tstart: new Vec(),\n\t})\n\n\t// Swallow the native contextmenu that follows a right-click pointerdown. Without\n\t// this, Radix's trigger catches the native event and opens a menu at the pointer-\n\t// DOWN position \u2014 then our own synthetic contextmenu (fired on pointerup) opens it\n\t// again at the release position, producing a visible flash.\n\tconst rCancelContextMenuSwallow = useRef<null | (() => void)>(null)\n\tuseEffect(\n\t\t() => () => {\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t},\n\t\t[]\n\t)\n\tconst swallowNextNativeContextMenu = useCallback(() => {\n\t\trCancelContextMenuSwallow.current?.()\n\t\tconst doc = editor.getContainerDocument()\n\t\tconst onContextMenu = (event: MouseEvent) => {\n\t\t\t// Skip our own synthetic contextmenu \u2014 only swallow the real browser one\n\t\t\tif (!event.isTrusted) return\n\t\t\trCancelContextMenuSwallow.current?.()\n\t\t\trCancelContextMenuSwallow.current = null\n\t\t\tevent.preventDefault()\n\t\t\tevent.stopImmediatePropagation()\n\t\t}\n\t\tconst cancel = () => doc.removeEventListener('contextmenu', onContextMenu, true)\n\t\trCancelContextMenuSwallow.current = cancel\n\t\tdoc.addEventListener('contextmenu', onContextMenu, true)\n\t\t// Drop the listener on the next tick if it never fires (e.g. pointer moved off-screen)\n\t\tdoc.defaultView?.setTimeout(() => {\n\t\t\tif (rCancelContextMenuSwallow.current === cancel) {\n\t\t\t\tcancel()\n\t\t\t\trCancelContextMenuSwallow.current = null\n\t\t\t}\n\t\t}, 0)\n\t}, [editor])\n\n\tconst handlePointerDown = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tif (e.button !== 0 && e.button !== 2) return\n\n\t\t\tflushSync(() => setIsPointing(true))\n\t\t\tsetPointerCapture(e.currentTarget, e)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: true,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton: e.button,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\n\t\t\tif (e.button === 2) {\n\t\t\t\tif (!editor.options.rightClickPanning) {\n\t\t\t\t\t// Right-click panning off: close the open menu and swallow the native\n\t\t\t\t\t// contextmenu that would otherwise briefly open a new one (causing a flash).\n\t\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t\t\teditor.menus.clearOpenMenus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Forward right-click pointerdown through the canvas's own handler so\n\t\t\t\t// pointer capture is also set on the canvas (load-bearing: without this\n\t\t\t\t// the context menu briefly flashes closed during consecutive right-clicks).\n\t\t\t\t// We don't clearOpenMenus() \u2014 Radix's DismissableLayer closes the menu\n\t\t\t\t// via outside-click detection, keeping its internal state in sync.\n\t\t\t\tconst canvas =\n\t\t\t\t\teditor.getContainer().querySelector<HTMLDivElement>('.tl-canvas') ?? e.currentTarget\n\t\t\t\tcanvasEvents.onPointerDown?.({ ...e, currentTarget: canvas })\n\t\t\t\tswallowNextNativeContextMenu()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\teditor.menus.clearOpenMenus()\n\t\t},\n\t\t[canvasEvents, editor, swallowNextNativeContextMenu]\n\t)\n\n\tconst handlePointerMove = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst state = rPointerState.current\n\t\t\tif (!state.isDown) return\n\n\t\t\t// Left-click: wait for the drag threshold before forwarding anything, then\n\t\t\t// replay pointerdown at the original start so the editor records the\n\t\t\t// correct drag origin. Right-click forwards moves immediately (pointerdown\n\t\t\t// was already dispatched in handlePointerDown).\n\t\t\tif (state.button !== 2 && !state.isDragging) {\n\t\t\t\tif (\n\t\t\t\t\tVec.Dist2(state.start, new Vec(e.clientX, e.clientY)) <=\n\t\t\t\t\teditor.options.dragDistanceSquared\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tstate.isDragging = true\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, { ...e, clientX: state.start.x, clientY: state.start.y }),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_move',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t})\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handlePointerUp = useCallback(\n\t\t(e: PointerEvent) => {\n\t\t\tconst isStaticRightClick = e.button === 2 && !rPointerState.current.isDragging\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_up',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t})\n\n\t\t\tif (isStaticRightClick && editor.options.rightClickPanning) {\n\t\t\t\t// Dispatch contextmenu on the canvas's parent (Radix's trigger) so the\n\t\t\t\t// menu opens at the release position. Bypassing the canvas avoids its\n\t\t\t\t// own onContextMenu handler, which preventDefaults non-synthesized events.\n\t\t\t\tconst canvas = editor.getContainer().querySelector<HTMLDivElement>('.tl-canvas')\n\t\t\t\tconst trigger = canvas?.parentElement ?? e.currentTarget\n\t\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\t\ttrigger.dispatchEvent(\n\t\t\t\t\t\tnew PointerEvent('contextmenu', {\n\t\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treleasePointerCapture(e.currentTarget, e)\n\t\t\tsetIsPointing(false)\n\t\t\trPointerState.current = {\n\t\t\t\tisDown: false,\n\t\t\t\tisDragging: false,\n\t\t\t\tbutton: 0,\n\t\t\t\tstart: new Vec(e.clientX, e.clientY),\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\tshowElement && (\n\t\t\t<div\n\t\t\t\tclassName=\"tlui-menu-click-capture\"\n\t\t\t\tdata-testid=\"menu-click-capture.content\"\n\t\t\t\t{...canvasEvents}\n\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\tonPointerMove={handlePointerMove}\n\t\t\t\tonPointerUp={handlePointerUp}\n\t\t\t\tonContextMenu={(e) => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t}}\n\t\t\t/>\n\t\t)\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -107,6 +107,13 @@ function renderIndicatorPath(ctx, indicatorPath) {
107
107
  }
108
108
  }
109
109
  const CanvasShapeIndicators = (0, import_react.memo)(function CanvasShapeIndicators2() {
110
+ const editor = (0, import_useEditor.useEditor)();
111
+ if (!editor.options.useCanvasIndicators) {
112
+ return null;
113
+ }
114
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CanvasShapeIndicatorsInner, {});
115
+ });
116
+ const CanvasShapeIndicatorsInner = (0, import_react.memo)(function CanvasShapeIndicatorsInner2() {
110
117
  const editor = (0, import_useEditor.useEditor)();
111
118
  const canvasRef = (0, import_react.useRef)(null);
112
119
  const rSelectedColor = (0, import_react.useRef)(null);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/components/default-components/CanvasShapeIndicators.tsx"],
4
- "sourcesContent": ["import { useComputed, useQuickReactor } from '@tldraw/state-react'\nimport { createComputedCache } from '@tldraw/store'\nimport { TLShape, TLShapeId } from '@tldraw/tlschema'\nimport { dedupe } from '@tldraw/utils'\nimport { memo, useEffect, useRef } from 'react'\nimport { Editor } from '../../editor/Editor'\nimport { TLIndicatorPath } from '../../editor/shapes/ShapeUtil'\nimport { getComputedStyle } from '../../exports/domUtils'\nimport { useColorMode } from '../../hooks/useColorMode'\nimport { useEditor } from '../../hooks/useEditor'\nimport { useActivePeerIds$ } from '../../hooks/usePeerIds'\n\ninterface CollaboratorIndicatorData {\n\tcolor: string\n\tshapeIds: TLShapeId[]\n}\n\ninterface RenderData {\n\tidsToDisplay: Set<TLShapeId>\n\trenderingShapeIds: Set<TLShapeId>\n\thintingShapeIds: TLShapeId[]\n\tcollaboratorIndicators: CollaboratorIndicatorData[]\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n\tif (a.size !== b.size) return false\n\tfor (const item of a) {\n\t\tif (!b.has(item)) return false\n\t}\n\treturn true\n}\n\nfunction arraysEqual<T>(a: readonly T[], b: readonly T[]): boolean {\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i] !== b[i]) return false\n\t}\n\treturn true\n}\n\nfunction collaboratorIndicatorsEqual(\n\ta: CollaboratorIndicatorData[],\n\tb: CollaboratorIndicatorData[]\n): boolean {\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i].color !== b[i].color) return false\n\t\tif (!arraysEqual(a[i].shapeIds, b[i].shapeIds)) return false\n\t}\n\treturn true\n}\n\nfunction renderDataEqual(a: RenderData, b: RenderData): boolean {\n\treturn (\n\t\tsetsEqual(a.idsToDisplay, b.idsToDisplay) &&\n\t\tsetsEqual(a.renderingShapeIds, b.renderingShapeIds) &&\n\t\tarraysEqual(a.hintingShapeIds, b.hintingShapeIds) &&\n\t\tcollaboratorIndicatorsEqual(a.collaboratorIndicators, b.collaboratorIndicators)\n\t)\n}\n\nconst indicatorPathCache = createComputedCache(\n\t'indicatorPath',\n\t(editor: Editor, shape: TLShape) => {\n\t\tconst util = editor.getShapeUtil(shape)\n\t\treturn util.getIndicatorPath(shape)\n\t}\n)\n\nconst getIndicatorPath = (editor: Editor, shape: TLShape) => {\n\treturn indicatorPathCache.get(editor, shape.id)\n}\n\nfunction renderShapeIndicator(\n\tctx: CanvasRenderingContext2D,\n\teditor: Editor,\n\tshapeId: TLShapeId,\n\trenderingShapeIds: Set<TLShapeId>\n): boolean {\n\tif (!renderingShapeIds.has(shapeId)) return false\n\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape || shape.isLocked) return false\n\n\tconst pageTransform = editor.getShapePageTransform(shape)\n\tif (!pageTransform) return false\n\n\tconst indicatorPath = getIndicatorPath(editor, shape)\n\tif (!indicatorPath) return false\n\n\tctx.save()\n\tctx.transform(\n\t\tpageTransform.a,\n\t\tpageTransform.b,\n\t\tpageTransform.c,\n\t\tpageTransform.d,\n\t\tpageTransform.e,\n\t\tpageTransform.f\n\t)\n\trenderIndicatorPath(ctx, indicatorPath)\n\tctx.restore()\n\n\treturn true\n}\n\nfunction renderIndicatorPath(ctx: CanvasRenderingContext2D, indicatorPath: TLIndicatorPath) {\n\tif (indicatorPath instanceof Path2D) {\n\t\tctx.stroke(indicatorPath)\n\t} else {\n\t\tconst { path, clipPath, additionalPaths } = indicatorPath\n\n\t\tif (clipPath) {\n\t\t\tctx.save()\n\t\t\tctx.clip(clipPath, 'evenodd')\n\t\t\tctx.stroke(path)\n\t\t\tctx.restore()\n\t\t} else {\n\t\t\tctx.stroke(path)\n\t\t}\n\n\t\tif (additionalPaths) {\n\t\t\tfor (const additionalPath of additionalPaths) {\n\t\t\t\tctx.stroke(additionalPath)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** @internal @react */\nexport const CanvasShapeIndicators = memo(function CanvasShapeIndicators() {\n\tconst editor = useEditor()\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\n\t// Cache the selected color to avoid getComputedStyle on every render\n\tconst rSelectedColor = useRef<string | null>(null)\n\tconst colorMode = useColorMode()\n\n\tuseEffect(() => {\n\t\tconst timer = editor.timers.setTimeout(() => {\n\t\t\trSelectedColor.current = null\n\t\t}, 0)\n\t\treturn () => clearTimeout(timer)\n\t}, [colorMode, editor])\n\n\t// Get active peer IDs (already handles time-based state transitions)\n\tconst activePeerIds$ = useActivePeerIds$()\n\n\tconst $renderData = useComputed(\n\t\t'indicator render data',\n\t\t() => {\n\t\t\tconst renderingShapeIds = new Set(editor.getRenderingShapes().map((s) => s.id))\n\n\t\t\t// Compute ids to display for selected/hovered shapes\n\t\t\tconst idsToDisplay = new Set<TLShapeId>()\n\t\t\tconst instanceState = editor.getInstanceState()\n\t\t\tconst isChangingStyle = instanceState.isChangingStyle\n\t\t\tconst isIdleOrEditing = editor.isInAny('select.idle', 'select.editing_shape')\n\t\t\tconst isInSelectState = editor.isInAny(\n\t\t\t\t'select.brushing',\n\t\t\t\t'select.scribble_brushing',\n\t\t\t\t'select.pointing_shape',\n\t\t\t\t'select.pointing_selection',\n\t\t\t\t'select.pointing_handle'\n\t\t\t)\n\n\t\t\tif (!isChangingStyle && (isIdleOrEditing || isInSelectState)) {\n\t\t\t\tfor (const id of editor.getSelectedShapeIds()) {\n\t\t\t\t\tidsToDisplay.add(id)\n\t\t\t\t}\n\t\t\t\tif (isIdleOrEditing && instanceState.isHoveringCanvas && !instanceState.isCoarsePointer) {\n\t\t\t\t\tconst hovered = editor.getHoveredShapeId()\n\t\t\t\t\tif (hovered) idsToDisplay.add(hovered)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compute hinting shape ids\n\t\t\tconst hintingShapeIds = dedupe(editor.getHintingShapeIds())\n\n\t\t\t// Compute collaborator indicators\n\t\t\tconst collaboratorIndicators: CollaboratorIndicatorData[] = []\n\t\t\tconst currentPageId = editor.getCurrentPageId()\n\t\t\tconst activePeerIds = activePeerIds$.get()\n\n\t\t\tconst collaborators = editor.getCollaborators()\n\t\t\tfor (const peerId of activePeerIds.values()) {\n\t\t\t\t// Skip collaborators on different pages\n\t\t\t\tconst presence = collaborators.find((c) => c.userId === peerId)\n\t\t\t\tif (!presence || presence.currentPageId !== currentPageId) continue\n\n\t\t\t\t// Filter to shapes that are visible and on the current rendering set\n\t\t\t\tconst visibleShapeIds = presence.selectedShapeIds.filter(\n\t\t\t\t\t(id) => renderingShapeIds.has(id) && !editor.isShapeHidden(id)\n\t\t\t\t)\n\n\t\t\t\tif (visibleShapeIds.length > 0) {\n\t\t\t\t\tcollaboratorIndicators.push({\n\t\t\t\t\t\tcolor: presence.color,\n\t\t\t\t\t\tshapeIds: visibleShapeIds,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tidsToDisplay,\n\t\t\t\trenderingShapeIds,\n\t\t\t\thintingShapeIds,\n\t\t\t\tcollaboratorIndicators,\n\t\t\t}\n\t\t},\n\t\t{ isEqual: renderDataEqual },\n\t\t[editor, activePeerIds$]\n\t)\n\n\tuseQuickReactor(\n\t\t'canvas indicators render',\n\t\t() => {\n\t\t\tconst canvas = canvasRef.current\n\t\t\tif (!canvas) return\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tconst { idsToDisplay, renderingShapeIds, hintingShapeIds, collaboratorIndicators } =\n\t\t\t\t$renderData.get()\n\n\t\t\tconst { w, h } = editor.getViewportScreenBounds()\n\t\t\tconst dpr = editor.getInstanceState().devicePixelRatio\n\t\t\tconst { x: cx, y: cy, z: zoom } = editor.getCamera()\n\n\t\t\tconst canvasWidth = Math.ceil(w * dpr)\n\t\t\tconst canvasHeight = Math.ceil(h * dpr)\n\n\t\t\tif (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\t\t\t\tcanvas.width = canvasWidth\n\t\t\t\tcanvas.height = canvasHeight\n\t\t\t\tcanvas.style.width = `${w}px`\n\t\t\t\tcanvas.style.height = `${h}px`\n\t\t\t}\n\n\t\t\tctx.resetTransform()\n\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height)\n\n\t\t\tctx.scale(dpr, dpr)\n\t\t\tctx.scale(zoom, zoom)\n\t\t\tctx.translate(cx, cy)\n\n\t\t\tctx.lineCap = 'round'\n\t\t\tctx.lineJoin = 'round'\n\n\t\t\t// Draw collaborator indicators first (underneath local indicators)\n\t\t\t// Use 0.5 opacity to match the original SVG-based collaborator indicators\n\t\t\tctx.lineWidth = 1.5 / zoom\n\t\t\tfor (const collaborator of collaboratorIndicators) {\n\t\t\t\tctx.strokeStyle = collaborator.color\n\t\t\t\tctx.globalAlpha = 0.7\n\t\t\t\tfor (const shapeId of collaborator.shapeIds) {\n\t\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reset alpha for local indicators\n\t\t\tctx.globalAlpha = 1.0\n\n\t\t\t// Use cached color, only call getComputedStyle when cache is empty\n\t\t\tif (!rSelectedColor.current) {\n\t\t\t\trSelectedColor.current = getComputedStyle(canvas).getPropertyValue('--tl-color-selected')\n\t\t\t}\n\n\t\t\tctx.strokeStyle = rSelectedColor.current\n\n\t\t\t// Draw selected/hovered indicators (1.5px stroke)\n\t\t\tctx.lineWidth = 1.5 / zoom\n\t\t\tfor (const shapeId of idsToDisplay) {\n\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t}\n\n\t\t\t// Draw hinted indicators with a thicker stroke (2.5px)\n\t\t\tif (hintingShapeIds.length > 0) {\n\t\t\t\tctx.lineWidth = 2.5 / zoom\n\t\t\t\tfor (const shapeId of hintingShapeIds) {\n\t\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, $renderData]\n\t)\n\n\treturn <canvas ref={canvasRef} className=\"tl-canvas-indicators\" />\n})\n"],
5
- "mappings": "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",
6
- "names": ["CanvasShapeIndicators"]
4
+ "sourcesContent": ["import { useComputed, useQuickReactor } from '@tldraw/state-react'\nimport { createComputedCache } from '@tldraw/store'\nimport { TLShape, TLShapeId } from '@tldraw/tlschema'\nimport { dedupe } from '@tldraw/utils'\nimport { memo, useEffect, useRef } from 'react'\nimport { Editor } from '../../editor/Editor'\nimport { TLIndicatorPath } from '../../editor/shapes/ShapeUtil'\nimport { getComputedStyle } from '../../exports/domUtils'\nimport { useColorMode } from '../../hooks/useColorMode'\nimport { useEditor } from '../../hooks/useEditor'\nimport { useActivePeerIds$ } from '../../hooks/usePeerIds'\n\ninterface CollaboratorIndicatorData {\n\tcolor: string\n\tshapeIds: TLShapeId[]\n}\n\ninterface RenderData {\n\tidsToDisplay: Set<TLShapeId>\n\trenderingShapeIds: Set<TLShapeId>\n\thintingShapeIds: TLShapeId[]\n\tcollaboratorIndicators: CollaboratorIndicatorData[]\n}\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n\tif (a.size !== b.size) return false\n\tfor (const item of a) {\n\t\tif (!b.has(item)) return false\n\t}\n\treturn true\n}\n\nfunction arraysEqual<T>(a: readonly T[], b: readonly T[]): boolean {\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i] !== b[i]) return false\n\t}\n\treturn true\n}\n\nfunction collaboratorIndicatorsEqual(\n\ta: CollaboratorIndicatorData[],\n\tb: CollaboratorIndicatorData[]\n): boolean {\n\tif (a.length !== b.length) return false\n\tfor (let i = 0; i < a.length; i++) {\n\t\tif (a[i].color !== b[i].color) return false\n\t\tif (!arraysEqual(a[i].shapeIds, b[i].shapeIds)) return false\n\t}\n\treturn true\n}\n\nfunction renderDataEqual(a: RenderData, b: RenderData): boolean {\n\treturn (\n\t\tsetsEqual(a.idsToDisplay, b.idsToDisplay) &&\n\t\tsetsEqual(a.renderingShapeIds, b.renderingShapeIds) &&\n\t\tarraysEqual(a.hintingShapeIds, b.hintingShapeIds) &&\n\t\tcollaboratorIndicatorsEqual(a.collaboratorIndicators, b.collaboratorIndicators)\n\t)\n}\n\nconst indicatorPathCache = createComputedCache(\n\t'indicatorPath',\n\t(editor: Editor, shape: TLShape) => {\n\t\tconst util = editor.getShapeUtil(shape)\n\t\treturn util.getIndicatorPath(shape)\n\t}\n)\n\nconst getIndicatorPath = (editor: Editor, shape: TLShape) => {\n\treturn indicatorPathCache.get(editor, shape.id)\n}\n\nfunction renderShapeIndicator(\n\tctx: CanvasRenderingContext2D,\n\teditor: Editor,\n\tshapeId: TLShapeId,\n\trenderingShapeIds: Set<TLShapeId>\n): boolean {\n\tif (!renderingShapeIds.has(shapeId)) return false\n\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape || shape.isLocked) return false\n\n\tconst pageTransform = editor.getShapePageTransform(shape)\n\tif (!pageTransform) return false\n\n\tconst indicatorPath = getIndicatorPath(editor, shape)\n\tif (!indicatorPath) return false\n\n\tctx.save()\n\tctx.transform(\n\t\tpageTransform.a,\n\t\tpageTransform.b,\n\t\tpageTransform.c,\n\t\tpageTransform.d,\n\t\tpageTransform.e,\n\t\tpageTransform.f\n\t)\n\trenderIndicatorPath(ctx, indicatorPath)\n\tctx.restore()\n\n\treturn true\n}\n\nfunction renderIndicatorPath(ctx: CanvasRenderingContext2D, indicatorPath: TLIndicatorPath) {\n\tif (indicatorPath instanceof Path2D) {\n\t\tctx.stroke(indicatorPath)\n\t} else {\n\t\tconst { path, clipPath, additionalPaths } = indicatorPath\n\n\t\tif (clipPath) {\n\t\t\tctx.save()\n\t\t\tctx.clip(clipPath, 'evenodd')\n\t\t\tctx.stroke(path)\n\t\t\tctx.restore()\n\t\t} else {\n\t\t\tctx.stroke(path)\n\t\t}\n\n\t\tif (additionalPaths) {\n\t\t\tfor (const additionalPath of additionalPaths) {\n\t\t\t\tctx.stroke(additionalPath)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** @internal @react */\nexport const CanvasShapeIndicators = memo(function CanvasShapeIndicators() {\n\tconst editor = useEditor()\n\n\t// Skip canvas indicator rendering when the option is disabled (e.g. A/B test)\n\tif (!editor.options.useCanvasIndicators) {\n\t\treturn null\n\t}\n\n\treturn <CanvasShapeIndicatorsInner />\n})\n\nconst CanvasShapeIndicatorsInner = memo(function CanvasShapeIndicatorsInner() {\n\tconst editor = useEditor()\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\n\t// Cache the selected color to avoid getComputedStyle on every render\n\tconst rSelectedColor = useRef<string | null>(null)\n\tconst colorMode = useColorMode()\n\n\tuseEffect(() => {\n\t\tconst timer = editor.timers.setTimeout(() => {\n\t\t\trSelectedColor.current = null\n\t\t}, 0)\n\t\treturn () => clearTimeout(timer)\n\t}, [colorMode, editor])\n\n\t// Get active peer IDs (already handles time-based state transitions)\n\tconst activePeerIds$ = useActivePeerIds$()\n\n\tconst $renderData = useComputed(\n\t\t'indicator render data',\n\t\t() => {\n\t\t\tconst renderingShapeIds = new Set(editor.getRenderingShapes().map((s) => s.id))\n\n\t\t\t// Compute ids to display for selected/hovered shapes\n\t\t\tconst idsToDisplay = new Set<TLShapeId>()\n\t\t\tconst instanceState = editor.getInstanceState()\n\t\t\tconst isChangingStyle = instanceState.isChangingStyle\n\t\t\tconst isIdleOrEditing = editor.isInAny('select.idle', 'select.editing_shape')\n\t\t\tconst isInSelectState = editor.isInAny(\n\t\t\t\t'select.brushing',\n\t\t\t\t'select.scribble_brushing',\n\t\t\t\t'select.pointing_shape',\n\t\t\t\t'select.pointing_selection',\n\t\t\t\t'select.pointing_handle'\n\t\t\t)\n\n\t\t\tif (!isChangingStyle && (isIdleOrEditing || isInSelectState)) {\n\t\t\t\tfor (const id of editor.getSelectedShapeIds()) {\n\t\t\t\t\tidsToDisplay.add(id)\n\t\t\t\t}\n\t\t\t\tif (isIdleOrEditing && instanceState.isHoveringCanvas && !instanceState.isCoarsePointer) {\n\t\t\t\t\tconst hovered = editor.getHoveredShapeId()\n\t\t\t\t\tif (hovered) idsToDisplay.add(hovered)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Compute hinting shape ids\n\t\t\tconst hintingShapeIds = dedupe(editor.getHintingShapeIds())\n\n\t\t\t// Compute collaborator indicators\n\t\t\tconst collaboratorIndicators: CollaboratorIndicatorData[] = []\n\t\t\tconst currentPageId = editor.getCurrentPageId()\n\t\t\tconst activePeerIds = activePeerIds$.get()\n\n\t\t\tconst collaborators = editor.getCollaborators()\n\t\t\tfor (const peerId of activePeerIds.values()) {\n\t\t\t\t// Skip collaborators on different pages\n\t\t\t\tconst presence = collaborators.find((c) => c.userId === peerId)\n\t\t\t\tif (!presence || presence.currentPageId !== currentPageId) continue\n\n\t\t\t\t// Filter to shapes that are visible and on the current rendering set\n\t\t\t\tconst visibleShapeIds = presence.selectedShapeIds.filter(\n\t\t\t\t\t(id) => renderingShapeIds.has(id) && !editor.isShapeHidden(id)\n\t\t\t\t)\n\n\t\t\t\tif (visibleShapeIds.length > 0) {\n\t\t\t\t\tcollaboratorIndicators.push({\n\t\t\t\t\t\tcolor: presence.color,\n\t\t\t\t\t\tshapeIds: visibleShapeIds,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tidsToDisplay,\n\t\t\t\trenderingShapeIds,\n\t\t\t\thintingShapeIds,\n\t\t\t\tcollaboratorIndicators,\n\t\t\t}\n\t\t},\n\t\t{ isEqual: renderDataEqual },\n\t\t[editor, activePeerIds$]\n\t)\n\n\tuseQuickReactor(\n\t\t'canvas indicators render',\n\t\t() => {\n\t\t\tconst canvas = canvasRef.current\n\t\t\tif (!canvas) return\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tconst { idsToDisplay, renderingShapeIds, hintingShapeIds, collaboratorIndicators } =\n\t\t\t\t$renderData.get()\n\n\t\t\tconst { w, h } = editor.getViewportScreenBounds()\n\t\t\tconst dpr = editor.getInstanceState().devicePixelRatio\n\t\t\tconst { x: cx, y: cy, z: zoom } = editor.getCamera()\n\n\t\t\tconst canvasWidth = Math.ceil(w * dpr)\n\t\t\tconst canvasHeight = Math.ceil(h * dpr)\n\n\t\t\tif (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\t\t\t\tcanvas.width = canvasWidth\n\t\t\t\tcanvas.height = canvasHeight\n\t\t\t\tcanvas.style.width = `${w}px`\n\t\t\t\tcanvas.style.height = `${h}px`\n\t\t\t}\n\n\t\t\tctx.resetTransform()\n\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height)\n\n\t\t\tctx.scale(dpr, dpr)\n\t\t\tctx.scale(zoom, zoom)\n\t\t\tctx.translate(cx, cy)\n\n\t\t\tctx.lineCap = 'round'\n\t\t\tctx.lineJoin = 'round'\n\n\t\t\t// Draw collaborator indicators first (underneath local indicators)\n\t\t\t// Use 0.5 opacity to match the original SVG-based collaborator indicators\n\t\t\tctx.lineWidth = 1.5 / zoom\n\t\t\tfor (const collaborator of collaboratorIndicators) {\n\t\t\t\tctx.strokeStyle = collaborator.color\n\t\t\t\tctx.globalAlpha = 0.7\n\t\t\t\tfor (const shapeId of collaborator.shapeIds) {\n\t\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reset alpha for local indicators\n\t\t\tctx.globalAlpha = 1.0\n\n\t\t\t// Use cached color, only call getComputedStyle when cache is empty\n\t\t\tif (!rSelectedColor.current) {\n\t\t\t\trSelectedColor.current = getComputedStyle(canvas).getPropertyValue('--tl-color-selected')\n\t\t\t}\n\n\t\t\tctx.strokeStyle = rSelectedColor.current\n\n\t\t\t// Draw selected/hovered indicators (1.5px stroke)\n\t\t\tctx.lineWidth = 1.5 / zoom\n\t\t\tfor (const shapeId of idsToDisplay) {\n\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t}\n\n\t\t\t// Draw hinted indicators with a thicker stroke (2.5px)\n\t\t\tif (hintingShapeIds.length > 0) {\n\t\t\t\tctx.lineWidth = 2.5 / zoom\n\t\t\t\tfor (const shapeId of hintingShapeIds) {\n\t\t\t\t\trenderShapeIndicator(ctx, editor, shapeId, renderingShapeIds)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, $renderData]\n\t)\n\n\treturn <canvas ref={canvasRef} className=\"tl-canvas-indicators\" />\n})\n"],
5
+ "mappings": "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",
6
+ "names": ["CanvasShapeIndicators", "CanvasShapeIndicatorsInner"]
7
7
  }
@@ -377,7 +377,9 @@ function HintedShapeIndicator() {
377
377
  const ids = (0, import_state_react.useValue)(
378
378
  "hinting shape ids without canvas indicator",
379
379
  () => {
380
- return (0, import_utils.dedupe)(editor.getHintingShapeIds()).filter((id) => {
380
+ const hintingIds = (0, import_utils.dedupe)(editor.getHintingShapeIds());
381
+ if (!editor.options.useCanvasIndicators) return hintingIds;
382
+ return hintingIds.filter((id) => {
381
383
  const shape = editor.getShape(id);
382
384
  if (!shape) return false;
383
385
  const util = editor.getShapeUtil(shape);