tldraw 3.16.0-internal.51e99e128bd4 → 3.16.0-internal.71f83a8a571b

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 (310) hide show
  1. package/dist-cjs/index.d.ts +177 -110
  2. package/dist-cjs/index.js +29 -14
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/Tldraw.js +12 -2
  5. package/dist-cjs/lib/Tldraw.js.map +2 -2
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  9. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  10. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +1 -1
  12. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  13. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  15. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +8 -1
  16. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  17. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -2
  18. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  19. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
  20. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  21. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  22. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  24. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  26. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  28. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  29. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  30. package/dist-cjs/lib/shapes/shared/crop.js +1 -0
  31. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  32. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -4
  33. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  34. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  35. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  36. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  37. package/dist-cjs/lib/shapes/text/PlainTextArea.js +2 -2
  38. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  39. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  40. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
  42. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  43. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  44. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  46. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  48. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  49. package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
  50. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  52. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  53. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  54. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  56. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  58. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  60. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  61. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  62. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  63. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  64. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  65. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  66. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  67. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  68. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  69. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  70. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  72. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  74. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  76. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +11 -2
  78. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +62 -36
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  87. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +5 -5
  88. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +1 -1
  89. package/dist-cjs/lib/ui/context/actions.js +23 -10
  90. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  91. package/dist-cjs/lib/ui/context/components.js +2 -0
  92. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  93. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  94. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  95. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  96. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  97. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  98. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  99. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  100. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  101. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -2
  102. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  103. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  104. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  105. package/dist-cjs/lib/ui/version.js +3 -3
  106. package/dist-cjs/lib/ui/version.js.map +1 -1
  107. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +1 -1
  108. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  109. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  110. package/dist-cjs/lib/utils/export/export.js +0 -20
  111. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  112. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  113. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  114. package/dist-esm/index.d.mts +177 -110
  115. package/dist-esm/index.mjs +57 -29
  116. package/dist-esm/index.mjs.map +2 -2
  117. package/dist-esm/lib/Tldraw.mjs +14 -4
  118. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  119. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  120. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  121. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  122. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  123. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +1 -1
  125. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
  126. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  128. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +8 -1
  129. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  130. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +3 -3
  131. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  132. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
  133. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  134. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  135. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  136. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
  137. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  138. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  139. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  140. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  141. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  142. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  143. package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
  144. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  145. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +4 -5
  146. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  147. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  148. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  149. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  150. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -3
  151. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  152. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  153. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  154. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
  155. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  156. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  157. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  158. package/dist-esm/lib/ui/components/A11y.mjs +2 -2
  159. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  160. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  161. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  162. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
  163. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  164. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  165. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  166. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -2
  167. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  168. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  169. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  170. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  171. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  172. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  173. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  174. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  175. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  176. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  177. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  178. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  179. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  180. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  181. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  182. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  183. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  184. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  185. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  186. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  187. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  188. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  189. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  190. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +12 -3
  191. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  192. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +3 -3
  193. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  194. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
  195. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  196. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  197. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  198. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +63 -36
  199. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  200. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +5 -5
  201. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +1 -1
  202. package/dist-esm/lib/ui/context/actions.mjs +23 -10
  203. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  204. package/dist-esm/lib/ui/context/components.mjs +2 -0
  205. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  206. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  207. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  208. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  209. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  210. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  211. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  212. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  213. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -2
  214. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  215. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  216. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  217. package/dist-esm/lib/ui/version.mjs +3 -3
  218. package/dist-esm/lib/ui/version.mjs.map +1 -1
  219. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +1 -1
  220. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  221. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  222. package/dist-esm/lib/utils/export/export.mjs +0 -20
  223. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  224. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  225. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  226. package/package.json +3 -3
  227. package/src/index.ts +41 -22
  228. package/src/lib/Tldraw.tsx +15 -2
  229. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  230. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +2 -2
  231. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +41 -0
  232. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  233. package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
  234. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +2 -2
  235. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
  236. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  237. package/src/lib/shapes/frame/FrameShapeUtil.tsx +9 -0
  238. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
  239. package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
  240. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  241. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -4
  242. package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
  243. package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
  244. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  245. package/src/lib/shapes/shared/PlainTextLabel.tsx +2 -7
  246. package/src/lib/shapes/shared/RichTextLabel.tsx +2 -1
  247. package/src/lib/shapes/shared/crop.ts +1 -0
  248. package/src/lib/shapes/shared/useEditablePlainText.ts +12 -12
  249. package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
  250. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  251. package/src/lib/shapes/text/PlainTextArea.tsx +3 -3
  252. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  253. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +1 -1
  254. package/src/lib/ui/TldrawUi.tsx +16 -10
  255. package/src/lib/ui/components/A11y.tsx +2 -2
  256. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  257. package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
  258. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  259. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +2 -2
  260. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  261. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  262. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  263. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  264. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  265. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  266. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  267. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +5 -4
  268. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  269. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  270. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  271. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +8 -3
  272. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +3 -3
  273. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
  274. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  275. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +67 -29
  276. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +6 -6
  277. package/src/lib/ui/context/actions.tsx +23 -10
  278. package/src/lib/ui/context/components.tsx +3 -0
  279. package/src/lib/ui/context/events.tsx +1 -1
  280. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  281. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  282. package/src/lib/ui/hooks/useTools.tsx +1 -1
  283. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  284. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -2
  285. package/src/lib/ui/kbd-utils.ts +10 -3
  286. package/src/lib/ui/version.ts +3 -3
  287. package/src/lib/ui.css +19 -2
  288. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +6 -6
  289. package/src/lib/utils/export/copyAs.ts +1 -24
  290. package/src/lib/utils/export/export.ts +0 -36
  291. package/src/lib/utils/export/exportAs.ts +1 -32
  292. package/src/test/Editor.test.tsx +37 -10
  293. package/src/test/TldrawEditor.test.tsx +15 -9
  294. package/src/test/commands/putContent.test.ts +1 -0
  295. package/src/test/commands/updateShapes.test.ts +9 -5
  296. package/src/test/custom-clipping.test.ts +442 -0
  297. package/src/test/customSnapping.test.tsx +55 -41
  298. package/src/test/getCulledShapes.test.tsx +77 -2
  299. package/src/test/groups.test.tsx +4 -2
  300. package/src/test/translating.test.ts +2 -2
  301. package/tldraw.css +35 -5
  302. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  303. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  304. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  305. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  306. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  307. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  308. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  309. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  310. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/kbd-utils.ts"],
