tldraw 3.16.0-next.282b7be564ae → 3.16.0-next.2f9d39693e4c

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 (291) hide show
  1. package/dist-cjs/index.d.ts +224 -102
  2. package/dist-cjs/index.js +33 -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/frame/FrameShapeUtil.js +6 -0
  11. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  13. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  15. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  16. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  17. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
  18. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  19. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  20. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  21. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  22. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  23. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  24. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  25. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  26. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  27. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  28. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  29. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  30. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  31. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  32. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  33. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  34. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  36. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  37. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  38. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  39. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  40. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  41. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  42. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  43. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  44. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  45. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  46. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  47. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  48. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  50. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  52. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  54. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
  56. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
  58. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  60. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  61. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +37 -36
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +2 -1
  64. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  65. package/dist-cjs/lib/ui/context/actions.js +23 -10
  66. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  67. package/dist-cjs/lib/ui/context/components.js +2 -0
  68. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  69. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  70. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  71. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  72. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  73. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  74. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  75. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  76. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  77. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  78. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  79. package/dist-cjs/lib/ui/version.js +3 -3
  80. package/dist-cjs/lib/ui/version.js.map +1 -1
  81. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  82. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  83. package/dist-cjs/lib/utils/export/export.js +0 -20
  84. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  85. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  86. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  87. package/dist-esm/index.d.mts +224 -102
  88. package/dist-esm/index.mjs +61 -29
  89. package/dist-esm/index.mjs.map +2 -2
  90. package/dist-esm/lib/Tldraw.mjs +14 -4
  91. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  92. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  93. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  94. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  95. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  96. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -0
  97. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  98. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  99. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  100. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  101. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  102. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  103. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
  104. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  105. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  106. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  107. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  108. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  109. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  110. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  111. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  112. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  113. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  114. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  115. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  116. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  117. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  118. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  119. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  120. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  121. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  122. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  123. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  124. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  125. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  126. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  127. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  128. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  129. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  130. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  131. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  132. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  133. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  134. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  135. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  136. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  137. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  138. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  139. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  140. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  141. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
  142. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  143. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
  144. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  145. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  146. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  147. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +37 -36
  148. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  149. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +2 -1
  150. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  151. package/dist-esm/lib/ui/context/actions.mjs +23 -10
  152. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  153. package/dist-esm/lib/ui/context/components.mjs +2 -0
  154. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  155. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  156. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  157. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  158. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  159. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  160. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  161. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  162. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  163. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  164. package/dist-esm/lib/ui/version.mjs +3 -3
  165. package/dist-esm/lib/ui/version.mjs.map +1 -1
  166. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  167. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  168. package/dist-esm/lib/utils/export/export.mjs +0 -20
  169. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  170. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  171. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  172. package/package.json +11 -34
  173. package/src/index.ts +44 -22
  174. package/src/lib/Tldraw.tsx +15 -2
  175. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  176. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  177. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  178. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  179. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  180. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  181. package/src/lib/shapes/frame/FrameShapeUtil.tsx +8 -0
  182. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  183. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  184. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  185. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  186. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  187. package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
  188. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  189. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  190. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  191. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  192. package/src/lib/ui/TldrawUi.tsx +16 -10
  193. package/src/lib/ui/assetUrls.ts +13 -10
  194. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  195. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  196. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  197. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  198. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  199. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  200. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  201. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  202. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  203. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  204. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  205. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  206. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  207. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
  208. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
  209. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  210. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +29 -21
  211. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -2
  212. package/src/lib/ui/context/actions.tsx +23 -10
  213. package/src/lib/ui/context/components.tsx +3 -0
  214. package/src/lib/ui/context/events.tsx +1 -1
  215. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  216. package/src/lib/ui/hooks/useTools.tsx +1 -1
  217. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  218. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  219. package/src/lib/ui/kbd-utils.ts +10 -3
  220. package/src/lib/ui/version.ts +3 -3
  221. package/src/lib/ui.css +19 -2
  222. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  223. package/src/lib/utils/export/copyAs.ts +1 -24
  224. package/src/lib/utils/export/export.ts +0 -36
  225. package/src/lib/utils/export/exportAs.ts +1 -32
  226. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  227. package/src/test/A11y.test.tsx +3 -2
  228. package/src/test/ClickManager.test.ts +7 -6
  229. package/src/test/Editor.test.tsx +20 -19
  230. package/src/test/EraserTool.test.ts +184 -13
  231. package/src/test/HandTool.test.ts +10 -9
  232. package/src/test/HighlightShape.test.ts +2 -1
  233. package/src/test/SelectTool.test.ts +3 -2
  234. package/src/test/TLUserPreferences.test.ts +4 -3
  235. package/src/test/TestEditor.ts +13 -15
  236. package/src/test/TldrawEditor.test.tsx +11 -10
  237. package/src/test/ZoomTool.test.ts +7 -6
  238. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  239. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  240. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  241. package/src/test/arrows-megabus.test.tsx +5 -4
  242. package/src/test/bindings.test.tsx +24 -37
  243. package/src/test/bookmark-shapes.test.ts +1 -8
  244. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  245. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  246. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  247. package/src/test/commands/alignShapes.test.tsx +25 -24
  248. package/src/test/commands/animationSpeed.test.ts +2 -1
  249. package/src/test/commands/centerOnPoint.test.ts +3 -2
  250. package/src/test/commands/clipboard.test.ts +3 -2
  251. package/src/test/commands/createShapes.test.ts +2 -1
  252. package/src/test/commands/deleteShapes.test.ts +2 -1
  253. package/src/test/commands/distributeShapes.test.tsx +11 -10
  254. package/src/test/commands/getSvgString.test.ts +2 -1
  255. package/src/test/commands/packShapes.test.ts +5 -4
  256. package/src/test/commands/resizeShape.test.ts +2 -1
  257. package/src/test/commands/rotateShapes.test.ts +7 -6
  258. package/src/test/commands/setCamera.test.ts +4 -3
  259. package/src/test/commands/setCurrentPage.test.ts +3 -2
  260. package/src/test/commands/stackShapes.test.ts +11 -10
  261. package/src/test/commands/stretch.test.tsx +13 -12
  262. package/src/test/createDeepLink.test.tsx +2 -1
  263. package/src/test/cropping.test.ts +3 -2
  264. package/src/test/custom-clipping.test.ts +436 -0
  265. package/src/test/drawing.test.ts +2 -1
  266. package/src/test/flipShapes.test.ts +4 -3
  267. package/src/test/frames.test.ts +25 -24
  268. package/src/test/getCulledShapes.test.tsx +3 -2
  269. package/src/test/groups.test.tsx +1 -1
  270. package/src/test/handleDeepLink.test.tsx +2 -1
  271. package/src/test/maxShapes.test.ts +3 -2
  272. package/src/test/modifiers.test.ts +5 -4
  273. package/src/test/navigation.test.ts +12 -11
  274. package/src/test/panning.test.ts +2 -1
  275. package/src/test/perf/perf.test.ts +2 -1
  276. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  277. package/src/test/resizing.test.ts +39 -38
  278. package/src/test/select.test.tsx +4 -3
  279. package/src/test/selection-omnibus.test.ts +11 -10
  280. package/src/test/shapeutils.test.ts +4 -3
  281. package/src/test/translating.test.ts +9 -8
  282. package/tldraw.css +27 -2
  283. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  284. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  285. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  286. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  287. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  288. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  289. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  290. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  291. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -12,417 +12,333 @@ import {
12
12
  DefaultVerticalAlignStyle,
13
13
  GeoShapeGeoStyle,
14
14
  LineShapeSplineStyle,
15
- ReadonlySharedStyleMap,
16
- StyleProp,
17
15
  TLArrowShapeArrowheadStyle,
18
- TLDefaultColorTheme,
19
- getDefaultColorTheme,
20
16
  kickoutOccludedShapes,
21
17
  minBy,
22
18
  useEditor,
23
- useIsDarkMode,
24
19
  useValue,
25
20
  } from '@tldraw/editor'
