@tldraw/editor 3.16.0-internal.a478398270c6 → 3.16.0-internal.f8b97f0c414f

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 (325) hide show
  1. package/dist-cjs/index.d.ts +350 -142
  2. package/dist-cjs/index.js +13 -6
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +10 -8
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/SVGContainer.js +1 -1
  9. package/dist-cjs/lib/components/SVGContainer.js.map +2 -2
  10. package/dist-cjs/lib/components/Shape.js +11 -36
  11. package/dist-cjs/lib/components/Shape.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultBrush.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +15 -24
  15. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +2 -2
  17. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
  19. package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
  20. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  21. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  22. package/dist-cjs/lib/components/default-components/DefaultGrid.js +1 -1
  23. package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
  24. package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
  25. package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +2 -2
  26. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  27. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  28. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  29. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  30. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +53 -0
  31. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +7 -0
  32. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +1 -1
  33. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
  34. package/dist-cjs/lib/components/default-components/DefaultSpinner.js +27 -15
  35. package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +3 -3
  36. package/dist-cjs/lib/config/TLUserPreferences.js +15 -3
  37. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  38. package/dist-cjs/lib/editor/Editor.js +174 -180
  39. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  40. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +4 -0
  41. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
  42. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  43. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +14 -4
  44. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  45. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  46. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +23 -0
  47. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  48. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  49. package/dist-cjs/lib/editor/tools/StateNode.js +20 -1
  50. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  51. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  52. package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
  53. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  54. package/dist-cjs/lib/hooks/useCanvasEvents.js +44 -35
  55. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  56. package/dist-cjs/lib/hooks/useDocumentEvents.js +5 -5
  57. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  58. package/dist-cjs/lib/hooks/useEditor.js +1 -4
  59. package/dist-cjs/lib/hooks/useEditor.js.map +2 -2
  60. package/dist-cjs/lib/hooks/useEditorComponents.js +2 -0
  61. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  62. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -2
  63. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  64. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  65. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  66. package/dist-cjs/lib/hooks/useHandleEvents.js +3 -3
  67. package/dist-cjs/lib/hooks/useHandleEvents.js.map +2 -2
  68. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
  69. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  70. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  71. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  72. package/dist-cjs/lib/hooks/useSelectionEvents.js +4 -4
  73. package/dist-cjs/lib/hooks/useSelectionEvents.js.map +2 -2
  74. package/dist-cjs/lib/{utils/nearestMultiple.js → hooks/useStateAttribute.js} +15 -14
  75. package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
  76. package/dist-cjs/lib/license/LicenseManager.js +140 -53
  77. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  78. package/dist-cjs/lib/license/LicenseProvider.js +39 -1
  79. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  80. package/dist-cjs/lib/license/Watermark.js +75 -13
  81. package/dist-cjs/lib/license/Watermark.js.map +3 -3
  82. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  83. package/dist-cjs/lib/options.js +7 -0
  84. package/dist-cjs/lib/options.js.map +2 -2
  85. package/dist-cjs/lib/primitives/Box.js +3 -0
  86. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  87. package/dist-cjs/lib/primitives/Vec.js +0 -4
  88. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  89. package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
  90. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  91. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
  92. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  93. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +3 -1
  94. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  95. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
  96. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  97. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +50 -20
  98. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  99. package/dist-cjs/lib/primitives/geometry/Group2d.js +8 -1
  100. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  101. package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
  102. package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
  103. package/dist-cjs/lib/primitives/intersect.js +4 -4
  104. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  105. package/dist-cjs/lib/primitives/utils.js +4 -0
  106. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  107. package/dist-cjs/lib/utils/EditorAtom.js +45 -0
  108. package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
  109. package/dist-cjs/lib/utils/dom.js +12 -1
  110. package/dist-cjs/lib/utils/dom.js.map +2 -2
  111. package/dist-cjs/lib/utils/getPointerInfo.js +2 -2
  112. package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
  113. package/dist-cjs/lib/utils/reparenting.js +2 -35
  114. package/dist-cjs/lib/utils/reparenting.js.map +3 -3
  115. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +0 -1
  116. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  117. package/dist-cjs/version.js +3 -3
  118. package/dist-cjs/version.js.map +1 -1
  119. package/dist-esm/index.d.mts +350 -142
  120. package/dist-esm/index.mjs +24 -8
  121. package/dist-esm/index.mjs.map +2 -2
  122. package/dist-esm/lib/TldrawEditor.mjs +11 -9
  123. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  124. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  125. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  126. package/dist-esm/lib/components/SVGContainer.mjs +1 -1
  127. package/dist-esm/lib/components/SVGContainer.mjs.map +2 -2
  128. package/dist-esm/lib/components/Shape.mjs +11 -36
  129. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  130. package/dist-esm/lib/components/default-components/DefaultBrush.mjs +1 -1
  131. package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
  132. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +16 -25
  133. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  134. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +2 -2
  135. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
  136. package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
  137. package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
  138. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  139. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  140. package/dist-esm/lib/components/default-components/DefaultGrid.mjs +1 -1
  141. package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
  142. package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
  143. package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +2 -2
  144. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  145. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  146. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  147. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  148. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +23 -0
  149. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +7 -0
  150. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +1 -1
  151. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
  152. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +17 -15
  153. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
  154. package/dist-esm/lib/config/TLUserPreferences.mjs +15 -3
  155. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  156. package/dist-esm/lib/editor/Editor.mjs +174 -180
  157. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  158. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +4 -0
  159. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
  160. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  161. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +14 -4
  162. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  163. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  164. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +23 -0
  165. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  166. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  167. package/dist-esm/lib/editor/tools/StateNode.mjs +20 -1
  168. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  169. package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
  170. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  171. package/dist-esm/lib/hooks/useCanvasEvents.mjs +47 -37
  172. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  173. package/dist-esm/lib/hooks/useDocumentEvents.mjs +11 -6
  174. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  175. package/dist-esm/lib/hooks/useEditor.mjs +1 -4
  176. package/dist-esm/lib/hooks/useEditor.mjs.map +2 -2
  177. package/dist-esm/lib/hooks/useEditorComponents.mjs +4 -0
  178. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  179. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +2 -3
  180. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  181. package/dist-esm/lib/hooks/useGestureEvents.mjs +2 -2
  182. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  183. package/dist-esm/lib/hooks/useHandleEvents.mjs +9 -4
  184. package/dist-esm/lib/hooks/useHandleEvents.mjs.map +2 -2
  185. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
  186. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  187. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  188. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  189. package/dist-esm/lib/hooks/useSelectionEvents.mjs +6 -5
  190. package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +2 -2
  191. package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
  192. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
  193. package/dist-esm/lib/license/LicenseManager.mjs +141 -54
  194. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  195. package/dist-esm/lib/license/LicenseProvider.mjs +39 -2
  196. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  197. package/dist-esm/lib/license/Watermark.mjs +76 -14
  198. package/dist-esm/lib/license/Watermark.mjs.map +3 -3
  199. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  200. package/dist-esm/lib/options.mjs +7 -0
  201. package/dist-esm/lib/options.mjs.map +2 -2
  202. package/dist-esm/lib/primitives/Box.mjs +4 -1
  203. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  204. package/dist-esm/lib/primitives/Vec.mjs +0 -4
  205. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  206. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  207. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  208. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
  209. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  210. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +3 -1
  211. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  212. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
  213. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  214. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +53 -21
  215. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  216. package/dist-esm/lib/primitives/geometry/Group2d.mjs +8 -1
  217. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  218. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
  219. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
  220. package/dist-esm/lib/primitives/intersect.mjs +5 -5
  221. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  222. package/dist-esm/lib/primitives/utils.mjs +4 -0
  223. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  224. package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
  225. package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
  226. package/dist-esm/lib/utils/dom.mjs +12 -1
  227. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  228. package/dist-esm/lib/utils/getPointerInfo.mjs +2 -2
  229. package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
  230. package/dist-esm/lib/utils/reparenting.mjs +3 -40
  231. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  232. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +0 -1
  233. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  234. package/dist-esm/version.mjs +3 -3
  235. package/dist-esm/version.mjs.map +1 -1
  236. package/editor.css +327 -315
  237. package/package.json +16 -38
  238. package/src/index.ts +19 -10
  239. package/src/lib/TldrawEditor.tsx +16 -21
  240. package/src/lib/components/MenuClickCapture.tsx +0 -8
  241. package/src/lib/components/SVGContainer.tsx +1 -1
  242. package/src/lib/components/Shape.tsx +12 -33
  243. package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
  244. package/src/lib/components/default-components/DefaultCanvas.tsx +13 -24
  245. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +2 -2
  246. package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
  247. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  248. package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
  249. package/src/lib/components/default-components/DefaultHandles.tsx +5 -1
  250. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  251. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +6 -2
  252. package/src/lib/components/default-components/DefaultShapeWrapper.tsx +35 -0
  253. package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
  254. package/src/lib/components/default-components/DefaultSpinner.tsx +12 -12
  255. package/src/lib/config/TLUserPreferences.ts +15 -1
  256. package/src/lib/editor/Editor.test.ts +512 -8
  257. package/src/lib/editor/Editor.ts +252 -267
  258. package/src/lib/editor/derivations/notVisibleShapes.ts +6 -0
  259. package/src/lib/editor/derivations/parentsToChildren.ts +1 -1
  260. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  261. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  262. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  263. package/src/lib/editor/managers/FontManager/FontManager.test.ts +38 -27
  264. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  265. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  266. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  267. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  268. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  269. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +55 -26
  270. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +14 -1
  271. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  272. package/src/lib/editor/shapes/ShapeUtil.ts +108 -8
  273. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
  274. package/src/lib/editor/tools/StateNode.test.ts +285 -0
  275. package/src/lib/editor/tools/StateNode.ts +27 -1
  276. package/src/lib/editor/types/misc-types.ts +73 -7
  277. package/src/lib/exports/getSvgJsx.test.ts +874 -0
  278. package/src/lib/exports/getSvgJsx.tsx +78 -21
  279. package/src/lib/hooks/useCanvasEvents.ts +60 -47
  280. package/src/lib/hooks/useDocumentEvents.ts +11 -6
  281. package/src/lib/hooks/useEditor.tsx +6 -5
  282. package/src/lib/hooks/useEditorComponents.tsx +8 -2
  283. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +2 -2
  284. package/src/lib/hooks/useGestureEvents.ts +2 -2
  285. package/src/lib/hooks/useHandleEvents.ts +9 -4
  286. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
  287. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  288. package/src/lib/hooks/useSelectionEvents.ts +6 -5
  289. package/src/lib/hooks/useStateAttribute.ts +15 -0
  290. package/src/lib/license/LicenseManager.test.ts +724 -383
  291. package/src/lib/license/LicenseManager.ts +201 -58
  292. package/src/lib/license/LicenseProvider.tsx +74 -2
  293. package/src/lib/license/Watermark.test.tsx +2 -1
  294. package/src/lib/license/Watermark.tsx +81 -14
  295. package/src/lib/license/useLicenseManagerState.ts +2 -2
  296. package/src/lib/options.ts +8 -0
  297. package/src/lib/primitives/Box.test.ts +126 -0
  298. package/src/lib/primitives/Box.ts +10 -1
  299. package/src/lib/primitives/Vec.ts +0 -5
  300. package/src/lib/primitives/geometry/Arc2d.ts +2 -2
  301. package/src/lib/primitives/geometry/Circle2d.ts +2 -2
  302. package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -1
  303. package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
  304. package/src/lib/primitives/geometry/Geometry2d.test.ts +420 -0
  305. package/src/lib/primitives/geometry/Geometry2d.ts +78 -21
  306. package/src/lib/primitives/geometry/Group2d.ts +10 -1
  307. package/src/lib/primitives/geometry/geometry-constants.ts +2 -1
  308. package/src/lib/primitives/intersect.test.ts +946 -0
  309. package/src/lib/primitives/intersect.ts +12 -5
  310. package/src/lib/primitives/utils.ts +11 -0
  311. package/src/lib/test/InFrontOfTheCanvas.test.tsx +187 -0
  312. package/src/lib/utils/EditorAtom.ts +37 -0
  313. package/src/lib/utils/dom.test.ts +94 -0
  314. package/src/lib/utils/dom.ts +38 -1
  315. package/src/lib/utils/getPointerInfo.ts +2 -1
  316. package/src/lib/utils/reparenting.ts +3 -69
  317. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  318. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  319. package/src/lib/utils/sync/TLLocalSyncClient.ts +0 -1
  320. package/src/version.ts +3 -3
  321. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  322. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  323. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  324. package/src/lib/test/currentToolIdMask.test.ts +0 -49
  325. package/src/lib/utils/nearestMultiple.ts +0 -13
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/primitives/intersect.ts"],
4
- "sourcesContent": ["import { Box } from './Box'\nimport { pointInPolygon } from './utils'\nimport { Vec, VecLike } from './Vec'\n\n// need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52\n\n/**\n * Find the intersection between a line segment and a line segment.\n *\n * @param a1 - The first segment's first point.\n * @param a2 - The first segment's second point.\n * @param b1 - The second segment's first point.\n * @param b2 - The second segment's second point.\n * @public\n */\nexport function intersectLineSegmentLineSegment(\n\ta1: VecLike,\n\ta2: VecLike,\n\tb1: VecLike,\n\tb2: VecLike\n) {\n\tconst ABx = a1.x - b1.x\n\tconst ABy = a1.y - b1.y\n\tconst BVx = b2.x - b1.x\n\tconst BVy = b2.y - b1.y\n\tconst AVx = a2.x - a1.x\n\tconst AVy = a2.y - a1.y\n\tconst ua_t = BVx * ABy - BVy * ABx\n\tconst ub_t = AVx * ABy - AVy * ABx\n\tconst u_b = BVy * AVx - BVx * AVy\n\n\tif (ua_t === 0 || ub_t === 0) return null // coincident\n\n\tif (u_b === 0) return null // parallel\n\n\tif (u_b !== 0) {\n\t\tconst ua = ua_t / u_b\n\t\tconst ub = ub_t / u_b\n\t\tif (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n\t\t\treturn Vec.AddXY(a1, ua * AVx, ua * AVy)\n\t\t}\n\t}\n\n\treturn null // no intersection\n}\n\n/**\n * Find the intersections between a line segment and a circle.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @public\n */\nexport function intersectLineSegmentCircle(a1: VecLike, a2: VecLike, c: VecLike, r: number) {\n\tconst a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y)\n\tconst b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y))\n\tconst cc =\n\t\tc.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r\n\tconst deter = b * b - 4 * a * cc\n\n\tif (deter < 0) return null // outside\n\tif (deter === 0) return null // tangent\n\n\tconst e = Math.sqrt(deter)\n\tconst u1 = (-b + e) / (2 * a)\n\tconst u2 = (-b - e) / (2 * a)\n\n\tif ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {\n\t\treturn null // outside or inside\n\t\t// if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {\n\t\t// \treturn null // outside\n\t\t// } else return null // inside'\n\t}\n\n\tconst result: VecLike[] = []\n\n\tif (0 <= u1 && u1 <= 1) result.push(Vec.Lrp(a1, a2, u1))\n\tif (0 <= u2 && u2 <= 1) result.push(Vec.Lrp(a1, a2, u2))\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a polyline.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectLineSegmentPolyline(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 0, n = points.length - 1; i < n; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(a1, a2, points[i], points[i + 1])\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a closed polygon.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectLineSegmentPolygon(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 1, n = points.length; i < n + 1; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(\n\t\t\ta1,\n\t\t\ta2,\n\t\t\tpoints[i - 1],\n\t\t\tpoints[i % points.length]\n\t\t)\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a circle.\n *\n * @param c1 - The first circle's center.\n * @param r1 - The first circle's radius.\n * @param c2 - The second circle's center.\n * @param r2 - The second circle's radius.\n * @public\n */\nexport function intersectCircleCircle(c1: VecLike, r1: number, c2: VecLike, r2: number) {\n\tlet dx = c2.x - c1.x\n\tlet dy = c2.y - c1.y\n\tconst d = Math.sqrt(dx * dx + dy * dy),\n\t\tx = (d * d - r2 * r2 + r1 * r1) / (2 * d),\n\t\ty = Math.sqrt(r1 * r1 - x * x)\n\tdx /= d\n\tdy /= d\n\treturn [\n\t\tnew Vec(c1.x + dx * x - dy * y, c1.y + dy * x + dx * y),\n\t\tnew Vec(c1.x + dx * x + dy * y, c1.y + dy * x - dx * y),\n\t]\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectCirclePolygon(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\ta = points[i]\n\t\tb = points[(i + 1) % points.length]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectCirclePolyline(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 1, n = points.length; i < n; i++) {\n\t\ta = points[i - 1]\n\t\tb = points[i]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a polygon and a bounding box.\n *\n * @public\n */\nexport function intersectPolygonBounds(points: VecLike[], bounds: Box) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike[] | null\n\n\tfor (const side of bounds.sides) {\n\t\tsegmentIntersection = intersectLineSegmentPolygon(side[0], side[1], points)\n\t\tif (segmentIntersection) result.push(...segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\nfunction ccw(A: VecLike, B: VecLike, C: VecLike) {\n\treturn (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x)\n}\n\n/** @public */\nexport function linesIntersect(A: VecLike, B: VecLike, C: VecLike, D: VecLike) {\n\treturn ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D)\n}\n\n/**\n * Create a new convex polygon as the intersection of two convex polygons.\n *\n * @param polygonA - An array of points representing the first polygon.\n * @param polygonB - An array of points representing the second polygon.\n * @public\n */\nexport function intersectPolygonPolygon(\n\tpolygonA: VecLike[],\n\tpolygonB: VecLike[]\n): VecLike[] | null {\n\t// Create an empty polygon as result\n\tconst result: Map<string, VecLike> = new Map()\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\n\t// Add all corners of PolygonA that is inside PolygonB to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tif (pointInPolygon(a, polygonB)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\t// Add all corners of PolygonB that is inside PolygonA to result\n\tfor (let i = 0, n = polygonB.length; i < n; i++) {\n\t\ta = polygonB[i]\n\t\tif (pointInPolygon(a, polygonA)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tb = polygonA[(i + 1) % polygonA.length]\n\n\t\tfor (let j = 0, m = polygonB.length; j < m; j++) {\n\t\t\tc = polygonB[j]\n\t\t\td = polygonB[(j + 1) % polygonB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(a, b, c, d)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (result.size === 0) return null // no intersection\n\n\t// Order all points in the result counter-clockwise.\n\treturn orderClockwise([...result.values()])\n}\n\n/**\n * Find all the points where `polyA` and `polyB` intersect and returns them in an undefined order.\n * To find the polygon that's the intersection of polyA and polyB, use `intersectPolygonPolygon`\n * instead, which orders the points and includes internal points.\n *\n * @param polyA - The first polygon.\n * @param polyB - The second polygon.\n * @param isAClosed - Whether `polyA` is a closed polygon or a polyline.\n * @param isBClosed - Whether `polyB` is a closed polygon or a polyline.\n * @public\n */\nexport function intersectPolys(\n\tpolyA: VecLike[],\n\tpolyB: VecLike[],\n\tisAClosed: boolean,\n\tisBClosed: boolean\n): VecLike[] {\n\tconst result: Map<string, VecLike> = new Map()\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {\n\t\tconst currentA = polyA[i]\n\t\tconst nextA = polyA[(i + 1) % polyA.length]\n\n\t\tfor (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {\n\t\t\tconst currentB = polyB[j]\n\t\t\tconst nextB = polyB[(j + 1) % polyB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn [...result.values()]\n}\n\nfunction getPointId(point: VecLike) {\n\treturn `${point.x},${point.y}`\n}\n\nfunction orderClockwise(points: VecLike[]): VecLike[] {\n\tconst C = Vec.Average(points)\n\treturn points.sort((A, B) => Vec.Angle(C, A) - Vec.Angle(C, B))\n}\n\n/** @public */\nexport function polygonsIntersect(a: VecLike[], b: VecLike[]) {\n\tlet a0: VecLike, a1: VecLike, b0: VecLike, b1: VecLike\n\tfor (let i = 0, n = a.length; i < n; i++) {\n\t\ta0 = a[i]\n\t\ta1 = a[(i + 1) % n]\n\t\tfor (let j = 0, m = b.length; j < m; j++) {\n\t\t\tb0 = b[j]\n\t\t\tb1 = b[(j + 1) % m]\n\t\t\tif (linesIntersect(a0, a1, b0, b1)) return true\n\t\t}\n\t}\n\treturn false\n}\n\n/** @public */\nexport function polygonIntersectsPolyline(polygon: VecLike[], polyline: VecLike[]) {\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\tfor (let i = 0, n = polygon.length; i < n; i++) {\n\t\ta = polygon[i]\n\t\tb = polygon[(i + 1) % n]\n\n\t\tfor (let j = 1, m = polyline.length; j < m; j++) {\n\t\t\tc = polyline[j - 1]\n\t\t\td = polyline[j]\n\t\t\tif (linesIntersect(a, b, c, d)) return true\n\t\t}\n\t}\n\treturn false\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box } from './Box'\nimport { approximately, approximatelyLte, pointInPolygon } from './utils'\nimport { Vec, VecLike } from './Vec'\n\n// need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52\n\n/**\n * Find the intersection between a line segment and a line segment.\n *\n * @param a1 - The first segment's first point.\n * @param a2 - The first segment's second point.\n * @param b1 - The second segment's first point.\n * @param b2 - The second segment's second point.\n * @public\n */\nexport function intersectLineSegmentLineSegment(\n\ta1: VecLike,\n\ta2: VecLike,\n\tb1: VecLike,\n\tb2: VecLike,\n\tprecision = 1e-10\n) {\n\tconst ABx = a1.x - b1.x\n\tconst ABy = a1.y - b1.y\n\tconst BVx = b2.x - b1.x\n\tconst BVy = b2.y - b1.y\n\tconst AVx = a2.x - a1.x\n\tconst AVy = a2.y - a1.y\n\tconst ua_t = BVx * ABy - BVy * ABx\n\tconst ub_t = AVx * ABy - AVy * ABx\n\tconst u_b = BVy * AVx - BVx * AVy\n\n\tif (approximately(ua_t, 0, precision) || approximately(ub_t, 0, precision)) return null // coincident\n\n\tif (approximately(u_b, 0, precision)) return null // parallel\n\n\tif (u_b !== 0) {\n\t\tconst ua = ua_t / u_b\n\t\tconst ub = ub_t / u_b\n\t\tif (\n\t\t\tapproximatelyLte(0, ua, precision) &&\n\t\t\tapproximatelyLte(ua, 1, precision) &&\n\t\t\tapproximatelyLte(0, ub, precision) &&\n\t\t\tapproximatelyLte(ub, 1, precision)\n\t\t) {\n\t\t\treturn Vec.AddXY(a1, ua * AVx, ua * AVy)\n\t\t}\n\t}\n\n\treturn null // no intersection\n}\n\n/**\n * Find the intersections between a line segment and a circle.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @public\n */\nexport function intersectLineSegmentCircle(a1: VecLike, a2: VecLike, c: VecLike, r: number) {\n\tconst a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y)\n\tconst b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y))\n\tconst cc =\n\t\tc.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r\n\tconst deter = b * b - 4 * a * cc\n\n\tif (deter < 0) return null // outside\n\tif (deter === 0) return null // tangent\n\n\tconst e = Math.sqrt(deter)\n\tconst u1 = (-b + e) / (2 * a)\n\tconst u2 = (-b - e) / (2 * a)\n\n\tif ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {\n\t\treturn null // outside or inside\n\t\t// if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {\n\t\t// \treturn null // outside\n\t\t// } else return null // inside'\n\t}\n\n\tconst result: VecLike[] = []\n\n\tif (0 <= u1 && u1 <= 1) result.push(Vec.Lrp(a1, a2, u1))\n\tif (0 <= u2 && u2 <= 1) result.push(Vec.Lrp(a1, a2, u2))\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a polyline.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectLineSegmentPolyline(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 0, n = points.length - 1; i < n; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(a1, a2, points[i], points[i + 1])\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a closed polygon.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectLineSegmentPolygon(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 1, n = points.length; i < n + 1; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(\n\t\t\ta1,\n\t\t\ta2,\n\t\t\tpoints[i - 1],\n\t\t\tpoints[i % points.length]\n\t\t)\n\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a circle.\n *\n * @param c1 - The first circle's center.\n * @param r1 - The first circle's radius.\n * @param c2 - The second circle's center.\n * @param r2 - The second circle's radius.\n * @public\n */\nexport function intersectCircleCircle(c1: VecLike, r1: number, c2: VecLike, r2: number) {\n\tlet dx = c2.x - c1.x\n\tlet dy = c2.y - c1.y\n\tconst d = Math.sqrt(dx * dx + dy * dy),\n\t\tx = (d * d - r2 * r2 + r1 * r1) / (2 * d),\n\t\ty = Math.sqrt(r1 * r1 - x * x)\n\tdx /= d\n\tdy /= d\n\treturn [\n\t\tnew Vec(c1.x + dx * x - dy * y, c1.y + dy * x + dx * y),\n\t\tnew Vec(c1.x + dx * x + dy * y, c1.y + dy * x - dx * y),\n\t]\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectCirclePolygon(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\ta = points[i]\n\t\tb = points[(i + 1) % points.length]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectCirclePolyline(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 1, n = points.length; i < n; i++) {\n\t\ta = points[i - 1]\n\t\tb = points[i]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a polygon and a bounding box.\n *\n * @public\n */\nexport function intersectPolygonBounds(points: VecLike[], bounds: Box) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike[] | null\n\n\tfor (const side of bounds.sides) {\n\t\tsegmentIntersection = intersectLineSegmentPolygon(side[0], side[1], points)\n\t\tif (segmentIntersection) result.push(...segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\nfunction ccw(A: VecLike, B: VecLike, C: VecLike) {\n\treturn (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x)\n}\n\n/** @public */\nexport function linesIntersect(A: VecLike, B: VecLike, C: VecLike, D: VecLike) {\n\treturn ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D)\n}\n\n/**\n * Create a new convex polygon as the intersection of two convex polygons.\n *\n * @param polygonA - An array of points representing the first polygon.\n * @param polygonB - An array of points representing the second polygon.\n * @public\n */\nexport function intersectPolygonPolygon(\n\tpolygonA: VecLike[],\n\tpolygonB: VecLike[]\n): VecLike[] | null {\n\t// Create an empty polygon as result\n\tconst result: Map<string, VecLike> = new Map()\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\n\t// Add all corners of PolygonA that is inside PolygonB to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tif (pointInPolygon(a, polygonB)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\t// Add all corners of PolygonB that is inside PolygonA to result\n\tfor (let i = 0, n = polygonB.length; i < n; i++) {\n\t\ta = polygonB[i]\n\t\tif (pointInPolygon(a, polygonA)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tb = polygonA[(i + 1) % polygonA.length]\n\n\t\tfor (let j = 0, m = polygonB.length; j < m; j++) {\n\t\t\tc = polygonB[j]\n\t\t\td = polygonB[(j + 1) % polygonB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(a, b, c, d)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (result.size === 0) return null // no intersection\n\n\t// Order all points in the result counter-clockwise.\n\treturn orderClockwise([...result.values()])\n}\n\n/**\n * Find all the points where `polyA` and `polyB` intersect and returns them in an undefined order.\n * To find the polygon that's the intersection of polyA and polyB, use `intersectPolygonPolygon`\n * instead, which orders the points and includes internal points.\n *\n * @param polyA - The first polygon.\n * @param polyB - The second polygon.\n * @param isAClosed - Whether `polyA` is a closed polygon or a polyline.\n * @param isBClosed - Whether `polyB` is a closed polygon or a polyline.\n * @public\n */\nexport function intersectPolys(\n\tpolyA: VecLike[],\n\tpolyB: VecLike[],\n\tisAClosed: boolean,\n\tisBClosed: boolean\n): VecLike[] {\n\tconst result: Map<string, VecLike> = new Map()\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {\n\t\tconst currentA = polyA[i]\n\t\tconst nextA = polyA[(i + 1) % polyA.length]\n\n\t\tfor (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {\n\t\t\tconst currentB = polyB[j]\n\t\t\tconst nextB = polyB[(j + 1) % polyB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn [...result.values()]\n}\n\nfunction getPointId(point: VecLike) {\n\treturn `${point.x},${point.y}`\n}\n\nfunction orderClockwise(points: VecLike[]): VecLike[] {\n\tconst C = Vec.Average(points)\n\treturn points.sort((A, B) => Vec.Angle(C, A) - Vec.Angle(C, B))\n}\n\n/** @public */\nexport function polygonsIntersect(a: VecLike[], b: VecLike[]) {\n\tlet a0: VecLike, a1: VecLike, b0: VecLike, b1: VecLike\n\tfor (let i = 0, n = a.length; i < n; i++) {\n\t\ta0 = a[i]\n\t\ta1 = a[(i + 1) % n]\n\t\tfor (let j = 0, m = b.length; j < m; j++) {\n\t\t\tb0 = b[j]\n\t\t\tb1 = b[(j + 1) % m]\n\t\t\tif (linesIntersect(a0, a1, b0, b1)) return true\n\t\t}\n\t}\n\treturn false\n}\n\n/** @public */\nexport function polygonIntersectsPolyline(polygon: VecLike[], polyline: VecLike[]) {\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\tfor (let i = 0, n = polygon.length; i < n; i++) {\n\t\ta = polygon[i]\n\t\tb = polygon[(i + 1) % n]\n\n\t\tfor (let j = 1, m = polyline.length; j < m; j++) {\n\t\t\tc = polyline[j - 1]\n\t\t\td = polyline[j]\n\t\t\tif (linesIntersect(a, b, c, d)) return true\n\t\t}\n\t}\n\treturn false\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -19,6 +19,9 @@ function toPrecision(n, precision = 1e10) {
19
19
  function approximately(a, b, precision = 1e-6) {
20
20
  return Math.abs(a - b) <= precision;
21
21
  }
22
+ function approximatelyLte(a, b, precision = 1e-6) {
23
+ return a < b || approximately(a, b, precision);
24
+ }
22
25
  function perimeterOfEllipse(rx, ry) {
23
26
  const h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2);
24
27
  return PI * (rx + ry) * (1 + 3 * h / (10 + Math.sqrt(4 - 3 * h)));
@@ -203,6 +206,7 @@ export {
203
206
  SIN,
204
207
  angleDistance,
205
208
  approximately,
209
+ approximatelyLte,
206
210
  areAnglesCompatible,
207
211
  average,
208
212
  canonicalizeRotation,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/primitives/utils.ts"],
4
- "sourcesContent": ["import { Vec, VecLike } from './Vec'\n\n/** @public */\nexport function precise(A: VecLike) {\n\treturn `${toDomPrecision(A.x)},${toDomPrecision(A.y)} `\n}\n\n/** @public */\nexport function average(A: VecLike, B: VecLike) {\n\treturn `${toDomPrecision((A.x + B.x) / 2)},${toDomPrecision((A.y + B.y) / 2)} `\n}\n\n/** @public */\nexport const PI = Math.PI\n/** @public */\nexport const HALF_PI = PI / 2\n/** @public */\nexport const PI2 = PI * 2\n/** @public */\nexport const SIN = Math.sin\n\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1) // 1\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @public\n */\nexport function clamp(n: number, min: number): number\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1, 10) // 1\n * const B = clamp(11, 1, 10) // 10\n * const C = clamp(5, 1, 10) // 5\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @param max - The maximum value.\n * @public\n */\nexport function clamp(n: number, min: number, max: number): number\nexport function clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\n/**\n * Get a number to a precision.\n *\n * @param n - The number.\n * @param precision - The precision.\n * @public\n */\nexport function toPrecision(n: number, precision = 10000000000) {\n\tif (!n) return 0\n\treturn Math.round(n * precision) / precision\n}\n\n/**\n * Whether two numbers numbers a and b are approximately equal.\n *\n * @param a - The first point.\n * @param b - The second point.\n * @public\n */\nexport function approximately(a: number, b: number, precision = 0.000001) {\n\treturn Math.abs(a - b) <= precision\n}\n\n/**\n * Find the approximate perimeter of an ellipse.\n *\n * @param rx - The ellipse's x radius.\n * @param ry - The ellipse's y radius.\n * @public\n */\nexport function perimeterOfEllipse(rx: number, ry: number): number {\n\tconst h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2)\n\treturn PI * (rx + ry) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)))\n}\n\n/**\n * @param a - Any angle in radians\n * @returns A number between 0 and 2 * PI\n * @public\n */\nexport function canonicalizeRotation(a: number) {\n\ta = a % PI2\n\tif (a < 0) {\n\t\ta = a + PI2\n\t} else if (a === 0) {\n\t\t// prevent negative zero\n\t\ta = 0\n\t}\n\treturn a\n}\n\n/**\n * Get the clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function clockwiseAngleDist(a0: number, a1: number): number {\n\ta0 = canonicalizeRotation(a0)\n\ta1 = canonicalizeRotation(a1)\n\tif (a0 > a1) {\n\t\ta1 += PI2\n\t}\n\treturn a1 - a0\n}\n\n/**\n * Get the counter-clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function counterClockwiseAngleDist(a0: number, a1: number): number {\n\treturn PI2 - clockwiseAngleDist(a0, a1)\n}\n\n/**\n * Get the short angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function shortAngleDist(a0: number, a1: number): number {\n\tconst da = (a1 - a0) % PI2\n\treturn ((2 * da) % PI2) - da\n}\n\n/**\n * Clamp radians within 0 and 2PI\n *\n * @param r - The radian value.\n * @public\n */\nexport function clampRadians(r: number): number {\n\treturn (PI2 + r) % PI2\n}\n\n/**\n * Clamp rotation to even segments.\n *\n * @param r - The rotation in radians.\n * @param segments - The number of segments.\n * @public\n */\nexport function snapAngle(r: number, segments: number): number {\n\tconst seg = PI2 / segments\n\tlet ang = (Math.floor((clampRadians(r) + seg / 2) / seg) * seg) % PI2\n\tif (ang < PI) ang += PI2\n\tif (ang > PI) ang -= PI2\n\treturn ang\n}\n\n/**\n * Checks whether two angles are approximately at right-angles or parallel to each other\n *\n * @param a - Angle a (radians)\n * @param b - Angle b (radians)\n * @returns True iff the angles are approximately at right-angles or parallel to each other\n * @public\n */\nexport function areAnglesCompatible(a: number, b: number) {\n\treturn a === b || approximately((a % (Math.PI / 2)) - (b % (Math.PI / 2)), 0)\n}\n\n/**\n * Convert degrees to radians.\n *\n * @param d - The degree in degrees.\n * @public\n */\nexport function degreesToRadians(d: number): number {\n\treturn (d * PI) / 180\n}\n\n/**\n * Convert radians to degrees.\n *\n * @param r - The degree in radians.\n * @public\n */\nexport function radiansToDegrees(r: number): number {\n\treturn (r * 180) / PI\n}\n\n/**\n * Get a point on the perimeter of a circle.\n *\n * @param center - The center of the circle.\n * @param r - The radius of the circle.\n * @param a - The angle in radians.\n * @public\n */\nexport function getPointOnCircle(center: VecLike, r: number, a: number) {\n\treturn new Vec(center.x, center.y).add(Vec.FromAngle(a, r))\n}\n\n/** @public */\nexport function getPolygonVertices(width: number, height: number, sides: number) {\n\tconst cx = width / 2\n\tconst cy = height / 2\n\tconst pointsOnPerimeter: Vec[] = []\n\n\tlet minX = Infinity\n\tlet maxX = -Infinity\n\tlet minY = Infinity\n\tlet maxY = -Infinity\n\tfor (let i = 0; i < sides; i++) {\n\t\tconst step = PI2 / sides\n\t\tconst t = -HALF_PI + i * step\n\t\tconst x = cx + cx * Math.cos(t)\n\t\tconst y = cy + cy * Math.sin(t)\n\t\tif (x < minX) minX = x\n\t\tif (y < minY) minY = y\n\t\tif (x > maxX) maxX = x\n\t\tif (y > maxY) maxY = y\n\t\tpointsOnPerimeter.push(new Vec(x, y))\n\t}\n\n\t// Bounds of calculated points\n\tconst w = maxX - minX\n\tconst h = maxY - minY\n\n\t// Difference between input bounds and calculated bounds\n\tconst dx = width - w\n\tconst dy = height - h\n\n\t// If there's a difference, scale the points to the input bounds\n\tif (dx !== 0 || dy !== 0) {\n\t\tfor (let i = 0; i < pointsOnPerimeter.length; i++) {\n\t\t\tconst pt = pointsOnPerimeter[i]\n\t\t\tpt.x = ((pt.x - minX) / w) * width\n\t\t\tpt.y = ((pt.y - minY) / h) * height\n\t\t}\n\t}\n\n\treturn pointsOnPerimeter\n}\n\n/**\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns True if the ranges overlap\n * @public\n */\nexport function rangesOverlap(a0: number, a1: number, b0: number, b1: number): boolean {\n\treturn a0 < b1 && b0 < a1\n}\n\n/**\n * Finds the intersection of two ranges.\n *\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns The intersection of the ranges, or null if no intersection\n * @public\n */\nexport function rangeIntersection(\n\ta0: number,\n\ta1: number,\n\tb0: number,\n\tb1: number\n): [number, number] | null {\n\tconst min = Math.max(a0, b0)\n\tconst max = Math.min(a1, b1)\n\tif (min <= max) {\n\t\treturn [min, max]\n\t}\n\treturn null\n}\n\n/** Helper for point in polygon */\nfunction cross(x: VecLike, y: VecLike, z: VecLike): number {\n\treturn (y.x - x.x) * (z.y - x.y) - (z.x - x.x) * (y.y - x.y)\n}\n\n/**\n * Get whether a point is inside of a polygon.\n *\n * ```ts\n * const result = pointInPolygon(myPoint, myPoints)\n * ```\n *\n * @public\n */\nexport function pointInPolygon(A: VecLike, points: VecLike[]): boolean {\n\tlet windingNumber = 0\n\tlet a: VecLike\n\tlet b: VecLike\n\n\tfor (let i = 0; i < points.length; i++) {\n\t\ta = points[i]\n\t\t// Point is the same as one of the corners of the polygon\n\t\tif (a.x === A.x && a.y === A.y) return true\n\n\t\tb = points[(i + 1) % points.length]\n\n\t\t// Point is on the polygon edge\n\t\tif (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true\n\n\t\tif (a.y <= A.y) {\n\t\t\tif (b.y > A.y && cross(a, b, A) > 0) {\n\t\t\t\twindingNumber += 1\n\t\t\t}\n\t\t} else if (b.y <= A.y && cross(a, b, A) < 0) {\n\t\t\twindingNumber -= 1\n\t\t}\n\t}\n\n\treturn windingNumber !== 0\n}\n\n/**\n * The DOM likes values to be fixed to 3 decimal places\n *\n * @public\n */\nexport function toDomPrecision(v: number) {\n\treturn Math.round(v * 1e4) / 1e4\n}\n\n/**\n * @public\n */\nexport function toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/**\n * Check if a float is safe to use. ie: Not too big or small.\n * @public\n */\nexport const isSafeFloat = (n: number) => {\n\treturn Math.abs(n) < Number.MAX_SAFE_INTEGER\n}\n\n/**\n * Get the angle of a point on an arc.\n * @param fromAngle - The angle from center to arc's start point (A) on the circle\n * @param toAngle - The angle from center to arc's end point (B) on the circle\n * @param direction - The direction of the arc (1 = counter-clockwise, -1 = clockwise)\n * @returns The distance in radians between the two angles according to the direction\n * @public\n */\nexport function angleDistance(fromAngle: number, toAngle: number, direction: number) {\n\tconst dist =\n\t\tdirection < 0\n\t\t\t? clockwiseAngleDist(fromAngle, toAngle)\n\t\t\t: counterClockwiseAngleDist(fromAngle, toAngle)\n\treturn dist\n}\n\n/**\n * Returns the t value of the point on the arc.\n *\n * @param mAB - The measure of the arc from A to B, negative if counter-clockwise\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param P - The angle on the circle (P) to find the t value for\n *\n * @returns The t value of the point on the arc, with 0 being the start and 1 being the end\n *\n * @public\n */\nexport function getPointInArcT(mAB: number, A: number, B: number, P: number): number {\n\tlet mAP: number\n\tif (Math.abs(mAB) > PI) {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst mPB = shortAngleDist(P, B)\n\t\tif (Math.abs(mAP) < Math.abs(mPB)) {\n\t\t\treturn mAP / mAB\n\t\t} else {\n\t\t\treturn (mAB - mPB) / mAB\n\t\t}\n\t} else {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst t = mAP / mAB\n\n\t\t// If the arc is something like -2.8 to 2.2, then we'll get a weird bug\n\t\t// where the measurement to the center is negative but measure to points\n\t\t// near the end are positive\n\t\tif (Math.sign(mAP) !== Math.sign(mAB)) {\n\t\t\treturn Math.abs(t) > 0.5 ? 1 : 0\n\t\t}\n\n\t\treturn t\n\t}\n}\n\n/**\n * Get the measure of an arc.\n *\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param sweepFlag - 1 if the arc is clockwise, 0 if counter-clockwise\n * @param largeArcFlag - 1 if the arc is greater than 180 degrees, 0 if less than 180 degrees\n *\n * @returns The measure of the arc, negative if counter-clockwise\n *\n * @public\n */\nexport function getArcMeasure(A: number, B: number, sweepFlag: number, largeArcFlag: number) {\n\tconst m = ((2 * ((B - A) % PI2)) % PI2) - ((B - A) % PI2)\n\tif (!largeArcFlag) return m\n\treturn (PI2 - Math.abs(m)) * (sweepFlag ? 1 : -1)\n}\n\n/**\n * Get the center of a circle from three points.\n *\n * @param a - The first point\n * @param b - The second point\n * @param c - The third point\n *\n * @returns The center of the circle or null if the points are collinear\n *\n * @public\n */\nexport function centerOfCircleFromThreePoints(a: VecLike, b: VecLike, c: VecLike) {\n\tconst u = -2 * (a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - c.x * b.y)\n\tconst x =\n\t\t((a.x * a.x + a.y * a.y) * (c.y - b.y) +\n\t\t\t(b.x * b.x + b.y * b.y) * (a.y - c.y) +\n\t\t\t(c.x * c.x + c.y * c.y) * (b.y - a.y)) /\n\t\tu\n\tconst y =\n\t\t((a.x * a.x + a.y * a.y) * (b.x - c.x) +\n\t\t\t(b.x * b.x + b.y * b.y) * (c.x - a.x) +\n\t\t\t(c.x * c.x + c.y * c.y) * (a.x - b.x)) /\n\t\tu\n\tif (!Number.isFinite(x) || !Number.isFinite(y)) {\n\t\treturn null\n\t}\n\treturn new Vec(x, y)\n}\n\n/** @public */\nexport function getPointsOnArc(\n\tstartPoint: VecLike,\n\tendPoint: VecLike,\n\tcenter: VecLike | null,\n\tradius: number,\n\tnumPoints: number\n): Vec[] {\n\tif (center === null) {\n\t\treturn [Vec.From(startPoint), Vec.From(endPoint)]\n\t}\n\tconst results: Vec[] = []\n\tconst startAngle = Vec.Angle(center, startPoint)\n\tconst endAngle = Vec.Angle(center, endPoint)\n\tconst l = clockwiseAngleDist(startAngle, endAngle)\n\tfor (let i = 0; i < numPoints; i++) {\n\t\tconst t = i / (numPoints - 1)\n\t\tconst angle = startAngle + l * t\n\t\tconst point = getPointOnCircle(center, radius, angle)\n\t\tresults.push(point)\n\t}\n\treturn results\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Vec, VecLike } from './Vec'\n\n/** @public */\nexport function precise(A: VecLike) {\n\treturn `${toDomPrecision(A.x)},${toDomPrecision(A.y)} `\n}\n\n/** @public */\nexport function average(A: VecLike, B: VecLike) {\n\treturn `${toDomPrecision((A.x + B.x) / 2)},${toDomPrecision((A.y + B.y) / 2)} `\n}\n\n/** @public */\nexport const PI = Math.PI\n/** @public */\nexport const HALF_PI = PI / 2\n/** @public */\nexport const PI2 = PI * 2\n/** @public */\nexport const SIN = Math.sin\n\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1) // 1\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @public\n */\nexport function clamp(n: number, min: number): number\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1, 10) // 1\n * const B = clamp(11, 1, 10) // 10\n * const C = clamp(5, 1, 10) // 5\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @param max - The maximum value.\n * @public\n */\nexport function clamp(n: number, min: number, max: number): number\nexport function clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\n/**\n * Get a number to a precision.\n *\n * @param n - The number.\n * @param precision - The precision.\n * @public\n */\nexport function toPrecision(n: number, precision = 10000000000) {\n\tif (!n) return 0\n\treturn Math.round(n * precision) / precision\n}\n\n/**\n * Whether two numbers numbers a and b are approximately equal.\n *\n * @param a - The first point.\n * @param b - The second point.\n * @public\n */\nexport function approximately(a: number, b: number, precision = 0.000001) {\n\treturn Math.abs(a - b) <= precision\n}\n\n/**\n * Whether a number is approximately less than or equal to another number.\n *\n * @param a - The first number.\n * @param b - The second number.\n * @public\n */\nexport function approximatelyLte(a: number, b: number, precision = 0.000001) {\n\treturn a < b || approximately(a, b, precision)\n}\n\n/**\n * Find the approximate perimeter of an ellipse.\n *\n * @param rx - The ellipse's x radius.\n * @param ry - The ellipse's y radius.\n * @public\n */\nexport function perimeterOfEllipse(rx: number, ry: number): number {\n\tconst h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2)\n\treturn PI * (rx + ry) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)))\n}\n\n/**\n * @param a - Any angle in radians\n * @returns A number between 0 and 2 * PI\n * @public\n */\nexport function canonicalizeRotation(a: number) {\n\ta = a % PI2\n\tif (a < 0) {\n\t\ta = a + PI2\n\t} else if (a === 0) {\n\t\t// prevent negative zero\n\t\ta = 0\n\t}\n\treturn a\n}\n\n/**\n * Get the clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function clockwiseAngleDist(a0: number, a1: number): number {\n\ta0 = canonicalizeRotation(a0)\n\ta1 = canonicalizeRotation(a1)\n\tif (a0 > a1) {\n\t\ta1 += PI2\n\t}\n\treturn a1 - a0\n}\n\n/**\n * Get the counter-clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function counterClockwiseAngleDist(a0: number, a1: number): number {\n\treturn PI2 - clockwiseAngleDist(a0, a1)\n}\n\n/**\n * Get the short angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function shortAngleDist(a0: number, a1: number): number {\n\tconst da = (a1 - a0) % PI2\n\treturn ((2 * da) % PI2) - da\n}\n\n/**\n * Clamp radians within 0 and 2PI\n *\n * @param r - The radian value.\n * @public\n */\nexport function clampRadians(r: number): number {\n\treturn (PI2 + r) % PI2\n}\n\n/**\n * Clamp rotation to even segments.\n *\n * @param r - The rotation in radians.\n * @param segments - The number of segments.\n * @public\n */\nexport function snapAngle(r: number, segments: number): number {\n\tconst seg = PI2 / segments\n\tlet ang = (Math.floor((clampRadians(r) + seg / 2) / seg) * seg) % PI2\n\tif (ang < PI) ang += PI2\n\tif (ang > PI) ang -= PI2\n\treturn ang\n}\n\n/**\n * Checks whether two angles are approximately at right-angles or parallel to each other\n *\n * @param a - Angle a (radians)\n * @param b - Angle b (radians)\n * @returns True iff the angles are approximately at right-angles or parallel to each other\n * @public\n */\nexport function areAnglesCompatible(a: number, b: number) {\n\treturn a === b || approximately((a % (Math.PI / 2)) - (b % (Math.PI / 2)), 0)\n}\n\n/**\n * Convert degrees to radians.\n *\n * @param d - The degree in degrees.\n * @public\n */\nexport function degreesToRadians(d: number): number {\n\treturn (d * PI) / 180\n}\n\n/**\n * Convert radians to degrees.\n *\n * @param r - The degree in radians.\n * @public\n */\nexport function radiansToDegrees(r: number): number {\n\treturn (r * 180) / PI\n}\n\n/**\n * Get a point on the perimeter of a circle.\n *\n * @param center - The center of the circle.\n * @param r - The radius of the circle.\n * @param a - The angle in radians.\n * @public\n */\nexport function getPointOnCircle(center: VecLike, r: number, a: number) {\n\treturn new Vec(center.x, center.y).add(Vec.FromAngle(a, r))\n}\n\n/** @public */\nexport function getPolygonVertices(width: number, height: number, sides: number) {\n\tconst cx = width / 2\n\tconst cy = height / 2\n\tconst pointsOnPerimeter: Vec[] = []\n\n\tlet minX = Infinity\n\tlet maxX = -Infinity\n\tlet minY = Infinity\n\tlet maxY = -Infinity\n\tfor (let i = 0; i < sides; i++) {\n\t\tconst step = PI2 / sides\n\t\tconst t = -HALF_PI + i * step\n\t\tconst x = cx + cx * Math.cos(t)\n\t\tconst y = cy + cy * Math.sin(t)\n\t\tif (x < minX) minX = x\n\t\tif (y < minY) minY = y\n\t\tif (x > maxX) maxX = x\n\t\tif (y > maxY) maxY = y\n\t\tpointsOnPerimeter.push(new Vec(x, y))\n\t}\n\n\t// Bounds of calculated points\n\tconst w = maxX - minX\n\tconst h = maxY - minY\n\n\t// Difference between input bounds and calculated bounds\n\tconst dx = width - w\n\tconst dy = height - h\n\n\t// If there's a difference, scale the points to the input bounds\n\tif (dx !== 0 || dy !== 0) {\n\t\tfor (let i = 0; i < pointsOnPerimeter.length; i++) {\n\t\t\tconst pt = pointsOnPerimeter[i]\n\t\t\tpt.x = ((pt.x - minX) / w) * width\n\t\t\tpt.y = ((pt.y - minY) / h) * height\n\t\t}\n\t}\n\n\treturn pointsOnPerimeter\n}\n\n/**\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns True if the ranges overlap\n * @public\n */\nexport function rangesOverlap(a0: number, a1: number, b0: number, b1: number): boolean {\n\treturn a0 < b1 && b0 < a1\n}\n\n/**\n * Finds the intersection of two ranges.\n *\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns The intersection of the ranges, or null if no intersection\n * @public\n */\nexport function rangeIntersection(\n\ta0: number,\n\ta1: number,\n\tb0: number,\n\tb1: number\n): [number, number] | null {\n\tconst min = Math.max(a0, b0)\n\tconst max = Math.min(a1, b1)\n\tif (min <= max) {\n\t\treturn [min, max]\n\t}\n\treturn null\n}\n\n/** Helper for point in polygon */\nfunction cross(x: VecLike, y: VecLike, z: VecLike): number {\n\treturn (y.x - x.x) * (z.y - x.y) - (z.x - x.x) * (y.y - x.y)\n}\n\n/**\n * Get whether a point is inside of a polygon.\n *\n * ```ts\n * const result = pointInPolygon(myPoint, myPoints)\n * ```\n *\n * @public\n */\nexport function pointInPolygon(A: VecLike, points: VecLike[]): boolean {\n\tlet windingNumber = 0\n\tlet a: VecLike\n\tlet b: VecLike\n\n\tfor (let i = 0; i < points.length; i++) {\n\t\ta = points[i]\n\t\t// Point is the same as one of the corners of the polygon\n\t\tif (a.x === A.x && a.y === A.y) return true\n\n\t\tb = points[(i + 1) % points.length]\n\n\t\t// Point is on the polygon edge\n\t\tif (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true\n\n\t\tif (a.y <= A.y) {\n\t\t\tif (b.y > A.y && cross(a, b, A) > 0) {\n\t\t\t\twindingNumber += 1\n\t\t\t}\n\t\t} else if (b.y <= A.y && cross(a, b, A) < 0) {\n\t\t\twindingNumber -= 1\n\t\t}\n\t}\n\n\treturn windingNumber !== 0\n}\n\n/**\n * The DOM likes values to be fixed to 3 decimal places\n *\n * @public\n */\nexport function toDomPrecision(v: number) {\n\treturn Math.round(v * 1e4) / 1e4\n}\n\n/**\n * @public\n */\nexport function toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/**\n * Check if a float is safe to use. ie: Not too big or small.\n * @public\n */\nexport const isSafeFloat = (n: number) => {\n\treturn Math.abs(n) < Number.MAX_SAFE_INTEGER\n}\n\n/**\n * Get the angle of a point on an arc.\n * @param fromAngle - The angle from center to arc's start point (A) on the circle\n * @param toAngle - The angle from center to arc's end point (B) on the circle\n * @param direction - The direction of the arc (1 = counter-clockwise, -1 = clockwise)\n * @returns The distance in radians between the two angles according to the direction\n * @public\n */\nexport function angleDistance(fromAngle: number, toAngle: number, direction: number) {\n\tconst dist =\n\t\tdirection < 0\n\t\t\t? clockwiseAngleDist(fromAngle, toAngle)\n\t\t\t: counterClockwiseAngleDist(fromAngle, toAngle)\n\treturn dist\n}\n\n/**\n * Returns the t value of the point on the arc.\n *\n * @param mAB - The measure of the arc from A to B, negative if counter-clockwise\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param P - The angle on the circle (P) to find the t value for\n *\n * @returns The t value of the point on the arc, with 0 being the start and 1 being the end\n *\n * @public\n */\nexport function getPointInArcT(mAB: number, A: number, B: number, P: number): number {\n\tlet mAP: number\n\tif (Math.abs(mAB) > PI) {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst mPB = shortAngleDist(P, B)\n\t\tif (Math.abs(mAP) < Math.abs(mPB)) {\n\t\t\treturn mAP / mAB\n\t\t} else {\n\t\t\treturn (mAB - mPB) / mAB\n\t\t}\n\t} else {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst t = mAP / mAB\n\n\t\t// If the arc is something like -2.8 to 2.2, then we'll get a weird bug\n\t\t// where the measurement to the center is negative but measure to points\n\t\t// near the end are positive\n\t\tif (Math.sign(mAP) !== Math.sign(mAB)) {\n\t\t\treturn Math.abs(t) > 0.5 ? 1 : 0\n\t\t}\n\n\t\treturn t\n\t}\n}\n\n/**\n * Get the measure of an arc.\n *\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param sweepFlag - 1 if the arc is clockwise, 0 if counter-clockwise\n * @param largeArcFlag - 1 if the arc is greater than 180 degrees, 0 if less than 180 degrees\n *\n * @returns The measure of the arc, negative if counter-clockwise\n *\n * @public\n */\nexport function getArcMeasure(A: number, B: number, sweepFlag: number, largeArcFlag: number) {\n\tconst m = ((2 * ((B - A) % PI2)) % PI2) - ((B - A) % PI2)\n\tif (!largeArcFlag) return m\n\treturn (PI2 - Math.abs(m)) * (sweepFlag ? 1 : -1)\n}\n\n/**\n * Get the center of a circle from three points.\n *\n * @param a - The first point\n * @param b - The second point\n * @param c - The third point\n *\n * @returns The center of the circle or null if the points are collinear\n *\n * @public\n */\nexport function centerOfCircleFromThreePoints(a: VecLike, b: VecLike, c: VecLike) {\n\tconst u = -2 * (a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - c.x * b.y)\n\tconst x =\n\t\t((a.x * a.x + a.y * a.y) * (c.y - b.y) +\n\t\t\t(b.x * b.x + b.y * b.y) * (a.y - c.y) +\n\t\t\t(c.x * c.x + c.y * c.y) * (b.y - a.y)) /\n\t\tu\n\tconst y =\n\t\t((a.x * a.x + a.y * a.y) * (b.x - c.x) +\n\t\t\t(b.x * b.x + b.y * b.y) * (c.x - a.x) +\n\t\t\t(c.x * c.x + c.y * c.y) * (a.x - b.x)) /\n\t\tu\n\tif (!Number.isFinite(x) || !Number.isFinite(y)) {\n\t\treturn null\n\t}\n\treturn new Vec(x, y)\n}\n\n/** @public */\nexport function getPointsOnArc(\n\tstartPoint: VecLike,\n\tendPoint: VecLike,\n\tcenter: VecLike | null,\n\tradius: number,\n\tnumPoints: number\n): Vec[] {\n\tif (center === null) {\n\t\treturn [Vec.From(startPoint), Vec.From(endPoint)]\n\t}\n\tconst results: Vec[] = []\n\tconst startAngle = Vec.Angle(center, startPoint)\n\tconst endAngle = Vec.Angle(center, endPoint)\n\tconst l = clockwiseAngleDist(startAngle, endAngle)\n\tfor (let i = 0; i < numPoints; i++) {\n\t\tconst t = i / (numPoints - 1)\n\t\tconst angle = startAngle + l * t\n\t\tconst point = getPointOnCircle(center, radius, angle)\n\t\tresults.push(point)\n\t}\n\treturn results\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,25 @@
1
+ import { atom } from "@tldraw/state";
2
+ import { WeakCache } from "@tldraw/utils";
3
+ class EditorAtom {
4
+ constructor(name, getInitialState) {
5
+ this.name = name;
6
+ this.getInitialState = getInitialState;
7
+ }
8
+ states = new WeakCache();
9
+ getAtom(editor) {
10
+ return this.states.get(editor, () => atom(this.name, this.getInitialState(editor)));
11
+ }
12
+ get(editor) {
13
+ return this.getAtom(editor).get();
14
+ }
15
+ update(editor, update) {
16
+ return this.getAtom(editor).update(update);
17
+ }
18
+ set(editor, state) {
19
+ return this.getAtom(editor).set(state);
20
+ }
21
+ }
22
+ export {
23
+ EditorAtom
24
+ };
25
+ //# sourceMappingURL=EditorAtom.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/utils/EditorAtom.ts"],
4
+ "sourcesContent": ["import { atom, Atom } from '@tldraw/state'\nimport { WeakCache } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\n\n/**\n * An Atom that is scoped to the lifetime of an Editor.\n *\n * This is useful for storing UI state for tldraw applications. Keeping state scoped to an editor\n * instead of stored in a global atom can prevent issues with state being shared between editors\n * when navigating between pages, or when multiple editor instances are used on the same page.\n *\n * @public\n */\nexport class EditorAtom<T> {\n\tprivate states = new WeakCache<Editor, Atom<T>>()\n\n\tconstructor(\n\t\tprivate name: string,\n\t\tprivate getInitialState: (editor: Editor) => T\n\t) {}\n\n\tgetAtom(editor: Editor): Atom<T> {\n\t\treturn this.states.get(editor, () => atom(this.name, this.getInitialState(editor)))\n\t}\n\n\tget(editor: Editor): T {\n\t\treturn this.getAtom(editor).get()\n\t}\n\n\tupdate(editor: Editor, update: (state: T) => T): T {\n\t\treturn this.getAtom(editor).update(update)\n\t}\n\n\tset(editor: Editor, state: T): T {\n\t\treturn this.getAtom(editor).set(state)\n\t}\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAkB;AAC3B,SAAS,iBAAiB;AAYnB,MAAM,WAAc;AAAA,EAG1B,YACS,MACA,iBACP;AAFO;AACA;AAAA,EACN;AAAA,EALK,SAAS,IAAI,UAA2B;AAAA,EAOhD,QAAQ,QAAyB;AAChC,WAAO,KAAK,OAAO,IAAI,QAAQ,MAAM,KAAK,KAAK,MAAM,KAAK,gBAAgB,MAAM,CAAC,CAAC;AAAA,EACnF;AAAA,EAEA,IAAI,QAAmB;AACtB,WAAO,KAAK,QAAQ,MAAM,EAAE,IAAI;AAAA,EACjC;AAAA,EAEA,OAAO,QAAgB,QAA4B;AAClD,WAAO,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM;AAAA,EAC1C;AAAA,EAEA,IAAI,QAAgB,OAAa;AAChC,WAAO,KAAK,QAAQ,MAAM,EAAE,IAAI,KAAK;AAAA,EACtC;AACD;",
6
+ "names": []
7
+ }
@@ -36,6 +36,15 @@ function releasePointerCapture(element, event) {
36
36
  }
37
37
  }
38
38
  const stopEventPropagation = (e) => e.stopPropagation();
39
+ const handledEvents = /* @__PURE__ */ new WeakSet();
40
+ function markEventAsHandled(e) {
41
+ const nativeEvent = "nativeEvent" in e ? e.nativeEvent : e;
42
+ handledEvents.add(nativeEvent);
43
+ }
44
+ function wasEventAlreadyHandled(e) {
45
+ const nativeEvent = "nativeEvent" in e ? e.nativeEvent : e;
46
+ return handledEvents.has(nativeEvent);
47
+ }
39
48
  const setStyleProperty = (elm, property, value) => {
40
49
  if (!elm) return;
41
50
  elm.style.setProperty(property, value);
@@ -48,10 +57,12 @@ function activeElementShouldCaptureKeys(allowButtons = false) {
48
57
  export {
49
58
  activeElementShouldCaptureKeys,
50
59
  loopToHtmlElement,
60
+ markEventAsHandled,
51
61
  preventDefault,
52
62
  releasePointerCapture,
53
63
  setPointerCapture,
54
64
  setStyleProperty,
55
- stopEventPropagation
65
+ stopEventPropagation,
66
+ wasEventAlreadyHandled
56
67
  };
57
68
  //# sourceMappingURL=dom.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/dom.ts"],
4
- "sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elemnets do not support pointerCapture in \nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport React from 'react'\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Beacuase if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortuantly it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, value as string)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(allowButtons = false) {\n\tconst { activeElement } = document\n\tconst elements = allowButtons ? ['input', 'textarea'] : ['input', 'select', 'button', 'textarea']\n\treturn !!(\n\t\tactiveElement &&\n\t\t((activeElement as HTMLElement).isContentEditable ||\n\t\t\telements.indexOf(activeElement.tagName.toLowerCase()) > -1 ||\n\t\t\tactiveElement.classList.contains('tlui-slider__thumb'))\n\t)\n}\n"],
5
- "mappings": "AAgBA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAGO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAG3D,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,KAAe;AAChD;AAGO,SAAS,+BAA+B,eAAe,OAAO;AACpE,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,WAAW,eAAe,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,UAAU,UAAU,UAAU;AAChG,SAAO,CAAC,EACP,kBACE,cAA8B,qBAC/B,SAAS,QAAQ,cAAc,QAAQ,YAAY,CAAC,IAAI,MACxD,cAAc,UAAU,SAAS,oBAAoB;AAExD;",
4
+ "sourcesContent": ["/*\nThis is used to facilitate double clicking and pointer capture on elements.\n\nThe events in this file are possibly set on individual SVG elements, \nsuch as handles or corner handles, rather than on HTML elements or \nSVGSVGElements. Raw SVG elemnets do not support pointerCapture in \nmost cases, meaning that in order for pointer capture to work, we \nneed to crawl up the DOM tree to find the nearest HTML element. Then,\nin order for that element to also call the `onPointerUp` event from\nthis file, we need to manually set that event on that element and\nlater remove it when the pointerup occurs. This is a potential leak\nif the user clicks on a handle but the pointerup does not fire for\nwhatever reason.\n*/\n\nimport React from 'react'\nimport { debugFlags, pointerCaptureTrackingObject } from './debug-flags'\n\n/** @public */\nexport function loopToHtmlElement(elm: Element): HTMLElement {\n\tif (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement\n\tif (elm.parentElement) return loopToHtmlElement(elm.parentElement)\n\telse throw Error('Could not find a parent element of an HTML type!')\n}\n\n/**\n * This function calls `event.preventDefault()` for you. Why is that useful?\n *\n * Beacuase if you enable `window.preventDefaultLogging = true` it'll log out a message when it\n * happens. Because we use console.warn rather than (log) you'll get a stack trace in the inspector\n * telling you exactly where it happened. This is important because `e.preventDefault()` is the\n * source of many bugs, but unfortuantly it can't be avoided because it also stops a lot of default\n * behaviour which doesn't make sense in our UI\n *\n * @param event - To prevent default on\n * @public\n */\nexport function preventDefault(event: React.BaseSyntheticEvent | Event) {\n\tevent.preventDefault()\n\tif (debugFlags.logPreventDefaults.get()) {\n\t\tconsole.warn('preventDefault called on event:', event)\n\t}\n}\n\n/** @public */\nexport function setPointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\telement.setPointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\ttrackingObj.set(element, (trackingObj.get(element) ?? 0) + 1)\n\t\tconsole.warn('setPointerCapture called on element:', element, event)\n\t}\n}\n\n/** @public */\nexport function releasePointerCapture(\n\telement: Element,\n\tevent: React.PointerEvent<Element> | PointerEvent\n) {\n\tif (!element.hasPointerCapture(event.pointerId)) {\n\t\treturn\n\t}\n\n\telement.releasePointerCapture(event.pointerId)\n\tif (debugFlags.logPointerCaptures.get()) {\n\t\tconst trackingObj = pointerCaptureTrackingObject.get()\n\t\tif (trackingObj.get(element) === 1) {\n\t\t\ttrackingObj.delete(element)\n\t\t} else if (trackingObj.has(element)) {\n\t\t\ttrackingObj.set(element, trackingObj.get(element)! - 1)\n\t\t} else {\n\t\t\tconsole.warn('Release without capture')\n\t\t}\n\t\tconsole.warn('releasePointerCapture called on element:', element, event)\n\t}\n}\n\n/**\n * Calls `event.stopPropagation()`.\n *\n * @deprecated Use {@link markEventAsHandled} instead, or manually call `event.stopPropagation()` if\n * that's what you really want.\n *\n * @public\n */\nexport const stopEventPropagation = (e: any) => e.stopPropagation()\n\nconst handledEvents = new WeakSet<Event>()\n\n/**\n * In tldraw, events are sometimes handled by multiple components. For example, the shapes might\n * have events, but the canvas handles events too. The way that the canvas handles events can\n * interfere with the with the shapes event handlers - for example, it calls `.preventDefault()` on\n * `pointerDown`, which also prevents `click` events from firing on the shapes.\n *\n * You can use `.stopPropagation()` to prevent the event from propagating to the rest of the DOM,\n * but that can impact non-tldraw event handlers set up elsewhere. By using `markEventAsHandled`,\n * you'll stop other parts of tldraw from handling the event without impacting other, non-tldraw\n * event handlers. See also {@link wasEventAlreadyHandled}.\n *\n * @public\n */\nexport function markEventAsHandled(e: Event | { nativeEvent: Event }) {\n\tconst nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e\n\thandledEvents.add(nativeEvent)\n}\n\n/**\n * Checks if an event has already been handled. See {@link markEventAsHandled}.\n *\n * @public\n */\nexport function wasEventAlreadyHandled(e: Event | { nativeEvent: Event }) {\n\tconst nativeEvent = 'nativeEvent' in e ? e.nativeEvent : e\n\treturn handledEvents.has(nativeEvent)\n}\n\n/** @internal */\nexport const setStyleProperty = (\n\telm: HTMLElement | null,\n\tproperty: string,\n\tvalue: string | number\n) => {\n\tif (!elm) return\n\telm.style.setProperty(property, value as string)\n}\n\n/** @internal */\nexport function activeElementShouldCaptureKeys(allowButtons = false) {\n\tconst { activeElement } = document\n\tconst elements = allowButtons ? ['input', 'textarea'] : ['input', 'select', 'button', 'textarea']\n\treturn !!(\n\t\tactiveElement &&\n\t\t((activeElement as HTMLElement).isContentEditable ||\n\t\t\telements.indexOf(activeElement.tagName.toLowerCase()) > -1 ||\n\t\t\tactiveElement.classList.contains('tlui-slider__thumb'))\n\t)\n}\n"],
5
+ "mappings": "AAgBA,SAAS,YAAY,oCAAoC;AAGlD,SAAS,kBAAkB,KAA2B;AAC5D,MAAI,IAAI,aAAa,KAAK,aAAc,QAAO;AAC/C,MAAI,IAAI,cAAe,QAAO,kBAAkB,IAAI,aAAa;AAAA,MAC5D,OAAM,MAAM,kDAAkD;AACpE;AAcO,SAAS,eAAe,OAAyC;AACvE,QAAM,eAAe;AACrB,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,YAAQ,KAAK,mCAAmC,KAAK;AAAA,EACtD;AACD;AAGO,SAAS,kBACf,SACA,OACC;AACD,UAAQ,kBAAkB,MAAM,SAAS;AACzC,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,gBAAY,IAAI,UAAU,YAAY,IAAI,OAAO,KAAK,KAAK,CAAC;AAC5D,YAAQ,KAAK,wCAAwC,SAAS,KAAK;AAAA,EACpE;AACD;AAGO,SAAS,sBACf,SACA,OACC;AACD,MAAI,CAAC,QAAQ,kBAAkB,MAAM,SAAS,GAAG;AAChD;AAAA,EACD;AAEA,UAAQ,sBAAsB,MAAM,SAAS;AAC7C,MAAI,WAAW,mBAAmB,IAAI,GAAG;AACxC,UAAM,cAAc,6BAA6B,IAAI;AACrD,QAAI,YAAY,IAAI,OAAO,MAAM,GAAG;AACnC,kBAAY,OAAO,OAAO;AAAA,IAC3B,WAAW,YAAY,IAAI,OAAO,GAAG;AACpC,kBAAY,IAAI,SAAS,YAAY,IAAI,OAAO,IAAK,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,KAAK,yBAAyB;AAAA,IACvC;AACA,YAAQ,KAAK,4CAA4C,SAAS,KAAK;AAAA,EACxE;AACD;AAUO,MAAM,uBAAuB,CAAC,MAAW,EAAE,gBAAgB;AAElE,MAAM,gBAAgB,oBAAI,QAAe;AAelC,SAAS,mBAAmB,GAAmC;AACrE,QAAM,cAAc,iBAAiB,IAAI,EAAE,cAAc;AACzD,gBAAc,IAAI,WAAW;AAC9B;AAOO,SAAS,uBAAuB,GAAmC;AACzE,QAAM,cAAc,iBAAiB,IAAI,EAAE,cAAc;AACzD,SAAO,cAAc,IAAI,WAAW;AACrC;AAGO,MAAM,mBAAmB,CAC/B,KACA,UACA,UACI;AACJ,MAAI,CAAC,IAAK;AACV,MAAI,MAAM,YAAY,UAAU,KAAe;AAChD;AAGO,SAAS,+BAA+B,eAAe,OAAO;AACpE,QAAM,EAAE,cAAc,IAAI;AAC1B,QAAM,WAAW,eAAe,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,UAAU,UAAU,UAAU;AAChG,SAAO,CAAC,EACP,kBACE,cAA8B,qBAC/B,SAAS,QAAQ,cAAc,QAAQ,YAAY,CAAC,IAAI,MACxD,cAAc,UAAU,SAAS,oBAAoB;AAExD;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
+ import { markEventAsHandled } from "./dom.mjs";
1
2
  import { isAccelKey } from "./keyboard.mjs";
2
3
  function getPointerInfo(e) {
3
- ;
4
- e.isKilled = true;
4
+ markEventAsHandled(e);
5
5
  return {
6
6
  point: {
7
7
  x: e.clientX,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/getPointerInfo.ts"],
4
- "sourcesContent": ["import { isAccelKey } from './keyboard'\n\n/** @public */\nexport function getPointerInfo(e: React.PointerEvent | PointerEvent) {\n\t;(e as any).isKilled = true\n\n\treturn {\n\t\tpoint: {\n\t\t\tx: e.clientX,\n\t\t\ty: e.clientY,\n\t\t\tz: e.pressure,\n\t\t},\n\t\tshiftKey: e.shiftKey,\n\t\taltKey: e.altKey,\n\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\tmetaKey: e.metaKey,\n\t\taccelKey: isAccelKey(e),\n\t\tpointerId: e.pointerId,\n\t\tbutton: e.button,\n\t\tisPen: e.pointerType === 'pen',\n\t}\n}\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAGpB,SAAS,eAAe,GAAsC;AACpE;AAAC,EAAC,EAAU,WAAW;AAEvB,SAAO;AAAA,IACN,OAAO;AAAA,MACN,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACN;AAAA,IACA,UAAU,EAAE;AAAA,IACZ,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE,WAAW,EAAE;AAAA,IACxB,SAAS,EAAE;AAAA,IACX,UAAU,WAAW,CAAC;AAAA,IACtB,WAAW,EAAE;AAAA,IACb,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE,gBAAgB;AAAA,EAC1B;AACD;",
4
+ "sourcesContent": ["import { markEventAsHandled } from './dom'\nimport { isAccelKey } from './keyboard'\n\n/** @public */\nexport function getPointerInfo(e: React.PointerEvent | PointerEvent) {\n\tmarkEventAsHandled(e)\n\n\treturn {\n\t\tpoint: {\n\t\t\tx: e.clientX,\n\t\t\ty: e.clientY,\n\t\t\tz: e.pressure,\n\t\t},\n\t\tshiftKey: e.shiftKey,\n\t\taltKey: e.altKey,\n\t\tctrlKey: e.metaKey || e.ctrlKey,\n\t\tmetaKey: e.metaKey,\n\t\taccelKey: isAccelKey(e),\n\t\tpointerId: e.pointerId,\n\t\tbutton: e.button,\n\t\tisPen: e.pointerType === 'pen',\n\t}\n}\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAGpB,SAAS,eAAe,GAAsC;AACpE,qBAAmB,CAAC;AAEpB,SAAO;AAAA,IACN,OAAO;AAAA,MACN,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,MACL,GAAG,EAAE;AAAA,IACN;AAAA,IACA,UAAU,EAAE;AAAA,IACZ,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE,WAAW,EAAE;AAAA,IACxB,SAAS,EAAE;AAAA,IACX,UAAU,WAAW,CAAC;AAAA,IACtB,WAAW,EAAE;AAAA,IACb,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE,gBAAgB;AAAA,EAC1B;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,6 @@
1
1
  import { EMPTY_ARRAY } from "@tldraw/state";
2
2
  import { compact, getIndexAbove, getIndexBetween } from "@tldraw/utils";
3
- import { Group2d } from "../primitives/geometry/Group2d.mjs";
4
- import {
5
- intersectPolygonPolygon,
6
- polygonIntersectsPolyline,
7
- polygonsIntersect
8
- } from "../primitives/intersect.mjs";
9
- import { pointInPolygon } from "../primitives/utils.mjs";
3
+ import { intersectPolygonPolygon } from "../primitives/intersect.mjs";
10
4
  function kickoutOccludedShapes(editor, shapeIds, opts) {
11
5
  const parentsToCheck = /* @__PURE__ */ new Set();
12
6
  for (const id of shapeIds) {
@@ -102,39 +96,9 @@ function getOverlappingShapes(editor, shape, otherShapes) {
102
96
  if (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false;
103
97
  const parentPolygonInShapeShape = editor.getShapePageTransform(childId).clone().invert().applyToPoints(parentPagePolygon);
104
98
  const geometry = editor.getShapeGeometry(childId);
105
- return doesGeometryOverlapPolygon(geometry, parentPolygonInShapeShape);
99
+ return geometry.overlapsPolygon(parentPolygonInShapeShape);
106
100
  });
107
101
  }
108
- function doesGeometryOverlapPolygon(geometry, parentCornersInShapeSpace) {
109
- if (geometry instanceof Group2d) {
110
- return geometry.children.some(
111
- (childGeometry) => doesGeometryOverlapPolygon(childGeometry, parentCornersInShapeSpace)
112
- );
113
- }
114
- const { vertices, center, isFilled, isEmptyLabel, isClosed } = geometry;
115
- if (isEmptyLabel) return false;
116
- if (vertices.some((v) => pointInPolygon(v, parentCornersInShapeSpace))) {
117
- return true;
118
- }
119
- if (isClosed) {
120
- if (isFilled) {
121
- if (pointInPolygon(center, parentCornersInShapeSpace)) {
122
- return true;
123
- }
124
- if (parentCornersInShapeSpace.every((v) => pointInPolygon(v, vertices))) {
125
- return true;
126
- }
127
- }
128
- if (polygonsIntersect(parentCornersInShapeSpace, vertices)) {
129
- return true;
130
- }
131
- } else {
132
- if (polygonIntersectsPolyline(parentCornersInShapeSpace, vertices)) {
133
- return true;
134
- }
135
- }
136
- return false;
137
- }
138
102
  function getDroppedShapesToNewParents(editor, shapes, cb) {
139
103
  const shapesToActuallyCheck = new Set(shapes);
140
104
  const movingGroups = /* @__PURE__ */ new Set();
@@ -187,7 +151,7 @@ function getDroppedShapesToNewParents(editor, shapes, cb) {
187
151
  if (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck;
188
152
  if (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck;
189
153
  const parentPolygonInShapeSpace = editor.getShapePageTransform(shape).clone().invert().applyToPoints(parentPagePolygon);
190
- if (doesGeometryOverlapPolygon(editor.getShapeGeometry(shape), parentPolygonInShapeSpace)) {
154
+ if (editor.getShapeGeometry(shape).overlapsPolygon(parentPolygonInShapeSpace)) {
191
155
  if (!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type))
192
156
  continue shapeCheck;
193
157
  if (shape.parentId !== parentShape.id) {
@@ -209,7 +173,6 @@ function getDroppedShapesToNewParents(editor, shapes, cb) {
209
173
  };
210
174
  }
211
175
  export {
212
- doesGeometryOverlapPolygon,
213
176
  getDroppedShapesToNewParents,
214
177
  kickoutOccludedShapes
215
178
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/reparenting.ts"],
4
- "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\nimport { TLGroupShape, TLParentId, TLShape, TLShapeId } from '@tldraw/tlschema'\nimport { IndexKey, compact, getIndexAbove, getIndexBetween } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { Vec } from '../primitives/Vec'\nimport { Geometry2d } from '../primitives/geometry/Geometry2d'\nimport { Group2d } from '../primitives/geometry/Group2d'\nimport {\n\tintersectPolygonPolygon,\n\tpolygonIntersectsPolyline,\n\tpolygonsIntersect,\n} from '../primitives/intersect'\nimport { pointInPolygon } from '../primitives/utils'\n\n/**\n * Reparents shapes that are no longer contained within their parent shapes.\n * todo: rename me to something more descriptive, like `reparentOccludedShapes` or `reparentAutoDroppedShapes`\n *\n * @param editor - The editor instance.\n * @param shapeIds - The IDs of the shapes to reparent.\n * @param opts - Optional options, including a callback to filter out certain parents, such as when removing a frame.\n *\n * @public\n */\nexport function kickoutOccludedShapes(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts?: { filter?(parent: TLShape): boolean }\n) {\n\tconst parentsToCheck = new Set<TLShape>()\n\n\tfor (const id of shapeIds) {\n\t\tconst shape = editor.getShape(id)\n\n\t\tif (!shape) continue\n\t\tparentsToCheck.add(shape)\n\n\t\tconst parent = editor.getShape(shape.parentId)\n\t\tif (!parent) continue\n\t\tparentsToCheck.add(parent)\n\t}\n\n\t// Check all of the parents and gather up parents who have lost children\n\tconst parentsToLostChildren = new Map<TLShape, TLShapeId[]>()\n\n\tfor (const parent of parentsToCheck) {\n\t\tconst childIds = editor.getSortedChildIdsForParent(parent)\n\t\tif (opts?.filter && !opts.filter(parent)) {\n\t\t\t// If the shape is filtered out, we kick out all of its children\n\t\t\tparentsToLostChildren.set(parent, childIds)\n\t\t} else {\n\t\t\tconst overlappingChildren = getOverlappingShapes(editor, parent.id, childIds)\n\t\t\tif (overlappingChildren.length < childIds.length) {\n\t\t\t\tparentsToLostChildren.set(\n\t\t\t\t\tparent,\n\t\t\t\t\tchildIds.filter((id) => !overlappingChildren.includes(id))\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get all of the shapes on the current page, sorted by their index\n\tconst sortedShapeIds = editor.getCurrentPageShapesSorted().map((s) => s.id)\n\n\tconst parentsToNewChildren: Record<\n\t\tTLParentId,\n\t\t{ parentId: TLParentId; shapeIds: TLShapeId[]; index?: IndexKey }\n\t> = {}\n\n\tfor (const [prevParent, lostChildrenIds] of parentsToLostChildren) {\n\t\tconst lostChildren = compact(lostChildrenIds.map((id) => editor.getShape(id)))\n\n\t\t// Don't fall \"up\" into frames in front of the shape\n\t\t// if (pageShapes.indexOf(shape) < frameSortPosition) continue shapeCheck\n\n\t\t// Otherwise, we have no next dropping shape under the cursor, so go find\n\t\t// all the frames on the page where the moving shapes will fall into\n\t\tconst { reparenting, remainingShapesToReparent } = getDroppedShapesToNewParents(\n\t\t\teditor,\n\t\t\tlostChildren,\n\t\t\t(shape, maybeNewParent) => {\n\t\t\t\t// If we're filtering out a potential parent, don't reparent shapes to the filtered out shape\n\t\t\t\tif (opts?.filter && !opts.filter(maybeNewParent)) return false\n\t\t\t\treturn (\n\t\t\t\t\tmaybeNewParent.id !== prevParent.id &&\n\t\t\t\t\tsortedShapeIds.indexOf(maybeNewParent.id) < sortedShapeIds.indexOf(shape.id)\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\n\t\treparenting.forEach((childrenToReparent, newParentId) => {\n\t\t\tif (childrenToReparent.length === 0) return\n\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\tshapeIds: [],\n\t\t\t\t}\n\t\t\t}\n\t\t\tparentsToNewChildren[newParentId].shapeIds.push(...childrenToReparent.map((s) => s.id))\n\t\t})\n\n\t\t// Reparent the rest to the page (or containing group)\n\t\tif (remainingShapesToReparent.size > 0) {\n\t\t\t// The remaining shapes are going to be reparented to the old parent's containing group, if there was one, or else to the page\n\t\t\tconst newParentId =\n\t\t\t\teditor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))\n\t\t\t\t\t?.id ?? editor.getCurrentPageId()\n\n\t\t\tremainingShapesToReparent.forEach((shape) => {\n\t\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\t\tlet insertIndexKey: IndexKey | undefined\n\n\t\t\t\t\tconst oldParentSiblingIds = editor.getSortedChildIdsForParent(newParentId)\n\t\t\t\t\tconst oldParentIndex = oldParentSiblingIds.indexOf(prevParent.id)\n\t\t\t\t\tif (oldParentIndex > -1) {\n\t\t\t\t\t\t// If the old parent is a direct child of the new parent, then we'll add them above the old parent but below the next sibling.\n\t\t\t\t\t\tconst siblingsIndexAbove = oldParentSiblingIds[oldParentIndex + 1]\n\t\t\t\t\t\tconst indexKeyAbove = siblingsIndexAbove\n\t\t\t\t\t\t\t? editor.getShape(siblingsIndexAbove)!.index\n\t\t\t\t\t\t\t: getIndexAbove(prevParent.index)\n\t\t\t\t\t\tinsertIndexKey = getIndexBetween(prevParent.index, indexKeyAbove)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If the old parent is not a direct child of the new parent, then we'll add them to the \"top\" of the new parent's children.\n\t\t\t\t\t\t// This is done automatically if we leave the index undefined, so let's do that.\n\t\t\t\t\t}\n\n\t\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\t\tshapeIds: [],\n\t\t\t\t\t\tindex: insertIndexKey,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tparentsToNewChildren[newParentId].shapeIds.push(shape.id)\n\t\t\t})\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\tObject.values(parentsToNewChildren).forEach(({ parentId, shapeIds, index }) => {\n\t\t\tif (shapeIds.length === 0) return\n\t\t\t// Before we reparent, sort the new shape ids by their place in the original absolute order on the page\n\t\t\tshapeIds.sort((a, b) => (sortedShapeIds.indexOf(a) < sortedShapeIds.indexOf(b) ? -1 : 1))\n\t\t\teditor.reparentShapes(shapeIds, parentId, index)\n\t\t})\n\t})\n}\n\n/**\n * Get the shapes that overlap with a given shape.\n *\n * @param editor - The editor instance.\n * @param shape - The shapes or shape IDs to check against.\n * @param otherShapes - The shapes or shape IDs to check for overlap.\n * @returns An array of shapes or shape IDs that overlap with the given shape.\n */\nfunction getOverlappingShapes<T extends TLShape[] | TLShapeId[]>(\n\teditor: Editor,\n\tshape: T[number],\n\totherShapes: T\n) {\n\tif (otherShapes.length === 0) {\n\t\treturn EMPTY_ARRAY\n\t}\n\n\tconst parentPageBounds = editor.getShapePageBounds(shape)\n\tif (!parentPageBounds) return EMPTY_ARRAY\n\n\tconst parentGeometry = editor.getShapeGeometry(shape)\n\tconst parentPageTransform = editor.getShapePageTransform(shape)\n\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\n\tconst parentPageMaskVertices = editor.getShapeMask(shape)\n\tconst parentPagePolygon = parentPageMaskVertices\n\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t: parentPageCorners\n\n\tif (!parentPagePolygon) return EMPTY_ARRAY\n\n\treturn otherShapes.filter((childId) => {\n\t\tconst shapePageBounds = editor.getShapePageBounds(childId)\n\t\tif (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false\n\n\t\tconst parentPolygonInShapeShape = editor\n\t\t\t.getShapePageTransform(childId)\n\t\t\t.clone()\n\t\t\t.invert()\n\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\tconst geometry = editor.getShapeGeometry(childId)\n\n\t\treturn doesGeometryOverlapPolygon(geometry, parentPolygonInShapeShape)\n\t})\n}\n\n/**\n * @public\n */\nexport function doesGeometryOverlapPolygon(\n\tgeometry: Geometry2d,\n\tparentCornersInShapeSpace: Vec[]\n): boolean {\n\t// If the child is a group, check if any of its children overlap the box\n\tif (geometry instanceof Group2d) {\n\t\treturn geometry.children.some((childGeometry) =>\n\t\t\tdoesGeometryOverlapPolygon(childGeometry, parentCornersInShapeSpace)\n\t\t)\n\t}\n\n\t// Otherwise, check if the geometry overlaps the box\n\tconst { vertices, center, isFilled, isEmptyLabel, isClosed } = geometry\n\n\t// We'll do things in order of cheapest to most expensive checks\n\n\t// Skip empty labels\n\tif (isEmptyLabel) return false\n\n\t// If any of the shape's vertices are inside the occluder, it's inside\n\tif (vertices.some((v) => pointInPolygon(v, parentCornersInShapeSpace))) {\n\t\treturn true\n\t}\n\n\t// If the shape is filled and closed and its center is inside the parent, it's inside\n\tif (isClosed) {\n\t\tif (isFilled) {\n\t\t\t// If closed and filled, check if the center is inside the parent\n\t\t\tif (pointInPolygon(center, parentCornersInShapeSpace)) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// ..then, slightly more expensive check, see the shape covers the entire parent but not its center\n\t\t\tif (parentCornersInShapeSpace.every((v) => pointInPolygon(v, vertices))) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\t// If any the shape's vertices intersect the edge of the occluder, it's inside.\n\t\t// for example when a rotated rectangle is moved over the corner of a parent rectangle\n\t\t// If the child shape is closed, intersect as a polygon\n\t\tif (polygonsIntersect(parentCornersInShapeSpace, vertices)) {\n\t\t\treturn true\n\t\t}\n\t} else {\n\t\t// if the child shape is not closed, intersect as a polyline\n\t\tif (polygonIntersectsPolyline(parentCornersInShapeSpace, vertices)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// If none of the above checks passed, the shape is outside the parent\n\treturn false\n}\n\n/**\n * Get the shapes that will be reparented to new parents when the shapes are dropped.\n *\n * @param editor - The editor instance.\n * @param shapes - The shapes to check.\n * @param cb - A callback to filter out certain shapes.\n * @returns An object with the shapes that will be reparented to new parents and the shapes that will be reparented to the page or their ancestral group.\n *\n * @public\n */\nexport function getDroppedShapesToNewParents(\n\teditor: Editor,\n\tshapes: Set<TLShape> | TLShape[],\n\tcb?: (shape: TLShape, parent: TLShape) => boolean\n) {\n\tconst shapesToActuallyCheck = new Set<TLShape>(shapes)\n\tconst movingGroups = new Set<TLGroupShape>()\n\n\tfor (const shape of shapes) {\n\t\tconst parent = editor.getShapeParent(shape)\n\t\tif (parent && editor.isShapeOfType<TLGroupShape>(parent, 'group')) {\n\t\t\tif (!movingGroups.has(parent)) {\n\t\t\t\tmovingGroups.add(parent)\n\t\t\t}\n\t\t}\n\t}\n\n\t// If all of a group's children are moving, then move the group instead\n\tfor (const movingGroup of movingGroups) {\n\t\tconst children = compact(\n\t\t\teditor.getSortedChildIdsForParent(movingGroup).map((id) => editor.getShape(id))\n\t\t)\n\t\tfor (const child of children) {\n\t\t\tshapesToActuallyCheck.delete(child)\n\t\t}\n\t\tshapesToActuallyCheck.add(movingGroup)\n\t}\n\n\t// this could be cached and passed in\n\tconst shapeGroupIds = new Map<TLShapeId, TLShapeId | undefined>()\n\n\tconst reparenting = new Map<TLShapeId, TLShape[]>()\n\n\tconst remainingShapesToReparent = new Set(shapesToActuallyCheck)\n\n\tconst potentialParentShapes = editor\n\t\t.getCurrentPageShapesSorted()\n\t\t// filter out any shapes that aren't frames or that are included among the provided shapes\n\t\t.filter(\n\t\t\t(s) =>\n\t\t\t\teditor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) &&\n\t\t\t\t!remainingShapesToReparent.has(s)\n\t\t)\n\n\tparentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {\n\t\tconst parentShape = potentialParentShapes[i]\n\t\tconst parentShapeContainingGroupId = editor.findShapeAncestor(parentShape, (s) =>\n\t\t\teditor.isShapeOfType<TLGroupShape>(s, 'group')\n\t\t)?.id\n\n\t\tconst parentGeometry = editor.getShapeGeometry(parentShape)\n\t\tconst parentPageTransform = editor.getShapePageTransform(parentShape)\n\t\tconst parentPageMaskVertices = editor.getShapeMask(parentShape)\n\t\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\t\tconst parentPagePolygon = parentPageMaskVertices\n\t\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t\t: parentPageCorners\n\n\t\tif (!parentPagePolygon) continue parentCheck\n\n\t\tconst childrenToReparent = []\n\n\t\t// For each of the dropping shapes...\n\t\tshapeCheck: for (const shape of remainingShapesToReparent) {\n\t\t\t// Don't reparent a frame to itself\n\t\t\tif (parentShape.id === shape.id) continue shapeCheck\n\n\t\t\t// Use the callback to filter out certain shapes\n\t\t\tif (cb && !cb(shape, parentShape)) continue shapeCheck\n\n\t\t\tif (!shapeGroupIds.has(shape.id)) {\n\t\t\t\tshapeGroupIds.set(\n\t\t\t\t\tshape.id,\n\t\t\t\t\teditor.findShapeAncestor(shape, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))?.id\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst shapeGroupId = shapeGroupIds.get(shape.id)\n\n\t\t\t// Are the shape and the parent part of different groups?\n\t\t\tif (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck\n\n\t\t\t// Is the shape is actually the ancestor of the parent?\n\t\t\tif (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck\n\n\t\t\t// Convert the parent polygon to the shape's space\n\t\t\tconst parentPolygonInShapeSpace = editor\n\t\t\t\t.getShapePageTransform(shape)\n\t\t\t\t.clone()\n\t\t\t\t.invert()\n\t\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\t\t// If the shape overlaps the parent polygon, reparent it to that parent\n\t\t\tif (doesGeometryOverlapPolygon(editor.getShapeGeometry(shape), parentPolygonInShapeSpace)) {\n\t\t\t\t// Use the util to check if the shape can be reparented to the parent\n\t\t\t\tif (\n\t\t\t\t\t!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type)\n\t\t\t\t)\n\t\t\t\t\tcontinue shapeCheck\n\n\t\t\t\tif (shape.parentId !== parentShape.id) {\n\t\t\t\t\tchildrenToReparent.push(shape)\n\t\t\t\t}\n\t\t\t\tremainingShapesToReparent.delete(shape)\n\t\t\t\tcontinue shapeCheck\n\t\t\t}\n\t\t}\n\n\t\tif (childrenToReparent.length) {\n\t\t\treparenting.set(parentShape.id, childrenToReparent)\n\t\t}\n\t}\n\n\treturn {\n\t\t// these are the shapes that will be reparented to new parents\n\t\treparenting,\n\t\t// these are the shapes that will be reparented to the page or their ancestral group\n\t\tremainingShapesToReparent,\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\nimport { TLGroupShape, TLParentId, TLShape, TLShapeId } from '@tldraw/tlschema'\nimport { IndexKey, compact, getIndexAbove, getIndexBetween } from '@tldraw/utils'\nimport { Editor } from '../editor/Editor'\nimport { intersectPolygonPolygon } from '../primitives/intersect'\n\n/**\n * Reparents shapes that are no longer contained within their parent shapes.\n * todo: rename me to something more descriptive, like `reparentOccludedShapes` or `reparentAutoDroppedShapes`\n *\n * @param editor - The editor instance.\n * @param shapeIds - The IDs of the shapes to reparent.\n * @param opts - Optional options, including a callback to filter out certain parents, such as when removing a frame.\n *\n * @public\n */\nexport function kickoutOccludedShapes(\n\teditor: Editor,\n\tshapeIds: TLShapeId[],\n\topts?: { filter?(parent: TLShape): boolean }\n) {\n\tconst parentsToCheck = new Set<TLShape>()\n\n\tfor (const id of shapeIds) {\n\t\tconst shape = editor.getShape(id)\n\n\t\tif (!shape) continue\n\t\tparentsToCheck.add(shape)\n\n\t\tconst parent = editor.getShape(shape.parentId)\n\t\tif (!parent) continue\n\t\tparentsToCheck.add(parent)\n\t}\n\n\t// Check all of the parents and gather up parents who have lost children\n\tconst parentsToLostChildren = new Map<TLShape, TLShapeId[]>()\n\n\tfor (const parent of parentsToCheck) {\n\t\tconst childIds = editor.getSortedChildIdsForParent(parent)\n\t\tif (opts?.filter && !opts.filter(parent)) {\n\t\t\t// If the shape is filtered out, we kick out all of its children\n\t\t\tparentsToLostChildren.set(parent, childIds)\n\t\t} else {\n\t\t\tconst overlappingChildren = getOverlappingShapes(editor, parent.id, childIds)\n\t\t\tif (overlappingChildren.length < childIds.length) {\n\t\t\t\tparentsToLostChildren.set(\n\t\t\t\t\tparent,\n\t\t\t\t\tchildIds.filter((id) => !overlappingChildren.includes(id))\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get all of the shapes on the current page, sorted by their index\n\tconst sortedShapeIds = editor.getCurrentPageShapesSorted().map((s) => s.id)\n\n\tconst parentsToNewChildren: Record<\n\t\tTLParentId,\n\t\t{ parentId: TLParentId; shapeIds: TLShapeId[]; index?: IndexKey }\n\t> = {}\n\n\tfor (const [prevParent, lostChildrenIds] of parentsToLostChildren) {\n\t\tconst lostChildren = compact(lostChildrenIds.map((id) => editor.getShape(id)))\n\n\t\t// Don't fall \"up\" into frames in front of the shape\n\t\t// if (pageShapes.indexOf(shape) < frameSortPosition) continue shapeCheck\n\n\t\t// Otherwise, we have no next dropping shape under the cursor, so go find\n\t\t// all the frames on the page where the moving shapes will fall into\n\t\tconst { reparenting, remainingShapesToReparent } = getDroppedShapesToNewParents(\n\t\t\teditor,\n\t\t\tlostChildren,\n\t\t\t(shape, maybeNewParent) => {\n\t\t\t\t// If we're filtering out a potential parent, don't reparent shapes to the filtered out shape\n\t\t\t\tif (opts?.filter && !opts.filter(maybeNewParent)) return false\n\t\t\t\treturn (\n\t\t\t\t\tmaybeNewParent.id !== prevParent.id &&\n\t\t\t\t\tsortedShapeIds.indexOf(maybeNewParent.id) < sortedShapeIds.indexOf(shape.id)\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\n\t\treparenting.forEach((childrenToReparent, newParentId) => {\n\t\t\tif (childrenToReparent.length === 0) return\n\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\tshapeIds: [],\n\t\t\t\t}\n\t\t\t}\n\t\t\tparentsToNewChildren[newParentId].shapeIds.push(...childrenToReparent.map((s) => s.id))\n\t\t})\n\n\t\t// Reparent the rest to the page (or containing group)\n\t\tif (remainingShapesToReparent.size > 0) {\n\t\t\t// The remaining shapes are going to be reparented to the old parent's containing group, if there was one, or else to the page\n\t\t\tconst newParentId =\n\t\t\t\teditor.findShapeAncestor(prevParent, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))\n\t\t\t\t\t?.id ?? editor.getCurrentPageId()\n\n\t\t\tremainingShapesToReparent.forEach((shape) => {\n\t\t\t\tif (!parentsToNewChildren[newParentId]) {\n\t\t\t\t\tlet insertIndexKey: IndexKey | undefined\n\n\t\t\t\t\tconst oldParentSiblingIds = editor.getSortedChildIdsForParent(newParentId)\n\t\t\t\t\tconst oldParentIndex = oldParentSiblingIds.indexOf(prevParent.id)\n\t\t\t\t\tif (oldParentIndex > -1) {\n\t\t\t\t\t\t// If the old parent is a direct child of the new parent, then we'll add them above the old parent but below the next sibling.\n\t\t\t\t\t\tconst siblingsIndexAbove = oldParentSiblingIds[oldParentIndex + 1]\n\t\t\t\t\t\tconst indexKeyAbove = siblingsIndexAbove\n\t\t\t\t\t\t\t? editor.getShape(siblingsIndexAbove)!.index\n\t\t\t\t\t\t\t: getIndexAbove(prevParent.index)\n\t\t\t\t\t\tinsertIndexKey = getIndexBetween(prevParent.index, indexKeyAbove)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If the old parent is not a direct child of the new parent, then we'll add them to the \"top\" of the new parent's children.\n\t\t\t\t\t\t// This is done automatically if we leave the index undefined, so let's do that.\n\t\t\t\t\t}\n\n\t\t\t\t\tparentsToNewChildren[newParentId] = {\n\t\t\t\t\t\tparentId: newParentId,\n\t\t\t\t\t\tshapeIds: [],\n\t\t\t\t\t\tindex: insertIndexKey,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tparentsToNewChildren[newParentId].shapeIds.push(shape.id)\n\t\t\t})\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\tObject.values(parentsToNewChildren).forEach(({ parentId, shapeIds, index }) => {\n\t\t\tif (shapeIds.length === 0) return\n\t\t\t// Before we reparent, sort the new shape ids by their place in the original absolute order on the page\n\t\t\tshapeIds.sort((a, b) => (sortedShapeIds.indexOf(a) < sortedShapeIds.indexOf(b) ? -1 : 1))\n\t\t\teditor.reparentShapes(shapeIds, parentId, index)\n\t\t})\n\t})\n}\n\n/**\n * Get the shapes that overlap with a given shape.\n *\n * @param editor - The editor instance.\n * @param shape - The shapes or shape IDs to check against.\n * @param otherShapes - The shapes or shape IDs to check for overlap.\n * @returns An array of shapes or shape IDs that overlap with the given shape.\n */\nfunction getOverlappingShapes<T extends TLShape[] | TLShapeId[]>(\n\teditor: Editor,\n\tshape: T[number],\n\totherShapes: T\n) {\n\tif (otherShapes.length === 0) {\n\t\treturn EMPTY_ARRAY\n\t}\n\n\tconst parentPageBounds = editor.getShapePageBounds(shape)\n\tif (!parentPageBounds) return EMPTY_ARRAY\n\n\tconst parentGeometry = editor.getShapeGeometry(shape)\n\tconst parentPageTransform = editor.getShapePageTransform(shape)\n\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\n\tconst parentPageMaskVertices = editor.getShapeMask(shape)\n\tconst parentPagePolygon = parentPageMaskVertices\n\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t: parentPageCorners\n\n\tif (!parentPagePolygon) return EMPTY_ARRAY\n\n\treturn otherShapes.filter((childId) => {\n\t\tconst shapePageBounds = editor.getShapePageBounds(childId)\n\t\tif (!shapePageBounds || !parentPageBounds.includes(shapePageBounds)) return false\n\n\t\tconst parentPolygonInShapeShape = editor\n\t\t\t.getShapePageTransform(childId)\n\t\t\t.clone()\n\t\t\t.invert()\n\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\tconst geometry = editor.getShapeGeometry(childId)\n\n\t\treturn geometry.overlapsPolygon(parentPolygonInShapeShape)\n\t})\n}\n\n/**\n * Get the shapes that will be reparented to new parents when the shapes are dropped.\n *\n * @param editor - The editor instance.\n * @param shapes - The shapes to check.\n * @param cb - A callback to filter out certain shapes.\n * @returns An object with the shapes that will be reparented to new parents and the shapes that will be reparented to the page or their ancestral group.\n *\n * @public\n */\nexport function getDroppedShapesToNewParents(\n\teditor: Editor,\n\tshapes: Set<TLShape> | TLShape[],\n\tcb?: (shape: TLShape, parent: TLShape) => boolean\n) {\n\tconst shapesToActuallyCheck = new Set<TLShape>(shapes)\n\tconst movingGroups = new Set<TLGroupShape>()\n\n\tfor (const shape of shapes) {\n\t\tconst parent = editor.getShapeParent(shape)\n\t\tif (parent && editor.isShapeOfType<TLGroupShape>(parent, 'group')) {\n\t\t\tif (!movingGroups.has(parent)) {\n\t\t\t\tmovingGroups.add(parent)\n\t\t\t}\n\t\t}\n\t}\n\n\t// If all of a group's children are moving, then move the group instead\n\tfor (const movingGroup of movingGroups) {\n\t\tconst children = compact(\n\t\t\teditor.getSortedChildIdsForParent(movingGroup).map((id) => editor.getShape(id))\n\t\t)\n\t\tfor (const child of children) {\n\t\t\tshapesToActuallyCheck.delete(child)\n\t\t}\n\t\tshapesToActuallyCheck.add(movingGroup)\n\t}\n\n\t// this could be cached and passed in\n\tconst shapeGroupIds = new Map<TLShapeId, TLShapeId | undefined>()\n\n\tconst reparenting = new Map<TLShapeId, TLShape[]>()\n\n\tconst remainingShapesToReparent = new Set(shapesToActuallyCheck)\n\n\tconst potentialParentShapes = editor\n\t\t.getCurrentPageShapesSorted()\n\t\t// filter out any shapes that aren't frames or that are included among the provided shapes\n\t\t.filter(\n\t\t\t(s) =>\n\t\t\t\teditor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) &&\n\t\t\t\t!remainingShapesToReparent.has(s)\n\t\t)\n\n\tparentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {\n\t\tconst parentShape = potentialParentShapes[i]\n\t\tconst parentShapeContainingGroupId = editor.findShapeAncestor(parentShape, (s) =>\n\t\t\teditor.isShapeOfType<TLGroupShape>(s, 'group')\n\t\t)?.id\n\n\t\tconst parentGeometry = editor.getShapeGeometry(parentShape)\n\t\tconst parentPageTransform = editor.getShapePageTransform(parentShape)\n\t\tconst parentPageMaskVertices = editor.getShapeMask(parentShape)\n\t\tconst parentPageCorners = parentPageTransform.applyToPoints(parentGeometry.vertices)\n\t\tconst parentPagePolygon = parentPageMaskVertices\n\t\t\t? intersectPolygonPolygon(parentPageMaskVertices, parentPageCorners)\n\t\t\t: parentPageCorners\n\n\t\tif (!parentPagePolygon) continue parentCheck\n\n\t\tconst childrenToReparent = []\n\n\t\t// For each of the dropping shapes...\n\t\tshapeCheck: for (const shape of remainingShapesToReparent) {\n\t\t\t// Don't reparent a frame to itself\n\t\t\tif (parentShape.id === shape.id) continue shapeCheck\n\n\t\t\t// Use the callback to filter out certain shapes\n\t\t\tif (cb && !cb(shape, parentShape)) continue shapeCheck\n\n\t\t\tif (!shapeGroupIds.has(shape.id)) {\n\t\t\t\tshapeGroupIds.set(\n\t\t\t\t\tshape.id,\n\t\t\t\t\teditor.findShapeAncestor(shape, (s) => editor.isShapeOfType<TLGroupShape>(s, 'group'))?.id\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst shapeGroupId = shapeGroupIds.get(shape.id)\n\n\t\t\t// Are the shape and the parent part of different groups?\n\t\t\tif (shapeGroupId !== parentShapeContainingGroupId) continue shapeCheck\n\n\t\t\t// Is the shape is actually the ancestor of the parent?\n\t\t\tif (editor.findShapeAncestor(parentShape, (s) => shape.id === s.id)) continue shapeCheck\n\n\t\t\t// Convert the parent polygon to the shape's space\n\t\t\tconst parentPolygonInShapeSpace = editor\n\t\t\t\t.getShapePageTransform(shape)\n\t\t\t\t.clone()\n\t\t\t\t.invert()\n\t\t\t\t.applyToPoints(parentPagePolygon)\n\n\t\t\t// If the shape overlaps the parent polygon, reparent it to that parent\n\t\t\tif (editor.getShapeGeometry(shape).overlapsPolygon(parentPolygonInShapeSpace)) {\n\t\t\t\t// Use the util to check if the shape can be reparented to the parent\n\t\t\t\tif (\n\t\t\t\t\t!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type)\n\t\t\t\t)\n\t\t\t\t\tcontinue shapeCheck\n\n\t\t\t\tif (shape.parentId !== parentShape.id) {\n\t\t\t\t\tchildrenToReparent.push(shape)\n\t\t\t\t}\n\t\t\t\tremainingShapesToReparent.delete(shape)\n\t\t\t\tcontinue shapeCheck\n\t\t\t}\n\t\t}\n\n\t\tif (childrenToReparent.length) {\n\t\t\treparenting.set(parentShape.id, childrenToReparent)\n\t\t}\n\t}\n\n\treturn {\n\t\t// these are the shapes that will be reparented to new parents\n\t\treparenting,\n\t\t// these are the shapes that will be reparented to the page or their ancestral group\n\t\tremainingShapesToReparent,\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["shapeIds"]
7
7
  }
@@ -185,7 +185,6 @@ class TLLocalSyncClient {
185
185
  }
186
186
  isPersisting = false;
187
187
  didLastWriteError = false;
188
- // eslint-disable-next-line no-restricted-globals
189
188
  scheduledPersistTimeout = null;
190
189
  /**
191
190
  * Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too