4
- "sourcesContent": ["import { tlenv } from '@tldraw/editor'\n\n// N.B. We rework these Windows placeholders down below.\nconst cmdKey = tlenv.isDarwin ? '\u2318' : '__CTRL__'\nconst ctrlKey = tlenv.isDarwin ? '\u2303' : '__CTRL__'\nconst altKey = tlenv.isDarwin ? '\u2325' : '__ALT__'\n\n/** @public */\nexport function kbd(str: string) {\n\tif (str === ',') return [',']\n\n\treturn (\n\t\tstr\n\t\t\t.split(',')[0]\n\t\t\t// If the string contains [[Tab]], we don't split these up\n\t\t\t// as they're meant to be atomic.\n\t\t\t.split(/(\\[\\[[^\\]]+\\]\\])/g)\n\t\t\t.map((s) =>\n\t\t\t\ts.startsWith('[[')\n\t\t\t\t\t? s.replace(/[[\\]]/g, '')\n\t\t\t\t\t: s\n\t\t\t\t\t\t\t.replace(/cmd\\+/g, cmdKey)\n\t\t\t\t\t\t\t.replace(/ctrl\\+/g, ctrlKey)\n\t\t\t\t\t\t\t.replace(/alt\\+/g, altKey)\n\t\t\t\t\t\t\t.replace(/shift\\+/g, '\u21E7')\n\t\t\t\t\t\t\t// Backwards compatibility with the old system.\n\t\t\t\t\t\t\t.replace(/\\$/g, cmdKey)\n\t\t\t\t\t\t\t.replace(/\\?/g, altKey)\n\t\t\t\t\t\t\t.replace(/!/g, '\u21E7')\n\t\t\t\t\t\t\t.match(/__CTRL__|__ALT__|./g) || []\n\t\t\t)\n\t\t\t.flat()\n\t\t\t.map((sub, index) => {\n\t\t\t\tif (sub === '__CTRL__') return 'Ctrl'\n\t\t\t\tif (sub === '__ALT__') return 'Alt'\n\t\t\t\tconst modifiedKey = sub[0].toUpperCase() + sub.slice(1)\n\t\t\t\treturn tlenv.isDarwin || !index ? modifiedKey : ['+', modifiedKey]\n\t\t\t})\n\t\t\t.flat()\n\t)\n}\n\n/** @public */\nexport function kbdStr(str: string) {\n\treturn '\u2014 ' + kbd(str).join('\u2009')\n}\n"],
5
- "mappings": "AAAA,SAAS,aAAa;AAGtB,MAAM,SAAS,MAAM,WAAW,WAAM;AACtC,MAAM,UAAU,MAAM,WAAW,WAAM;AACvC,MAAM,SAAS,MAAM,WAAW,WAAM;AAG/B,SAAS,IAAI,KAAa;AAChC,MAAI,QAAQ,IAAK,QAAO,CAAC,GAAG;AAE5B,SACC,IACE,MAAM,GAAG,EAAE,CAAC,EAGZ,MAAM,mBAAmB,EACzB;AAAA,IAAI,CAAC,MACL,EAAE,WAAW,IAAI,IACd,EAAE,QAAQ,UAAU,EAAE,IACtB,EACC,QAAQ,UAAU,MAAM,EACxB,QAAQ,WAAW,OAAO,EAC1B,QAAQ,UAAU,MAAM,EACxB,QAAQ,YAAY,QAAG,EAEvB,QAAQ,OAAO,MAAM,EACrB,QAAQ,OAAO,MAAM,EACrB,QAAQ,MAAM,QAAG,EACjB,MAAM,qBAAqB,KAAK,CAAC;AAAA,EACtC,EACC,KAAK,EACL,IAAI,CAAC,KAAK,UAAU;AACpB,QAAI,QAAQ,WAAY,QAAO;AAC/B,QAAI,QAAQ,UAAW,QAAO;AAC9B,UAAM,cAAc,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AACtD,WAAO,MAAM,YAAY,CAAC,QAAQ,cAAc,CAAC,KAAK,WAAW;AAAA,EAClE,CAAC,EACA,KAAK;AAET;AAGO,SAAS,OAAO,KAAa;AACnC,SAAO,YAAO,IAAI,GAAG,EAAE,KAAK,QAAG;AAChC;",
4
+ "sourcesContent": ["import { tlenv } from '@tldraw/editor'\n\n// N.B. We rework these Windows placeholders down below.\nconst cmdKey = tlenv.isDarwin ? '\u2318' : '__CTRL__'\nconst ctrlKey = tlenv.isDarwin ? '\u2303' : '__CTRL__'\nconst altKey = tlenv.isDarwin ? '\u2325' : '__ALT__'\n\n/** @public */\nexport function kbd(str: string) {\n\tif (str === ',') return [',']\n\n\treturn (\n\t\tstr\n\t\t\t.split(',')[0]\n\t\t\t// If the string contains [[Tab]], we don't split these up\n\t\t\t// as they're meant to be atomic.\n\t\t\t.split(/(\\[\\[[^\\]]+\\]\\])/g)\n\t\t\t.map((s) =>\n\t\t\t\ts.startsWith('[[')\n\t\t\t\t\t? s.replace(/[[\\]]/g, '')\n\t\t\t\t\t: s\n\t\t\t\t\t\t\t.replace(/cmd\\+/g, cmdKey)\n\t\t\t\t\t\t\t.replace(/ctrl\\+/g, ctrlKey)\n\t\t\t\t\t\t\t.replace(/alt\\+/g, altKey)\n\t\t\t\t\t\t\t.replace(/shift\\+/g, '\u21E7')\n\t\t\t\t\t\t\t// Backwards compatibility with the old system.\n\t\t\t\t\t\t\t.replace(/\\$/g, cmdKey)\n\t\t\t\t\t\t\t.replace(/\\?/g, altKey)\n\t\t\t\t\t\t\t.replace(/!/g, '\u21E7')\n\t\t\t\t\t\t\t.match(/__CTRL__|__ALT__|./g) || []\n\t\t\t)\n\t\t\t.flat()\n\t\t\t.map((sub, index) => {\n\t\t\t\tif (sub[0] === '+') return []\n\n\t\t\t\tlet modifiedKey\n\t\t\t\tif (sub === '__CTRL__') {\n\t\t\t\t\tmodifiedKey = 'Ctrl'\n\t\t\t\t} else if (sub === '__ALT__') {\n\t\t\t\t\tmodifiedKey = 'Alt'\n\t\t\t\t} else {\n\t\t\t\t\tmodifiedKey = sub[0].toUpperCase() + sub.slice(1)\n\t\t\t\t}\n\t\t\t\treturn tlenv.isDarwin || !index ? modifiedKey : ['+', modifiedKey]\n\t\t\t})\n\t\t\t.flat()\n\t)\n}\n\n/** @public */\nexport function kbdStr(str: string) {\n\treturn '\u2014 ' + kbd(str).join('\u2009')\n}\n"],
5
+ "mappings": "AAAA,SAAS,aAAa;AAGtB,MAAM,SAAS,MAAM,WAAW,WAAM;AACtC,MAAM,UAAU,MAAM,WAAW,WAAM;AACvC,MAAM,SAAS,MAAM,WAAW,WAAM;AAG/B,SAAS,IAAI,KAAa;AAChC,MAAI,QAAQ,IAAK,QAAO,CAAC,GAAG;AAE5B,SACC,IACE,MAAM,GAAG,EAAE,CAAC,EAGZ,MAAM,mBAAmB,EACzB;AAAA,IAAI,CAAC,MACL,EAAE,WAAW,IAAI,IACd,EAAE,QAAQ,UAAU,EAAE,IACtB,EACC,QAAQ,UAAU,MAAM,EACxB,QAAQ,WAAW,OAAO,EAC1B,QAAQ,UAAU,MAAM,EACxB,QAAQ,YAAY,QAAG,EAEvB,QAAQ,OAAO,MAAM,EACrB,QAAQ,OAAO,MAAM,EACrB,QAAQ,MAAM,QAAG,EACjB,MAAM,qBAAqB,KAAK,CAAC;AAAA,EACtC,EACC,KAAK,EACL,IAAI,CAAC,KAAK,UAAU;AACpB,QAAI,IAAI,CAAC,MAAM,IAAK,QAAO,CAAC;AAE5B,QAAI;AACJ,QAAI,QAAQ,YAAY;AACvB,oBAAc;AAAA,IACf,WAAW,QAAQ,WAAW;AAC7B,oBAAc;AAAA,IACf,OAAO;AACN,oBAAc,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAAA,IACjD;AACA,WAAO,MAAM,YAAY,CAAC,QAAQ,cAAc,CAAC,KAAK,WAAW;AAAA,EAClE,CAAC,EACA,KAAK;AAET;AAGO,SAAS,OAAO,KAAa;AACnC,SAAO,YAAO,IAAI,GAAG,EAAE,KAAK,QAAG;AAChC;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.16.0-internal.51e99e128bd4";
1
+ const version = "3.16.0-internal.71f83a8a571b";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-08-19T10:06:54.740Z",
5
- patch: "2025-08-19T10:06:54.740Z"
4
+ minor: "2025-09-15T18:29:53.804Z",
5
+ patch: "2025-09-15T18:29:53.804Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-internal.51e99e128bd4'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-19T10:06:54.740Z',\n\tpatch: '2025-08-19T10:06:54.740Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-internal.71f83a8a571b'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-09-15T18:29:53.804Z',\n\tpatch: '2025-09-15T18:29:53.804Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/utils/excalidraw/putExcalidrawContent.ts"],
4
- "sourcesContent": ["import {\n\tAssetRecordType,\n\tBox,\n\tEditor,\n\tTLArrowShapeArrowheadStyle,\n\tTLAssetId,\n\tTLContent,\n\tTLDefaultColorStyle,\n\tTLDefaultDashStyle,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultSizeStyle,\n\tTLDefaultTextAlignStyle,\n\tTLOpacityType,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tZERO_INDEX_KEY,\n\tcompact,\n\tcreateBindingId,\n\tcreateShapeId,\n\tgetIndexAbove,\n\tgetIndices,\n\tisShapeId,\n\ttoRichText,\n} from '@tldraw/editor'\n\n/**\n * Put excalidraw clipboard content onto the current page.\n *\n * @param editor - The editor instance.\n * @param excalidrawClipboardContent - The excalidraw clipboard model.\n * @param point - The point at which to put the excalidraw content.\n * @public\n */\nexport async function putExcalidrawContent(\n\teditor: Editor,\n\texcalidrawClipboardContent: any,\n\tpoint?: VecLike\n) {\n\tconst { elements, files } = excalidrawClipboardContent\n\n\tconst tldrawContent: TLContent = {\n\t\tshapes: [],\n\t\tbindings: [],\n\t\trootShapeIds: [],\n\t\tassets: [],\n\t\tschema: editor.store.schema.serialize(),\n\t}\n\n\tconst groupShapeIdToChildren = new Map<string, TLShapeId[]>()\n\tconst rotatedElements = new Map<TLShapeId, number>()\n\n\tconst currentPageId = editor.getCurrentPageId()\n\n\tconst excElementIdsToTldrawShapeIds = new Map<string, TLShapeId>()\n\tconst rootShapeIds: TLShapeId[] = []\n\n\tconst skipIds = new Set<string>()\n\n\telements.forEach((element: any) => {\n\t\texcElementIdsToTldrawShapeIds.set(element.id, createShapeId())\n\n\t\tif (element.boundElements !== null) {\n\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\tskipIds.add(boundElement.id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\tlet index = ZERO_INDEX_KEY\n\n\tfor (const element of elements) {\n\t\tif (skipIds.has(element.id)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst id = excElementIdsToTldrawShapeIds.get(element.id)!\n\n\t\tconst base = {\n\t\t\tid,\n\t\t\ttypeName: 'shape',\n\t\t\tparentId: currentPageId,\n\t\t\tindex,\n\t\t\tx: element.x,\n\t\t\ty: element.y,\n\t\t\trotation: 0,\n\t\t\tisLocked: element.locked,\n\t\t\topacity: getOpacity(element.opacity),\n\t\t\tmeta: {},\n\t\t} as const\n\n\t\tif (element.angle !== 0) {\n\t\t\trotatedElements.set(id, element.angle)\n\t\t}\n\n\t\tif (element.groupIds && element.groupIds.length > 0) {\n\t\t\tif (groupShapeIdToChildren.has(element.groupIds[0])) {\n\t\t\t\tgroupShapeIdToChildren.get(element.groupIds[0])?.push(id)\n\t\t\t} else {\n\t\t\t\tgroupShapeIdToChildren.set(element.groupIds[0], [id])\n\t\t\t}\n\t\t} else {\n\t\t\trootShapeIds.push(id)\n\t\t}\n\n\t\tswitch (element.type) {\n\t\t\tcase 'rectangle':\n\t\t\tcase 'ellipse':\n\t\t\tcase 'diamond': {\n\t\t\t\tlet text = ''\n\t\t\t\tlet align: TLDefaultHorizontalAlignStyle = 'middle'\n\n\t\t\t\tif (element.boundElements !== null) {\n\t\t\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\t\t\tconst labelElement = elements.find((elm: any) => elm.id === boundElement.id)\n\t\t\t\t\t\t\tif (labelElement) {\n\t\t\t\t\t\t\t\ttext = labelElement.text\n\t\t\t\t\t\t\t\talign = textAlignToAlignTypes[labelElement.textAlign]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst colorToUse =\n\t\t\t\t\telement.backgroundColor === 'transparent' ? element.strokeColor : element.backgroundColor\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'geo',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tgeo: element.type,\n\t\t\t\t\t\turl: element.link ?? '',\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth] ?? 'draw',\n\t\t\t\t\t\tcolor: colorsToColors[colorToUse] ?? 'black',\n\t\t\t\t\t\trichText: toRichText(text),\n\t\t\t\t\t\talign,\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tfill: getFill(element),\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'freedraw': {\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'draw',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth],\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'free',\n\t\t\t\t\t\t\t\tpoints: element.points.map(([x, y, z = 0.5]: number[]) => ({\n\t\t\t\t\t\t\t\t\tx,\n\t\t\t\t\t\t\t\t\ty,\n\t\t\t\t\t\t\t\t\tz,\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\tconst points = element.points.slice()\n\t\t\t\tif (points.length < 2) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tconst indices = getIndices(element.points.length)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'line',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth],\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tspline: element.roundness ? 'cubic' : 'line',\n\t\t\t\t\t\tpoints: {\n\t\t\t\t\t\t\t...Object.fromEntries(\n\t\t\t\t\t\t\t\telement.points.map(([x, y]: number[], i: number) => {\n\t\t\t\t\t\t\t\t\tconst index = indices[i]\n\t\t\t\t\t\t\t\t\treturn [index, { id: index, index, x, y }]\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'arrow': {\n\t\t\t\tlet text = ''\n\n\t\t\t\tif (element.boundElements !== null) {\n\t\t\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\t\t\tconst labelElement = elements.find((elm: any) => elm.id === boundElement.id)\n\t\t\t\t\t\t\tif (labelElement) {\n\t\t\t\t\t\t\t\ttext = labelElement.text\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst start = element.points[0]\n\t\t\t\tconst end = element.points[element.points.length - 1]\n\n\t\t\t\tconst startTargetId = excElementIdsToTldrawShapeIds.get(element.startBinding?.elementId)\n\t\t\t\tconst endTargetId = excElementIdsToTldrawShapeIds.get(element.endBinding?.elementId)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trichText: toRichText(text),\n\t\t\t\t\t\tkind: element.elbowed ? 'elbow' : 'arc',\n\t\t\t\t\t\tbend: getBend(element, start, end),\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth] ?? 'm',\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tstart: { x: start[0], y: start[1] },\n\t\t\t\t\t\tend: { x: end[0], y: end[1] },\n\t\t\t\t\t\tarrowheadEnd: arrowheadsToArrowheadTypes[element.endArrowhead] ?? 'none',\n\t\t\t\t\t\tarrowheadStart: arrowheadsToArrowheadTypes[element.startArrowhead] ?? 'none',\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tif (startTargetId) {\n\t\t\t\t\ttldrawContent.bindings!.push({\n\t\t\t\t\t\tid: createBindingId(),\n\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\tfromId: id,\n\t\t\t\t\t\ttoId: startTargetId,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tterminal: 'start',\n\t\t\t\t\t\t\tnormalizedAnchor: { x: 0.5, y: 0.5 },\n\t\t\t\t\t\t\tisPrecise: false,\n\t\t\t\t\t\t\tisExact: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (endTargetId) {\n\t\t\t\t\ttldrawContent.bindings!.push({\n\t\t\t\t\t\tid: createBindingId(),\n\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\tfromId: id,\n\t\t\t\t\t\ttoId: endTargetId,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tterminal: 'end',\n\t\t\t\t\t\t\tnormalizedAnchor: { x: 0.5, y: 0.5 },\n\t\t\t\t\t\t\tisPrecise: false,\n\t\t\t\t\t\t\tisExact: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'text': {\n\t\t\t\tconst { size, scale } = getFontSizeAndScale(element.fontSize)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale,\n\t\t\t\t\t\tfont: fontFamilyToFontType[element.fontFamily] ?? 'draw',\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\trichText: toRichText(element.text),\n\t\t\t\t\t\ttextAlign: textAlignToTextAlignTypes[element.textAlign],\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst file = files[element.fileId]\n\t\t\t\tif (!file) break\n\n\t\t\t\tconst assetId: TLAssetId = AssetRecordType.createId()\n\t\t\t\ttldrawContent.assets.push({\n\t\t\t\t\tid: assetId,\n\t\t\t\t\ttypeName: 'asset',\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tfileSize: file.size,\n\t\t\t\t\t\tname: element.id ?? 'Untitled',\n\t\t\t\t\t\tisAnimated: false,\n\t\t\t\t\t\tmimeType: file.mimeType,\n\t\t\t\t\t\tsrc: file.dataURL,\n\t\t\t\t\t},\n\t\t\t\t\tmeta: {},\n\t\t\t\t})\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tassetId,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tindex = getIndexAbove(index)\n\t}\n\n\tconst p = point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : undefined)\n\n\teditor.putContentOntoCurrentPage(tldrawContent, {\n\t\tpoint: p,\n\t\tselect: false,\n\t\tpreserveIds: true,\n\t})\n\tfor (const groupedShapeIds of groupShapeIdToChildren.values()) {\n\t\tif (groupedShapeIds.length > 1) {\n\t\t\teditor.groupShapes(groupedShapeIds)\n\t\t\tconst groupShape = editor.getShape(groupedShapeIds[0])\n\t\t\tif (groupShape?.parentId && isShapeId(groupShape.parentId)) {\n\t\t\t\trootShapeIds.push(groupShape.parentId)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const [id, angle] of rotatedElements) {\n\t\teditor.select(id)\n\t\teditor.rotateShapesBy([id], angle)\n\t}\n\n\tconst rootShapes = compact(rootShapeIds.map((id) => editor.getShape(id)))\n\tconst bounds = Box.Common(rootShapes.map((s) => editor.getShapePageBounds(s)!))\n\tconst viewPortCenter = editor.getViewportPageBounds().center\n\teditor.updateShapes(\n\t\trootShapes.map((s) => {\n\t\t\tconst delta = {\n\t\t\t\tx: (s.x ?? 0) - (bounds.x + bounds.w / 2),\n\t\t\t\ty: (s.y ?? 0) - (bounds.y + bounds.h / 2),\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: s.id,\n\t\t\t\ttype: s.type,\n\t\t\t\tx: viewPortCenter.x + delta.x,\n\t\t\t\ty: viewPortCenter.y + delta.y,\n\t\t\t}\n\t\t})\n\t)\n\teditor.setSelectedShapes(rootShapeIds)\n}\n\n/* --------------- Translating Helpers --------_------ */\n\nconst getOpacity = (opacity: number): TLOpacityType => {\n\tconst t = opacity / 100\n\tif (t < 0.2) {\n\t\treturn 0.1\n\t} else if (t < 0.4) {\n\t\treturn 0.25\n\t} else if (t < 0.6) {\n\t\treturn 0.5\n\t} else if (t < 0.8) {\n\t\treturn 0.75\n\t}\n\n\treturn 1\n}\n\nconst strokeWidthsToSizes: Record<number, TLDefaultSizeStyle> = {\n\t1: 's',\n\t2: 'm',\n\t3: 'l',\n\t4: 'xl',\n}\n\nconst fontSizesToSizes: Record<number, TLDefaultSizeStyle> = {\n\t16: 's',\n\t20: 'm',\n\t28: 'l',\n\t36: 'xl',\n}\n\nfunction getFontSizeAndScale(fontSize: number): { size: TLDefaultSizeStyle; scale: number } {\n\tconst size = fontSizesToSizes[fontSize]\n\tif (size) {\n\t\treturn { size, scale: 1 }\n\t}\n\tif (fontSize < 16) {\n\t\treturn { size: 's', scale: fontSize / 16 }\n\t}\n\tif (fontSize > 36) {\n\t\treturn { size: 'xl', scale: fontSize / 36 }\n\t}\n\treturn { size: 'm', scale: 1 }\n}\n\nconst fontFamilyToFontType: Record<number, TLDefaultFontStyle> = {\n\t1: 'draw',\n\t2: 'sans',\n\t3: 'mono',\n}\n\nconst oc = {\n\tgray: ['#f8f9fa', '#e9ecef', '#ced4da', '#868e96', '#343a40'],\n\tred: ['#fff5f5', '#ffc9c9', '#ff8787', '#fa5252', '#e03131'],\n\tpink: ['#fff0f6', '#fcc2d7', '#f783ac', '#e64980', '#c2255c'],\n\tgrape: ['#f8f0fc', '#eebefa', '#da77f2', '#be4bdb', '#9c36b5'],\n\tviolet: ['#f3f0ff', '#d0bfff', '#9775fa', '#7950f2', '#6741d9'],\n\tindigo: ['#edf2ff', '#bac8ff', '#748ffc', '#4c6ef5', '#3b5bdb'],\n\tblue: ['#e7f5ff', '#a5d8ff', '#4dabf7', '#228be6', '#1971c2'],\n\tcyan: ['#e3fafc', '#99e9f2', '#3bc9db', '#15aabf', '#0c8599'],\n\tteal: ['#e6fcf5', '#96f2d7', '#38d9a9', '#12b886', '#099268'],\n\tgreen: ['#ebfbee', '#b2f2bb', '#69db7c', '#40c057', '#2f9e44'],\n\tlime: ['#f4fce3', '#d8f5a2', '#a9e34b', '#82c91e', '#66a80f'],\n\tyellow: ['#fff9db', '#ffec99', '#ffd43b', '#fab005', '#f08c00'],\n\torange: ['#fff4e6', '#ffd8a8', '#ffa94d', '#fd7e14', '#e8590c'],\n}\n\nfunction mapExcalidrawColorToTldrawColors(\n\texcalidrawColor: keyof typeof oc,\n\tlight: TLDefaultColorStyle,\n\tdark: TLDefaultColorStyle\n) {\n\tconst colors = [0, 1, 2, 3, 4].map((index) => oc[excalidrawColor][index])\n\treturn Object.fromEntries(colors.map((c, i) => [c, i < 3 ? light : dark]))\n}\n\nconst colorsToColors: Record<string, TLDefaultColorStyle> = {\n\t...mapExcalidrawColorToTldrawColors('gray', 'grey', 'black'),\n\t...mapExcalidrawColorToTldrawColors('red', 'light-red', 'red'),\n\t...mapExcalidrawColorToTldrawColors('pink', 'light-red', 'red'),\n\t...mapExcalidrawColorToTldrawColors('grape', 'light-violet', 'violet'),\n\t...mapExcalidrawColorToTldrawColors('blue', 'light-blue', 'blue'),\n\t...mapExcalidrawColorToTldrawColors('cyan', 'light-blue', 'blue'),\n\t...mapExcalidrawColorToTldrawColors('teal', 'light-green', 'green'),\n\t...mapExcalidrawColorToTldrawColors('green', 'light-green', 'green'),\n\t...mapExcalidrawColorToTldrawColors('yellow', 'yellow', 'orange'),\n\t...mapExcalidrawColorToTldrawColors('orange', 'yellow', 'orange'),\n\t'#ffffff': 'white',\n\t'#000000': 'black',\n}\n\nconst strokeStylesToStrokeTypes: Record<string, TLDefaultDashStyle> = {\n\tsolid: 'draw',\n\tdashed: 'dashed',\n\tdotted: 'dotted',\n}\n\nconst fillStylesToFillType: Record<string, TLDefaultFillStyle> = {\n\t'cross-hatch': 'pattern',\n\thachure: 'pattern',\n\tsolid: 'solid',\n}\n\nconst textAlignToAlignTypes: Record<string, TLDefaultHorizontalAlignStyle> = {\n\tleft: 'start',\n\tcenter: 'middle',\n\tright: 'end',\n}\n\nconst textAlignToTextAlignTypes: Record<string, TLDefaultTextAlignStyle> = {\n\tleft: 'start',\n\tcenter: 'middle',\n\tright: 'end',\n}\n\nconst arrowheadsToArrowheadTypes: Record<string, TLArrowShapeArrowheadStyle> = {\n\tarrow: 'arrow',\n\tdot: 'dot',\n\ttriangle: 'triangle',\n\tbar: 'pipe',\n}\n\nfunction getBend(element: any, startPoint: any, endPoint: any) {\n\tlet bend = 0\n\tif (element.points.length > 2) {\n\t\tconst start = new Vec(startPoint[0], startPoint[1])\n\t\tconst end = new Vec(endPoint[0], endPoint[1])\n\t\tconst handle = new Vec(element.points[1][0], element.points[1][1])\n\t\tconst delta = Vec.Sub(end, start)\n\t\tconst v = Vec.Per(delta)\n\n\t\tconst med = Vec.Med(end, start)\n\t\tconst A = Vec.Sub(med, v)\n\t\tconst B = Vec.Add(med, v)\n\n\t\tconst point = Vec.NearestPointOnLineSegment(A, B, handle, false)\n\t\tbend = Vec.Dist(point, med)\n\t\tif (Vec.Clockwise(point, end, med)) bend *= -1\n\t}\n\treturn bend\n}\n\nconst getDash = (element: any): TLDefaultDashStyle => {\n\tlet dash: TLDefaultDashStyle = strokeStylesToStrokeTypes[element.strokeStyle] ?? 'draw'\n\tif (dash === 'draw' && element.roughness === 0) {\n\t\tdash = 'solid'\n\t}\n\treturn dash\n}\n\nconst getFill = (element: any): TLDefaultFillStyle => {\n\tif (element.backgroundColor === 'transparent') {\n\t\treturn 'none'\n\t}\n\treturn fillStylesToFillType[element.fillStyle] ?? 'solid'\n}\n"],
4
+ "sourcesContent": ["import {\n\tAssetRecordType,\n\tBox,\n\tEditor,\n\tTLArrowShapeArrowheadStyle,\n\tTLAssetId,\n\tTLContent,\n\tTLDefaultColorStyle,\n\tTLDefaultDashStyle,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultSizeStyle,\n\tTLDefaultTextAlignStyle,\n\tTLOpacityType,\n\tTLShapeId,\n\tVec,\n\tVecLike,\n\tZERO_INDEX_KEY,\n\tcompact,\n\tcreateBindingId,\n\tcreateShapeId,\n\tgetIndexAbove,\n\tgetIndices,\n\tisShapeId,\n\ttoRichText,\n} from '@tldraw/editor'\n\n/**\n * Put excalidraw clipboard content onto the current page.\n *\n * @param editor - The editor instance.\n * @param excalidrawClipboardContent - The excalidraw clipboard model.\n * @param point - The point at which to put the excalidraw content.\n * @public\n */\nexport async function putExcalidrawContent(\n\teditor: Editor,\n\texcalidrawClipboardContent: any,\n\tpoint?: VecLike\n) {\n\tconst { elements, files } = excalidrawClipboardContent\n\n\tconst tldrawContent: TLContent = {\n\t\tshapes: [],\n\t\tbindings: [],\n\t\trootShapeIds: [],\n\t\tassets: [],\n\t\tschema: editor.store.schema.serialize(),\n\t}\n\n\tconst groupShapeIdToChildren = new Map<string, TLShapeId[]>()\n\tconst rotatedElements = new Map<TLShapeId, number>()\n\n\tconst currentPageId = editor.getCurrentPageId()\n\n\tconst excElementIdsToTldrawShapeIds = new Map<string, TLShapeId>()\n\tconst rootShapeIds: TLShapeId[] = []\n\n\tconst skipIds = new Set<string>()\n\n\telements.forEach((element: any) => {\n\t\texcElementIdsToTldrawShapeIds.set(element.id, createShapeId())\n\n\t\tif (element.boundElements !== null) {\n\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\tskipIds.add(boundElement.id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\tlet index = ZERO_INDEX_KEY\n\n\tfor (const element of elements) {\n\t\tif (skipIds.has(element.id)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst id = excElementIdsToTldrawShapeIds.get(element.id)!\n\n\t\tconst base = {\n\t\t\tid,\n\t\t\ttypeName: 'shape',\n\t\t\tparentId: currentPageId,\n\t\t\tindex,\n\t\t\tx: element.x,\n\t\t\ty: element.y,\n\t\t\trotation: 0,\n\t\t\tisLocked: element.locked,\n\t\t\topacity: getOpacity(element.opacity),\n\t\t\tmeta: {},\n\t\t} as const\n\n\t\tif (element.angle !== 0) {\n\t\t\trotatedElements.set(id, element.angle)\n\t\t}\n\n\t\tif (element.groupIds && element.groupIds.length > 0) {\n\t\t\tif (groupShapeIdToChildren.has(element.groupIds[0])) {\n\t\t\t\tgroupShapeIdToChildren.get(element.groupIds[0])?.push(id)\n\t\t\t} else {\n\t\t\t\tgroupShapeIdToChildren.set(element.groupIds[0], [id])\n\t\t\t}\n\t\t} else {\n\t\t\trootShapeIds.push(id)\n\t\t}\n\n\t\tswitch (element.type) {\n\t\t\tcase 'rectangle':\n\t\t\tcase 'ellipse':\n\t\t\tcase 'diamond': {\n\t\t\t\tlet text = ''\n\t\t\t\tlet align: TLDefaultHorizontalAlignStyle = 'middle'\n\n\t\t\t\tif (element.boundElements !== null) {\n\t\t\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\t\t\tconst labelElement = elements.find((elm: any) => elm.id === boundElement.id)\n\t\t\t\t\t\t\tif (labelElement) {\n\t\t\t\t\t\t\t\ttext = labelElement.text\n\t\t\t\t\t\t\t\talign = textAlignToAlignTypes[labelElement.textAlign]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst colorToUse =\n\t\t\t\t\telement.backgroundColor === 'transparent' ? element.strokeColor : element.backgroundColor\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'geo',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tgeo: element.type,\n\t\t\t\t\t\turl: element.link ?? '',\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth] ?? 'draw',\n\t\t\t\t\t\tcolor: colorsToColors[colorToUse] ?? 'black',\n\t\t\t\t\t\trichText: toRichText(text),\n\t\t\t\t\t\talign,\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tfill: getFill(element),\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'freedraw': {\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'draw',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth],\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'free',\n\t\t\t\t\t\t\t\tpoints: element.points.map(([x, y, z = 0.5]: number[]) => ({\n\t\t\t\t\t\t\t\t\tx,\n\t\t\t\t\t\t\t\t\ty,\n\t\t\t\t\t\t\t\t\tz,\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\tconst points = element.points.slice()\n\t\t\t\tif (points.length < 2) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tconst indices = getIndices(element.points.length)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'line',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth],\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tspline: element.roundness ? 'cubic' : 'line',\n\t\t\t\t\t\tpoints: {\n\t\t\t\t\t\t\t...Object.fromEntries(\n\t\t\t\t\t\t\t\telement.points.map(([x, y]: number[], i: number) => {\n\t\t\t\t\t\t\t\t\tconst index = indices[i]\n\t\t\t\t\t\t\t\t\treturn [index, { id: index, index, x, y }]\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'arrow': {\n\t\t\t\tlet text = ''\n\n\t\t\t\tif (element.boundElements !== null) {\n\t\t\t\t\tfor (const boundElement of element.boundElements) {\n\t\t\t\t\t\tif (boundElement.type === 'text') {\n\t\t\t\t\t\t\tconst labelElement = elements.find((elm: any) => elm.id === boundElement.id)\n\t\t\t\t\t\t\tif (labelElement) {\n\t\t\t\t\t\t\t\ttext = labelElement.text\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst start = element.points[0]\n\t\t\t\tconst end = element.points[element.points.length - 1]\n\n\t\t\t\tconst startTargetId = excElementIdsToTldrawShapeIds.get(element.startBinding?.elementId)\n\t\t\t\tconst endTargetId = excElementIdsToTldrawShapeIds.get(element.endBinding?.elementId)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trichText: toRichText(text),\n\t\t\t\t\t\tkind: element.elbowed ? 'elbow' : 'arc',\n\t\t\t\t\t\tbend: getBend(element, start, end),\n\t\t\t\t\t\tdash: getDash(element),\n\t\t\t\t\t\tsize: strokeWidthsToSizes[element.strokeWidth] ?? 'm',\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\tstart: { x: start[0], y: start[1] },\n\t\t\t\t\t\tend: { x: end[0], y: end[1] },\n\t\t\t\t\t\tarrowheadEnd: arrowheadsToArrowheadTypes[element.endArrowhead] ?? 'none',\n\t\t\t\t\t\tarrowheadStart: arrowheadsToArrowheadTypes[element.startArrowhead] ?? 'none',\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\n\t\t\t\tif (startTargetId) {\n\t\t\t\t\ttldrawContent.bindings!.push({\n\t\t\t\t\t\tid: createBindingId(),\n\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\tfromId: id,\n\t\t\t\t\t\ttoId: startTargetId,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tterminal: 'start',\n\t\t\t\t\t\t\tnormalizedAnchor: { x: 0.5, y: 0.5 },\n\t\t\t\t\t\t\tisPrecise: false,\n\t\t\t\t\t\t\tisExact: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (endTargetId) {\n\t\t\t\t\ttldrawContent.bindings!.push({\n\t\t\t\t\t\tid: createBindingId(),\n\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\tfromId: id,\n\t\t\t\t\t\ttoId: endTargetId,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tterminal: 'end',\n\t\t\t\t\t\t\tnormalizedAnchor: { x: 0.5, y: 0.5 },\n\t\t\t\t\t\t\tisPrecise: false,\n\t\t\t\t\t\t\tisExact: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'text': {\n\t\t\t\tconst { size, scale } = getFontSizeAndScale(element.fontSize)\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale,\n\t\t\t\t\t\tfont: fontFamilyToFontType[element.fontFamily] ?? 'draw',\n\t\t\t\t\t\tcolor: colorsToColors[element.strokeColor] ?? 'black',\n\t\t\t\t\t\trichText: toRichText(element.text),\n\t\t\t\t\t\ttextAlign: textAlignToTextAlignTypes[element.textAlign],\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'image': {\n\t\t\t\tconst file = files[element.fileId]\n\t\t\t\tif (!file) break\n\n\t\t\t\tconst assetId: TLAssetId = AssetRecordType.createId()\n\t\t\t\ttldrawContent.assets.push({\n\t\t\t\t\tid: assetId,\n\t\t\t\t\ttypeName: 'asset',\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tfileSize: file.size,\n\t\t\t\t\t\tname: element.id ?? 'Untitled',\n\t\t\t\t\t\tisAnimated: false,\n\t\t\t\t\t\tmimeType: file.mimeType,\n\t\t\t\t\t\tsrc: file.dataURL,\n\t\t\t\t\t},\n\t\t\t\t\tmeta: {},\n\t\t\t\t})\n\n\t\t\t\ttldrawContent.shapes.push({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tw: element.width,\n\t\t\t\t\t\th: element.height,\n\t\t\t\t\t\tassetId,\n\t\t\t\t\t} as any,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tindex = getIndexAbove(index)\n\t}\n\n\tconst p = point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : undefined)\n\n\teditor.putContentOntoCurrentPage(tldrawContent, {\n\t\tpoint: p,\n\t\tselect: false,\n\t\tpreserveIds: true,\n\t})\n\tfor (const groupedShapeIds of groupShapeIdToChildren.values()) {\n\t\tif (groupedShapeIds.length > 1) {\n\t\t\teditor.groupShapes(groupedShapeIds)\n\t\t\tconst groupShape = editor.getShape(groupedShapeIds[0])\n\t\t\tif (groupShape?.parentId && isShapeId(groupShape.parentId)) {\n\t\t\t\trootShapeIds.push(groupShape.parentId)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const [id, angle] of rotatedElements) {\n\t\teditor.select(id)\n\t\teditor.rotateShapesBy([id], angle)\n\t}\n\n\tconst rootShapes = compact(rootShapeIds.map((id) => editor.getShape(id)))\n\tconst bounds = Box.Common(rootShapes.map((s) => editor.getShapePageBounds(s)!))\n\tconst viewPortCenter = editor.getViewportPageBounds().center\n\teditor.updateShapes(\n\t\trootShapes.map((s) => {\n\t\t\tconst delta = {\n\t\t\t\tx: (s.x ?? 0) - (bounds.x + bounds.w / 2),\n\t\t\t\ty: (s.y ?? 0) - (bounds.y + bounds.h / 2),\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: s.id,\n\t\t\t\ttype: s.type,\n\t\t\t\tx: viewPortCenter.x + delta.x,\n\t\t\t\ty: viewPortCenter.y + delta.y,\n\t\t\t}\n\t\t})\n\t)\n\teditor.setSelectedShapes(rootShapeIds)\n}\n\n/* --------------- Translating Helpers --------_------ */\n\nconst getOpacity = (opacity: number): TLOpacityType => {\n\tconst t = opacity / 100\n\tif (t < 0.2) {\n\t\treturn 0.1\n\t} else if (t < 0.4) {\n\t\treturn 0.25\n\t} else if (t < 0.6) {\n\t\treturn 0.5\n\t} else if (t < 0.8) {\n\t\treturn 0.75\n\t}\n\n\treturn 1\n}\n\nconst strokeWidthsToSizes: Record<number, TLDefaultSizeStyle> = {\n\t1: 's',\n\t2: 'm',\n\t3: 'l',\n\t4: 'xl',\n}\n\nconst fontSizesToSizes: Record<number, TLDefaultSizeStyle> = {\n\t16: 's',\n\t20: 'm',\n\t28: 'l',\n\t36: 'xl',\n}\n\nfunction getFontSizeAndScale(fontSize: number): { size: TLDefaultSizeStyle; scale: number } {\n\tconst size = fontSizesToSizes[fontSize]\n\tif (size) {\n\t\treturn { size, scale: 1 }\n\t}\n\tif (fontSize < 16) {\n\t\treturn { size: 's', scale: fontSize / 16 }\n\t}\n\tif (fontSize > 36) {\n\t\treturn { size: 'xl', scale: fontSize / 36 }\n\t}\n\treturn { size: 'm', scale: 1 }\n}\n\nconst fontFamilyToFontType: Record<number, TLDefaultFontStyle> = {\n\t1: 'draw',\n\t2: 'sans',\n\t3: 'mono',\n}\n\nconst oc = {\n\tgray: ['#f8f9fa', '#e9ecef', '#ced4da', '#868e96', '#343a40'],\n\tred: ['#fff5f5', '#ffc9c9', '#ff8787', '#fa5252', '#e03131'],\n\tpink: ['#fff0f6', '#fcc2d7', '#f783ac', '#e64980', '#c2255c'],\n\tgrape: ['#f8f0fc', '#eebefa', '#da77f2', '#be4bdb', '#9c36b5'],\n\tviolet: ['#f3f0ff', '#d0bfff', '#9775fa', '#7950f2', '#6741d9'],\n\tindigo: ['#edf2ff', '#bac8ff', '#748ffc', '#4c6ef5', '#3b5bdb'],\n\tblue: ['#e7f5ff', '#a5d8ff', '#4dabf7', '#228be6', '#1971c2'],\n\tcyan: ['#e3fafc', '#99e9f2', '#3bc9db', '#15aabf', '#0c8599'],\n\tteal: ['#e6fcf5', '#96f2d7', '#38d9a9', '#12b886', '#099268'],\n\tgreen: ['#ebfbee', '#b2f2bb', '#69db7c', '#40c057', '#2f9e44'],\n\tlime: ['#f4fce3', '#d8f5a2', '#a9e34b', '#82c91e', '#66a80f'],\n\tyellow: ['#fff9db', '#ffec99', '#ffd43b', '#fab005', '#f08c00'],\n\torange: ['#fff4e6', '#ffd8a8', '#ffa94d', '#fd7e14', '#e8590c'],\n}\n\nfunction mapExcalidrawColorToTldrawColors(\n\texcalidrawColor: keyof typeof oc,\n\tlight: TLDefaultColorStyle,\n\tdark: TLDefaultColorStyle\n) {\n\tconst colors = [0, 1, 2, 3, 4].map((index) => oc[excalidrawColor][index])\n\treturn Object.fromEntries(colors.map((c, i) => [c, i < 3 ? light : dark]))\n}\n\nconst colorsToColors: Record<string, TLDefaultColorStyle> = {\n\t...mapExcalidrawColorToTldrawColors('gray', 'grey', 'black'),\n\t...mapExcalidrawColorToTldrawColors('red', 'light-red', 'red'),\n\t...mapExcalidrawColorToTldrawColors('pink', 'light-red', 'red'),\n\t...mapExcalidrawColorToTldrawColors('grape', 'light-violet', 'violet'),\n\t...mapExcalidrawColorToTldrawColors('blue', 'light-blue', 'blue'),\n\t...mapExcalidrawColorToTldrawColors('cyan', 'light-blue', 'blue'),\n\t...mapExcalidrawColorToTldrawColors('teal', 'light-green', 'green'),\n\t...mapExcalidrawColorToTldrawColors('green', 'light-green', 'green'),\n\t...mapExcalidrawColorToTldrawColors('yellow', 'yellow', 'orange'),\n\t...mapExcalidrawColorToTldrawColors('orange', 'yellow', 'orange'),\n\t'#ffffff': 'white',\n\t'#000000': 'black',\n}\n\nconst strokeStylesToStrokeTypes: Record<string, TLDefaultDashStyle> = {\n\tsolid: 'draw',\n\tdashed: 'dashed',\n\tdotted: 'dotted',\n}\n\nconst fillStylesToFillType: Record<string, TLDefaultFillStyle> = {\n\t'cross-hatch': 'pattern',\n\thachure: 'pattern',\n\tsolid: 'solid',\n}\n\nconst textAlignToAlignTypes: Record<string, TLDefaultHorizontalAlignStyle> = {\n\tleft: 'start',\n\tcenter: 'middle',\n\tright: 'end',\n}\n\nconst textAlignToTextAlignTypes: Record<string, TLDefaultTextAlignStyle> = {\n\tleft: 'start',\n\tcenter: 'middle',\n\tright: 'end',\n}\n\nconst arrowheadsToArrowheadTypes: Record<string, TLArrowShapeArrowheadStyle> = {\n\tarrow: 'arrow',\n\tdot: 'dot',\n\ttriangle: 'triangle',\n\tbar: 'pipe',\n}\n\nfunction getBend(element: any, startPoint: any, endPoint: any) {\n\tlet bend = 0\n\tif (element.points.length > 2) {\n\t\tconst start = new Vec(startPoint[0], startPoint[1])\n\t\tconst end = new Vec(endPoint[0], endPoint[1])\n\t\tconst handle = new Vec(element.points[1][0], element.points[1][1])\n\t\tconst delta = Vec.Sub(end, start)\n\t\tconst v = Vec.Per(delta)\n\n\t\tconst med = Vec.Med(end, start)\n\t\tconst A = Vec.Sub(med, v)\n\t\tconst B = Vec.Add(med, v)\n\n\t\tconst point = Vec.NearestPointOnLineSegment(A, B, handle, false)\n\t\tbend = Vec.Dist(point, med)\n\t\tif (Vec.Clockwise(point, end, med)) bend *= -1\n\t}\n\treturn bend\n}\n\nconst getDash = (element: any): TLDefaultDashStyle => {\n\tlet dash: TLDefaultDashStyle = strokeStylesToStrokeTypes[element.strokeStyle] ?? 'draw'\n\tif (dash === 'draw' && element.roughness === 0) {\n\t\tdash = 'solid'\n\t}\n\treturn dash\n}\n\nconst getFill = (element: any): TLDefaultFillStyle => {\n\tif (element.backgroundColor === 'transparent') {\n\t\treturn 'none'\n\t}\n\treturn fillStylesToFillType[element.fillStyle] ?? 'solid'\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["index"]
7
7
  }
