tldraw 3.16.0-next.15f085081fd5 → 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 (163) hide show
  1. package/dist-cjs/index.d.ts +134 -102
  2. package/dist-cjs/index.js +25 -14
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  5. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  6. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +3 -0
  7. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  8. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  9. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  10. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
  11. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  12. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  13. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  14. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  15. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  16. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  17. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  18. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  19. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  20. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  21. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  22. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  23. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  24. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +23 -20
  25. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  26. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  27. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  28. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  29. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  30. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  31. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  32. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  33. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  34. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  35. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  36. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
  37. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
  39. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  40. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  41. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  42. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +7 -0
  43. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  44. package/dist-cjs/lib/ui/context/actions.js +7 -8
  45. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  46. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  47. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  48. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  49. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  50. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  51. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  52. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +1 -0
  53. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  54. package/dist-cjs/lib/ui/version.js +3 -3
  55. package/dist-cjs/lib/ui/version.js.map +1 -1
  56. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  57. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  58. package/dist-cjs/lib/utils/export/export.js +0 -20
  59. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  60. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  61. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  62. package/dist-esm/index.d.mts +134 -102
  63. package/dist-esm/index.mjs +51 -28
  64. package/dist-esm/index.mjs.map +2 -2
  65. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  66. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  67. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +3 -0
  68. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  69. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  70. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  71. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
  72. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  73. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  74. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  75. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  76. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  77. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  78. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  79. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  80. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  81. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  82. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  83. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  84. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  85. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +20 -17
  86. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  87. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  88. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  89. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  90. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  91. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  92. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  93. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  94. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  95. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  96. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  97. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
  98. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  99. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
  100. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  101. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  102. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  103. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +7 -0
  104. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  105. package/dist-esm/lib/ui/context/actions.mjs +7 -8
  106. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  107. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  108. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  109. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  110. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  111. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  112. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +1 -0
  113. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  114. package/dist-esm/lib/ui/version.mjs +3 -3
  115. package/dist-esm/lib/ui/version.mjs.map +1 -1
  116. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  117. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  118. package/dist-esm/lib/utils/export/export.mjs +0 -20
  119. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  120. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  121. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  122. package/package.json +3 -3
  123. package/src/index.ts +38 -21
  124. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  125. package/src/lib/shapes/frame/FrameShapeUtil.tsx +4 -0
  126. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  127. package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
  128. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  129. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  130. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  131. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  132. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  133. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  134. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  135. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  136. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  137. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  138. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  139. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  140. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
  141. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
  142. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  143. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +10 -0
  144. package/src/lib/ui/context/actions.tsx +7 -8
  145. package/src/lib/ui/context/events.tsx +1 -1
  146. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  147. package/src/lib/ui/hooks/useTools.tsx +1 -1
  148. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +1 -0
  149. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +1 -0
  150. package/src/lib/ui/version.ts +3 -3
  151. package/src/lib/ui.css +16 -2
  152. package/src/lib/utils/export/copyAs.ts +1 -24
  153. package/src/lib/utils/export/export.ts +0 -36
  154. package/src/lib/utils/export/exportAs.ts +1 -32
  155. package/src/test/custom-clipping.test.ts +436 -0
  156. package/tldraw.css +16 -2
  157. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  158. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  159. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  160. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  161. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  162. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  163. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -1,7 +1,9 @@
1
+ import { tltime } from '@tldraw/editor'
1
2
  import { Slider as _Slider } from 'radix-ui'
2
3
  import React, { useCallback, useEffect, useState } from 'react'
3
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
4
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
+ import { TldrawUiTooltip, tooltipManager } from './TldrawUiTooltip'
5
7
 
6
8
  /** @public */
7
9
  export interface TLUiSliderProps {
@@ -32,6 +34,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
32
34
  ref
33
35
  ) {
34
36
  const msg = useTranslation()
37
+ const [titleAndLabel, setTitleAndLabel] = useState('')
35
38
 
36
39
  // XXX: Radix starts out our slider with a tabIndex of 0
37
40
  // This causes some tab focusing issues, most prevelant in MobileStylePanel,
@@ -49,9 +52,25 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
49
52
  )
