tldraw 5.2.0-next.e2b8d10bf10e → 5.2.0

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 (420) hide show
  1. package/DOCS.md +20294 -0
  2. package/README.md +13 -1
  3. package/RELEASE_NOTES.md +2908 -0
  4. package/dist-cjs/index.d.ts +110 -23
  5. package/dist-cjs/index.js +3 -3
  6. package/dist-cjs/index.js.map +2 -2
  7. package/dist-cjs/lib/TldrawImage.js +0 -1
  8. package/dist-cjs/lib/TldrawImage.js.map +2 -2
  9. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js +2 -1
  10. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  11. package/dist-cjs/lib/defaultEmbedDefinitions.js +3 -2
  12. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  13. package/dist-cjs/lib/defaultOverlayUtils.js +11 -11
  14. package/dist-cjs/lib/defaultOverlayUtils.js.map +2 -2
  15. package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js +76 -64
  16. package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js.map +2 -2
  17. package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js +1 -1
  18. package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js.map +2 -2
  19. package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js +107 -0
  20. package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
  21. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
  22. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  23. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +12 -3
  24. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/shapes/bookmark/bookmarks.js +54 -6
  26. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  27. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +2 -1
  28. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  29. package/dist-cjs/lib/shapes/draw/getPath.js +1 -1
  30. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  31. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +45 -47
  32. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
  33. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +2 -1
  34. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js +23 -18
  36. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +2 -2
  37. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -1
  38. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -0
  40. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  41. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +11 -7
  42. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  43. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -11
  44. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  45. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +5 -1
  46. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  47. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +31 -41
  48. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  49. package/dist-cjs/lib/shapes/note/noteHelpers.js +1 -1
  50. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  51. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +28 -6
  52. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  53. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +3 -2
  54. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  55. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +3 -3
  56. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  57. package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js +17 -3
  58. package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js.map +2 -2
  59. package/dist-cjs/lib/shapes/shared/freehand/core.js +424 -0
  60. package/dist-cjs/lib/shapes/shared/freehand/core.js.map +7 -0
  61. package/dist-cjs/lib/shapes/shared/freehand/fmt.js +106 -0
  62. package/dist-cjs/lib/shapes/shared/freehand/fmt.js.map +7 -0
  63. package/dist-cjs/lib/shapes/shared/freehand/getStroke.js +6 -6
  64. package/dist-cjs/lib/shapes/shared/freehand/getStroke.js.map +2 -2
  65. package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js +320 -86
  66. package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js.map +3 -3
  67. package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js +20 -96
  68. package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js.map +3 -3
  69. package/dist-cjs/lib/shapes/shared/freehand/svg.js +55 -19
  70. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  71. package/dist-cjs/lib/shapes/shared/freehand/svgInk.js +189 -97
  72. package/dist-cjs/lib/shapes/shared/freehand/svgInk.js.map +3 -3
  73. package/dist-cjs/lib/shapes/shared/freehand/types.js.map +1 -1
  74. package/dist-cjs/lib/shapes/shared/interpolate-props.js +6 -2
  75. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  76. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +3 -0
  77. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  78. package/dist-cjs/lib/tools/HandTool/HandTool.js +16 -6
  79. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  80. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +10 -1
  81. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  82. package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js +84 -0
  83. package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js.map +7 -0
  84. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +12 -0
  85. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  86. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -0
  87. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  88. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +107 -46
  89. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  90. package/dist-cjs/lib/ui/TldrawUi.js +4 -3
  91. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  92. package/dist-cjs/lib/ui/components/A11y.js +2 -0
  93. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  94. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +14 -1
  95. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  96. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js +0 -6
  97. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js.map +2 -2
  98. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +2 -2
  99. package/dist-cjs/lib/ui/components/Dialogs.js +17 -37
  100. package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
  101. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +19 -4
  102. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
  103. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +12 -2
  104. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  105. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +47 -70
  106. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  107. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +25 -46
  108. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  109. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.js.map +2 -2
  110. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuContent.js.map +2 -2
  111. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.js.map +2 -2
  112. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js +1 -1
  113. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js.map +2 -2
  114. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +1 -0
  115. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
  116. package/dist-cjs/lib/ui/components/menu-items.js +7 -0
  117. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  118. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +2 -1
  119. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js.map +2 -2
  120. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +14 -3
  121. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
  122. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -0
  123. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  124. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -0
  125. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +2 -2
  126. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +0 -2
  127. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  128. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js +1 -2
  129. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js.map +2 -2
  130. package/dist-cjs/lib/ui/context/actions.js +70 -1
  131. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  132. package/dist-cjs/lib/ui/context/asset-urls.js +5 -8
  133. package/dist-cjs/lib/ui/context/asset-urls.js.map +2 -2
  134. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  135. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +13 -0
  136. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  137. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  138. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  139. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  140. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  141. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  142. package/dist-cjs/lib/ui/version.js +3 -3
  143. package/dist-cjs/lib/ui/version.js.map +1 -1
  144. package/dist-cjs/lib/utils/embeds/embeds.js +4 -4
  145. package/dist-cjs/lib/utils/embeds/embeds.js.map +2 -2
  146. package/dist-cjs/lib/utils/test-helpers.js +2 -2
  147. package/dist-cjs/lib/utils/test-helpers.js.map +2 -2
  148. package/dist-cjs/lib/utils/text/richText.js +3 -1
  149. package/dist-cjs/lib/utils/text/richText.js.map +2 -2
  150. package/dist-esm/index.d.mts +110 -23
  151. package/dist-esm/index.mjs +5 -3
  152. package/dist-esm/index.mjs.map +2 -2
  153. package/dist-esm/lib/TldrawImage.mjs +0 -1
  154. package/dist-esm/lib/TldrawImage.mjs.map +2 -2
  155. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs +2 -1
  156. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  157. package/dist-esm/lib/defaultEmbedDefinitions.mjs +3 -2
  158. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  159. package/dist-esm/lib/defaultOverlayUtils.mjs +11 -11
  160. package/dist-esm/lib/defaultOverlayUtils.mjs.map +2 -2
  161. package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs +77 -65
  162. package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs.map +2 -2
  163. package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs +1 -1
  164. package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs.map +2 -2
  165. package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs +87 -0
  166. package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
  167. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +9 -1
  168. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  169. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +15 -3
  170. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  171. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +54 -6
  172. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  173. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +3 -1
  174. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  175. package/dist-esm/lib/shapes/draw/getPath.mjs +1 -1
  176. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  177. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +46 -47
  178. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
  179. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +2 -1
  180. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  181. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs +23 -18
  182. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +2 -2
  183. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +2 -1
  184. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  185. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +4 -0
  186. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  187. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +12 -7
  188. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  189. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -11
  190. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  191. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +6 -1
  192. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  193. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +32 -42
  194. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  195. package/dist-esm/lib/shapes/note/noteHelpers.mjs +1 -1
  196. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  197. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +29 -6
  198. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  199. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +3 -2
  200. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  201. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +4 -3
  202. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  203. package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs +17 -3
  204. package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs.map +2 -2
  205. package/dist-esm/lib/shapes/shared/freehand/core.mjs +404 -0
  206. package/dist-esm/lib/shapes/shared/freehand/core.mjs.map +7 -0
  207. package/dist-esm/lib/shapes/shared/freehand/fmt.mjs +86 -0
  208. package/dist-esm/lib/shapes/shared/freehand/fmt.mjs.map +7 -0
  209. package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs +7 -7
  210. package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs.map +2 -2
  211. package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs +332 -86
  212. package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs.map +3 -3
  213. package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs +31 -96
  214. package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs.map +3 -3
  215. package/dist-esm/lib/shapes/shared/freehand/svg.mjs +55 -19
  216. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  217. package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs +214 -99
  218. package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs.map +3 -3
  219. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +6 -2
  220. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  221. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +4 -0
  222. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  223. package/dist-esm/lib/tools/HandTool/HandTool.mjs +16 -6
  224. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  225. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +10 -1
  226. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  227. package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs +64 -0
  228. package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs.map +7 -0
  229. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +12 -0
  230. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  231. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -0
  232. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  233. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +108 -46
  234. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  235. package/dist-esm/lib/ui/TldrawUi.mjs +4 -3
  236. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  237. package/dist-esm/lib/ui/components/A11y.mjs +2 -0
  238. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  239. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +21 -2
  240. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  241. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs +0 -6
  242. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs.map +2 -2
  243. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +2 -2
  244. package/dist-esm/lib/ui/components/Dialogs.mjs +19 -39
  245. package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
  246. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +20 -5
  247. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
  248. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +12 -2
  249. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  250. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +47 -70
  251. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  252. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +25 -46
  253. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  254. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.mjs.map +2 -2
  255. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuContent.mjs.map +2 -2
  256. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.mjs.map +2 -2
  257. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs +1 -1
  258. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs.map +2 -2
  259. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +1 -0
  260. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
  261. package/dist-esm/lib/ui/components/menu-items.mjs +7 -0
  262. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  263. package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs +2 -1
  264. package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs.map +2 -2
  265. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +14 -3
  266. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
  267. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +2 -0
  268. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  269. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +2 -0
  270. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  271. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +0 -2
  272. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  273. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs +1 -2
  274. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs.map +2 -2
  275. package/dist-esm/lib/ui/context/actions.mjs +71 -1
  276. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  277. package/dist-esm/lib/ui/context/asset-urls.mjs +5 -8
  278. package/dist-esm/lib/ui/context/asset-urls.mjs.map +2 -2
  279. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  280. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +13 -0
  281. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  282. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  283. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  284. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  285. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  286. package/dist-esm/lib/ui/version.mjs +3 -3
  287. package/dist-esm/lib/ui/version.mjs.map +1 -1
  288. package/dist-esm/lib/utils/embeds/embeds.mjs +4 -4
  289. package/dist-esm/lib/utils/embeds/embeds.mjs.map +2 -2
  290. package/dist-esm/lib/utils/test-helpers.mjs +2 -2
  291. package/dist-esm/lib/utils/test-helpers.mjs.map +2 -2
  292. package/dist-esm/lib/utils/text/richText.mjs +3 -1
  293. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  294. package/package.json +11 -6
  295. package/src/index.ts +6 -1
  296. package/src/lib/TldrawImage.tsx +2 -2
  297. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +5 -1
  298. package/src/lib/defaultEmbedDefinitions.ts +28 -6
  299. package/src/lib/defaultOverlayUtils.ts +11 -11
  300. package/src/lib/overlays/SelectionForegroundOverlayUtil.ts +91 -72
  301. package/src/lib/overlays/ShapeHandleOverlayUtil.ts +3 -1
  302. package/src/lib/overlays/ShapeIndicatorOverlayUtil.ts +133 -0
  303. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +11 -1
  304. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +16 -3
  305. package/src/lib/shapes/bookmark/bookmarks.ts +105 -15
  306. package/src/lib/shapes/draw/DrawShapeUtil.tsx +7 -5
  307. package/src/lib/shapes/draw/getPath.ts +1 -1
  308. package/src/lib/shapes/draw/toolStates/Drawing.ts +55 -48
  309. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +14 -4
  310. package/src/lib/shapes/frame/FrameShapeTool.ts +35 -24
  311. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +46 -0
  312. package/src/lib/shapes/geo/GeoShapeUtil.tsx +2 -1
  313. package/src/lib/shapes/geo/toolStates/Pointing.ts +5 -0
  314. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +14 -11
  315. package/src/lib/shapes/image/ImageShapeUtil.tsx +7 -11
  316. package/src/lib/shapes/line/LineShapeTool.test.ts +41 -0
  317. package/src/lib/shapes/line/toolStates/Pointing.ts +12 -2
  318. package/src/lib/shapes/note/NoteShapeUtil.tsx +36 -51
  319. package/src/lib/shapes/note/noteCloning.test.ts +5 -5
  320. package/src/lib/shapes/note/noteHelpers.ts +1 -1
  321. package/src/lib/shapes/note/toolStates/Pointing.ts +40 -7
  322. package/src/lib/shapes/shared/PlainTextLabel.tsx +3 -3
  323. package/src/lib/shapes/shared/RichTextLabel.tsx +4 -3
  324. package/src/lib/shapes/shared/defaultStyleDefs.tsx +25 -3
  325. package/src/lib/shapes/shared/freehand/core.ts +547 -0
  326. package/src/lib/shapes/shared/freehand/fmt.ts +106 -0
  327. package/src/lib/shapes/shared/freehand/getStroke.ts +7 -7
  328. package/src/lib/shapes/shared/freehand/getStrokeOutlinePoints.ts +451 -139
  329. package/src/lib/shapes/shared/freehand/getStrokePoints.ts +33 -153
  330. package/src/lib/shapes/shared/freehand/svg.ts +72 -23
  331. package/src/lib/shapes/shared/freehand/svgInk.ts +281 -136
  332. package/src/lib/shapes/shared/freehand/types.ts +0 -1
  333. package/src/lib/shapes/shared/interpolate-props.ts +6 -2
  334. package/src/lib/shapes/text/toolStates/Pointing.ts +5 -0
  335. package/src/lib/tools/HandTool/HandTool.ts +19 -6
  336. package/src/lib/tools/HandTool/childStates/Dragging.ts +17 -1
  337. package/src/lib/tools/HandTool/childStates/OneFingerZooming.ts +79 -0
  338. package/src/lib/tools/SelectTool/childStates/Idle.ts +16 -2
  339. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +8 -0
  340. package/src/lib/tools/SelectTool/childStates/Resizing.ts +137 -49
  341. package/src/lib/ui/TldrawUi.tsx +3 -3
  342. package/src/lib/ui/components/A11y.tsx +2 -0
  343. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +32 -2
  344. package/src/lib/ui/components/ContextMenu/DefaultContextMenuContent.tsx +5 -6
  345. package/src/lib/ui/components/DefaultFollowingIndicator.tsx +2 -2
  346. package/src/lib/ui/components/Dialogs.tsx +20 -23
  347. package/src/lib/ui/components/HelperButtons/BackToContent.tsx +32 -4
  348. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +10 -0
  349. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +60 -74
  350. package/src/lib/ui/components/Minimap/MinimapManager.ts +35 -57
  351. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.tsx +2 -2
  352. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuContent.tsx +2 -1
  353. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.tsx +2 -1
  354. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuItem.tsx +3 -3
  355. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +5 -0
  356. package/src/lib/ui/components/menu-items.tsx +9 -0
  357. package/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx +3 -1
  358. package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +15 -3
  359. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +4 -0
  360. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +7 -0
  361. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +0 -2
  362. package/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx +0 -1
  363. package/src/lib/ui/context/actions.tsx +88 -1
  364. package/src/lib/ui/context/asset-urls.tsx +9 -8
  365. package/src/lib/ui/context/events.tsx +2 -0
  366. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +45 -7
  367. package/src/lib/ui/hooks/useTools.tsx +7 -1
  368. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  369. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  370. package/src/lib/ui/version.ts +3 -3
  371. package/src/lib/ui.css +20 -9
  372. package/src/lib/utils/embeds/embeds.test.ts +14 -12
  373. package/src/lib/utils/embeds/embeds.ts +10 -4
  374. package/src/lib/utils/test-helpers.ts +3 -3
  375. package/src/lib/utils/text/richText.test.ts +36 -0
  376. package/src/lib/utils/text/richText.ts +9 -1
  377. package/src/test/HandTool.test.ts +93 -0
  378. package/src/test/ImageShapeUtil.test.ts +88 -0
  379. package/src/test/SelectTool.test.ts +102 -1
  380. package/src/test/__snapshots__/drawing.test.ts.snap +2 -1
  381. package/src/test/attribution.test.ts +40 -29
  382. package/src/test/bookmark-shapes.test.ts +256 -28
  383. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +2 -2
  384. package/src/test/commands/clipboardCallbacks.test.ts +3 -1
  385. package/src/test/commands/getSvgString.test.ts +30 -0
  386. package/src/test/commands/penmode.test.ts +97 -1
  387. package/src/test/commands/setCamera.test.ts +12 -0
  388. package/src/test/dragFromToolbar.test.ts +67 -0
  389. package/src/test/drawing.test.ts +48 -7
  390. package/src/test/frames.test.ts +72 -0
  391. package/src/test/freehand/corpus/presets.ts +71 -0
  392. package/src/test/freehand/corpus/real.ts +370 -0
  393. package/src/test/freehand/corpus/strokes.ts +50 -0
  394. package/src/test/freehand/svg.test.ts +20 -0
  395. package/src/test/freehand/wellformed.test.ts +30 -0
  396. package/src/test/long-press-create.test.ts +102 -0
  397. package/src/test/overlays/CollaboratorBrushOverlayUtil.test.ts +4 -4
  398. package/src/test/overlays/CollaboratorCursorOverlayUtil.test.ts +18 -18
  399. package/src/test/overlays/CollaboratorHintOverlayUtil.test.ts +7 -7
  400. package/src/test/overlays/CollaboratorScribbleOverlayUtil.test.ts +3 -3
  401. package/src/test/overlays/OverlayManager.test.ts +1 -1
  402. package/src/test/overlays/SelectionForegroundOverlayUtil.test.ts +58 -0
  403. package/src/test/overlays/ShapeHandleOverlayUtil.test.ts +2 -2
  404. package/src/test/overlays/ShapeIndicatorOverlayUtil.test.ts +36 -0
  405. package/src/test/resizing.test.ts +250 -0
  406. package/src/test/right-click-context-menu.test.ts +90 -0
  407. package/src/test/rightClickPanning.test.ts +11 -0
  408. package/src/test/selection-omnibus.test.ts +15 -2
  409. package/src/test/spatialIndex.test.ts +132 -0
  410. package/src/test/translating.test.ts +0 -6
  411. package/src/test/ui/ContextMenu.test.tsx +146 -3
  412. package/src/test/ui/Dialogs.test.tsx +256 -0
  413. package/src/test/ui/copyHoveredStyles.test.tsx +154 -0
  414. package/src/test/ui/keyboardShortcuts.test.tsx +266 -0
  415. package/tldraw.css +35 -12
  416. package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js +0 -100
  417. package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js.map +0 -7
  418. package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs +0 -80
  419. package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs.map +0 -7
  420. package/src/lib/shapes/shared/freehand/setStrokePointRadii.ts +0 -127