@@ -8,8 +8,7 @@ import {
8
8
  getAdditionalClipboardWriteType
9
9
  } from "../clipboard.mjs";
10
10
  import { exportToImagePromiseForClipboard } from "./export.mjs";
11
- function copyAs(...args) {
12
- const [editor, ids, opts] = typeof args[2] === "string" ? [args[0], args[1], { ...args[3], format: args[2] }] : args;
11
+ function copyAs(editor, ids, opts) {
13
12
  if (!navigator.clipboard) return Promise.reject(new Error("Copy not supported"));
14
13
  if (navigator.clipboard.write) {
15
14
  const { blobPromise, mimeType } = exportToImagePromiseForClipboard(editor, ids, opts);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/utils/export/copyAs.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tFileHelpers,\n\tTLImageExportOptions,\n\tTLShapeId,\n\texhaustiveSwitchError,\n} from '@tldraw/editor'\nimport {\n\tclipboardWrite,\n\tdoesClipboardSupportType,\n\tgetAdditionalClipboardWriteType,\n} from '../clipboard'\nimport { exportToImagePromiseForClipboard } from './export'\n\n/** @public */\nexport type TLCopyType = 'svg' | 'png'\n\n/** @public */\nexport interface CopyAsOptions extends TLImageExportOptions {\n\t/** The format to copy as. */\n\tformat: TLCopyType\n}\n\n/**\n * Copy the given shapes to the clipboard.\n *\n * @param editor - The editor instance.\n * @param ids - The ids of the shapes to copy.\n * @param format - The format to copy as. Defaults to png.\n * @param opts - Options for the copy.\n *\n * @public\n */\nexport function copyAs(editor: Editor, ids: TLShapeId[], opts: CopyAsOptions): Promise<void>\n/**\n * @deprecated The format parameter is now part of the opts object.\n * @public\n */\nexport function copyAs(\n\teditor: Editor,\n\tids: TLShapeId[],\n\tformat: TLCopyType,\n\topts?: TLImageExportOptions & { format?: undefined }\n): Promise<void>\nexport function copyAs(\n\t...args:\n\t\t| [editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions & { format: TLCopyType }]\n\t\t| [\n\t\t\t\teditor: Editor,\n\t\t\t\tids: TLShapeId[],\n\t\t\t\tformat: TLCopyType,\n\t\t\t\topts?: TLImageExportOptions & { format?: undefined },\n\t\t ]\n) {\n\tconst [editor, ids, opts] =\n\t\ttypeof args[2] === 'string' ? [args[0], args[1], { ...args[3], format: args[2] }] : args\n\n\t// Note: it's important that this function itself isn't async and doesn't really use promises -\n\t// we need to create the relevant `ClipboardItem`s and call navigator.clipboard.write\n\t// synchronously to make sure safari knows that the user _wants_ to copy See\n\t// https://bugs.webkit.org/show_bug.cgi?id=222262\n\n\tif (!navigator.clipboard) return Promise.reject(new Error('Copy not supported'))\n\tif (navigator.clipboard.write as any) {\n\t\tconst { blobPromise, mimeType } = exportToImagePromiseForClipboard(editor, ids, opts)\n\n\t\tconst types: Record<string, Promise<Blob>> = { [mimeType]: blobPromise }\n\t\tconst additionalMimeType = getAdditionalClipboardWriteType(opts.format)\n\t\tif (additionalMimeType && doesClipboardSupportType(additionalMimeType)) {\n\t\t\ttypes[additionalMimeType] = blobPromise.then((blob) =>\n\t\t\t\tFileHelpers.rewriteMimeType(blob, additionalMimeType)\n\t\t\t)\n\t\t}\n\n\t\treturn clipboardWrite(types)\n\t}\n\n\tswitch (opts.format) {\n\t\tcase 'svg': {\n\t\t\treturn fallbackWriteTextAsync(async () => {\n\t\t\t\tconst result = await editor.getSvgString(ids, opts)\n\n\t\t\t\tif (!result) throw new Error('Failed to copy')\n\t\t\t\treturn result.svg\n\t\t\t})\n\t\t}\n\n\t\tcase 'png':\n\t\t\tthrow new Error('Copy not supported')\n\t\tdefault:\n\t\t\texhaustiveSwitchError(opts.format)\n\t}\n}\n\nasync function fallbackWriteTextAsync(getText: () => Promise<string>) {\n\tawait navigator.clipboard?.writeText?.(await getText())\n}\n"],
5
- "mappings": "AAAA;AAAA,EAEC;AAAA,EAGA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,wCAAwC;AAgC1C,SAAS,UACZ,MAQF;AACD,QAAM,CAAC,QAAQ,KAAK,IAAI,IACvB,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE,CAAC,IAAI;AAOrF,MAAI,CAAC,UAAU,UAAW,QAAO,QAAQ,OAAO,IAAI,MAAM,oBAAoB,CAAC;AAC/E,MAAI,UAAU,UAAU,OAAc;AACrC,UAAM,EAAE,aAAa,SAAS,IAAI,iCAAiC,QAAQ,KAAK,IAAI;AAEpF,UAAM,QAAuC,EAAE,CAAC,QAAQ,GAAG,YAAY;AACvE,UAAM,qBAAqB,gCAAgC,KAAK,MAAM;AACtE,QAAI,sBAAsB,yBAAyB,kBAAkB,GAAG;AACvE,YAAM,kBAAkB,IAAI,YAAY;AAAA,QAAK,CAAC,SAC7C,YAAY,gBAAgB,MAAM,kBAAkB;AAAA,MACrD;AAAA,IACD;AAEA,WAAO,eAAe,KAAK;AAAA,EAC5B;AAEA,UAAQ,KAAK,QAAQ;AAAA,IACpB,KAAK,OAAO;AACX,aAAO,uBAAuB,YAAY;AACzC,cAAM,SAAS,MAAM,OAAO,aAAa,KAAK,IAAI;AAElD,YAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,gBAAgB;AAC7C,eAAO,OAAO;AAAA,MACf,CAAC;AAAA,IACF;AAAA,IAEA,KAAK;AACJ,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACrC;AACC,4BAAsB,KAAK,MAAM;AAAA,EACnC;AACD;AAEA,eAAe,uBAAuB,SAAgC;AACrE,QAAM,UAAU,WAAW,YAAY,MAAM,QAAQ,CAAC;AACvD;",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tFileHelpers,\n\tTLImageExportOptions,\n\tTLShapeId,\n\texhaustiveSwitchError,\n} from '@tldraw/editor'\nimport {\n\tclipboardWrite,\n\tdoesClipboardSupportType,\n\tgetAdditionalClipboardWriteType,\n} from '../clipboard'\nimport { exportToImagePromiseForClipboard } from './export'\n\n/** @public */\nexport type TLCopyType = 'svg' | 'png'\n\n/** @public */\nexport interface CopyAsOptions extends TLImageExportOptions {\n\t/** The format to copy as. */\n\tformat: TLCopyType\n}\n\n/**\n * Copy the given shapes to the clipboard.\n *\n * @param editor - The editor instance.\n * @param ids - The ids of the shapes to copy.\n * @param format - The format to copy as. Defaults to png.\n * @param opts - Options for the copy.\n *\n * @public\n */\nexport function copyAs(editor: Editor, ids: TLShapeId[], opts: CopyAsOptions): Promise<void> {\n\t// Note: it's important that this function itself isn't async and doesn't really use promises -\n\t// we need to create the relevant `ClipboardItem`s and call navigator.clipboard.write\n\t// synchronously to make sure safari knows that the user _wants_ to copy See\n\t// https://bugs.webkit.org/show_bug.cgi?id=222262\n\n\tif (!navigator.clipboard) return Promise.reject(new Error('Copy not supported'))\n\tif (navigator.clipboard.write as any) {\n\t\tconst { blobPromise, mimeType } = exportToImagePromiseForClipboard(editor, ids, opts)\n\n\t\tconst types: Record<string, Promise<Blob>> = { [mimeType]: blobPromise }\n\t\tconst additionalMimeType = getAdditionalClipboardWriteType(opts.format)\n\t\tif (additionalMimeType && doesClipboardSupportType(additionalMimeType)) {\n\t\t\ttypes[additionalMimeType] = blobPromise.then((blob) =>\n\t\t\t\tFileHelpers.rewriteMimeType(blob, additionalMimeType)\n\t\t\t)\n\t\t}\n\n\t\treturn clipboardWrite(types)\n\t}\n\n\tswitch (opts.format) {\n\t\tcase 'svg': {\n\t\t\treturn fallbackWriteTextAsync(async () => {\n\t\t\t\tconst result = await editor.getSvgString(ids, opts)\n\n\t\t\t\tif (!result) throw new Error('Failed to copy')\n\t\t\t\treturn result.svg\n\t\t\t})\n\t\t}\n\n\t\tcase 'png':\n\t\t\tthrow new Error('Copy not supported')\n\t\tdefault:\n\t\t\texhaustiveSwitchError(opts.format)\n\t}\n}\n\nasync function fallbackWriteTextAsync(getText: () => Promise<string>) {\n\tawait navigator.clipboard?.writeText?.(await getText())\n}\n"],
5
+ "mappings": "AAAA;AAAA,EAEC;AAAA,EAGA;AAAA,OACM;AACP;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,wCAAwC;AAqB1C,SAAS,OAAO,QAAgB,KAAkB,MAAoC;AAM5F,MAAI,CAAC,UAAU,UAAW,QAAO,QAAQ,OAAO,IAAI,MAAM,oBAAoB,CAAC;AAC/E,MAAI,UAAU,UAAU,OAAc;AACrC,UAAM,EAAE,aAAa,SAAS,IAAI,iCAAiC,QAAQ,KAAK,IAAI;AAEpF,UAAM,QAAuC,EAAE,CAAC,QAAQ,GAAG,YAAY;AACvE,UAAM,qBAAqB,gCAAgC,KAAK,MAAM;AACtE,QAAI,sBAAsB,yBAAyB,kBAAkB,GAAG;AACvE,YAAM,kBAAkB,IAAI,YAAY;AAAA,QAAK,CAAC,SAC7C,YAAY,gBAAgB,MAAM,kBAAkB;AAAA,MACrD;AAAA,IACD;AAEA,WAAO,eAAe,KAAK;AAAA,EAC5B;AAEA,UAAQ,KAAK,QAAQ;AAAA,IACpB,KAAK,OAAO;AACX,aAAO,uBAAuB,YAAY;AACzC,cAAM,SAAS,MAAM,OAAO,aAAa,KAAK,IAAI;AAElD,YAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,gBAAgB;AAC7C,eAAO,OAAO;AAAA,MACf,CAAC;AAAA,IACF;AAAA,IAEA,KAAK;AACJ,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACrC;AACC,4BAAsB,KAAK,MAAM;AAAA,EACnC;AACD;AAEA,eAAe,uBAAuB,SAAgC;AACrE,QAAM,UAAU,WAAW,YAAY,MAAM,QAAQ,CAAC;AACvD;",
6
6
  "names": []
7
7
  }
@@ -23,25 +23,6 @@ async function exportToString(editor, ids, format, opts = {}) {
23
23
  }
24
24
  }
25
25
  }
