tldraw 4.1.0-canary.9c36de6e611c → 4.1.0-canary.a152954244d2

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 (225) hide show
  1. package/dist-cjs/index.d.ts +46 -12
  2. package/dist-cjs/index.js +6 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +1 -1
  7. package/dist-cjs/lib/defaultEmbedDefinitions.js +25 -30
  8. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -33
  10. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
  12. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/curved-arrow.js +8 -2
  14. package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/straight-arrow.js +4 -1
  16. package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
  17. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +44 -102
  18. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  19. package/dist-cjs/lib/shapes/bookmark/bookmarks.js +138 -0
  20. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +7 -0
  21. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +25 -3
  22. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
  24. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +1 -1
  25. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
  26. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
  28. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
  29. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +2 -2
  30. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  31. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  32. package/dist-cjs/lib/shapes/text/PlainTextArea.js +1 -1
  33. package/dist-cjs/lib/shapes/text/RichTextArea.js +1 -1
  34. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  35. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +20 -4
  36. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  37. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  38. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  39. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +23 -11
  40. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +27 -6
  42. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  43. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -1
  44. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  45. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +21 -9
  46. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  47. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +24 -8
  48. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  49. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +21 -9
  50. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  51. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +23 -8
  52. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  53. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +21 -9
  54. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  55. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +26 -11
  56. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  57. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  58. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js +3 -3
  59. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js.map +1 -1
  60. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog.js +1 -1
  61. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +1 -1
  62. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  63. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  64. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +5 -0
  65. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +1 -1
  67. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -2
  68. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +1 -1
  70. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +1 -1
  71. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +64 -56
  72. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +54 -47
  74. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +3 -3
  75. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +63 -56
  76. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +13 -6
  78. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +1 -1
  80. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  81. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +1 -1
  82. package/dist-cjs/lib/ui/components/menu-items.js +2 -2
  83. package/dist-cjs/lib/ui/components/menu-items.js.map +1 -1
  84. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
  87. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +1 -1
  88. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +1 -1
  89. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  90. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -2
  91. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  92. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -2
  93. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +1 -1
  94. package/dist-cjs/lib/ui/components/primitives/layout.js +1 -1
  95. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +1 -1
  96. package/dist-cjs/lib/ui/context/actions.js +44 -30
  97. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  98. package/dist-cjs/lib/ui/context/breakpoints.js +1 -1
  99. package/dist-cjs/lib/ui/context/events.js +1 -1
  100. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  101. package/dist-cjs/lib/ui/hooks/useEditorEvents.js +1 -1
  102. package/dist-cjs/lib/ui/hooks/useEditorEvents.js.map +1 -1
  103. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -1
  104. package/dist-cjs/lib/ui/hooks/useLocalStorageState.js +1 -1
  105. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  106. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -4
  107. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +1 -1
  108. package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -1
  109. package/dist-cjs/lib/ui/version.js +3 -3
  110. package/dist-cjs/lib/ui/version.js.map +1 -1
  111. package/dist-cjs/lib/utils/text/richText.js +4 -4
  112. package/dist-esm/index.d.mts +46 -12
  113. package/dist-esm/index.mjs +12 -4
  114. package/dist-esm/index.mjs.map +2 -2
  115. package/dist-esm/lib/defaultEmbedDefinitions.mjs +25 -30
  116. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  117. package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -33
  118. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  119. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
  120. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  121. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +8 -2
  122. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
  123. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +4 -1
  124. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
  125. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +46 -101
  126. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +124 -0
  128. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +7 -0
  129. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +26 -3
  130. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  131. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
  132. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  133. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -1
  134. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  135. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +20 -4
  136. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  137. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  138. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  139. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +23 -11
  140. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  141. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +29 -7
  142. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  143. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +1 -1
  144. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  145. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +21 -9
  146. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  147. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +24 -8
  148. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  149. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +21 -9
  150. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  151. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +23 -8
  152. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  153. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +21 -9
  154. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  155. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +26 -11
  156. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  157. package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs +2 -2
  158. package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs.map +1 -1
  159. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +1 -1
  160. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  161. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +5 -0
  162. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -2
  164. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  165. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +68 -57
  166. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +54 -47
  168. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +3 -3
  169. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +63 -56
  170. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
  171. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs +12 -5
  172. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +2 -2
  173. package/dist-esm/lib/ui/components/menu-items.mjs +2 -2
  174. package/dist-esm/lib/ui/components/menu-items.mjs.map +1 -1
  175. package/dist-esm/lib/ui/context/actions.mjs +43 -29
  176. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  177. package/dist-esm/lib/ui/hooks/useEditorEvents.mjs +1 -1
  178. package/dist-esm/lib/ui/hooks/useEditorEvents.mjs.map +1 -1
  179. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -4
  180. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +1 -1
  181. package/dist-esm/lib/ui/version.mjs +3 -3
  182. package/dist-esm/lib/ui/version.mjs.map +1 -1
  183. package/package.json +11 -11
  184. package/src/index.ts +4 -0
  185. package/src/lib/defaultEmbedDefinitions.ts +20 -24
  186. package/src/lib/defaultExternalContentHandlers.ts +12 -37
  187. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +211 -1
  188. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +3 -0
  189. package/src/lib/shapes/arrow/curved-arrow.ts +8 -2
  190. package/src/lib/shapes/arrow/straight-arrow.ts +5 -1
  191. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +51 -135
  192. package/src/lib/shapes/bookmark/bookmarks.ts +170 -0
  193. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +28 -2
  194. package/src/lib/shapes/line/LineShapeUtil.tsx +3 -0
  195. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -1
  196. package/src/lib/shapes/text/TextShapeTool.test.ts +74 -0
  197. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +23 -6
  198. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +1 -1
  199. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +24 -12
  200. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +34 -11
  201. package/src/lib/tools/SelectTool/childStates/Idle.ts +1 -1
  202. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +23 -11
  203. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +26 -9
  204. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +23 -10
  205. package/src/lib/tools/SelectTool/childStates/Resizing.ts +24 -9
  206. package/src/lib/tools/SelectTool/childStates/Rotating.ts +27 -11
  207. package/src/lib/tools/SelectTool/childStates/Translating.ts +28 -12
  208. package/src/lib/ui/components/DebugMenu/DefaultDebugMenuContent.tsx +2 -2
  209. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +1 -1
  210. package/src/lib/ui/components/Minimap/MinimapManager.ts +6 -0
  211. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +6 -2
  212. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +60 -49
  213. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +70 -53
  214. package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +105 -90
  215. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +72 -51
  216. package/src/lib/ui/components/menu-items.tsx +2 -2
  217. package/src/lib/ui/context/actions.tsx +49 -31
  218. package/src/lib/ui/hooks/useEditorEvents.ts +1 -1
  219. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -4
  220. package/src/lib/ui/version.ts +3 -3
  221. package/src/lib/utils/embeds/embeds.test.ts +16 -34
  222. package/src/test/SelectTool.test.ts +251 -0
  223. package/src/test/bookmark-shapes.test.ts +129 -7
  224. package/src/test/customSnapping.test.tsx +55 -11
  225. package/tldraw.css +7 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/curved-arrow.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tMat,\n\tPI,\n\tPI2,\n\tTLArrowShape,\n\tVec,\n\tVecLike,\n\tcenterOfCircleFromThreePoints,\n\tclockwiseAngleDist,\n\tcounterClockwiseAngleDist,\n\tisSafeFloat,\n} from '@tldraw/editor'\nimport { TLArcInfo, TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tMIN_ARROW_LENGTH,\n\tSTROKE_SIZES,\n\tTLArrowBindings,\n\tWAY_TOO_BIG_ARROW_BEND_FACTOR,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nexport function getCurvedArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n): TLArrowInfo {\n\tconst { arrowheadEnd, arrowheadStart } = shape.props\n\tconst bend = shape.props.bend\n\n\tif (\n\t\tMath.abs(bend) >\n\t\tMath.abs(shape.props.bend * (WAY_TOO_BIG_ARROW_BEND_FACTOR * shape.props.scale))\n\t) {\n\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t}\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst med = Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end) // point between start and end\n\tconst distance = Vec.Sub(terminalsInArrowSpace.end, terminalsInArrowSpace.start)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance) // unit vector between start and end\n\tconst middle = Vec.Add(med, u.per().mul(-bend)) // middle handle\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\t// The positions of the body of the arrow, which may be different\n\t// than the arrow's start / end points if the arrow is bound to shapes\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = middle.clone()\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst isClockwise = shape.props.bend < 0\n\tconst distFn = isClockwise ? clockwiseAngleDist : counterClockwiseAngleDist\n\n\tconst handleArc = getArcInfo(a, b, c)\n\tconst handle_aCA = Vec.Angle(handleArc.center, a)\n\tconst handle_aCB = Vec.Angle(handleArc.center, b)\n\tconst handle_dAB = distFn(handle_aCA, handle_aCB)\n\n\tif (\n\t\thandleArc.length === 0 ||\n\t\thandleArc.size === 0 ||\n\t\t!isSafeFloat(handleArc.length) ||\n\t\t!isSafeFloat(handleArc.size)\n\t) {\n\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t}\n\n\tconst tempA = a.clone()\n\tconst tempB = b.clone()\n\tconst tempC = c.clone()\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tif (startShapeInfo && !startShapeInfo.isExact) {\n\t\tconst startInPageSpace = Mat.applyToPoint(arrowPageTransform, tempA)\n\t\tconst centerInPageSpace = Mat.applyToPoint(arrowPageTransform, handleArc.center)\n\t\tconst endInPageSpace = Mat.applyToPoint(arrowPageTransform, tempB)\n\n\t\tconst inverseTransform = Mat.Inverse(startShapeInfo.transform)\n\n\t\tconst startInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, startInPageSpace)\n\t\tconst centerInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, centerInPageSpace)\n\t\tconst endInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, endInPageSpace)\n\n\t\tconst { isClosed } = startShapeInfo\n\t\tlet point: VecLike | undefined\n\t\tlet intersections = Array.from(\n\t\t\tstartShapeInfo.geometry.intersectCircle(centerInStartShapeLocalSpace, handleArc.radius, {\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t})\n\t\t)\n\n\t\tif (intersections.length) {\n\t\t\tconst angleToStart = centerInStartShapeLocalSpace.angle(startInStartShapeLocalSpace)\n\t\t\tconst angleToEnd = centerInStartShapeLocalSpace.angle(endInStartShapeLocalSpace)\n\t\t\tconst dAB = distFn(angleToStart, angleToEnd)\n\n\t\t\t// Filter out any intersections that aren't in the arc\n\t\t\tintersections = intersections.filter(\n\t\t\t\t(pt) => distFn(angleToStart, centerInStartShapeLocalSpace.angle(pt)) <= dAB\n\t\t\t)\n\n\t\t\tconst targetDist = dAB * 0.25\n\n\t\t\tintersections.sort(\n\t\t\t\tisClosed\n\t\t\t\t\t? (p0, p1) =>\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInStartShapeLocalSpace.angle(p0)) - targetDist) <\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInStartShapeLocalSpace.angle(p1)) - targetDist)\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t\t\t: (p0, p1) =>\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInStartShapeLocalSpace.angle(p0)) <\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInStartShapeLocalSpace.angle(p1))\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t)\n\n\t\t\tpoint = intersections[0]\n\t\t}\n\t\tif (!point) {\n\t\t\tif (isClosed) {\n\t\t\t\tconst nearestPoint = startShapeInfo.geometry.nearestPoint(startInStartShapeLocalSpace)\n\t\t\t\tif (Vec.DistMin(nearestPoint, startInStartShapeLocalSpace, 1)) {\n\t\t\t\t\tpoint = nearestPoint\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = startInStartShapeLocalSpace\n\t\t\t}\n\t\t}\n\n\t\tif (point) {\n\t\t\ttempA.setTo(\n\t\t\t\teditor.getPointInShapeSpace(shape, Mat.applyToPoint(startShapeInfo.transform, point))\n\t\t\t)\n\n\t\t\tstartShapeInfo.didIntersect = true\n\n\t\t\tif (arrowheadStart !== 'none') {\n\t\t\t\tconst strokeOffset =\n\t\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t\t? STROKE_SIZES[startShapeInfo.shape.props.size] / 2\n\t\t\t\t\t\t: 0)\n\t\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffset) * shape.props.scale\n\t\t\t\tminLength += strokeOffset * shape.props.scale\n\t\t\t}\n\t\t}\n\t}\n\n\tif (endShapeInfo && !endShapeInfo.isExact) {\n\t\t// get points in shape's coordinates?\n\t\tconst startInPageSpace = Mat.applyToPoint(arrowPageTransform, tempA)\n\t\tconst endInPageSpace = Mat.applyToPoint(arrowPageTransform, tempB)\n\t\tconst centerInPageSpace = Mat.applyToPoint(arrowPageTransform, handleArc.center)\n\n\t\tconst inverseTransform = Mat.Inverse(endShapeInfo.transform)\n\n\t\tconst startInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, startInPageSpace)\n\t\tconst centerInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, centerInPageSpace)\n\t\tconst endInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, endInPageSpace)\n\n\t\tconst isClosed = endShapeInfo.isClosed\n\t\tlet point: VecLike | undefined\n\t\tlet intersections = Array.from(\n\t\t\tendShapeInfo.geometry.intersectCircle(centerInEndShapeLocalSpace, handleArc.radius, {\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t})\n\t\t)\n\n\t\tif (intersections.length) {\n\t\t\tconst angleToStart = centerInEndShapeLocalSpace.angle(startInEndShapeLocalSpace)\n\t\t\tconst angleToEnd = centerInEndShapeLocalSpace.angle(endInEndShapeLocalSpace)\n\t\t\tconst dAB = distFn(angleToStart, angleToEnd)\n\t\t\tconst targetDist = dAB * 0.75\n\n\t\t\t// or simplified...\n\n\t\t\tintersections = intersections.filter(\n\t\t\t\t(pt) => distFn(angleToStart, centerInEndShapeLocalSpace.angle(pt)) <= dAB\n\t\t\t)\n\n\t\t\tintersections.sort(\n\t\t\t\tisClosed\n\t\t\t\t\t? (p0, p1) =>\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInEndShapeLocalSpace.angle(p0)) - targetDist) <\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInEndShapeLocalSpace.angle(p1)) - targetDist)\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t\t\t: (p0, p1) =>\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInEndShapeLocalSpace.angle(p0)) <\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInEndShapeLocalSpace.angle(p1))\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t)\n\n\t\t\tpoint = intersections[0]\n\t\t}\n\t\tif (!point) {\n\t\t\tif (isClosed) {\n\t\t\t\tconst nearestPoint = endShapeInfo.geometry.nearestPoint(endInEndShapeLocalSpace)\n\t\t\t\tif (Vec.DistMin(nearestPoint, endInEndShapeLocalSpace, 1)) {\n\t\t\t\t\tpoint = nearestPoint\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = endInEndShapeLocalSpace\n\t\t\t}\n\t\t}\n\n\t\tif (point) {\n\t\t\t// Set b to target local point -> page point -> shape local point\n\t\t\ttempB.setTo(\n\t\t\t\teditor.getPointInShapeSpace(shape, Mat.applyToPoint(endShapeInfo.transform, point))\n\t\t\t)\n\n\t\t\tendShapeInfo.didIntersect = true\n\n\t\t\tif (arrowheadEnd !== 'none') {\n\t\t\t\tconst strokeOffset =\n\t\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t\t('size' in endShapeInfo.shape.props ? STROKE_SIZES[endShapeInfo.shape.props.size] / 2 : 0)\n\t\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffset) * shape.props.scale\n\t\t\t\tminLength += strokeOffset * shape.props.scale\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply arrowhead offsets\n\n\tlet aCA = Vec.Angle(handleArc.center, tempA) // angle center -> a\n\tlet aCB = Vec.Angle(handleArc.center, tempB) // angle center -> b\n\tlet dAB = distFn(aCA, aCB) // angle distance between a and b\n\tlet lAB = dAB * handleArc.radius // length of arc between a and b\n\n\t// Try the offsets first, then check whether the distance between the points is too small;\n\t// if it is, flip the offsets and expand them. We need to do this using temporary points\n\t// so that we can apply them both in a balanced way.\n\tconst tA = tempA.clone()\n\tconst tB = tempB.clone()\n\n\tif (offsetA !== 0) {\n\t\ttA.setTo(handleArc.center).add(\n\t\t\tVec.FromAngle(aCA + dAB * ((offsetA / lAB) * (isClockwise ? 1 : -1))).mul(handleArc.radius)\n\t\t)\n\t}\n\n\tif (offsetB !== 0) {\n\t\ttB.setTo(handleArc.center).add(\n\t\t\tVec.FromAngle(aCB + dAB * ((offsetB / lAB) * (isClockwise ? -1 : 1))).mul(handleArc.radius)\n\t\t)\n\t}\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\toffsetA *= -2\n\t\t} else if (offsetB !== 0) {\n\t\t\toffsetB *= -2\n\t\t} else {\n\t\t\t// noop\n\t\t}\n\n\t\t// if we're using negative offsets, we need to make sure that the body arc doesn't end up\n\t\t// larger than the handle arc or things will get weird:\n\t\tconst minOffsetA = 0.1 - distFn(handle_aCA, aCA) * handleArc.radius\n\t\tconst minOffsetB = 0.1 - distFn(aCB, handle_aCB) * handleArc.radius\n\t\toffsetA = Math.max(offsetA, minOffsetA)\n\t\toffsetB = Math.max(offsetB, minOffsetB)\n\t}\n\n\tif (offsetA !== 0) {\n\t\ttempA\n\t\t\t.setTo(handleArc.center)\n\t\t\t.add(\n\t\t\t\tVec.FromAngle(aCA + dAB * ((offsetA / lAB) * (isClockwise ? 1 : -1))).mul(handleArc.radius)\n\t\t\t)\n\t}\n\n\tif (offsetB !== 0) {\n\t\ttempB\n\t\t\t.setTo(handleArc.center)\n\t\t\t.add(\n\t\t\t\tVec.FromAngle(aCB + dAB * ((offsetB / lAB) * (isClockwise ? -1 : 1))).mul(handleArc.radius)\n\t\t\t)\n\t}\n\n\t// Did we miss intersections? This happens when we have overlapping shapes.\n\tif (startShapeInfo && endShapeInfo && !startShapeInfo.isExact && !endShapeInfo.isExact) {\n\t\taCA = Vec.Angle(handleArc.center, tempA) // angle center -> a\n\t\taCB = Vec.Angle(handleArc.center, tempB) // angle center -> b\n\t\tdAB = distFn(aCA, aCB) // angle distance between a and b\n\t\tlAB = dAB * handleArc.radius // length of arc between a and b\n\t\tconst relationship = getBoundShapeRelationships(\n\t\t\teditor,\n\t\t\tstartShapeInfo.shape.id,\n\t\t\tendShapeInfo.shape.id\n\t\t)\n\n\t\tif (relationship === 'double-bound' && lAB < 30) {\n\t\t\ttempA.setTo(a)\n\t\t\ttempB.setTo(b)\n\t\t\ttempC.setTo(c)\n\t\t} else if (relationship === 'safe') {\n\t\t\tif (startShapeInfo && !startShapeInfo.didIntersect) {\n\t\t\t\ttempA.setTo(a)\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t(endShapeInfo && !endShapeInfo.didIntersect) ||\n\t\t\t\tdistFn(handle_aCA, aCA) > distFn(handle_aCA, aCB)\n\t\t\t) {\n\t\t\t\ttempB\n\t\t\t\t\t.setTo(handleArc.center)\n\t\t\t\t\t.add(\n\t\t\t\t\t\tVec.FromAngle(\n\t\t\t\t\t\t\taCA +\n\t\t\t\t\t\t\t\tdAB *\n\t\t\t\t\t\t\t\t\t(Math.min(0.9, (MIN_ARROW_LENGTH * shape.props.scale) / lAB) *\n\t\t\t\t\t\t\t\t\t\t(isClockwise ? 1 : -1))\n\t\t\t\t\t\t).mul(handleArc.radius)\n\t\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\tplaceCenterHandle(\n\t\thandleArc.center,\n\t\thandleArc.radius,\n\t\ttempA,\n\t\ttempB,\n\t\ttempC,\n\t\thandle_dAB,\n\t\tisClockwise\n\t)\n\n\tif (tempA.equals(tempB)) {\n\t\ttempA.setTo(tempC.clone().addXY(1, 1))\n\t\ttempB.setTo(tempC.clone().subXY(1, 1))\n\t}\n\n\ta.setTo(tempA)\n\tb.setTo(tempB)\n\tc.setTo(tempC)\n\tconst bodyArc = getArcInfo(a, b, c)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'arc',\n\t\tstart: {\n\t\t\tpoint: a,\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\tpoint: b,\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\thandleArc,\n\t\tbodyArc,\n\t\tisValid: bodyArc.length !== 0 && isFinite(bodyArc.center.x) && isFinite(bodyArc.center.y),\n\t}\n}\n\n/**\n * Get info about an arc formed by three points.\n *\n * @param a - The start of the arc\n * @param b - The end of the arc\n * @param c - A point on the arc\n */\nfunction getArcInfo(a: VecLike, b: VecLike, c: VecLike): TLArcInfo {\n\t// find a circle from the three points\n\tconst center = centerOfCircleFromThreePoints(a, b, c) ?? Vec.Med(a, b)\n\n\tconst radius = Vec.Dist(center, a)\n\n\t// Whether to draw the arc clockwise or counter-clockwise (are the points clockwise?)\n\tconst sweepFlag = +Vec.Clockwise(a, c, b)\n\n\t// The base angle of the arc in radians\n\tconst ab = ((a.y - b.y) ** 2 + (a.x - b.x) ** 2) ** 0.5\n\tconst bc = ((b.y - c.y) ** 2 + (b.x - c.x) ** 2) ** 0.5\n\tconst ca = ((c.y - a.y) ** 2 + (c.x - a.x) ** 2) ** 0.5\n\n\tconst theta = Math.acos((bc * bc + ca * ca - ab * ab) / (2 * bc * ca)) * 2\n\n\t// Whether to draw the long arc or short arc\n\tconst largeArcFlag = +(PI > theta)\n\n\t// The size of the arc to draw in radians\n\tconst size = (PI2 - theta) * (sweepFlag ? 1 : -1)\n\n\t// The length of the arc to draw in distance units\n\tconst length = size * radius\n\n\treturn {\n\t\tcenter,\n\t\tradius,\n\t\tsize,\n\t\tlength,\n\t\tlargeArcFlag,\n\t\tsweepFlag,\n\t}\n}\n\nfunction placeCenterHandle(\n\tcenter: VecLike,\n\tradius: number,\n\ttempA: Vec,\n\ttempB: Vec,\n\ttempC: Vec,\n\toriginalArcLength: number,\n\tisClockwise: boolean\n) {\n\tconst aCA = Vec.Angle(center, tempA) // angle center -> a\n\tconst aCB = Vec.Angle(center, tempB) // angle center -> b\n\tlet dAB = clockwiseAngleDist(aCA, aCB) // angle distance between a and b\n\tif (!isClockwise) dAB = PI2 - dAB\n\n\ttempC.setTo(center).add(Vec.FromAngle(aCA + dAB * (0.5 * (isClockwise ? 1 : -1))).mul(radius))\n\n\tif (dAB > originalArcLength) {\n\t\ttempC.rotWith(center, PI)\n\t\tconst t = tempB.clone()\n\t\ttempB.setTo(tempA)\n\t\ttempA.setTo(t)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tMat,\n\tPI,\n\tPI2,\n\tTLArrowShape,\n\tVec,\n\tVecLike,\n\tcenterOfCircleFromThreePoints,\n\tclockwiseAngleDist,\n\tcounterClockwiseAngleDist,\n\tisSafeFloat,\n} from '@tldraw/editor'\nimport { TLArcInfo, TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tMIN_ARROW_LENGTH,\n\tSTROKE_SIZES,\n\tTLArrowBindings,\n\tWAY_TOO_BIG_ARROW_BEND_FACTOR,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\nimport { getStraightArrowInfo } from './straight-arrow'\n\nexport function getCurvedArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n): TLArrowInfo {\n\tconst { arrowheadEnd, arrowheadStart } = shape.props\n\tconst bend = shape.props.bend\n\n\tif (\n\t\tMath.abs(bend) >\n\t\tMath.abs(shape.props.bend * (WAY_TOO_BIG_ARROW_BEND_FACTOR * shape.props.scale))\n\t) {\n\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t}\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst med = Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end) // point between start and end\n\tconst distance = Vec.Sub(terminalsInArrowSpace.end, terminalsInArrowSpace.start)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance) // unit vector between start and end\n\tconst middle = Vec.Add(med, u.per().mul(-bend)) // middle handle\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\t// The positions of the body of the arrow, which may be different\n\t// than the arrow's start / end points if the arrow is bound to shapes\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = middle.clone()\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst isClockwise = shape.props.bend < 0\n\tconst distFn = isClockwise ? clockwiseAngleDist : counterClockwiseAngleDist\n\n\tconst handleArc = getArcInfo(a, b, c)\n\tconst handle_aCA = Vec.Angle(handleArc.center, a)\n\tconst handle_aCB = Vec.Angle(handleArc.center, b)\n\tconst handle_dAB = distFn(handle_aCA, handle_aCB)\n\n\tif (\n\t\thandleArc.length === 0 ||\n\t\thandleArc.size === 0 ||\n\t\t!isSafeFloat(handleArc.length) ||\n\t\t!isSafeFloat(handleArc.size)\n\t) {\n\t\treturn getStraightArrowInfo(editor, shape, bindings)\n\t}\n\n\tconst tempA = a.clone()\n\tconst tempB = b.clone()\n\tconst tempC = c.clone()\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tif (startShapeInfo && !startShapeInfo.isExact) {\n\t\tconst startInPageSpace = Mat.applyToPoint(arrowPageTransform, tempA)\n\t\tconst centerInPageSpace = Mat.applyToPoint(arrowPageTransform, handleArc.center)\n\t\tconst endInPageSpace = Mat.applyToPoint(arrowPageTransform, tempB)\n\n\t\tconst inverseTransform = Mat.Inverse(startShapeInfo.transform)\n\n\t\tconst startInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, startInPageSpace)\n\t\tconst centerInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, centerInPageSpace)\n\t\tconst endInStartShapeLocalSpace = Mat.applyToPoint(inverseTransform, endInPageSpace)\n\n\t\tconst { isClosed } = startShapeInfo\n\t\tlet point: VecLike | undefined\n\t\tlet intersections = Array.from(\n\t\t\tstartShapeInfo.geometry.intersectCircle(centerInStartShapeLocalSpace, handleArc.radius, {\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t})\n\t\t)\n\n\t\tif (intersections.length) {\n\t\t\tconst angleToStart = centerInStartShapeLocalSpace.angle(startInStartShapeLocalSpace)\n\t\t\tconst angleToEnd = centerInStartShapeLocalSpace.angle(endInStartShapeLocalSpace)\n\t\t\tconst dAB = distFn(angleToStart, angleToEnd)\n\n\t\t\t// Filter out any intersections that aren't in the arc\n\t\t\tintersections = intersections.filter(\n\t\t\t\t(pt) => distFn(angleToStart, centerInStartShapeLocalSpace.angle(pt)) <= dAB\n\t\t\t)\n\n\t\t\tconst targetDist = dAB * 0.25\n\n\t\t\tintersections.sort(\n\t\t\t\tisClosed\n\t\t\t\t\t? (p0, p1) =>\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInStartShapeLocalSpace.angle(p0)) - targetDist) <\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInStartShapeLocalSpace.angle(p1)) - targetDist)\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t\t\t: (p0, p1) =>\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInStartShapeLocalSpace.angle(p0)) <\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInStartShapeLocalSpace.angle(p1))\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t)\n\n\t\t\tpoint = intersections[0]\n\t\t}\n\t\tif (!point) {\n\t\t\tif (isClosed) {\n\t\t\t\tconst nearestPoint = startShapeInfo.geometry.nearestPoint(startInStartShapeLocalSpace, {\n\t\t\t\t\tincludeInternal: false,\n\t\t\t\t\tincludeLabels: false,\n\t\t\t\t})\n\t\t\t\tif (Vec.DistMin(nearestPoint, startInStartShapeLocalSpace, 1)) {\n\t\t\t\t\tpoint = nearestPoint\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = startInStartShapeLocalSpace\n\t\t\t}\n\t\t}\n\n\t\tif (point) {\n\t\t\ttempA.setTo(\n\t\t\t\teditor.getPointInShapeSpace(shape, Mat.applyToPoint(startShapeInfo.transform, point))\n\t\t\t)\n\n\t\t\tstartShapeInfo.didIntersect = true\n\n\t\t\tif (arrowheadStart !== 'none') {\n\t\t\t\tconst strokeOffset =\n\t\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t\t? STROKE_SIZES[startShapeInfo.shape.props.size] / 2\n\t\t\t\t\t\t: 0)\n\t\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffset) * shape.props.scale\n\t\t\t\tminLength += strokeOffset * shape.props.scale\n\t\t\t}\n\t\t}\n\t}\n\n\tif (endShapeInfo && !endShapeInfo.isExact) {\n\t\t// get points in shape's coordinates?\n\t\tconst startInPageSpace = Mat.applyToPoint(arrowPageTransform, tempA)\n\t\tconst endInPageSpace = Mat.applyToPoint(arrowPageTransform, tempB)\n\t\tconst centerInPageSpace = Mat.applyToPoint(arrowPageTransform, handleArc.center)\n\n\t\tconst inverseTransform = Mat.Inverse(endShapeInfo.transform)\n\n\t\tconst startInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, startInPageSpace)\n\t\tconst centerInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, centerInPageSpace)\n\t\tconst endInEndShapeLocalSpace = Mat.applyToPoint(inverseTransform, endInPageSpace)\n\n\t\tconst isClosed = endShapeInfo.isClosed\n\t\tlet point: VecLike | undefined\n\t\tlet intersections = Array.from(\n\t\t\tendShapeInfo.geometry.intersectCircle(centerInEndShapeLocalSpace, handleArc.radius, {\n\t\t\t\tincludeLabels: false,\n\t\t\t\tincludeInternal: false,\n\t\t\t})\n\t\t)\n\n\t\tif (intersections.length) {\n\t\t\tconst angleToStart = centerInEndShapeLocalSpace.angle(startInEndShapeLocalSpace)\n\t\t\tconst angleToEnd = centerInEndShapeLocalSpace.angle(endInEndShapeLocalSpace)\n\t\t\tconst dAB = distFn(angleToStart, angleToEnd)\n\t\t\tconst targetDist = dAB * 0.75\n\n\t\t\t// or simplified...\n\n\t\t\tintersections = intersections.filter(\n\t\t\t\t(pt) => distFn(angleToStart, centerInEndShapeLocalSpace.angle(pt)) <= dAB\n\t\t\t)\n\n\t\t\tintersections.sort(\n\t\t\t\tisClosed\n\t\t\t\t\t? (p0, p1) =>\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInEndShapeLocalSpace.angle(p0)) - targetDist) <\n\t\t\t\t\t\t\tMath.abs(distFn(angleToStart, centerInEndShapeLocalSpace.angle(p1)) - targetDist)\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t\t\t: (p0, p1) =>\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInEndShapeLocalSpace.angle(p0)) <\n\t\t\t\t\t\t\tdistFn(angleToStart, centerInEndShapeLocalSpace.angle(p1))\n\t\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t\t: 1\n\t\t\t)\n\n\t\t\tpoint = intersections[0]\n\t\t}\n\t\tif (!point) {\n\t\t\tif (isClosed) {\n\t\t\t\tconst nearestPoint = endShapeInfo.geometry.nearestPoint(endInEndShapeLocalSpace, {\n\t\t\t\t\tincludeInternal: false,\n\t\t\t\t\tincludeLabels: false,\n\t\t\t\t})\n\t\t\t\tif (Vec.DistMin(nearestPoint, endInEndShapeLocalSpace, 1)) {\n\t\t\t\t\tpoint = nearestPoint\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = endInEndShapeLocalSpace\n\t\t\t}\n\t\t}\n\n\t\tif (point) {\n\t\t\t// Set b to target local point -> page point -> shape local point\n\t\t\ttempB.setTo(\n\t\t\t\teditor.getPointInShapeSpace(shape, Mat.applyToPoint(endShapeInfo.transform, point))\n\t\t\t)\n\n\t\t\tendShapeInfo.didIntersect = true\n\n\t\t\tif (arrowheadEnd !== 'none') {\n\t\t\t\tconst strokeOffset =\n\t\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t\t('size' in endShapeInfo.shape.props ? STROKE_SIZES[endShapeInfo.shape.props.size] / 2 : 0)\n\t\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffset) * shape.props.scale\n\t\t\t\tminLength += strokeOffset * shape.props.scale\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply arrowhead offsets\n\n\tlet aCA = Vec.Angle(handleArc.center, tempA) // angle center -> a\n\tlet aCB = Vec.Angle(handleArc.center, tempB) // angle center -> b\n\tlet dAB = distFn(aCA, aCB) // angle distance between a and b\n\tlet lAB = dAB * handleArc.radius // length of arc between a and b\n\n\t// Try the offsets first, then check whether the distance between the points is too small;\n\t// if it is, flip the offsets and expand them. We need to do this using temporary points\n\t// so that we can apply them both in a balanced way.\n\tconst tA = tempA.clone()\n\tconst tB = tempB.clone()\n\n\tif (offsetA !== 0) {\n\t\ttA.setTo(handleArc.center).add(\n\t\t\tVec.FromAngle(aCA + dAB * ((offsetA / lAB) * (isClockwise ? 1 : -1))).mul(handleArc.radius)\n\t\t)\n\t}\n\n\tif (offsetB !== 0) {\n\t\ttB.setTo(handleArc.center).add(\n\t\t\tVec.FromAngle(aCB + dAB * ((offsetB / lAB) * (isClockwise ? -1 : 1))).mul(handleArc.radius)\n\t\t)\n\t}\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\toffsetA *= -2\n\t\t} else if (offsetB !== 0) {\n\t\t\toffsetB *= -2\n\t\t} else {\n\t\t\t// noop\n\t\t}\n\n\t\t// if we're using negative offsets, we need to make sure that the body arc doesn't end up\n\t\t// larger than the handle arc or things will get weird:\n\t\tconst minOffsetA = 0.1 - distFn(handle_aCA, aCA) * handleArc.radius\n\t\tconst minOffsetB = 0.1 - distFn(aCB, handle_aCB) * handleArc.radius\n\t\toffsetA = Math.max(offsetA, minOffsetA)\n\t\toffsetB = Math.max(offsetB, minOffsetB)\n\t}\n\n\tif (offsetA !== 0) {\n\t\ttempA\n\t\t\t.setTo(handleArc.center)\n\t\t\t.add(\n\t\t\t\tVec.FromAngle(aCA + dAB * ((offsetA / lAB) * (isClockwise ? 1 : -1))).mul(handleArc.radius)\n\t\t\t)\n\t}\n\n\tif (offsetB !== 0) {\n\t\ttempB\n\t\t\t.setTo(handleArc.center)\n\t\t\t.add(\n\t\t\t\tVec.FromAngle(aCB + dAB * ((offsetB / lAB) * (isClockwise ? -1 : 1))).mul(handleArc.radius)\n\t\t\t)\n\t}\n\n\t// Did we miss intersections? This happens when we have overlapping shapes.\n\tif (startShapeInfo && endShapeInfo && !startShapeInfo.isExact && !endShapeInfo.isExact) {\n\t\taCA = Vec.Angle(handleArc.center, tempA) // angle center -> a\n\t\taCB = Vec.Angle(handleArc.center, tempB) // angle center -> b\n\t\tdAB = distFn(aCA, aCB) // angle distance between a and b\n\t\tlAB = dAB * handleArc.radius // length of arc between a and b\n\t\tconst relationship = getBoundShapeRelationships(\n\t\t\teditor,\n\t\t\tstartShapeInfo.shape.id,\n\t\t\tendShapeInfo.shape.id\n\t\t)\n\n\t\tif (relationship === 'double-bound' && lAB < 30) {\n\t\t\ttempA.setTo(a)\n\t\t\ttempB.setTo(b)\n\t\t\ttempC.setTo(c)\n\t\t} else if (relationship === 'safe') {\n\t\t\tif (startShapeInfo && !startShapeInfo.didIntersect) {\n\t\t\t\ttempA.setTo(a)\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t(endShapeInfo && !endShapeInfo.didIntersect) ||\n\t\t\t\tdistFn(handle_aCA, aCA) > distFn(handle_aCA, aCB)\n\t\t\t) {\n\t\t\t\ttempB\n\t\t\t\t\t.setTo(handleArc.center)\n\t\t\t\t\t.add(\n\t\t\t\t\t\tVec.FromAngle(\n\t\t\t\t\t\t\taCA +\n\t\t\t\t\t\t\t\tdAB *\n\t\t\t\t\t\t\t\t\t(Math.min(0.9, (MIN_ARROW_LENGTH * shape.props.scale) / lAB) *\n\t\t\t\t\t\t\t\t\t\t(isClockwise ? 1 : -1))\n\t\t\t\t\t\t).mul(handleArc.radius)\n\t\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\tplaceCenterHandle(\n\t\thandleArc.center,\n\t\thandleArc.radius,\n\t\ttempA,\n\t\ttempB,\n\t\ttempC,\n\t\thandle_dAB,\n\t\tisClockwise\n\t)\n\n\tif (tempA.equals(tempB)) {\n\t\ttempA.setTo(tempC.clone().addXY(1, 1))\n\t\ttempB.setTo(tempC.clone().subXY(1, 1))\n\t}\n\n\ta.setTo(tempA)\n\tb.setTo(tempB)\n\tc.setTo(tempC)\n\tconst bodyArc = getArcInfo(a, b, c)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'arc',\n\t\tstart: {\n\t\t\tpoint: a,\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\tpoint: b,\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\thandleArc,\n\t\tbodyArc,\n\t\tisValid: bodyArc.length !== 0 && isFinite(bodyArc.center.x) && isFinite(bodyArc.center.y),\n\t}\n}\n\n/**\n * Get info about an arc formed by three points.\n *\n * @param a - The start of the arc\n * @param b - The end of the arc\n * @param c - A point on the arc\n */\nfunction getArcInfo(a: VecLike, b: VecLike, c: VecLike): TLArcInfo {\n\t// find a circle from the three points\n\tconst center = centerOfCircleFromThreePoints(a, b, c) ?? Vec.Med(a, b)\n\n\tconst radius = Vec.Dist(center, a)\n\n\t// Whether to draw the arc clockwise or counter-clockwise (are the points clockwise?)\n\tconst sweepFlag = +Vec.Clockwise(a, c, b)\n\n\t// The base angle of the arc in radians\n\tconst ab = ((a.y - b.y) ** 2 + (a.x - b.x) ** 2) ** 0.5\n\tconst bc = ((b.y - c.y) ** 2 + (b.x - c.x) ** 2) ** 0.5\n\tconst ca = ((c.y - a.y) ** 2 + (c.x - a.x) ** 2) ** 0.5\n\n\tconst theta = Math.acos((bc * bc + ca * ca - ab * ab) / (2 * bc * ca)) * 2\n\n\t// Whether to draw the long arc or short arc\n\tconst largeArcFlag = +(PI > theta)\n\n\t// The size of the arc to draw in radians\n\tconst size = (PI2 - theta) * (sweepFlag ? 1 : -1)\n\n\t// The length of the arc to draw in distance units\n\tconst length = size * radius\n\n\treturn {\n\t\tcenter,\n\t\tradius,\n\t\tsize,\n\t\tlength,\n\t\tlargeArcFlag,\n\t\tsweepFlag,\n\t}\n}\n\nfunction placeCenterHandle(\n\tcenter: VecLike,\n\tradius: number,\n\ttempA: Vec,\n\ttempB: Vec,\n\ttempC: Vec,\n\toriginalArcLength: number,\n\tisClockwise: boolean\n) {\n\tconst aCA = Vec.Angle(center, tempA) // angle center -> a\n\tconst aCB = Vec.Angle(center, tempB) // angle center -> b\n\tlet dAB = clockwiseAngleDist(aCA, aCB) // angle distance between a and b\n\tif (!isClockwise) dAB = PI2 - dAB\n\n\ttempC.setTo(center).add(Vec.FromAngle(aCA + dAB * (0.5 * (isClockwise ? 1 : -1))).mul(radius))\n\n\tif (dAB > originalArcLength) {\n\t\ttempC.rotWith(center, PI)\n\t\tconst t = tempB.clone()\n\t\ttempB.setTo(tempA)\n\t\ttempA.setTo(t)\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["dAB"]