26
- import React, { useCallback } from 'react'
21
+ import React from 'react'
27
22
  import { STYLES } from '../../../styles'
28
23
  import { useUiEvents } from '../../context/events'
29
- import { useRelevantStyles } from '../../hooks/useRelevantStyles'
30
24
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
31
25
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
32
- import { TldrawUiButtonPicker } from '../primitives/TldrawUiButtonPicker'
33
26
  import { TldrawUiSlider } from '../primitives/TldrawUiSlider'
34
27
  import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
35
- import { DoubleDropdownPicker } from './DoubleDropdownPicker'
36
- import { DropdownPicker } from './DropdownPicker'
28
+ import { StylePanelButtonPicker } from './StylePanelButtonPicker'
29
+ import { useStylePanelContext } from './StylePanelContext'
30
+ import { StylePanelDoubleDropdownPicker } from './StylePanelDoubleDropdownPicker'
31
+ import { StylePanelDropdownPicker } from './StylePanelDropdownPicker'
32
+ import { StylePanelSubheading } from './StylePanelSubheading'
37
33
 
38
- // Local component for style panel subheadings
39
- function StylePanelSubheading({ children }: { children: React.ReactNode }) {
40
- return <h3 className="tlui-style-panel__subheading">{children}</h3>
34
+ /** @public @react */
35
+ export function DefaultStylePanelContent() {
36
+ return (
37
+ <>
38
+ <StylePanelSection>
39
+ <StylePanelColorPicker />
40
+ <StylePanelOpacityPicker />
41
+ </StylePanelSection>
42
+ <StylePanelSection>
43
+ <StylePanelFillPicker />
44
+ <StylePanelDashPicker />
45
+ <StylePanelSizePicker />
46
+ </StylePanelSection>
47
+ <StylePanelSection>
48
+ <StylePanelFontPicker />
49
+ <StylePanelTextAlignPicker />
50
+ <StylePanelLabelAlignPicker />
51
+ </StylePanelSection>
52
+ <StylePanelSection>
53
+ <StylePanelGeoShapePicker />
54
+ <StylePanelArrowKindPicker />
55
+ <StylePanelArrowheadPicker />
56
+ <StylePanelSplinePicker />
57
+ </StylePanelSection>
58
+ </>
59
+ )
41
60
  }
42
61
 
43
62
  /** @public */
44
- export interface TLUiStylePanelContentProps {
45
- styles: ReturnType<typeof useRelevantStyles>
63
+ export interface StylePanelSectionProps {
64
+ children: React.ReactNode
46
65
  }
47
66
 
48
67
  /** @public @react */
49
- export function DefaultStylePanelContent({ styles }: TLUiStylePanelContentProps) {
50
- const isDarkMode = useIsDarkMode()
51
-
52
- if (!styles) return null
53
-
54
- const geo = styles.get(GeoShapeGeoStyle)
55
- const arrowheadEnd = styles.get(ArrowShapeArrowheadEndStyle)
56
- const arrowheadStart = styles.get(ArrowShapeArrowheadStartStyle)
57
- const arrowKind = styles.get(ArrowShapeKindStyle)
58
- const spline = styles.get(LineShapeSplineStyle)
59
- const font = styles.get(DefaultFontStyle)
60
-
61
- const hideGeo = geo === undefined
62
- const hideArrowHeads = arrowheadEnd === undefined && arrowheadStart === undefined
63
- const hideSpline = spline === undefined
64
- const hideArrowKind = arrowKind === undefined
65
- const hideText = font === undefined
68
+ export function StylePanelSection({ children }: StylePanelSectionProps) {
69
+ return <div className="tlui-style-panel__section">{children}</div>
70
+ }
66
71
 
67
- const theme = getDefaultColorTheme({ isDarkMode: isDarkMode })
72
+ /** @public @react */
73
+ export function StylePanelColorPicker() {
74
+ const { styles } = useStylePanelContext()
75
+ const msg = useTranslation()
76
+ const color = styles.get(DefaultColorStyle)
77
+ if (color === undefined) return null
68
78
 
69
79
  return (
70
- <>
71
- <CommonStylePickerSet theme={theme} styles={styles} />
72
- {!hideText && <TextStylePickerSet theme={theme} styles={styles} />}
73
- {!(hideGeo && hideArrowHeads && hideSpline && hideArrowKind) && (
74
- <div className="tlui-style-panel__section">
75
- <GeoStylePickerSet styles={styles} />
76
- <ArrowStylePickerSet styles={styles} />
77
- <ArrowheadStylePickerSet styles={styles} />
78
- <SplineStylePickerSet styles={styles} />
79
- </div>
80
- )}
81
- </>
80
+ <StylePanelButtonPicker
81
+ title={msg('style-panel.color')}
82
+ uiType="color"
83
+ style={DefaultColorStyle}
84
+ items={STYLES.color}
85
+ value={color}
86
+ />
82
87
  )
83
88
  }
84
89
 
85
- function useStyleChangeCallback() {
90
+ const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const
91
+ /** @public @react */
92
+ export function StylePanelOpacityPicker() {
86
93
  const editor = useEditor()
94
+ const { onHistoryMark, showUiLabels } = useStylePanelContext()
95
+
96
+ const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor])
87
97
  const trackEvent = useUiEvents()
98
+ const msg = useTranslation()
99
+
100
+ const handleOpacityValueChange = React.useCallback(
101
+ (value: number) => {
102
+ const item = tldrawSupportedOpacities[value]
103
+ editor.run(() => {
104
+ if (editor.isIn('select')) {
105
+ editor.setOpacityForSelectedShapes(item)
106
+ }
107
+ editor.setOpacityForNextShapes(item)
108
+ editor.updateInstanceState({ isChangingStyle: true })
109
+ })
88
110
 
89
- return React.useMemo(
90
- () =>
91
- function handleStyleChange<T>(style: StyleProp<T>, value: T) {
92
- editor.run(() => {
93
- if (editor.isIn('select')) {
94
- editor.setStyleForSelectedShapes(style, value)
95
- }
96
- editor.setStyleForNextShapes(style, value)
97
- editor.updateInstanceState({ isChangingStyle: true })
98
- })
99
-
100
- trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string })
101
- },
111
+ trackEvent('set-style', { source: 'style-panel', id: 'opacity', value })
112
+ },
102
113
  [editor, trackEvent]
103
114
  )
104
- }
105
115
 
106
- /** @public */
107
- export interface ThemeStylePickerSetProps {
108
- styles: ReadonlySharedStyleMap
109
- theme: TLDefaultColorTheme
110
- }
116
+ if (opacity === undefined) return null
111
117
 
112
- /** @public */
113
- export interface StylePickerSetProps {
114
- styles: ReadonlySharedStyleMap
118
+ const opacityIndex =
119
+ opacity.type === 'mixed'
120
+ ? -1
121
+ : tldrawSupportedOpacities.indexOf(
122
+ minBy(tldrawSupportedOpacities, (supportedOpacity) =>
123
+ Math.abs(supportedOpacity - opacity.value)
124
+ )!
125
+ )
126
+
127
+ return (
128
+ <>
129
+ {showUiLabels && <StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>}
130
+ <TldrawUiSlider
131
+ data-testid="style.opacity"
132
+ value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
133
+ label={opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}`}
134
+ onValueChange={handleOpacityValueChange}
135
+ steps={tldrawSupportedOpacities.length - 1}
136
+ title={msg('style-panel.opacity')}
137
+ onHistoryMark={onHistoryMark}
138
+ ariaValueModifier={25}
139
+ />
140
+ </>
141
+ )
115
142
  }
116
143
 
117
144
  /** @public @react */
118
- export function CommonStylePickerSet({ styles, theme }: ThemeStylePickerSetProps) {
145
+ export function StylePanelFillPicker() {
146
+ const { styles } = useStylePanelContext()
119
147
  const msg = useTranslation()
120
- const editor = useEditor()
121
-
122
- const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
123
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
148
+ const fill = styles.get(DefaultFillStyle)
149
+ if (fill === undefined) return null
124
150
 
125
- const handleValueChange = useStyleChangeCallback()
151
+ return (
152
+ <StylePanelButtonPicker
153
+ title={msg('style-panel.fill')}
154
+ uiType="fill"
155
+ style={DefaultFillStyle}
156
+ items={STYLES.fill}
157
+ value={fill}
158
+ />
159
+ )
160
+ }
126
161
 
127
- const color = styles.get(DefaultColorStyle)
128
- const fill = styles.get(DefaultFillStyle)
162
+ /** @public @react */
163
+ export function StylePanelDashPicker() {
164
+ const { styles } = useStylePanelContext()
165
+ const msg = useTranslation()
129
166
  const dash = styles.get(DefaultDashStyle)
130
- const size = styles.get(DefaultSizeStyle)
131
-
132
- const showPickers = fill !== undefined || dash !== undefined || size !== undefined
167
+ if (dash === undefined) return null
133
168
 
134
169
  return (
135
- <>
136
- <div className="tlui-style-panel__section__common" data-testid="style.panel">
137
- {color === undefined ? null : (
138
- <>
139
- {showUiLabels && (
140
- <StylePanelSubheading>{msg('style-panel.color')}</StylePanelSubheading>
141
- )}
142
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.color')}>
143
- <TldrawUiButtonPicker
144
- title={msg('style-panel.color')}
145
- uiType="color"
146
- style={DefaultColorStyle}
147
- items={STYLES.color}
148
- value={color}
149
- onValueChange={handleValueChange}
150
- theme={theme}
151
- onHistoryMark={onHistoryMark}
152
- />
153
- </TldrawUiToolbar>
154
- </>
155
- )}
156
- <OpacitySlider />
157
- </div>
158
- {showPickers && (
159
- <div className="tlui-style-panel__section">
160
- {fill === undefined ? null : (
161
- <>
162
- {showUiLabels && (
163
- <StylePanelSubheading>{msg('style-panel.fill')}</StylePanelSubheading>
164
- )}
165
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.fill')}>
166
- <TldrawUiButtonPicker
167
- title={msg('style-panel.fill')}
168
- uiType="fill"
169
- style={DefaultFillStyle}
170
- items={STYLES.fill}
171
- value={fill}
172
- onValueChange={handleValueChange}
173
- theme={theme}
174
- onHistoryMark={onHistoryMark}
175
- />
176
- </TldrawUiToolbar>
177
- </>
178
- )}
179
- {dash === undefined ? null : (
180
- <>
181
- {showUiLabels && (
182
- <StylePanelSubheading>{msg('style-panel.dash')}</StylePanelSubheading>
183
- )}
184
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.dash')}>
185
- <TldrawUiButtonPicker
186
- title={msg('style-panel.dash')}
187
- uiType="dash"
188
- style={DefaultDashStyle}
189
- items={STYLES.dash}
190
- value={dash}
191
- onValueChange={handleValueChange}
192
- theme={theme}
193
- onHistoryMark={onHistoryMark}
194
- />
195
- </TldrawUiToolbar>
196
- </>
197
- )}
198
- {size === undefined ? null : (
199
- <>
200
- {showUiLabels && (
201
- <StylePanelSubheading>{msg('style-panel.size')}</StylePanelSubheading>
202
- )}
203
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.size')}>
204
- <TldrawUiButtonPicker
205
- title={msg('style-panel.size')}
206
- uiType="size"
207
- style={DefaultSizeStyle}
208
- items={STYLES.size}
209
- value={size}
210
- onValueChange={(style, value) => {
211
- handleValueChange(style, value)
212
- const selectedShapeIds = editor.getSelectedShapeIds()
213
- if (selectedShapeIds.length > 0) {
214
- kickoutOccludedShapes(editor, selectedShapeIds)
215
- }
216
- }}
217
- theme={theme}
218
- onHistoryMark={onHistoryMark}
219
- />
220
- </TldrawUiToolbar>
221
- </>
222
- )}
223
- </div>
224
- )}
225
- </>
170
+ <StylePanelButtonPicker
171
+ title={msg('style-panel.dash')}
172
+ uiType="dash"
173
+ style={DefaultDashStyle}
174
+ items={STYLES.dash}
175
+ value={dash}
176
+ />
226
177
  )
227
178
  }
228
179
 
229
180
  /** @public @react */
230
- export function TextStylePickerSet({ theme, styles }: ThemeStylePickerSetProps) {
181
+ export function StylePanelSizePicker() {
182
+ const editor = useEditor()
183
+ const { styles, onValueChange } = useStylePanelContext()
231
184
  const msg = useTranslation()
232
- const handleValueChange = useStyleChangeCallback()
185
+ const size = styles.get(DefaultSizeStyle)
186
+ if (size === undefined) return null
233
187
 
234
- const editor = useEditor()
235
- const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
236
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
237
- const labelStr = showUiLabels && msg('style-panel.font')
188
+ return (
189
+ <StylePanelButtonPicker
190
+ title={msg('style-panel.size')}
191
+ uiType="size"
192
+ style={DefaultSizeStyle}
193
+ items={STYLES.size}
194
+ value={size}
195
+ onValueChange={(style, value) => {
196
+ onValueChange(style, value)
197
+ const selectedShapeIds = editor.getSelectedShapeIds()
198
+ if (selectedShapeIds.length > 0) {
199
+ kickoutOccludedShapes(editor, selectedShapeIds)
200
+ }
201
+ }}
202
+ />
203
+ )
204
+ }
238
205
 
206
+ /** @public @react */
207
+ export function StylePanelFontPicker() {
208
+ const { styles } = useStylePanelContext()
209
+ const msg = useTranslation()
239
210
  const font = styles.get(DefaultFontStyle)
240
- const textAlign = styles.get(DefaultTextAlignStyle)
241
- const labelAlign = styles.get(DefaultHorizontalAlignStyle)
242
- const verticalLabelAlign = styles.get(DefaultVerticalAlignStyle)
243
- if (font === undefined && labelAlign === undefined) {
244
- return null
245
- }
211
+ if (font === undefined) return null
246
212
 
247
213
  return (
248
- <div className="tlui-style-panel__section">
249
- {font === undefined ? null : (
250
- <>
251
- {labelStr && <StylePanelSubheading>{labelStr}</StylePanelSubheading>}
252
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.font')}>
253
- <TldrawUiButtonPicker
254
- title={msg('style-panel.font')}
255
- uiType="font"
256
- style={DefaultFontStyle}
257
- items={STYLES.font}
258
- value={font}
259
- onValueChange={handleValueChange}
260
- theme={theme}
261
- onHistoryMark={onHistoryMark}
262
- />
263
- </TldrawUiToolbar>
264
- </>
265
- )}
266
-
267
- {textAlign === undefined ? null : (
268
- <>
269
- {showUiLabels && <StylePanelSubheading>{msg('style-panel.align')}</StylePanelSubheading>}
270
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.align')}>
271
- <TldrawUiButtonPicker
272
- title={msg('style-panel.align')}
273
- uiType="align"
274
- style={DefaultTextAlignStyle}
275
- items={STYLES.textAlign}
276
- value={textAlign}
277
- onValueChange={handleValueChange}
278
- theme={theme}
279
- onHistoryMark={onHistoryMark}
280
- />
281
- <TldrawUiToolbarButton
282
- type="icon"
283
- title={msg('style-panel.vertical-align')}
284
- data-testid="vertical-align"
285
- disabled
286
- >
287
- <TldrawUiButtonIcon icon="vertical-align-middle" />
288
- </TldrawUiToolbarButton>
289
- </TldrawUiToolbar>
290
- </>
291
- )}
292
-
293
- {labelAlign === undefined ? null : (
294
- <>
295
- {showUiLabels && (
296
- <StylePanelSubheading>{msg('style-panel.label-align')}</StylePanelSubheading>
297
- )}
298
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.label-align')}>
299
- <TldrawUiButtonPicker
300
- title={msg('style-panel.label-align')}
301
- uiType="align"
302
- style={DefaultHorizontalAlignStyle}
303
- items={STYLES.horizontalAlign}
304
- value={labelAlign}
305
- onValueChange={handleValueChange}
306
- theme={theme}
307
- onHistoryMark={onHistoryMark}
308
- />
309
- {verticalLabelAlign === undefined ? (
310
- <TldrawUiToolbarButton
311
- type="icon"
312
- title={msg('style-panel.vertical-align')}
313
- data-testid="vertical-align"
314
- disabled
315
- >
316
- <TldrawUiButtonIcon icon="vertical-align-middle" />
317
- </TldrawUiToolbarButton>
318
- ) : (
319
- <DropdownPicker
320
- type="icon"
321
- id="geo-vertical-alignment"
322
- uiType="verticalAlign"
323
- stylePanelType="vertical-align"
324
- style={DefaultVerticalAlignStyle}
325
- items={STYLES.verticalAlign}
326
- value={verticalLabelAlign}
327
- onValueChange={handleValueChange}
328
- />
329
- )}
330
- </TldrawUiToolbar>
331
- </>
332
- )}
333
- </div>
214
+ <StylePanelButtonPicker
215
+ title={msg('style-panel.font')}
216
+ uiType="font"
217
+ style={DefaultFontStyle}
218
+ items={STYLES.font}
219
+ value={font}
220
+ />
334
221
  )
335
222
  }
223
+
336
224
  /** @public @react */
337
- export function GeoStylePickerSet({ styles }: StylePickerSetProps) {
225
+ export function StylePanelTextAlignPicker() {
226
+ const { styles } = useStylePanelContext()
338
227
  const msg = useTranslation()
339
- const handleValueChange = useStyleChangeCallback()
340
-
341
- const geo = styles.get(GeoShapeGeoStyle)
342
- if (geo === undefined) {
343
- return null
344
- }
228
+ const textAlign = styles.get(DefaultTextAlignStyle)
229
+ if (textAlign === undefined) return null
345
230
 
346
231
  return (
347
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.geo')}>
348
- <DropdownPicker
349
- id="geo"
350
- type="menu"
351
- label={'style-panel.geo'}
352
- uiType="geo"
353
- stylePanelType="geo"
354
- style={GeoShapeGeoStyle}
355
- items={STYLES.geo}
356
- value={geo}
357
- onValueChange={handleValueChange}
232
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.align')}>
233
+ <StylePanelButtonPicker
234
+ title={msg('style-panel.align')}
235
+ uiType="align"
236
+ style={DefaultTextAlignStyle}
237
+ items={STYLES.textAlign}
238
+ value={textAlign}
358
239
  />
240
+ <TldrawUiToolbarButton
241
+ type="icon"
242
+ title={msg('style-panel.vertical-align')}
243
+ data-testid="vertical-align"
244
+ disabled
245
+ >
246
+ <TldrawUiButtonIcon icon="vertical-align-middle" />
247
+ </TldrawUiToolbarButton>
359
248
  </TldrawUiToolbar>
360
249
  )
361
250
  }
251
+
362
252
  /** @public @react */
363
- export function SplineStylePickerSet({ styles }: StylePickerSetProps) {
253
+ export function StylePanelLabelAlignPicker() {
254
+ const { styles } = useStylePanelContext()
364
255
  const msg = useTranslation()
365
- const handleValueChange = useStyleChangeCallback()
366
-
367
- const spline = styles.get(LineShapeSplineStyle)
368
- if (spline === undefined) {
369
- return null
370
- }
256
+ const labelAlign = styles.get(DefaultHorizontalAlignStyle)
257
+ const verticalLabelAlign = styles.get(DefaultVerticalAlignStyle)
258
+ if (labelAlign === undefined) return null
371
259
 
372
260
  return (
373
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.spline')}>
374
- <DropdownPicker
375
- id="spline"
376
- type="menu"
377
- label={'style-panel.spline'}
378
- uiType="spline"
379
- stylePanelType="spline"
380
- style={LineShapeSplineStyle}
381
- items={STYLES.spline}
382
- value={spline}
383
- onValueChange={handleValueChange}
261
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.label-align')}>
262
+ <StylePanelButtonPicker
263
+ title={msg('style-panel.label-align')}
264
+ uiType="align"
265
+ style={DefaultHorizontalAlignStyle}
266
+ items={STYLES.horizontalAlign}
267
+ value={labelAlign}
384
268
  />
269
+ {verticalLabelAlign === undefined ? (
270
+ <TldrawUiToolbarButton
271
+ type="icon"
272
+ title={msg('style-panel.vertical-align')}
273
+ data-testid="vertical-align"
274
+ disabled
275
+ >
276
+ <TldrawUiButtonIcon icon="vertical-align-middle" />
277
+ </TldrawUiToolbarButton>
278
+ ) : (
279
+ <StylePanelDropdownPicker
280
+ type="icon"
281
+ id="geo-vertical-alignment"
282
+ uiType="verticalAlign"
283
+ stylePanelType="vertical-align"
284
+ style={DefaultVerticalAlignStyle}
285
+ items={STYLES.verticalAlign}
286
+ value={verticalLabelAlign}
287
+ />
288
+ )}
385
289
  </TldrawUiToolbar>
386
290
  )
387
291
  }
292
+
388
293
  /** @public @react */
389
- export function ArrowStylePickerSet({ styles }: StylePickerSetProps) {
390
- const msg = useTranslation()
391
- const handleValueChange = useStyleChangeCallback()
294
+ export function StylePanelGeoShapePicker() {
295
+ const { styles } = useStylePanelContext()
296
+ const geo = styles.get(GeoShapeGeoStyle)
297
+ if (geo === undefined) return null
298
+
299
+ return (
300
+ <StylePanelDropdownPicker
301
+ label="style-panel.geo"
302
+ type="menu"
303
+ id="geo"
304
+ uiType="geo"
305
+ stylePanelType="geo"
306
+ style={GeoShapeGeoStyle}
307
+ items={STYLES.geo}
308
+ value={geo}
309
+ />
310
+ )
311
+ }
392
312
 
313
+ /** @public @react */
314
+ export function StylePanelArrowKindPicker() {
315
+ const { styles } = useStylePanelContext()
393
316
  const arrowKind = styles.get(ArrowShapeKindStyle)
394
- if (arrowKind === undefined) {
395
- return null
396
- }
317
+ if (arrowKind === undefined) return null
397
318
 
398
319
  return (
399
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.arrow-kind')}>
400
- <DropdownPicker
401
- id="arrow-kind"
402
- type="menu"
403
- label={'style-panel.arrow-kind'}
404
- uiType="arrow-kind"
405
- stylePanelType="arrow-kind"
406
- style={ArrowShapeKindStyle}
407
- items={STYLES.arrowKind}
408
- value={arrowKind}
409
- onValueChange={handleValueChange}
410
- />
411
- </TldrawUiToolbar>
320
+ <StylePanelDropdownPicker
321
+ id="arrow-kind"
322
+ type="menu"
323
+ label={'style-panel.arrow-kind'}
324
+ uiType="arrow-kind"
325
+ stylePanelType="arrow-kind"
326
+ style={ArrowShapeKindStyle}
327
+ items={STYLES.arrowKind}
328
+ value={arrowKind}
329
+ />
412
330
  )
413
331
  }
414
- /** @public @react */
415
- export function ArrowheadStylePickerSet({ styles }: StylePickerSetProps) {
416
- const handleValueChange = useStyleChangeCallback()
417
332
 
333
+ /** @public @react */
334
+ export function StylePanelArrowheadPicker() {
335
+ const { styles } = useStylePanelContext()
418
336
  const arrowheadEnd = styles.get(ArrowShapeArrowheadEndStyle)
419
337
  const arrowheadStart = styles.get(ArrowShapeArrowheadStartStyle)
420
- if (!arrowheadEnd || !arrowheadStart) {
421
- return null
422
- }
338
+ if (arrowheadEnd === undefined || arrowheadStart === undefined) return null
423
339
 
424
340
  return (
425
- <DoubleDropdownPicker<TLArrowShapeArrowheadStyle>
341
+ <StylePanelDoubleDropdownPicker<TLArrowShapeArrowheadStyle>
426
342
  label={'style-panel.arrowheads'}
427
343
  uiTypeA="arrowheadStart"
428
344
  styleA={ArrowShapeArrowheadStartStyle}
@@ -432,65 +348,28 @@ export function ArrowheadStylePickerSet({ styles }: StylePickerSetProps) {
432
348
  styleB={ArrowShapeArrowheadEndStyle}
433
349
  itemsB={STYLES.arrowheadEnd}
434
350
  valueB={arrowheadEnd}
435
- onValueChange={handleValueChange}
436
351
  labelA="style-panel.arrowhead-start"
437
352
  labelB="style-panel.arrowhead-end"
438
353
  />
439
354
  )
440
355
  }
441
356
 
442
- const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const
443
357
  /** @public @react */
444
- export function OpacitySlider() {
445
- const editor = useEditor()
446
-
447
- const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
448
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
449
-
450
- const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor])
451
- const trackEvent = useUiEvents()
452
- const msg = useTranslation()
453
-
454
- const handleOpacityValueChange = React.useCallback(
455
- (value: number) => {
456
- const item = tldrawSupportedOpacities[value]
457
- editor.run(() => {
458
- if (editor.isIn('select')) {
459
- editor.setOpacityForSelectedShapes(item)
460
- }
461
- editor.setOpacityForNextShapes(item)
462
- editor.updateInstanceState({ isChangingStyle: true })
463
- })
464
-
465
- trackEvent('set-style', { source: 'style-panel', id: 'opacity', value })
466
- },
467
- [editor, trackEvent]
468
- )
469
-
470
- if (opacity === undefined) return null
471
-
472
- const opacityIndex =
473
- opacity.type === 'mixed'
474
- ? -1
475
- : tldrawSupportedOpacities.indexOf(
476
- minBy(tldrawSupportedOpacities, (supportedOpacity) =>
477
- Math.abs(supportedOpacity - opacity.value)
478
- )!
479
- )
358
+ export function StylePanelSplinePicker() {
359
+ const { styles } = useStylePanelContext()
360
+ const spline = styles.get(LineShapeSplineStyle)
361
+ if (spline === undefined) return null
480
362
 
481
363
  return (
482
- <>
483
- {showUiLabels && <StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>}
484
- <TldrawUiSlider
485
- data-testid="style.opacity"
486
- value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
487
- label={opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}`}
488
- onValueChange={handleOpacityValueChange}
489
- steps={tldrawSupportedOpacities.length - 1}
490
- title={msg('style-panel.opacity')}
491
- onHistoryMark={onHistoryMark}
492
- ariaValueModifier={25}
493
- />
494
- </>
364
+ <StylePanelDropdownPicker
365
+ type="menu"
366
+ id="spline"
367
+ uiType="spline"
368
+ stylePanelType="spline"
369
+ label="style-panel.spline"
370
+ style={LineShapeSplineStyle}
371
+ items={STYLES.spline}
372
+ value={spline}
373
+ />
495
374
  )
496
375
  }