@@ -22,106 +22,30 @@ __export(getStrokePoints_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(getStrokePoints_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
- const MIN_PRESSURE = 0.025;
25
+ var import_core = require("./core");
26
26
  function getStrokePoints(rawInputPoints, options = {}) {
27
- const { streamline = 0.5, size = 16, simulatePressure = false } = options;
28
- if (rawInputPoints.length === 0) return [];
29
- const t = 0.15 + (1 - streamline) * 0.85;
30
- let pts = rawInputPoints.map(import_editor.Vec.From);
31
- let pointsRemovedFromNearEnd = 0;
32
- if (!simulatePressure) {
33
- for (const pt2 of pts) {
34
- if (pt2.z < MIN_PRESSURE) {
35
- pt2.z = MIN_PRESSURE;
36
- }
37
- }
38
- }
39
- if (pts.length === 0)
40
- return [
41
- {
42
- point: import_editor.Vec.From(rawInputPoints[0]),
43
- input: import_editor.Vec.From(rawInputPoints[0]),
44
- pressure: simulatePressure ? 0.5 : 0.15,
45
- vector: new import_editor.Vec(1, 1),
46
- distance: 0,
47
- runningLength: 0,
48
- radius: 1
49
- }
50
- ];
51
- let pt = pts[1];
52
- while (pt) {
53
- if (import_editor.Vec.Dist2(pt, pts[0]) > (size / 3) ** 2) break;
54
- pts[0].z = Math.max(pts[0].z, pt.z);
55
- pts.splice(1, 1);
56
- pt = pts[1];
57
- }
58
- const last = pts.pop();
59
- pt = pts[pts.length - 1];
60
- while (pt) {
61
- if (import_editor.Vec.Dist2(pt, last) > (size / 3) ** 2) break;
62
- pts.pop();
63
- pt = pts[pts.length - 1];
64
- pointsRemovedFromNearEnd++;
65
- }
66
- pts.push(last);
67
- const isComplete = options.last || !options.simulatePressure || pts.length > 1 && import_editor.Vec.Dist2(pts[pts.length - 1], pts[pts.length - 2]) < size ** 2 || pointsRemovedFromNearEnd > 0;
68
- if (pts.length === 2 && options.simulatePressure) {
69
- const last2 = pts[1];
70
- pts = pts.slice(0, -1);
71
- for (let i = 1; i < 5; i++) {
72
- const next = import_editor.Vec.Lrp(pts[0], last2, i / 4);
73
- next.z = (pts[0].z + (last2.z - pts[0].z)) * i / 4;
74
- pts.push(next);
75
- }
76
- }
77
- const strokePoints = [
78
- {
79
- point: pts[0],
80
- input: pts[0],
81
- pressure: simulatePressure ? 0.5 : pts[0].z,
82
- vector: new import_editor.Vec(1, 1),
83
- distance: 0,
84
- runningLength: 0,
85
- radius: 1
86
- }
87
- ];
88
- let totalLength = 0;
89
- let prev = strokePoints[0];
90
- let point, distance;
91
- if (isComplete && streamline > 0) {
92
- pts.push(pts[pts.length - 1].clone());
93
- }
94
- for (let i = 1, n = pts.length; i < n; i++) {
95
- point = !t || options.last && i === n - 1 ? pts[i].clone() : pts[i].clone().lrp(prev.point, 1 - t);
96
- if (prev.point.equals(point)) continue;
97
- distance = import_editor.Vec.Dist(point, prev.point);
98
- totalLength += distance;
99
- if (i < 4 && totalLength < size) {
100
- continue;
101
- }
102
- prev = {
103
- input: pts[i],
104
- // The adjusted point
27
+ (0, import_core.ingest)(rawInputPoints, options);
28
+ const n = import_core.pointCount;
29
+ const ptX = import_core.pointX;
30
+ const ptY = import_core.pointY;
31
+ const inX = import_core.inputX;
32
+ const inY = import_core.inputY;
33
+ const inZ = import_core.inputZ;
34
+ const press = import_core.pressures;
35
+ const dists = import_core.distances;
36
+ const runs = import_core.runningLengths;
37
+ const strokePoints = new Array(n);
38
+ for (let i = 0; i < n; i++) {
39
+ const input = new import_editor.Vec(inX[i], inY[i], inZ[i]);
40
+ const point = i === 0 ? input : new import_editor.Vec(ptX[i], ptY[i], inZ[i]);
41
+ strokePoints[i] = {
105
42
  point,
106
- // The input pressure (or .5 if not specified)
107
- pressure: simulatePressure ? 0.5 : pts[i].z,
108
- // The vector from the current point to the previous point
109
- vector: import_editor.Vec.Sub(prev.point, point).uni(),
110
- // The distance between the current point and the previous point
111
- distance,
112
- // The total distance so far
113
- runningLength: totalLength,
114
- // The stroke point's radius
43
+ input,
44
+ pressure: press[i],
45
+ distance: dists[i],
46
+ runningLength: runs[i],
115
47
  radius: 1
116
48
  };
117
- strokePoints.push(prev);
118
- }
119
- if (strokePoints[1]?.vector) {
120
- strokePoints[0].vector = strokePoints[1].vector.clone();
121
- }
122
- if (totalLength < 1) {
123
- const maxPressureAmongPoints = Math.max(0.5, ...strokePoints.map((s) => s.pressure));
124
- strokePoints.forEach((s) => s.pressure = maxPressureAmongPoints);
125
49
  }
126
50
  return strokePoints;
127
51
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/shared/freehand/getStrokePoints.ts"],
4
- "sourcesContent": ["import { Vec, VecLike } from '@tldraw/editor'\nimport type { StrokeOptions, StrokePoint } from './types'\n\nconst MIN_PRESSURE = 0.025\n\n/**\n * ## getStrokePoints\n *\n * Get an array of points as objects with an adjusted point, pressure, vector, distance, and\n * runningLength.\n *\n * @param points - An array of points (as `[x, y, pressure]` or `{x, y, pressure}`). Pressure is\n * optional in both cases.\n * @param options - An object with options.\n * @public\n */\nexport function getStrokePoints(\n\trawInputPoints: VecLike[],\n\toptions: StrokeOptions = {}\n): StrokePoint[] {\n\tconst { streamline = 0.5, size = 16, simulatePressure = false } = options\n\n\t// If we don't have any points, return an empty array.\n\tif (rawInputPoints.length === 0) return []\n\n\t// Find the interpolation level between points.\n\tconst t = 0.15 + (1 - streamline) * 0.85\n\n\t// Whatever the input is, make sure that the points are in number[][].\n\tlet pts = rawInputPoints.map(Vec.From)\n\n\tlet pointsRemovedFromNearEnd = 0\n\n\tif (!simulatePressure) {\n\t\t// Clamp any zero/near-zero pressure points to a minimum value.\n\t\t// Some pens or OSes report z=0 even while the pen is touching,\n\t\t// so we clamp rather than strip to avoid removing real input.\n\t\tfor (const pt of pts) {\n\t\t\tif (pt.z < MIN_PRESSURE) {\n\t\t\t\tpt.z = MIN_PRESSURE\n\t\t\t}\n\t\t}\n\t}\n\n\tif (pts.length === 0)\n\t\treturn [\n\t\t\t{\n\t\t\t\tpoint: Vec.From(rawInputPoints[0]),\n\t\t\t\tinput: Vec.From(rawInputPoints[0]),\n\t\t\t\tpressure: simulatePressure ? 0.5 : 0.15,\n\t\t\t\tvector: new Vec(1, 1),\n\t\t\t\tdistance: 0,\n\t\t\t\trunningLength: 0,\n\t\t\t\tradius: 1,\n\t\t\t},\n\t\t]\n\n\t// Strip points that are too close to the first point.\n\tlet pt = pts[1]\n\twhile (pt) {\n\t\tif (Vec.Dist2(pt, pts[0]) > (size / 3) ** 2) break\n\t\tpts[0].z = Math.max(pts[0].z, pt.z) // Use maximum pressure\n\t\tpts.splice(1, 1)\n\t\tpt = pts[1]\n\t}\n\n\t// Strip points that are too close to the last point.\n\tconst last = pts.pop()!\n\tpt = pts[pts.length - 1]\n\twhile (pt) {\n\t\tif (Vec.Dist2(pt, last) > (size / 3) ** 2) break\n\t\tpts.pop()\n\t\tpt = pts[pts.length - 1]\n\t\tpointsRemovedFromNearEnd++\n\t}\n\tpts.push(last)\n\n\tconst isComplete =\n\t\toptions.last ||\n\t\t!options.simulatePressure ||\n\t\t(pts.length > 1 && Vec.Dist2(pts[pts.length - 1], pts[pts.length - 2]) < size ** 2) ||\n\t\tpointsRemovedFromNearEnd > 0\n\n\t// Add extra points between the two, to help avoid \"dash\" lines\n\t// for strokes with tapered start and ends. Don't mutate the\n\t// input array!\n\tif (pts.length === 2 && options.simulatePressure) {\n\t\tconst last = pts[1]\n\t\tpts = pts.slice(0, -1)\n\t\tfor (let i = 1; i < 5; i++) {\n\t\t\tconst next = Vec.Lrp(pts[0], last, i / 4)\n\t\t\tnext.z = ((pts[0].z + (last.z - pts[0].z)) * i) / 4\n\t\t\tpts.push(next)\n\t\t}\n\t}\n\n\t// The strokePoints array will hold the points for the stroke.\n\t// Start it out with the first point, which needs no adjustment.\n\tconst strokePoints: StrokePoint[] = [\n\t\t{\n\t\t\tpoint: pts[0],\n\t\t\tinput: pts[0],\n\t\t\tpressure: simulatePressure ? 0.5 : pts[0].z,\n\t\t\tvector: new Vec(1, 1),\n\t\t\tdistance: 0,\n\t\t\trunningLength: 0,\n\t\t\tradius: 1,\n\t\t},\n\t]\n\n\t// We use the totalLength to keep track of the total distance\n\tlet totalLength = 0\n\n\t// We're set this to the latest point, so we can use it to calculate\n\t// the distance and vector of the next point.\n\tlet prev = strokePoints[0]\n\n\t// Iterate through all of the points, creating StrokePoints.\n\tlet point: Vec, distance: number\n\n\tif (isComplete && streamline > 0) {\n\t\tpts.push(pts[pts.length - 1].clone())\n\t}\n\n\tfor (let i = 1, n = pts.length; i < n; i++) {\n\t\tpoint =\n\t\t\t!t || (options.last && i === n - 1) ? pts[i].clone() : pts[i].clone().lrp(prev.point, 1 - t)\n\n\t\t// If the new point is the same as the previous point, skip ahead.\n\t\tif (prev.point.equals(point)) continue\n\n\t\t// How far is the new point from the previous point?\n\t\tdistance = Vec.Dist(point, prev.point)\n\n\t\t// Add this distance to the total \"running length\" of the line.\n\t\ttotalLength += distance\n\n\t\t// At the start of the line, we wait until the new point is a\n\t\t// certain distance away from the original point, to avoid noise\n\n\t\tif (i < 4 && totalLength < size) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Create a new strokepoint (it will be the new \"previous\" one).\n\t\tprev = {\n\t\t\tinput: pts[i],\n\t\t\t// The adjusted point\n\t\t\tpoint,\n\t\t\t// The input pressure (or .5 if not specified)\n\t\t\tpressure: simulatePressure ? 0.5 : pts[i].z,\n\t\t\t// The vector from the current point to the previous point\n\t\t\tvector: Vec.Sub(prev.point, point).uni(),\n\t\t\t// The distance between the current point and the previous point\n\t\t\tdistance,\n\t\t\t// The total distance so far\n\t\t\trunningLength: totalLength,\n\t\t\t// The stroke point's radius\n\t\t\tradius: 1,\n\t\t}\n\n\t\t// Push it to the strokePoints array.\n\t\tstrokePoints.push(prev)\n\t}\n\n\t// Set the vector of the first point to be the same as the second point.\n\tif (strokePoints[1]?.vector) {\n\t\tstrokePoints[0].vector = strokePoints[1].vector.clone()\n\t}\n\n\tif (totalLength < 1) {\n\t\tconst maxPressureAmongPoints = Math.max(0.5, ...strokePoints.map((s) => s.pressure))\n\t\tstrokePoints.forEach((s) => (s.pressure = maxPressureAmongPoints))\n\t}\n\n\treturn strokePoints\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAG7B,MAAM,eAAe;AAad,SAAS,gBACf,gBACA,UAAyB,CAAC,GACV;AAChB,QAAM,EAAE,aAAa,KAAK,OAAO,IAAI,mBAAmB,MAAM,IAAI;AAGlE,MAAI,eAAe,WAAW,EAAG,QAAO,CAAC;AAGzC,QAAM,IAAI,QAAQ,IAAI,cAAc;AAGpC,MAAI,MAAM,eAAe,IAAI,kBAAI,IAAI;AAErC,MAAI,2BAA2B;AAE/B,MAAI,CAAC,kBAAkB;AAItB,eAAWA,OAAM,KAAK;AACrB,UAAIA,IAAG,IAAI,cAAc;AACxB,QAAAA,IAAG,IAAI;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEA,MAAI,IAAI,WAAW;AAClB,WAAO;AAAA,MACN;AAAA,QACC,OAAO,kBAAI,KAAK,eAAe,CAAC,CAAC;AAAA,QACjC,OAAO,kBAAI,KAAK,eAAe,CAAC,CAAC;AAAA,QACjC,UAAU,mBAAmB,MAAM;AAAA,QACnC,QAAQ,IAAI,kBAAI,GAAG,CAAC;AAAA,QACpB,UAAU;AAAA,QACV,eAAe;AAAA,QACf,QAAQ;AAAA,MACT;AAAA,IACD;AAGD,MAAI,KAAK,IAAI,CAAC;AACd,SAAO,IAAI;AACV,QAAI,kBAAI,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,OAAO,MAAM,EAAG;AAC7C,QAAI,CAAC,EAAE,IAAI,KAAK,IAAI,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC;AAClC,QAAI,OAAO,GAAG,CAAC;AACf,SAAK,IAAI,CAAC;AAAA,EACX;AAGA,QAAM,OAAO,IAAI,IAAI;AACrB,OAAK,IAAI,IAAI,SAAS,CAAC;AACvB,SAAO,IAAI;AACV,QAAI,kBAAI,MAAM,IAAI,IAAI,KAAK,OAAO,MAAM,EAAG;AAC3C,QAAI,IAAI;AACR,SAAK,IAAI,IAAI,SAAS,CAAC;AACvB;AAAA,EACD;AACA,MAAI,KAAK,IAAI;AAEb,QAAM,aACL,QAAQ,QACR,CAAC,QAAQ,oBACR,IAAI,SAAS,KAAK,kBAAI,MAAM,IAAI,IAAI,SAAS,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC,CAAC,IAAI,QAAQ,KACjF,2BAA2B;AAK5B,MAAI,IAAI,WAAW,KAAK,QAAQ,kBAAkB;AACjD,UAAMC,QAAO,IAAI,CAAC;AAClB,UAAM,IAAI,MAAM,GAAG,EAAE;AACrB,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,YAAM,OAAO,kBAAI,IAAI,IAAI,CAAC,GAAGA,OAAM,IAAI,CAAC;AACxC,WAAK,KAAM,IAAI,CAAC,EAAE,KAAKA,MAAK,IAAI,IAAI,CAAC,EAAE,MAAM,IAAK;AAClD,UAAI,KAAK,IAAI;AAAA,IACd;AAAA,EACD;AAIA,QAAM,eAA8B;AAAA,IACnC;AAAA,MACC,OAAO,IAAI,CAAC;AAAA,MACZ,OAAO,IAAI,CAAC;AAAA,MACZ,UAAU,mBAAmB,MAAM,IAAI,CAAC,EAAE;AAAA,MAC1C,QAAQ,IAAI,kBAAI,GAAG,CAAC;AAAA,MACpB,UAAU;AAAA,MACV,eAAe;AAAA,MACf,QAAQ;AAAA,IACT;AAAA,EACD;AAGA,MAAI,cAAc;AAIlB,MAAI,OAAO,aAAa,CAAC;AAGzB,MAAI,OAAY;AAEhB,MAAI,cAAc,aAAa,GAAG;AACjC,QAAI,KAAK,IAAI,IAAI,SAAS,CAAC,EAAE,MAAM,CAAC;AAAA,EACrC;AAEA,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAI,GAAG,KAAK;AAC3C,YACC,CAAC,KAAM,QAAQ,QAAQ,MAAM,IAAI,IAAK,IAAI,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC;AAG5F,QAAI,KAAK,MAAM,OAAO,KAAK,EAAG;AAG9B,eAAW,kBAAI,KAAK,OAAO,KAAK,KAAK;AAGrC,mBAAe;AAKf,QAAI,IAAI,KAAK,cAAc,MAAM;AAChC;AAAA,IACD;AAGA,WAAO;AAAA,MACN,OAAO,IAAI,CAAC;AAAA;AAAA,MAEZ;AAAA;AAAA,MAEA,UAAU,mBAAmB,MAAM,IAAI,CAAC,EAAE;AAAA;AAAA,MAE1C,QAAQ,kBAAI,IAAI,KAAK,OAAO,KAAK,EAAE,IAAI;AAAA;AAAA,MAEvC;AAAA;AAAA,MAEA,eAAe;AAAA;AAAA,MAEf,QAAQ;AAAA,IACT;AAGA,iBAAa,KAAK,IAAI;AAAA,EACvB;AAGA,MAAI,aAAa,CAAC,GAAG,QAAQ;AAC5B,iBAAa,CAAC,EAAE,SAAS,aAAa,CAAC,EAAE,OAAO,MAAM;AAAA,EACvD;AAEA,MAAI,cAAc,GAAG;AACpB,UAAM,yBAAyB,KAAK,IAAI,KAAK,GAAG,aAAa,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AACnF,iBAAa,QAAQ,CAAC,MAAO,EAAE,WAAW,sBAAuB;AAAA,EAClE;AAEA,SAAO;AACR;",
6
- "names": ["pt", "last"]
4
+ "sourcesContent": ["import { Vec, VecLike } from '@tldraw/editor'\nimport {\n\tdistances,\n\tingest,\n\tinputX,\n\tinputY,\n\tinputZ,\n\tpointCount,\n\tpointX,\n\tpointY,\n\tpressures,\n\trunningLengths,\n} from './core'\nimport type { StrokeOptions, StrokePoint } from './types'\n\n/**\n * ## getStrokePoints\n *\n * Get an array of points as objects with an adjusted point, pressure, vector, distance, and\n * runningLength.\n *\n * @param points - An array of points (as `[x, y, pressure]` or `{x, y, pressure}`). Pressure is\n * optional in both cases.\n * @param options - An object with options.\n * @public\n */\nexport function getStrokePoints(\n\trawInputPoints: VecLike[],\n\toptions: StrokeOptions = {}\n): StrokePoint[] {\n\tingest(rawInputPoints, options)\n\n\tconst n = pointCount\n\tconst ptX = pointX\n\tconst ptY = pointY\n\tconst inX = inputX\n\tconst inY = inputY\n\tconst inZ = inputZ\n\tconst press = pressures\n\tconst dists = distances\n\tconst runs = runningLengths\n\tconst strokePoints: StrokePoint[] = new Array(n)\n\tfor (let i = 0; i < n; i++) {\n\t\tconst input = new Vec(inX[i], inY[i], inZ[i])\n\t\t// The first point needs no adjustment, so its point and input are the same vector.\n\t\tconst point = i === 0 ? input : new Vec(ptX[i], ptY[i], inZ[i])\n\t\tstrokePoints[i] = {\n\t\t\tpoint,\n\t\t\tinput,\n\t\t\tpressure: press[i],\n\t\t\tdistance: dists[i],\n\t\t\trunningLength: runs[i],\n\t\t\tradius: 1,\n\t\t}\n\t}\n\treturn strokePoints\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA6B;AAC7B,kBAWO;AAcA,SAAS,gBACf,gBACA,UAAyB,CAAC,GACV;AAChB,0BAAO,gBAAgB,OAAO;AAE9B,QAAM,IAAI;AACV,QAAM,MAAM;AACZ,QAAM,MAAM;AACZ,QAAM,MAAM;AACZ,QAAM,MAAM;AACZ,QAAM,MAAM;AACZ,QAAM,QAAQ;AACd,QAAM,QAAQ;AACd,QAAM,OAAO;AACb,QAAM,eAA8B,IAAI,MAAM,CAAC;AAC/C,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC3B,UAAM,QAAQ,IAAI,kBAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAE5C,UAAM,QAAQ,MAAM,IAAI,QAAQ,IAAI,kBAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9D,iBAAa,CAAC,IAAI;AAAA,MACjB;AAAA,MACA;AAAA,MACA,UAAU,MAAM,CAAC;AAAA,MACjB,UAAU,MAAM,CAAC;AAAA,MACjB,eAAe,KAAK,CAAC;AAAA,MACrB,QAAQ;AAAA,IACT;AAAA,EACD;AACA,SAAO;AACR;",
6
+ "names": []
7
7
  }
@@ -21,36 +21,72 @@ __export(svg_exports, {
21
21
  getSvgPathFromStrokePoints: () => getSvgPathFromStrokePoints
22
22
  });
23
23
  module.exports = __toCommonJS(svg_exports);
24
- var import_editor = require("@tldraw/editor");
24
+ var import_fmt = require("./fmt");
25
25
  function getSvgPathFromStrokePoints(points, closed = false) {
26
26
  const len = points.length;
27
27
  if (len < 2) {
28
28
  return "";
29
29
  }
30
- let a = points[0].point;
31
- let b = points[1].point;
30
+ (0, import_fmt.resetPath)();
32
31
  if (len === 2) {
33
- return `M${(0, import_editor.precise)(a)}L${(0, import_editor.precise)(b)}`;
32
+ const a = points[0].point;
33
+ const b = points[1].point;
34
+ const ax = (0, import_fmt.toCenti)(a.x);
35
+ const ay = (0, import_fmt.toCenti)(a.y);
36
+ (0, import_fmt.writeStr)("M");
37
+ (0, import_fmt.writeCPair)(ax, ay);
38
+ (0, import_fmt.writeStr)("l");
39
+ (0, import_fmt.writeCPair)((0, import_fmt.toCenti)(b.x) - ax, (0, import_fmt.toCenti)(b.y) - ay);
40
+ return (0, import_fmt.finishPath)();
41
+ }
42
+ const first = points[0].point;
43
+ const second = points[1].point;
44
+ const third = points[2].point;
45
+ const secondX = (0, import_fmt.toCenti)(second.x);
46
+ const secondY = (0, import_fmt.toCenti)(second.y);
47
+ const m01x = Math.round((first.x + second.x) * 50);
48
+ const m01y = Math.round((first.y + second.y) * 50);
49
+ const m12x = Math.round((second.x + third.x) * 50);
50
+ const m12y = Math.round((second.y + third.y) * 50);
51
+ let cx = m12x;
52
+ let cy = m12y;
53
+ if (closed) {
54
+ (0, import_fmt.writeStr)("M");
55
+ (0, import_fmt.writeCPair)(m01x, m01y);
56
+ (0, import_fmt.writeStr)("q");
57
+ (0, import_fmt.writeCPair)(secondX - m01x, secondY - m01y);
58
+ (0, import_fmt.writeCPair)(m12x - m01x, m12y - m01y);
59
+ (0, import_fmt.writeStr)("t");
60
+ } else {
61
+ const firstX = (0, import_fmt.toCenti)(first.x);
62
+ const firstY = (0, import_fmt.toCenti)(first.y);
63
+ (0, import_fmt.writeStr)("M");
64
+ (0, import_fmt.writeCPair)(firstX, firstY);
65
+ (0, import_fmt.writeStr)("q");
66
+ (0, import_fmt.writeCPair)(secondX - firstX, secondY - firstY);
67
+ (0, import_fmt.writeCPair)(m12x - firstX, m12y - firstY);
68
+ if (len > 3) (0, import_fmt.writeStr)("t");
34
69
  }
35
- let result = "";
36
70
  for (let i = 2, max = len - 1; i < max; i++) {
37
- a = points[i].point;
38
- b = points[i + 1].point;
39
- result += (0, import_editor.average)(a, b);
71
+ const p = points[i].point;
72
+ const q = points[i + 1].point;
73
+ const mx = Math.round((p.x + q.x) * 50);
74
+ const my = Math.round((p.y + q.y) * 50);
75
+ (0, import_fmt.writeCPair)(mx - cx, my - cy);
76
+ cx = mx;
77
+ cy = my;
40
78
  }
79
+ const last = points[len - 1].point;
41
80
  if (closed) {
42
- return `M${(0, import_editor.average)(points[0].point, points[1].point)}Q${(0, import_editor.precise)(points[1].point)}${(0, import_editor.average)(
43
- points[1].point,
44
- points[2].point
45
- )}T${result}${(0, import_editor.average)(points[len - 1].point, points[0].point)}${(0, import_editor.average)(
46
- points[0].point,
47
- points[1].point
48
- )}Z`;
81
+ const mLastX = Math.round((last.x + first.x) * 50);
82
+ const mLastY = Math.round((last.y + first.y) * 50);
83
+ (0, import_fmt.writeCPair)(mLastX - cx, mLastY - cy);
84
+ (0, import_fmt.writeCPair)(m01x - mLastX, m01y - mLastY);
85
+ (0, import_fmt.writeStr)("Z");
49
86
  } else {
50
- return `M${(0, import_editor.precise)(points[0].point)}Q${(0, import_editor.precise)(points[1].point)}${(0, import_editor.average)(
51
- points[1].point,
52
- points[2].point
53
- )}${points.length > 3 ? "T" : ""}${result}L${(0, import_editor.precise)(points[len - 1].point)}`;
87
+ (0, import_fmt.writeStr)("l");
88
+ (0, import_fmt.writeCPair)((0, import_fmt.toCenti)(last.x) - cx, (0, import_fmt.toCenti)(last.y) - cy);
54
89
  }
90
+ return (0, import_fmt.finishPath)();
55
91
  }
56
92
  //# sourceMappingURL=svg.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/shared/freehand/svg.ts"],
4
- "sourcesContent": ["import { average, precise } from '@tldraw/editor'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadratic curves.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n *\n * @public\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tlet a = points[0].point\n\tlet b = points[1].point\n\n\tif (len === 2) {\n\t\treturn `M${precise(a)}L${precise(b)}`\n\t}\n\n\tlet result = ''\n\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\ta = points[i].point\n\t\tb = points[i + 1].point\n\t\tresult += average(a, b)\n\t}\n\n\tif (closed) {\n\t\t// If closed, draw a curve from the last point to the first\n\t\treturn `M${average(points[0].point, points[1].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}T${result}${average(points[len - 1].point, points[0].point)}${average(\n\t\t\tpoints[0].point,\n\t\t\tpoints[1].point\n\t\t)}Z`\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the last and second-last point, then\n\t\t// complete the curve with a line segment to the last point.\n\t\treturn `M${precise(points[0].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}${points.length > 3 ? 'T' : ''}${result}L${precise(points[len - 1].point)}`\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiC;AAW1B,SAAS,2BAA2B,QAAuB,SAAS,OAAe;AACzF,QAAM,MAAM,OAAO;AAEnB,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,OAAO,CAAC,EAAE;AAClB,MAAI,IAAI,OAAO,CAAC,EAAE;AAElB,MAAI,QAAQ,GAAG;AACd,WAAO,QAAI,uBAAQ,CAAC,CAAC,QAAI,uBAAQ,CAAC,CAAC;AAAA,EACpC;AAEA,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;AAC5C,QAAI,OAAO,CAAC,EAAE;AACd,QAAI,OAAO,IAAI,CAAC,EAAE;AAClB,kBAAU,uBAAQ,GAAG,CAAC;AAAA,EACvB;AAEA,MAAI,QAAQ;AAEX,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAClF,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,IAAI,MAAM,OAAG,uBAAQ,OAAO,MAAM,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAC/D,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AAIN,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MACjE,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,GAAG,MAAM,QAAI,uBAAQ,OAAO,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC5E;AACD;",
4
+ "sourcesContent": ["import { finishPath, resetPath, toCenti, writeCPair, writeStr } from './fmt'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadratic curves.\n *\n * The path uses relative commands with coordinates rounded to hundredths of a pixel, which\n * renders identically to the absolute 4-decimal form but is much smaller and faster to build.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n *\n * @public\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tresetPath()\n\n\tif (len === 2) {\n\t\tconst a = points[0].point\n\t\tconst b = points[1].point\n\t\tconst ax = toCenti(a.x)\n\t\tconst ay = toCenti(a.y)\n\t\twriteStr('M')\n\t\twriteCPair(ax, ay)\n\t\twriteStr('l')\n\t\twriteCPair(toCenti(b.x) - ax, toCenti(b.y) - ay)\n\t\treturn finishPath()\n\t}\n\n\tconst first = points[0].point\n\tconst second = points[1].point\n\tconst third = points[2].point\n\n\tconst secondX = toCenti(second.x)\n\tconst secondY = toCenti(second.y)\n\t// midpoint of the first and second points\n\tconst m01x = Math.round((first.x + second.x) * 50)\n\tconst m01y = Math.round((first.y + second.y) * 50)\n\t// midpoint of the second and third points\n\tconst m12x = Math.round((second.x + third.x) * 50)\n\tconst m12y = Math.round((second.y + third.y) * 50)\n\n\t// Current position in integer hundredths\n\tlet cx = m12x\n\tlet cy = m12y\n\n\tif (closed) {\n\t\t// If closed, start at the first midpoint and draw a curve through the second point\n\t\twriteStr('M')\n\t\twriteCPair(m01x, m01y)\n\t\twriteStr('q')\n\t\twriteCPair(secondX - m01x, secondY - m01y)\n\t\twriteCPair(m12x - m01x, m12y - m01y)\n\t\twriteStr('t')\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the second and third points.\n\t\tconst firstX = toCenti(first.x)\n\t\tconst firstY = toCenti(first.y)\n\t\twriteStr('M')\n\t\twriteCPair(firstX, firstY)\n\t\twriteStr('q')\n\t\twriteCPair(secondX - firstX, secondY - firstY)\n\t\twriteCPair(m12x - firstX, m12y - firstY)\n\t\tif (len > 3) writeStr('t')\n\t}\n\n\t// Continue the smooth quadratic chain through the midpoints of the remaining points\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\tconst p = points[i].point\n\t\tconst q = points[i + 1].point\n\t\tconst mx = Math.round((p.x + q.x) * 50)\n\t\tconst my = Math.round((p.y + q.y) * 50)\n\t\twriteCPair(mx - cx, my - cy)\n\t\tcx = mx\n\t\tcy = my\n\t}\n\n\tconst last = points[len - 1].point\n\n\tif (closed) {\n\t\t// Draw a curve from the last-first midpoint back to the first-second midpoint\n\t\tconst mLastX = Math.round((last.x + first.x) * 50)\n\t\tconst mLastY = Math.round((last.y + first.y) * 50)\n\t\twriteCPair(mLastX - cx, mLastY - cy)\n\t\twriteCPair(m01x - mLastX, m01y - mLastY)\n\t\twriteStr('Z')\n\t} else {\n\t\t// Complete the curve with a line segment to the last point.\n\t\twriteStr('l')\n\t\twriteCPair(toCenti(last.x) - cx, toCenti(last.y) - cy)\n\t}\n\n\treturn finishPath()\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAqE;AAc9D,SAAS,2BAA2B,QAAuB,SAAS,OAAe;AACzF,QAAM,MAAM,OAAO;AAEnB,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,4BAAU;AAEV,MAAI,QAAQ,GAAG;AACd,UAAM,IAAI,OAAO,CAAC,EAAE;AACpB,UAAM,IAAI,OAAO,CAAC,EAAE;AACpB,UAAM,SAAK,oBAAQ,EAAE,CAAC;AACtB,UAAM,SAAK,oBAAQ,EAAE,CAAC;AACtB,6BAAS,GAAG;AACZ,+BAAW,IAAI,EAAE;AACjB,6BAAS,GAAG;AACZ,mCAAW,oBAAQ,EAAE,CAAC,IAAI,QAAI,oBAAQ,EAAE,CAAC,IAAI,EAAE;AAC/C,eAAO,uBAAW;AAAA,EACnB;AAEA,QAAM,QAAQ,OAAO,CAAC,EAAE;AACxB,QAAM,SAAS,OAAO,CAAC,EAAE;AACzB,QAAM,QAAQ,OAAO,CAAC,EAAE;AAExB,QAAM,cAAU,oBAAQ,OAAO,CAAC;AAChC,QAAM,cAAU,oBAAQ,OAAO,CAAC;AAEhC,QAAM,OAAO,KAAK,OAAO,MAAM,IAAI,OAAO,KAAK,EAAE;AACjD,QAAM,OAAO,KAAK,OAAO,MAAM,IAAI,OAAO,KAAK,EAAE;AAEjD,QAAM,OAAO,KAAK,OAAO,OAAO,IAAI,MAAM,KAAK,EAAE;AACjD,QAAM,OAAO,KAAK,OAAO,OAAO,IAAI,MAAM,KAAK,EAAE;AAGjD,MAAI,KAAK;AACT,MAAI,KAAK;AAET,MAAI,QAAQ;AAEX,6BAAS,GAAG;AACZ,+BAAW,MAAM,IAAI;AACrB,6BAAS,GAAG;AACZ,+BAAW,UAAU,MAAM,UAAU,IAAI;AACzC,+BAAW,OAAO,MAAM,OAAO,IAAI;AACnC,6BAAS,GAAG;AAAA,EACb,OAAO;AAGN,UAAM,aAAS,oBAAQ,MAAM,CAAC;AAC9B,UAAM,aAAS,oBAAQ,MAAM,CAAC;AAC9B,6BAAS,GAAG;AACZ,+BAAW,QAAQ,MAAM;AACzB,6BAAS,GAAG;AACZ,+BAAW,UAAU,QAAQ,UAAU,MAAM;AAC7C,+BAAW,OAAO,QAAQ,OAAO,MAAM;AACvC,QAAI,MAAM,EAAG,0BAAS,GAAG;AAAA,EAC1B;AAGA,WAAS,IAAI,GAAG,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;AAC5C,UAAM,IAAI,OAAO,CAAC,EAAE;AACpB,UAAM,IAAI,OAAO,IAAI,CAAC,EAAE;AACxB,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;AACtC,UAAM,KAAK,KAAK,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;AACtC,+BAAW,KAAK,IAAI,KAAK,EAAE;AAC3B,SAAK;AACL,SAAK;AAAA,EACN;AAEA,QAAM,OAAO,OAAO,MAAM,CAAC,EAAE;AAE7B,MAAI,QAAQ;AAEX,UAAM,SAAS,KAAK,OAAO,KAAK,IAAI,MAAM,KAAK,EAAE;AACjD,UAAM,SAAS,KAAK,OAAO,KAAK,IAAI,MAAM,KAAK,EAAE;AACjD,+BAAW,SAAS,IAAI,SAAS,EAAE;AACnC,+BAAW,OAAO,QAAQ,OAAO,MAAM;AACvC,6BAAS,GAAG;AAAA,EACb,OAAO;AAEN,6BAAS,GAAG;AACZ,mCAAW,oBAAQ,KAAK,CAAC,IAAI,QAAI,oBAAQ,KAAK,CAAC,IAAI,EAAE;AAAA,EACtD;AAEA,aAAO,uBAAW;AACnB;",
6
6
  "names": []
7
7
  }
@@ -22,9 +22,9 @@ __export(svgInk_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(svgInk_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
+ var import_core = require("./core");
26
+ var import_fmt = require("./fmt");
25
27
  var import_getStrokeOutlinePoints = require("./getStrokeOutlinePoints");
26
- var import_getStrokePoints = require("./getStrokePoints");
27
- var import_setStrokePointRadii = require("./setStrokePointRadii");
28
28
  function svgInk(rawInputPoints, options = {}) {
29
29
  const { start = {}, end = {} } = options;
30
30
  const { cap: capStart = true } = start;
@@ -32,128 +32,220 @@ function svgInk(rawInputPoints, options = {}) {
32
32
  (0, import_editor.assert)(!start.taper && !end.taper, "cap taper not supported here");
33
33
  (0, import_editor.assert)(!start.easing && !end.easing, "cap easing not supported here");
34
34
  (0, import_editor.assert)(capStart && capEnd, "cap must be true");
35
- const points = (0, import_getStrokePoints.getStrokePoints)(rawInputPoints, options);
36
- (0, import_setStrokePointRadii.setStrokePointRadii)(points, options);
37
- const partitions = partitionAtElbows(points);
38
- let svg = "";
39
- for (const partition of partitions) {
40
- svg += renderPartition(partition, options);
41
- }
42
- return svg;
35
+ (0, import_core.ingest)(rawInputPoints, options);
36
+ (0, import_core.computeRadii)(options);
37
+ (0, import_fmt.resetPath)();
38
+ partitionAtElbows(options);
39
+ return (0, import_fmt.finishPath)();
43
40
  }
44
- function partitionAtElbows(points) {
45
- if (points.length <= 2) return [points];
46
- const result = [];
47
- let currentPartition = [points[0]];
48
- let prevV = import_editor.Vec.Sub(points[1].point, points[0].point).uni();
49
- let nextV;
50
- let dpr;
51
- let prevPoint, thisPoint, nextPoint;
52
- for (let i = 1, n = points.length; i < n - 1; i++) {
53
- prevPoint = points[i - 1];
54
- thisPoint = points[i];
55
- nextPoint = points[i + 1];
56
- nextV = import_editor.Vec.Sub(nextPoint.point, thisPoint.point).uni();
57
- dpr = import_editor.Vec.Dpr(prevV, nextV);
58
- prevV = nextV;
41
+ function partitionAtElbows(options) {
42
+ const n = import_core.pointCount;
43
+ if (n === 0) return;
44
+ if (n <= 2) {
45
+ (0, import_core.loadSrcFromPipeline)();
46
+ renderPartition(options, false, 0, 0);
47
+ return;
48
+ }
49
+ const ptX = import_core.pointX;
50
+ const ptY = import_core.pointY;
51
+ const rads = import_core.radii;
52
+ let a = 0;
53
+ let aElbow = false;
54
+ let hasAnchor = false;
55
+ let anchorX = 0;
56
+ let anchorY = 0;
57
+ let dx = ptX[1] - ptX[0];
58
+ let dy = ptY[1] - ptY[0];
59
+ let len = Math.sqrt(dx * dx + dy * dy);
60
+ let prevVx = dx / len;
61
+ let prevVy = dy / len;
62
+ for (let i = 1; i < n - 1; i++) {
63
+ dx = ptX[i + 1] - ptX[i];
64
+ dy = ptY[i + 1] - ptY[i];
65
+ len = Math.sqrt(dx * dx + dy * dy);
66
+ const nextVx = dx / len;
67
+ const nextVy = dy / len;
68
+ const dpr = prevVx * nextVx + prevVy * nextVy;
69
+ prevVx = nextVx;
70
+ prevVy = nextVy;
59
71
  if (dpr < -0.8) {
60
- const elbowPoint = {
61
- ...thisPoint,
62
- point: thisPoint.input
63
- };
64
- currentPartition.push(elbowPoint);
65
- result.push(cleanUpPartition(currentPartition));
66
- currentPartition = [elbowPoint];
72
+ finishPartition(a, aElbow, i, true, false, hasAnchor, anchorX, anchorY, options);
73
+ a = i;
74
+ aElbow = true;
75
+ hasAnchor = true;
76
+ anchorX = ptX[i];
77
+ anchorY = ptY[i];
67
78
  continue;
68
79
  }
69
- currentPartition.push(thisPoint);
70
80
  if (dpr > 0.7) {
71
81
  continue;
72
82
  }
73
- if ((import_editor.Vec.Dist2(prevPoint.point, thisPoint.point) + import_editor.Vec.Dist2(thisPoint.point, nextPoint.point)) / ((prevPoint.radius + thisPoint.radius + nextPoint.radius) / 3) ** 2 < 1.5) {
74
- currentPartition.push(thisPoint);
75
- result.push(cleanUpPartition(currentPartition));
76
- currentPartition = [thisPoint];
83
+ const pdx = ptX[i] - ptX[i - 1];
84
+ const pdy = ptY[i] - ptY[i - 1];
85
+ const ndx = ptX[i + 1] - ptX[i];
86
+ const ndy = ptY[i + 1] - ptY[i];
87
+ const meanRadius = (rads[i - 1] + rads[i] + rads[i + 1]) / 3;
88
+ if ((pdx * pdx + pdy * pdy + ndx * ndx + ndy * ndy) / (meanRadius * meanRadius) < 1.5) {
89
+ finishPartition(a, aElbow, i, false, true, hasAnchor, anchorX, anchorY, options);
90
+ a = i;
91
+ aElbow = false;
92
+ hasAnchor = false;
77
93
  continue;
78
94
  }
79
95
  }
80
- currentPartition.push(points[points.length - 1]);
81
- result.push(cleanUpPartition(currentPartition));
82
- return result;
96
+ finishPartition(a, aElbow, n - 1, false, false, hasAnchor, anchorX, anchorY, options);
83
97
  }
84
- function cleanUpPartition(partition) {
85
- const startPoint = partition[0];
86
- let nextPoint;
87
- while (partition.length > 2) {
88
- nextPoint = partition[1];
89
- if (import_editor.Vec.Dist2(startPoint.point, nextPoint.point) < ((startPoint.radius + nextPoint.radius) / 2 * 0.5) ** 2) {
90
- partition.splice(1, 1);
98
+ function finishPartition(a, aElbow, b, bElbow, bDup, hasAnchor, anchorX, anchorY, options) {
99
+ const ptX = import_core.pointX;
100
+ const ptY = import_core.pointY;
101
+ const rads = import_core.radii;
102
+ const len = b - a + 1 + (bDup ? 1 : 0);
103
+ let s = 0;
104
+ let e = 0;
105
+ const startX = aElbow ? import_core.inputX[a] : ptX[a];
106
+ const startY = aElbow ? import_core.inputY[a] : ptY[a];
107
+ const startRadius = rads[a];
108
+ while (len - s > 2) {
109
+ const i = a + 1 + s;
110
+ const dx = startX - ptX[i];
111
+ const dy = startY - ptY[i];
112
+ if (dx * dx + dy * dy < ((startRadius + rads[i]) / 2 * 0.5) ** 2) {
113
+ hasAnchor = true;
114
+ anchorX = ptX[i];
115
+ anchorY = ptY[i];
116
+ s++;
91
117
  } else {
92
118
  break;
93
119
  }
94
120
  }
95
- const endPoint = partition[partition.length - 1];
96
- let prevPoint;
97
- while (partition.length > 2) {
98
- prevPoint = partition[partition.length - 2];
99
- if (import_editor.Vec.Dist2(endPoint.point, prevPoint.point) < ((endPoint.radius + prevPoint.radius) / 2 * 0.5) ** 2) {
100
- partition.splice(partition.length - 2, 1);
121
+ const endX = bElbow ? import_core.inputX[b] : ptX[b];
122
+ const endY = bElbow ? import_core.inputY[b] : ptY[b];
123
+ const endRadius = rads[b];
124
+ while (len - s - e > 2) {
125
+ const i = bDup ? b - e : b - 1 - e;
126
+ const dx = endX - ptX[i];
127
+ const dy = endY - ptY[i];
128
+ if (dx * dx + dy * dy < ((endRadius + rads[i]) / 2 * 0.5) ** 2) {
129
+ e++;
101
130
  } else {
102
131
  break;
103
132
  }
104
133
  }
105
- if (partition.length > 1) {
106
- partition[0] = {
107
- ...partition[0],
108
- vector: import_editor.Vec.Sub(partition[0].point, partition[1].point).uni()
109
- };
110
- partition[partition.length - 1] = {
111
- ...partition[partition.length - 1],
112
- vector: import_editor.Vec.Sub(
113
- partition[partition.length - 2].point,
114
- partition[partition.length - 1].point
115
- ).uni()
116
- };
117
- }
118
- return partition;
134
+ const innerStart = a + 1 + s;
135
+ const innerEnd = bDup ? b - e : b - 1 - e;
136
+ (0, import_core.loadSrcPartition)(a, aElbow, innerStart, innerEnd, b, bElbow, bDup && e === 0);
137
+ renderPartition(options, hasAnchor, anchorX, anchorY);
138
+ }
139
+ function writeCirclePath(cx, cy, r) {
140
+ const ncx = (0, import_fmt.toCenti)(cx);
141
+ const ncy = (0, import_fmt.toCenti)(cy);
142
+ const nr = (0, import_fmt.toCenti)(r);
143
+ (0, import_fmt.writeStr)("M ");
144
+ (0, import_fmt.writeC)(ncx);
145
+ (0, import_fmt.writeStr)(" ");
146
+ (0, import_fmt.writeC)(ncy);
147
+ (0, import_fmt.writeStr)(" m -");
148
+ (0, import_fmt.writeC)(nr);
149
+ (0, import_fmt.writeStr)(", 0 a ");
150
+ (0, import_fmt.writeC)(nr);
151
+ (0, import_fmt.writeStr)(",");
152
+ (0, import_fmt.writeC)(nr);
153
+ (0, import_fmt.writeStr)(" 0 1,1 ");
154
+ (0, import_fmt.writeC)(nr * 2);
155
+ (0, import_fmt.writeStr)(",0 a ");
156
+ (0, import_fmt.writeC)(nr);
157
+ (0, import_fmt.writeStr)(",");
158
+ (0, import_fmt.writeC)(nr);
159
+ (0, import_fmt.writeStr)(" 0 1,1 -");
160
+ (0, import_fmt.writeC)(nr * 2);
161
+ (0, import_fmt.writeStr)(",0");
119
162
  }
120
- function circlePath(cx, cy, r) {
121
- return "M " + cx + " " + cy + " m -" + r + ", 0 a " + r + "," + r + " 0 1,1 " + r * 2 + ",0 a " + r + "," + r + " 0 1,1 -" + r * 2 + ",0";
163
+ function writeCapArc(nr, dx, dy) {
164
+ (0, import_fmt.writeStr)("a");
165
+ (0, import_fmt.writeC)(nr);
166
+ (0, import_fmt.writeStr)(",");
167
+ (0, import_fmt.writeC)(nr);
168
+ (0, import_fmt.writeStr)(" 0 0 1 ");
169
+ (0, import_fmt.writeCPair)(dx, dy);
122
170
  }
123
- function renderPartition(strokePoints, options = {}) {
124
- if (strokePoints.length === 0) return "";
125
- if (strokePoints.length === 1) {
126
- return circlePath(strokePoints[0].point.x, strokePoints[0].point.y, strokePoints[0].radius);
171
+ function renderPartition(options, hasAnchor, anchorX, anchorY) {
172
+ const n = import_core.srcCount;
173
+ if (n === 0) return;
174
+ if (n === 1) {
175
+ writeCirclePath(import_core.srcX[0], import_core.srcY[0], import_core.srcRadius[0]);
176
+ return;
127
177
  }
128
- const { left, right } = (0, import_getStrokeOutlinePoints.getStrokeOutlineTracks)(strokePoints, options);
129
- right.reverse();
130
- let svg = `M${(0, import_editor.precise)(left[0])}T`;
131
- for (let i = 1; i < left.length; i++) {
132
- svg += (0, import_editor.average)(left[i - 1], left[i]);
178
+ (0, import_getStrokeOutlinePoints.buildTracks)(options, hasAnchor, anchorX, anchorY);
179
+ const lxs = import_getStrokeOutlinePoints.trackLeftX;
180
+ const lys = import_getStrokeOutlinePoints.trackLeftY;
181
+ const rxs = import_getStrokeOutlinePoints.trackRightX;
182
+ const rys = import_getStrokeOutlinePoints.trackRightY;
183
+ let cx = (0, import_fmt.toCenti)(lxs[0]);
184
+ let cy = (0, import_fmt.toCenti)(lys[0]);
185
+ (0, import_fmt.writeStr)("M");
186
+ (0, import_fmt.writeCPair)(cx, cy);
187
+ (0, import_fmt.writeStr)("t");
188
+ let prevX = lxs[0];
189
+ let prevY = lys[0];
190
+ for (let i = 1; i < import_getStrokeOutlinePoints.trackLeftCount; i++) {
191
+ const ptX = lxs[i];
192
+ const ptY = lys[i];
193
+ const mx = Math.round((prevX + ptX) * 50);
194
+ const my = Math.round((prevY + ptY) * 50);
195
+ (0, import_fmt.writeCPair)(mx - cx, my - cy);
196
+ cx = mx;
197
+ cy = my;
198
+ prevX = ptX;
199
+ prevY = ptY;
133
200
  }
134
201
  {
135
- const point = strokePoints[strokePoints.length - 1];
136
- const radius = point.radius;
137
- const direction = point.vector.clone().per().neg();
138
- const arcStart = import_editor.Vec.Add(point.point, import_editor.Vec.Mul(direction, radius));
139
- const arcEnd = import_editor.Vec.Add(point.point, import_editor.Vec.Mul(direction, -radius));
140
- svg += `${(0, import_editor.precise)(arcStart)}A${(0, import_editor.toDomPrecision)(radius)},${(0, import_editor.toDomPrecision)(
141
- radius
142
- )} 0 0 1 ${(0, import_editor.precise)(arcEnd)}T`;
202
+ const pointX2 = import_core.srcX[n - 1];
203
+ const pointY2 = import_core.srcY[n - 1];
204
+ const radius = import_core.srcRadius[n - 1];
205
+ const vdx = import_core.srcX[n - 2] - pointX2;
206
+ const vdy = import_core.srcY[n - 2] - pointY2;
207
+ const vlen = Math.sqrt(vdx * vdx + vdy * vdy);
208
+ const dx = -vdy / vlen * radius;
209
+ const dy = vdx / vlen * radius;
210
+ const asx = (0, import_fmt.toCenti)(pointX2 + dx);
211
+ const asy = (0, import_fmt.toCenti)(pointY2 + dy);
212
+ const aex = (0, import_fmt.toCenti)(pointX2 - dx);
213
+ const aey = (0, import_fmt.toCenti)(pointY2 - dy);
214
+ (0, import_fmt.writeCPair)(asx - cx, asy - cy);
215
+ writeCapArc((0, import_fmt.toCenti)(radius), aex - asx, aey - asy);
216
+ (0, import_fmt.writeStr)("t");
217
+ cx = aex;
218
+ cy = aey;
143
219
  }
144
- for (let i = 1; i < right.length; i++) {
145
- svg += (0, import_editor.average)(right[i - 1], right[i]);
220
+ prevX = rxs[import_getStrokeOutlinePoints.trackRightCount - 1];
221
+ prevY = rys[import_getStrokeOutlinePoints.trackRightCount - 1];
222
+ for (let i = import_getStrokeOutlinePoints.trackRightCount - 2; i >= 0; i--) {
223
+ const ptX = rxs[i];
224
+ const ptY = rys[i];
225
+ const mx = Math.round((prevX + ptX) * 50);
226
+ const my = Math.round((prevY + ptY) * 50);
227
+ (0, import_fmt.writeCPair)(mx - cx, my - cy);
228
+ cx = mx;
229
+ cy = my;
230
+ prevX = ptX;
231
+ prevY = ptY;
146
232
  }
147
233
  {
148
- const point = strokePoints[0];
149
- const radius = point.radius;
150
- const direction = point.vector.clone().per();
151
- const arcStart = import_editor.Vec.Add(point.point, import_editor.Vec.Mul(direction, radius));
152
- const arcEnd = import_editor.Vec.Add(point.point, import_editor.Vec.Mul(direction, -radius));
153
- svg += `${(0, import_editor.precise)(arcStart)}A${(0, import_editor.toDomPrecision)(radius)},${(0, import_editor.toDomPrecision)(
154
- radius
155
- )} 0 0 1 ${(0, import_editor.precise)(arcEnd)}Z`;
234
+ const pointX2 = import_core.srcX[0];
235
+ const pointY2 = import_core.srcY[0];
236
+ const radius = import_core.srcRadius[0];
237
+ const vdx = pointX2 - import_core.srcX[1];
238
+ const vdy = pointY2 - import_core.srcY[1];
239
+ const vlen = Math.sqrt(vdx * vdx + vdy * vdy);
240
+ const dx = vdy / vlen * radius;
241
+ const dy = -vdx / vlen * radius;
242
+ const asx = (0, import_fmt.toCenti)(pointX2 + dx);
243
+ const asy = (0, import_fmt.toCenti)(pointY2 + dy);
244
+ const aex = (0, import_fmt.toCenti)(pointX2 - dx);
245
+ const aey = (0, import_fmt.toCenti)(pointY2 - dy);
246
+ (0, import_fmt.writeCPair)(asx - cx, asy - cy);
247
+ writeCapArc((0, import_fmt.toCenti)(radius), aex - asx, aey - asy);
248
+ (0, import_fmt.writeStr)("Z");
156
249
  }
157
- return svg;
158
250
  }
159
251
  //# sourceMappingURL=svgInk.js.map