@tldraw/editor 5.4.0-next.ef99ab47e5ce → 5.5.0-next.6d9e51e9f3f7

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 (288) hide show
  1. package/dist-cjs/index.d.ts +119 -49
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +7 -2
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
  9. package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
  12. package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
  13. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  14. package/dist-cjs/lib/config/createTLStore.js +1 -1
  15. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  16. package/dist-cjs/lib/constants.js +2 -0
  17. package/dist-cjs/lib/constants.js.map +2 -2
  18. package/dist-cjs/lib/editor/Editor.js +184 -296
  19. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  20. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
  21. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
  23. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
  25. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
  26. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +10 -6
  27. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
  29. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  30. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
  31. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  32. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +7 -0
  33. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
  35. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  36. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -2
  37. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  38. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +7 -3
  39. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +2 -2
  40. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +6 -3
  41. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  42. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +12 -1
  43. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  44. package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
  45. package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
  46. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
  47. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
  48. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
  49. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
  50. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
  51. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  52. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
  53. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  54. package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
  55. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  56. package/dist-cjs/lib/globals/editors.js +57 -0
  57. package/dist-cjs/lib/globals/editors.js.map +7 -0
  58. package/dist-cjs/lib/globals/menus.js +9 -4
  59. package/dist-cjs/lib/globals/menus.js.map +2 -2
  60. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
  61. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  62. package/dist-cjs/lib/hooks/useDocumentEvents.js +39 -9
  63. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  64. package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
  65. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  66. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
  67. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  68. package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
  69. package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
  70. package/dist-cjs/lib/license/LicenseManager.js +9 -2
  71. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  72. package/dist-cjs/lib/license/LicenseProvider.js +16 -3
  73. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  74. package/dist-cjs/lib/license/useLicenseManagerState.js +5 -4
  75. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  76. package/dist-cjs/lib/primitives/Box.js +2 -1
  77. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  78. package/dist-cjs/lib/primitives/Vec.js +4 -3
  79. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  80. package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
  81. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  82. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -1
  83. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  84. package/dist-cjs/lib/primitives/geometry/Edge2d.js +1 -1
  85. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  86. package/dist-cjs/lib/primitives/geometry/Group2d.js +71 -26
  87. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  88. package/dist-cjs/lib/primitives/geometry/Point2d.js +1 -1
  89. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  90. package/dist-cjs/lib/primitives/utils.js +2 -1
  91. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  92. package/dist-cjs/lib/utils/deepLinks.js +5 -1
  93. package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
  94. package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
  95. package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
  96. package/dist-cjs/lib/utils/rotation.js +1 -9
  97. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  98. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +17 -0
  99. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  100. package/dist-cjs/lib/utils/sync/alerts.js +1 -1
  101. package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
  102. package/dist-cjs/version.js +3 -3
  103. package/dist-cjs/version.js.map +1 -1
  104. package/dist-esm/index.d.mts +119 -49
  105. package/dist-esm/index.mjs +9 -2
  106. package/dist-esm/index.mjs.map +2 -2
  107. package/dist-esm/lib/TldrawEditor.mjs +9 -4
  108. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  109. package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
  110. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  111. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
  112. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
  113. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  114. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
  115. package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
  116. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  117. package/dist-esm/lib/config/createTLStore.mjs +1 -1
  118. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  119. package/dist-esm/lib/constants.mjs +2 -0
  120. package/dist-esm/lib/constants.mjs.map +2 -2
  121. package/dist-esm/lib/editor/Editor.mjs +193 -297
  122. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  123. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
  124. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
  125. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
  126. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  127. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
  128. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
  129. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +10 -6
  130. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  131. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
  132. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  133. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
  134. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  135. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +7 -0
  136. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
  137. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
  138. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  139. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
  140. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  141. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +7 -3
  142. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +2 -2
  143. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +6 -3
  144. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  145. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +12 -1
  146. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  147. package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
  148. package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
  149. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
  150. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
  151. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
  152. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
  153. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
  154. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  155. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
  156. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  157. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
  158. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  159. package/dist-esm/lib/globals/editors.mjs +37 -0
  160. package/dist-esm/lib/globals/editors.mjs.map +7 -0
  161. package/dist-esm/lib/globals/menus.mjs +9 -4
  162. package/dist-esm/lib/globals/menus.mjs.map +2 -2
  163. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
  164. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  165. package/dist-esm/lib/hooks/useDocumentEvents.mjs +40 -10
  166. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  167. package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
  168. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  169. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
  170. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  171. package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
  172. package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
  173. package/dist-esm/lib/license/LicenseManager.mjs +9 -2
  174. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  175. package/dist-esm/lib/license/LicenseProvider.mjs +16 -3
  176. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  177. package/dist-esm/lib/license/useLicenseManagerState.mjs +5 -4
  178. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  179. package/dist-esm/lib/primitives/Box.mjs +2 -1
  180. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  181. package/dist-esm/lib/primitives/Vec.mjs +4 -3
  182. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  183. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +1 -1
  184. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  185. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -1
  186. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  187. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +1 -1
  188. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  189. package/dist-esm/lib/primitives/geometry/Group2d.mjs +75 -27
  190. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  191. package/dist-esm/lib/primitives/geometry/Point2d.mjs +1 -1
  192. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  193. package/dist-esm/lib/primitives/utils.mjs +2 -1
  194. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  195. package/dist-esm/lib/utils/deepLinks.mjs +5 -1
  196. package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
  197. package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
  198. package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
  199. package/dist-esm/lib/utils/rotation.mjs +1 -9
  200. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  201. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +17 -0
  202. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  203. package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
  204. package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
  205. package/dist-esm/version.mjs +3 -3
  206. package/dist-esm/version.mjs.map +1 -1
  207. package/package.json +13 -7
  208. package/src/index.ts +6 -1
  209. package/src/lib/TldrawEditor.tsx +16 -4
  210. package/src/lib/components/MenuClickCapture.tsx +19 -18
  211. package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
  212. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  213. package/src/lib/config/TLUserPreferences.test.ts +18 -1
  214. package/src/lib/config/TLUserPreferences.ts +8 -4
  215. package/src/lib/config/createTLStore.ts +1 -1
  216. package/src/lib/constants.ts +8 -0
  217. package/src/lib/editor/Editor.ts +273 -386
  218. package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
  219. package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
  220. package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
  221. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +35 -4
  222. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +13 -7
  223. package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
  224. package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
  225. package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
  226. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +12 -1
  227. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
  228. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -6
  229. package/src/lib/editor/managers/ThemeManager/ThemeManager.test.ts +53 -0
  230. package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +9 -3
  231. package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -0
  232. package/src/lib/editor/managers/TickManager/TickManager.ts +9 -3
  233. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +64 -3
  234. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +18 -1
  235. package/src/lib/editor/overlays/OverlayManager.ts +3 -7
  236. package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
  237. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
  238. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
  239. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
  240. package/src/lib/editor/tools/StateNode.test.ts +64 -0
  241. package/src/lib/editor/tools/StateNode.ts +12 -2
  242. package/src/lib/globals/editors.test.ts +76 -0
  243. package/src/lib/globals/editors.ts +53 -0
  244. package/src/lib/globals/menus.test.ts +33 -0
  245. package/src/lib/globals/menus.ts +11 -4
  246. package/src/lib/hooks/useCanvasEvents.ts +2 -0
  247. package/src/lib/hooks/useDocumentEvents.ts +60 -16
  248. package/src/lib/hooks/useLocalStore.ts +16 -8
  249. package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
  250. package/src/lib/hooks/usePeerIds.ts +2 -1
  251. package/src/lib/license/LicenseManager.test.ts +160 -0
  252. package/src/lib/license/LicenseManager.ts +13 -4
  253. package/src/lib/license/LicenseProvider.tsx +24 -3
  254. package/src/lib/license/useLicenseManagerState.ts +8 -6
  255. package/src/lib/primitives/Box.test.ts +9 -1
  256. package/src/lib/primitives/Box.ts +3 -1
  257. package/src/lib/primitives/Vec.test.ts +10 -0
  258. package/src/lib/primitives/Vec.ts +4 -4
  259. package/src/lib/primitives/geometry/Arc2d.test.ts +235 -3
  260. package/src/lib/primitives/geometry/Arc2d.ts +1 -1
  261. package/src/lib/primitives/geometry/CubicBezier2d.test.ts +186 -3
  262. package/src/lib/primitives/geometry/CubicBezier2d.ts +1 -1
  263. package/src/lib/primitives/geometry/CubicSpline2d.test.ts +160 -3
  264. package/src/lib/primitives/geometry/Edge2d.test.ts +21 -3
  265. package/src/lib/primitives/geometry/Edge2d.ts +1 -1
  266. package/src/lib/primitives/geometry/Ellipse2d.test.ts +243 -3
  267. package/src/lib/primitives/geometry/Geometry2d.test.ts +553 -1
  268. package/src/lib/primitives/geometry/Group2d.test.ts +419 -3
  269. package/src/lib/primitives/geometry/Group2d.ts +81 -34
  270. package/src/lib/primitives/geometry/Point2d.test.ts +14 -3
  271. package/src/lib/primitives/geometry/Point2d.ts +1 -1
  272. package/src/lib/primitives/geometry/Polyline2d.test.ts +207 -0
  273. package/src/lib/primitives/geometry/Stadium2d.test.ts +191 -3
  274. package/src/lib/primitives/utils.test.ts +10 -1
  275. package/src/lib/primitives/utils.ts +4 -1
  276. package/src/lib/test/useCanvasEvents.test.tsx +74 -0
  277. package/src/lib/test/useDocumentEvents.test.tsx +107 -0
  278. package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
  279. package/src/lib/utils/deepLinks.test.ts +15 -0
  280. package/src/lib/utils/deepLinks.ts +7 -1
  281. package/src/lib/utils/normalizeWheel.test.ts +39 -0
  282. package/src/lib/utils/normalizeWheel.ts +6 -0
  283. package/src/lib/utils/rotation.ts +4 -12
  284. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +56 -0
  285. package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -0
  286. package/src/lib/utils/sync/alerts.ts +1 -1
  287. package/src/version.ts +3 -3
  288. package/src/lib/primitives/geometry/Polyline.test.ts +0 -5
