@tldraw/editor 4.5.3 → 4.6.0-canary.00a8c03b5687

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 (279) hide show
  1. package/dist-cjs/index.d.ts +37 -6
  2. package/dist-cjs/index.js +6 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +7 -5
  5. package/dist-cjs/lib/TldrawEditor.js.map +3 -3
  6. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -2
  7. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +8 -5
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  12. package/dist-cjs/lib/config/TLSessionStateSnapshot.js +8 -5
  13. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
  14. package/dist-cjs/lib/config/TLUserPreferences.js +3 -2
  15. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  16. package/dist-cjs/lib/config/createTLStore.js +1 -0
  17. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  18. package/dist-cjs/lib/config/createTLUser.js.map +1 -1
  19. package/dist-cjs/lib/editor/Editor.js +511 -366
  20. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  21. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +25 -64
  22. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  23. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +22 -5
  24. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
  25. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +4 -3
  26. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  27. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +5 -0
  28. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  29. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +71 -112
  30. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  31. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +20 -55
  32. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
  33. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +11 -52
  34. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
  35. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +19 -56
  36. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +1 -1
  37. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -2
  38. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  39. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +16 -55
  40. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
  41. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +60 -70
  42. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  43. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  44. package/dist-cjs/lib/exports/ExportDelay.js +12 -53
  45. package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
  46. package/dist-cjs/lib/exports/FontEmbedder.js +23 -65
  47. package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
  48. package/dist-cjs/lib/exports/StyleEmbedder.js +27 -15
  49. package/dist-cjs/lib/exports/StyleEmbedder.js.map +3 -3
  50. package/dist-cjs/lib/exports/domUtils.js +15 -0
  51. package/dist-cjs/lib/exports/domUtils.js.map +2 -2
  52. package/dist-cjs/lib/exports/embedMedia.js +15 -12
  53. package/dist-cjs/lib/exports/embedMedia.js.map +2 -2
  54. package/dist-cjs/lib/exports/exportToSvg.js +8 -7
  55. package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
  56. package/dist-cjs/lib/exports/getSvgAsImage.js +181 -29
  57. package/dist-cjs/lib/exports/getSvgAsImage.js.map +3 -3
  58. package/dist-cjs/lib/exports/getSvgJsx.js +21 -9
  59. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  60. package/dist-cjs/lib/globals/environment.js +4 -3
  61. package/dist-cjs/lib/globals/environment.js.map +2 -2
  62. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
  63. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  64. package/dist-cjs/lib/hooks/useDocumentEvents.js +13 -11
  65. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  66. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +3 -2
  67. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  68. package/dist-cjs/lib/hooks/useScreenBounds.js +10 -6
  69. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  70. package/dist-cjs/lib/hooks/useViewportHeight.js +13 -11
  71. package/dist-cjs/lib/hooks/useViewportHeight.js.map +3 -3
  72. package/dist-cjs/lib/license/Watermark.js +10 -0
  73. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  74. package/dist-cjs/lib/primitives/Box.js +25 -25
  75. package/dist-cjs/lib/primitives/Box.js.map +1 -1
  76. package/dist-cjs/lib/primitives/Vec.js +36 -23
  77. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  78. package/dist-cjs/lib/primitives/geometry/Arc2d.js +6 -13
  79. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  80. package/dist-cjs/lib/primitives/geometry/Circle2d.js +31 -2
  81. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  82. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +9 -0
  83. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  84. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +10 -1
  85. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  86. package/dist-cjs/lib/primitives/geometry/Edge2d.js +32 -18
  87. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  88. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +13 -1
  89. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  90. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -6
  91. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
  92. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +52 -13
  93. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  94. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +12 -0
  95. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  96. package/dist-cjs/lib/primitives/geometry/geometry.bench.js +133 -0
  97. package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +7 -0
  98. package/dist-cjs/lib/primitives/intersect.js +16 -15
  99. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  100. package/dist-cjs/lib/primitives/utils.js +0 -1
  101. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  102. package/dist-cjs/lib/utils/SharedStylesMap.js +1 -1
  103. package/dist-cjs/lib/utils/SharedStylesMap.js.map +1 -1
  104. package/dist-cjs/lib/utils/browserCanvasMaxSize.js +3 -2
  105. package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
  106. package/dist-cjs/lib/utils/dom.js +15 -2
  107. package/dist-cjs/lib/utils/dom.js.map +2 -2
  108. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +2 -1
  109. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  110. package/dist-cjs/version.js +3 -3
  111. package/dist-cjs/version.js.map +1 -1
  112. package/dist-esm/index.d.mts +37 -6
  113. package/dist-esm/index.mjs +8 -1
  114. package/dist-esm/index.mjs.map +2 -2
  115. package/dist-esm/lib/TldrawEditor.mjs +7 -5
  116. package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
  117. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +2 -1
  118. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
  119. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  120. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  121. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +8 -5
  122. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  123. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +8 -5
  124. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  125. package/dist-esm/lib/config/TLUserPreferences.mjs +3 -2
  126. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  127. package/dist-esm/lib/config/createTLStore.mjs +1 -0
  128. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  129. package/dist-esm/lib/config/createTLUser.mjs.map +1 -1
  130. package/dist-esm/lib/editor/Editor.mjs +512 -368
  131. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  132. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +25 -64
  133. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  134. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +24 -5
  135. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
  136. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +4 -3
  137. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  138. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +5 -0
  139. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  140. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +71 -112
  141. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  142. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +20 -55
  143. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
  144. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +11 -52
  145. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
  146. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +19 -56
  147. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +1 -1
  148. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -2
  149. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  150. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +16 -55
  151. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
  152. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +60 -70
  153. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  154. package/dist-esm/lib/exports/ExportDelay.mjs +12 -53
  155. package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
  156. package/dist-esm/lib/exports/FontEmbedder.mjs +23 -65
  157. package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
  158. package/dist-esm/lib/exports/StyleEmbedder.mjs +29 -16
  159. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +3 -3
  160. package/dist-esm/lib/exports/domUtils.mjs +15 -0
  161. package/dist-esm/lib/exports/domUtils.mjs.map +2 -2
  162. package/dist-esm/lib/exports/embedMedia.mjs +16 -13
  163. package/dist-esm/lib/exports/embedMedia.mjs.map +2 -2
  164. package/dist-esm/lib/exports/exportToSvg.mjs +8 -7
  165. package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
  166. package/dist-esm/lib/exports/getSvgAsImage.mjs +181 -29
  167. package/dist-esm/lib/exports/getSvgAsImage.mjs.map +3 -3
  168. package/dist-esm/lib/exports/getSvgJsx.mjs +21 -9
  169. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  170. package/dist-esm/lib/globals/environment.mjs +4 -3
  171. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  172. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
  173. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  174. package/dist-esm/lib/hooks/useDocumentEvents.mjs +13 -11
  175. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  176. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +3 -2
  177. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  178. package/dist-esm/lib/hooks/useScreenBounds.mjs +10 -6
  179. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  180. package/dist-esm/lib/hooks/useViewportHeight.mjs +13 -11
  181. package/dist-esm/lib/hooks/useViewportHeight.mjs.map +3 -3
  182. package/dist-esm/lib/license/Watermark.mjs +10 -0
  183. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  184. package/dist-esm/lib/primitives/Box.mjs +25 -25
  185. package/dist-esm/lib/primitives/Box.mjs.map +1 -1
  186. package/dist-esm/lib/primitives/Vec.mjs +36 -23
  187. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  188. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +6 -13
  189. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  190. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +31 -2
  191. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  192. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +9 -0
  193. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  194. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +10 -1
  195. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  196. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +32 -18
  197. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  198. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +14 -2
  199. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  200. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -6
  201. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
  202. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +52 -13
  203. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  204. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +13 -1
  205. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  206. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +132 -0
  207. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +7 -0
  208. package/dist-esm/lib/primitives/intersect.mjs +17 -16
  209. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  210. package/dist-esm/lib/primitives/utils.mjs +0 -1
  211. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  212. package/dist-esm/lib/utils/SharedStylesMap.mjs +1 -1
  213. package/dist-esm/lib/utils/SharedStylesMap.mjs.map +1 -1
  214. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +3 -2
  215. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
  216. package/dist-esm/lib/utils/dom.mjs +15 -2
  217. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  218. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +2 -1
  219. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  220. package/dist-esm/version.mjs +3 -3
  221. package/dist-esm/version.mjs.map +1 -1
  222. package/package.json +8 -8
  223. package/src/index.ts +10 -6
  224. package/src/lib/TldrawEditor.tsx +7 -5
  225. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +2 -1
  226. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  227. package/src/lib/components/default-components/DefaultErrorFallback.tsx +9 -5
  228. package/src/lib/config/TLSessionStateSnapshot.ts +8 -5
  229. package/src/lib/config/TLUserPreferences.ts +3 -2
  230. package/src/lib/config/createTLStore.ts +3 -0
  231. package/src/lib/config/createTLUser.ts +3 -3
  232. package/src/lib/editor/Editor.ts +53 -15
  233. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  234. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +7 -6
  235. package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -7
  236. package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
  237. package/src/lib/editor/managers/FontManager/FontManager.ts +4 -3
  238. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +16 -0
  239. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +7 -2
  240. package/src/lib/editor/managers/InputsManager/InputsManager.ts +30 -30
  241. package/src/lib/editor/managers/TextManager/TextManager.test.ts +4 -5
  242. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -2
  243. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +3 -2
  244. package/src/lib/editor/types/misc-types.ts +8 -2
  245. package/src/lib/exports/FontEmbedder.ts +10 -9
  246. package/src/lib/exports/StyleEmbedder.ts +33 -15
  247. package/src/lib/exports/domUtils.ts +20 -0
  248. package/src/lib/exports/embedMedia.ts +23 -17
  249. package/src/lib/exports/exportToSvg.tsx +8 -7
  250. package/src/lib/exports/getSvgAsImage.ts +292 -32
  251. package/src/lib/exports/getSvgJsx.test.ts +103 -101
  252. package/src/lib/exports/getSvgJsx.tsx +33 -10
  253. package/src/lib/globals/environment.ts +4 -3
  254. package/src/lib/hooks/useCanvasEvents.ts +2 -3
  255. package/src/lib/hooks/useDocumentEvents.ts +16 -11
  256. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +3 -3
  257. package/src/lib/hooks/useScreenBounds.ts +10 -6
  258. package/src/lib/hooks/useViewportHeight.ts +13 -11
  259. package/src/lib/license/Watermark.tsx +10 -0
  260. package/src/lib/primitives/Box.ts +25 -25
  261. package/src/lib/primitives/Vec.ts +52 -25
  262. package/src/lib/primitives/geometry/Arc2d.ts +10 -15
  263. package/src/lib/primitives/geometry/Circle2d.ts +40 -2
  264. package/src/lib/primitives/geometry/CubicBezier2d.ts +10 -0
  265. package/src/lib/primitives/geometry/CubicSpline2d.ts +11 -1
  266. package/src/lib/primitives/geometry/Edge2d.ts +41 -18
  267. package/src/lib/primitives/geometry/Ellipse2d.ts +15 -2
  268. package/src/lib/primitives/geometry/Geometry2d.ts +6 -6
  269. package/src/lib/primitives/geometry/Polyline2d.ts +61 -13
  270. package/src/lib/primitives/geometry/Stadium2d.ts +14 -1
  271. package/src/lib/primitives/geometry/geometry.bench.ts +179 -0
  272. package/src/lib/primitives/intersect.ts +27 -27
  273. package/src/lib/primitives/utils.ts +4 -4
  274. package/src/lib/test/TestEditor.ts +1 -0
  275. package/src/lib/utils/SharedStylesMap.ts +1 -1
  276. package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
  277. package/src/lib/utils/dom.ts +34 -2
  278. package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
  279. package/src/version.ts +3 -3