26
- async function exportToBlob({
27
- editor,
28
- ids,
29
- format,
30
- opts = {}
31
- }) {
32
- const idsToUse = ids?.length ? ids : [...editor.getCurrentPageShapeIds()];
33
- switch (format) {
34
- case "jpeg":
35
- case "png":
36
- case "webp":
37
- case "svg": {
38
- return (await editor.toImage(idsToUse, { ...opts, format })).blob;
39
- }
40
- default: {
41
- exhaustiveSwitchError(format);
42
- }
43
- }
44
- }
45
26
  const clipboardMimeTypesByFormat = {
46
27
  jpeg: "image/jpeg",
47
28
  png: "image/png",
@@ -59,7 +40,6 @@ function exportToImagePromiseForClipboard(editor, ids, opts = {}) {
59
40
  };
60
41
  }
61
42
  export {
62
- exportToBlob,
63
43
  exportToImagePromiseForClipboard,
64
44
  exportToString
65
45
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/utils/export/export.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tFileHelpers,\n\tTLExportType,\n\tTLImageExportOptions,\n\tTLShapeId,\n\texhaustiveSwitchError,\n} from '@tldraw/editor'\n\nasync function getSvgString(editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions) {\n\tconst svg = await editor.getSvgString(ids, opts)\n\tif (!svg) {\n\t\tthrow new Error('Could not construct SVG.')\n\t}\n\treturn svg\n}\n\nexport async function exportToString(\n\teditor: Editor,\n\tids: TLShapeId[],\n\tformat: 'svg' | 'json',\n\topts: TLImageExportOptions = {}\n) {\n\tswitch (format) {\n\t\tcase 'svg': {\n\t\t\treturn (await getSvgString(editor, ids, opts))?.svg\n\t\t}\n\t\tcase 'json': {\n\t\t\tconst data = await editor.resolveAssetsInContent(editor.getContentFromCurrentPage(ids))\n\t\t\treturn JSON.stringify(data)\n\t\t}\n\t\tdefault: {\n\t\t\texhaustiveSwitchError(format)\n\t\t}\n\t}\n}\n\n/**\n * Export the given shapes as a blob.\n * @param editor - The editor instance.\n * @param ids - The ids of the shapes to export.\n * @param format - The format to export as.\n * @param opts - Rendering options.\n * @returns A promise that resolves to a blob.\n * @deprecated Use {@link @tldraw/editor#Editor.toImage} instead.\n * @public\n */\nexport async function exportToBlob({\n\teditor,\n\tids,\n\tformat,\n\topts = {},\n}: {\n\teditor: Editor\n\tids: TLShapeId[]\n\tformat: TLExportType\n\topts?: TLImageExportOptions\n}): Promise<Blob> {\n\tconst idsToUse = ids?.length ? ids : [...editor.getCurrentPageShapeIds()]\n\tswitch (format) {\n\t\tcase 'jpeg':\n\t\tcase 'png':\n\t\tcase 'webp':\n\t\tcase 'svg': {\n\t\t\treturn (await editor.toImage(idsToUse, { ...opts, format })).blob\n\t\t}\n\t\tdefault: {\n\t\t\texhaustiveSwitchError(format)\n\t\t}\n\t}\n}\n\nconst clipboardMimeTypesByFormat = {\n\tjpeg: 'image/jpeg',\n\tpng: 'image/png',\n\twebp: 'image/webp',\n\tsvg: 'text/plain',\n}\n\nexport function exportToImagePromiseForClipboard(\n\teditor: Editor,\n\tids: TLShapeId[],\n\topts: TLImageExportOptions = {}\n): { blobPromise: Promise<Blob>; mimeType: string } {\n\tconst idsToUse = ids?.length ? ids : [...editor.getCurrentPageShapeIds()]\n\tconst format = opts.format ?? 'png'\n\treturn {\n\t\tblobPromise: editor\n\t\t\t.toImage(idsToUse, opts)\n\t\t\t.then((result) =>\n\t\t\t\tFileHelpers.rewriteMimeType(result.blob, clipboardMimeTypesByFormat[format])\n\t\t\t),\n\t\tmimeType: clipboardMimeTypesByFormat[format],\n\t}\n}\n"],
5
- "mappings": "AAAA;AAAA,EAEC;AAAA,EAIA;AAAA,OACM;AAEP,eAAe,aAAa,QAAgB,KAAkB,MAA4B;AACzF,QAAM,MAAM,MAAM,OAAO,aAAa,KAAK,IAAI;AAC/C,MAAI,CAAC,KAAK;AACT,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC3C;AACA,SAAO;AACR;AAEA,eAAsB,eACrB,QACA,KACA,QACA,OAA6B,CAAC,GAC7B;AACD,UAAQ,QAAQ;AAAA,IACf,KAAK,OAAO;AACX,cAAQ,MAAM,aAAa,QAAQ,KAAK,IAAI,IAAI;AAAA,IACjD;AAAA,IACA,KAAK,QAAQ;AACZ,YAAM,OAAO,MAAM,OAAO,uBAAuB,OAAO,0BAA0B,GAAG,CAAC;AACtF,aAAO,KAAK,UAAU,IAAI;AAAA,IAC3B;AAAA,IACA,SAAS;AACR,4BAAsB,MAAM;AAAA,IAC7B;AAAA,EACD;AACD;AAYA,eAAsB,aAAa;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO,CAAC;AACT,GAKkB;AACjB,QAAM,WAAW,KAAK,SAAS,MAAM,CAAC,GAAG,OAAO,uBAAuB,CAAC;AACxE,UAAQ,QAAQ;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,OAAO;AACX,cAAQ,MAAM,OAAO,QAAQ,UAAU,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG;AAAA,IAC9D;AAAA,IACA,SAAS;AACR,4BAAsB,MAAM;AAAA,IAC7B;AAAA,EACD;AACD;AAEA,MAAM,6BAA6B;AAAA,EAClC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AACN;AAEO,SAAS,iCACf,QACA,KACA,OAA6B,CAAC,GACqB;AACnD,QAAM,WAAW,KAAK,SAAS,MAAM,CAAC,GAAG,OAAO,uBAAuB,CAAC;AACxE,QAAM,SAAS,KAAK,UAAU;AAC9B,SAAO;AAAA,IACN,aAAa,OACX,QAAQ,UAAU,IAAI,EACtB;AAAA,MAAK,CAAC,WACN,YAAY,gBAAgB,OAAO,MAAM,2BAA2B,MAAM,CAAC;AAAA,IAC5E;AAAA,IACD,UAAU,2BAA2B,MAAM;AAAA,EAC5C;AACD;",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tFileHelpers,\n\tTLImageExportOptions,\n\tTLShapeId,\n\texhaustiveSwitchError,\n} from '@tldraw/editor'\n\nasync function getSvgString(editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions) {\n\tconst svg = await editor.getSvgString(ids, opts)\n\tif (!svg) {\n\t\tthrow new Error('Could not construct SVG.')\n\t}\n\treturn svg\n}\n\nexport async function exportToString(\n\teditor: Editor,\n\tids: TLShapeId[],\n\tformat: 'svg' | 'json',\n\topts: TLImageExportOptions = {}\n) {\n\tswitch (format) {\n\t\tcase 'svg': {\n\t\t\treturn (await getSvgString(editor, ids, opts))?.svg\n\t\t}\n\t\tcase 'json': {\n\t\t\tconst data = await editor.resolveAssetsInContent(editor.getContentFromCurrentPage(ids))\n\t\t\treturn JSON.stringify(data)\n\t\t}\n\t\tdefault: {\n\t\t\texhaustiveSwitchError(format)\n\t\t}\n\t}\n}\n\nconst clipboardMimeTypesByFormat = {\n\tjpeg: 'image/jpeg',\n\tpng: 'image/png',\n\twebp: 'image/webp',\n\tsvg: 'text/plain',\n}\n\nexport function exportToImagePromiseForClipboard(\n\teditor: Editor,\n\tids: TLShapeId[],\n\topts: TLImageExportOptions = {}\n): { blobPromise: Promise<Blob>; mimeType: string } {\n\tconst idsToUse = ids?.length ? ids : [...editor.getCurrentPageShapeIds()]\n\tconst format = opts.format ?? 'png'\n\treturn {\n\t\tblobPromise: editor\n\t\t\t.toImage(idsToUse, opts)\n\t\t\t.then((result) =>\n\t\t\t\tFileHelpers.rewriteMimeType(result.blob, clipboardMimeTypesByFormat[format])\n\t\t\t),\n\t\tmimeType: clipboardMimeTypesByFormat[format],\n\t}\n}\n"],
5
+ "mappings": "AAAA;AAAA,EAEC;AAAA,EAGA;AAAA,OACM;AAEP,eAAe,aAAa,QAAgB,KAAkB,MAA4B;AACzF,QAAM,MAAM,MAAM,OAAO,aAAa,KAAK,IAAI;AAC/C,MAAI,CAAC,KAAK;AACT,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC3C;AACA,SAAO;AACR;AAEA,eAAsB,eACrB,QACA,KACA,QACA,OAA6B,CAAC,GAC7B;AACD,UAAQ,QAAQ;AAAA,IACf,KAAK,OAAO;AACX,cAAQ,MAAM,aAAa,QAAQ,KAAK,IAAI,IAAI;AAAA,IACjD;AAAA,IACA,KAAK,QAAQ;AACZ,YAAM,OAAO,MAAM,OAAO,uBAAuB,OAAO,0BAA0B,GAAG,CAAC;AACtF,aAAO,KAAK,UAAU,IAAI;AAAA,IAC3B;AAAA,IACA,SAAS;AACR,4BAAsB,MAAM;AAAA,IAC7B;AAAA,EACD;AACD;AAEA,MAAM,6BAA6B;AAAA,EAClC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AACN;AAEO,SAAS,iCACf,QACA,KACA,OAA6B,CAAC,GACqB;AACnD,QAAM,WAAW,KAAK,SAAS,MAAM,CAAC,GAAG,OAAO,uBAAuB,CAAC;AACxE,QAAM,SAAS,KAAK,UAAU;AAC9B,SAAO;AAAA,IACN,aAAa,OACX,QAAQ,UAAU,IAAI,EACtB;AAAA,MAAK,CAAC,WACN,YAAY,gBAAgB,OAAO,MAAM,2BAA2B,MAAM,CAAC;AAAA,IAC5E;AAAA,IACD,UAAU,2BAA2B,MAAM;AAAA,EAC5C;AACD;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  sanitizeId
3
3
  } from "@tldraw/editor";