50
53
 
51
54
  const handlePointerDown = useCallback(() => {
55
+ tooltipManager.hideAllTooltips()
52
56
  onHistoryMark('click slider')
53
57
  }, [onHistoryMark])
54
58
 
59
+ // N.B. This is a bit silly. The Radix slider auto-focuses which
60
+ // triggers TldrawUiTooltip handleFocus when we dbl-click to edit an image,
61
+ // which in turn makes the tooltip display prematurely.
62
+ // This makes it wait until we've focused to show the tooltip.
63
+ useEffect(() => {
64
+ const timeout = tltime.setTimeout(
65
+ 'set title and label',
66
+ () => {
67
+ setTitleAndLabel(title + ' — ' + msg(label as TLUiTranslationKey))
68
+ },
69
+ 0
70
+ )
71
+ return () => clearTimeout(timeout)
72
+ }, [label, msg, title])
73
+
55
74
  // N.B. Annoying. For a11y purposes, we need Tab to work.
56
75
  // For some reason, Radix has some custom behavior here
57
76
  // that interferes with tabbing past the slider and then
@@ -64,36 +83,37 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
64
83
 
65
84
  return (
66
85
  <div className="tlui-slider__container">
67
- <_Slider.Root
68
- data-testid={testId}
69
- className="tlui-slider"
70
- dir="ltr"
71
- min={min ?? 0}
72
- max={steps}
73
- step={1}
74
- value={value !== null ? [value] : undefined}
75
- onPointerDown={handlePointerDown}
76
- onValueChange={handleValueChange}
77
- onKeyDownCapture={handleKeyEvent}
78
- onKeyUpCapture={handleKeyEvent}
79
- title={title + ' — ' + msg(label as TLUiTranslationKey)}
80
- >
81
- <_Slider.Track className="tlui-slider__track" dir="ltr">
82
- {value !== null && <_Slider.Range className="tlui-slider__range" dir="ltr" />}
83
- </_Slider.Track>
84
- {value !== null && (
85
- <_Slider.Thumb
86
- aria-valuemin={(min ?? 0) * ariaValueModifier}
87
- aria-valuenow={value * ariaValueModifier}
88
- aria-valuemax={steps * ariaValueModifier}
89
- aria-label={title + ' — ' + msg(label as TLUiTranslationKey)}
90
- className="tlui-slider__thumb"
91
- dir="ltr"
92
- ref={ref}
93
- tabIndex={tabIndex}
94
- />
95
- )}
96
- </_Slider.Root>
86
+ <TldrawUiTooltip content={titleAndLabel}>
87
+ <_Slider.Root
88
+ data-testid={testId}
89
+ className="tlui-slider"
90
+ dir="ltr"
91
+ min={min ?? 0}
92
+ max={steps}
93
+ step={1}
94
+ value={value !== null ? [value] : undefined}
95
+ onPointerDown={handlePointerDown}
96
+ onValueChange={handleValueChange}
97
+ onKeyDownCapture={handleKeyEvent}
98
+ onKeyUpCapture={handleKeyEvent}
99
+ >
100
+ <_Slider.Track className="tlui-slider__track" dir="ltr">
101
+ {value !== null && <_Slider.Range className="tlui-slider__range" dir="ltr" />}
102
+ </_Slider.Track>
103
+ {value !== null && (
104
+ <_Slider.Thumb
105
+ aria-valuemin={(min ?? 0) * ariaValueModifier}
106
+ aria-valuenow={value * ariaValueModifier}
107
+ aria-valuemax={steps * ariaValueModifier}
108
+ aria-label={titleAndLabel}
109
+ className="tlui-slider__thumb"
110
+ dir="ltr"
111
+ ref={ref}
112
+ tabIndex={tabIndex}
113
+ />
114
+ )}
115
+ </_Slider.Root>
116
+ </TldrawUiTooltip>
97
117
  </div>
98
118
  )
99
119
  })
@@ -94,6 +94,7 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes<HTMLDi
94
94
  // TODO: fix up this type later