@@ -1,4 +1,5 @@
1
1
  import { useLayoutEffect, useState } from 'react'
2
+ import { useMaybeEditor } from './useEditor'
2
3
 
3
4
  /*!
4
5
  * BSD License: https://github.com/outline/rich-markdown-editor/blob/main/LICENSE
@@ -12,26 +13,27 @@ import { useLayoutEffect, useState } from 'react'
12
13
  */
13
14
  /** @public */
14
15
  export function useViewportHeight(): number {
15
- const visualViewport = window.visualViewport
16
+ const editor = useMaybeEditor()
17
+ const win = editor?.getContainerWindow() ?? window
18
+ const vv = win.visualViewport
16
19
  const [height, setHeight] = useState<number>(() =>
17
- visualViewport ? visualViewport.height + visualViewport.offsetTop : window.innerHeight
20
+ vv ? vv.height + vv.offsetTop : win.innerHeight
18
21
  )
19
22
 
20
23
  useLayoutEffect(() => {
24
+ const win = editor?.getContainerWindow() ?? window
21
25
  const handleResize = () => {
22
- const visualViewport = window.visualViewport
23
- setHeight(() =>
24
- visualViewport ? visualViewport.height + visualViewport.offsetTop : window.innerHeight
25
- )
26
+ const vv = win.visualViewport
27
+ setHeight(() => (vv ? vv.height + vv.offsetTop : win.innerHeight))
26
28
  }
27
29
 
28
- window.visualViewport?.addEventListener('resize', handleResize)
29
- window.visualViewport?.addEventListener('scroll', handleResize)
30
+ win.visualViewport?.addEventListener('resize', handleResize)
31
+ win.visualViewport?.addEventListener('scroll', handleResize)
30
32
 
31
33
  return () => {
32
- window.visualViewport?.removeEventListener('resize', handleResize)
33
- window.visualViewport?.removeEventListener('scroll', handleResize)
34
+ win.visualViewport?.removeEventListener('resize', handleResize)
35
+ win.visualViewport?.removeEventListener('scroll', handleResize)
34
36
  }
35
- }, [])
37
+ }, [editor])
36
38
  return height