4
- async function exportAs(...args) {
5
- const [editor, ids, opts] = typeof args[2] === "object" ? args : [args[0], args[1], { ...args[4], format: args[2] ?? "png", name: args[3] }];
4
+ async function exportAs(editor, ids, opts) {
6
5
  let name = opts.name;
7
6
  if (!name) {
8
7
  name = `shapes at ${getTimestamp()}`;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/utils/export/exportAs.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tsanitizeId,\n\tTLExportType,\n\tTLFrameShape,\n\tTLImageExportOptions,\n\tTLShapeId,\n} from '@tldraw/editor'\n\n/** @public */\nexport interface ExportAsOptions extends TLImageExportOptions {\n\t/** {@inheritdoc @tldraw/editor#TLImageExportOptions.format} */\n\tformat: TLExportType\n\t/** Name of the exported file. If undefined a predefined name, based on the selection, will be used. */\n\tname?: string\n}\n\n/**\n * Export the given shapes as files.\n *\n * @param editor - The editor instance.\n * @param ids - The ids of the shapes to export.\n * @param opts - Options for the export.\n *\n * @public\n */\nexport async function exportAs(\n\teditor: Editor,\n\tids: TLShapeId[],\n\topts: ExportAsOptions\n): Promise<void>\n/**\n * @deprecated The format & name parameters are now part of the opts object.\n * @public\n */\nexport async function exportAs(\n\teditor: Editor,\n\tids: TLShapeId[],\n\tformat?: TLExportType,\n\tname?: string,\n\topts?: TLImageExportOptions\n): Promise<void>\nexport async function exportAs(\n\t...args:\n\t\t| [\n\t\t\t\teditor: Editor,\n\t\t\t\tids: TLShapeId[],\n\t\t\t\topts: TLImageExportOptions & { format: TLExportType; name?: string },\n\t\t ]\n\t\t| [\n\t\t\t\teditor: Editor,\n\t\t\t\tids: TLShapeId[],\n\t\t\t\tformat?: TLExportType,\n\t\t\t\tname?: string,\n\t\t\t\topts?: TLImageExportOptions,\n\t\t ]\n) {\n\tconst [editor, ids, opts] =\n\t\ttypeof args[2] === 'object'\n\t\t\t? args\n\t\t\t: [args[0], args[1], { ...args[4], format: args[2] ?? 'png', name: args[3] }]\n\n\t// If we don't get name then use a predefined one\n\tlet name = opts.name\n\tif (!name) {\n\t\tname = `shapes at ${getTimestamp()}`\n\t\tif (ids.length === 1) {\n\t\t\tconst first = editor.getShape(ids[0])!\n\t\t\tif (editor.isShapeOfType<TLFrameShape>(first, 'frame')) {\n\t\t\t\tname = first.props.name || 'frame'\n\t\t\t} else {\n\t\t\t\tname = `${sanitizeId(first.id)} at ${getTimestamp()}`\n\t\t\t}\n\t\t}\n\t}\n\tname += `.${opts.format}`\n\n\tconst { blob } = await editor.toImage(ids, opts)\n\tconst file = new File([blob], name, { type: blob.type })\n\tdownloadFile(file)\n}\n\nfunction getTimestamp() {\n\tconst now = new Date()\n\n\tconst year = String(now.getFullYear()).slice(2)\n\tconst month = String(now.getMonth() + 1).padStart(2, '0')\n\tconst day = String(now.getDate()).padStart(2, '0')\n\tconst hours = String(now.getHours()).padStart(2, '0')\n\tconst minutes = String(now.getMinutes()).padStart(2, '0')\n\tconst seconds = String(now.getSeconds()).padStart(2, '0')\n\n\treturn `${year}-${month}-${day} ${hours}.${minutes}.${seconds}`\n}\n\n/** @internal */\nexport function downloadFile(file: File) {\n\tconst link = document.createElement('a')\n\tconst url = URL.createObjectURL(file)\n\tlink.href = url\n\tlink.download = file.name\n\tlink.click()\n\tURL.revokeObjectURL(url)\n}\n"],
5
- "mappings": "AAAA;AAAA,EAEC;AAAA,OAKM;AAmCP,eAAsB,YAClB,MAaF;AACD,QAAM,CAAC,QAAQ,KAAK,IAAI,IACvB,OAAO,KAAK,CAAC,MAAM,WAChB,OACA,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,QAAQ,KAAK,CAAC,KAAK,OAAO,MAAM,KAAK,CAAC,EAAE,CAAC;AAG9E,MAAI,OAAO,KAAK;AAChB,MAAI,CAAC,MAAM;AACV,WAAO,aAAa,aAAa,CAAC;AAClC,QAAI,IAAI,WAAW,GAAG;AACrB,YAAM,QAAQ,OAAO,SAAS,IAAI,CAAC,CAAC;AACpC,UAAI,OAAO,cAA4B,OAAO,OAAO,GAAG;AACvD,eAAO,MAAM,MAAM,QAAQ;AAAA,MAC5B,OAAO;AACN,eAAO,GAAG,WAAW,MAAM,EAAE,CAAC,OAAO,aAAa,CAAC;AAAA,MACpD;AAAA,IACD;AAAA,EACD;AACA,UAAQ,IAAI,KAAK,MAAM;AAEvB,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,QAAQ,KAAK,IAAI;AAC/C,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC;AACvD,eAAa,IAAI;AAClB;AAEA,SAAS,eAAe;AACvB,QAAM,MAAM,oBAAI,KAAK;AAErB,QAAM,OAAO,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,CAAC;AAC9C,QAAM,QAAQ,OAAO,IAAI,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,QAAM,MAAM,OAAO,IAAI,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AACjD,QAAM,QAAQ,OAAO,IAAI,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,QAAM,UAAU,OAAO,IAAI,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,QAAM,UAAU,OAAO,IAAI,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG;AAExD,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO;AAC9D;AAGO,SAAS,aAAa,MAAY;AACxC,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,OAAK,OAAO;AACZ,OAAK,WAAW,KAAK;AACrB,OAAK,MAAM;AACX,MAAI,gBAAgB,GAAG;AACxB;",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tsanitizeId,\n\tTLExportType,\n\tTLFrameShape,\n\tTLImageExportOptions,\n\tTLShapeId,\n} from '@tldraw/editor'\n\n/** @public */\nexport interface ExportAsOptions extends TLImageExportOptions {\n\t/** {@inheritdoc @tldraw/editor#TLImageExportOptions.format} */\n\tformat: TLExportType\n\t/** Name of the exported file. If undefined a predefined name, based on the selection, will be used. */\n\tname?: string\n}\n\n/**\n * Export the given shapes as files.\n *\n * @param editor - The editor instance.\n * @param ids - The ids of the shapes to export.\n * @param opts - Options for the export.\n *\n * @public\n */\nexport async function exportAs(\n\teditor: Editor,\n\tids: TLShapeId[],\n\topts: ExportAsOptions\n): Promise<void> {\n\t// If we don't get name then use a predefined one\n\tlet name = opts.name\n\tif (!name) {\n\t\tname = `shapes at ${getTimestamp()}`\n\t\tif (ids.length === 1) {\n\t\t\tconst first = editor.getShape(ids[0])!\n\t\t\tif (editor.isShapeOfType<TLFrameShape>(first, 'frame')) {\n\t\t\t\tname = first.props.name || 'frame'\n\t\t\t} else {\n\t\t\t\tname = `${sanitizeId(first.id)} at ${getTimestamp()}`\n\t\t\t}\n\t\t}\n\t}\n\tname += `.${opts.format}`\n\n\tconst { blob } = await editor.toImage(ids, opts)\n\tconst file = new File([blob], name, { type: blob.type })\n\tdownloadFile(file)\n}\n\nfunction getTimestamp() {\n\tconst now = new Date()\n\n\tconst year = String(now.getFullYear()).slice(2)\n\tconst month = String(now.getMonth() + 1).padStart(2, '0')\n\tconst day = String(now.getDate()).padStart(2, '0')\n\tconst hours = String(now.getHours()).padStart(2, '0')\n\tconst minutes = String(now.getMinutes()).padStart(2, '0')\n\tconst seconds = String(now.getSeconds()).padStart(2, '0')\n\n\treturn `${year}-${month}-${day} ${hours}.${minutes}.${seconds}`\n}\n\n/** @internal */\nexport function downloadFile(file: File) {\n\tconst link = document.createElement('a')\n\tconst url = URL.createObjectURL(file)\n\tlink.href = url\n\tlink.download = file.name\n\tlink.click()\n\tURL.revokeObjectURL(url)\n}\n"],
5
+ "mappings": "AAAA;AAAA,EAEC;AAAA,OAKM;AAmBP,eAAsB,SACrB,QACA,KACA,MACgB;AAEhB,MAAI,OAAO,KAAK;AAChB,MAAI,CAAC,MAAM;AACV,WAAO,aAAa,aAAa,CAAC;AAClC,QAAI,IAAI,WAAW,GAAG;AACrB,YAAM,QAAQ,OAAO,SAAS,IAAI,CAAC,CAAC;AACpC,UAAI,OAAO,cAA4B,OAAO,OAAO,GAAG;AACvD,eAAO,MAAM,MAAM,QAAQ;AAAA,MAC5B,OAAO;AACN,eAAO,GAAG,WAAW,MAAM,EAAE,CAAC,OAAO,aAAa,CAAC;AAAA,MACpD;AAAA,IACD;AAAA,EACD;AACA,UAAQ,IAAI,KAAK,MAAM;AAEvB,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,QAAQ,KAAK,IAAI;AAC/C,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,MAAM,EAAE,MAAM,KAAK,KAAK,CAAC;AACvD,eAAa,IAAI;AAClB;AAEA,SAAS,eAAe;AACvB,QAAM,MAAM,oBAAI,KAAK;AAErB,QAAM,OAAO,OAAO,IAAI,YAAY,CAAC,EAAE,MAAM,CAAC;AAC9C,QAAM,QAAQ,OAAO,IAAI,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,QAAM,MAAM,OAAO,IAAI,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AACjD,QAAM,QAAQ,OAAO,IAAI,SAAS,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,QAAM,UAAU,OAAO,IAAI,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG;AACxD,QAAM,UAAU,OAAO,IAAI,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG;AAExD,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO;AAC9D;AAGO,SAAS,aAAa,MAAY;AACxC,QAAM,OAAO,SAAS,cAAc,GAAG;AACvC,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,OAAK,OAAO;AACZ,OAAK,WAAW,KAAK;AACrB,OAAK,MAAM;AACX,MAAI,gBAAgB,GAAG;AACxB;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tldraw",
3
3
  "description": "A tiny little drawing editor.",
4
- "version": "3.16.0-internal.51e99e128bd4",
4
+ "version": "3.16.0-internal.71f83a8a571b",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -55,8 +55,8 @@
55
55
  "@tiptap/pm": "^2.9.1",
56
56
  "@tiptap/react": "^2.9.1",
57
57
  "@tiptap/starter-kit": "^2.9.1",
58
- "@tldraw/editor": "3.16.0-internal.51e99e128bd4",
59
- "@tldraw/store": "3.16.0-internal.51e99e128bd4",
58
+ "@tldraw/editor": "3.16.0-internal.71f83a8a571b",
59
+ "@tldraw/store": "3.16.0-internal.71f83a8a571b",
60
60
  "classnames": "^2.5.1",
61
61
  "hotkeys-js": "^3.13.9",
62
62
  "idb": "^7.1.1",
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ export { usePrefersReducedMotion } from './lib/shapes/shared/usePrefersReducedMo
24
24
  export { DefaultA11yAnnouncer, useSelectedShapesAnnouncer } from './lib/ui/components/A11y'
25
25
  export { AccessibilityMenu } from './lib/ui/components/AccessibilityMenu'
26
26
  export { ColorSchemeMenu } from './lib/ui/components/ColorSchemeMenu'
27
+ export { DefaultFollowingIndicator } from './lib/ui/components/DefaultFollowingIndicator'
27
28
  export { DefaultDialogs } from './lib/ui/components/Dialogs'
28
29
  export {
29
30
  TldrawUiColumn,
@@ -85,6 +86,7 @@ export {
85
86
  defaultHandleExternalUrlContent,
86
87
  getAssetInfo,
87
88
  getMediaAssetInfoPartial,
89
+ notifyIfFileNotAllowed,
88
90
  registerDefaultExternalContentHandlers,
89
91
  type TLDefaultExternalContentHandlerOpts,
90
92
  type TLExternalContentProps,
@@ -169,11 +171,7 @@ export {
169
171
  export { getStrokePoints } from './lib/shapes/shared/freehand/getStrokePoints'
170
172
  export { getSvgPathFromStrokePoints } from './lib/shapes/shared/freehand/svg'
171
173
  export { type StrokeOptions, type StrokePoint } from './lib/shapes/shared/freehand/types'
172
- export {
173
- PlainTextLabel,
174
- TextLabel,
175
- type PlainTextLabelProps,
176
- } from './lib/shapes/shared/PlainTextLabel'
174
+ export { PlainTextLabel, type PlainTextLabelProps } from './lib/shapes/shared/PlainTextLabel'
177
175
  export {
178
176
  RichTextLabel,
179
177
  RichTextSVG,
@@ -181,10 +179,9 @@ export {
181
179
  type RichTextSVGProps,
182
180
  } from './lib/shapes/shared/RichTextLabel'
183
181
  export { useDefaultColorTheme } from './lib/shapes/shared/useDefaultColorTheme'
184
- export { useEditablePlainText, useEditableText } from './lib/shapes/shared/useEditablePlainText'
182
+ export { useEditablePlainText } from './lib/shapes/shared/useEditablePlainText'
185
183
  export { useEditableRichText } from './lib/shapes/shared/useEditableRichText'
186
184
  export {
187
- useAsset,
188
185
  useImageOrVideoAsset,
189
186
  type UseImageOrVideoAssetOptions,
190
187
  } from './lib/shapes/shared/useImageOrVideoAsset'
@@ -363,10 +360,6 @@ export {
363
360
  TldrawUiMenuSubmenu,
364
361
  type TLUiMenuSubmenuProps,
365
362
  } from './lib/ui/components/primitives/menus/TldrawUiMenuSubmenu'
366
- export {
367
- TldrawUiButtonPicker,
368
- type TLUiButtonPickerProps,
369
- } from './lib/ui/components/primitives/TldrawUiButtonPicker'
370
363
  export {
371
364
  TldrawUiContextualToolbar,
372
365
  type TLUiContextualToolbarProps,
@@ -446,17 +439,44 @@ export {
446
439
  type TLUiStylePanelProps,
447
440
  } from './lib/ui/components/StylePanel/DefaultStylePanel'
448
441
  export {
449
- ArrowheadStylePickerSet,
450
- CommonStylePickerSet,
451
442
  DefaultStylePanelContent,
452
- GeoStylePickerSet,
453
- OpacitySlider,
454
- SplineStylePickerSet,
455
- TextStylePickerSet,
456
- type StylePickerSetProps,
457
- type ThemeStylePickerSetProps,
458
- type TLUiStylePanelContentProps,
443
+ StylePanelArrowheadPicker,
444
+ StylePanelArrowKindPicker,
445
+ StylePanelColorPicker,
446
+ StylePanelDashPicker,
447
+ StylePanelFillPicker,
448
+ StylePanelFontPicker,
449
+ StylePanelGeoShapePicker,
450
+ StylePanelLabelAlignPicker,
451
+ StylePanelOpacityPicker,
452
+ StylePanelSection,
453
+ StylePanelSizePicker,
454
+ StylePanelSplinePicker,
455
+ StylePanelTextAlignPicker,
456
+ type StylePanelSectionProps,
459
457
  } from './lib/ui/components/StylePanel/DefaultStylePanelContent'
458
+ export {
459
+ StylePanelButtonPicker,
460
+ type StylePanelButtonPickerProps,
461
+ } from './lib/ui/components/StylePanel/StylePanelButtonPicker'
462
+ export {
463
+ StylePanelContextProvider,
464
+ useStylePanelContext,
465
+ type StylePanelContext,
466
+ type StylePanelContextProviderProps,
467
+ } from './lib/ui/components/StylePanel/StylePanelContext'
468
+ export {
469
+ StylePanelDoubleDropdownPicker,
470
+ type StylePanelDoubleDropdownPickerProps,
471
+ } from './lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker'
472
+ export {
473
+ StylePanelDropdownPicker,
474
+ type StylePanelDropdownPickerProps,
475
+ } from './lib/ui/components/StylePanel/StylePanelDropdownPicker'
476
+ export {
477
+ StylePanelSubheading,
478
+ type StylePanelSubheadingProps,
479
+ } from './lib/ui/components/StylePanel/StylePanelSubheading'
460
480
  export {
461
481
  DefaultImageToolbar,
462
482
  type TLUiImageToolbarProps,
@@ -628,13 +648,12 @@ export {
628
648
  } from './lib/ui/hooks/useTranslation/useTranslation'
629
649
  export { type TLUiIconType } from './lib/ui/icon-types'
630
650
  export { useDefaultHelpers, type TLUiOverrideHelpers, type TLUiOverrides } from './lib/ui/overrides'
631
- export { TldrawUi, type TldrawUiProps } from './lib/ui/TldrawUi'
651
+ export { TldrawUi, TldrawUiInFrontOfTheCanvas, type TldrawUiProps } from './lib/ui/TldrawUi'
632
652
  export { containBoxSize, downsizeImage, type BoxWidthHeight } from './lib/utils/assets/assets'
633
653
  export { preloadFont, type TLTypeFace } from './lib/utils/assets/preload-font'
634
654
  export { getEmbedInfo, type TLEmbedResult } from './lib/utils/embeds/embeds'
635
655
  export { putExcalidrawContent } from './lib/utils/excalidraw/putExcalidrawContent'
636
656
  export { copyAs, type CopyAsOptions, type TLCopyType } from './lib/utils/export/copyAs'
637
- export { exportToBlob } from './lib/utils/export/export'
638
657
  export { downloadFile, exportAs, type ExportAsOptions } from './lib/utils/export/exportAs'
639
658
  export { fitFrameToContent, removeFrame } from './lib/utils/frames/frames'
640
659
  export {
@@ -33,7 +33,7 @@ import { registerDefaultSideEffects } from './defaultSideEffects'
33
33
  import { defaultTools } from './defaultTools'
34
34
  import { EmbedShapeUtil } from './shapes/embed/EmbedShapeUtil'
35
35
  import { allDefaultFontFaces } from './shapes/shared/defaultFonts'
36
- import { TldrawUi, TldrawUiProps } from './ui/TldrawUi'
36
+ import { TldrawUi, TldrawUiInFrontOfTheCanvas, TldrawUiProps } from './ui/TldrawUi'
37
37
  import { TLUiAssetUrlOverrides, useDefaultUiAssetUrlsWithOverrides } from './ui/assetUrls'
38
38
  import { LoadingScreen } from './ui/components/LoadingScreen'
39
39
  import { Spinner } from './ui/components/Spinner'
@@ -118,6 +118,18 @@ export function Tldraw(props: TldrawProps) {
118
118
 
119
119
  const _components = useShallowObjectIdentity(components)
120
120
 
121
+ const CustomInFrontOfTheCanvas = components?.InFrontOfTheCanvas
122
+ const InFrontOfTheCanvas = useMemo(() => {
123
+ if (rest.hideUi) return CustomInFrontOfTheCanvas ?? null
124
+ if (!CustomInFrontOfTheCanvas) return TldrawUiInFrontOfTheCanvas
125
+
126
+ return () => (
127
+ <>
128
+ <TldrawUiInFrontOfTheCanvas />
129
+ <CustomInFrontOfTheCanvas />
130
+ </>
131
+ )
132
+ }, [rest.hideUi, CustomInFrontOfTheCanvas])
121
133
  const componentsWithDefault = useMemo(
122
134
  () => ({
123
135
  Scribble: TldrawScribble,
@@ -129,8 +141,9 @@ export function Tldraw(props: TldrawProps) {
129
141
  Spinner,
130
142
  LoadingScreen,
131
143
  ..._components,
144
+ InFrontOfTheCanvas,
132
145
  }),
133
- [_components]
146
+ [_components, InFrontOfTheCanvas]
134
147
  )
135
148
 
136
149
  const _shapeUtils = useShallowArrayIdentity(shapeUtils)
@@ -144,7 +144,7 @@ export async function defaultHandleExternalFileAsset(
144
144
  { file, assetId }: TLFileExternalAsset,
145
145
  options: TLDefaultExternalContentHandlerOpts
146
146
  ) {
147
- const isSuccess = runFileChecks(file, options)
147
+ const isSuccess = notifyIfFileNotAllowed(file, options)
148
148
  if (!isSuccess) assert(false, 'File checks failed')
149
149
 
150
150
  const assetInfo = await getAssetInfo(file, options, assetId)
@@ -161,7 +161,7 @@ export async function defaultHandleExternalFileReplaceContent(
161
161
  { file, shapeId, isImage }: TLFileReplaceExternalContent,
162
162
  options: TLDefaultExternalContentHandlerOpts
163
163
  ) {
164
- const isSuccess = runFileChecks(file, options)
164
+ const isSuccess = notifyIfFileNotAllowed(file, options)
165
165
  if (!isSuccess) assert(false, 'File checks failed')
166
166
 
167
167
  const shape = editor.getShape(shapeId)
@@ -399,7 +399,7 @@ export async function defaultHandleExternalFileContent(
399
399
  file: File
400
400
  }[] = []
401
401
  for (const file of files) {
402
- const isSuccess = runFileChecks(file, options)
402
+ const isSuccess = notifyIfFileNotAllowed(file, options)
403
403
  if (!isSuccess) continue
404
404
 
405
405
  const assetInfo = await getAssetInfo(file, options)
@@ -873,7 +873,15 @@ export function createEmptyBookmarkShape(
873
873
  return editor.getShape(partial.id) as TLBookmarkShape
874
874
  }
875
875
 
876
- function runFileChecks(file: File, options: TLDefaultExternalContentHandlerOpts) {
876
+ /**
877
+ * Checks if a file is allowed to be uploaded. If it is not, it will show a toast explaining why to the user.
878
+ *
879
+ * @param file - The file to check
880
+ * @param options - The options for the external content handler
881
+ * @returns True if the file is allowed, false otherwise
882
+ * @public
883
+ */
884
+ export function notifyIfFileNotAllowed(file: File, options: TLDefaultExternalContentHandlerOpts) {
877
885
  const {
878
886
  acceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES,
879
887
  acceptedVideoMimeTypes = DEFAULT_SUPPORT_VIDEO_TYPES,
@@ -569,12 +569,12 @@ describe('reparenting issue', () => {
569
569
  const arrow1BoundIndex = editor.getShape(arrow1Id)!.index
570
570
  const arrow2BoundIndex = editor.getShape(arrow2Id)!.index
571
571
  expect(arrow1BoundIndex).toBe('a1V')
572
- expect(arrow2BoundIndex).toBe('a1F')
572
+ expect(arrow2BoundIndex).toBe('a1G')
573
573
 
574
574
  // nudge everything around and make sure we all stay in the right order
575
575
  editor.selectAll().nudgeShapes(editor.getSelectedShapeIds(), { x: -1, y: 0 })
576
576
  expect(editor.getShape(arrow1Id)!.index).toBe('a1V')
577
- expect(editor.getShape(arrow2Id)!.index).toBe('a1F')
577
+ expect(editor.getShape(arrow2Id)!.index).toBe('a1G')
578
578
  })
579
579
  })
580
580
 
@@ -579,3 +579,44 @@ describe("an arrow's parents", () => {
579
579
  })
580
580
  })
581
581
  })
582
+
583
+ describe('Arrow export bounds', () => {
584
+ it('excludes labels from shape bounds for export', () => {
585
+ editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
586
+
587
+ // Create shapes for the arrow to bind to
588
+ editor.createShapes([
589
+ { id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
590
+ { id: ids.box2, type: 'geo', x: 300, y: 100, props: { w: 100, h: 100 } },
591
+ ])
592
+
593
+ // Create an arrow with a label
594
+ editor.createShapes([
595
+ {
596
+ id: ids.arrow1,
597
+ type: 'arrow',
598
+ x: 0,
599
+ y: 0,
600
+ props: {
601
+ start: { x: 0, y: 0 },
602
+ end: { x: 0, y: 100 },
603
+ richText: toRichText('Test Label'),
604
+ },
605
+ },
606
+ ])
607
+
608
+ // Get the page bounds (should exclude labels due to excludeFromShapeBounds flag)
609
+ const pageBounds = editor.getShapePageBounds(ids.arrow1)
610
+ expect(pageBounds).toBeDefined()
611
+
612
+ // The bounds should be smaller than if labels were included
613
+ // Since the arrow has a label that's excluded, the bounds should be minimal
614
+ expect(pageBounds!.width).toBeLessThan(200) // Should not include label width
615
+ expect(pageBounds!.height).toBeLessThan(200) // Should not include label height
616
+
617
+ // Verify that the arrow has a label (which should be excluded from shape bounds)
618
+ const arrow = editor.getShape(ids.arrow1) as TLArrowShape
619
+ expect(arrow.props.richText).toBeDefined()
620
+ expect(arrow.props.richText).not.toBeNull()
621
+ })
622
+ })
@@ -227,6 +227,14 @@ interface ArrowheadInfo {
227
227
  hasEndArrowhead: boolean
228
228
  }
229
229
  export function getArrowLabelPosition(editor: Editor, shape: TLArrowShape) {
230
+ const isEditing = editor.getEditingShapeId() === shape.id
231
+ if (!isEditing && isEmptyRichText(shape.props.richText)) {
232
+ // Short-circuit for empty labels.
233
+ const bodyGeom = getArrowBodyGeometry(editor, shape)
234
+ const labelCenter = bodyGeom.interpolateAlongEdge(0.5)
235
+ return { box: Box.FromCenter(labelCenter, new Vec(0, 0)), debugGeom: [] }
236
+ }
237
+
230
238
  const debugGeom: Geometry2d[] = []
231
239
  const info = getArrowInfo(editor, shape)!
232
240
 
@@ -346,7 +346,7 @@ export function updateArrowTargetState({
346
346
  return result
347
347
  }
348
348
 
349
- const targetFilterFallback = { type: 'arrow' }
349
+ const targetFilterFallback = { type: 'arrow' as const }
350
350
 
351
351
  /**
352
352
  * Funky math but we want the snap distance to be 4 at the minimum and either 16 or 15% of the
@@ -45,11 +45,11 @@ export function getElbowArrowSnapLines(editor: Editor) {
45
45
 
46
46
  const unselectedArrowShapeIds = editor.store.query.ids('shape', () => {
47
47
  const activeArrowShapeId = currentSelectedArrowShape.get()
48
- if (!activeArrowShapeId) return { type: { eq: 'arrow' } }
48
+ if (!activeArrowShapeId) return { type: { eq: 'arrow' } } as const
49
49
  return {
50
50
  type: { eq: 'arrow' },
51
51
  id: { neq: activeArrowShapeId },
52
- }
52
+ } as const
53
53
  })
54
54
 
55
55
  return computed('elbow arrow snap lines', () => {