7
7
  }
@@ -147,7 +147,10 @@ function updateArrowheadPointWithBoundShape(point, opposite, arrowPageTransform,
147
147
  targetInt = intersection.sort((p1, p2) => Vec.Dist2(p1, targetFrom) - Vec.Dist2(p2, targetFrom))[0] ?? (targetShapeInfo.isClosed ? void 0 : targetTo);
148
148
  }
149
149
  if (targetInt === void 0) {
150
- targetInt = targetShapeInfo.geometry.nearestPoint(targetTo);
150
+ targetInt = targetShapeInfo.geometry.nearestPoint(targetTo, {
151
+ includeLabels: false,
152
+ includeInternal: false
153
+ });
151
154
  if (!Vec.DistMin(targetInt, targetTo, 1)) {
152
155
  return;
153
156
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/arrow/straight-arrow.ts"],
4
- "sourcesContent": ["import { Editor, Mat, MatModel, TLArrowShape, Vec, VecLike } from '@tldraw/editor'\nimport { TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tBoundShapeInfo,\n\tMIN_ARROW_LENGTH,\n\tSTROKE_SIZES,\n\tTLArrowBindings,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\n\nexport function getStraightArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n): TLArrowInfo {\n\tconst { arrowheadStart, arrowheadEnd } = shape.props\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = Vec.Med(a, b)\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst uAB = Vec.Sub(b, a).uni()\n\n\t// Update the arrowhead points using intersections with the bound shapes, if any.\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\t// Update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\tb, // <-- will be mutated\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tendShapeInfo\n\t)\n\n\t// Then update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\ta, // <-- will be mutated\n\t\tterminalsInArrowSpace.end,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\tlet strokeOffsetA = 0\n\tlet strokeOffsetB = 0\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tconst isSelfIntersection =\n\t\tstartShapeInfo && endShapeInfo && startShapeInfo.shape === endShapeInfo.shape\n\n\tconst relationship =\n\t\tstartShapeInfo && endShapeInfo\n\t\t\t? getBoundShapeRelationships(editor, startShapeInfo.shape.id, endShapeInfo.shape.id)\n\t\t\t: 'safe'\n\n\tif (\n\t\trelationship === 'safe' &&\n\t\tstartShapeInfo &&\n\t\tendShapeInfo &&\n\t\t!isSelfIntersection &&\n\t\t!startShapeInfo.isExact &&\n\t\t!endShapeInfo.isExact\n\t) {\n\t\tif (endShapeInfo.didIntersect && !startShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, then make it\n\t\t\t// a short arrow ending at the end shape intersection.\n\t\t\tif (startShapeInfo.isClosed) {\n\t\t\t\ta.setTo(b.clone().add(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t} else if (!endShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, or if neither\n\t\t\t// shape intersected, then make it a short arrow starting\n\t\t\t// at the start shape intersection.\n\t\t\tif (endShapeInfo.isClosed) {\n\t\t\t\tb.setTo(a.clone().sub(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t}\n\t}\n\n\tconst distance = Vec.Sub(b, a)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance)\n\tconst didFlip = !Vec.Equals(u, uAB)\n\n\t// If the arrow is bound non-exact to a start shape and the\n\t// start point has an arrowhead, then offset the start point\n\tif (!isSelfIntersection) {\n\t\tif (\n\t\t\trelationship !== 'start-contains-end' &&\n\t\t\tstartShapeInfo &&\n\t\t\tarrowheadStart !== 'none' &&\n\t\t\t!startShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetA =\n\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t? STROKE_SIZES[startShapeInfo.shape.props.size] / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffsetA) * shape.props.scale\n\t\t\tminLength += strokeOffsetA * shape.props.scale\n\t\t}\n\n\t\t// If the arrow is bound non-exact to an end shape and the\n\t\t// end point has an arrowhead offset the end point\n\t\tif (\n\t\t\trelationship !== 'end-contains-start' &&\n\t\t\tendShapeInfo &&\n\t\t\tarrowheadEnd !== 'none' &&\n\t\t\t!endShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetB =\n\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t('size' in endShapeInfo.shape.props ? STROKE_SIZES[endShapeInfo.shape.props.size] / 2 : 0)\n\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffsetB) * shape.props.scale\n\t\t\tminLength += strokeOffsetB * shape.props.scale\n\t\t}\n\t}\n\n\t// Adjust offsets if the length of the arrow is too small\n\n\tconst tA = a.clone().add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tconst tB = b.clone().sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\t// both bound + offset\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\t// start bound + offset\n\t\t\toffsetA *= -1\n\t\t} else if (offsetB !== 0) {\n\t\t\t// end bound + offset\n\t\t\toffsetB *= -1\n\t\t} else {\n\t\t\t// noop, its just a really short arrow\n\t\t}\n\t}\n\n\ta.add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tb.sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\t// If the handles flipped their order, then set the center handle\n\t// to the midpoint of the terminals (rather than the midpoint of the\n\t// arrow body); otherwise, it may not be \"between\" the other terminals.\n\tif (didFlip) {\n\t\tif (startShapeInfo && endShapeInfo) {\n\t\t\t// If we have two bound shapes...then make the arrow a short arrow from\n\t\t\t// the start point towards where the end point should be.\n\t\t\tb.setTo(Vec.Add(a, u.clone().mul(-MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t}\n\t\tc.setTo(Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end))\n\t} else {\n\t\tc.setTo(Vec.Med(a, b))\n\t}\n\n\tconst length = Vec.Dist(a, b)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'straight',\n\t\tstart: {\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tpoint: a,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tpoint: b,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\tisValid: length > 0,\n\t\tlength,\n\t}\n}\n\n/** Get an intersection point from A -> B with bound shape (target) from shape (arrow). */\nfunction updateArrowheadPointWithBoundShape(\n\tpoint: Vec,\n\topposite: Vec,\n\tarrowPageTransform: MatModel,\n\ttargetShapeInfo?: BoundShapeInfo\n) {\n\tif (targetShapeInfo === undefined) {\n\t\t// No bound shape? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\tif (targetShapeInfo.isExact) {\n\t\t// Exact type binding? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\t// From and To in page space\n\tconst pageFrom = Mat.applyToPoint(arrowPageTransform, opposite)\n\tconst pageTo = Mat.applyToPoint(arrowPageTransform, point)\n\n\t// From and To in local space of the target shape\n\tconst targetFrom = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageFrom)\n\tconst targetTo = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageTo)\n\n\tconst intersection = Array.from(\n\t\ttargetShapeInfo.geometry.intersectLineSegment(targetFrom, targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t)\n\n\tlet targetInt: VecLike | undefined\n\n\tif (intersection.length) {\n\t\ttargetInt =\n\t\t\tintersection.sort((p1, p2) => Vec.Dist2(p1, targetFrom) - Vec.Dist2(p2, targetFrom))[0] ??\n\t\t\t(targetShapeInfo.isClosed ? undefined : targetTo)\n\t}\n\n\tif (targetInt === undefined) {\n\t\t// No intersection? The arrowhead point will be at the arrow terminal.\n\t\t// if we _almost_ hit the target, just put the arrowhead at the target.\n\t\ttargetInt = targetShapeInfo.geometry.nearestPoint(targetTo)\n\t\tif (!Vec.DistMin(targetInt, targetTo, 1)) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst pageInt = Mat.applyToPoint(targetShapeInfo.transform, targetInt)\n\tconst arrowInt = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pageInt)\n\n\tpoint.setTo(arrowInt)\n\n\ttargetShapeInfo.didIntersect = true\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Editor, Mat, MatModel, TLArrowShape, Vec, VecLike } from '@tldraw/editor'\nimport { TLArrowInfo } from './arrow-types'\nimport {\n\tBOUND_ARROW_OFFSET,\n\tBoundShapeInfo,\n\tMIN_ARROW_LENGTH,\n\tSTROKE_SIZES,\n\tTLArrowBindings,\n\tgetArrowTerminalsInArrowSpace,\n\tgetBoundShapeInfoForTerminal,\n\tgetBoundShapeRelationships,\n} from './shared'\n\nexport function getStraightArrowInfo(\n\teditor: Editor,\n\tshape: TLArrowShape,\n\tbindings: TLArrowBindings\n): TLArrowInfo {\n\tconst { arrowheadStart, arrowheadEnd } = shape.props\n\n\tconst terminalsInArrowSpace = getArrowTerminalsInArrowSpace(editor, shape, bindings)\n\n\tconst a = terminalsInArrowSpace.start.clone()\n\tconst b = terminalsInArrowSpace.end.clone()\n\tconst c = Vec.Med(a, b)\n\n\tif (Vec.Equals(a, b)) {\n\t\treturn {\n\t\t\tbindings,\n\t\t\ttype: 'straight',\n\t\t\tstart: {\n\t\t\t\thandle: a,\n\t\t\t\tpoint: a,\n\t\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t\t},\n\t\t\tend: {\n\t\t\t\thandle: b,\n\t\t\t\tpoint: b,\n\t\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t\t},\n\t\t\tmiddle: c,\n\t\t\tisValid: false,\n\t\t\tlength: 0,\n\t\t}\n\t}\n\n\tconst uAB = Vec.Sub(b, a).uni()\n\n\t// Update the arrowhead points using intersections with the bound shapes, if any.\n\n\tconst startShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'start')\n\tconst endShapeInfo = getBoundShapeInfoForTerminal(editor, shape, 'end')\n\n\tconst arrowPageTransform = editor.getShapePageTransform(shape)!\n\n\t// Update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\tb, // <-- will be mutated\n\t\tterminalsInArrowSpace.start,\n\t\tarrowPageTransform,\n\t\tendShapeInfo\n\t)\n\n\t// Then update the position of the arrowhead's end point\n\tupdateArrowheadPointWithBoundShape(\n\t\ta, // <-- will be mutated\n\t\tterminalsInArrowSpace.end,\n\t\tarrowPageTransform,\n\t\tstartShapeInfo\n\t)\n\n\tlet offsetA = 0\n\tlet offsetB = 0\n\tlet strokeOffsetA = 0\n\tlet strokeOffsetB = 0\n\tlet minLength = MIN_ARROW_LENGTH * shape.props.scale\n\n\tconst isSelfIntersection =\n\t\tstartShapeInfo && endShapeInfo && startShapeInfo.shape === endShapeInfo.shape\n\n\tconst relationship =\n\t\tstartShapeInfo && endShapeInfo\n\t\t\t? getBoundShapeRelationships(editor, startShapeInfo.shape.id, endShapeInfo.shape.id)\n\t\t\t: 'safe'\n\n\tif (\n\t\trelationship === 'safe' &&\n\t\tstartShapeInfo &&\n\t\tendShapeInfo &&\n\t\t!isSelfIntersection &&\n\t\t!startShapeInfo.isExact &&\n\t\t!endShapeInfo.isExact\n\t) {\n\t\tif (endShapeInfo.didIntersect && !startShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, then make it\n\t\t\t// a short arrow ending at the end shape intersection.\n\t\t\tif (startShapeInfo.isClosed) {\n\t\t\t\ta.setTo(b.clone().add(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t} else if (!endShapeInfo.didIntersect) {\n\t\t\t// ...and if only the end shape intersected, or if neither\n\t\t\t// shape intersected, then make it a short arrow starting\n\t\t\t// at the start shape intersection.\n\t\t\tif (endShapeInfo.isClosed) {\n\t\t\t\tb.setTo(a.clone().sub(uAB.clone().mul(MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t\t}\n\t\t}\n\t}\n\n\tconst distance = Vec.Sub(b, a)\n\t// Check for divide-by-zero before we call uni()\n\tconst u = Vec.Len(distance) ? distance.uni() : Vec.From(distance)\n\tconst didFlip = !Vec.Equals(u, uAB)\n\n\t// If the arrow is bound non-exact to a start shape and the\n\t// start point has an arrowhead, then offset the start point\n\tif (!isSelfIntersection) {\n\t\tif (\n\t\t\trelationship !== 'start-contains-end' &&\n\t\t\tstartShapeInfo &&\n\t\t\tarrowheadStart !== 'none' &&\n\t\t\t!startShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetA =\n\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t('size' in startShapeInfo.shape.props\n\t\t\t\t\t? STROKE_SIZES[startShapeInfo.shape.props.size] / 2\n\t\t\t\t\t: 0)\n\t\t\toffsetA = (BOUND_ARROW_OFFSET + strokeOffsetA) * shape.props.scale\n\t\t\tminLength += strokeOffsetA * shape.props.scale\n\t\t}\n\n\t\t// If the arrow is bound non-exact to an end shape and the\n\t\t// end point has an arrowhead offset the end point\n\t\tif (\n\t\t\trelationship !== 'end-contains-start' &&\n\t\t\tendShapeInfo &&\n\t\t\tarrowheadEnd !== 'none' &&\n\t\t\t!endShapeInfo.isExact\n\t\t) {\n\t\t\tstrokeOffsetB =\n\t\t\t\tSTROKE_SIZES[shape.props.size] / 2 +\n\t\t\t\t('size' in endShapeInfo.shape.props ? STROKE_SIZES[endShapeInfo.shape.props.size] / 2 : 0)\n\t\t\toffsetB = (BOUND_ARROW_OFFSET + strokeOffsetB) * shape.props.scale\n\t\t\tminLength += strokeOffsetB * shape.props.scale\n\t\t}\n\t}\n\n\t// Adjust offsets if the length of the arrow is too small\n\n\tconst tA = a.clone().add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tconst tB = b.clone().sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\tif (Vec.DistMin(tA, tB, minLength)) {\n\t\tif (offsetA !== 0 && offsetB !== 0) {\n\t\t\t// both bound + offset\n\t\t\toffsetA *= -1.5\n\t\t\toffsetB *= -1.5\n\t\t} else if (offsetA !== 0) {\n\t\t\t// start bound + offset\n\t\t\toffsetA *= -1\n\t\t} else if (offsetB !== 0) {\n\t\t\t// end bound + offset\n\t\t\toffsetB *= -1\n\t\t} else {\n\t\t\t// noop, its just a really short arrow\n\t\t}\n\t}\n\n\ta.add(u.clone().mul(offsetA * (didFlip ? -1 : 1)))\n\tb.sub(u.clone().mul(offsetB * (didFlip ? -1 : 1)))\n\n\t// If the handles flipped their order, then set the center handle\n\t// to the midpoint of the terminals (rather than the midpoint of the\n\t// arrow body); otherwise, it may not be \"between\" the other terminals.\n\tif (didFlip) {\n\t\tif (startShapeInfo && endShapeInfo) {\n\t\t\t// If we have two bound shapes...then make the arrow a short arrow from\n\t\t\t// the start point towards where the end point should be.\n\t\t\tb.setTo(Vec.Add(a, u.clone().mul(-MIN_ARROW_LENGTH * shape.props.scale)))\n\t\t}\n\t\tc.setTo(Vec.Med(terminalsInArrowSpace.start, terminalsInArrowSpace.end))\n\t} else {\n\t\tc.setTo(Vec.Med(a, b))\n\t}\n\n\tconst length = Vec.Dist(a, b)\n\n\treturn {\n\t\tbindings,\n\t\ttype: 'straight',\n\t\tstart: {\n\t\t\thandle: terminalsInArrowSpace.start,\n\t\t\tpoint: a,\n\t\t\tarrowhead: shape.props.arrowheadStart,\n\t\t},\n\t\tend: {\n\t\t\thandle: terminalsInArrowSpace.end,\n\t\t\tpoint: b,\n\t\t\tarrowhead: shape.props.arrowheadEnd,\n\t\t},\n\t\tmiddle: c,\n\t\tisValid: length > 0,\n\t\tlength,\n\t}\n}\n\n/** Get an intersection point from A -> B with bound shape (target) from shape (arrow). */\nfunction updateArrowheadPointWithBoundShape(\n\tpoint: Vec,\n\topposite: Vec,\n\tarrowPageTransform: MatModel,\n\ttargetShapeInfo?: BoundShapeInfo\n) {\n\tif (targetShapeInfo === undefined) {\n\t\t// No bound shape? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\tif (targetShapeInfo.isExact) {\n\t\t// Exact type binding? The arrowhead point will be at the arrow terminal.\n\t\treturn\n\t}\n\n\t// From and To in page space\n\tconst pageFrom = Mat.applyToPoint(arrowPageTransform, opposite)\n\tconst pageTo = Mat.applyToPoint(arrowPageTransform, point)\n\n\t// From and To in local space of the target shape\n\tconst targetFrom = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageFrom)\n\tconst targetTo = Mat.applyToPoint(Mat.Inverse(targetShapeInfo.transform), pageTo)\n\n\tconst intersection = Array.from(\n\t\ttargetShapeInfo.geometry.intersectLineSegment(targetFrom, targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\t)\n\n\tlet targetInt: VecLike | undefined\n\n\tif (intersection.length) {\n\t\ttargetInt =\n\t\t\tintersection.sort((p1, p2) => Vec.Dist2(p1, targetFrom) - Vec.Dist2(p2, targetFrom))[0] ??\n\t\t\t(targetShapeInfo.isClosed ? undefined : targetTo)\n\t}\n\n\tif (targetInt === undefined) {\n\t\t// No intersection? The arrowhead point will be at the arrow terminal.\n\t\t// if we _almost_ hit the target, just put the arrowhead at the target.\n\t\ttargetInt = targetShapeInfo.geometry.nearestPoint(targetTo, {\n\t\t\tincludeLabels: false,\n\t\t\tincludeInternal: false,\n\t\t})\n\n\t\tif (!Vec.DistMin(targetInt, targetTo, 1)) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tconst pageInt = Mat.applyToPoint(targetShapeInfo.transform, targetInt)\n\tconst arrowInt = Mat.applyToPoint(Mat.Inverse(arrowPageTransform), pageInt)\n\n\tpoint.setTo(arrowInt)\n\n\ttargetShapeInfo.didIntersect = true\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,13 +1,10 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import {
3
- AssetRecordType,
4
3
  BaseBoxShapeUtil,
5
4
  HTMLContainer,
6
5
  T,
7
6
  bookmarkShapeMigrations,
8
7
  bookmarkShapeProps,
9
- debounce,
10
- getHashForString,
11
8
  lerp,
12
9
  tlenv,
13
10
  toDomPrecision,
@@ -20,10 +17,13 @@ import { convertCommonTitleHTMLEntities } from "../../utils/text/text.mjs";
20
17
  import { HyperlinkButton } from "../shared/HyperlinkButton.mjs";
21
18
  import { LINK_ICON } from "../shared/icons-editor.mjs";
22
19
  import { getRotatedBoxShadow } from "../shared/rotated-box-shadow.mjs";
23
- const BOOKMARK_WIDTH = 300;
24
- const BOOKMARK_HEIGHT = 320;
25
- const BOOKMARK_JUST_URL_HEIGHT = 46;
26
- const SHORT_BOOKMARK_HEIGHT = 101;
20
+ import {
21
+ BOOKMARK_HEIGHT,
22
+ BOOKMARK_WIDTH,
23
+ getHumanReadableAddress,
24
+ setBookmarkHeight,
25
+ updateBookmarkAssetOnUrlChange
26
+ } from "./bookmarks.mjs";
27
27
  class BookmarkShapeUtil extends BaseBoxShapeUtil {
28
28
  static type = "bookmark";
29
29
  static props = bookmarkShapeProps;
@@ -51,21 +51,15 @@ class BookmarkShapeUtil extends BaseBoxShapeUtil {
51
51
  };
52
52
  }
53
53
  component(shape) {
54
- return /* @__PURE__ */ jsx(BookmarkShapeComponent, { shape });
54
+ const { assetId, url, h } = shape.props;
55
+ const rotation = this.editor.getShapePageTransform(shape).rotation();
56
+ return /* @__PURE__ */ jsx(BookmarkShapeComponent, { assetId, url, h, rotation });
55
57
  }
56
58
  indicator(shape) {
57
- return /* @__PURE__ */ jsx(
58
- "rect",
59
- {
60
- width: toDomPrecision(shape.props.w),
61
- height: toDomPrecision(shape.props.h),
62
- rx: "6",
63
- ry: "6"
64
- }
65
- );
59
+ return /* @__PURE__ */ jsx(BookmarkIndicatorComponent, { w: shape.props.w, h: shape.props.h });
66
60
  }
67
61
  onBeforeCreate(next) {
68
- return getBookmarkSize(this.editor, next);
62
+ return setBookmarkHeight(this.editor, next);
69
63
  }
70
64
  onBeforeUpdate(prev, shape) {
71
65
  if (prev.props.url !== shape.props.url) {
@@ -76,7 +70,7 @@ class BookmarkShapeUtil extends BaseBoxShapeUtil {
76
70
  }
77
71
  }
78
72
  if (prev.props.assetId !== shape.props.assetId) {
79
- return getBookmarkSize(this.editor, shape);
73
+ return setBookmarkHeight(this.editor, shape);
80
74
  }
81
75
  }
82
76
  getInterpolatedProps(startShape, endShape, t) {
@@ -87,12 +81,20 @@ class BookmarkShapeUtil extends BaseBoxShapeUtil {
87
81
  };
88
82
  }
89
83
  }
90
- function BookmarkShapeComponent({ shape }) {
84
+ function BookmarkIndicatorComponent({ w, h }) {
85
+ return /* @__PURE__ */ jsx("rect", { width: toDomPrecision(w), height: toDomPrecision(h), rx: "6", ry: "6" });
86
+ }
87
+ function BookmarkShapeComponent({
88
+ assetId,
89
+ rotation,
90
+ url,
91
+ h,
92
+ showImageContainer = true
93
+ }) {
91
94
  const editor = useEditor();
92
- const asset = shape.props.assetId ? editor.getAsset(shape.props.assetId) : null;
95
+ const asset = assetId ? editor.getAsset(assetId) : null;
93
96
  const isSafariExport = !!useSvgExportContext() && tlenv.isSafari;
94
- const pageRotation = editor.getShapePageTransform(shape).rotation();
95
- const address = getHumanReadableAddress(shape);
97
+ const address = getHumanReadableAddress(url);
96
98
  const [isFaviconValid, setIsFaviconValid] = useState(true);
97
99
  const onFaviconError = () => setIsFaviconValid(false);
98
100
  const markAsHandledOnShiftKey = useCallback(
@@ -109,11 +111,11 @@ function BookmarkShapeComponent({ shape }) {
109
111
  isSafariExport && "tl-bookmark__container--safariExport"
110
112
  ),
111
113
  style: {
112
- boxShadow: isSafariExport ? void 0 : getRotatedBoxShadow(pageRotation),
113
- maxHeight: shape.props.h
114
+ boxShadow: isSafariExport ? void 0 : getRotatedBoxShadow(rotation),
115
+ maxHeight: h
114
116
  },
115
117
  children: [
116
- (!asset || asset.props.image) && /* @__PURE__ */ jsxs("div", { className: "tl-bookmark__image_container", children: [
118
+ showImageContainer && (!asset || asset.props.image) && /* @__PURE__ */ jsxs("div", { className: "tl-bookmark__image_container", children: [
117
119
  asset ? /* @__PURE__ */ jsx(
118
120
  "img",
119
121
  {
@@ -124,16 +126,28 @@ function BookmarkShapeComponent({ shape }) {
124
126
  alt: asset?.props.title || ""
125
127
  }
126
128
  ) : /* @__PURE__ */ jsx("div", { className: "tl-bookmark__placeholder" }),
127
- asset?.props.image && /* @__PURE__ */ jsx(HyperlinkButton, { url: shape.props.url })
129
+ asset?.props.image && /* @__PURE__ */ jsx(HyperlinkButton, { url })
128
130
  ] }),
129
131
  /* @__PURE__ */ jsxs("div", { className: "tl-bookmark__copy_container", children: [
130
- asset?.props.title ? /* @__PURE__ */ jsx("h2", { className: "tl-bookmark__heading", children: convertCommonTitleHTMLEntities(asset.props.title) }) : null,
132
+ asset?.props.title ? /* @__PURE__ */ jsx(
133
+ "a",
134
+ {
135
+ className: "tl-bookmark__link",
136
+ href: url || "",
137
+ target: "_blank",
138
+ rel: "noopener noreferrer",
139
+ draggable: false,
140
+ onPointerDown: markAsHandledOnShiftKey,
141
+ onPointerUp: markAsHandledOnShiftKey,
142
+ children: /* @__PURE__ */ jsx("h2", { className: "tl-bookmark__heading", children: convertCommonTitleHTMLEntities(asset.props.title) })
143
+ }
144
+ ) : null,
131
145
  asset?.props.description && asset?.props.image ? /* @__PURE__ */ jsx("p", { className: "tl-bookmark__description", children: asset.props.description }) : null,
132
146
  /* @__PURE__ */ jsxs(
133
147
  "a",
134
148
  {
135
149
  className: "tl-bookmark__link",
136
- href: shape.props.url || "",
150
+ href: url || "",
137
151
  target: "_blank",
138
152
  rel: "noopener noreferrer",
139
153
  draggable: false,
@@ -168,78 +182,9 @@ function BookmarkShapeComponent({ shape }) {
168
182
  }
169
183
  ) });
170
184
  }
171
- function getBookmarkSize(editor, shape) {
172
- const asset = shape.props.assetId ? editor.getAsset(shape.props.assetId) : null;
173
- let h = BOOKMARK_HEIGHT;
174
- if (asset) {
175
- if (!asset.props.image) {
176
- if (!asset.props.title) {
177
- h = BOOKMARK_JUST_URL_HEIGHT;
178
- } else {
179
- h = SHORT_BOOKMARK_HEIGHT;
180
- }
181
- }
182
- }
183
- return {
184
- ...shape,
185
- props: {
186
- ...shape.props,
187
- h
188
- }
189
- };
190
- }
191
- const getHumanReadableAddress = (shape) => {
192
- try {
193
- const url = new URL(shape.props.url);
194
- return url.hostname.replace(/^www\./, "");
195
- } catch {
196
- return shape.props.url;
197
- }
198
- };
199
- function updateBookmarkAssetOnUrlChange(editor, shape) {
200
- const { url } = shape.props;
201
- const assetId = AssetRecordType.createId(getHashForString(url));
202
- if (editor.getAsset(assetId)) {
203
- if (shape.props.assetId !== assetId) {
204
- editor.updateShapes([
205
- {
206
- id: shape.id,
207
- type: shape.type,
208
- props: { assetId }
209
- }
210
- ]);
211
- }
212
- } else {
213
- editor.updateShapes([
214
- {
215
- id: shape.id,
216
- type: shape.type,
217
- props: { assetId: null }
218
- }
219
- ]);
220
- createBookmarkAssetOnUrlChange(editor, shape);
221
- }
222
- }
223
- const createBookmarkAssetOnUrlChange = debounce(async (editor, shape) => {
224
- if (editor.isDisposed) return;
225
- const { url } = shape.props;
226
- const asset = await editor.getAssetForExternalContent({ type: "url", url });
227
- if (!asset) {
228
- return;
229
- }
230
- editor.run(() => {
231
- editor.createAssets([asset]);
232
- editor.updateShapes([
233
- {
234
- id: shape.id,
235
- type: shape.type,
236
- props: { assetId: asset.id }
237
- }
238
- ]);
239
- });
240
- }, 500);
241
185
  export {
242
- BookmarkShapeUtil,
243
- getHumanReadableAddress
186
+ BookmarkIndicatorComponent,
187
+ BookmarkShapeComponent,
188
+ BookmarkShapeUtil
244
189
  };
245
190
  //# sourceMappingURL=BookmarkShapeUtil.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/bookmark/BookmarkShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tAssetRecordType,\n\tBaseBoxShapeUtil,\n\tEditor,\n\tHTMLContainer,\n\tT,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLBookmarkShapeProps,\n\tbookmarkShapeMigrations,\n\tbookmarkShapeProps,\n\tdebounce,\n\tgetHashForString,\n\tlerp,\n\ttlenv,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback, useState } from 'react'\nimport { convertCommonTitleHTMLEntities } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { LINK_ICON } from '../shared/icons-editor'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\nconst BOOKMARK_WIDTH = 300\nconst BOOKMARK_HEIGHT = 320\nconst BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\n/** @public */\nexport class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {\n\tstatic override type = 'bookmark' as const\n\tstatic override props = bookmarkShapeProps\n\tstatic override migrations = bookmarkShapeMigrations\n\n\toverride canResize() {\n\t\treturn false\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride getText(shape: TLBookmarkShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLBookmarkShape) {\n\t\tconst asset = (\n\t\t\tshape.props.assetId ? this.editor.getAsset(shape.props.assetId) : null\n\t\t) as TLBookmarkAsset | null\n\n\t\tif (!asset?.props.title) return undefined\n\n\t\treturn (\n\t\t\tconvertCommonTitleHTMLEntities(asset.props.title) +\n\t\t\t(asset.props.description ? ', ' + asset.props.description : '')\n\t\t)\n\t}\n\n\toverride getDefaultProps(): TLBookmarkShape['props'] {\n\t\treturn {\n\t\t\turl: '',\n\t\t\tw: BOOKMARK_WIDTH,\n\t\t\th: BOOKMARK_HEIGHT,\n\t\t\tassetId: null,\n\t\t}\n\t}\n\n\toverride component(shape: TLBookmarkShape) {\n\t\treturn <BookmarkShapeComponent shape={shape} />\n\t}\n\n\toverride indicator(shape: TLBookmarkShape) {\n\t\treturn (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\trx=\"6\"\n\t\t\t\try=\"6\"\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLBookmarkShape) {\n\t\treturn getBookmarkSize(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLBookmarkShape, shape: TLBookmarkShape) {\n\t\tif (prev.props.url !== shape.props.url) {\n\t\t\tif (!T.linkUrl.isValid(shape.props.url)) {\n\t\t\t\treturn { ...shape, props: { ...shape.props, url: prev.props.url } }\n\t\t\t} else {\n\t\t\t\tupdateBookmarkAssetOnUrlChange(this.editor, shape)\n\t\t\t}\n\t\t}\n\n\t\tif (prev.props.assetId !== shape.props.assetId) {\n\t\t\treturn getBookmarkSize(this.editor, shape)\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLBookmarkShape,\n\t\tendShape: TLBookmarkShape,\n\t\tt: number\n\t): TLBookmarkShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction BookmarkShapeComponent({ shape }: { shape: TLBookmarkShape }) {\n\tconst editor = useEditor()\n\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tconst isSafariExport = !!useSvgExportContext() && tlenv.isSafari\n\n\tconst pageRotation = editor.getShapePageTransform(shape)!.rotation()\n\n\tconst address = getHumanReadableAddress(shape)\n\n\tconst [isFaviconValid, setIsFaviconValid] = useState(true)\n\tconst onFaviconError = () => setIsFaviconValid(false)\n\n\tconst markAsHandledOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) editor.markEventAsHandled(e)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<HTMLContainer>\n\t\t\t<div\n\t\t\t\tclassName={classNames(\n\t\t\t\t\t'tl-bookmark__container',\n\t\t\t\t\tisSafariExport && 'tl-bookmark__container--safariExport'\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\tboxShadow: isSafariExport ? undefined : getRotatedBoxShadow(pageRotation),\n\t\t\t\t\tmaxHeight: shape.props.h,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{(!asset || asset.props.image) && (\n\t\t\t\t\t<div className=\"tl-bookmark__image_container\">\n\t\t\t\t\t\t{asset ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__image\"\n\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.image}\n\t\t\t\t\t\t\t\talt={asset?.props.title || ''}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"tl-bookmark__placeholder\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{asset?.props.image && <HyperlinkButton url={shape.props.url} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"tl-bookmark__copy_container\">\n\t\t\t\t\t{asset?.props.title ? (\n\t\t\t\t\t\t<h2 className=\"tl-bookmark__heading\">\n\t\t\t\t\t\t\t{convertCommonTitleHTMLEntities(asset.props.title)}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{asset?.props.description && asset?.props.image ? (\n\t\t\t\t\t\t<p className=\"tl-bookmark__description\">{asset.props.description}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"tl-bookmark__link\"\n\t\t\t\t\t\thref={shape.props.url || ''}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\tonPointerDown={markAsHandledOnShiftKey}\n\t\t\t\t\t\tonPointerUp={markAsHandledOnShiftKey}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isFaviconValid && asset?.props.favicon ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__favicon\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.favicon}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tonError={onFaviconError}\n\t\t\t\t\t\t\t\talt={`favicon of ${address}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span>{address}</span>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</HTMLContainer>\n\t)\n}\n\nfunction getBookmarkSize(editor: Editor, shape: TLBookmarkShape) {\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tlet h = BOOKMARK_HEIGHT\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\th = BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\th = SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t...shape,\n\t\tprops: {\n\t\t\t...shape.props,\n\t\t\th,\n\t\t},\n\t}\n}\n\n/** @internal */\nexport const getHumanReadableAddress = (shape: TLBookmarkShape) => {\n\ttry {\n\t\tconst url = new URL(shape.props.url)\n\t\t// we want the hostname without any www\n\t\treturn url.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn shape.props.url\n\t}\n}\n\nfunction 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"],
5
- "mappings": "AAyES,cAgFJ,YAhFI;AAzET;AAAA,EACC;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAKA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,OAAO,gBAAgB;AACvB,SAA8B,aAAa,gBAAgB;AAC3D,SAAS,sCAAsC;AAC/C,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AAEpC,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AACxB,MAAM,2BAA2B;AACjC,MAAM,wBAAwB;AAGvB,MAAM,0BAA0B,iBAAkC;AAAA,EACxE,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,YAAY;AACpB,WAAO;AAAA,EACR;AAAA,EAES,wBAAwB;AAChC,WAAO;AAAA,EACR;AAAA,EAES,QAAQ,OAAwB;AACxC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA,EAES,kBAAkB,OAAwB;AAClD,UAAM,QACL,MAAM,MAAM,UAAU,KAAK,OAAO,SAAS,MAAM,MAAM,OAAO,IAAI;AAGnE,QAAI,CAAC,OAAO,MAAM,MAAO,QAAO;AAEhC,WACC,+BAA+B,MAAM,MAAM,KAAK,KAC/C,MAAM,MAAM,cAAc,OAAO,MAAM,MAAM,cAAc;AAAA,EAE9D;AAAA,EAES,kBAA4C;AACpD,WAAO;AAAA,MACN,KAAK;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,SAAS;AAAA,IACV;AAAA,EACD;AAAA,EAES,UAAU,OAAwB;AAC1C,WAAO,oBAAC,0BAAuB,OAAc;AAAA,EAC9C;AAAA,EAES,UAAU,OAAwB;AAC1C,WACC;AAAA,MAAC;AAAA;AAAA,QACA,OAAO,eAAe,MAAM,MAAM,CAAC;AAAA,QACnC,QAAQ,eAAe,MAAM,MAAM,CAAC;AAAA,QACpC,IAAG;AAAA,QACH,IAAG;AAAA;AAAA,IACJ;AAAA,EAEF;AAAA,EAES,eAAe,MAAuB;AAC9C,WAAO,gBAAgB,KAAK,QAAQ,IAAI;AAAA,EACzC;AAAA,EAES,eAAe,MAAuB,OAAwB;AACtE,QAAI,KAAK,MAAM,QAAQ,MAAM,MAAM,KAAK;AACvC,UAAI,CAAC,EAAE,QAAQ,QAAQ,MAAM,MAAM,GAAG,GAAG;AACxC,eAAO,EAAE,GAAG,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,KAAK,KAAK,MAAM,IAAI,EAAE;AAAA,MACnE,OAAO;AACN,uCAA+B,KAAK,QAAQ,KAAK;AAAA,MAClD;AAAA,IACD;AAEA,QAAI,KAAK,MAAM,YAAY,MAAM,MAAM,SAAS;AAC/C,aAAO,gBAAgB,KAAK,QAAQ,KAAK;AAAA,IAC1C;AAAA,EACD;AAAA,EACS,qBACR,YACA,UACA,GACuB;AACvB,WAAO;AAAA,MACN,GAAI,IAAI,MAAM,SAAS,QAAQ,WAAW;AAAA,MAC1C,GAAG,KAAK,WAAW,MAAM,GAAG,SAAS,MAAM,GAAG,CAAC;AAAA,MAC/C,GAAG,KAAK,WAAW,MAAM,GAAG,SAAS,MAAM,GAAG,CAAC;AAAA,IAChD;AAAA,EACD;AACD;AAEA,SAAS,uBAAuB,EAAE,MAAM,GAA+B;AACtE,QAAM,SAAS,UAAU;AAEzB,QAAM,QACL,MAAM,MAAM,UAAU,OAAO,SAAS,MAAM,MAAM,OAAO,IAAI;AAG9D,QAAM,iBAAiB,CAAC,CAAC,oBAAoB,KAAK,MAAM;AAExD,QAAM,eAAe,OAAO,sBAAsB,KAAK,EAAG,SAAS;AAEnE,QAAM,UAAU,wBAAwB,KAAK;AAE7C,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,iBAAiB,MAAM,kBAAkB,KAAK;AAEpD,QAAM,0BAA0B;AAAA,IAC/B,CAAC,MAAM;AACN,UAAI,CAAC,OAAO,OAAO,SAAU,QAAO,mBAAmB,CAAC;AAAA,IACzD;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AAEA,SACC,oBAAC,iBACA;AAAA,IAAC;AAAA;AAAA,MACA,WAAW;AAAA,QACV;AAAA,QACA,kBAAkB;AAAA,MACnB;AAAA,MACA,OAAO;AAAA,QACN,WAAW,iBAAiB,SAAY,oBAAoB,YAAY;AAAA,QACxE,WAAW,MAAM,MAAM;AAAA,MACxB;AAAA,MAEE;AAAA,UAAC,SAAS,MAAM,MAAM,UACvB,qBAAC,SAAI,WAAU,gCACb;AAAA,kBACA;AAAA,YAAC;AAAA;AAAA,cACA,WAAU;AAAA,cACV,WAAW;AAAA,cACX,gBAAe;AAAA,cACf,KAAK,OAAO,MAAM;AAAA,cAClB,KAAK,OAAO,MAAM,SAAS;AAAA;AAAA,UAC5B,IAEA,oBAAC,SAAI,WAAU,4BAA2B;AAAA,UAE1C,OAAO,MAAM,SAAS,oBAAC,mBAAgB,KAAK,MAAM,MAAM,KAAK;AAAA,WAC/D;AAAA,QAED,qBAAC,SAAI,WAAU,+BACb;AAAA,iBAAO,MAAM,QACb,oBAAC,QAAG,WAAU,wBACZ,yCAA+B,MAAM,MAAM,KAAK,GAClD,IACG;AAAA,UACH,OAAO,MAAM,eAAe,OAAO,MAAM,QACzC,oBAAC,OAAE,WAAU,4BAA4B,gBAAM,MAAM,aAAY,IAC9D;AAAA,UACJ;AAAA,YAAC;AAAA;AAAA,cACA,WAAU;AAAA,cACV,MAAM,MAAM,MAAM,OAAO;AAAA,cACzB,QAAO;AAAA,cACP,KAAI;AAAA,cACJ,WAAW;AAAA,cACX,eAAe;AAAA,cACf,aAAa;AAAA,cAEZ;AAAA,kCAAkB,OAAO,MAAM,UAC/B;AAAA,kBAAC;AAAA;AAAA,oBACA,WAAU;AAAA,oBACV,KAAK,OAAO,MAAM;AAAA,oBAClB,gBAAe;AAAA,oBACf,SAAS;AAAA,oBACT,KAAK,cAAc,OAAO;AAAA;AAAA,gBAC3B,IAEA;AAAA,kBAAC;AAAA;AAAA,oBACA,WAAU;AAAA,oBACV,OAAO;AAAA,sBACN,MAAM,QAAQ,SAAS;AAAA,sBACvB,YAAY,QAAQ,SAAS;AAAA,oBAC9B;AAAA;AAAA,gBACD;AAAA,gBAED,oBAAC,UAAM,mBAAQ;AAAA;AAAA;AAAA,UAChB;AAAA,WACD;AAAA;AAAA;AAAA,EACD,GACD;AAEF;AAEA,SAAS,gBAAgB,QAAgB,OAAwB;AAChE,QAAM,QACL,MAAM,MAAM,UAAU,OAAO,SAAS,MAAM,MAAM,OAAO,IAAI;AAG9D,MAAI,IAAI;AAER,MAAI,OAAO;AACV,QAAI,CAAC,MAAM,MAAM,OAAO;AACvB,UAAI,CAAC,MAAM,MAAM,OAAO;AACvB,YAAI;AAAA,MACL,OAAO;AACN,YAAI;AAAA,MACL;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,GAAG;AAAA,IACH,OAAO;AAAA,MACN,GAAG,MAAM;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;AAGO,MAAM,0BAA0B,CAAC,UAA2B;AAClE,MAAI;AACH,UAAM,MAAM,IAAI,IAAI,MAAM,MAAM,GAAG;AAEnC,WAAO,IAAI,SAAS,QAAQ,UAAU,EAAE;AAAA,EACzC,QAAQ;AACP,WAAO,MAAM,MAAM;AAAA,EACpB;AACD;AAEA,SAAS,+BAA+B,QAAgB,OAAwB;AAC/E,QAAM,EAAE,IAAI,IAAI,MAAM;AAGtB,QAAM,UAAqB,gBAAgB,SAAS,iBAAiB,GAAG,CAAC;AAEzE,MAAI,OAAO,SAAS,OAAO,GAAG;AAE7B,QAAI,MAAM,MAAM,YAAY,SAAS;AACpC,aAAO,aAA8B;AAAA,QACpC;AAAA,UACC,IAAI,MAAM;AAAA,UACV,MAAM,MAAM;AAAA,UACZ,OAAO,EAAE,QAAQ;AAAA,QAClB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD,OAAO;AAIN,WAAO,aAA8B;AAAA,MACpC;AAAA,QACC,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,OAAO,EAAE,SAAS,KAAK;AAAA,MACxB;AAAA,IACD,CAAC;AAGD,mCAA+B,QAAQ,KAAK;AAAA,EAC7C;AACD;AAEA,MAAM,iCAAiC,SAAS,OAAO,QAAgB,UAA2B;AACjG,MAAI,OAAO,WAAY;AAEvB,QAAM,EAAE,IAAI,IAAI,MAAM;AAItB,QAAM,QAAQ,MAAM,OAAO,2BAA2B,EAAE,MAAM,OAAO,IAAI,CAAC;AAE1E,MAAI,CAAC,OAAO;AAEX;AAAA,EACD;AAEA,SAAO,IAAI,MAAM;AAEhB,WAAO,aAAa,CAAC,KAAK,CAAC;AAG3B,WAAO,aAA8B;AAAA,MACpC;AAAA,QACC,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,OAAO,EAAE,SAAS,MAAM,GAAG;AAAA,MAC5B;AAAA,IACD,CAAC;AAAA,EACF,CAAC;AACF,GAAG,GAAG;",
4
+ "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tT,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLBookmarkShapeProps,\n\tbookmarkShapeMigrations,\n\tbookmarkShapeProps,\n\tlerp,\n\ttlenv,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback, useState } from 'react'\nimport { convertCommonTitleHTMLEntities } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { LINK_ICON } from '../shared/icons-editor'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\nimport {\n\tBOOKMARK_HEIGHT,\n\tBOOKMARK_WIDTH,\n\tgetHumanReadableAddress,\n\tsetBookmarkHeight,\n\tupdateBookmarkAssetOnUrlChange,\n} from './bookmarks'\n\n/** @public */\nexport class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {\n\tstatic override type = 'bookmark' as const\n\tstatic override props = bookmarkShapeProps\n\tstatic override migrations = bookmarkShapeMigrations\n\n\toverride canResize() {\n\t\treturn false\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride getText(shape: TLBookmarkShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLBookmarkShape) {\n\t\tconst asset = (\n\t\t\tshape.props.assetId ? this.editor.getAsset(shape.props.assetId) : null\n\t\t) as TLBookmarkAsset | null\n\n\t\tif (!asset?.props.title) return undefined\n\n\t\treturn (\n\t\t\tconvertCommonTitleHTMLEntities(asset.props.title) +\n\t\t\t(asset.props.description ? ', ' + asset.props.description : '')\n\t\t)\n\t}\n\n\toverride getDefaultProps(): TLBookmarkShape['props'] {\n\t\treturn {\n\t\t\turl: '',\n\t\t\tw: BOOKMARK_WIDTH,\n\t\t\th: BOOKMARK_HEIGHT,\n\t\t\tassetId: null,\n\t\t}\n\t}\n\n\toverride component(shape: TLBookmarkShape) {\n\t\tconst { assetId, url, h } = shape.props\n\t\tconst rotation = this.editor.getShapePageTransform(shape)!.rotation()\n\n\t\treturn <BookmarkShapeComponent assetId={assetId} url={url} h={h} rotation={rotation} />\n\t}\n\n\toverride indicator(shape: TLBookmarkShape) {\n\t\treturn <BookmarkIndicatorComponent w={shape.props.w} h={shape.props.h} />\n\t}\n\n\toverride onBeforeCreate(next: TLBookmarkShape) {\n\t\treturn setBookmarkHeight(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLBookmarkShape, shape: TLBookmarkShape) {\n\t\tif (prev.props.url !== shape.props.url) {\n\t\t\tif (!T.linkUrl.isValid(shape.props.url)) {\n\t\t\t\treturn { ...shape, props: { ...shape.props, url: prev.props.url } }\n\t\t\t} else {\n\t\t\t\tupdateBookmarkAssetOnUrlChange(this.editor, shape)\n\t\t\t}\n\t\t}\n\n\t\tif (prev.props.assetId !== shape.props.assetId) {\n\t\t\treturn setBookmarkHeight(this.editor, shape)\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLBookmarkShape,\n\t\tendShape: TLBookmarkShape,\n\t\tt: number\n\t): TLBookmarkShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nexport function BookmarkIndicatorComponent({ w, h }: { w: number; h: number }) {\n\treturn <rect width={toDomPrecision(w)} height={toDomPrecision(h)} rx=\"6\" ry=\"6\" />\n}\n\nexport function BookmarkShapeComponent({\n\tassetId,\n\trotation,\n\turl,\n\th,\n\tshowImageContainer = true,\n}: {\n\tassetId: TLAssetId | null\n\trotation: number\n\th: number\n\turl: string\n\tshowImageContainer?: boolean\n}) {\n\tconst editor = useEditor()\n\n\tconst asset = assetId ? (editor.getAsset(assetId) as TLBookmarkAsset) : null\n\n\tconst isSafariExport = !!useSvgExportContext() && tlenv.isSafari\n\n\tconst address = getHumanReadableAddress(url)\n\n\tconst [isFaviconValid, setIsFaviconValid] = useState(true)\n\tconst onFaviconError = () => setIsFaviconValid(false)\n\n\tconst markAsHandledOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) editor.markEventAsHandled(e)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<HTMLContainer>\n\t\t\t<div\n\t\t\t\tclassName={classNames(\n\t\t\t\t\t'tl-bookmark__container',\n\t\t\t\t\tisSafariExport && 'tl-bookmark__container--safariExport'\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\tboxShadow: isSafariExport ? undefined : getRotatedBoxShadow(rotation),\n\t\t\t\t\tmaxHeight: h,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{showImageContainer && (!asset || asset.props.image) && (\n\t\t\t\t\t<div className=\"tl-bookmark__image_container\">\n\t\t\t\t\t\t{asset ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__image\"\n\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.image}\n\t\t\t\t\t\t\t\talt={asset?.props.title || ''}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"tl-bookmark__placeholder\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{asset?.props.image && <HyperlinkButton url={url} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"tl-bookmark__copy_container\">\n\t\t\t\t\t{asset?.props.title ? (\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclassName=\"tl-bookmark__link\"\n\t\t\t\t\t\t\thref={url || ''}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\tonPointerDown={markAsHandledOnShiftKey}\n\t\t\t\t\t\t\tonPointerUp={markAsHandledOnShiftKey}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<h2 className=\"tl-bookmark__heading\">\n\t\t\t\t\t\t\t\t{convertCommonTitleHTMLEntities(asset.props.title)}\n\t\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{asset?.props.description && asset?.props.image ? (\n\t\t\t\t\t\t<p className=\"tl-bookmark__description\">{asset.props.description}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"tl-bookmark__link\"\n\t\t\t\t\t\thref={url || ''}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\tonPointerDown={markAsHandledOnShiftKey}\n\t\t\t\t\t\tonPointerUp={markAsHandledOnShiftKey}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isFaviconValid && asset?.props.favicon ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__favicon\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.favicon}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tonError={onFaviconError}\n\t\t\t\t\t\t\t\talt={`favicon of ${address}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span>{address}</span>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</HTMLContainer>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,124 @@
1
+ import {
2
+ AssetRecordType,
3
+ Result,
4
+ createShapeId,
5
+ debounce,
6
+ getHashForString
7
+ } from "@tldraw/editor";
8
+ const BOOKMARK_WIDTH = 300;
9
+ const BOOKMARK_HEIGHT = 320;
10
+ const BOOKMARK_JUST_URL_HEIGHT = 46;
11
+ const SHORT_BOOKMARK_HEIGHT = 101;
12
+ function getBookmarkHeight(editor, assetId) {
13
+ const asset = assetId ? editor.getAsset(assetId) : null;
14
+ if (asset) {
15
+ if (!asset.props.image) {
16
+ if (!asset.props.title) {
17
+ return BOOKMARK_JUST_URL_HEIGHT;
18
+ } else {
19
+ return SHORT_BOOKMARK_HEIGHT;
20
+ }
21
+ }
22
+ }
23
+ return BOOKMARK_HEIGHT;
24
+ }
25
+ function setBookmarkHeight(editor, shape) {
26
+ return {
27
+ ...shape,
28
+ props: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) }
29
+ };
30
+ }
31
+ const getHumanReadableAddress = (url) => {
32
+ try {
33
+ const objUrl = new URL(url);
34
+ return objUrl.hostname.replace(/^www\./, "");
35
+ } catch {
36
+ return url;
37
+ }
38
+ };
39
+ function updateBookmarkAssetOnUrlChange(editor, shape) {
40
+ const { url } = shape.props;
41
+ const assetId = AssetRecordType.createId(getHashForString(url));
42
+ if (editor.getAsset(assetId)) {
43
+ if (shape.props.assetId !== assetId) {
44
+ editor.updateShapes([
45
+ {
46
+ id: shape.id,
47
+ type: shape.type,
48
+ props: { assetId }
49
+ }
50
+ ]);
51
+ }
52
+ } else {
53
+ editor.updateShapes([
54
+ {
55
+ id: shape.id,
56
+ type: shape.type,
57
+ props: { assetId: null }
58
+ }
59
+ ]);
60
+ createBookmarkAssetOnUrlChange(editor, shape);
61
+ }
62
+ }
63
+ const createBookmarkAssetOnUrlChange = debounce(async (editor, shape) => {
64
+ if (editor.isDisposed) return;
65
+ const { url } = shape.props;
66
+ const asset = await editor.getAssetForExternalContent({ type: "url", url });
67
+ if (!asset) {
68
+ return;
69
+ }
70
+ editor.run(() => {
71
+ editor.createAssets([asset]);
72
+ editor.updateShapes([
73
+ {
74
+ id: shape.id,
75
+ type: shape.type,
76
+ props: { assetId: asset.id }
77
+ }
78
+ ]);
79
+ });
80
+ }, 500);
81
+ async function createBookmarkFromUrl(editor, {
82
+ url,
83
+ center = editor.getViewportPageBounds().center
84
+ }) {
85
+ try {
86
+ const asset = await editor.getAssetForExternalContent({ type: "url", url });
87
+ const shapeId = createShapeId();
88
+ const shapePartial = {
89
+ id: shapeId,
90
+ type: "bookmark",
91
+ x: center.x - BOOKMARK_WIDTH / 2,
92
+ y: center.y - BOOKMARK_HEIGHT / 2,
93
+ rotation: 0,
94
+ opacity: 1,
95
+ props: {
96
+ url,
97
+ assetId: asset?.id || null,
98
+ w: BOOKMARK_WIDTH,
99
+ h: getBookmarkHeight(editor, asset?.id)
100
+ }
101
+ };
102
+ editor.run(() => {
103
+ if (asset) {
104
+ editor.createAssets([asset]);
105
+ }
106
+ editor.createShapes([shapePartial]);
107
+ });
108
+ const createdShape = editor.getShape(shapeId);
109
+ return Result.ok(createdShape);
110
+ } catch (error) {
111
+ return Result.err(error instanceof Error ? error.message : "Failed to create bookmark");
112
+ }
113
+ }
114
+ export {
115
+ BOOKMARK_HEIGHT,
116
+ BOOKMARK_JUST_URL_HEIGHT,
117
+ BOOKMARK_WIDTH,
118
+ createBookmarkFromUrl,
119
+ getBookmarkHeight,
120
+ getHumanReadableAddress,
121
+ setBookmarkHeight,
122
+ updateBookmarkAssetOnUrlChange
123
+ };
124
+ //# sourceMappingURL=bookmarks.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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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",
6
+ "names": []
7
+ }