37
39
  }
@@ -191,6 +191,16 @@ To remove the watermark, please purchase a license at tldraw.dev.
191
191
  height: 32px;
192
192
  }
193
193
 
194
+ .tl-container[dir='rtl'] .${className} {
195
+ right: auto;
196
+ left: max(var(--tl-space-2), env(safe-area-inset-left));
197
+ }
198
+
199
+ .tl-container[dir='rtl'] .${className}[data-mobile='true'] {
200
+ border-radius: 0px 4px 4px 0px;
201
+ left: max(-2px, calc(env(safe-area-inset-left) - 2px));
202
+ }
203
+
194
204
  .${className}[data-unlicensed='true'] > button {
195
205
  font-size: 100px;
196
206
  position: absolute;
@@ -36,114 +36,114 @@ export class Box {
36
36
  w = 0
37
37
  h = 0
38
38
 
39
- // eslint-disable-next-line no-restricted-syntax
39
+ // eslint-disable-next-line tldraw/no-setter-getter
40
40
  get point() {
41
41
  return new Vec(this.x, this.y)
42
42
  }
43
43
 
44
- // eslint-disable-next-line no-restricted-syntax
44
+ // eslint-disable-next-line tldraw/no-setter-getter
45
45
  set point(val: Vec) {
46
46
  this.x = val.x
47
47
  this.y = val.y
48
48
  }
49
49
 
50
- // eslint-disable-next-line no-restricted-syntax
50
+ // eslint-disable-next-line tldraw/no-setter-getter
51
51
  get minX() {
52
52
  return this.x
53
53
  }
54
54
 
55
- // eslint-disable-next-line no-restricted-syntax
55
+ // eslint-disable-next-line tldraw/no-setter-getter
56
56
  set minX(n: number) {
57
57
  this.x = n
58
58
  }
59
59
 
60
- // eslint-disable-next-line no-restricted-syntax
60
+ // eslint-disable-next-line tldraw/no-setter-getter
61
61
  get left() {
62
62
  return this.x
63
63
  }
64
64
 
65
- // eslint-disable-next-line no-restricted-syntax
65
+ // eslint-disable-next-line tldraw/no-setter-getter
66
66
  get midX() {
67
67
  return this.x + this.w / 2
68
68
  }
69
69
 
70
- // eslint-disable-next-line no-restricted-syntax
70
+ // eslint-disable-next-line tldraw/no-setter-getter
71
71
  get maxX() {
72
72
  return this.x + this.w
73
73
  }
74
74
 
75
- // eslint-disable-next-line no-restricted-syntax
75
+ // eslint-disable-next-line tldraw/no-setter-getter
76
76
  get right() {
77
77
  return this.x + this.w
78
78
  }
79
79
 
80
- // eslint-disable-next-line no-restricted-syntax
80
+ // eslint-disable-next-line tldraw/no-setter-getter
81
81
  get minY() {
82
82
  return this.y
83
83
  }
84
84
 
85
- // eslint-disable-next-line no-restricted-syntax
85
+ // eslint-disable-next-line tldraw/no-setter-getter
86
86
  set minY(n: number) {
87
87
  this.y = n
88
88
  }
89
89
 
90
- // eslint-disable-next-line no-restricted-syntax
90
+ // eslint-disable-next-line tldraw/no-setter-getter
91
91
  get top() {
92
92
  return this.y
93
93
  }
94
94
 
95
- // eslint-disable-next-line no-restricted-syntax
95
+ // eslint-disable-next-line tldraw/no-setter-getter
96
96
  get midY() {
97
97
  return this.y + this.h / 2
98
98
  }
99
99
 
100
- // eslint-disable-next-line no-restricted-syntax
100
+ // eslint-disable-next-line tldraw/no-setter-getter
101
101
  get maxY() {
102
102
  return this.y + this.h
103
103
  }
104
104
 
105
- // eslint-disable-next-line no-restricted-syntax
105
+ // eslint-disable-next-line tldraw/no-setter-getter
106
106
  get bottom() {
107
107
  return this.y + this.h
108
108
  }
109
109
 
110
- // eslint-disable-next-line no-restricted-syntax
110
+ // eslint-disable-next-line tldraw/no-setter-getter
111
111
  get width() {
112
112
  return this.w
113
113
  }
114
114
 
115
- // eslint-disable-next-line no-restricted-syntax
115
+ // eslint-disable-next-line tldraw/no-setter-getter
116
116
  set width(n: number) {
117
117
  this.w = n
118
118
  }
119
119
 
120
- // eslint-disable-next-line no-restricted-syntax
120
+ // eslint-disable-next-line tldraw/no-setter-getter
121
121
  get height() {
122
122
  return this.h
123
123
  }
124
124
 
125
- // eslint-disable-next-line no-restricted-syntax
125
+ // eslint-disable-next-line tldraw/no-setter-getter
126
126
  set height(n: number) {
127
127
  this.h = n
128
128
  }
129
129
 
130
- // eslint-disable-next-line no-restricted-syntax
130
+ // eslint-disable-next-line tldraw/no-setter-getter
131
131
  get aspectRatio() {
132
132
  return this.width / this.height
133
133
  }
134
134
 
135
- // eslint-disable-next-line no-restricted-syntax
135
+ // eslint-disable-next-line tldraw/no-setter-getter
136
136
  get center() {
137
137
  return new Vec(this.x + this.w / 2, this.y + this.h / 2)
138
138
  }
139
139
 
140
- // eslint-disable-next-line no-restricted-syntax
140
+ // eslint-disable-next-line tldraw/no-setter-getter
141
141
  set center(v: Vec) {
142
142
  this.x = v.x - this.w / 2
143
143
  this.y = v.y - this.h / 2
144
144
  }
145
145
 
146
- // eslint-disable-next-line no-restricted-syntax
146
+ // eslint-disable-next-line tldraw/no-setter-getter
147
147
  get corners() {
148
148
  return [
149
149
  new Vec(this.x, this.y),
@@ -153,7 +153,7 @@ export class Box {
153
153
  ]
154
154
  }
155
155
 
156
- // eslint-disable-next-line no-restricted-syntax
156
+ // eslint-disable-next-line tldraw/no-setter-getter
157
157
  get cornersAndCenter() {
158
158
  return [
159
159
  new Vec(this.x, this.y),
@@ -164,7 +164,7 @@ export class Box {
164
164
  ]
165
165
  }
166
166
 
167
- // eslint-disable-next-line no-restricted-syntax
167
+ // eslint-disable-next-line tldraw/no-setter-getter
168
168
  get sides(): Array<[Vec, Vec]> {
169
169
  const { corners } = this
170
170
  return [
@@ -175,7 +175,7 @@ export class Box {
175
175
  ]
176
176
  }
177
177
 
178
- // eslint-disable-next-line no-restricted-syntax
178
+ // eslint-disable-next-line tldraw/no-setter-getter
179
179
  get size(): Vec {
180
180
  return new Vec(this.w, this.h)
181
181
  }
@@ -19,7 +19,7 @@ export class Vec {
19
19
  public z = 1
20
20
  ) {}
21
21
 
22
- // eslint-disable-next-line no-restricted-syntax
22
+ // eslint-disable-next-line tldraw/no-setter-getter
23
23
  get pressure() {
24
24
  return this.z
25
25
  }
@@ -430,32 +430,58 @@ export class Vec {
430
430
  * @param P - A point not on the line to test.
431
431
  */
432
432
  static NearestPointOnLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): Vec {
433
- return Vec.Mul(u, Vec.Sub(P, A).pry(u)).add(A)
433
+ // Inlined: t = Vec.Sub(P, A).pry(u), return Vec.Mul(u, t).add(A)
434
+ const t = (P.x - A.x) * u.x + (P.y - A.y) * u.y
435
+ return new Vec(A.x + u.x * t, A.y + u.y * t)
434
436
  }
435
437
 
436
438
  static NearestPointOnLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): Vec {
437
- if (Vec.Equals(A, P)) return Vec.From(P)
438
- if (Vec.Equals(B, P)) return Vec.From(P)
439
+ // Parametric projection of P onto segment AB.
440
+ // Inlined: d = Vec.Sub(B, A); t = Vec.Sub(P, A).pry(d) / d.len(); return Vec.Lrp(A, B, t)
441
+ const dx = B.x - A.x
442
+ const dy = B.y - A.y
443
+ const d2 = dx * dx + dy * dy
439
444
 
440
- const u = Vec.Tan(B, A)
441
- const C = Vec.Add(A, Vec.Mul(u, Vec.Sub(P, A).pry(u)))
445
+ if (d2 === 0) return Vec.From(A)
446
+
447
+ let t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2
442
448
 
443
449
  if (clamp) {
444
- if (C.x < Math.min(A.x, B.x)) return Vec.Cast(A.x < B.x ? A : B)
445
- if (C.x > Math.max(A.x, B.x)) return Vec.Cast(A.x > B.x ? A : B)
446
- if (C.y < Math.min(A.y, B.y)) return Vec.Cast(A.y < B.y ? A : B)
447
- if (C.y > Math.max(A.y, B.y)) return Vec.Cast(A.y > B.y ? A : B)
450
+ if (t < 0) t = 0
451
+ else if (t > 1) t = 1
448
452
  }
449
453
 
450
- return C
454
+ return new Vec(A.x + t * dx, A.y + t * dy)
451
455
  }
452
456
 
453
457
  static DistanceToLineThroughPoint(A: VecLike, u: VecLike, P: VecLike): number {
454
- return Vec.Dist(P, Vec.NearestPointOnLineThroughPoint(A, u, P))
458
+ // Inlined: Vec.Dist(P, Vec.NearestPointOnLineThroughPoint(A, u, P))
459
+ // Uses |cross(P-A, u)| which equals the perpendicular distance when u is a unit vector.
460
+ const dx = P.x - A.x
461
+ const dy = P.y - A.y
462
+ return Math.abs(dx * u.y - dy * u.x)
455
463
  }
456
464
 
457
465
  static DistanceToLineSegment(A: VecLike, B: VecLike, P: VecLike, clamp = true): number {
458
- return Vec.Dist(P, Vec.NearestPointOnLineSegment(A, B, P, clamp))
466
+ // Inlined: Vec.Dist(P, Vec.NearestPointOnLineSegment(A, B, P, clamp))
467
+ // Computes the nearest point via parametric t-projection then returns the scalar distance,
468
+ // avoiding the intermediate Vec allocation that NearestPointOnLineSegment would create.
469
+ const dx = B.x - A.x
470
+ const dy = B.y - A.y
471
+ const d2 = dx * dx + dy * dy
472
+
473
+ if (d2 === 0) return Vec.Dist(A, P)
474
+
475
+ let t = ((P.x - A.x) * dx + (P.y - A.y) * dy) / d2
476
+
477
+ if (clamp) {
478
+ if (t < 0) t = 0
479
+ else if (t > 1) t = 1
480
+ }
481
+
482
+ const nx = A.x + t * dx - P.x
483
+ const ny = A.y + t * dy - P.y
484
+ return Math.sqrt(nx * nx + ny * ny)
459
485
  }
460
486
 
461
487
  static Snap(A: VecLike, step = 1) {
@@ -476,6 +502,10 @@ export class Vec {
476
502
  return isNaN(A.x) || isNaN(A.y)
477
503
  }
478
504
 
505
+ static IsFinite(A: VecLike): boolean {
506
+ return Number.isFinite(A.x) && Number.isFinite(A.y)
507
+ }
508
+
479
509
  /**
480
510
  * Get the angle from position A to position B.
481
511
  */
@@ -488,14 +518,11 @@ export class Vec {
488
518
  * two vectors, between -π and π. The sign indicates direction of angle.
489
519
  */
490
520
  static AngleBetween(A: VecLike, B: VecLike): number {
521
+ // p = dot(A, B); n = |A| * |B| (uses x*x instead of Math.pow(x, 2))
491
522
  const p = A.x * B.x + A.y * B.y
492
- const n = Math.sqrt(
493
- (Math.pow(A.x, 2) + Math.pow(A.y, 2)) * (Math.pow(B.x, 2) + Math.pow(B.y, 2))
494
- )
523
+ const n = Math.sqrt((A.x * A.x + A.y * A.y) * (B.x * B.x + B.y * B.y))
495
524
  const sign = A.x * B.y - A.y * B.x < 0 ? -1 : 1
496
- const angle = sign * Math.acos(clamp(p / n, -1, 1))
497
-
498
- return angle
525
+ return sign * Math.acos(clamp(p / n, -1, 1))
499
526
  }
500
527
 
501
528
  /**
@@ -506,7 +533,8 @@ export class Vec {
506
533
  * @returns The interpolated point.
507
534
  */
508
535
  static Lrp(A: VecLike, B: VecLike, t: number): Vec {
509
- return Vec.Sub(B, A).mul(t).add(A)
536
+ // Inlined: Vec.Sub(B, A).mul(t).add(A) — note: only interpolates x/y, not z.
537
+ return new Vec(A.x + (B.x - A.x) * t, A.y + (B.y - A.y) * t)
510
538
  }
511
539
 
512
540
  static Med(A: VecLike, B: VecLike): Vec {
@@ -604,14 +632,15 @@ export class Vec {
604
632
  * @param A - The first point.
605
633
  * @param B - The second point.
606
634
  * @param steps - The number of points to return.
635
+ * @param ease - The easing to use.
607
636
  */
608
- static PointsBetween(A: VecModel, B: VecModel, steps = 6): Vec[] {
637
+ static PointsBetween(A: VecModel, B: VecModel, steps = 6, ease = EASINGS.easeInQuad): Vec[] {
609
638
  const results: Vec[] = []
610
639
 
611
640
  for (let i = 0; i < steps; i++) {
612
- const t = EASINGS.easeInQuad(i / (steps - 1))
641
+ const t = ease(i / (steps - 1))
613
642
  const point = Vec.Lrp(A, B, t)
614
- point.z = Math.min(1, 0.5 + Math.abs(0.5 - ease(t)) * 0.65)
643
+ point.z = Math.min(1, 0.5 + Math.abs(0.5 - EASINGS.easeInOutQuad(t)) * 0.65)
615
644
  results.push(point)
616
645
  }
617
646
 
@@ -622,5 +651,3 @@ export class Vec {
622
651
  return new Vec(Math.round(A.x / gridSize) * gridSize, Math.round(A.y / gridSize) * gridSize)
623
652
  }
624
653
  }
625
-
626
- const ease = (t: number) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t)
@@ -57,21 +57,16 @@ export class Arc2d extends Geometry2d {
57
57
  if (t <= 0) return A
58
58
  if (t >= 1) return B
59
59
 
60
- // Get the point (P) on the arc, then pick the nearest of A, B, and P
61
- const P = Vec.Sub(point, _center).uni().mul(radius).add(_center)
62
-
63
- let nearest: Vec | undefined
64
- let dist = Infinity
65
- let d: number
66
- for (const p of [A, B, P]) {
67
- d = Vec.Dist2(point, p)
68
- if (d < dist) {
69
- nearest = p
70
- dist = d
71
- }
72
- }
73
- if (!nearest) throw Error('nearest point not found')
74
- return nearest
60
+ // Inlined: Vec.Sub(point, _center).uni().mul(radius).add(_center)
61
+ // When t is in (0,1), the nearest point is the radial projection of point onto the arc.
62
+ // Previously this also checked min-distance against A and B, but that's unnecessary when
63
+ // t is already in range — the radial projection is always closer.
64
+ const dx = point.x - _center.x
65
+ const dy = point.y - _center.y
66
+ const len = Math.sqrt(dx * dx + dy * dy)
67
+ if (len === 0) return A
68
+ const scale = radius / len
69
+ return new Vec(_center.x + dx * scale, _center.y + dy * scale)
75
70
  }
76
71
 
77
72
  hitTestLineSegment(A: VecLike, B: VecLike): boolean {
@@ -44,9 +44,47 @@ export class Circle2d extends Geometry2d {
44
44
  }
45
45
 
46
46
  nearestPoint(point: VecLike): Vec {
47
+ // Inlined: Vec.Sub(point, _center).uni().mul(radius).add(_center)
48
+ // Computes direction from center to point, normalizes, scales by radius, offsets by center.
47
49
  const { _center, _radius: radius } = this
48
- if (_center.equals(point)) return Vec.AddXY(_center, radius, 0)
49
- return Vec.Sub(point, _center).uni().mul(radius).add(_center)
50
+ const dx = point.x - _center.x
51
+ const dy = point.y - _center.y
52
+ const len = Math.sqrt(dx * dx + dy * dy)
53
+ if (len === 0) return new Vec(_center.x + radius, _center.y)
54
+ const scale = radius / len
55
+ return new Vec(_center.x + dx * scale, _center.y + dy * scale)
56
+ }
57
+
58
+ override distanceToPoint(point: VecLike, hitInside = false): number {
59
+ // Inlined: Math.abs(Vec.Dist(point, _center) - radius)
60
+ // Computes distance from point to center, then subtracts radius for edge distance.
61
+ // Returns negative when inside a filled circle to indicate containment.
62
+ const { _center, _radius: radius } = this
63
+ const dx = point.x - _center.x
64
+ const dy = point.y - _center.y
65
+ const dist = Math.sqrt(dx * dx + dy * dy)
66
+ const distToEdge = dist - radius
67
+ if (distToEdge < 0 && (this.isFilled || hitInside)) {
68
+ return distToEdge
69
+ }
70
+ return Math.abs(distToEdge)
71
+ }
72
+
73
+ override hitTestPoint(point: VecLike, margin = 0, hitInside = false): boolean {
74
+ // Equivalent to: dist = Vec.Dist(point, _center); return dist within [radius - margin, radius + margin]
75
+ // Uses squared distances throughout to avoid any sqrt calls.
76
+ const { _center, _radius: radius } = this
77
+ const dx = point.x - _center.x
78
+ const dy = point.y - _center.y
79
+ const dist2 = dx * dx + dy * dy
80
+ if ((this.isFilled || hitInside) && dist2 <= radius * radius) {
81
+ return true
82
+ }
83
+ const outerR = radius + margin
84
+ if (dist2 > outerR * outerR) return false
85
+ const innerR = radius - margin
86
+ if (innerR <= 0) return true
87
+ return dist2 >= innerR * innerR
50
88
  }
51
89
 
52
90
  hitTestLineSegment(A: VecLike, B: VecLike, distance = 0): boolean {
@@ -69,6 +69,16 @@ export class CubicBezier2d extends Polyline2d {
69
69
  return nearest
70
70
  }
71
71
 
72
+ override distanceToPoint(point: VecLike, _hitInside = false): number {
73
+ const { segments } = this
74
+ let minDist = Infinity
75
+ for (let i = 0; i < segments.length; i++) {
76
+ const d = segments[i].distanceToPoint(point)
77
+ if (d < minDist) minDist = d
78
+ }
79
+ return minDist
80
+ }
81
+
72
82
  getSvgPathData(first = true) {
73
83
  const { _a: a, _b: b, _c: c, _d: d } = this
74
84
  return `${first ? `M ${a.toFixed()} ` : ``} C${b.toFixed()} ${c.toFixed()} ${d.toFixed()}`
@@ -15,7 +15,7 @@ export class CubicSpline2d extends Geometry2d {
15
15
 
16
16
  private _segments?: CubicBezier2d[]
17
17
 
18
- // eslint-disable-next-line no-restricted-syntax
18
+ // eslint-disable-next-line tldraw/no-setter-getter
19
19
  get segments() {
20
20
  if (!this._segments) {
21
21
  this._segments = []
@@ -75,6 +75,16 @@ export class CubicSpline2d extends Geometry2d {
75
75
  return nearest
76
76
  }
77
77
 
78
+ override distanceToPoint(point: VecLike, _hitInside = false): number {
79
+ const { segments } = this
80
+ let minDist = Infinity
81
+ for (let i = 0; i < segments.length; i++) {
82
+ const d = segments[i].distanceToPoint(point)
83
+ if (d < minDist) minDist = d
84
+ }
85
+ return minDist
86
+ }
87
+
78
88
  hitTestLineSegment(A: VecLike, B: VecLike): boolean {
79
89
  return this.segments.some((segment) => segment.hitTestLineSegment(A, B))
80
90
  }
@@ -5,9 +5,9 @@ import { Geometry2d } from './Geometry2d'
5
5
  export class Edge2d extends Geometry2d {
6
6
  private _start: Vec
7
7
  private _end: Vec
8
- private _d: Vec
9
- private _u: Vec
10
- private _ul: number
8
+ private _dx: number
9
+ private _dy: number
10
+ private _len2: number
11
11
 
12
12
  constructor(config: { start: Vec; end: Vec }) {
13
13
  super({ ...config, isClosed: false, isFilled: false })
@@ -16,13 +16,14 @@ export class Edge2d extends Geometry2d {
16
16
  this._start = start
17
17
  this._end = end
18
18
 
19
- this._d = start.clone().sub(end) // the delta from start to end
20
- this._u = this._d.clone().uni() // the unit vector of the edge
21
- this._ul = this._u.len() // the length of the unit vector
19
+ // Precomputed segment delta and squared length (replaces Vec.Sub(end, start) and Vec.Len2)
20
+ this._dx = end.x - start.x
21
+ this._dy = end.y - start.y
22
+ this._len2 = this._dx * this._dx + this._dy * this._dy
22
23
  }
23
24
 
24
25
  override getLength() {
25
- return this._d.len()
26
+ return Math.sqrt(this._len2)
26
27
  }
27
28
 
28
29
  override getVertices(): Vec[] {
@@ -30,17 +31,39 @@ export class Edge2d extends Geometry2d {
30
31
  }
31
32
 
32
33
  override nearestPoint(point: VecLike): Vec {
33
- const { _start: start, _end: end, _d: d, _u: u, _ul: l } = this
34
- if (d.len() === 0) return start // start and end are the same
35
- if (l === 0) return start // no length in the unit vector
36
- const k = Vec.Sub(point, start).dpr(u) / l
37
- const cx = start.x + u.x * k
38
- if (cx < Math.min(start.x, end.x)) return start.x < end.x ? start : end
39
- if (cx > Math.max(start.x, end.x)) return start.x > end.x ? start : end
40
- const cy = start.y + u.y * k
41
- if (cy < Math.min(start.y, end.y)) return start.y < end.y ? start : end
42
- if (cy > Math.max(start.y, end.y)) return start.y > end.y ? start : end
43
- return new Vec(cx, cy)
34
+ // Inlined: Vec.NearestPointOnLineSegment(start, end, point)
35
+ // Uses precomputed dx/dy/len2 and parametric t-clamping instead of Vec allocations.
36
+ const { _start: start, _end: end, _dx: dx, _dy: dy, _len2: len2 } = this
37
+ if (len2 === 0) return start
38
+
39
+ const t = ((point.x - start.x) * dx + (point.y - start.y) * dy) / len2
40
+ if (t <= 0) return start
41
+ if (t >= 1) return end
42
+ return new Vec(start.x + dx * t, start.y + dy * t)
43
+ }
44
+
45
+ override distanceToPoint(point: VecLike, _hitInside = false): number {
46
+ // Inlined: Vec.Dist(point, this.nearestPoint(point))
47
+ // Finds nearest point via parametric t-projection then returns scalar distance directly,
48
+ // avoiding the Vec allocation that nearestPoint would create.
49
+ const { _start: start, _end: end, _dx: dx, _dy: dy, _len2: len2 } = this
50
+ if (len2 === 0) return Vec.Dist(point, start)
51
+
52
+ const t = ((point.x - start.x) * dx + (point.y - start.y) * dy) / len2
53
+ let nx: number, ny: number
54
+ if (t <= 0) {
55
+ nx = start.x
56
+ ny = start.y
57
+ } else if (t >= 1) {
58
+ nx = end.x
59
+ ny = end.y
60
+ } else {
61
+ nx = start.x + dx * t
62
+ ny = start.y + dy * t
63
+ }
64
+ const ex = point.x - nx
65
+ const ey = point.y - ny
66
+ return Math.sqrt(ex * ex + ey * ey)
44
67
  }
45
68
 
46
69
  getSvgPathData(first = true) {
@@ -1,6 +1,6 @@
1
1
  import { Box } from '../Box'
2
2
  import { Vec, VecLike } from '../Vec'
3
- import { PI, PI2, clamp, perimeterOfEllipse } from '../utils'
3
+ import { PI, PI2, clamp, perimeterOfEllipse, pointInPolygon } from '../utils'
4
4
  import { Edge2d } from './Edge2d'
5
5
  import { Geometry2d, Geometry2dOptions } from './Geometry2d'
6
6
  import { getVerticesCountForArcLength } from './geometry-constants'
@@ -23,7 +23,7 @@ export class Ellipse2d extends Geometry2d {
23
23
  this._h = height
24
24
  }
25
25
 
26
- // eslint-disable-next-line no-restricted-syntax
26
+ // eslint-disable-next-line tldraw/no-setter-getter
27
27
  get edges() {
28
28
  if (!this._edges) {
29
29
  const { vertices } = this
@@ -89,6 +89,19 @@ export class Ellipse2d extends Geometry2d {
89
89
  return nearest
90
90
  }
91
91
 
92
+ override distanceToPoint(point: VecLike, hitInside = false): number {
93
+ const { edges } = this
94
+ let minDist = Infinity
95
+ for (let i = 0; i < edges.length; i++) {
96
+ const d = edges[i].distanceToPoint(point)
97
+ if (d < minDist) minDist = d
98
+ }
99
+ if (this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)) {
100
+ return -minDist
101
+ }
102
+ return minDist
103
+ }
104
+
92
105
  hitTestLineSegment(A: VecLike, B: VecLike): boolean {
93
106
  return this.edges.some((edge) => edge.hitTestLineSegment(A, B))
94
107
  }
@@ -307,7 +307,7 @@ export abstract class Geometry2d {
307
307
 
308
308
  private _vertices: Vec[] | undefined
309
309
 
310
- // eslint-disable-next-line no-restricted-syntax
310
+ // eslint-disable-next-line tldraw/no-setter-getter
311
311
  get vertices(): Vec[] {
312
312
  if (!this._vertices) {
313
313
  this._vertices = this.getVertices(Geometry2dFilters.EXCLUDE_LABELS)
@@ -323,7 +323,7 @@ export abstract class Geometry2d {
323
323
 
324
324
  private _boundsVertices: Vec[] | undefined
325
325
 
326
- // eslint-disable-next-line no-restricted-syntax
326
+ // eslint-disable-next-line tldraw/no-setter-getter
327
327
  get boundsVertices(): Vec[] {
328
328
  if (!this._boundsVertices) {
329
329
  this._boundsVertices = this.getBoundsVertices()
@@ -337,7 +337,7 @@ export abstract class Geometry2d {
337
337
 
338
338
  private _bounds: Box | undefined
339
339
 
340
- // eslint-disable-next-line no-restricted-syntax
340
+ // eslint-disable-next-line tldraw/no-setter-getter
341
341
  get bounds(): Box {
342
342
  if (!this._bounds) {
343
343
  this._bounds = this.getBounds()
@@ -345,14 +345,14 @@ export abstract class Geometry2d {
345
345
  return this._bounds
346
346
  }
347
347
 
348
- // eslint-disable-next-line no-restricted-syntax
348
+ // eslint-disable-next-line tldraw/no-setter-getter
349
349
  get center() {
350
350
  return this.bounds.center
351
351
  }
352
352
 
353
353
  private _area: number | undefined
354
354
 
355
- // eslint-disable-next-line no-restricted-syntax
355
+ // eslint-disable-next-line tldraw/no-setter-getter
356
356
  get area() {
357
357
  if (!this._area) {
358
358
  this._area = this.getArea()
@@ -397,7 +397,7 @@ export abstract class Geometry2d {
397
397
 
398
398
  private _length?: number
399
399
 
400
- // eslint-disable-next-line no-restricted-syntax
400
+ // eslint-disable-next-line tldraw/no-setter-getter
401
401
  get length() {
402
402
  if (this._length) return this._length
403
403
  this._length = this.getLength(Geometry2dFilters.EXCLUDE_LABELS)