tldraw 3.16.0-canary.4c3f2b4783e6 → 3.16.0-canary.5170ef6b6e20
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.
- package/dist-cjs/index.d.ts +12 -2
- package/dist-cjs/index.js +4 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/Tldraw.js +12 -2
- package/dist-cjs/lib/Tldraw.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +6 -0
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +13 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
- package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +5 -5
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +4 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/context/components.js +2 -0
- package/dist-cjs/lib/ui/context/components.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +9 -3
- package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.d.mts +12 -2
- package/dist-esm/index.mjs +5 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/Tldraw.mjs +14 -4
- package/dist-esm/lib/Tldraw.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -0
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
- package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +5 -5
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +4 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/context/components.mjs +2 -0
- package/dist-esm/lib/ui/context/components.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +1 -1
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
- package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +2 -1
- package/src/lib/Tldraw.tsx +15 -2
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +8 -0
- package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
- package/src/lib/ui/TldrawUi.tsx +16 -10
- package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +5 -5
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
- package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +6 -0
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/context/events.tsx +1 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/test/custom-clipping.test.ts +436 -0
- package/tldraw.css +8 -0
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
package/src/lib/ui/TldrawUi.tsx
CHANGED
|
@@ -3,7 +3,6 @@ import classNames from 'classnames'
|
|
|
3
3
|
import React, { ReactNode, useMemo, useRef, useState } from 'react'
|
|
4
4
|
import { TLUiAssetUrlOverrides } from './assetUrls'
|
|
5
5
|
import { SkipToMainContent } from './components/A11y'
|
|
6
|
-
import { FollowingIndicator } from './components/FollowingIndicator'
|
|
7
6
|
import { TldrawUiButton } from './components/primitives/Button/TldrawUiButton'
|
|
8
7
|
import { TldrawUiButtonIcon } from './components/primitives/Button/TldrawUiButtonIcon'
|
|
9
8
|
import { PORTRAIT_BREAKPOINT, PORTRAIT_BREAKPOINTS } from './constants'
|
|
@@ -108,10 +107,6 @@ const TldrawUiContent = React.memo(function TldrawUI() {
|
|
|
108
107
|
NavigationPanel,
|
|
109
108
|
HelperButtons,
|
|
110
109
|
DebugPanel,
|
|
111
|
-
CursorChatBubble,
|
|
112
|
-
RichTextToolbar,
|
|
113
|
-
ImageToolbar,
|
|
114
|
-
VideoToolbar,
|
|
115
110
|
Toasts,
|
|
116
111
|
Dialogs,
|
|
117
112
|
A11y,
|
|
@@ -223,13 +218,24 @@ const TldrawUiContent = React.memo(function TldrawUI() {
|
|
|
223
218
|
</div>
|
|
224
219
|
</>
|
|
225
220
|
)}
|
|
226
|
-
{RichTextToolbar && <RichTextToolbar />}
|
|
227
|
-
{ImageToolbar && <ImageToolbar />}
|
|
228
|
-
{VideoToolbar && <VideoToolbar />}
|
|
229
221
|
{Toasts && <Toasts />}
|
|
230
222
|
{Dialogs && <Dialogs />}
|
|
231
|
-
<FollowingIndicator />
|
|
232
|
-
{CursorChatBubble && <CursorChatBubble />}
|
|
233
223
|
</div>
|
|
234
224
|
)
|
|
235
225
|
})
|
|
226
|
+
|
|
227
|
+
/** @public @react */
|
|
228
|
+
export function TldrawUiInFrontOfTheCanvas() {
|
|
229
|
+
const { RichTextToolbar, ImageToolbar, VideoToolbar, CursorChatBubble, FollowingIndicator } =
|
|
230
|
+
useTldrawUiComponents()
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<>
|
|
234
|
+
{RichTextToolbar && <RichTextToolbar />}
|
|
235
|
+
{ImageToolbar && <ImageToolbar />}
|
|
236
|
+
{VideoToolbar && <VideoToolbar />}
|
|
237
|
+
{FollowingIndicator && <FollowingIndicator />}
|
|
238
|
+
{CursorChatBubble && <CursorChatBubble />}
|
|
239
|
+
</>
|
|
240
|
+
)
|
|
241
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEditor, usePresence, useValue } from '@tldraw/editor'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/** @public @react */
|
|
4
|
+
export function DefaultFollowingIndicator() {
|
|
4
5
|
const editor = useEditor()
|
|
5
6
|
const followingUserId = useValue('follow', () => editor.getInstanceState().followingUserId, [
|
|
6
7
|
editor,
|
package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx
CHANGED
|
@@ -157,7 +157,7 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
157
157
|
<TldrawUiMenuItem
|
|
158
158
|
id="a11y-select-next-shape-direction"
|
|
159
159
|
label="a11y.select-shape-direction"
|
|
160
|
-
kbd="cmd
|
|
160
|
+
kbd="cmd+[[↑→↓←]]"
|
|
161
161
|
onSelect={() => {
|
|
162
162
|
/* do nothing */
|
|
163
163
|
}}
|
|
@@ -165,7 +165,7 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
165
165
|
<TldrawUiMenuItem
|
|
166
166
|
id="a11y-select-next-shape-container"
|
|
167
167
|
label="a11y.enter-leave-container"
|
|
168
|
-
kbd="cmd+shift
|
|
168
|
+
kbd="cmd+shift+[[↑→]]"
|
|
169
169
|
onSelect={() => {
|
|
170
170
|
/* do nothing */
|
|
171
171
|
}}
|
|
@@ -173,7 +173,7 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
173
173
|
<TldrawUiMenuItem
|
|
174
174
|
id="a11y-pan-camera"
|
|
175
175
|
label="a11y.pan-camera"
|
|
176
|
-
kbd="[[Space]]
|
|
176
|
+
kbd="[[Space]]+[[↑→↓←]]"
|
|
177
177
|
onSelect={() => {
|
|
178
178
|
/* do nothing */
|
|
179
179
|
}}
|
|
@@ -197,7 +197,7 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
197
197
|
<TldrawUiMenuItem
|
|
198
198
|
id="a11y-move-shape"
|
|
199
199
|
label="a11y.move-shape"
|
|
200
|
-
kbd="↑→↓←"
|
|
200
|
+
kbd="[[↑→↓←]]"
|
|
201
201
|
onSelect={() => {
|
|
202
202
|
/* do nothing */
|
|
203
203
|
}}
|
|
@@ -205,7 +205,7 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
205
205
|
<TldrawUiMenuItem
|
|
206
206
|
id="a11y-move-shape-faster"
|
|
207
207
|
label="a11y.move-shape-faster"
|
|
208
|
-
kbd="shift
|
|
208
|
+
kbd="shift+[[↑→↓←]]"
|
|
209
209
|
onSelect={() => {
|
|
210
210
|
/* do nothing */
|
|
211
211
|
}}
|
|
@@ -2,9 +2,9 @@ import { preventDefault, TLShape, TLShapeId, useEditor } from '@tldraw/editor'
|
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
3
|
import { useUiEvents } from '../../context/events'
|
|
4
4
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
5
|
-
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
6
5
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
7
6
|
import { TldrawUiInput } from '../primitives/TldrawUiInput'
|
|
7
|
+
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
10
|
export interface AltTextEditorProps {
|
|
@@ -76,14 +76,15 @@ export function AltTextEditor({ shapeId, onClose, source }: AltTextEditorProps)
|
|
|
76
76
|
disabled={isReadonly}
|
|
77
77
|
/>
|
|
78
78
|
{!isReadonly && (
|
|
79
|
-
<
|
|
79
|
+
<TldrawUiToolbarButton
|
|
80
80
|
title={msg('tool.media-alt-text-confirm')}
|
|
81
|
+
data-testid="tool.media-alt-text-confirm"
|
|
81
82
|
type="icon"
|
|
82
83
|
onPointerDown={preventDefault}
|
|
83
84
|
onClick={handleConfirm}
|
|
84
85
|
>
|
|
85
86
|
<TldrawUiButtonIcon small icon="check" />
|
|
86
|
-
</
|
|
87
|
+
</TldrawUiToolbarButton>
|
|
87
88
|
)}
|
|
88
89
|
</>
|
|
89
90
|
)
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
import { useActions } from '../../context/actions'
|
|
23
23
|
import { useUiEvents } from '../../context/events'
|
|
24
24
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
25
|
-
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
26
25
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
27
26
|
import { TldrawUiButtonLabel } from '../primitives/Button/TldrawUiButtonLabel'
|
|
28
27
|
import {
|
|
@@ -32,6 +31,7 @@ import {
|
|
|
32
31
|
TldrawUiDropdownMenuTrigger,
|
|
33
32
|
} from '../primitives/TldrawUiDropdownMenu'
|
|
34
33
|
import { TldrawUiSlider } from '../primitives/TldrawUiSlider'
|
|
34
|
+
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
35
35
|
|
|
36
36
|
/** @public */
|
|
37
37
|
export interface DefaultImageToolbarContentProps {
|
|
@@ -226,9 +226,13 @@ export const DefaultImageToolbarContent = track(function DefaultImageToolbarCont
|
|
|
226
226
|
/>
|
|
227
227
|
<TldrawUiDropdownMenuRoot id="image-toolbar-aspect-ratio">
|
|
228
228
|
<TldrawUiDropdownMenuTrigger>
|
|
229
|
-
<
|
|
229
|
+
<TldrawUiToolbarButton
|
|
230
|
+
title={msg('tool.aspect-ratio')}
|
|
231
|
+
type="icon"
|
|
232
|
+
data-testid="tool.image-aspect-ratio"
|
|
233
|
+
>
|
|
230
234
|
<TldrawUiButtonIcon icon="corners" />
|
|
231
|
-
</
|
|
235
|
+
</TldrawUiToolbarButton>
|
|
232
236
|
</TldrawUiDropdownMenuTrigger>
|
|
233
237
|
<TldrawUiDropdownMenuContent side="top" align="center">
|
|
234
238
|
{ASPECT_RATIO_OPTIONS.map((aspectRatio) => {
|
|
@@ -268,14 +272,15 @@ export const DefaultImageToolbarContent = track(function DefaultImageToolbarCont
|
|
|
268
272
|
})}
|
|
269
273
|
</TldrawUiDropdownMenuContent>
|
|
270
274
|
</TldrawUiDropdownMenuRoot>
|
|
271
|
-
<
|
|
275
|
+
<TldrawUiToolbarButton
|
|
272
276
|
type="icon"
|
|
273
277
|
onClick={onManipulatingEnd}
|
|
274
|
-
data-testid="tool.image-confirm"
|
|
278
|
+
data-testid="tool.image-crop-confirm"
|
|
275
279
|
style={{ borderLeft: '1px solid var(--tl-color-divider)', marginLeft: '2px' }}
|
|
280
|
+
title={msg('tool.image-crop-confirm')}
|
|
276
281
|
>
|
|
277
282
|
<TldrawUiButtonIcon small icon="check" />
|
|
278
|
-
</
|
|
283
|
+
</TldrawUiToolbarButton>
|
|
279
284
|
</>
|
|
280
285
|
)
|
|
281
286
|
}
|
|
@@ -283,33 +288,45 @@ export const DefaultImageToolbarContent = track(function DefaultImageToolbarCont
|
|
|
283
288
|
return (
|
|
284
289
|
<>
|
|
285
290
|
{!isReadonly && (
|
|
286
|
-
<
|
|
291
|
+
<TldrawUiToolbarButton
|
|
292
|
+
type="icon"
|
|
293
|
+
data-testid="tool.image-replace"
|
|
294
|
+
onClick={handleImageReplace}
|
|
295
|
+
title={msg('tool.replace-media')}
|
|
296
|
+
>
|
|
287
297
|
<TldrawUiButtonIcon small icon="tool-media" />
|
|
288
|
-
</
|
|
298
|
+
</TldrawUiToolbarButton>
|
|
289
299
|
)}
|
|
290
300
|
{!isReadonly && (
|
|
291
|
-
<
|
|
301
|
+
<TldrawUiToolbarButton
|
|
302
|
+
type="icon"
|
|
303
|
+
title={msg('tool.image-crop')}
|
|
304
|
+
onClick={onManipulatingStart}
|
|
305
|
+
data-testid="tool.image-crop"
|
|
306
|
+
>
|
|
292
307
|
<TldrawUiButtonIcon small icon="crop" />
|
|
293
|
-
</
|
|
308
|
+
</TldrawUiToolbarButton>
|
|
294
309
|
)}
|
|
295
|
-
<
|
|
310
|
+
<TldrawUiToolbarButton
|
|
296
311
|
type="icon"
|
|
297
312
|
title={msg('action.download-original')}
|
|
298
313
|
onClick={handleImageDownload}
|
|
314
|
+
data-testid="tool.image-download"
|
|
299
315
|
>
|
|
300
316
|
<TldrawUiButtonIcon small icon="download" />
|
|
301
|
-
</
|
|
317
|
+
</TldrawUiToolbarButton>
|
|
302
318
|
{(altText || !isReadonly) && (
|
|
303
|
-
<
|
|
304
|
-
type="
|
|
319
|
+
<TldrawUiToolbarButton
|
|
320
|
+
type="icon"
|
|
305
321
|
title={msg('tool.media-alt-text')}
|
|
322
|
+
data-testid="tool.image-alt-text"
|
|
306
323
|
onClick={() => {
|
|
307
324
|
trackEvent('alt-text-start', { source })
|
|
308
325
|
onEditAltTextStart()
|
|
309
326
|
}}
|
|
310
327
|
>
|
|
311
328
|
<TldrawUiButtonIcon small icon="alt" />
|
|
312
|
-
</
|
|
329
|
+
</TldrawUiToolbarButton>
|
|
313
330
|
)}
|
|
314
331
|
</>
|
|
315
332
|
)
|
|
@@ -5,6 +5,7 @@ import { useUiEvents } from '../../context/events'
|
|
|
5
5
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
6
6
|
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
7
7
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
8
|
+
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
8
9
|
|
|
9
10
|
/** @public */
|
|
10
11
|
export interface DefaultVideoToolbarContentProps {
|
|
@@ -44,7 +45,12 @@ export const DefaultVideoToolbarContent = track(function DefaultVideoToolbarCont
|
|
|
44
45
|
return (
|
|
45
46
|
<>
|
|
46
47
|
{!isReadonly && (
|
|
47
|
-
<TldrawUiButton
|
|
48
|
+
<TldrawUiButton
|
|
49
|
+
type="icon"
|
|
50
|
+
title={msg('tool.replace-media')}
|
|
51
|
+
onClick={handleVideoReplace}
|
|
52
|
+
data-testid="tool.video-replace"
|
|
53
|
+
>
|
|
48
54
|
<TldrawUiButtonIcon small icon="tool-media" />
|
|
49
55
|
</TldrawUiButton>
|
|
50
56
|
)}
|
|
@@ -52,21 +58,23 @@ export const DefaultVideoToolbarContent = track(function DefaultVideoToolbarCont
|
|
|
52
58
|
type="icon"
|
|
53
59
|
title={msg('action.download-original')}
|
|
54
60
|
onClick={handleVideoDownload}
|
|
61
|
+
data-testid="tool.video-download"
|
|
55
62
|
>
|
|
56
63
|
<TldrawUiButtonIcon small icon="download" />
|
|
57
64
|
</TldrawUiButton>
|
|
58
65
|
{(altText || !isReadonly) && (
|
|
59
|
-
<
|
|
60
|
-
type="
|
|
66
|
+
<TldrawUiToolbarButton
|
|
67
|
+
type="icon"
|
|
61
68
|
isActive={!!altText}
|
|
62
69
|
title={msg('tool.media-alt-text')}
|
|
70
|
+
data-testid="tool.video-alt-text"
|
|
63
71
|
onClick={() => {
|
|
64
72
|
trackEvent('alt-text-start', { source })
|
|
65
73
|
onEditAltTextStart()
|
|
66
74
|
}}
|
|
67
75
|
>
|
|
68
76
|
<TldrawUiButtonIcon small icon="alt" />
|
|
69
|
-
</
|
|
77
|
+
</TldrawUiToolbarButton>
|
|
70
78
|
)}
|
|
71
79
|
</>
|
|
72
80
|
)
|
|
@@ -2,9 +2,9 @@ import { preventDefault, TiptapEditor, useEditor } from '@tldraw/editor'
|
|
|
2
2
|
import { useEffect, useRef, useState } from 'react'
|
|
3
3
|
import { useUiEvents } from '../../context/events'
|
|
4
4
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
5
|
-
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
6
5
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
7
6
|
import { TldrawUiInput } from '../primitives/TldrawUiInput'
|
|
7
|
+
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
10
|
export interface LinkEditorProps {
|
|
@@ -76,7 +76,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
76
76
|
onCancel={handleLinkCancel}
|
|
77
77
|
placeholder="example.com"
|
|
78
78
|
/>
|
|
79
|
-
<
|
|
79
|
+
<TldrawUiToolbarButton
|
|
80
80
|
className="tlui-rich-text__toolbar-link-visit"
|
|
81
81
|
title={msg('tool.rich-text-link-visit')}
|
|
82
82
|
type="icon"
|
|
@@ -85,8 +85,8 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
85
85
|
disabled={!value}
|
|
86
86
|
>
|
|
87
87
|
<TldrawUiButtonIcon small icon="external-link" />
|
|
88
|
-
</
|
|
89
|
-
<
|
|
88
|
+
</TldrawUiToolbarButton>
|
|
89
|
+
<TldrawUiToolbarButton
|
|
90
90
|
className="tlui-rich-text__toolbar-link-remove"
|
|
91
91
|
title={msg('tool.rich-text-link-remove')}
|
|
92
92
|
data-testid="rich-text.link-remove"
|
|
@@ -95,7 +95,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
95
95
|
onClick={handleRemoveLink}
|
|
96
96
|
>
|
|
97
97
|
<TldrawUiButtonIcon small icon="trash" />
|
|
98
|
-
</
|
|
98
|
+
</TldrawUiToolbarButton>
|
|
99
99
|
</>
|
|
100
100
|
)
|
|
101
101
|
}
|
|
@@ -172,7 +172,12 @@ export const TldrawUiContextualToolbar = ({
|
|
|
172
172
|
className={classNames('tlui-contextual-toolbar', className)}
|
|
173
173
|
onPointerDown={stopEventPropagation}
|
|
174
174
|
>
|
|
175
|
-
<TldrawUiToolbar
|
|
175
|
+
<TldrawUiToolbar
|
|
176
|
+
orientation="horizontal"
|
|
177
|
+
className="tlui-menu"
|
|
178
|
+
label={label}
|
|
179
|
+
tooltipSide="top"
|
|
180
|
+
>
|
|
176
181
|
{children}
|
|
177
182
|
</TldrawUiToolbar>
|
|
178
183
|
</div>
|
|
@@ -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
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
})
|
|
@@ -235,6 +235,8 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
235
235
|
const orientationCtx = useTldrawUiOrientation()
|
|
236
236
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
237
237
|
|
|
238
|
+
const camera = useValue('camera', () => editor?.getCamera(), [])
|
|
239
|
+
|
|
238
240
|
useEffect(() => {
|
|
239
241
|
const currentTooltipId = tooltipId.current
|
|
240
242
|
return () => {
|
|
@@ -244,6 +246,10 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
244
246
|
}
|
|
245
247
|
}, [editor, hasProvider])
|
|
246
248
|
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
tooltipManager.hideTooltip(editor, tooltipId.current, true)
|
|
251
|
+
}, [editor, camera])
|
|
252
|
+
|
|
247
253
|
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
248
254
|
if (disabled || !content) {
|
|
249
255
|
return <>{children}</>
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { CursorChatBubble } from '../components/CursorChatBubble'
|
|
13
13
|
import { DefaultDebugMenu } from '../components/DebugMenu/DefaultDebugMenu'
|
|
14
14
|
import { DefaultDebugPanel } from '../components/DefaultDebugPanel'
|
|
15
|
+
import { DefaultFollowingIndicator } from '../components/DefaultFollowingIndicator'
|
|
15
16
|
import { DefaultMenuPanel } from '../components/DefaultMenuPanel'
|
|
16
17
|
import { DefaultDialogs } from '../components/Dialogs'
|
|
17
18
|
import { TLUiHelpMenuProps } from '../components/HelpMenu/DefaultHelpMenu'
|
|
@@ -72,6 +73,7 @@ export interface TLUiComponents {
|
|
|
72
73
|
Dialogs?: ComponentType | null
|
|
73
74
|
Toasts?: ComponentType | null
|
|
74
75
|
A11y?: ComponentType | null
|
|
76
|
+
FollowingIndicator?: ComponentType | null
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
const TldrawUiComponentsContext = createContext<TLUiComponents | null>(null)
|
|
@@ -119,6 +121,7 @@ export function TldrawUiComponentsProvider({
|
|
|
119
121
|
Dialogs: DefaultDialogs,
|
|
120
122
|
Toasts: DefaultToasts,
|
|
121
123
|
A11y: DefaultA11yAnnouncer,
|
|
124
|
+
FollowingIndicator: DefaultFollowingIndicator,
|
|
122
125
|
..._overrides,
|
|
123
126
|
}),
|
|
124
127
|
[_overrides, showCollaborationUi]
|
|
@@ -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': {
|
|
126
|
+
'open-url': { destinationUrl: string }
|
|
127
127
|
'open-context-menu': null
|
|
128
128
|
'adjust-shape-styles': null
|
|
129
129
|
'copy-link': null
|
|
@@ -186,6 +186,7 @@ export type TLUiTranslationKey =
|
|
|
186
186
|
| 'geo-style.pentagon'
|
|
187
187
|
| 'geo-style.rectangle'
|
|
188
188
|
| 'geo-style.rhombus'
|
|
189
|
+
| 'geo-style.rhombus-2'
|
|
189
190
|
| 'geo-style.star'
|
|
190
191
|
| 'geo-style.trapezoid'
|
|
191
192
|
| 'geo-style.triangle'
|
|
@@ -260,6 +261,7 @@ export type TLUiTranslationKey =
|
|
|
260
261
|
| 'tool.aspect-ratio.wide'
|
|
261
262
|
| 'tool.image-toolbar-title'
|
|
262
263
|
| 'tool.image-crop'
|
|
264
|
+
| 'tool.image-crop-confirm'
|
|
263
265
|
| 'tool.media-alt-text'
|
|
264
266
|
| 'tool.media-alt-text-desc'
|
|
265
267
|
| 'tool.media-alt-text-confirm'
|
|
@@ -187,6 +187,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
187
187
|
'geo-style.pentagon': 'Pentagon',
|
|
188
188
|
'geo-style.rectangle': 'Rectangle',
|
|
189
189
|
'geo-style.rhombus': 'Rhombus',
|
|
190
|
+
'geo-style.rhombus-2': 'Rhombus left',
|
|
190
191
|
'geo-style.star': 'Star',
|
|
191
192
|
'geo-style.trapezoid': 'Trapezoid',
|
|
192
193
|
'geo-style.triangle': 'Triangle',
|
|
@@ -261,6 +262,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
261
262
|
'tool.aspect-ratio.wide': 'Wide (16:9)',
|
|
262
263
|
'tool.image-toolbar-title': 'Image tools',
|
|
263
264
|
'tool.image-crop': 'Crop image',
|
|
265
|
+
'tool.image-crop-confirm': 'Confirm',
|
|
264
266
|
'tool.media-alt-text': 'Alternative text',
|
|
265
267
|
'tool.media-alt-text-desc': 'Give a description…',
|
|
266
268
|
'tool.media-alt-text-confirm': 'Confirm',
|
package/src/lib/ui/kbd-utils.ts
CHANGED
|
@@ -31,9 +31,16 @@ export function kbd(str: string) {
|
|
|
31
31
|
)
|
|
32
32
|
.flat()
|
|
33
33
|
.map((sub, index) => {
|
|
34
|
-
if (sub === '
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (sub[0] === '+') return []
|
|
35
|
+
|
|
36
|
+
let modifiedKey
|
|
37
|
+
if (sub === '__CTRL__') {
|
|
38
|
+
modifiedKey = 'Ctrl'
|
|
39
|
+
} else if (sub === '__ALT__') {
|
|
40
|
+
modifiedKey = 'Alt'
|
|
41
|
+
} else {
|
|
42
|
+
modifiedKey = sub[0].toUpperCase() + sub.slice(1)
|
|
43
|
+
}
|
|
37
44
|
return tlenv.isDarwin || !index ? modifiedKey : ['+', modifiedKey]
|
|
38
45
|
})
|
|
39
46
|
.flat()
|
package/src/lib/ui/version.ts
CHANGED
|
@@ -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-canary.
|
|
4
|
+
export const version = '3.16.0-canary.5170ef6b6e20'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-08-
|
|
8
|
-
patch: '2025-08-
|
|
7
|
+
minor: '2025-08-29T13:37:30.941Z',
|
|
8
|
+
patch: '2025-08-29T13:37:30.941Z',
|
|
9
9
|
}
|