95
95
  defaultValue?: any
96
96
  type: 'single' | 'multiple'
97
+ asChild?: boolean
97
98
  }
98
99
 
99
100
  /** @public @react */
@@ -101,10 +102,12 @@ export const TldrawUiToolbarToggleGroup = ({
101
102
  children,
102
103
  className,
103
104
  type,
105
+ asChild,
104
106
  ...props
105
107
  }: TLUiToolbarToggleGroupProps) => {
106
108
  return (
107
109
  <_Toolbar.ToggleGroup
110
+ asChild={asChild}
108
111
  type={type}
109
112
  {...props}
110
113
  // TODO: this fixes a bug in Radix until they fix it.
@@ -142,6 +142,7 @@ function TooltipSingleton() {
142
142
  const [isOpen, setIsOpen] = useState(false)
143
143
  const triggerRef = useRef<HTMLDivElement>(null)
144
144
  const isFirstShowRef = useRef(true)
145
+ const editor = useMaybeEditor()
145
146
 
146
147
  const currentTooltip = useValue(
147
148
  'current tooltip',
@@ -149,6 +150,15 @@ function TooltipSingleton() {
149
150
  []
150
151
  )
151
152
 
153
+ const cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])
154
+
155
+ // Hide tooltip when camera is moving (panning/zooming)
156
+ useEffect(() => {
157
+ if (cameraState === 'moving' && isOpen && currentTooltip) {
158
+ tooltipManager.hideTooltip(editor, currentTooltip.id, true)
159
+ }
160
+ }, [cameraState, isOpen, currentTooltip, editor])
161
+
152
162
  // Update open state and trigger position
153
163
  useEffect(() => {
154
164
  let timer: ReturnType<typeof setTimeout> | null = null
@@ -225,7 +225,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
225
225
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
226
226
  if (ids.length === 0) return
227
227
  trackEvent('export-as', { format: 'svg', source })
228
- helpers.exportAs(ids, 'svg', getExportName(editor, defaultDocumentName))
228
+ helpers.exportAs(ids, { format: 'svg', name: getExportName(editor, defaultDocumentName) })
229
229
  },
230
230
  },
231
231
  {
@@ -241,7 +241,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
241
241
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
242
242
  if (ids.length === 0) return
243
243
  trackEvent('export-as', { format: 'png', source })
244
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
244
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
245
245
  },
246
246
  },
247
247
  {
@@ -257,11 +257,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
257
257
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
258
258
  if (ids.length === 0) return
259
259
  trackEvent('export-all-as', { format: 'svg', source })
260
- helpers.exportAs(
261
- Array.from(editor.getCurrentPageShapeIds()),
262
- 'svg',
263
- getExportName(editor, defaultDocumentName)
264
- )
260
+ helpers.exportAs(Array.from(editor.getCurrentPageShapeIds()), {
261
+ format: 'svg',
262
+ name: getExportName(editor, defaultDocumentName),
263
+ })
265
264
  },
266
265
  },
267
266
  {
@@ -276,7 +275,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
276
275
  const ids = Array.from(editor.getCurrentPageShapeIds().values())
277
276
  if (ids.length === 0) return
278
277
  trackEvent('export-all-as', { format: 'png', source })
279
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
278
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
280
279
  },
281
280
  },
