tldraw 4.3.0-canary.d8da2a99f394 → 4.3.0-canary.e1766dd4eab3

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 (310) hide show
  1. package/dist-cjs/index.d.ts +26 -5
  2. package/dist-cjs/index.js +2 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  5. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +2 -2
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +9 -12
  9. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  11. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  12. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
  14. package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  16. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  17. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  18. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  19. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
  20. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  21. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  22. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
  23. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  24. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +10 -6
  25. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  27. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +1 -1
  28. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  29. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  30. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +5 -5
  31. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  32. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  33. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +2 -1
  34. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  35. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +14 -2
  36. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +3 -3
  37. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +11 -3
  38. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +3 -3
  39. package/dist-cjs/lib/shapes/shared/ShapeFill.js +2 -2
  40. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  41. package/dist-cjs/lib/shapes/shared/crop.js +1 -0
  42. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  43. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  44. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  45. package/dist-cjs/lib/shapes/shared/{useForceSolid.js → useEfficientZoomThreshold.js} +10 -7
  46. package/dist-cjs/lib/shapes/shared/useEfficientZoomThreshold.js.map +7 -0
  47. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +1 -1
  48. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  49. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -2
  50. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  51. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  52. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  53. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
  54. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  55. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  56. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +1 -4
  57. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  58. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  59. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  60. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
  61. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  62. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js +30 -10
  63. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  64. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  65. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  66. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  67. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  68. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  69. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  70. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js +3 -9
  72. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
  74. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  76. package/dist-cjs/lib/ui/components/ZoomMenu/DefaultZoomMenu.js +1 -1
  77. package/dist-cjs/lib/ui/components/ZoomMenu/DefaultZoomMenu.js.map +2 -2
  78. package/dist-cjs/lib/ui/components/menu-items.js +3 -1
  79. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +143 -88
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  84. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +1 -1
  85. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  86. package/dist-cjs/lib/ui/context/actions.js +1 -2
  87. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  88. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  89. package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
  90. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  91. package/dist-cjs/lib/ui/version.js +3 -3
  92. package/dist-cjs/lib/ui/version.js.map +1 -1
  93. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +8 -0
  94. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  95. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  96. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  97. package/dist-cjs/lib/utils/text/richText.js +7 -17
  98. package/dist-cjs/lib/utils/text/richText.js.map +3 -3
  99. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  100. package/dist-esm/index.d.mts +26 -5
  101. package/dist-esm/index.mjs +3 -1
  102. package/dist-esm/index.mjs.map +2 -2
  103. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  104. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +2 -2
  105. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  106. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  107. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +10 -14
  108. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  109. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  110. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  111. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
  112. package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
  113. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  114. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  115. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +3 -3
  116. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  117. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
  118. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  119. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  120. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +1 -1
  121. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  122. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +10 -6
  123. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  125. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +1 -1
  126. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  128. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -5
  129. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  130. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  131. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +3 -2
  132. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  133. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +14 -2
  134. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  135. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +11 -3
  136. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  137. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +2 -2
  138. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  139. package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
  140. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  141. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  142. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  143. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs +12 -0
  144. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs.map +7 -0
  145. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +1 -1
  146. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  147. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -2
  148. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  149. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  150. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +1 -1
  151. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
  152. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  153. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +1 -4
  154. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  155. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +1 -4
  156. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  157. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  158. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  159. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
  160. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  161. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs +30 -10
  162. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  163. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  164. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  165. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +1 -4
  166. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  167. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  168. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  169. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  170. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  171. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs +2 -8
  172. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs.map +2 -2
  173. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
  174. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  175. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  176. package/dist-esm/lib/ui/components/ZoomMenu/DefaultZoomMenu.mjs +1 -1
  177. package/dist-esm/lib/ui/components/ZoomMenu/DefaultZoomMenu.mjs.map +2 -2
  178. package/dist-esm/lib/ui/components/menu-items.mjs +4 -5
  179. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  180. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +2 -2
  181. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  182. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +151 -90
  183. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  184. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +2 -2
  185. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  186. package/dist-esm/lib/ui/context/actions.mjs +1 -2
  187. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  188. package/dist-esm/lib/ui/hooks/menu-hooks.mjs +1 -4
  189. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  190. package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
  191. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  192. package/dist-esm/lib/ui/version.mjs +3 -3
  193. package/dist-esm/lib/ui/version.mjs.map +1 -1
  194. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +8 -0
  195. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  196. package/dist-esm/lib/utils/export/exportAs.mjs +1 -3
  197. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  198. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  199. package/dist-esm/lib/utils/text/richText.mjs +3 -3
  200. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  201. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  202. package/package.json +10 -10
  203. package/src/index.ts +1 -0
  204. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
  205. package/src/lib/canvas/TldrawSelectionForeground.tsx +6 -11
  206. package/src/lib/defaultExternalContentHandlers.ts +3 -4
  207. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
  208. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +11 -13
  209. package/src/lib/shapes/arrow/arrow-types.ts +2 -0
  210. package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
  211. package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
  212. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
  213. package/src/lib/shapes/arrow/shared.ts +4 -4
  214. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
  215. package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
  216. package/src/lib/shapes/draw/DrawShapeUtil.tsx +3 -3
  217. package/src/lib/shapes/draw/toolStates/Drawing.ts +4 -4
  218. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  219. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  220. package/src/lib/shapes/frame/FrameShapeUtil.tsx +1 -1
  221. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +10 -2
  222. package/src/lib/shapes/geo/GeoShapeUtil.tsx +9 -4
  223. package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
  224. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +1 -1
  225. package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
  226. package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
  227. package/src/lib/shapes/line/toolStates/Pointing.ts +1 -1
  228. package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
  229. package/src/lib/shapes/note/NoteShapeUtil.tsx +7 -8
  230. package/src/lib/shapes/note/noteHelpers.ts +2 -2
  231. package/src/lib/shapes/shared/HyperlinkButton.tsx +3 -2
  232. package/src/lib/shapes/shared/PlainTextLabel.tsx +12 -2
  233. package/src/lib/shapes/shared/RichTextLabel.tsx +13 -3
  234. package/src/lib/shapes/shared/ShapeFill.tsx +2 -2
  235. package/src/lib/shapes/shared/crop.ts +1 -0
  236. package/src/lib/shapes/shared/useEditablePlainText.ts +7 -3
  237. package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
  238. package/src/lib/shapes/shared/useEfficientZoomThreshold.ts +10 -0
  239. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +1 -1
  240. package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
  241. package/src/lib/shapes/text/TextShapeUtil.tsx +5 -0
  242. package/src/lib/shapes/text/toolStates/Pointing.ts +1 -1
  243. package/src/lib/shapes/video/VideoShapeUtil.tsx +2 -1
  244. package/src/lib/tools/EraserTool/childStates/Erasing.ts +3 -5
  245. package/src/lib/tools/EraserTool/childStates/Pointing.ts +3 -16
  246. package/src/lib/tools/SelectTool/DragAndDropManager.ts +2 -4
  247. package/src/lib/tools/SelectTool/childStates/Brushing.ts +2 -6
  248. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +2 -3
  249. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +4 -7
  250. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +46 -15
  251. package/src/lib/tools/SelectTool/childStates/Idle.ts +6 -10
  252. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
  253. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +4 -12
  254. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
  255. package/src/lib/tools/SelectTool/childStates/Resizing.ts +2 -4
  256. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +2 -4
  257. package/src/lib/tools/SelectTool/childStates/Translating.ts +1 -3
  258. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.tsx +1 -9
  259. package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
  260. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
  261. package/src/lib/ui/components/ZoomMenu/DefaultZoomMenu.tsx +1 -1
  262. package/src/lib/ui/components/menu-items.tsx +9 -15
  263. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  264. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +196 -108
  265. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +2 -2
  266. package/src/lib/ui/context/actions.tsx +9 -13
  267. package/src/lib/ui/hooks/menu-hooks.ts +9 -19
  268. package/src/lib/ui/hooks/useFlatten.ts +1 -2
  269. package/src/lib/ui/hooks/useTools.tsx +1 -2
  270. package/src/lib/ui/version.ts +3 -3
  271. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +8 -0
  272. package/src/lib/utils/export/exportAs.ts +2 -9
  273. package/src/lib/utils/frames/frames.ts +1 -1
  274. package/src/lib/utils/text/richText.ts +3 -3
  275. package/src/lib/utils/tldr/buildFromV1Document.ts +12 -17
  276. package/src/test/Editor.test.tsx +38 -12
  277. package/src/test/SelectTool.test.ts +11 -19
  278. package/src/test/TestEditor.ts +1 -4
  279. package/src/test/TldrawEditor.test.tsx +21 -18
  280. package/src/test/bindings.test.tsx +29 -25
  281. package/src/test/bindingsIndex.test.tsx +4 -4
  282. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +2 -2
  283. package/src/test/commands/cameraState.test.ts +299 -0
  284. package/src/test/commands/createShape.test.ts +64 -0
  285. package/src/test/commands/createShapes.test.ts +15 -1
  286. package/src/test/commands/getSvgString.test.ts +2 -2
  287. package/src/test/commands/isShapeOfType.test.ts +44 -0
  288. package/src/test/commands/putContent.test.ts +80 -1
  289. package/src/test/commands/updateShape.test.ts +67 -0
  290. package/src/test/commands/updateShapes.test.ts +21 -5
  291. package/src/test/custom-clipping.test.ts +36 -35
  292. package/src/test/customSnapping.test.tsx +77 -62
  293. package/src/test/duplicate.test.ts +1 -1
  294. package/src/test/frames.test.ts +2 -2
  295. package/src/test/getCulledShapes.test.tsx +11 -3
  296. package/src/test/getShapeAtPoint.test.ts +2 -2
  297. package/src/test/groups.test.tsx +6 -3
  298. package/src/test/resizing.test.ts +9 -13
  299. package/src/test/selection-omnibus.test.ts +11 -11
  300. package/src/test/shapeutils.test.ts +1 -1
  301. package/src/test/styles2.test.tsx +1 -1
  302. package/src/test/styles3.test.ts +5 -5
  303. package/src/test/test-jsx.tsx +69 -57
  304. package/src/test/text.test.ts +15 -17
  305. package/src/test/translating.test.ts +6 -8
  306. package/tldraw.css +8 -4
  307. package/dist-cjs/lib/shapes/shared/useForceSolid.js.map +0 -7
  308. package/dist-esm/lib/shapes/shared/useForceSolid.mjs +0 -9
  309. package/dist-esm/lib/shapes/shared/useForceSolid.mjs.map +0 -7
  310. package/src/lib/shapes/shared/useForceSolid.ts +0 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/arrow-types.ts"],