@@ -1,5 +1,245 @@
1
- describe('Ellipse2d', () => {
2
- it('should be tested', () => {
3
- expect(true).toBe(true)
1
+ import { perimeterOfEllipse } from '../utils'
2
+ import { Vec } from '../Vec'
3
+ import { Edge2d } from './Edge2d'
4
+ import { Ellipse2d } from './Ellipse2d'
5
+ import { getVerticesCountForArcLength } from './geometry-constants'
6
+
7
+ // A 100x50 ellipse: centre (50, 25), rx = 50, ry = 25
8
+ const ellipse = () => new Ellipse2d({ width: 100, height: 50, isFilled: false })
9
+ const filled = () => new Ellipse2d({ width: 100, height: 50, isFilled: true })
10
+
11
+ function expectOnEllipse(p: Vec, cx: number, cy: number, rx: number, ry: number) {
12
+ const dx = (p.x - cx) / rx
13
+ const dy = (p.y - cy) / ry
14
+ expect(dx * dx + dy * dy).toBeCloseTo(1, 6)
15
+ }
16
+
17
+ describe('Ellipse2d construction', () => {
18
+ it('is always closed and keeps the fill flag from config', () => {
19
+ expect(ellipse()).toMatchObject({ isClosed: true, isFilled: false })
20
+ expect(filled()).toMatchObject({ isClosed: true, isFilled: true })
21
+ })
22
+
23
+ it('passes through the other geometry options', () => {
24
+ const e = new Ellipse2d({
25
+ width: 10,
26
+ height: 10,
27
+ isFilled: true,
28
+ isLabel: true,
29
+ isInternal: true,
30
+ debugColor: 'red',
31
+ ignore: true,
32
+ excludeFromShapeBounds: true,
33
+ })
34
+ expect(e).toMatchObject({
35
+ isLabel: true,
36
+ isInternal: true,
37
+ debugColor: 'red',
38
+ ignore: true,
39
+ excludeFromShapeBounds: true,
40
+ })
41
+ })
42
+ })
43
+
44
+ describe('Ellipse2d.getVertices', () => {
45
+ it('samples one vertex per 20 units of perimeter, starting at the rightmost point', () => {
46
+ const e = ellipse()
47
+ const { vertices } = e
48
+ expect(vertices.length).toBe(getVerticesCountForArcLength(perimeterOfEllipse(50, 25)))
49
+ expect(vertices.length).toBe(13)
50
+ expect(vertices[0]).toMatchObject({ x: 100, y: 25 })
51
+ })
52
+
53
+ it('places every vertex on the ellipse and inside the bounds', () => {
54
+ const { vertices, bounds } = ellipse()
55
+ for (const v of vertices) {
56
+ expectOnEllipse(v, 50, 25, 50, 25)
57
+ expect(bounds.containsPoint(v)).toBe(true)
58
+ }
59
+ })
60
+
61
+ it('walks the ellipse in the positive angular direction', () => {
62
+ const { vertices } = ellipse()
63
+ // second vertex is one step (2π/13) clockwise in screen space, so below the first
64
+ expect(vertices[1].x).toBeLessThan(100)
65
+ expect(vertices[1].y).toBeGreaterThan(25)
66
+ })
67
+
68
+ it('falls back to the minimum vertex count for a tiny ellipse', () => {
69
+ const { vertices } = new Ellipse2d({ width: 1, height: 1, isFilled: false })
70
+ expect(vertices.length).toBe(8)
71
+ })
72
+
73
+ it('does not produce NaNs for a zero size ellipse', () => {
74
+ const e = new Ellipse2d({ width: 0, height: 0, isFilled: false })
75
+ expect(e.vertices.length).toBe(8)
76
+ for (const v of e.vertices) {
77
+ expect(Number.isFinite(v.x)).toBe(true)
78
+ expect(Number.isFinite(v.y)).toBe(true)
79
+ }
80
+ expect(e.bounds).toMatchObject({ x: 0, y: 0, w: 0, h: 0 })
81
+ })
82
+
83
+ it('has a NaN length for a zero size ellipse (known quirk)', () => {
84
+ // perimeterOfEllipse divides by (rx + ry) ** 2, which is zero here
85
+ expect(new Ellipse2d({ width: 0, height: 0, isFilled: false }).getLength()).toBeNaN()
86
+ })
87
+ })
88
+
89
+ describe('Ellipse2d.edges', () => {
90
+ it('connects consecutive vertices and closes back to the first', () => {
91
+ const e = ellipse()
92
+ const { edges, vertices } = e
93
+ expect(edges.length).toBe(vertices.length)
94
+ expect(edges[0]).toBeInstanceOf(Edge2d)
95
+ expect(edges[0].vertices).toEqual([vertices[0], vertices[1]])
96
+ expect(edges[edges.length - 1].vertices).toEqual([vertices[vertices.length - 1], vertices[0]])
97
+ })
98
+
99
+ it('caches the edges', () => {
100
+ const e = ellipse()
101
+ expect(e.edges).toBe(e.edges)
102
+ })
103
+ })
104
+
105
+ describe('Ellipse2d.bounds', () => {
106
+ it('is the width by height box at the origin', () => {
107
+ expect(ellipse().bounds).toMatchObject({ x: 0, y: 0, w: 100, h: 50 })
108
+ expect(ellipse().center).toMatchObject({ x: 50, y: 25 })
109
+ })
110
+
111
+ it('is not affected by the polygon approximation', () => {
112
+ // the bounds come from the config, not from the sampled vertices
113
+ const e = new Ellipse2d({ width: 3, height: 7, isFilled: false })
114
+ expect(e.bounds).toMatchObject({ x: 0, y: 0, w: 3, h: 7 })
115
+ })
116
+ })
117
+
118
+ describe('Ellipse2d.getLength', () => {
119
+ it("uses Ramanujan's perimeter approximation", () => {
120
+ expect(ellipse().length).toBeCloseTo(242.21, 1)
121
+ expect(ellipse().length).toBeCloseTo(perimeterOfEllipse(50, 25))
122
+ })
123
+
124
+ it('matches a circle circumference when width equals height', () => {
125
+ expect(new Ellipse2d({ width: 100, height: 100, isFilled: false }).length).toBeCloseTo(
126
+ Math.PI * 100
127
+ )
128
+ })
129
+ })
130
+
131
+ describe('Ellipse2d.area', () => {
132
+ it('is the area of the inscribed polygon', () => {
133
+ const e = ellipse()
134
+ const n = e.vertices.length
135
+ expect(e.area).toBeCloseTo((n / 2) * 50 * 25 * Math.sin((2 * Math.PI) / n), 5)
136
+ expect(e.area).toBeLessThan(Math.PI * 50 * 25)
137
+ })
138
+ })
139
+
140
+ describe('Ellipse2d.nearestPoint', () => {
141
+ it('returns the vertex when it is the nearest point', () => {
142
+ expect(ellipse().nearestPoint(new Vec(150, 25))).toMatchObject({ x: 100, y: 25 })
143
+ })
144
+
145
+ it('returns a point on the edge polygon nearest to the point', () => {
146
+ const e = ellipse()
147
+ const p = e.nearestPoint(new Vec(50, -10))
148
+ expect(Vec.Dist(p, new Vec(50, 0))).toBeLessThan(1.5)
149
+ expect(e.hitTestPoint(p, 0.001)).toBe(true)
150
+ })
151
+
152
+ it('accepts plain objects', () => {
153
+ expect(ellipse().nearestPoint({ x: 150, y: 25 })).toMatchObject({ x: 100, y: 25 })
154
+ })
155
+ })
156
+
157
+ describe('Ellipse2d.distanceToPoint', () => {
158
+ it('is positive outside', () => {
159
+ expect(ellipse().distanceToPoint(new Vec(150, 25))).toBe(50)
160
+ expect(filled().distanceToPoint(new Vec(150, 25))).toBe(50)
161
+ })
162
+
163
+ it('is zero on a vertex', () => {
164
+ expect(ellipse().distanceToPoint(new Vec(100, 25))).toBe(0)
165
+ })
166
+
167
+ it('is negative inside only when filled or hitInside', () => {
168
+ const unfilledDist = ellipse().distanceToPoint(new Vec(50, 25))
169
+ expect(unfilledDist).toBeGreaterThan(0)
170
+ expect(filled().distanceToPoint(new Vec(50, 25))).toBe(-unfilledDist)
171
+ expect(ellipse().distanceToPoint(new Vec(50, 25), true)).toBe(-unfilledDist)
172
+ })
173
+ })
174
+
175
+ describe('Ellipse2d.hitTestPoint', () => {
176
+ it('hits the interior only when filled or hitInside', () => {
177
+ expect(filled().hitTestPoint(new Vec(50, 25))).toBe(true)
178
+ expect(ellipse().hitTestPoint(new Vec(50, 25))).toBe(false)
179
+ expect(ellipse().hitTestPoint(new Vec(50, 25), 0, true)).toBe(true)
180
+ })
181
+
182
+ it('misses points outside', () => {
183
+ expect(filled().hitTestPoint(new Vec(150, 25))).toBe(false)
184
+ expect(ellipse().hitTestPoint(new Vec(150, 25))).toBe(false)
185
+ })
186
+
187
+ it('misses the bounding box corners, which are outside the ellipse', () => {
188
+ expect(filled().hitTestPoint(new Vec(1, 1))).toBe(false)
189
+ expect(filled().hitTestPoint(new Vec(99, 49))).toBe(false)
190
+ })
191
+
192
+ it('hits the edge', () => {
193
+ expect(ellipse().hitTestPoint(new Vec(100, 25))).toBe(true)
194
+ })
195
+
196
+ it('respects the margin', () => {
197
+ expect(ellipse().hitTestPoint(new Vec(105, 25), 5)).toBe(true)
198
+ expect(ellipse().hitTestPoint(new Vec(105, 25), 4)).toBe(false)
199
+ expect(ellipse().hitTestPoint(new Vec(95, 25), 5)).toBe(true)
200
+ })
201
+ })
202
+
203
+ describe('Ellipse2d.hitTestLineSegment', () => {
204
+ it('hits a segment crossing the edge', () => {
205
+ expect(ellipse().hitTestLineSegment(new Vec(50, -10), new Vec(50, 60))).toBe(true)
206
+ expect(ellipse().hitTestLineSegment(new Vec(90, 25), new Vec(110, 25))).toBe(true)
207
+ })
208
+
209
+ it('misses a segment entirely outside', () => {
210
+ expect(ellipse().hitTestLineSegment(new Vec(150, 0), new Vec(150, 50))).toBe(false)
211
+ })
212
+
213
+ it('misses a segment entirely inside, even when filled', () => {
214
+ expect(ellipse().hitTestLineSegment(new Vec(40, 25), new Vec(60, 25))).toBe(false)
215
+ expect(filled().hitTestLineSegment(new Vec(40, 25), new Vec(60, 25))).toBe(false)
216
+ })
217
+
218
+ it('misses a segment that cuts through a bounding box corner only', () => {
219
+ expect(ellipse().hitTestLineSegment(new Vec(0, 0), new Vec(5, 5))).toBe(false)
220
+ })
221
+ })
222
+
223
+ describe('Ellipse2d.intersectLineSegment', () => {
224
+ it('returns both crossings of a horizontal line through the centre', () => {
225
+ const hits = ellipse().intersectLineSegment(new Vec(-10, 25), new Vec(110, 25))
226
+ expect(hits.length).toBe(2)
227
+ expect(hits.map((h) => h.y)).toEqual([25, 25])
228
+ const xs = hits.map((h) => h.x).sort((a, b) => a - b)
229
+ // the leftmost point is not a vertex, so the polygon edge sits slightly inside the ellipse
230
+ expect(xs[0]).toBeGreaterThanOrEqual(0)
231
+ expect(xs[0]).toBeLessThan(2)
232
+ expect(xs[1]).toBe(100)
233
+ })
234
+ })
235
+
236
+ describe('Ellipse2d.getSvgPathData', () => {
237
+ it('draws two arcs starting from the leftmost point', () => {
238
+ expect(ellipse().getSvgPathData(true)).toBe('M0,25 a50,25,0,1,1,100,0a50,25,0,1,1,-100,0')
239
+ })
240
+
241
+ it('omits the move command when not first', () => {
242
+ expect(ellipse().getSvgPathData()).toBe(' a50,25,0,1,1,100,0a50,25,0,1,1,-100,0')
243
+ expect(ellipse().getSvgPathData(false)).toBe(ellipse().getSvgPathData())
4
244
  })
5
245
  })