282
281
  {
@@ -123,7 +123,7 @@ export interface TLUiEventMap {
123
123
  'shrink-shapes': null
124
124
  'flatten-to-image': null
125
125
  'a11y-repeat-shape-announce': null
126
- 'open-url': { url: string }
126
+ 'open-url': { destinationUrl: string }
127
127
  'open-context-menu': null
128
128
  'adjust-shape-styles': null
129
129
  'copy-link': null
@@ -11,12 +11,13 @@ export function useExportAs() {
11
11
  const msg = useTranslation()
12
12
 
13
13
  return useCallback(
14
- (ids: TLShapeId[], format: TLExportType = 'png', name: string | undefined) => {
14
+ (ids: TLShapeId[], opts: { format?: TLExportType; name?: string; scale?: number } = {}) => {
15
15
  assert(editor, 'useExportAs: editor is required')
16
+ const { format = 'png', name, scale = 1 } = opts
16
17
  exportAs(editor, ids, {
17
18
  format,
18
19
  name,
19
- scale: 1,
20
+ scale,
20
21
  }).catch((e) => {
21
22
  console.error(e.message)
22
23
  addToast({
@@ -176,7 +176,7 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
176
176
  editor.createShape({
177
177
  id,
178
178
  type: 'arrow',
179
- props: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },
179
+ props: { start: { x: 0, y: 200 }, end: { x: 200, y: 0 } },
180
180
  }),
181
181
  })
182
182
  trackEvent('drag-tool', { source, id: 'arrow' })
@@ -261,6 +261,7 @@ export type TLUiTranslationKey =
261
261
  | 'tool.aspect-ratio.wide'
262
262
  | 'tool.image-toolbar-title'
263
263
  | 'tool.image-crop'
264
+ | 'tool.image-crop-confirm'
264
265
  | 'tool.media-alt-text'
265
266
  | 'tool.media-alt-text-desc'
266
267
  | 'tool.media-alt-text-confirm'
@@ -262,6 +262,7 @@ export const DEFAULT_TRANSLATION = {
262
262
  'tool.aspect-ratio.wide': 'Wide (16:9)',
263
263
  'tool.image-toolbar-title': 'Image tools',
264
264
  'tool.image-crop': 'Crop image',
265
+ 'tool.image-crop-confirm': 'Confirm',
265
266
  'tool.media-alt-text': 'Alternative text',
266
267
  'tool.media-alt-text-desc': 'Give a description…',
267
268
  'tool.media-alt-text-confirm': 'Confirm',
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.16.0-next.15f085081fd5'
4
+ export const version = '3.16.0-next.2f9d39693e4c'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-08-27T13:43:07.665Z',
8
- patch: '2025-08-27T13:43:07.665Z',
7
+ minor: '2025-09-08T10:59:15.016Z',
8
+ patch: '2025-09-08T10:59:15.016Z',
9
9
  }
package/src/lib/ui.css CHANGED
@@ -1007,9 +1007,23 @@
1007
1007
  flex-direction: column;
1008
1008
  }
1009
1009
 
1010
- .tlui-style-panel__section:nth-of-type(n + 2):not(:last-child) {
1010
+ /*
1011
+ add a border to the bottom of all but the last section. we have to handle empty sections too, which
1012
+ are hidden and shouldn't be counted
1013
+ */
1014
+ .tlui-style-panel__section:not(:nth-last-child(-n + 1 of .tlui-style-panel__section:not(:empty))) {
1011
1015
  border-bottom: 1px solid var(--tl-color-divider);
1012
1016
  }
1017
+ /*
1018
+ if a section ends with a slider and we're adding a border, we need some extra space for visual
1019
+ balance. we need to handle empty sections as above. is this the most complex css selector in all of
1020
+ tldraw? probably.
1021
+ */
1022
+ .tlui-style-panel__section:has(.tlui-slider__container:last-child):not(
1023
+ :nth-last-child(-n + 1 of .tlui-style-panel__section:not(:empty))
1024
+ ) {
1025
+ margin-bottom: 7px;
1026
+ }
1013
1027
 
1014
1028
  .tlui-style-panel__section:empty {
1015
1029
  display: none;
@@ -1021,7 +1035,7 @@
1021
1035
  }
1022
1036
 
1023
1037
  .tlui-style-panel__dropdown-picker:only-child {
1024
- width: 100%;
1038
+ flex: 1;
1025
1039
  }
1026
1040
 
1027
1041
  .tlui-style-panel__double-select-picker {
@@ -31,30 +31,7 @@ export interface CopyAsOptions extends TLImageExportOptions {
31
31
  *
32
32
  * @public
33
33
  */
34
- export function copyAs(editor: Editor, ids: TLShapeId[], opts: CopyAsOptions): Promise<void>
35
- /**
36
- * @deprecated The format parameter is now part of the opts object.
37
- * @public
38
- */
39
- export function copyAs(
40
- editor: Editor,
41
- ids: TLShapeId[],
42
- format: TLCopyType,
43
- opts?: TLImageExportOptions & { format?: undefined }
44
- ): Promise<void>
45
- export function copyAs(
46
- ...args:
47
- | [editor: Editor, ids: TLShapeId[], opts: TLImageExportOptions & { format: TLCopyType }]
48
- | [
49
- editor: Editor,
50
- ids: TLShapeId[],
51
- format: TLCopyType,
52
- opts?: TLImageExportOptions & { format?: undefined },
53
- ]
54
- ) {
55
- const [editor, ids, opts] =
56
- typeof args[2] === 'string' ? [args[0], args[1], { ...args[3], format: args[2] }] : args
57
-
34
+ export function copyAs(editor: Editor, ids: TLShapeId[], opts: CopyAsOptions): Promise<void> {
58
35
  // Note: it's important that this function itself isn't async and doesn't really use promises -
59
36
  // we need to create the relevant `ClipboardItem`s and call navigator.clipboard.write
60
37
  // synchronously to make sure safari knows that the user _wants_ to copy See
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  Editor,
3
3
  FileHelpers,
4
- TLExportType,
5
4
  TLImageExportOptions,
6
5
  TLShapeId,
7
6
  exhaustiveSwitchError,
@@ -35,41 +34,6 @@ export async function exportToString(
35
34
  }
36
35
  }
37
36
 
38
- /**
39
- * Export the given shapes as a blob.
40
- * @param editor - The editor instance.
41
- * @param ids - The ids of the shapes to export.
42
- * @param format - The format to export as.
43
- * @param opts - Rendering options.
44
- * @returns A promise that resolves to a blob.
45
- * @deprecated Use {@link @tldraw/editor#Editor.toImage} instead.
46
- * @public
47
- */
48
- export async function exportToBlob({
49
- editor,
50
- ids,
51
- format,
52
- opts = {},
53
- }: {
54
- editor: Editor
55
- ids: TLShapeId[]
56
- format: TLExportType
57
- opts?: TLImageExportOptions
58
- }): Promise<Blob> {
59
- const idsToUse = ids?.length ? ids : [...editor.getCurrentPageShapeIds()]
60
- switch (format) {
61
- case 'jpeg':
62
- case 'png':
63
- case 'webp':
64
- case 'svg': {
65
- return (await editor.toImage(idsToUse, { ...opts, format })).blob
66
- }
67
- default: {
68
- exhaustiveSwitchError(format)
69
- }
70
- }
71
- }
72
-
73
37
  const clipboardMimeTypesByFormat = {
74
38
  jpeg: 'image/jpeg',
75
39
  png: 'image/png',
@@ -28,38 +28,7 @@ export async function exportAs(
28
28
  editor: Editor,
29
29
  ids: TLShapeId[],
30
30
  opts: ExportAsOptions
31
- ): Promise<void>
32
- /**
33
- * @deprecated The format & name parameters are now part of the opts object.
34
- * @public
35
- */
36
- export async function exportAs(
37
- editor: Editor,
38
- ids: TLShapeId[],
39
- format?: TLExportType,
40
- name?: string,
41
- opts?: TLImageExportOptions
42
- ): Promise<void>
43
- export async function exportAs(
44
- ...args:
45
- | [
46
- editor: Editor,
47
- ids: TLShapeId[],
48
- opts: TLImageExportOptions & { format: TLExportType; name?: string },
49
- ]
50
- | [
51
- editor: Editor,
52
- ids: TLShapeId[],
53
- format?: TLExportType,
54
- name?: string,
55
- opts?: TLImageExportOptions,
56
- ]
57
- ) {
58
- const [editor, ids, opts] =
59
- typeof args[2] === 'object'
60
- ? args
61
- : [args[0], args[1], { ...args[4], format: args[2] ?? 'png', name: args[3] }]
62
-
31
+ ): Promise<void> {
63
32
  // If we don't get name then use a predefined one
64
33
  let name = opts.name
65
34
  if (!name) {