4
- "sourcesContent": ["import { Editor, TLArrowShapeArrowheadStyle, TLDefaultSizeStyle, VecLike } from '@tldraw/editor'\nimport { ElbowArrowInfo, ElbowArrowRoute } from './elbow/definitions'\nimport { TLArrowBindings } from './shared'\n\n/**\n * Options for the arrow shape.\n *\n * @example\n * ```tsx\n * const shapeUtils = [\n * ArrowShapeUtil.configure({ arcArrowCenterSnapDistance: 0 }),\n * ]\n *\n * function MyApp() {\n * return <Tldraw shapeUtils={shapeUtils} />\n * }\n * ```\n *\n * @public\n */\nexport interface ArrowShapeOptions {\n\t/**\n\t * How far should elbow arrows expand from the shapes they're targeting?\n\t */\n\treadonly expandElbowLegLength: Record<TLDefaultSizeStyle, number>\n\t/**\n\t * The minimum length of an elbow arrow's leg.\n\t */\n\treadonly minElbowLegLength: Record<TLDefaultSizeStyle, number>\n\t/**\n\t * The minimum distance, in screen pixels, between two handles on an elbow arrow. If two handles\n\t * would be closer than this distance, they're both hidden.\n\t */\n\treadonly minElbowHandleDistance: number\n\n\t/**\n\t * The distance, in screen pixels, at which we snap to the center of a target shape when drawing\n\t * an arc arrow. Set to 0 to disable.\n\t */\n\treadonly arcArrowCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the center of a target shape when drawing\n\t * an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the edge of a target shape when drawing\n\t * an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowEdgeSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to one of the 4 directional points (top,\n\t * right, bottom, left) of a target shape when drawing an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowPointSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the axis passing through the center of a\n\t * shape when drawing an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowAxisSnapDistance: number\n\n\t/**\n\t * The distance, in screen pixels, at which we snap an arrow label to center of the arrow when\n\t * dragging it. Set to 0 to disable.\n\t */\n\treadonly labelCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap an elbow arrow midpoint handle to the\n\t * midpoint between two shapes. Set to 0 to disable.\n\t */\n\treadonly elbowMidpointSnapDistance: number\n\t/**\n\t * The minimum length, in screen pixels, of an elbow arrows midpoint segment before we show the\n\t * handle for dragging that segment.\n\t */\n\treadonly elbowMinSegmentLengthToShowMidpointHandle: number\n\n\t/**\n\t * When hovering over a shape using the arrow tool, how long should we wait before we assume the\n\t * user is targeting precisely instead of imprecisely.\n\t */\n\treadonly hoverPreciseTimeout: number\n\t/**\n\t * When pointing at a shape using the arrow tool or dragging an arrow terminal handle, how long\n\t * should we wait before we assume the user is targeting precisely instead of imprecisely.\n\t */\n\treadonly pointingPreciseTimeout: number\n\n\t/**\n\t * When creating an arrow, should it stop exactly at the pointer, or should\n\t * it stop at the edge of the target shape.\n\t */\n\tshouldBeExact(editor: Editor, isPrecise: boolean): boolean\n\t/**\n\t * When creating an arrow, should it bind to the target shape.\n\t */\n\tshouldIgnoreTargets(editor: Editor): boolean\n}\n\n/** @public */\nexport interface TLArrowPoint {\n\thandle: VecLike\n\tpoint: VecLike\n\tarrowhead: TLArrowShapeArrowheadStyle\n}\n\n/** @public */\nexport interface TLArcInfo {\n\tcenter: VecLike\n\tradius: number\n\tsize: number\n\tlength: number\n\tlargeArcFlag: number\n\tsweepFlag: number\n}\n\n/** @public */\nexport interface TLArcArrowInfo {\n\tbindings: TLArrowBindings\n\ttype: 'arc'\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\tmiddle: VecLike\n\thandleArc: TLArcInfo\n\tbodyArc: TLArcInfo\n\tisValid: boolean\n}\n\n/** @public */\nexport interface TLStraightArrowInfo {\n\tbindings: TLArrowBindings\n\ttype: 'straight'\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\tmiddle: VecLike\n\tisValid: boolean\n\tlength: number\n}\n\n/** @public */\nexport interface TLElbowArrowInfo {\n\ttype: 'elbow'\n\tbindings: TLArrowBindings\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\telbow: ElbowArrowInfo\n\troute: ElbowArrowRoute\n\tisValid: boolean\n}\n\n/** @public */\nexport type TLArrowInfo = TLArcArrowInfo | TLStraightArrowInfo | TLElbowArrowInfo\n"],
4
+ "sourcesContent": ["import { Editor, TLArrowShapeArrowheadStyle, TLDefaultSizeStyle, VecLike } from '@tldraw/editor'\nimport { ElbowArrowInfo, ElbowArrowRoute } from './elbow/definitions'\nimport { TLArrowBindings } from './shared'\n\n/**\n * Options for the arrow shape.\n *\n * @example\n * ```tsx\n * const shapeUtils = [\n * ArrowShapeUtil.configure({ arcArrowCenterSnapDistance: 0 }),\n * ]\n *\n * function MyApp() {\n * return <Tldraw shapeUtils={shapeUtils} />\n * }\n * ```\n *\n * @public\n */\nexport interface ArrowShapeOptions {\n\t/**\n\t * How far should elbow arrows expand from the shapes they're targeting?\n\t */\n\treadonly expandElbowLegLength: Record<TLDefaultSizeStyle, number>\n\t/**\n\t * The minimum length of an elbow arrow's leg.\n\t */\n\treadonly minElbowLegLength: Record<TLDefaultSizeStyle, number>\n\t/**\n\t * The minimum distance, in screen pixels, between two handles on an elbow arrow. If two handles\n\t * would be closer than this distance, they're both hidden.\n\t */\n\treadonly minElbowHandleDistance: number\n\n\t/**\n\t * The distance, in screen pixels, at which we snap to the center of a target shape when drawing\n\t * an arc arrow. Set to 0 to disable.\n\t */\n\treadonly arcArrowCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the center of a target shape when drawing\n\t * an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the edge of a target shape when drawing\n\t * an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowEdgeSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to one of the 4 directional points (top,\n\t * right, bottom, left) of a target shape when drawing an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowPointSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap to the axis passing through the center of a\n\t * shape when drawing an elbow arrow. Set to 0 to disable.\n\t */\n\treadonly elbowArrowAxisSnapDistance: number\n\n\t/**\n\t * The distance, in screen pixels, at which we snap an arrow label to center of the arrow when\n\t * dragging it. Set to 0 to disable.\n\t */\n\treadonly labelCenterSnapDistance: number\n\t/**\n\t * The distance, in screen pixels, at which we snap an elbow arrow midpoint handle to the\n\t * midpoint between two shapes. Set to 0 to disable.\n\t */\n\treadonly elbowMidpointSnapDistance: number\n\t/**\n\t * The minimum length, in screen pixels, of an elbow arrows midpoint segment before we show the\n\t * handle for dragging that segment.\n\t */\n\treadonly elbowMinSegmentLengthToShowMidpointHandle: number\n\n\t/**\n\t * When hovering over a shape using the arrow tool, how long should we wait before we assume the\n\t * user is targeting precisely instead of imprecisely.\n\t */\n\treadonly hoverPreciseTimeout: number\n\t/**\n\t * When pointing at a shape using the arrow tool or dragging an arrow terminal handle, how long\n\t * should we wait before we assume the user is targeting precisely instead of imprecisely.\n\t */\n\treadonly pointingPreciseTimeout: number\n\n\t/**\n\t * When creating an arrow, should it stop exactly at the pointer, or should\n\t * it stop at the edge of the target shape.\n\t */\n\tshouldBeExact(editor: Editor, isPrecise: boolean): boolean\n\t/**\n\t * When creating an arrow, should it bind to the target shape.\n\t */\n\tshouldIgnoreTargets(editor: Editor): boolean\n\t/** Whether to show the outline of the arrow shape's label (using the same color as the canvas). This helps with overlapping shapes. It does not show up on Safari, where text outline is a performance issues. */\n\treadonly showTextOutline: boolean\n}\n\n/** @public */\nexport interface TLArrowPoint {\n\thandle: VecLike\n\tpoint: VecLike\n\tarrowhead: TLArrowShapeArrowheadStyle\n}\n\n/** @public */\nexport interface TLArcInfo {\n\tcenter: VecLike\n\tradius: number\n\tsize: number\n\tlength: number\n\tlargeArcFlag: number\n\tsweepFlag: number\n}\n\n/** @public */\nexport interface TLArcArrowInfo {\n\tbindings: TLArrowBindings\n\ttype: 'arc'\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\tmiddle: VecLike\n\thandleArc: TLArcInfo\n\tbodyArc: TLArcInfo\n\tisValid: boolean\n}\n\n/** @public */\nexport interface TLStraightArrowInfo {\n\tbindings: TLArrowBindings\n\ttype: 'straight'\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\tmiddle: VecLike\n\tisValid: boolean\n\tlength: number\n}\n\n/** @public */\nexport interface TLElbowArrowInfo {\n\ttype: 'elbow'\n\tbindings: TLArrowBindings\n\tstart: TLArrowPoint\n\tend: TLArrowPoint\n\telbow: ElbowArrowInfo\n\troute: ElbowArrowRoute\n\tisValid: boolean\n}\n\n/** @public */\nexport type TLArrowInfo = TLArcArrowInfo | TLStraightArrowInfo | TLElbowArrowInfo\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/arrowLabel.ts"],
4
- "sourcesContent": ["import {\n\tArc2d,\n\tBox,\n\tCircle2d,\n\tEdge2d,\n\tEditor,\n\tGeometry2d,\n\tGroup2d,\n\tPolygon2d,\n\tPolyline2d,\n\tTLArrowShape,\n\tTLShape,\n\tVec,\n\tVecLike,\n\tclamp,\n\tcreateComputedCache,\n\texhaustiveSwitchError,\n\tgetChangedKeys,\n\tpointInPolygon,\n\ttoRichText,\n} from '@tldraw/editor'\nimport { isEmptyRichText, renderHtmlFromRichTextForMeasurement } from '../../utils/text/richText'\nimport {\n\tARROW_LABEL_FONT_SIZES,\n\tARROW_LABEL_PADDING,\n\tFONT_FAMILIES,\n\tLABEL_TO_ARROW_PADDING,\n\tSTROKE_SIZES,\n\tTEXT_PROPS,\n} from '../shared/default-shape-constants'\nimport { TLArrowInfo } from './arrow-types'\nimport { getArrowInfo } from './shared'\n\nexport function getArrowBodyGeometry(editor: Editor, shape: TLArrowShape) {\n\tconst info = getArrowInfo(editor, shape)!\n\tswitch (info.type) {\n\t\tcase 'straight':\n\t\t\treturn new Edge2d({\n\t\t\t\tstart: Vec.From(info.start.point),\n\t\t\t\tend: Vec.From(info.end.point),\n\t\t\t})\n\t\tcase 'arc':\n\t\t\treturn new Arc2d({\n\t\t\t\tcenter: Vec.Cast(info.handleArc.center),\n\t\t\t\tstart: Vec.Cast(info.start.point),\n\t\t\t\tend: Vec.Cast(info.end.point),\n\t\t\t\tsweepFlag: info.bodyArc.sweepFlag,\n\t\t\t\tlargeArcFlag: info.bodyArc.largeArcFlag,\n\t\t\t})\n\t\tcase 'elbow':\n\t\t\treturn new Polyline2d({ points: info.route.points })\n\t\tdefault:\n\t\t\texhaustiveSwitchError(info, 'type')\n\t}\n}\n\nconst labelSizeCache = createComputedCache(\n\t'arrow label size',\n\t(editor: Editor, shape: TLArrowShape) => {\n\t\teditor.fonts.trackFontsForShape(shape)\n\t\tlet width = 0\n\t\tlet height = 0\n\n\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\t// We use 'i' as a default label to measure against as a minimum width.\n\t\tconst isEmpty = isEmptyRichText(shape.props.richText)\n\t\tconst html = renderHtmlFromRichTextForMeasurement(\n\t\t\teditor,\n\t\t\tisEmpty ? toRichText('i') : shape.props.richText\n\t\t)\n\n\t\tconst bodyBounds = bodyGeom.bounds\n\n\t\tconst fontSize = getArrowLabelFontSize(shape)\n\n\t\t// First we measure the text with no constraints\n\t\tconst { w, h } = editor.textMeasure.measureHtml(html, {\n\t\t\t...TEXT_PROPS,\n\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\tfontSize,\n\t\t\tmaxWidth: null,\n\t\t})\n\n\t\twidth = w\n\t\theight = h\n\n\t\tlet shouldSquish = false\n\n\t\t// If the text is wider than the body, we need to squish it\n\t\tconst info = getArrowInfo(editor, shape)!\n\t\tconst labelToArrowPadding = getLabelToArrowPadding(shape)\n\t\tconst margin =\n\t\t\tinfo.type === 'elbow'\n\t\t\t\t? Math.max(info.elbow.A.arrowheadOffset + labelToArrowPadding, 32) +\n\t\t\t\t\tMath.max(info.elbow.B.arrowheadOffset + labelToArrowPadding, 32)\n\t\t\t\t: 64\n\n\t\tif (bodyBounds.width > bodyBounds.height) {\n\t\t\twidth = Math.max(Math.min(w, margin), Math.min(bodyBounds.width - margin, w))\n\t\t\tshouldSquish = true\n\t\t} else if (width > 16 * fontSize) {\n\t\t\twidth = 16 * fontSize\n\t\t\tshouldSquish = true\n\t\t}\n\n\t\tif (shouldSquish) {\n\t\t\tconst { w: squishedWidth, h: squishedHeight } = editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\t\tfontSize,\n\t\t\t\tmaxWidth: width,\n\t\t\t})\n\n\t\t\twidth = squishedWidth\n\t\t\theight = squishedHeight\n\t\t}\n\n\t\treturn new Vec(width, height).addScalar(ARROW_LABEL_PADDING * 2 * shape.props.scale)\n\t},\n\t{\n\t\tareRecordsEqual: (a, b) => {\n\t\t\tif (a.props === b.props) return true\n\n\t\t\t// If the only thing that has changed is the label position, we can skip recalculating the size\n\t\t\tconst changedKeys = getChangedKeys(a.props, b.props)\n\t\t\treturn changedKeys.length === 1 && changedKeys[0] === 'labelPosition'\n\t\t},\n\t}\n)\n\nfunction getArrowLabelSize(editor: Editor, shape: TLArrowShape) {\n\treturn labelSizeCache.get(editor, shape.id) ?? new Vec(0, 0)\n}\n\nfunction getLabelToArrowPadding(shape: TLArrowShape) {\n\tconst strokeWidth = STROKE_SIZES[shape.props.size]\n\tconst labelToArrowPadding =\n\t\t(LABEL_TO_ARROW_PADDING +\n\t\t\t(strokeWidth - STROKE_SIZES.s) * 2 +\n\t\t\t(strokeWidth === STROKE_SIZES.xl ? 20 : 0)) *\n\t\tshape.props.scale\n\n\treturn labelToArrowPadding\n}\n\n/**\n * Return the range of possible label positions for an arrow. The full possible range is 0 to 1, but\n * as the label itself takes up space the usable range is smaller.\n */\nfunction getArrowLabelRange(editor: Editor, shape: TLArrowShape, info: TLArrowInfo) {\n\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\tconst dbgPoints: VecLike[] = []\n\tconst dbg: Geometry2d[] = [new Group2d({ children: [bodyGeom], debugColor: 'lime' })]\n\n\tconst labelSize = getArrowLabelSize(editor, shape)\n\tconst labelToArrowPadding = getLabelToArrowPadding(shape)\n\tconst paddingRelative = labelToArrowPadding / bodyGeom.length\n\n\t// we can calculate the range by sticking the center of the label at the very start/end of the\n\t// arrow, and seeing where the label intersects with the arrow. Then, if we move the label's\n\t// center to that point, that'll be the start/end of the range.\n\n\tlet startBox, endBox\n\tif (info.type === 'elbow') {\n\t\t// for elbow arrows, because they have multiple segments but are always axis-aligned, we can use\n\t\t// an expanded box. This helps keep the box from partially covering the first segment when it's\n\t\t// very small.\n\t\tdbgPoints.push(info.start.point, info.end.point)\n\t\tstartBox = Box.FromCenter(info.start.point, labelSize).expandBy(labelToArrowPadding)\n\t\tendBox = Box.FromCenter(info.end.point, labelSize).expandBy(labelToArrowPadding)\n\t} else {\n\t\t// for other arrows, we move along the arrow by the padding amount to find the start/end points\n\t\tconst startPoint = bodyGeom.interpolateAlongEdge(paddingRelative)\n\t\tconst endPoint = bodyGeom.interpolateAlongEdge(1 - paddingRelative)\n\t\tdbgPoints.push(startPoint, endPoint)\n\t\tstartBox = Box.FromCenter(startPoint, labelSize)\n\t\tendBox = Box.FromCenter(endPoint, labelSize)\n\t}\n\tconst startIntersections = bodyGeom.intersectPolygon(startBox.corners)\n\tconst endIntersections = bodyGeom.intersectPolygon(endBox.corners)\n\n\tconst startConstrained = furthest(info.start.point, startIntersections)\n\tconst endConstrained = furthest(info.end.point, endIntersections)\n\n\tlet startRelative = startConstrained ? bodyGeom.uninterpolateAlongEdge(startConstrained) : 0.5\n\tlet endRelative = endConstrained ? bodyGeom.uninterpolateAlongEdge(endConstrained) : 0.5\n\n\tif (startRelative > endRelative) {\n\t\tstartRelative = 0.5\n\t\tendRelative = 0.5\n\t}\n\n\tfor (const pt of [...startIntersections, ...endIntersections, ...dbgPoints]) {\n\t\tdbg.push(\n\t\t\tnew Circle2d({\n\t\t\t\tx: pt.x - 3,\n\t\t\t\ty: pt.y - 3,\n\t\t\t\tradius: 3,\n\t\t\t\tisFilled: false,\n\t\t\t\tdebugColor: 'magenta',\n\t\t\t\tignore: true,\n\t\t\t})\n\t\t)\n\t}\n\tdbg.push(\n\t\tnew Polygon2d({\n\t\t\tpoints: startBox.corners,\n\t\t\tdebugColor: 'lime',\n\t\t\tisFilled: false,\n\t\t\tignore: true,\n\t\t}),\n\t\tnew Polygon2d({\n\t\t\tpoints: endBox.corners,\n\t\t\tdebugColor: 'lime',\n\t\t\tisFilled: false,\n\t\t\tignore: true,\n\t\t})\n\t)\n\n\treturn { start: startRelative, end: endRelative, dbg }\n}\n\ninterface ArrowheadInfo {\n\thasStartBinding: boolean\n\thasEndBinding: boolean\n\thasStartArrowhead: boolean\n\thasEndArrowhead: boolean\n}\nexport function getArrowLabelPosition(editor: Editor, shape: TLArrowShape) {\n\tconst isEditing = editor.getEditingShapeId() === shape.id\n\tif (!isEditing && isEmptyRichText(shape.props.richText)) {\n\t\t// Short-circuit for empty labels.\n\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\tconst labelCenter = bodyGeom.interpolateAlongEdge(0.5)\n\t\treturn { box: Box.FromCenter(labelCenter, new Vec(0, 0)), debugGeom: [] }\n\t}\n\n\tconst debugGeom: Geometry2d[] = []\n\tconst info = getArrowInfo(editor, shape)!\n\n\tconst arrowheadInfo: ArrowheadInfo = {\n\t\thasStartBinding: !!info.bindings.start,\n\t\thasEndBinding: !!info.bindings.end,\n\t\thasStartArrowhead: info.start.arrowhead !== 'none',\n\t\thasEndArrowhead: info.end.arrowhead !== 'none',\n\t}\n\n\tconst range = getArrowLabelRange(editor, shape, info)\n\tif (range.dbg) debugGeom.push(...range.dbg)\n\n\tconst clampedPosition = getClampedPosition(shape, range, arrowheadInfo)\n\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\tconst labelCenter = bodyGeom.interpolateAlongEdge(clampedPosition)\n\tconst labelSize = getArrowLabelSize(editor, shape)\n\n\treturn { box: Box.FromCenter(labelCenter, labelSize), debugGeom }\n}\n\nfunction getClampedPosition(\n\tshape: TLArrowShape,\n\trange: { start: number; end: number },\n\tarrowheadInfo: ArrowheadInfo\n) {\n\tconst { hasEndArrowhead, hasEndBinding, hasStartBinding, hasStartArrowhead } = arrowheadInfo\n\tconst clampedPosition = clamp(\n\t\tshape.props.labelPosition,\n\t\thasStartArrowhead || hasStartBinding ? range.start : 0,\n\t\thasEndArrowhead || hasEndBinding ? range.end : 1\n\t)\n\n\treturn clampedPosition\n}\n\nfunction furthest(from: VecLike, candidates: VecLike[]): VecLike | null {\n\tlet furthest: VecLike | null = null\n\tlet furthestDist = -Infinity\n\n\tfor (const candidate of candidates) {\n\t\tconst dist = Vec.Dist2(from, candidate)\n\t\tif (dist > furthestDist) {\n\t\t\tfurthest = candidate\n\t\t\tfurthestDist = dist\n\t\t}\n\t}\n\n\treturn furthest\n}\n\nexport function getArrowLabelFontSize(shape: TLArrowShape) {\n\treturn ARROW_LABEL_FONT_SIZES[shape.props.size] * shape.props.scale\n}\n\nexport function getArrowLabelDefaultPosition(editor: Editor, shape: TLArrowShape) {\n\tconst info = getArrowInfo(editor, shape)!\n\tswitch (info.type) {\n\t\tcase 'straight':\n\t\tcase 'arc':\n\t\t\treturn 0.5\n\t\tcase 'elbow': {\n\t\t\tconst midpointHandle = info.route.midpointHandle\n\t\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\t\tif (midpointHandle && bodyGeom) {\n\t\t\t\treturn bodyGeom.uninterpolateAlongEdge(midpointHandle.point)\n\t\t\t}\n\t\t\treturn 0.5\n\t\t}\n\t\tdefault:\n\t\t\texhaustiveSwitchError(info, 'type')\n\t}\n}\n\n/** @internal */\nexport function isOverArrowLabel(editor: Editor, shape: TLShape) {\n\tif (!editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) return false\n\n\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, editor.inputs.currentPagePoint)\n\t// How should we handle multiple labels? Do shapes ever have multiple labels?\n\tconst labelGeometry = editor.getShapeGeometry<Group2d>(shape).children[1]\n\t// Knowing what we know about arrows... if the shape has no text in its label,\n\t// then the label geometry should not be there.\n\treturn labelGeometry && pointInPolygon(pointInShapeSpace, labelGeometry.vertices)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tArc2d,\n\tBox,\n\tCircle2d,\n\tEdge2d,\n\tEditor,\n\tGeometry2d,\n\tGroup2d,\n\tPolygon2d,\n\tPolyline2d,\n\tTLArrowShape,\n\tTLShape,\n\tVec,\n\tVecLike,\n\tclamp,\n\tcreateComputedCache,\n\texhaustiveSwitchError,\n\tgetChangedKeys,\n\tpointInPolygon,\n\ttoRichText,\n} from '@tldraw/editor'\nimport { isEmptyRichText, renderHtmlFromRichTextForMeasurement } from '../../utils/text/richText'\nimport {\n\tARROW_LABEL_FONT_SIZES,\n\tARROW_LABEL_PADDING,\n\tFONT_FAMILIES,\n\tLABEL_TO_ARROW_PADDING,\n\tSTROKE_SIZES,\n\tTEXT_PROPS,\n} from '../shared/default-shape-constants'\nimport { TLArrowInfo } from './arrow-types'\nimport { getArrowInfo } from './shared'\n\nexport function getArrowBodyGeometry(editor: Editor, shape: TLArrowShape) {\n\tconst info = getArrowInfo(editor, shape)!\n\tswitch (info.type) {\n\t\tcase 'straight':\n\t\t\treturn new Edge2d({\n\t\t\t\tstart: Vec.From(info.start.point),\n\t\t\t\tend: Vec.From(info.end.point),\n\t\t\t})\n\t\tcase 'arc':\n\t\t\treturn new Arc2d({\n\t\t\t\tcenter: Vec.Cast(info.handleArc.center),\n\t\t\t\tstart: Vec.Cast(info.start.point),\n\t\t\t\tend: Vec.Cast(info.end.point),\n\t\t\t\tsweepFlag: info.bodyArc.sweepFlag,\n\t\t\t\tlargeArcFlag: info.bodyArc.largeArcFlag,\n\t\t\t})\n\t\tcase 'elbow':\n\t\t\treturn new Polyline2d({ points: info.route.points })\n\t\tdefault:\n\t\t\texhaustiveSwitchError(info, 'type')\n\t}\n}\n\nconst labelSizeCache = createComputedCache(\n\t'arrow label size',\n\t(editor: Editor, shape: TLArrowShape) => {\n\t\teditor.fonts.trackFontsForShape(shape)\n\t\tlet width = 0\n\t\tlet height = 0\n\n\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\t// We use 'i' as a default label to measure against as a minimum width.\n\t\tconst isEmpty = isEmptyRichText(shape.props.richText)\n\t\tconst html = renderHtmlFromRichTextForMeasurement(\n\t\t\teditor,\n\t\t\tisEmpty ? toRichText('i') : shape.props.richText\n\t\t)\n\n\t\tconst bodyBounds = bodyGeom.bounds\n\n\t\tconst fontSize = getArrowLabelFontSize(shape)\n\n\t\t// First we measure the text with no constraints\n\t\tconst { w, h } = editor.textMeasure.measureHtml(html, {\n\t\t\t...TEXT_PROPS,\n\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\tfontSize,\n\t\t\tmaxWidth: null,\n\t\t})\n\n\t\twidth = w\n\t\theight = h\n\n\t\tlet shouldSquish = false\n\n\t\t// If the text is wider than the body, we need to squish it\n\t\tconst info = getArrowInfo(editor, shape)!\n\t\tconst labelToArrowPadding = getLabelToArrowPadding(shape)\n\t\tconst margin =\n\t\t\tinfo.type === 'elbow'\n\t\t\t\t? Math.max(info.elbow.A.arrowheadOffset + labelToArrowPadding, 32) +\n\t\t\t\t\tMath.max(info.elbow.B.arrowheadOffset + labelToArrowPadding, 32)\n\t\t\t\t: 64\n\n\t\tif (bodyBounds.width > bodyBounds.height) {\n\t\t\twidth = Math.max(Math.min(w, margin), Math.min(bodyBounds.width - margin, w))\n\t\t\tshouldSquish = true\n\t\t} else if (width > 16 * fontSize) {\n\t\t\twidth = 16 * fontSize\n\t\t\tshouldSquish = true\n\t\t}\n\n\t\tif (shouldSquish) {\n\t\t\tconst { w: squishedWidth, h: squishedHeight } = editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\t\tfontSize,\n\t\t\t\tmaxWidth: width,\n\t\t\t})\n\n\t\t\twidth = squishedWidth\n\t\t\theight = squishedHeight\n\t\t}\n\n\t\treturn new Vec(width, height).addScalar(ARROW_LABEL_PADDING * 2 * shape.props.scale)\n\t},\n\t{\n\t\tareRecordsEqual: (a, b) => {\n\t\t\tif (a.props === b.props) return true\n\n\t\t\t// If the only thing that has changed is the label position, we can skip recalculating the size\n\t\t\tconst changedKeys = getChangedKeys(a.props, b.props)\n\t\t\treturn changedKeys.length === 1 && changedKeys[0] === 'labelPosition'\n\t\t},\n\t}\n)\n\nfunction getArrowLabelSize(editor: Editor, shape: TLArrowShape) {\n\treturn labelSizeCache.get(editor, shape.id) ?? new Vec(0, 0)\n}\n\nfunction getLabelToArrowPadding(shape: TLArrowShape) {\n\tconst strokeWidth = STROKE_SIZES[shape.props.size]\n\tconst labelToArrowPadding =\n\t\t(LABEL_TO_ARROW_PADDING +\n\t\t\t(strokeWidth - STROKE_SIZES.s) * 2 +\n\t\t\t(strokeWidth === STROKE_SIZES.xl ? 20 : 0)) *\n\t\tshape.props.scale\n\n\treturn labelToArrowPadding\n}\n\n/**\n * Return the range of possible label positions for an arrow. The full possible range is 0 to 1, but\n * as the label itself takes up space the usable range is smaller.\n */\nfunction getArrowLabelRange(editor: Editor, shape: TLArrowShape, info: TLArrowInfo) {\n\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\tconst dbgPoints: VecLike[] = []\n\tconst dbg: Geometry2d[] = [new Group2d({ children: [bodyGeom], debugColor: 'lime' })]\n\n\tconst labelSize = getArrowLabelSize(editor, shape)\n\tconst labelToArrowPadding = getLabelToArrowPadding(shape)\n\tconst paddingRelative = labelToArrowPadding / bodyGeom.length\n\n\t// we can calculate the range by sticking the center of the label at the very start/end of the\n\t// arrow, and seeing where the label intersects with the arrow. Then, if we move the label's\n\t// center to that point, that'll be the start/end of the range.\n\n\tlet startBox, endBox\n\tif (info.type === 'elbow') {\n\t\t// for elbow arrows, because they have multiple segments but are always axis-aligned, we can use\n\t\t// an expanded box. This helps keep the box from partially covering the first segment when it's\n\t\t// very small.\n\t\tdbgPoints.push(info.start.point, info.end.point)\n\t\tstartBox = Box.FromCenter(info.start.point, labelSize).expandBy(labelToArrowPadding)\n\t\tendBox = Box.FromCenter(info.end.point, labelSize).expandBy(labelToArrowPadding)\n\t} else {\n\t\t// for other arrows, we move along the arrow by the padding amount to find the start/end points\n\t\tconst startPoint = bodyGeom.interpolateAlongEdge(paddingRelative)\n\t\tconst endPoint = bodyGeom.interpolateAlongEdge(1 - paddingRelative)\n\t\tdbgPoints.push(startPoint, endPoint)\n\t\tstartBox = Box.FromCenter(startPoint, labelSize)\n\t\tendBox = Box.FromCenter(endPoint, labelSize)\n\t}\n\tconst startIntersections = bodyGeom.intersectPolygon(startBox.corners)\n\tconst endIntersections = bodyGeom.intersectPolygon(endBox.corners)\n\n\tconst startConstrained = furthest(info.start.point, startIntersections)\n\tconst endConstrained = furthest(info.end.point, endIntersections)\n\n\tlet startRelative = startConstrained ? bodyGeom.uninterpolateAlongEdge(startConstrained) : 0.5\n\tlet endRelative = endConstrained ? bodyGeom.uninterpolateAlongEdge(endConstrained) : 0.5\n\n\tif (startRelative > endRelative) {\n\t\tstartRelative = 0.5\n\t\tendRelative = 0.5\n\t}\n\n\tfor (const pt of [...startIntersections, ...endIntersections, ...dbgPoints]) {\n\t\tdbg.push(\n\t\t\tnew Circle2d({\n\t\t\t\tx: pt.x - 3,\n\t\t\t\ty: pt.y - 3,\n\t\t\t\tradius: 3,\n\t\t\t\tisFilled: false,\n\t\t\t\tdebugColor: 'magenta',\n\t\t\t\tignore: true,\n\t\t\t})\n\t\t)\n\t}\n\tdbg.push(\n\t\tnew Polygon2d({\n\t\t\tpoints: startBox.corners,\n\t\t\tdebugColor: 'lime',\n\t\t\tisFilled: false,\n\t\t\tignore: true,\n\t\t}),\n\t\tnew Polygon2d({\n\t\t\tpoints: endBox.corners,\n\t\t\tdebugColor: 'lime',\n\t\t\tisFilled: false,\n\t\t\tignore: true,\n\t\t})\n\t)\n\n\treturn { start: startRelative, end: endRelative, dbg }\n}\n\ninterface ArrowheadInfo {\n\thasStartBinding: boolean\n\thasEndBinding: boolean\n\thasStartArrowhead: boolean\n\thasEndArrowhead: boolean\n}\nexport function getArrowLabelPosition(editor: Editor, shape: TLArrowShape) {\n\tconst isEditing = editor.getEditingShapeId() === shape.id\n\tif (!isEditing && isEmptyRichText(shape.props.richText)) {\n\t\t// Short-circuit for empty labels.\n\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\tconst labelCenter = bodyGeom.interpolateAlongEdge(0.5)\n\t\treturn { box: Box.FromCenter(labelCenter, new Vec(0, 0)), debugGeom: [] }\n\t}\n\n\tconst debugGeom: Geometry2d[] = []\n\tconst info = getArrowInfo(editor, shape)!\n\n\tconst arrowheadInfo: ArrowheadInfo = {\n\t\thasStartBinding: !!info.bindings.start,\n\t\thasEndBinding: !!info.bindings.end,\n\t\thasStartArrowhead: info.start.arrowhead !== 'none',\n\t\thasEndArrowhead: info.end.arrowhead !== 'none',\n\t}\n\n\tconst range = getArrowLabelRange(editor, shape, info)\n\tif (range.dbg) debugGeom.push(...range.dbg)\n\n\tconst clampedPosition = getClampedPosition(shape, range, arrowheadInfo)\n\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\tconst labelCenter = bodyGeom.interpolateAlongEdge(clampedPosition)\n\tconst labelSize = getArrowLabelSize(editor, shape)\n\n\treturn { box: Box.FromCenter(labelCenter, labelSize), debugGeom }\n}\n\nfunction getClampedPosition(\n\tshape: TLArrowShape,\n\trange: { start: number; end: number },\n\tarrowheadInfo: ArrowheadInfo\n) {\n\tconst { hasEndArrowhead, hasEndBinding, hasStartBinding, hasStartArrowhead } = arrowheadInfo\n\tconst clampedPosition = clamp(\n\t\tshape.props.labelPosition,\n\t\thasStartArrowhead || hasStartBinding ? range.start : 0,\n\t\thasEndArrowhead || hasEndBinding ? range.end : 1\n\t)\n\n\treturn clampedPosition\n}\n\nfunction furthest(from: VecLike, candidates: VecLike[]): VecLike | null {\n\tlet furthest: VecLike | null = null\n\tlet furthestDist = -Infinity\n\n\tfor (const candidate of candidates) {\n\t\tconst dist = Vec.Dist2(from, candidate)\n\t\tif (dist > furthestDist) {\n\t\t\tfurthest = candidate\n\t\t\tfurthestDist = dist\n\t\t}\n\t}\n\n\treturn furthest\n}\n\nexport function getArrowLabelFontSize(shape: TLArrowShape) {\n\treturn ARROW_LABEL_FONT_SIZES[shape.props.size] * shape.props.scale\n}\n\nexport function getArrowLabelDefaultPosition(editor: Editor, shape: TLArrowShape) {\n\tconst info = getArrowInfo(editor, shape)!\n\tswitch (info.type) {\n\t\tcase 'straight':\n\t\tcase 'arc':\n\t\t\treturn 0.5\n\t\tcase 'elbow': {\n\t\t\tconst midpointHandle = info.route.midpointHandle\n\t\t\tconst bodyGeom = getArrowBodyGeometry(editor, shape)\n\t\t\tif (midpointHandle && bodyGeom) {\n\t\t\t\treturn bodyGeom.uninterpolateAlongEdge(midpointHandle.point)\n\t\t\t}\n\t\t\treturn 0.5\n\t\t}\n\t\tdefault:\n\t\t\texhaustiveSwitchError(info, 'type')\n\t}\n}\n\n/** @internal */\nexport function isOverArrowLabel(editor: Editor, shape: TLShape) {\n\tif (!editor.isShapeOfType(shape, 'arrow')) return false\n\n\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, editor.inputs.currentPagePoint)\n\t// How should we handle multiple labels? Do shapes ever have multiple labels?\n\tconst labelGeometry = editor.getShapeGeometry<Group2d>(shape).children[1]\n\t// Knowing what we know about arrows... if the shape has no text in its label,\n\t// then the label geometry should not be there.\n\treturn labelGeometry && pointInPolygon(pointInShapeSpace, labelGeometry.vertices)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAoBO;AACP,sBAAsE;AACtE,qCAOO;AAEP,oBAA6B;AAEtB,SAAS,qBAAqB,QAAgB,OAAqB;AACzE,QAAM,WAAO,4BAAa,QAAQ,KAAK;AACvC,UAAQ,KAAK,MAAM;AAAA,IAClB,KAAK;AACJ,aAAO,IAAI,qBAAO;AAAA,QACjB,OAAO,kBAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QAChC,KAAK,kBAAI,KAAK,KAAK,IAAI,KAAK;AAAA,MAC7B,CAAC;AAAA,IACF,KAAK;AACJ,aAAO,IAAI,oBAAM;AAAA,QAChB,QAAQ,kBAAI,KAAK,KAAK,UAAU,MAAM;AAAA,QACtC,OAAO,kBAAI,KAAK,KAAK,MAAM,KAAK;AAAA,QAChC,KAAK,kBAAI,KAAK,KAAK,IAAI,KAAK;AAAA,QAC5B,WAAW,KAAK,QAAQ;AAAA,QACxB,cAAc,KAAK,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACF,KAAK;AACJ,aAAO,IAAI,yBAAW,EAAE,QAAQ,KAAK,MAAM,OAAO,CAAC;AAAA,IACpD;AACC,+CAAsB,MAAM,MAAM;AAAA,EACpC;AACD;AAEA,MAAM,qBAAiB;AAAA,EACtB;AAAA,EACA,CAAC,QAAgB,UAAwB;AACxC,WAAO,MAAM,mBAAmB,KAAK;AACrC,QAAI,QAAQ;AACZ,QAAI,SAAS;AAEb,UAAM,WAAW,qBAAqB,QAAQ,KAAK;AAEnD,UAAM,cAAU,iCAAgB,MAAM,MAAM,QAAQ;AACpD,UAAM,WAAO;AAAA,MACZ;AAAA,MACA,cAAU,0BAAW,GAAG,IAAI,MAAM,MAAM;AAAA,IACzC;AAEA,UAAM,aAAa,SAAS;AAE5B,UAAM,WAAW,sBAAsB,KAAK;AAG5C,UAAM,EAAE,GAAG,EAAE,IAAI,OAAO,YAAY,YAAY,MAAM;AAAA,MACrD,GAAG;AAAA,MACH,YAAY,6CAAc,MAAM,MAAM,IAAI;AAAA,MAC1C;AAAA,MACA,UAAU;AAAA,IACX,CAAC;AAED,YAAQ;AACR,aAAS;AAET,QAAI,eAAe;AAGnB,UAAM,WAAO,4BAAa,QAAQ,KAAK;AACvC,UAAM,sBAAsB,uBAAuB,KAAK;AACxD,UAAM,SACL,KAAK,SAAS,UACX,KAAK,IAAI,KAAK,MAAM,EAAE,kBAAkB,qBAAqB,EAAE,IAChE,KAAK,IAAI,KAAK,MAAM,EAAE,kBAAkB,qBAAqB,EAAE,IAC9D;AAEJ,QAAI,WAAW,QAAQ,WAAW,QAAQ;AACzC,cAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,KAAK,IAAI,WAAW,QAAQ,QAAQ,CAAC,CAAC;AAC5E,qBAAe;AAAA,IAChB,WAAW,QAAQ,KAAK,UAAU;AACjC,cAAQ,KAAK;AACb,qBAAe;AAAA,IAChB;AAEA,QAAI,cAAc;AACjB,YAAM,EAAE,GAAG,eAAe,GAAG,eAAe,IAAI,OAAO,YAAY,YAAY,MAAM;AAAA,QACpF,GAAG;AAAA,QACH,YAAY,6CAAc,MAAM,MAAM,IAAI;AAAA,QAC1C;AAAA,QACA,UAAU;AAAA,MACX,CAAC;AAED,cAAQ;AACR,eAAS;AAAA,IACV;AAEA,WAAO,IAAI,kBAAI,OAAO,MAAM,EAAE,UAAU,qDAAsB,IAAI,MAAM,MAAM,KAAK;AAAA,EACpF;AAAA,EACA;AAAA,IACC,iBAAiB,CAAC,GAAG,MAAM;AAC1B,UAAI,EAAE,UAAU,EAAE,MAAO,QAAO;AAGhC,YAAM,kBAAc,8BAAe,EAAE,OAAO,EAAE,KAAK;AACnD,aAAO,YAAY,WAAW,KAAK,YAAY,CAAC,MAAM;AAAA,IACvD;AAAA,EACD;AACD;AAEA,SAAS,kBAAkB,QAAgB,OAAqB;AAC/D,SAAO,eAAe,IAAI,QAAQ,MAAM,EAAE,KAAK,IAAI,kBAAI,GAAG,CAAC;AAC5D;AAEA,SAAS,uBAAuB,OAAqB;AACpD,QAAM,cAAc,4CAAa,MAAM,MAAM,IAAI;AACjD,QAAM,uBACJ,yDACC,cAAc,4CAAa,KAAK,KAChC,gBAAgB,4CAAa,KAAK,KAAK,MACzC,MAAM,MAAM;AAEb,SAAO;AACR;AAMA,SAAS,mBAAmB,QAAgB,OAAqB,MAAmB;AACnF,QAAM,WAAW,qBAAqB,QAAQ,KAAK;AACnD,QAAM,YAAuB,CAAC;AAC9B,QAAM,MAAoB,CAAC,IAAI,sBAAQ,EAAE,UAAU,CAAC,QAAQ,GAAG,YAAY,OAAO,CAAC,CAAC;AAEpF,QAAM,YAAY,kBAAkB,QAAQ,KAAK;AACjD,QAAM,sBAAsB,uBAAuB,KAAK;AACxD,QAAM,kBAAkB,sBAAsB,SAAS;AAMvD,MAAI,UAAU;AACd,MAAI,KAAK,SAAS,SAAS;AAI1B,cAAU,KAAK,KAAK,MAAM,OAAO,KAAK,IAAI,KAAK;AAC/C,eAAW,kBAAI,WAAW,KAAK,MAAM,OAAO,SAAS,EAAE,SAAS,mBAAmB;AACnF,aAAS,kBAAI,WAAW,KAAK,IAAI,OAAO,SAAS,EAAE,SAAS,mBAAmB;AAAA,EAChF,OAAO;AAEN,UAAM,aAAa,SAAS,qBAAqB,eAAe;AAChE,UAAM,WAAW,SAAS,qBAAqB,IAAI,eAAe;AAClE,cAAU,KAAK,YAAY,QAAQ;AACnC,eAAW,kBAAI,WAAW,YAAY,SAAS;AAC/C,aAAS,kBAAI,WAAW,UAAU,SAAS;AAAA,EAC5C;AACA,QAAM,qBAAqB,SAAS,iBAAiB,SAAS,OAAO;AACrE,QAAM,mBAAmB,SAAS,iBAAiB,OAAO,OAAO;AAEjE,QAAM,mBAAmB,SAAS,KAAK,MAAM,OAAO,kBAAkB;AACtE,QAAM,iBAAiB,SAAS,KAAK,IAAI,OAAO,gBAAgB;AAEhE,MAAI,gBAAgB,mBAAmB,SAAS,uBAAuB,gBAAgB,IAAI;AAC3F,MAAI,cAAc,iBAAiB,SAAS,uBAAuB,cAAc,IAAI;AAErF,MAAI,gBAAgB,aAAa;AAChC,oBAAgB;AAChB,kBAAc;AAAA,EACf;AAEA,aAAW,MAAM,CAAC,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,SAAS,GAAG;AAC5E,QAAI;AAAA,MACH,IAAI,uBAAS;AAAA,QACZ,GAAG,GAAG,IAAI;AAAA,QACV,GAAG,GAAG,IAAI;AAAA,QACV,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,QAAQ;AAAA,MACT,CAAC;AAAA,IACF;AAAA,EACD;AACA,MAAI;AAAA,IACH,IAAI,wBAAU;AAAA,MACb,QAAQ,SAAS;AAAA,MACjB,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,IACT,CAAC;AAAA,IACD,IAAI,wBAAU;AAAA,MACb,QAAQ,OAAO;AAAA,MACf,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,QAAQ;AAAA,IACT,CAAC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,eAAe,KAAK,aAAa,IAAI;AACtD;AAQO,SAAS,sBAAsB,QAAgB,OAAqB;AAC1E,QAAM,YAAY,OAAO,kBAAkB,MAAM,MAAM;AACvD,MAAI,CAAC,iBAAa,iCAAgB,MAAM,MAAM,QAAQ,GAAG;AAExD,UAAMA,YAAW,qBAAqB,QAAQ,KAAK;AACnD,UAAMC,eAAcD,UAAS,qBAAqB,GAAG;AACrD,WAAO,EAAE,KAAK,kBAAI,WAAWC,cAAa,IAAI,kBAAI,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,EAAE;AAAA,EACzE;AAEA,QAAM,YAA0B,CAAC;AACjC,QAAM,WAAO,4BAAa,QAAQ,KAAK;AAEvC,QAAM,gBAA+B;AAAA,IACpC,iBAAiB,CAAC,CAAC,KAAK,SAAS;AAAA,IACjC,eAAe,CAAC,CAAC,KAAK,SAAS;AAAA,IAC/B,mBAAmB,KAAK,MAAM,cAAc;AAAA,IAC5C,iBAAiB,KAAK,IAAI,cAAc;AAAA,EACzC;AAEA,QAAM,QAAQ,mBAAmB,QAAQ,OAAO,IAAI;AACpD,MAAI,MAAM,IAAK,WAAU,KAAK,GAAG,MAAM,GAAG;AAE1C,QAAM,kBAAkB,mBAAmB,OAAO,OAAO,aAAa;AACtE,QAAM,WAAW,qBAAqB,QAAQ,KAAK;AACnD,QAAM,cAAc,SAAS,qBAAqB,eAAe;AACjE,QAAM,YAAY,kBAAkB,QAAQ,KAAK;AAEjD,SAAO,EAAE,KAAK,kBAAI,WAAW,aAAa,SAAS,GAAG,UAAU;AACjE;AAEA,SAAS,mBACR,OACA,OACA,eACC;AACD,QAAM,EAAE,iBAAiB,eAAe,iBAAiB,kBAAkB,IAAI;AAC/E,QAAM,sBAAkB;AAAA,IACvB,MAAM,MAAM;AAAA,IACZ,qBAAqB,kBAAkB,MAAM,QAAQ;AAAA,IACrD,mBAAmB,gBAAgB,MAAM,MAAM;AAAA,EAChD;AAEA,SAAO;AACR;AAEA,SAAS,SAAS,MAAe,YAAuC;AACvE,MAAIC,YAA2B;AAC/B,MAAI,eAAe;AAEnB,aAAW,aAAa,YAAY;AACnC,UAAM,OAAO,kBAAI,MAAM,MAAM,SAAS;AACtC,QAAI,OAAO,cAAc;AACxB,MAAAA,YAAW;AACX,qBAAe;AAAA,IAChB;AAAA,EACD;AAEA,SAAOA;AACR;AAEO,SAAS,sBAAsB,OAAqB;AAC1D,SAAO,sDAAuB,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM;AAC/D;AAEO,SAAS,6BAA6B,QAAgB,OAAqB;AACjF,QAAM,WAAO,4BAAa,QAAQ,KAAK;AACvC,UAAQ,KAAK,MAAM;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK,SAAS;AACb,YAAM,iBAAiB,KAAK,MAAM;AAClC,YAAM,WAAW,qBAAqB,QAAQ,KAAK;AACnD,UAAI,kBAAkB,UAAU;AAC/B,eAAO,SAAS,uBAAuB,eAAe,KAAK;AAAA,MAC5D;AACA,aAAO;AAAA,IACR;AAAA,IACA;AACC,+CAAsB,MAAM,MAAM;AAAA,EACpC;AACD;AAGO,SAAS,iBAAiB,QAAgB,OAAgB;AAChE,MAAI,CAAC,OAAO,cAAc,OAAO,OAAO,EAAG,QAAO;AAElD,QAAM,oBAAoB,OAAO,qBAAqB,OAAO,OAAO,OAAO,gBAAgB;AAE3F,QAAM,gBAAgB,OAAO,iBAA0B,KAAK,EAAE,SAAS,CAAC;AAGxE,SAAO,qBAAiB,8BAAe,mBAAmB,cAAc,QAAQ;AACjF;",
6
6
  "names": ["bodyGeom", "labelCenter", "furthest"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/arrowTargetState.ts"],
4
- "sourcesContent": ["import {\n\tArrowShapeKindStyle,\n\tatom,\n\tAtom,\n\tBox,\n\tclamp,\n\tEditor,\n\tElbowArrowSnap,\n\tGeometry2dFilters,\n\tinvLerp,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapKeys,\n\tTLArrowBinding,\n\tTLArrowShape,\n\tTLArrowShapeKind,\n\tTLShape,\n\tVec,\n\tVecLike,\n\tWeakCache,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from './ArrowShapeUtil'\nimport {\n\tElbowArrowAxes,\n\tElbowArrowSide,\n\tElbowArrowSideAxes,\n\tElbowArrowSideDeltas,\n} from './elbow/definitions'\n\n/**\n * Options passed to {@link updateArrowTargetState}.\n *\n * @public\n */\nexport interface UpdateArrowTargetStateOpts {\n\teditor: Editor\n\tpointInPageSpace: VecLike\n\tarrow: TLArrowShape | undefined\n\tisPrecise: boolean\n\tcurrentBinding: TLArrowBinding | undefined\n\t/** The binding from the opposite end of the arrow, if one exists. */\n\toppositeBinding: TLArrowBinding | undefined\n}\n\n/**\n * State representing what we're pointing to when drawing or updating an arrow. You can get this\n * state using {@link getArrowTargetState}, and update it as part of an arrow interaction with\n * {@link updateArrowTargetState} or {@link clearArrowTargetState}.\n *\n * @public\n */\nexport interface ArrowTargetState {\n\ttarget: TLShape\n\tarrowKind: TLArrowShapeKind\n\n\thandlesInPageSpace: {\n\t\ttop: { point: VecLike; isEnabled: boolean }\n\t\tbottom: { point: VecLike; isEnabled: boolean }\n\t\tleft: { point: VecLike; isEnabled: boolean }\n\t\tright: { point: VecLike; isEnabled: boolean }\n\t}\n\n\tisExact: boolean\n\tisPrecise: boolean\n\n\tcenterInPageSpace: VecLike\n\tanchorInPageSpace: VecLike\n\tsnap: ElbowArrowSnap\n\tnormalizedAnchor: VecLike\n}\n\nconst arrowTargetStore = new WeakCache<Editor, Atom<ArrowTargetState | null>>()\n\nfunction getArrowTargetAtom(editor: Editor) {\n\treturn arrowTargetStore.get(editor, () => atom('arrowTarget', null))\n}\n\n/**\n * Get the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function getArrowTargetState(editor: Editor) {\n\treturn getArrowTargetAtom(editor).get()\n}\n\n/**\n * Clear the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function clearArrowTargetState(editor: Editor) {\n\tgetArrowTargetAtom(editor).set(null)\n}\n\n/**\n * Update the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function updateArrowTargetState({\n\teditor,\n\tpointInPageSpace,\n\tarrow,\n\tisPrecise,\n\tcurrentBinding,\n\toppositeBinding,\n}: UpdateArrowTargetStateOpts): ArrowTargetState | null {\n\tconst util = editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\n\t// no target picking when ctrl is held:\n\tif (util.options.shouldIgnoreTargets(editor)) {\n\t\tgetArrowTargetAtom(editor).set(null)\n\t\treturn null\n\t}\n\n\tconst arrowKind = arrow ? arrow.props.kind : editor.getStyleForNextShape(ArrowShapeKindStyle)\n\n\tconst target = editor.getShapeAtPoint(pointInPageSpace, {\n\t\thitInside: true,\n\t\thitFrameInside: true,\n\t\tmargin: arrowKind === 'elbow' ? 8 : [8, 0],\n\t\tfilter: (targetShape) => {\n\t\t\treturn (\n\t\t\t\t!targetShape.isLocked &&\n\t\t\t\teditor.canBindShapes({\n\t\t\t\t\tfromShape: arrow ?? targetFilterFallback,\n\t\t\t\t\ttoShape: targetShape,\n\t\t\t\t\tbinding: 'arrow',\n\t\t\t\t})\n\t\t\t)\n\t\t},\n\t})\n\n\tif (!target) {\n\t\tgetArrowTargetAtom(editor).set(null)\n\t\treturn null\n\t}\n\n\tconst targetGeometryInTargetSpace = editor.getShapeGeometry(target)\n\tconst targetBoundsInTargetSpace = Box.ZeroFix(targetGeometryInTargetSpace.bounds)\n\tconst targetCenterInTargetSpace = targetGeometryInTargetSpace.center\n\tconst targetTransform = editor.getShapePageTransform(target)\n\tconst pointInTargetSpace = editor.getPointInShapeSpace(target, pointInPageSpace)\n\n\tconst castDistance = Math.max(\n\t\ttargetGeometryInTargetSpace.bounds.width,\n\t\ttargetGeometryInTargetSpace.bounds.height\n\t)\n\n\tconst handlesInPageSpace = mapObjectMapValues(ElbowArrowSideDeltas, (side, delta) => {\n\t\tconst axis = ElbowArrowAxes[ElbowArrowSideAxes[side]]\n\n\t\tconst farPoint = Vec.Mul(delta, castDistance).add(targetCenterInTargetSpace)\n\n\t\tlet isEnabled = false\n\t\tlet handlePointInTargetSpace: VecLike = axis.v(\n\t\t\ttargetBoundsInTargetSpace[side],\n\t\t\ttargetBoundsInTargetSpace[axis.crossMid]\n\t\t)\n\t\tlet furthestDistance = 0\n\n\t\tconst intersections = targetGeometryInTargetSpace.intersectLineSegment(\n\t\t\ttargetCenterInTargetSpace,\n\t\t\tfarPoint,\n\t\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t\t)\n\t\tfor (const intersection of intersections) {\n\t\t\tconst distance = Vec.Dist2(intersection, targetCenterInTargetSpace)\n\t\t\tif (distance > furthestDistance) {\n\t\t\t\tfurthestDistance = distance\n\t\t\t\thandlePointInTargetSpace = intersection\n\t\t\t\tisEnabled = targetGeometryInTargetSpace.isClosed\n\t\t\t}\n\t\t}\n\n\t\tconst handlePointInPageSpace = targetTransform.applyToPoint(handlePointInTargetSpace)\n\n\t\treturn { point: handlePointInPageSpace, isEnabled, far: targetTransform.applyToPoint(farPoint) }\n\t})\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst minDistScaled = util.options.minElbowHandleDistance / zoomLevel\n\n\tconst targetCenterInPageSpace = targetTransform.applyToPoint(targetCenterInTargetSpace)\n\tfor (const side of objectMapKeys(handlesInPageSpace)) {\n\t\tconst handle = handlesInPageSpace[side]\n\t\tif (Vec.DistMin(handle.point, targetCenterInPageSpace, minDistScaled)) {\n\t\t\thandle.isEnabled = false\n\t\t}\n\t}\n\n\tlet precise = isPrecise\n\n\tif (!precise) {\n\t\t// If we're switching to a new bound shape, then precise only if moving slowly\n\t\tif (!currentBinding || (currentBinding && target.id !== currentBinding.toId)) {\n\t\t\tprecise = editor.inputs.pointerVelocity.len() < 0.5\n\t\t}\n\t}\n\n\tif (!isPrecise) {\n\t\tif (!targetGeometryInTargetSpace.isClosed) {\n\t\t\tprecise = true\n\t\t}\n\n\t\t// Double check that we're not going to be doing an imprecise snap on\n\t\t// the same shape twice, as this would result in a zero length line\n\t\tif (oppositeBinding && target.id === oppositeBinding.toId && oppositeBinding.props.isPrecise) {\n\t\t\tprecise = true\n\t\t}\n\t}\n\n\tconst isExact = util.options.shouldBeExact(editor, precise)\n\tif (isExact) precise = true\n\n\tconst shouldSnapCenter = !isExact && precise && targetGeometryInTargetSpace.isClosed\n\t// const shouldSnapEdges = !isExact && (precise || !targetGeometryInTargetSpace.isClosed)\n\tconst shouldSnapEdges =\n\t\t!isExact && ((precise && arrowKind === 'elbow') || !targetGeometryInTargetSpace.isClosed)\n\tconst shouldSnapEdgePoints =\n\t\t!isExact && precise && arrowKind === 'elbow' && targetGeometryInTargetSpace.isClosed\n\tconst shouldSnapNone = precise && (targetGeometryInTargetSpace.isClosed || isExact)\n\tconst shouldSnapCenterAxis =\n\t\t!isExact && precise && arrowKind === 'elbow' && targetGeometryInTargetSpace.isClosed\n\n\t// we run through all the snapping options from least to most specific:\n\tlet snap: ElbowArrowSnap = 'none'\n\tlet anchorInPageSpace: VecLike = pointInPageSpace\n\n\tif (!shouldSnapNone) {\n\t\tsnap = 'center'\n\t\tanchorInPageSpace = targetCenterInPageSpace\n\t}\n\n\tif (shouldSnapEdges) {\n\t\tconst snapDistance = shouldSnapNone\n\t\t\t? calculateSnapDistance(\n\t\t\t\t\teditor,\n\t\t\t\t\ttargetBoundsInTargetSpace,\n\t\t\t\t\tutil.options.elbowArrowEdgeSnapDistance\n\t\t\t\t)\n\t\t\t: Infinity\n\n\t\tconst nearestPointOnEdgeInTargetSpace = targetGeometryInTargetSpace.nearestPoint(\n\t\t\tpointInTargetSpace,\n\t\t\t{\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t}\n\t\t)\n\n\t\tconst nearestPointOnEdgeInPageSpace = targetTransform.applyToPoint(\n\t\t\tnearestPointOnEdgeInTargetSpace\n\t\t)\n\n\t\tconst distance = Vec.Dist(nearestPointOnEdgeInPageSpace, pointInPageSpace)\n\n\t\tif (distance < snapDistance) {\n\t\t\tsnap = 'edge'\n\t\t\tanchorInPageSpace = nearestPointOnEdgeInPageSpace\n\t\t}\n\t}\n\n\tif (shouldSnapCenterAxis) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tutil.options.elbowArrowAxisSnapDistance\n\t\t)\n\n\t\tconst distanceFromXAxis = Vec.DistanceToLineSegment(\n\t\t\thandlesInPageSpace.left.far,\n\t\t\thandlesInPageSpace.right.far,\n\t\t\tpointInPageSpace\n\t\t)\n\t\tconst distanceFromYAxis = Vec.DistanceToLineSegment(\n\t\t\thandlesInPageSpace.top.far,\n\t\t\thandlesInPageSpace.bottom.far,\n\t\t\tpointInPageSpace\n\t\t)\n\n\t\tconst snapAxis =\n\t\t\tdistanceFromXAxis < distanceFromYAxis && distanceFromXAxis < snapDistance\n\t\t\t\t? 'x'\n\t\t\t\t: distanceFromYAxis < snapDistance\n\t\t\t\t\t? 'y'\n\t\t\t\t\t: null\n\n\t\tif (snapAxis) {\n\t\t\tconst axis = ElbowArrowAxes[snapAxis]\n\n\t\t\tconst loDist2 = Vec.Dist2(handlesInPageSpace[axis.loEdge].far, pointInPageSpace)\n\t\t\tconst hiDist2 = Vec.Dist2(handlesInPageSpace[axis.hiEdge].far, pointInPageSpace)\n\n\t\t\tconst side = loDist2 < hiDist2 ? axis.loEdge : axis.hiEdge\n\n\t\t\tif (handlesInPageSpace[side].isEnabled) {\n\t\t\t\tsnap = 'edge-point'\n\t\t\t\tanchorInPageSpace = handlesInPageSpace[side].point\n\t\t\t}\n\t\t}\n\t}\n\n\tif (shouldSnapEdgePoints) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tutil.options.elbowArrowPointSnapDistance\n\t\t)\n\n\t\tlet closestSide: ElbowArrowSide | null = null\n\t\tlet closestDistance = Infinity\n\n\t\tfor (const [side, handle] of objectMapEntries(handlesInPageSpace)) {\n\t\t\tif (!handle.isEnabled) continue\n\t\t\tconst distance = Vec.Dist(handle.point, pointInPageSpace)\n\t\t\tif (distance < snapDistance && distance < closestDistance) {\n\t\t\t\tclosestDistance = distance\n\t\t\t\tclosestSide = side\n\t\t\t}\n\t\t}\n\n\t\tif (closestSide) {\n\t\t\tsnap = 'edge-point'\n\t\t\tanchorInPageSpace = handlesInPageSpace[closestSide].point\n\t\t}\n\t}\n\n\tif (shouldSnapCenter) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tarrowKind === 'elbow'\n\t\t\t\t? util.options.elbowArrowCenterSnapDistance\n\t\t\t\t: util.options.arcArrowCenterSnapDistance\n\t\t)\n\n\t\tif (Vec.Dist(pointInTargetSpace, targetBoundsInTargetSpace.center) < snapDistance) {\n\t\t\tsnap = 'center'\n\t\t\tanchorInPageSpace = targetCenterInPageSpace\n\t\t}\n\t}\n\n\tconst snapPointInTargetSpace = editor.getPointInShapeSpace(target, anchorInPageSpace)\n\n\tconst normalizedAnchor = {\n\t\tx: invLerp(\n\t\t\ttargetBoundsInTargetSpace.minX,\n\t\t\ttargetBoundsInTargetSpace.maxX,\n\t\t\tsnapPointInTargetSpace.x\n\t\t),\n\t\ty: invLerp(\n\t\t\ttargetBoundsInTargetSpace.minY,\n\t\t\ttargetBoundsInTargetSpace.maxY,\n\t\t\tsnapPointInTargetSpace.y\n\t\t),\n\t}\n\n\tconst result: ArrowTargetState = {\n\t\ttarget,\n\t\tarrowKind,\n\t\thandlesInPageSpace,\n\t\tcenterInPageSpace: targetCenterInPageSpace,\n\t\tanchorInPageSpace,\n\t\tisExact,\n\t\tisPrecise: precise,\n\t\tsnap,\n\t\tnormalizedAnchor,\n\t}\n\n\tgetArrowTargetAtom(editor).set(result)\n\n\treturn result\n}\n\nconst targetFilterFallback = { type: 'arrow' }\n\n/**\n * Funky math but we want the snap distance to be 4 at the minimum and either 16 or 15% of the\n * smaller dimension of the target shape, whichever is smaller\n */\nfunction calculateSnapDistance(\n\teditor: Editor,\n\ttargetBoundsInTargetSpace: Box,\n\tidealSnapDistance: number\n) {\n\treturn (\n\t\tclamp(\n\t\t\tMath.min(targetBoundsInTargetSpace.width, targetBoundsInTargetSpace.height) * 0.15,\n\t\t\t4,\n\t\t\tidealSnapDistance\n\t\t) / editor.getZoomLevel()\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tArrowShapeKindStyle,\n\tatom,\n\tAtom,\n\tBox,\n\tclamp,\n\tEditor,\n\tElbowArrowSnap,\n\tGeometry2dFilters,\n\tinvLerp,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapKeys,\n\tTLArrowBinding,\n\tTLArrowShape,\n\tTLArrowShapeKind,\n\tTLShape,\n\tVec,\n\tVecLike,\n\tWeakCache,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from './ArrowShapeUtil'\nimport {\n\tElbowArrowAxes,\n\tElbowArrowSide,\n\tElbowArrowSideAxes,\n\tElbowArrowSideDeltas,\n} from './elbow/definitions'\n\n/**\n * Options passed to {@link updateArrowTargetState}.\n *\n * @public\n */\nexport interface UpdateArrowTargetStateOpts {\n\teditor: Editor\n\tpointInPageSpace: VecLike\n\tarrow: TLArrowShape | undefined\n\tisPrecise: boolean\n\tcurrentBinding: TLArrowBinding | undefined\n\t/** The binding from the opposite end of the arrow, if one exists. */\n\toppositeBinding: TLArrowBinding | undefined\n}\n\n/**\n * State representing what we're pointing to when drawing or updating an arrow. You can get this\n * state using {@link getArrowTargetState}, and update it as part of an arrow interaction with\n * {@link updateArrowTargetState} or {@link clearArrowTargetState}.\n *\n * @public\n */\nexport interface ArrowTargetState {\n\ttarget: TLShape\n\tarrowKind: TLArrowShapeKind\n\n\thandlesInPageSpace: {\n\t\ttop: { point: VecLike; isEnabled: boolean }\n\t\tbottom: { point: VecLike; isEnabled: boolean }\n\t\tleft: { point: VecLike; isEnabled: boolean }\n\t\tright: { point: VecLike; isEnabled: boolean }\n\t}\n\n\tisExact: boolean\n\tisPrecise: boolean\n\n\tcenterInPageSpace: VecLike\n\tanchorInPageSpace: VecLike\n\tsnap: ElbowArrowSnap\n\tnormalizedAnchor: VecLike\n}\n\nconst arrowTargetStore = new WeakCache<Editor, Atom<ArrowTargetState | null>>()\n\nfunction getArrowTargetAtom(editor: Editor) {\n\treturn arrowTargetStore.get(editor, () => atom('arrowTarget', null))\n}\n\n/**\n * Get the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function getArrowTargetState(editor: Editor) {\n\treturn getArrowTargetAtom(editor).get()\n}\n\n/**\n * Clear the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function clearArrowTargetState(editor: Editor) {\n\tgetArrowTargetAtom(editor).set(null)\n}\n\n/**\n * Update the current arrow target state for an editor. See {@link ArrowTargetState} for more\n * information.\n *\n * @public\n */\nexport function updateArrowTargetState({\n\teditor,\n\tpointInPageSpace,\n\tarrow,\n\tisPrecise,\n\tcurrentBinding,\n\toppositeBinding,\n}: UpdateArrowTargetStateOpts): ArrowTargetState | null {\n\tconst util = editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\n\t// no target picking when ctrl is held:\n\tif (util.options.shouldIgnoreTargets(editor)) {\n\t\tgetArrowTargetAtom(editor).set(null)\n\t\treturn null\n\t}\n\n\tconst arrowKind = arrow ? arrow.props.kind : editor.getStyleForNextShape(ArrowShapeKindStyle)\n\n\tconst target = editor.getShapeAtPoint(pointInPageSpace, {\n\t\thitInside: true,\n\t\thitFrameInside: true,\n\t\tmargin: arrowKind === 'elbow' ? 8 : [8, 0],\n\t\tfilter: (targetShape) => {\n\t\t\treturn (\n\t\t\t\t!targetShape.isLocked &&\n\t\t\t\teditor.canBindShapes({\n\t\t\t\t\tfromShape: arrow ?? targetFilterFallback,\n\t\t\t\t\ttoShape: targetShape,\n\t\t\t\t\tbinding: 'arrow',\n\t\t\t\t})\n\t\t\t)\n\t\t},\n\t})\n\n\tif (!target) {\n\t\tgetArrowTargetAtom(editor).set(null)\n\t\treturn null\n\t}\n\n\tconst targetGeometryInTargetSpace = editor.getShapeGeometry(target)\n\tconst targetBoundsInTargetSpace = Box.ZeroFix(targetGeometryInTargetSpace.bounds)\n\tconst targetCenterInTargetSpace = targetGeometryInTargetSpace.center\n\tconst targetTransform = editor.getShapePageTransform(target)\n\tconst pointInTargetSpace = editor.getPointInShapeSpace(target, pointInPageSpace)\n\n\tconst castDistance = Math.max(\n\t\ttargetGeometryInTargetSpace.bounds.width,\n\t\ttargetGeometryInTargetSpace.bounds.height\n\t)\n\n\tconst handlesInPageSpace = mapObjectMapValues(ElbowArrowSideDeltas, (side, delta) => {\n\t\tconst axis = ElbowArrowAxes[ElbowArrowSideAxes[side]]\n\n\t\tconst farPoint = Vec.Mul(delta, castDistance).add(targetCenterInTargetSpace)\n\n\t\tlet isEnabled = false\n\t\tlet handlePointInTargetSpace: VecLike = axis.v(\n\t\t\ttargetBoundsInTargetSpace[side],\n\t\t\ttargetBoundsInTargetSpace[axis.crossMid]\n\t\t)\n\t\tlet furthestDistance = 0\n\n\t\tconst intersections = targetGeometryInTargetSpace.intersectLineSegment(\n\t\t\ttargetCenterInTargetSpace,\n\t\t\tfarPoint,\n\t\t\tGeometry2dFilters.EXCLUDE_NON_STANDARD\n\t\t)\n\t\tfor (const intersection of intersections) {\n\t\t\tconst distance = Vec.Dist2(intersection, targetCenterInTargetSpace)\n\t\t\tif (distance > furthestDistance) {\n\t\t\t\tfurthestDistance = distance\n\t\t\t\thandlePointInTargetSpace = intersection\n\t\t\t\tisEnabled = targetGeometryInTargetSpace.isClosed\n\t\t\t}\n\t\t}\n\n\t\tconst handlePointInPageSpace = targetTransform.applyToPoint(handlePointInTargetSpace)\n\n\t\treturn { point: handlePointInPageSpace, isEnabled, far: targetTransform.applyToPoint(farPoint) }\n\t})\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst minDistScaled = util.options.minElbowHandleDistance / zoomLevel\n\n\tconst targetCenterInPageSpace = targetTransform.applyToPoint(targetCenterInTargetSpace)\n\tfor (const side of objectMapKeys(handlesInPageSpace)) {\n\t\tconst handle = handlesInPageSpace[side]\n\t\tif (Vec.DistMin(handle.point, targetCenterInPageSpace, minDistScaled)) {\n\t\t\thandle.isEnabled = false\n\t\t}\n\t}\n\n\tlet precise = isPrecise\n\n\tif (!precise) {\n\t\t// If we're switching to a new bound shape, then precise only if moving slowly\n\t\tif (!currentBinding || (currentBinding && target.id !== currentBinding.toId)) {\n\t\t\tprecise = editor.inputs.pointerVelocity.len() < 0.5\n\t\t}\n\t}\n\n\tif (!isPrecise) {\n\t\tif (!targetGeometryInTargetSpace.isClosed) {\n\t\t\tprecise = true\n\t\t}\n\n\t\t// Double check that we're not going to be doing an imprecise snap on\n\t\t// the same shape twice, as this would result in a zero length line\n\t\tif (oppositeBinding && target.id === oppositeBinding.toId && oppositeBinding.props.isPrecise) {\n\t\t\tprecise = true\n\t\t}\n\t}\n\n\tconst isExact = util.options.shouldBeExact(editor, precise)\n\tif (isExact) precise = true\n\n\tconst shouldSnapCenter = !isExact && precise && targetGeometryInTargetSpace.isClosed\n\t// const shouldSnapEdges = !isExact && (precise || !targetGeometryInTargetSpace.isClosed)\n\tconst shouldSnapEdges =\n\t\t!isExact && ((precise && arrowKind === 'elbow') || !targetGeometryInTargetSpace.isClosed)\n\tconst shouldSnapEdgePoints =\n\t\t!isExact && precise && arrowKind === 'elbow' && targetGeometryInTargetSpace.isClosed\n\tconst shouldSnapNone = precise && (targetGeometryInTargetSpace.isClosed || isExact)\n\tconst shouldSnapCenterAxis =\n\t\t!isExact && precise && arrowKind === 'elbow' && targetGeometryInTargetSpace.isClosed\n\n\t// we run through all the snapping options from least to most specific:\n\tlet snap: ElbowArrowSnap = 'none'\n\tlet anchorInPageSpace: VecLike = pointInPageSpace\n\n\tif (!shouldSnapNone) {\n\t\tsnap = 'center'\n\t\tanchorInPageSpace = targetCenterInPageSpace\n\t}\n\n\tif (shouldSnapEdges) {\n\t\tconst snapDistance = shouldSnapNone\n\t\t\t? calculateSnapDistance(\n\t\t\t\t\teditor,\n\t\t\t\t\ttargetBoundsInTargetSpace,\n\t\t\t\t\tutil.options.elbowArrowEdgeSnapDistance\n\t\t\t\t)\n\t\t\t: Infinity\n\n\t\tconst nearestPointOnEdgeInTargetSpace = targetGeometryInTargetSpace.nearestPoint(\n\t\t\tpointInTargetSpace,\n\t\t\t{\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t}\n\t\t)\n\n\t\tconst nearestPointOnEdgeInPageSpace = targetTransform.applyToPoint(\n\t\t\tnearestPointOnEdgeInTargetSpace\n\t\t)\n\n\t\tconst distance = Vec.Dist(nearestPointOnEdgeInPageSpace, pointInPageSpace)\n\n\t\tif (distance < snapDistance) {\n\t\t\tsnap = 'edge'\n\t\t\tanchorInPageSpace = nearestPointOnEdgeInPageSpace\n\t\t}\n\t}\n\n\tif (shouldSnapCenterAxis) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tutil.options.elbowArrowAxisSnapDistance\n\t\t)\n\n\t\tconst distanceFromXAxis = Vec.DistanceToLineSegment(\n\t\t\thandlesInPageSpace.left.far,\n\t\t\thandlesInPageSpace.right.far,\n\t\t\tpointInPageSpace\n\t\t)\n\t\tconst distanceFromYAxis = Vec.DistanceToLineSegment(\n\t\t\thandlesInPageSpace.top.far,\n\t\t\thandlesInPageSpace.bottom.far,\n\t\t\tpointInPageSpace\n\t\t)\n\n\t\tconst snapAxis =\n\t\t\tdistanceFromXAxis < distanceFromYAxis && distanceFromXAxis < snapDistance\n\t\t\t\t? 'x'\n\t\t\t\t: distanceFromYAxis < snapDistance\n\t\t\t\t\t? 'y'\n\t\t\t\t\t: null\n\n\t\tif (snapAxis) {\n\t\t\tconst axis = ElbowArrowAxes[snapAxis]\n\n\t\t\tconst loDist2 = Vec.Dist2(handlesInPageSpace[axis.loEdge].far, pointInPageSpace)\n\t\t\tconst hiDist2 = Vec.Dist2(handlesInPageSpace[axis.hiEdge].far, pointInPageSpace)\n\n\t\t\tconst side = loDist2 < hiDist2 ? axis.loEdge : axis.hiEdge\n\n\t\t\tif (handlesInPageSpace[side].isEnabled) {\n\t\t\t\tsnap = 'edge-point'\n\t\t\t\tanchorInPageSpace = handlesInPageSpace[side].point\n\t\t\t}\n\t\t}\n\t}\n\n\tif (shouldSnapEdgePoints) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tutil.options.elbowArrowPointSnapDistance\n\t\t)\n\n\t\tlet closestSide: ElbowArrowSide | null = null\n\t\tlet closestDistance = Infinity\n\n\t\tfor (const [side, handle] of objectMapEntries(handlesInPageSpace)) {\n\t\t\tif (!handle.isEnabled) continue\n\t\t\tconst distance = Vec.Dist(handle.point, pointInPageSpace)\n\t\t\tif (distance < snapDistance && distance < closestDistance) {\n\t\t\t\tclosestDistance = distance\n\t\t\t\tclosestSide = side\n\t\t\t}\n\t\t}\n\n\t\tif (closestSide) {\n\t\t\tsnap = 'edge-point'\n\t\t\tanchorInPageSpace = handlesInPageSpace[closestSide].point\n\t\t}\n\t}\n\n\tif (shouldSnapCenter) {\n\t\tconst snapDistance = calculateSnapDistance(\n\t\t\teditor,\n\t\t\ttargetBoundsInTargetSpace,\n\t\t\tarrowKind === 'elbow'\n\t\t\t\t? util.options.elbowArrowCenterSnapDistance\n\t\t\t\t: util.options.arcArrowCenterSnapDistance\n\t\t)\n\n\t\tif (Vec.Dist(pointInTargetSpace, targetBoundsInTargetSpace.center) < snapDistance) {\n\t\t\tsnap = 'center'\n\t\t\tanchorInPageSpace = targetCenterInPageSpace\n\t\t}\n\t}\n\n\tconst snapPointInTargetSpace = editor.getPointInShapeSpace(target, anchorInPageSpace)\n\n\tconst normalizedAnchor = {\n\t\tx: invLerp(\n\t\t\ttargetBoundsInTargetSpace.minX,\n\t\t\ttargetBoundsInTargetSpace.maxX,\n\t\t\tsnapPointInTargetSpace.x\n\t\t),\n\t\ty: invLerp(\n\t\t\ttargetBoundsInTargetSpace.minY,\n\t\t\ttargetBoundsInTargetSpace.maxY,\n\t\t\tsnapPointInTargetSpace.y\n\t\t),\n\t}\n\n\tconst result: ArrowTargetState = {\n\t\ttarget,\n\t\tarrowKind,\n\t\thandlesInPageSpace,\n\t\tcenterInPageSpace: targetCenterInPageSpace,\n\t\tanchorInPageSpace,\n\t\tisExact,\n\t\tisPrecise: precise,\n\t\tsnap,\n\t\tnormalizedAnchor,\n\t}\n\n\tgetArrowTargetAtom(editor).set(result)\n\n\treturn result\n}\n\nconst targetFilterFallback = { type: 'arrow' as const }\n\n/**\n * Funky math but we want the snap distance to be 4 at the minimum and either 16 or 15% of the\n * smaller dimension of the target shape, whichever is smaller\n */\nfunction calculateSnapDistance(\n\teditor: Editor,\n\ttargetBoundsInTargetSpace: Box,\n\tidealSnapDistance: number\n) {\n\treturn (\n\t\tclamp(\n\t\t\tMath.min(targetBoundsInTargetSpace.width, targetBoundsInTargetSpace.height) * 0.15,\n\t\t\t4,\n\t\t\tidealSnapDistance\n\t\t) / editor.getZoomLevel()\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx"],
4
- "sourcesContent": ["import {\n\tcomputed,\n\tComputed,\n\tEditor,\n\tTLArrowShape,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tWeakCache,\n} from '@tldraw/editor'\nimport { getArrowBindings } from '../shared'\n\n/**\n * A snap line for an elbow arrow segment.\n *\n * This should already belong to ElbowArrowSnapLines establishing an angle of the line.\n */\ninterface ElbowArrowSnapLine {\n\t/** The id of the shape that the snap line starts from. */\n\tstartBoundShapeId: TLShapeId | undefined\n\t/** The id of the shape that the snap line ends at. */\n\tendBoundShapeId: TLShapeId | undefined\n\t/** The perpendicular distance from the snap line to the origin. */\n\tperpDistance: number\n}\n\n/**\n * A map from an angle (0-\u03C0) to a set of snap lines. Snap lines are stored in page space. They're\n * modelled as an angle (the angle of the line itself) and a perpendicular signed distance from the\n * page origin. Each line is effectively infinite in length, but modelling them in this way makes it\n * pretty efficient for us to query for relevant snap lines.\n */\ntype ElbowArrowSnapLines = Map<number, Set<ElbowArrowSnapLine>>\n\nconst snapLinesStore = new WeakCache<Editor, Computed<ElbowArrowSnapLines>>()\n\nexport function getElbowArrowSnapLines(editor: Editor) {\n\treturn snapLinesStore\n\t\t.get(editor, (editor) => {\n\t\t\tconst currentSelectedArrowShape = computed('current selected arrow shape', () => {\n\t\t\t\tconst shape = editor.getOnlySelectedShape()\n\t\t\t\tif (!shape || !editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) return null\n\t\t\t\treturn shape.id\n\t\t\t})\n\n\t\t\tconst unselectedArrowShapeIds = editor.store.query.ids('shape', () => {\n\t\t\t\tconst activeArrowShapeId = currentSelectedArrowShape.get()\n\t\t\t\tif (!activeArrowShapeId) return { type: { eq: 'arrow' } }\n\t\t\t\treturn {\n\t\t\t\t\ttype: { eq: 'arrow' },\n\t\t\t\t\tid: { neq: activeArrowShapeId },\n\t\t\t\t}\n\t\t\t})\n\n\t\t\treturn computed('elbow arrow snap lines', () => {\n\t\t\t\t// the result is a map from angle (0-\u03C0), to a set of single-axis co-ordinates. For\n\t\t\t\t// example, if a line from (0, 1) to (1, 1) is found (ie a horizontal line at y-coord 1),\n\t\t\t\t// we'll add an entry to the map with the key 0 (horizontal), and the set containing 1.\n\t\t\t\tconst result = new Map<number, Set<ElbowArrowSnapLine>>()\n\n\t\t\t\tconst currentPageShapeIds = editor.getCurrentPageShapeIds()\n\t\t\t\tconst viewportBounds = editor.getViewportPageBounds()\n\n\t\t\t\tfor (const id of unselectedArrowShapeIds.get()) {\n\t\t\t\t\tif (!currentPageShapeIds.has(id)) continue\n\n\t\t\t\t\tconst shape = editor.getShape<TLArrowShape>(id)\n\t\t\t\t\tif (shape?.type !== 'arrow') continue\n\n\t\t\t\t\tconst shapeBounds = editor.getShapePageBounds(id)\n\t\t\t\t\tif (!shapeBounds || !viewportBounds.includes(shapeBounds)) continue\n\n\t\t\t\t\tconst bindings = getArrowBindings(editor, shape)\n\t\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\t\tif (!pageTransform) continue\n\n\t\t\t\t\tconst geometry = editor.getShapeGeometry(id)\n\n\t\t\t\t\tconst pageVertices = pageTransform.applyToPoints(geometry.vertices)\n\n\t\t\t\t\tfor (let i = 1; i < pageVertices.length; i++) {\n\t\t\t\t\t\tconst prev = pageVertices[i - 1]\n\t\t\t\t\t\tconst curr = pageVertices[i]\n\n\t\t\t\t\t\tlet angle = Vec.Angle(prev, curr)\n\n\t\t\t\t\t\t// we don't care if the angle is going \"up\" or \"down\" - so we only care\n\t\t\t\t\t\t// about the 0-\u03C0 range\n\t\t\t\t\t\tif (angle < 0) angle += Math.PI\n\n\t\t\t\t\t\tlet set = result.get(angle)\n\t\t\t\t\t\tif (!set) {\n\t\t\t\t\t\t\tset = new Set()\n\t\t\t\t\t\t\tresult.set(angle, set)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst perpDistance = perpDistanceToLineAngle(prev, angle)\n\n\t\t\t\t\t\tset.add({\n\t\t\t\t\t\t\tperpDistance,\n\t\t\t\t\t\t\tstartBoundShapeId: bindings.start?.toId,\n\t\t\t\t\t\t\tendBoundShapeId: bindings.end?.toId,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t})\n\t\t})\n\t\t.get()\n}\n\n/**\n * Return the signed distance from the origin to a point on a line of angle `lineAngle` that passes\n * through the point `pointOnLine`.\n */\nexport function perpDistanceToLineAngle(pointOnLine: VecLike, lineAngle: number): number {\n\t// The perpendicular unit vector to the line direction\n\tconst perpDir = Vec.FromAngle(lineAngle).per()\n\t// Project the point onto the perpendicular vector\n\treturn Vec.Dpr(pointOnLine, perpDir)\n}\n\n/**\n * Return the signed distance from the origin to the line segment defined by `A` and `B`.\n */\nexport function perpDistanceToLine(A: VecLike, B: VecLike): number {\n\treturn perpDistanceToLineAngle(A, Vec.Angle(A, B))\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBASO;AACP,oBAAiC;AAwBjC,MAAM,iBAAiB,IAAI,wBAAiD;AAErE,SAAS,uBAAuB,QAAgB;AACtD,SAAO,eACL,IAAI,QAAQ,CAACA,YAAW;AACxB,UAAM,gCAA4B,wBAAS,gCAAgC,MAAM;AAChF,YAAM,QAAQA,QAAO,qBAAqB;AAC1C,UAAI,CAAC,SAAS,CAACA,QAAO,cAA4B,OAAO,OAAO,EAAG,QAAO;AAC1E,aAAO,MAAM;AAAA,IACd,CAAC;AAED,UAAM,0BAA0BA,QAAO,MAAM,MAAM,IAAI,SAAS,MAAM;AACrE,YAAM,qBAAqB,0BAA0B,IAAI;AACzD,UAAI,CAAC,mBAAoB,QAAO,EAAE,MAAM,EAAE,IAAI,QAAQ,EAAE;AACxD,aAAO;AAAA,QACN,MAAM,EAAE,IAAI,QAAQ;AAAA,QACpB,IAAI,EAAE,KAAK,mBAAmB;AAAA,MAC/B;AAAA,IACD,CAAC;AAED,eAAO,wBAAS,0BAA0B,MAAM;AAI/C,YAAM,SAAS,oBAAI,IAAqC;AAExD,YAAM,sBAAsBA,QAAO,uBAAuB;AAC1D,YAAM,iBAAiBA,QAAO,sBAAsB;AAEpD,iBAAW,MAAM,wBAAwB,IAAI,GAAG;AAC/C,YAAI,CAAC,oBAAoB,IAAI,EAAE,EAAG;AAElC,cAAM,QAAQA,QAAO,SAAuB,EAAE;AAC9C,YAAI,OAAO,SAAS,QAAS;AAE7B,cAAM,cAAcA,QAAO,mBAAmB,EAAE;AAChD,YAAI,CAAC,eAAe,CAAC,eAAe,SAAS,WAAW,EAAG;AAE3D,cAAM,eAAW,gCAAiBA,SAAQ,KAAK;AAC/C,cAAM,gBAAgBA,QAAO,sBAAsB,EAAE;AACrD,YAAI,CAAC,cAAe;AAEpB,cAAM,WAAWA,QAAO,iBAAiB,EAAE;AAE3C,cAAM,eAAe,cAAc,cAAc,SAAS,QAAQ;AAElE,iBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,gBAAM,OAAO,aAAa,IAAI,CAAC;AAC/B,gBAAM,OAAO,aAAa,CAAC;AAE3B,cAAI,QAAQ,kBAAI,MAAM,MAAM,IAAI;AAIhC,cAAI,QAAQ,EAAG,UAAS,KAAK;AAE7B,cAAI,MAAM,OAAO,IAAI,KAAK;AAC1B,cAAI,CAAC,KAAK;AACT,kBAAM,oBAAI,IAAI;AACd,mBAAO,IAAI,OAAO,GAAG;AAAA,UACtB;AAEA,gBAAM,eAAe,wBAAwB,MAAM,KAAK;AAExD,cAAI,IAAI;AAAA,YACP;AAAA,YACA,mBAAmB,SAAS,OAAO;AAAA,YACnC,iBAAiB,SAAS,KAAK;AAAA,UAChC,CAAC;AAAA,QACF;AAAA,MACD;AAEA,aAAO;AAAA,IACR,CAAC;AAAA,EACF,CAAC,EACA,IAAI;AACP;AAMO,SAAS,wBAAwB,aAAsB,WAA2B;AAExF,QAAM,UAAU,kBAAI,UAAU,SAAS,EAAE,IAAI;AAE7C,SAAO,kBAAI,IAAI,aAAa,OAAO;AACpC;AAKO,SAAS,mBAAmB,GAAY,GAAoB;AAClE,SAAO,wBAAwB,GAAG,kBAAI,MAAM,GAAG,CAAC,CAAC;AAClD;",
4
+ "sourcesContent": ["import {\n\tcomputed,\n\tComputed,\n\tEditor,\n\tTLArrowShape,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tWeakCache,\n} from '@tldraw/editor'\nimport { getArrowBindings } from '../shared'\n\n/**\n * A snap line for an elbow arrow segment.\n *\n * This should already belong to ElbowArrowSnapLines establishing an angle of the line.\n */\ninterface ElbowArrowSnapLine {\n\t/** The id of the shape that the snap line starts from. */\n\tstartBoundShapeId: TLShapeId | undefined\n\t/** The id of the shape that the snap line ends at. */\n\tendBoundShapeId: TLShapeId | undefined\n\t/** The perpendicular distance from the snap line to the origin. */\n\tperpDistance: number\n}\n\n/**\n * A map from an angle (0-\u03C0) to a set of snap lines. Snap lines are stored in page space. They're\n * modelled as an angle (the angle of the line itself) and a perpendicular signed distance from the\n * page origin. Each line is effectively infinite in length, but modelling them in this way makes it\n * pretty efficient for us to query for relevant snap lines.\n */\ntype ElbowArrowSnapLines = Map<number, Set<ElbowArrowSnapLine>>\n\nconst snapLinesStore = new WeakCache<Editor, Computed<ElbowArrowSnapLines>>()\n\nexport function getElbowArrowSnapLines(editor: Editor) {\n\treturn snapLinesStore\n\t\t.get(editor, (editor) => {\n\t\t\tconst currentSelectedArrowShape = computed('current selected arrow shape', () => {\n\t\t\t\tconst shape = editor.getOnlySelectedShape()\n\t\t\t\tif (!shape || !editor.isShapeOfType(shape, 'arrow')) return null\n\t\t\t\treturn shape.id\n\t\t\t})\n\n\t\t\tconst unselectedArrowShapeIds = editor.store.query.ids('shape', () => {\n\t\t\t\tconst activeArrowShapeId = currentSelectedArrowShape.get()\n\t\t\t\tif (!activeArrowShapeId) return { type: { eq: 'arrow' } } as const\n\t\t\t\treturn {\n\t\t\t\t\ttype: { eq: 'arrow' },\n\t\t\t\t\tid: { neq: activeArrowShapeId },\n\t\t\t\t} as const\n\t\t\t})\n\n\t\t\treturn computed('elbow arrow snap lines', () => {\n\t\t\t\t// the result is a map from angle (0-\u03C0), to a set of single-axis co-ordinates. For\n\t\t\t\t// example, if a line from (0, 1) to (1, 1) is found (ie a horizontal line at y-coord 1),\n\t\t\t\t// we'll add an entry to the map with the key 0 (horizontal), and the set containing 1.\n\t\t\t\tconst result = new Map<number, Set<ElbowArrowSnapLine>>()\n\n\t\t\t\tconst currentPageShapeIds = editor.getCurrentPageShapeIds()\n\t\t\t\tconst viewportBounds = editor.getViewportPageBounds()\n\n\t\t\t\tfor (const id of unselectedArrowShapeIds.get()) {\n\t\t\t\t\tif (!currentPageShapeIds.has(id)) continue\n\n\t\t\t\t\tconst shape = editor.getShape<TLArrowShape>(id)\n\t\t\t\t\tif (shape?.type !== 'arrow') continue\n\n\t\t\t\t\tconst shapeBounds = editor.getShapePageBounds(id)\n\t\t\t\t\tif (!shapeBounds || !viewportBounds.includes(shapeBounds)) continue\n\n\t\t\t\t\tconst bindings = getArrowBindings(editor, shape)\n\t\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\t\tif (!pageTransform) continue\n\n\t\t\t\t\tconst geometry = editor.getShapeGeometry(id)\n\n\t\t\t\t\tconst pageVertices = pageTransform.applyToPoints(geometry.vertices)\n\n\t\t\t\t\tfor (let i = 1; i < pageVertices.length; i++) {\n\t\t\t\t\t\tconst prev = pageVertices[i - 1]\n\t\t\t\t\t\tconst curr = pageVertices[i]\n\n\t\t\t\t\t\tlet angle = Vec.Angle(prev, curr)\n\n\t\t\t\t\t\t// we don't care if the angle is going \"up\" or \"down\" - so we only care\n\t\t\t\t\t\t// about the 0-\u03C0 range\n\t\t\t\t\t\tif (angle < 0) angle += Math.PI\n\n\t\t\t\t\t\tlet set = result.get(angle)\n\t\t\t\t\t\tif (!set) {\n\t\t\t\t\t\t\tset = new Set()\n\t\t\t\t\t\t\tresult.set(angle, set)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst perpDistance = perpDistanceToLineAngle(prev, angle)\n\n\t\t\t\t\t\tset.add({\n\t\t\t\t\t\t\tperpDistance,\n\t\t\t\t\t\t\tstartBoundShapeId: bindings.start?.toId,\n\t\t\t\t\t\t\tendBoundShapeId: bindings.end?.toId,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t})\n\t\t})\n\t\t.get()\n}\n\n/**\n * Return the signed distance from the origin to a point on a line of angle `lineAngle` that passes\n * through the point `pointOnLine`.\n */\nexport function perpDistanceToLineAngle(pointOnLine: VecLike, lineAngle: number): number {\n\t// The perpendicular unit vector to the line direction\n\tconst perpDir = Vec.FromAngle(lineAngle).per()\n\t// Project the point onto the perpendicular vector\n\treturn Vec.Dpr(pointOnLine, perpDir)\n}\n\n/**\n * Return the signed distance from the origin to the line segment defined by `A` and `B`.\n */\nexport function perpDistanceToLine(A: VecLike, B: VecLike): number {\n\treturn perpDistanceToLineAngle(A, Vec.Angle(A, B))\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBASO;AACP,oBAAiC;AAwBjC,MAAM,iBAAiB,IAAI,wBAAiD;AAErE,SAAS,uBAAuB,QAAgB;AACtD,SAAO,eACL,IAAI,QAAQ,CAACA,YAAW;AACxB,UAAM,gCAA4B,wBAAS,gCAAgC,MAAM;AAChF,YAAM,QAAQA,QAAO,qBAAqB;AAC1C,UAAI,CAAC,SAAS,CAACA,QAAO,cAAc,OAAO,OAAO,EAAG,QAAO;AAC5D,aAAO,MAAM;AAAA,IACd,CAAC;AAED,UAAM,0BAA0BA,QAAO,MAAM,MAAM,IAAI,SAAS,MAAM;AACrE,YAAM,qBAAqB,0BAA0B,IAAI;AACzD,UAAI,CAAC,mBAAoB,QAAO,EAAE,MAAM,EAAE,IAAI,QAAQ,EAAE;AACxD,aAAO;AAAA,QACN,MAAM,EAAE,IAAI,QAAQ;AAAA,QACpB,IAAI,EAAE,KAAK,mBAAmB;AAAA,MAC/B;AAAA,IACD,CAAC;AAED,eAAO,wBAAS,0BAA0B,MAAM;AAI/C,YAAM,SAAS,oBAAI,IAAqC;AAExD,YAAM,sBAAsBA,QAAO,uBAAuB;AAC1D,YAAM,iBAAiBA,QAAO,sBAAsB;AAEpD,iBAAW,MAAM,wBAAwB,IAAI,GAAG;AAC/C,YAAI,CAAC,oBAAoB,IAAI,EAAE,EAAG;AAElC,cAAM,QAAQA,QAAO,SAAuB,EAAE;AAC9C,YAAI,OAAO,SAAS,QAAS;AAE7B,cAAM,cAAcA,QAAO,mBAAmB,EAAE;AAChD,YAAI,CAAC,eAAe,CAAC,eAAe,SAAS,WAAW,EAAG;AAE3D,cAAM,eAAW,gCAAiBA,SAAQ,KAAK;AAC/C,cAAM,gBAAgBA,QAAO,sBAAsB,EAAE;AACrD,YAAI,CAAC,cAAe;AAEpB,cAAM,WAAWA,QAAO,iBAAiB,EAAE;AAE3C,cAAM,eAAe,cAAc,cAAc,SAAS,QAAQ;AAElE,iBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,gBAAM,OAAO,aAAa,IAAI,CAAC;AAC/B,gBAAM,OAAO,aAAa,CAAC;AAE3B,cAAI,QAAQ,kBAAI,MAAM,MAAM,IAAI;AAIhC,cAAI,QAAQ,EAAG,UAAS,KAAK;AAE7B,cAAI,MAAM,OAAO,IAAI,KAAK;AAC1B,cAAI,CAAC,KAAK;AACT,kBAAM,oBAAI,IAAI;AACd,mBAAO,IAAI,OAAO,GAAG;AAAA,UACtB;AAEA,gBAAM,eAAe,wBAAwB,MAAM,KAAK;AAExD,cAAI,IAAI;AAAA,YACP;AAAA,YACA,mBAAmB,SAAS,OAAO;AAAA,YACnC,iBAAiB,SAAS,KAAK;AAAA,UAChC,CAAC;AAAA,QACF;AAAA,MACD;AAEA,aAAO;AAAA,IACR,CAAC;AAAA,EACF,CAAC,EACA,IAAI;AACP;AAMO,SAAS,wBAAwB,aAAsB,WAA2B;AAExF,QAAM,UAAU,kBAAI,UAAU,SAAS,EAAE,IAAI;AAE7C,SAAO,kBAAI,IAAI,aAAa,OAAO;AACpC;AAKO,SAAS,mBAAmB,GAAY,GAAoB;AAClE,SAAO,wBAAwB,GAAG,kBAAI,MAAM,GAAG,CAAC,CAAC;AAClD;",
6
6
  "names": ["editor"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/shared.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tGeometry2d,\n\tisEqualAllowingForFloatingPointErrors,\n\tMat,\n\tTLArrowBinding,\n\tTLArrowBindingProps,\n\tTLArrowShape,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n} from '@tldraw/editor'\nimport { createComputedCache } from '@tldraw/store'\nimport { TLArrowInfo } from './arrow-types'\nimport { getCurvedArrowInfo } from './curved-arrow'\nimport { getElbowArrowInfo } from './elbow/getElbowArrowInfo'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nconst MIN_ARROW_BEND = 8\n\nexport function getIsArrowStraight(shape: TLArrowShape) {\n\tif (shape.props.kind !== 'arc') return false\n\treturn Math.abs(shape.props.bend) < MIN_ARROW_BEND * shape.props.scale // snap to +-8px\n}\n\nexport interface BoundShapeInfo<T extends TLShape = TLShape> {\n\tshape: T\n\tdidIntersect: boolean\n\tisExact: boolean\n\tisClosed: boolean\n\ttransform: Mat\n\tgeometry: Geometry2d\n}\n\nexport function getBoundShapeInfoForTerminal(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tterminalName: 'start' | 'end'\n): BoundShapeInfo | undefined {\n\tconst binding = editor\n\t\t.getBindingsFromShape<TLArrowBinding>(arrow, 'arrow')\n\t\t.find((b) => b.props.terminal === terminalName)\n\tif (!binding) return\n\n\tconst boundShape = editor.getShape(binding.toId)!\n\tif (!boundShape) return\n\tconst transform = editor.getShapePageTransform(boundShape)!\n\tconst hasArrowhead =\n\t\tterminalName === 'start'\n\t\t\t? arrow.props.arrowheadStart !== 'none'\n\t\t\t: arrow.props.arrowheadEnd !== 'none'\n\tconst geometry = editor.getShapeGeometry(\n\t\tboundShape,\n\t\thasArrowhead ? undefined : { context: '@tldraw/arrow-without-arrowhead' }\n\t)\n\n\treturn {\n\t\tshape: boundShape,\n\t\ttransform,\n\t\tisClosed: geometry.isClosed,\n\t\tisExact: binding.props.isExact,\n\t\tdidIntersect: false,\n\t\tgeometry,\n\t}\n}\n\nexport function getArrowTerminalInArrowSpace(\n\teditor: Editor,\n\tarrowPageTransform: Mat,\n\tbinding: TLArrowBinding,\n\tforceImprecise: boolean\n) {\n\tconst boundShape = editor.getShape(binding.toId)\n\n\tif (!boundShape) {\n\t\t// this can happen in multiplayer contexts where the shape is being deleted\n\t\treturn new Vec(0, 0)\n\t} else {\n\t\t// Find the actual local point of the normalized terminal on\n\t\t// the bound shape and transform it to page space, then transform\n\t\t// it to arrow space\n\t\tconst { point, size } = editor.getShapeGeometry(boundShape).bounds\n\t\tconst shapePoint = Vec.Add(\n\t\t\tpoint,\n\t\t\tVec.MulV(\n\t\t\t\t// if the parent is the bound shape, then it's ALWAYS precise\n\t\t\t\tbinding.props.isPrecise || forceImprecise\n\t\t\t\t\t? binding.props.normalizedAnchor\n\t\t\t\t\t: { x: 0.5, y: 0.5 },\n\t\t\t\tsize\n\t\t\t)\n\t\t)\n\t\tconst pagePoint = Mat.applyToPoint(editor.getShapePageTransform(boundShape)!, shapePoint)\n\t\tconst arrowPoint = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pagePoint)\n\t\treturn arrowPoint\n\t}\n}\n\n/** @public */\nexport interface TLArrowBindings {\n\tstart: TLArrowBinding | undefined\n\tend: TLArrowBinding | undefined\n}\n\nconst arrowBindingsCache = createComputedCache(\n\t'arrow bindings',\n\t(editor: Editor, arrow: TLArrowShape) => {\n\t\tconst bindings = editor.getBindingsFromShape<TLArrowBinding>(arrow.id, 'arrow')\n\t\treturn {\n\t\t\tstart: bindings.find((b) => b.props.terminal === 'start'),\n\t\t\tend: bindings.find((b) => b.props.terminal === 'end'),\n\t\t}\n\t},\n\t{\n\t\t// we only look at the arrow IDs:\n\t\tareRecordsEqual: (a, b) => a.id === b.id,\n\t\t// the records should stay the same:\n\t\tareResultsEqual: (a, b) => a.start === b.start && a.end === b.end,\n\t}\n)\n\n/** @public */\nexport function getArrowBindings(editor: Editor, shape: TLArrowShape): TLArrowBindings {\n\treturn arrowBindingsCache.get(editor, shape.id)!\n}\n\nconst arrowInfoCache = createComputedCache<Editor, TLArrowInfo, TLArrowShape>(\n\t'arrow info',\n\t(editor: Editor, shape: TLArrowShape): TLArrowInfo => {\n\t\tconst bindings = getArrowBindings(editor, shape)\n\t\tif (shape.props.kind === 'elbow') {\n\t\t\tconst elbowInfo = getElbowArrowInfo(editor, shape, bindings)\n\t\t\tif (!elbowInfo?.route) return getStraightArrowInfo(editor, shape, bindings)\n\n\t\t\tconst start = elbowInfo.swapOrder ? elbowInfo.B : elbowInfo.A\n\t\t\tconst end = elbowInfo.swapOrder ? elbowInfo.A : elbowInfo.B\n\n\t\t\treturn {\n\t\t\t\ttype: 'elbow',\n\t\t\t\tbindings,\n\t\t\t\tstart: {\n\t\t\t\t\thandle: start.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[0],\n\t\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t\t},\n\t\t\t\tend: {\n\t\t\t\t\thandle: end.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[elbowInfo.route.points.length - 1],\n\t\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t\t},\n\t\t\t\telbow: elbowInfo,\n\t\t\t\troute: elbowInfo.route,\n\t\t\t\tisValid: true,\n\t\t\t}\n\t\t}\n\n\t\tif (getIsArrowStraight(shape)) {\n\t\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t\t} else {\n\t\t\treturn getCurvedArrowInfo(editor, shape, bindings)\n\t\t}\n\t},\n\t{\n\t\tareRecordsEqual: (a, b) => a.props === b.props,\n\t\tareResultsEqual: isEqualAllowingForFloatingPointErrors,\n\t}\n)\n\n/** @public */\nexport function getArrowInfo(editor: Editor, shape: TLArrowShape | TLShapeId) {\n\tconst id = typeof shape === 'string' ? shape : shape.id\n\treturn arrowInfoCache.get(editor, id)\n}\n\n/** @public */\nexport function getArrowTerminalsInArrowSpace(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n) {\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\tconst boundShapeRelationships = getBoundShapeRelationships(\n\t\teditor,\n\t\tbindings.start?.toId,\n\t\tbindings.end?.toId\n\t)\n\n\tconst start = bindings.start\n\t\t? getArrowTerminalInArrowSpace(\n\t\t\t\teditor,\n\t\t\t\tarrowPageTransform,\n\t\t\t\tbindings.start,\n\t\t\t\tboundShapeRelationships === 'double-bound' ||\n\t\t\t\t\tboundShapeRelationships === 'start-contains-end'\n\t\t\t)\n\t\t: Vec.From(shape.props.start)\n\n\tconst end = bindings.end\n\t\t? getArrowTerminalInArrowSpace(\n\t\t\t\teditor,\n\t\t\t\tarrowPageTransform,\n\t\t\t\tbindings.end,\n\t\t\t\tboundShapeRelationships === 'double-bound' ||\n\t\t\t\t\tboundShapeRelationships === 'end-contains-start'\n\t\t\t)\n\t\t: Vec.From(shape.props.end)\n\n\treturn { start, end }\n}\n\n/**\n * Create or update the arrow binding for a particular arrow terminal. Will clear up if needed.\n * @internal\n */\nexport function createOrUpdateArrowBinding(\n\teditor: Editor,\n\tarrow: TLArrowShape | TLShapeId,\n\ttarget: TLShape | TLShapeId,\n\tprops: TLArrowBindingProps\n) {\n\tconst arrowId = typeof arrow === 'string' ? arrow : arrow.id\n\tconst targetId = typeof target === 'string' ? target : target.id\n\n\tconst existingMany = editor\n\t\t.getBindingsFromShape<TLArrowBinding>(arrowId, 'arrow')\n\t\t.filter((b) => b.props.terminal === props.terminal)\n\n\t// if we've somehow ended up with too many bindings, delete the extras\n\tif (existingMany.length > 1) {\n\t\teditor.deleteBindings(existingMany.slice(1))\n\t}\n\n\tconst existing = existingMany[0]\n\tif (existing) {\n\t\teditor.updateBinding({\n\t\t\t...existing,\n\t\t\ttoId: targetId,\n\t\t\tprops,\n\t\t})\n\t} else {\n\t\teditor.createBinding({\n\t\t\ttype: 'arrow',\n\t\t\tfromId: arrowId,\n\t\t\ttoId: targetId,\n\t\t\tprops,\n\t\t})\n\t}\n}\n\n/**\n * Remove any arrow bindings for a particular terminal.\n * @internal\n */\nexport function removeArrowBinding(editor: Editor, arrow: TLArrowShape, terminal: 'start' | 'end') {\n\tconst existing = editor\n\t\t.getBindingsFromShape<TLArrowBinding>(arrow, 'arrow')\n\t\t.filter((b) => b.props.terminal === terminal)\n\n\teditor.deleteBindings(existing)\n}\n\n/** @internal */\nexport const MIN_ARROW_LENGTH = 10\n/** @internal */\nexport const BOUND_ARROW_OFFSET = 10\n/** @internal */\nexport const WAY_TOO_BIG_ARROW_BEND_FACTOR = 10\n\n/** @public */\nexport const STROKE_SIZES: Record<string, number> = {\n\ts: 2,\n\tm: 3.5,\n\tl: 5,\n\txl: 10,\n}\n\n/**\n * Get the relationships for an arrow that has two bound shape terminals.\n * If the arrow has only one bound shape, then it is always \"safe\" to apply\n * standard offsets and precision behavior. If the shape is bound to the same\n * shape on both ends, then that is an exception. If one of the shape's\n * terminals is bound to a shape that contains / is contained by the shape that\n * is bound to the other terminal, then that is also an exception.\n *\n * @param editor - the editor instance\n * @param startShapeId - the bound shape from the arrow's start\n * @param endShapeId - the bound shape from the arrow's end\n *\n * @internal */\nexport function getBoundShapeRelationships(\n\teditor: Editor,\n\tstartShapeId?: TLShapeId,\n\tendShapeId?: TLShapeId\n) {\n\tif (!startShapeId || !endShapeId) return 'safe'\n\tif (startShapeId === endShapeId) return 'double-bound'\n\tconst startBounds = editor.getShapePageBounds(startShapeId)\n\tconst endBounds = editor.getShapePageBounds(endShapeId)\n\tif (startBounds && endBounds) {\n\t\tif (startBounds.contains(endBounds)) return 'start-contains-end'\n\t\tif (endBounds.contains(startBounds)) return 'end-contains-start'\n\t}\n\treturn 'safe'\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tGeometry2d,\n\tisEqualAllowingForFloatingPointErrors,\n\tMat,\n\tTLArrowBinding,\n\tTLArrowBindingProps,\n\tTLArrowShape,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n} from '@tldraw/editor'\nimport { createComputedCache } from '@tldraw/store'\nimport { TLArrowInfo } from './arrow-types'\nimport { getCurvedArrowInfo } from './curved-arrow'\nimport { getElbowArrowInfo } from './elbow/getElbowArrowInfo'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nconst MIN_ARROW_BEND = 8\n\nexport function getIsArrowStraight(shape: TLArrowShape) {\n\tif (shape.props.kind !== 'arc') return false\n\treturn Math.abs(shape.props.bend) < MIN_ARROW_BEND * shape.props.scale // snap to +-8px\n}\n\nexport interface BoundShapeInfo<T extends TLShape = TLShape> {\n\tshape: T\n\tdidIntersect: boolean\n\tisExact: boolean\n\tisClosed: boolean\n\ttransform: Mat\n\tgeometry: Geometry2d\n}\n\nexport function getBoundShapeInfoForTerminal(\n\teditor: Editor,\n\tarrow: TLArrowShape,\n\tterminalName: 'start' | 'end'\n): BoundShapeInfo | undefined {\n\tconst binding = editor\n\t\t.getBindingsFromShape(arrow, 'arrow')\n\t\t.find((b) => b.props.terminal === terminalName)\n\tif (!binding) return\n\n\tconst boundShape = editor.getShape(binding.toId)!\n\tif (!boundShape) return\n\tconst transform = editor.getShapePageTransform(boundShape)!\n\tconst hasArrowhead =\n\t\tterminalName === 'start'\n\t\t\t? arrow.props.arrowheadStart !== 'none'\n\t\t\t: arrow.props.arrowheadEnd !== 'none'\n\tconst geometry = editor.getShapeGeometry(\n\t\tboundShape,\n\t\thasArrowhead ? undefined : { context: '@tldraw/arrow-without-arrowhead' }\n\t)\n\n\treturn {\n\t\tshape: boundShape,\n\t\ttransform,\n\t\tisClosed: geometry.isClosed,\n\t\tisExact: binding.props.isExact,\n\t\tdidIntersect: false,\n\t\tgeometry,\n\t}\n}\n\nexport function getArrowTerminalInArrowSpace(\n\teditor: Editor,\n\tarrowPageTransform: Mat,\n\tbinding: TLArrowBinding,\n\tforceImprecise: boolean\n) {\n\tconst boundShape = editor.getShape(binding.toId)\n\n\tif (!boundShape) {\n\t\t// this can happen in multiplayer contexts where the shape is being deleted\n\t\treturn new Vec(0, 0)\n\t} else {\n\t\t// Find the actual local point of the normalized terminal on\n\t\t// the bound shape and transform it to page space, then transform\n\t\t// it to arrow space\n\t\tconst { point, size } = editor.getShapeGeometry(boundShape).bounds\n\t\tconst shapePoint = Vec.Add(\n\t\t\tpoint,\n\t\t\tVec.MulV(\n\t\t\t\t// if the parent is the bound shape, then it's ALWAYS precise\n\t\t\t\tbinding.props.isPrecise || forceImprecise\n\t\t\t\t\t? binding.props.normalizedAnchor\n\t\t\t\t\t: { x: 0.5, y: 0.5 },\n\t\t\t\tsize\n\t\t\t)\n\t\t)\n\t\tconst pagePoint = Mat.applyToPoint(editor.getShapePageTransform(boundShape)!, shapePoint)\n\t\tconst arrowPoint = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pagePoint)\n\t\treturn arrowPoint\n\t}\n}\n\n/** @public */\nexport interface TLArrowBindings {\n\tstart: TLArrowBinding | undefined\n\tend: TLArrowBinding | undefined\n}\n\nconst arrowBindingsCache = createComputedCache(\n\t'arrow bindings',\n\t(editor: Editor, arrow: TLArrowShape) => {\n\t\tconst bindings = editor.getBindingsFromShape(arrow.id, 'arrow')\n\t\treturn {\n\t\t\tstart: bindings.find((b) => b.props.terminal === 'start'),\n\t\t\tend: bindings.find((b) => b.props.terminal === 'end'),\n\t\t}\n\t},\n\t{\n\t\t// we only look at the arrow IDs:\n\t\tareRecordsEqual: (a, b) => a.id === b.id,\n\t\t// the records should stay the same:\n\t\tareResultsEqual: (a, b) => a.start === b.start && a.end === b.end,\n\t}\n)\n\n/** @public */\nexport function getArrowBindings(editor: Editor, shape: TLArrowShape): TLArrowBindings {\n\treturn arrowBindingsCache.get(editor, shape.id)!\n}\n\nconst arrowInfoCache = createComputedCache<Editor, TLArrowInfo, TLArrowShape>(\n\t'arrow info',\n\t(editor: Editor, shape: TLArrowShape): TLArrowInfo => {\n\t\tconst bindings = getArrowBindings(editor, shape)\n\t\tif (shape.props.kind === 'elbow') {\n\t\t\tconst elbowInfo = getElbowArrowInfo(editor, shape, bindings)\n\t\t\tif (!elbowInfo?.route) return getStraightArrowInfo(editor, shape, bindings)\n\n\t\t\tconst start = elbowInfo.swapOrder ? elbowInfo.B : elbowInfo.A\n\t\t\tconst end = elbowInfo.swapOrder ? elbowInfo.A : elbowInfo.B\n\n\t\t\treturn {\n\t\t\t\ttype: 'elbow',\n\t\t\t\tbindings,\n\t\t\t\tstart: {\n\t\t\t\t\thandle: start.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[0],\n\t\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t\t},\n\t\t\t\tend: {\n\t\t\t\t\thandle: end.target,\n\t\t\t\t\tpoint: elbowInfo.route.points[elbowInfo.route.points.length - 1],\n\t\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t\t},\n\t\t\t\telbow: elbowInfo,\n\t\t\t\troute: elbowInfo.route,\n\t\t\t\tisValid: true,\n\t\t\t}\n\t\t}\n\n\t\tif (getIsArrowStraight(shape)) {\n\t\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t\t} else {\n\t\t\treturn getCurvedArrowInfo(editor, shape, bindings)\n\t\t}\n\t},\n\t{\n\t\tareRecordsEqual: (a, b) => a.props === b.props,\n\t\tareResultsEqual: isEqualAllowingForFloatingPointErrors,\n\t}\n)\n\n/** @public */\nexport function getArrowInfo(editor: Editor, shape: TLArrowShape | TLShapeId) {\n\tconst id = typeof shape === 'string' ? shape : shape.id\n\treturn arrowInfoCache.get(editor, id)\n}\n\n/** @public */\nexport function getArrowTerminalsInArrowSpace(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n) {\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\tconst boundShapeRelationships = getBoundShapeRelationships(\n\t\teditor,\n\t\tbindings.start?.toId,\n\t\tbindings.end?.toId\n\t)\n\n\tconst start = bindings.start\n\t\t? getArrowTerminalInArrowSpace(\n\t\t\t\teditor,\n\t\t\t\tarrowPageTransform,\n\t\t\t\tbindings.start,\n\t\t\t\tboundShapeRelationships === 'double-bound' ||\n\t\t\t\t\tboundShapeRelationships === 'start-contains-end'\n\t\t\t)\n\t\t: Vec.From(shape.props.start)\n\n\tconst end = bindings.end\n\t\t? getArrowTerminalInArrowSpace(\n\t\t\t\teditor,\n\t\t\t\tarrowPageTransform,\n\t\t\t\tbindings.end,\n\t\t\t\tboundShapeRelationships === 'double-bound' ||\n\t\t\t\t\tboundShapeRelationships === 'end-contains-start'\n\t\t\t)\n\t\t: Vec.From(shape.props.end)\n\n\treturn { start, end }\n}\n\n/**\n * Create or update the arrow binding for a particular arrow terminal. Will clear up if needed.\n * @internal\n */\nexport function createOrUpdateArrowBinding(\n\teditor: Editor,\n\tarrow: TLArrowShape | TLShapeId,\n\ttarget: TLShape | TLShapeId,\n\tprops: TLArrowBindingProps\n) {\n\tconst arrowId = typeof arrow === 'string' ? arrow : arrow.id\n\tconst targetId = typeof target === 'string' ? target : target.id\n\n\tconst existingMany = editor\n\t\t.getBindingsFromShape(arrowId, 'arrow')\n\t\t.filter((b) => b.props.terminal === props.terminal)\n\n\t// if we've somehow ended up with too many bindings, delete the extras\n\tif (existingMany.length > 1) {\n\t\teditor.deleteBindings(existingMany.slice(1))\n\t}\n\n\tconst existing = existingMany[0]\n\tif (existing) {\n\t\teditor.updateBinding({\n\t\t\t...existing,\n\t\t\ttoId: targetId,\n\t\t\tprops,\n\t\t})\n\t} else {\n\t\teditor.createBinding({\n\t\t\ttype: 'arrow',\n\t\t\tfromId: arrowId,\n\t\t\ttoId: targetId,\n\t\t\tprops,\n\t\t})\n\t}\n}\n\n/**\n * Remove any arrow bindings for a particular terminal.\n * @internal\n */\nexport function removeArrowBinding(editor: Editor, arrow: TLArrowShape, terminal: 'start' | 'end') {\n\tconst existing = editor\n\t\t.getBindingsFromShape(arrow, 'arrow')\n\t\t.filter((b) => b.props.terminal === terminal)\n\n\teditor.deleteBindings(existing)\n}\n\n/** @internal */\nexport const MIN_ARROW_LENGTH = 10\n/** @internal */\nexport const BOUND_ARROW_OFFSET = 10\n/** @internal */\nexport const WAY_TOO_BIG_ARROW_BEND_FACTOR = 10\n\n/** @public */\nexport const STROKE_SIZES: Record<string, number> = {\n\ts: 2,\n\tm: 3.5,\n\tl: 5,\n\txl: 10,\n}\n\n/**\n * Get the relationships for an arrow that has two bound shape terminals.\n * If the arrow has only one bound shape, then it is always \"safe\" to apply\n * standard offsets and precision behavior. If the shape is bound to the same\n * shape on both ends, then that is an exception. If one of the shape's\n * terminals is bound to a shape that contains / is contained by the shape that\n * is bound to the other terminal, then that is also an exception.\n *\n * @param editor - the editor instance\n * @param startShapeId - the bound shape from the arrow's start\n * @param endShapeId - the bound shape from the arrow's end\n *\n * @internal */\nexport function getBoundShapeRelationships(\n\teditor: Editor,\n\tstartShapeId?: TLShapeId,\n\tendShapeId?: TLShapeId\n) {\n\tif (!startShapeId || !endShapeId) return 'safe'\n\tif (startShapeId === endShapeId) return 'double-bound'\n\tconst startBounds = editor.getShapePageBounds(startShapeId)\n\tconst endBounds = editor.getShapePageBounds(endShapeId)\n\tif (startBounds && endBounds) {\n\t\tif (startBounds.contains(endBounds)) return 'start-contains-end'\n\t\tif (endBounds.contains(startBounds)) return 'end-contains-start'\n\t}\n\treturn 'safe'\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/arrow/toolStates/Pointing.tsx"],
4
- "sourcesContent": ["import { StateNode, TLArrowShape, createShapeId, maybeSnapToGrid } from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { clearArrowTargetState, updateArrowTargetState } from '../arrowTargetState'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape?: TLArrowShape\n\n\tisPrecise = false\n\tisPreciseTimerId: number | null = null\n\n\tmarkId = ''\n\n\toverride onEnter(info: { isPrecise?: boolean }) {\n\t\tthis.markId = ''\n\t\tthis.isPrecise = !!info.isPrecise\n\n\t\tconst targetState = updateArrowTargetState({\n\t\t\teditor: this.editor,\n\t\t\tpointInPageSpace: this.editor.inputs.currentPagePoint,\n\t\t\tarrow: undefined,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tcurrentBinding: undefined,\n\t\t\toppositeBinding: undefined,\n\t\t})\n\n\t\tif (!targetState) {\n\t\t\tthis.createArrowShape()\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.startPreciseTimeout()\n\t}\n\n\toverride onExit() {\n\t\tthis.shape = undefined\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.clearPreciseTimeout()\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.createArrowShape()\n\t\t\t}\n\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.updateArrowShapeEndHandle()\n\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape: this.shape,\n\t\t\t\thandle: { id: 'end', type: 'vertex', index: 'a3', x: 0, y: 0 },\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId || undefined,\n\t\t\t\tonInteractionEnd: 'arrow',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.cancel()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tcancel() {\n\t\tif (this.shape) {\n\t\t\t// the arrow might not have been created yet!\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcreateArrowShape() {\n\t\tconst { originPagePoint } = this.editor.inputs\n\n\t\tconst id = createShapeId()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_arrow:${id}`)\n\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\tthis.editor.createShape<TLArrowShape>({\n\t\t\tid,\n\t\t\ttype: 'arrow',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\tscale: this.editor.user.getIsDynamicResizeMode() ? 1 / this.editor.getZoomLevel() : 1,\n\t\t\t},\n\t\t})\n\n\t\tconst shape = this.editor.getShape<TLArrowShape>(id)\n\t\tif (!shape) return\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\tconst initial = this.shape\n\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\tisPrecise: true,\n\t\t\tisCreatingShape: true,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tif (change) {\n\t\t\tthis.editor.updateShapes([change])\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(id)\n\t\tthis.editor.select(id)\n\t}\n\n\tupdateArrowShapeEndHandle() {\n\t\tconst shape = this.shape\n\t\tif (!shape) throw Error(`expected shape`)\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\t// start update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// end update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst point = this.editor.getPointInShapeSpace(shape, this.editor.inputs.currentPagePoint)\n\t\t\tconst endHandle = handles.find((h) => h.id === 'end')!\n\t\t\tconst change = util.onHandleDrag?.(this.editor.getShape(shape)!, {\n\t\t\t\thandle: { ...endHandle, x: point.x, y: point.y },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(shape.id)\n\t}\n\n\tprivate startPreciseTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\n\t\tthis.isPreciseTimerId = this.editor.timers.setTimeout(() => {\n\t\t\tif (!this.getIsActive()) return\n\t\t\tthis.isPrecise = true\n\t\t}, arrowUtil.options.pointingPreciseTimeout)\n\t}\n\n\tprivate clearPreciseTimeout() {\n\t\tif (this.isPreciseTimerId !== null) {\n\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { StateNode, TLArrowShape, createShapeId, maybeSnapToGrid } from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../ArrowShapeUtil'\nimport { clearArrowTargetState, updateArrowTargetState } from '../arrowTargetState'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape?: TLArrowShape\n\n\tisPrecise = false\n\tisPreciseTimerId: number | null = null\n\n\tmarkId = ''\n\n\toverride onEnter(info: { isPrecise?: boolean }) {\n\t\tthis.markId = ''\n\t\tthis.isPrecise = !!info.isPrecise\n\n\t\tconst targetState = updateArrowTargetState({\n\t\t\teditor: this.editor,\n\t\t\tpointInPageSpace: this.editor.inputs.currentPagePoint,\n\t\t\tarrow: undefined,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tcurrentBinding: undefined,\n\t\t\toppositeBinding: undefined,\n\t\t})\n\n\t\tif (!targetState) {\n\t\t\tthis.createArrowShape()\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.startPreciseTimeout()\n\t}\n\n\toverride onExit() {\n\t\tthis.shape = undefined\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.clearPreciseTimeout()\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.createArrowShape()\n\t\t\t}\n\n\t\t\tif (!this.shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.updateArrowShapeEndHandle()\n\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape: this.shape,\n\t\t\t\thandle: { id: 'end', type: 'vertex', index: 'a3', x: 0, y: 0 },\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId || undefined,\n\t\t\t\tonInteractionEnd: 'arrow',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.cancel()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tcancel() {\n\t\tif (this.shape) {\n\t\t\t// the arrow might not have been created yet!\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcreateArrowShape() {\n\t\tconst { originPagePoint } = this.editor.inputs\n\n\t\tconst id = createShapeId()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_arrow:${id}`)\n\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\tthis.editor.createShape({\n\t\t\tid,\n\t\t\ttype: 'arrow',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\tscale: this.editor.user.getIsDynamicResizeMode() ? 1 / this.editor.getZoomLevel() : 1,\n\t\t\t},\n\t\t})\n\n\t\tconst shape = this.editor.getShape<TLArrowShape>(id)\n\t\tif (!shape) return\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\tconst initial = this.shape\n\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\tisPrecise: true,\n\t\t\tisCreatingShape: true,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tif (change) {\n\t\t\tthis.editor.updateShapes([change])\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(id)\n\t\tthis.editor.select(id)\n\t}\n\n\tupdateArrowShapeEndHandle() {\n\t\tconst shape = this.shape\n\t\tif (!shape) throw Error(`expected shape`)\n\n\t\tconst handles = this.editor.getShapeHandles(shape)\n\t\tif (!handles) throw Error(`expected handles for arrow`)\n\n\t\t// start update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst startHandle = handles.find((h) => h.id === 'start')!\n\t\t\tconst change = util.onHandleDrag?.(shape, {\n\t\t\t\thandle: { ...startHandle, x: 0, y: 0 },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// end update\n\t\t{\n\t\t\tconst util = this.editor.getShapeUtil<TLArrowShape>('arrow')\n\t\t\tconst initial = this.shape\n\t\t\tconst point = this.editor.getPointInShapeSpace(shape, this.editor.inputs.currentPagePoint)\n\t\t\tconst endHandle = handles.find((h) => h.id === 'end')!\n\t\t\tconst change = util.onHandleDrag?.(this.editor.getShape(shape)!, {\n\t\t\t\thandle: { ...endHandle, x: point.x, y: point.y },\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: true,\n\t\t\t\tinitial: initial,\n\t\t\t})\n\n\t\t\tif (change) {\n\t\t\t\tthis.editor.updateShapes([change])\n\t\t\t}\n\t\t}\n\n\t\t// Cache the current shape after those changes\n\t\tthis.shape = this.editor.getShape(shape.id)\n\t}\n\n\tprivate startPreciseTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\n\t\tthis.isPreciseTimerId = this.editor.timers.setTimeout(() => {\n\t\t\tif (!this.getIsActive()) return\n\t\t\tthis.isPrecise = true\n\t\t}, arrowUtil.options.pointingPreciseTimeout)\n\t}\n\n\tprivate clearPreciseTimeout() {\n\t\tif (this.isPreciseTimerId !== null) {\n\t\t\tclearTimeout(this.isPreciseTimerId)\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/bookmark/bookmarks.ts"],
4
- "sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tResult,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLShapePartial,\n\tcreateShapeId,\n\tdebounce,\n\tgetHashForString,\n} from '@tldraw/editor'\n\nexport const BOOKMARK_WIDTH = 300\nexport const BOOKMARK_HEIGHT = 320\nexport const BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\nexport function getBookmarkHeight(editor: Editor, assetId?: TLAssetId | null) {\n\tconst asset = (assetId ? editor.getAsset(assetId) : null) as TLBookmarkAsset | null\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\treturn BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\treturn SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn BOOKMARK_HEIGHT\n}\n\nexport function setBookmarkHeight(editor: Editor, shape: TLBookmarkShape) {\n\treturn {\n\t\t...shape,\n\t\tprops: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) },\n\t}\n}\n\n/** @internal */\nexport const getHumanReadableAddress = (url: string) => {\n\ttry {\n\t\tconst objUrl = new URL(url)\n\t\t// we want the hostname without any www\n\t\treturn objUrl.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn url\n\t}\n}\n\nexport function updateBookmarkAssetOnUrlChange(editor: Editor, shape: TLBookmarkShape) {\n\tconst { url } = shape.props\n\n\t// Derive the asset id from the URL\n\tconst assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))\n\n\tif (editor.getAsset(assetId)) {\n\t\t// Existing asset for this URL?\n\t\tif (shape.props.assetId !== assetId) {\n\t\t\teditor.updateShapes<TLBookmarkShape>([\n\t\t\t\t{\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tprops: { assetId },\n\t\t\t\t},\n\t\t\t])\n\t\t}\n\t} else {\n\t\t// No asset for this URL?\n\n\t\t// First, clear out the existing asset reference\n\t\teditor.updateShapes<TLBookmarkShape>([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: null },\n\t\t\t},\n\t\t])\n\n\t\t// Then try to asyncronously create a new one\n\t\tcreateBookmarkAssetOnUrlChange(editor, shape)\n\t}\n}\n\nconst createBookmarkAssetOnUrlChange = debounce(async (editor: Editor, shape: TLBookmarkShape) => {\n\tif (editor.isDisposed) return\n\n\tconst { url } = shape.props\n\n\t// Create the asset using the external content manager's createAssetFromUrl method.\n\t// This may be overwritten by the user (for example, we overwrite it on tldraw.com)\n\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\tif (!asset) {\n\t\t// No asset? Just leave the bookmark as a null assetId.\n\t\treturn\n\t}\n\n\teditor.run(() => {\n\t\t// Create the new asset\n\t\teditor.createAssets([asset])\n\n\t\t// And update the shape\n\t\teditor.updateShapes<TLBookmarkShape>([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: asset.id },\n\t\t\t},\n\t\t])\n\t})\n}, 500)\n\n/**\n * Creates a bookmark shape from a URL with unfurled metadata.\n *\n * @returns A Result containing the created bookmark shape or an error\n * @public\n */\n\nexport async function createBookmarkFromUrl(\n\teditor: Editor,\n\t{\n\t\turl,\n\t\tcenter = editor.getViewportPageBounds().center,\n\t}: {\n\t\turl: string\n\t\tcenter?: { x: number; y: number }\n\t}\n): Promise<Result<TLBookmarkShape, string>> {\n\ttry {\n\t\t// Create the bookmark asset with unfurled metadata\n\t\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\t\t// Create the bookmark shape\n\t\tconst shapeId = createShapeId()\n\t\tconst shapePartial: TLShapePartial<TLBookmarkShape> = {\n\t\t\tid: shapeId,\n\t\t\ttype: 'bookmark',\n\t\t\tx: center.x - BOOKMARK_WIDTH / 2,\n\t\t\ty: center.y - BOOKMARK_HEIGHT / 2,\n\t\t\trotation: 0,\n\t\t\topacity: 1,\n\t\t\tprops: {\n\t\t\t\turl,\n\t\t\t\tassetId: asset?.id || null,\n\t\t\t\tw: BOOKMARK_WIDTH,\n\t\t\t\th: getBookmarkHeight(editor, asset?.id),\n\t\t\t},\n\t\t}\n\n\t\teditor.run(() => {\n\t\t\t// Create the asset if we have one\n\t\t\tif (asset) {\n\t\t\t\teditor.createAssets([asset])\n\t\t\t}\n\n\t\t\t// Create the shape\n\t\t\teditor.createShapes([shapePartial])\n\t\t})\n\n\t\t// Get the created shape\n\t\tconst createdShape = editor.getShape(shapeId) as TLBookmarkShape\n\t\treturn Result.ok(createdShape)\n\t} catch (error) {\n\t\treturn Result.err(error instanceof Error ? error.message : 'Failed to create bookmark')\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tResult,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLShapePartial,\n\tcreateShapeId,\n\tdebounce,\n\tgetHashForString,\n} from '@tldraw/editor'\n\nexport const BOOKMARK_WIDTH = 300\nexport const BOOKMARK_HEIGHT = 320\nexport const BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\nexport function getBookmarkHeight(editor: Editor, assetId?: TLAssetId | null) {\n\tconst asset = (assetId ? editor.getAsset(assetId) : null) as TLBookmarkAsset | null\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\treturn BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\treturn SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn BOOKMARK_HEIGHT\n}\n\nexport function setBookmarkHeight(editor: Editor, shape: TLBookmarkShape) {\n\treturn {\n\t\t...shape,\n\t\tprops: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) },\n\t}\n}\n\n/** @internal */\nexport const getHumanReadableAddress = (url: string) => {\n\ttry {\n\t\tconst objUrl = new URL(url)\n\t\t// we want the hostname without any www\n\t\treturn objUrl.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn url\n\t}\n}\n\nexport function updateBookmarkAssetOnUrlChange(editor: Editor, shape: TLBookmarkShape) {\n\tconst { url } = shape.props\n\n\t// Derive the asset id from the URL\n\tconst assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))\n\n\tif (editor.getAsset(assetId)) {\n\t\t// Existing asset for this URL?\n\t\tif (shape.props.assetId !== assetId) {\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tprops: { assetId },\n\t\t\t\t},\n\t\t\t])\n\t\t}\n\t} else {\n\t\t// No asset for this URL?\n\n\t\t// First, clear out the existing asset reference\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: null },\n\t\t\t},\n\t\t])\n\n\t\t// Then try to asyncronously create a new one\n\t\tcreateBookmarkAssetOnUrlChange(editor, shape)\n\t}\n}\n\nconst createBookmarkAssetOnUrlChange = debounce(async (editor: Editor, shape: TLBookmarkShape) => {\n\tif (editor.isDisposed) return\n\n\tconst { url } = shape.props\n\n\t// Create the asset using the external content manager's createAssetFromUrl method.\n\t// This may be overwritten by the user (for example, we overwrite it on tldraw.com)\n\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\tif (!asset) {\n\t\t// No asset? Just leave the bookmark as a null assetId.\n\t\treturn\n\t}\n\n\teditor.run(() => {\n\t\t// Create the new asset\n\t\teditor.createAssets([asset])\n\n\t\t// And update the shape\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: asset.id },\n\t\t\t},\n\t\t])\n\t})\n}, 500)\n\n/**\n * Creates a bookmark shape from a URL with unfurled metadata.\n *\n * @returns A Result containing the created bookmark shape or an error\n * @public\n */\n\nexport async function createBookmarkFromUrl(\n\teditor: Editor,\n\t{\n\t\turl,\n\t\tcenter = editor.getViewportPageBounds().center,\n\t}: {\n\t\turl: string\n\t\tcenter?: { x: number; y: number }\n\t}\n): Promise<Result<TLBookmarkShape, string>> {\n\ttry {\n\t\t// Create the bookmark asset with unfurled metadata\n\t\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\t\t// Create the bookmark shape\n\t\tconst shapeId = createShapeId()\n\t\tconst shapePartial: TLShapePartial<TLBookmarkShape> = {\n\t\t\tid: shapeId,\n\t\t\ttype: 'bookmark',\n\t\t\tx: center.x - BOOKMARK_WIDTH / 2,\n\t\t\ty: center.y - BOOKMARK_HEIGHT / 2,\n\t\t\trotation: 0,\n\t\t\topacity: 1,\n\t\t\tprops: {\n\t\t\t\turl,\n\t\t\t\tassetId: asset?.id || null,\n\t\t\t\tw: BOOKMARK_WIDTH,\n\t\t\t\th: getBookmarkHeight(editor, asset?.id),\n\t\t\t},\n\t\t}\n\n\t\teditor.run(() => {\n\t\t\t// Create the asset if we have one\n\t\t\tif (asset) {\n\t\t\t\teditor.createAssets([asset])\n\t\t\t}\n\n\t\t\t// Create the shape\n\t\t\teditor.createShapes([shapePartial])\n\t\t})\n\n\t\t// Get the created shape\n\t\tconst createdShape = editor.getShape(shapeId) as TLBookmarkShape\n\t\treturn Result.ok(createdShape)\n\t} catch (error) {\n\t\treturn Result.err(error instanceof Error ? error.message : 'Failed to create bookmark')\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -106,7 +106,7 @@ class DrawShapeUtil extends import_editor.ShapeUtil {
106
106
  const forceSolid = (0, import_editor.useValue)(
107
107
  "force solid",
108
108
  () => {
109
- const zoomLevel = this.editor.getZoomLevel();
109
+ const zoomLevel = this.editor.getEfficientZoomLevel();
110
110
  return zoomLevel < 0.5 && zoomLevel < 1.5 / sw;
111
111
  },
112
112
  [this.editor, sw]
@@ -177,7 +177,7 @@ function DrawShapeSvg({ shape, zoomOverride }) {
177
177
  const forceSolid = (0, import_editor.useValue)(
178
178
  "force solid",
179
179
  () => {
180
- const zoomLevel = zoomOverride ?? editor.getZoomLevel();
180
+ const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel();
181
181
  return zoomLevel < 0.5 && zoomLevel < 1.5 / sw;
182
182
  },
183
183
  [editor, sw, zoomOverride]
@@ -185,7 +185,7 @@ function DrawShapeSvg({ shape, zoomOverride }) {
185
185
  const dotAdjustment = (0, import_editor.useValue)(
186
186
  "dot adjustment",
187
187
  () => {
188
- const zoomLevel = zoomOverride ?? editor.getZoomLevel();
188
+ const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel();
189
189
  return zoomLevel < 0.2 ? 0 : 0.1;
190
190
  },
191
191
  [editor, zoomOverride]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/draw/DrawShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLDrawShapeSegment,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\ttoFixed,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\n\nimport { ShapeFill } from '../shared/ShapeFill'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { getDrawShapeStrokeDashArray, getFreehandOptions, getPointsFromSegments } from './getPath'\n\n/** @public */\nexport interface DrawShapeOptions {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromSegments(shape.props.segments)\n\n\t\tconst sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg shape={shape} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLDrawShape) {\n\t\tconst allPointsFromSegments = getPointsFromSegments(shape.props.segments)\n\n\t\tlet sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst forceSolid = useValue(\n\t\t\t'force solid',\n\t\t\t() => {\n\t\t\t\tconst zoomLevel = this.editor.getZoomLevel()\n\t\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t\t},\n\t\t\t[this.editor, sw]\n\t\t)\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn <path d={solidStrokePath} />\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg shape={shape} zoomOverride={1} />\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\tconst newSegments: TLDrawShapeSegment[] = []\n\n\t\tfor (const segment of shape.props.segments) {\n\t\t\tnewSegments.push({\n\t\t\t\t...segment,\n\t\t\t\tpoints: segment.points.map(({ x, y, z }) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx: toFixed(scaleX * x),\n\t\t\t\t\t\ty: toFixed(scaleY * y),\n\t\t\t\t\t\tz,\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tsegments: newSegments,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((STROKE_SIZES[shape.props.size] * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\treturn shape.props.segments.length === 1 && shape.props.segments[0].points.length < 2\n}\n\nfunction DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverride?: number }) {\n\tconst theme = useDefaultColorTheme()\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromSegments(shape.props.segments)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 0 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed && shape.props.fill && allPointsFromSegments.length > 1 ? (\n\t\t\t\t\t<ShapeFill\n\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t)}\n\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\tcolor={shape.props.color}\n\t\t\t\t\t\tfill={shape.props.isClosed ? shape.props.fill : 'none'}\n\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t\t<path\n\t\t\t\t\td={svgInk(allPointsFromSegments, options)}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={getColorValue(theme, shape.props.color, 'solid')}\n\t\t\t\t/>\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\n\treturn (\n\t\t<>\n\t\t\t<ShapeFill\n\t\t\t\td={solidStrokePath}\n\t\t\t\ttheme={theme}\n\t\t\t\tcolor={shape.props.color}\n\t\t\t\tfill={isDot || shape.props.isClosed ? shape.props.fill : 'none'}\n\t\t\t\tscale={shape.props.scale}\n\t\t\t/>\n\t\t\t<path\n\t\t\t\td={solidStrokePath}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tfill={isDot ? getColorValue(theme, shape.props.color, 'solid') : 'none'}\n\t\t\t\tstroke={getColorValue(theme, shape.props.color, 'solid')}\n\t\t\t\tstrokeWidth={sw}\n\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t/>\n\t\t</>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBox,\n\tCircle2d,\n\tPolygon2d,\n\tPolyline2d,\n\tSVGContainer,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLDrawShape,\n\tTLDrawShapeProps,\n\tTLDrawShapeSegment,\n\tTLResizeInfo,\n\tTLShapeUtilCanvasSvgDef,\n\tVecLike,\n\tdrawShapeMigrations,\n\tdrawShapeProps,\n\tgetColorValue,\n\tlast,\n\tlerp,\n\trng,\n\ttoFixed,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\n\nimport { ShapeFill } from '../shared/ShapeFill'\nimport { STROKE_SIZES } from '../shared/default-shape-constants'\nimport { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'\nimport { getStrokePoints } from '../shared/freehand/getStrokePoints'\nimport { getSvgPathFromStrokePoints } from '../shared/freehand/svg'\nimport { svgInk } from '../shared/freehand/svgInk'\nimport { interpolateSegments } from '../shared/interpolate-props'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { getDrawShapeStrokeDashArray, getFreehandOptions, getPointsFromSegments } from './getPath'\n\n/** @public */\nexport interface DrawShapeOptions {\n\t/**\n\t * The maximum number of points in a line before the draw tool will begin a new shape.\n\t * A higher number will lead to poor performance while drawing very long lines.\n\t */\n\treadonly maxPointsPerShape: number\n}\n\n/** @public */\nexport class DrawShapeUtil extends ShapeUtil<TLDrawShape> {\n\tstatic override type = 'draw' as const\n\tstatic override props = drawShapeProps\n\tstatic override migrations = drawShapeMigrations\n\n\toverride options: DrawShapeOptions = {\n\t\tmaxPointsPerShape: 600,\n\t}\n\n\toverride hideResizeHandles(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideRotateHandle(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\toverride hideSelectionBoundsFg(shape: TLDrawShape) {\n\t\treturn getIsDot(shape)\n\t}\n\n\toverride getDefaultProps(): TLDrawShape['props'] {\n\t\treturn {\n\t\t\tsegments: [],\n\t\t\tcolor: 'black',\n\t\t\tfill: 'none',\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tisComplete: false,\n\t\t\tisClosed: false,\n\t\t\tisPen: false,\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLDrawShape) {\n\t\tconst points = getPointsFromSegments(shape.props.segments)\n\n\t\tconst sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\n\t\t// A dot\n\t\tif (shape.props.segments.length === 1) {\n\t\t\tconst box = Box.FromPoints(points)\n\t\t\tif (box.width < sw * 2 && box.height < sw * 2) {\n\t\t\t\treturn new Circle2d({\n\t\t\t\t\tx: -sw,\n\t\t\t\t\ty: -sw,\n\t\t\t\t\tradius: sw,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst strokePoints = getStrokePoints(\n\t\t\tpoints,\n\t\t\tgetFreehandOptions(shape.props, sw, shape.props.isPen, true)\n\t\t).map((p) => p.point)\n\n\t\t// A closed draw stroke\n\t\tif (shape.props.isClosed && strokePoints.length > 2) {\n\t\t\treturn new Polygon2d({\n\t\t\t\tpoints: strokePoints,\n\t\t\t\tisFilled: shape.props.fill !== 'none',\n\t\t\t})\n\t\t}\n\n\t\tif (strokePoints.length === 1) {\n\t\t\treturn new Circle2d({\n\t\t\t\tx: -sw,\n\t\t\t\ty: -sw,\n\t\t\t\tradius: sw,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\t// An open draw stroke\n\t\treturn new Polyline2d({\n\t\t\tpoints: strokePoints,\n\t\t})\n\t}\n\n\tcomponent(shape: TLDrawShape) {\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DrawShapeSvg shape={shape} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLDrawShape) {\n\t\tconst allPointsFromSegments = getPointsFromSegments(shape.props.segments)\n\n\t\tlet sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst forceSolid = useValue(\n\t\t\t'force solid',\n\t\t\t() => {\n\t\t\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t\t},\n\t\t\t[this.editor, sw]\n\t\t)\n\n\t\tif (\n\t\t\t!forceSolid &&\n\t\t\t!shape.props.isPen &&\n\t\t\tshape.props.dash === 'draw' &&\n\t\t\tallPointsFromSegments.length === 1\n\t\t) {\n\t\t\tsw += rng(shape.id)() * (sw / 6)\n\t\t}\n\n\t\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\t\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, true)\n\t\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\t\tconst solidStrokePath =\n\t\t\tstrokePoints.length > 1\n\t\t\t\t? getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\t\t\t\t: getDot(allPointsFromSegments[0], sw)\n\n\t\treturn <path d={solidStrokePath} />\n\t}\n\n\toverride toSvg(shape: TLDrawShape, ctx: SvgExportContext) {\n\t\tctx.addExportDef(getFillDefForExport(shape.props.fill))\n\t\tconst scaleFactor = 1 / shape.props.scale\n\t\treturn (\n\t\t\t<g transform={`scale(${scaleFactor})`}>\n\t\t\t\t<DrawShapeSvg shape={shape} zoomOverride={1} />\n\t\t\t</g>\n\t\t)\n\t}\n\n\toverride getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[] {\n\t\treturn [getFillDefForCanvas()]\n\t}\n\n\toverride onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\tconst newSegments: TLDrawShapeSegment[] = []\n\n\t\tfor (const segment of shape.props.segments) {\n\t\t\tnewSegments.push({\n\t\t\t\t...segment,\n\t\t\t\tpoints: segment.points.map(({ x, y, z }) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx: toFixed(scaleX * x),\n\t\t\t\t\t\ty: toFixed(scaleY * y),\n\t\t\t\t\t\tz,\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tsegments: newSegments,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride expandSelectionOutlinePx(shape: TLDrawShape): number {\n\t\tconst multiplier = shape.props.dash === 'draw' ? 1.6 : 1\n\t\treturn ((STROKE_SIZES[shape.props.size] * multiplier) / 2) * shape.props.scale\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLDrawShape,\n\t\tendShape: TLDrawShape,\n\t\tt: number\n\t): TLDrawShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tsegments: interpolateSegments(startShape.props.segments, endShape.props.segments, t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction getDot(point: VecLike, sw: number) {\n\tconst r = (sw + 1) * 0.5\n\treturn `M ${point.x} ${point.y} m -${r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${\n\t\tr * 2\n\t},0`\n}\n\nfunction getIsDot(shape: TLDrawShape) {\n\treturn shape.props.segments.length === 1 && shape.props.segments[0].points.length < 2\n}\n\nfunction DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverride?: number }) {\n\tconst theme = useDefaultColorTheme()\n\tconst editor = useEditor()\n\n\tconst allPointsFromSegments = getPointsFromSegments(shape.props.segments)\n\n\tconst showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'\n\n\tlet sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale\n\tconst forceSolid = useValue(\n\t\t'force solid',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\treturn zoomLevel < 0.5 && zoomLevel < 1.5 / sw\n\t\t},\n\t\t[editor, sw, zoomOverride]\n\t)\n\n\tconst dotAdjustment = useValue(\n\t\t'dot adjustment',\n\t\t() => {\n\t\t\tconst zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()\n\t\t\t// If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1\n\t\t\t// Chrome doesn't render anything otherwise.\n\t\t\treturn zoomLevel < 0.2 ? 0 : 0.1\n\t\t},\n\t\t[editor, zoomOverride]\n\t)\n\n\tif (\n\t\t!forceSolid &&\n\t\t!shape.props.isPen &&\n\t\tshape.props.dash === 'draw' &&\n\t\tallPointsFromSegments.length === 1\n\t) {\n\t\tsw += rng(shape.id)() * (sw / 6)\n\t}\n\n\tconst options = getFreehandOptions(shape.props, sw, showAsComplete, forceSolid)\n\n\tif (!forceSolid && shape.props.dash === 'draw') {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{shape.props.isClosed && shape.props.fill && allPointsFromSegments.length > 1 ? (\n\t\t\t\t\t<ShapeFill\n\t\t\t\t\t\td={getSvgPathFromStrokePoints(\n\t\t\t\t\t\t\tgetStrokePoints(allPointsFromSegments, options),\n\t\t\t\t\t\t\tshape.props.isClosed\n\t\t\t\t\t\t)}\n\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\tcolor={shape.props.color}\n\t\t\t\t\t\tfill={shape.props.isClosed ? shape.props.fill : 'none'}\n\t\t\t\t\t\tscale={shape.props.scale}\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t\t<path\n\t\t\t\t\td={svgInk(allPointsFromSegments, options)}\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tfill={getColorValue(theme, shape.props.color, 'solid')}\n\t\t\t\t/>\n\t\t\t</>\n\t\t)\n\t}\n\n\tconst strokePoints = getStrokePoints(allPointsFromSegments, options)\n\tconst isDot = strokePoints.length < 2\n\tconst solidStrokePath = isDot\n\t\t? getDot(allPointsFromSegments[0], 0)\n\t\t: getSvgPathFromStrokePoints(strokePoints, shape.props.isClosed)\n\n\treturn (\n\t\t<>\n\t\t\t<ShapeFill\n\t\t\t\td={solidStrokePath}\n\t\t\t\ttheme={theme}\n\t\t\t\tcolor={shape.props.color}\n\t\t\t\tfill={isDot || shape.props.isClosed ? shape.props.fill : 'none'}\n\t\t\t\tscale={shape.props.scale}\n\t\t\t/>\n\t\t\t<path\n\t\t\t\td={solidStrokePath}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tfill={isDot ? getColorValue(theme, shape.props.color, 'solid') : 'none'}\n\t\t\t\tstroke={getColorValue(theme, shape.props.color, 'solid')}\n\t\t\t\tstrokeWidth={sw}\n\t\t\t\tstrokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}\n\t\t\t\tstrokeDashoffset=\"0\"\n\t\t\t/>\n\t\t</>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }