tldraw 3.16.0-canary.5dac57cf9465 → 3.16.0-canary.614a556981b7
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 +74 -4
- package/dist-cjs/index.js +5 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -12
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +5 -5
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +14 -0
- package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +10 -2
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -22
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +188 -78
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +15 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +106 -82
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/layout.js +30 -5
- package/dist-cjs/lib/ui/components/primitives/layout.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +30 -7
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +152 -1
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +76 -9
- package/dist-cjs/lib/ui/hooks/useTools.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 +74 -4
- package/dist-esm/index.mjs +10 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +6 -5
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
- package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +10 -2
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -22
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -80
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +2 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +16 -4
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +108 -84
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/layout.mjs +31 -6
- package/dist-esm/lib/ui/components/primitives/layout.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +30 -7
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +160 -3
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +83 -10
- package/dist-esm/lib/ui/hooks/useTools.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 +7 -0
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +13 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
- package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
- package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
- package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
- package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
- package/src/lib/shapes/shared/ShapeFill.tsx +6 -5
- package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
- package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
- package/src/lib/tools/SelectTool/childStates/Translating.ts +0 -1
- package/src/lib/ui/TldrawUi.tsx +17 -2
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +13 -2
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -24
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +208 -56
- package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +3 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +22 -5
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +112 -82
- package/src/lib/ui/components/primitives/layout.tsx +79 -5
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +30 -7
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +218 -2
- package/src/lib/ui/context/events.tsx +1 -0
- package/src/lib/ui/hooks/useTools.tsx +118 -10
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +342 -238
- package/tldraw.css +635 -528
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Editor, uniqueId, useMaybeEditor, Vec } from '@tldraw/editor'
|
|
1
|
+
import { assert, Editor, uniqueId, useMaybeEditor, Vec } from '@tldraw/editor'
|
|
2
2
|
import { Tooltip as _Tooltip } from 'radix-ui'
|
|
3
|
-
import React, { createContext, useContext, useEffect, useRef, useState } from 'react'
|
|
3
|
+
import React, { createContext, forwardRef, useContext, useEffect, useRef, useState } from 'react'
|
|
4
4
|
import { usePrefersReducedMotion } from '../../../shapes/shared/usePrefersReducedMotion'
|
|
5
|
+
import { useTldrawUiOrientation } from './layout'
|
|
5
6
|
|
|
6
7
|
const DEFAULT_TOOLTIP_DELAY_MS = 700
|
|
7
8
|
|
|
@@ -69,20 +70,32 @@ class TooltipManager {
|
|
|
69
70
|
this.notify()
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
hideTooltip(tooltipId: string) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.destroyTimeoutId = null
|
|
82
|
-
this.notify()
|
|
83
|
-
}, 300)
|
|
73
|
+
hideTooltip(tooltipId: string, instant: boolean = false) {
|
|
74
|
+
const hide = () => {
|
|
75
|
+
// Only hide if this is the current tooltip
|
|
76
|
+
if (this.currentTooltipId === tooltipId) {
|
|
77
|
+
this.currentTooltipId = null
|
|
78
|
+
this.currentContent = ''
|
|
79
|
+
this.activeElement = null
|
|
80
|
+
this.destroyTimeoutId = null
|
|
81
|
+
this.notify()
|
|
84
82
|
}
|
|
85
83
|
}
|
|
84
|
+
|
|
85
|
+
if (instant) {
|
|
86
|
+
hide()
|
|
87
|
+
} else if (this.editor) {
|
|
88
|
+
// Start destroy timeout (1 second)
|
|
89
|
+
this.destroyTimeoutId = this.editor.timers.setTimeout(hide, 300)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
hideAllTooltips() {
|
|
94
|
+
this.currentTooltipId = null
|
|
95
|
+
this.currentContent = ''
|
|
96
|
+
this.activeElement = null
|
|
97
|
+
this.destroyTimeoutId = null
|
|
98
|
+
this.notify()
|
|
86
99
|
}
|
|
87
100
|
|
|
88
101
|
getCurrentTooltipData() {
|
|
@@ -96,7 +109,7 @@ class TooltipManager {
|
|
|
96
109
|
}
|
|
97
110
|
}
|
|
98
111
|
|
|
99
|
-
const tooltipManager = TooltipManager.getInstance()
|
|
112
|
+
export const tooltipManager = TooltipManager.getInstance()
|
|
100
113
|
|
|
101
114
|
// Context for the tooltip singleton
|
|
102
115
|
const TooltipSingletonContext = createContext<boolean>(false)
|
|
@@ -235,79 +248,96 @@ function TooltipSingleton() {
|
|
|
235
248
|
}
|
|
236
249
|
|
|
237
250
|
/** @public @react */
|
|
238
|
-
export
|
|
239
|
-
children,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
|
|
252
|
+
({ children, content, side, sideOffset = 5, disabled = false }, ref) => {
|
|
253
|
+
const editor = useMaybeEditor()
|
|
254
|
+
const tooltipId = useRef<string>(uniqueId())
|
|
255
|
+
const hasProvider = useContext(TooltipSingletonContext)
|
|
256
|
+
|
|
257
|
+
const orientationCtx = useTldrawUiOrientation()
|
|
258
|
+
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
259
|
+
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
const currentTooltipId = tooltipId.current
|
|
262
|
+
return () => {
|
|
263
|
+
if (hasProvider) {
|
|
264
|
+
tooltipManager.hideTooltip(currentTooltipId, true)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}, [hasProvider])
|
|
248
268
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
269
|
+
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
270
|
+
if (disabled || !content) {
|
|
271
|
+
return <>{children}</>
|
|
272
|
+
}
|
|
253
273
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
>
|
|
261
|
-
<_Tooltip.Trigger asChild>{children}</_Tooltip.Trigger>
|
|
262
|
-
<_Tooltip.Content
|
|
263
|
-
className="tlui-tooltip"
|
|
264
|
-
side={side}
|
|
265
|
-
sideOffset={sideOffset}
|
|
266
|
-
avoidCollisions
|
|
267
|
-
collisionPadding={8}
|
|
268
|
-
dir="ltr"
|
|
274
|
+
// Fallback to old behavior if no provider
|
|
275
|
+
if (!hasProvider) {
|
|
276
|
+
return (
|
|
277
|
+
<_Tooltip.Root
|
|
278
|
+
delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
|
|
279
|
+
disableHoverableContent
|
|
269
280
|
>
|
|
270
|
-
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
281
|
+
<_Tooltip.Trigger asChild ref={ref}>
|
|
282
|
+
{children}
|
|
283
|
+
</_Tooltip.Trigger>
|
|
284
|
+
<_Tooltip.Content
|
|
285
|
+
className="tlui-tooltip"
|
|
286
|
+
side={sideToUse}
|
|
287
|
+
sideOffset={sideOffset}
|
|
288
|
+
avoidCollisions
|
|
289
|
+
collisionPadding={8}
|
|
290
|
+
dir="ltr"
|
|
291
|
+
>
|
|
292
|
+
{content}
|
|
293
|
+
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
294
|
+
</_Tooltip.Content>
|
|
295
|
+
</_Tooltip.Root>
|
|
296
|
+
)
|
|
297
|
+
}
|
|
276
298
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
event
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
299
|
+
const child = React.Children.only(children)
|
|
300
|
+
assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
|
|
301
|
+
|
|
302
|
+
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
|
|
303
|
+
child.props.onMouseEnter?.(event)
|
|
304
|
+
tooltipManager.showTooltip(
|
|
305
|
+
tooltipId.current,
|
|
306
|
+
content,
|
|
307
|
+
event.currentTarget as HTMLElement,
|
|
308
|
+
sideToUse,
|
|
309
|
+
sideOffset
|
|
310
|
+
)
|
|
311
|
+
}
|
|
286
312
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
313
|
+
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
|
314
|
+
child.props.onMouseLeave?.(event)
|
|
315
|
+
tooltipManager.hideTooltip(tooltipId.current)
|
|
316
|
+
}
|
|
290
317
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
318
|
+
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
|
319
|
+
child.props.onFocus?.(event)
|
|
320
|
+
tooltipManager.showTooltip(
|
|
321
|
+
tooltipId.current,
|
|
322
|
+
content,
|
|
323
|
+
event.currentTarget as HTMLElement,
|
|
324
|
+
sideToUse,
|
|
325
|
+
sideOffset
|
|
326
|
+
)
|
|
327
|
+
}
|
|
300
328
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
329
|
+
const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
|
|
330
|
+
child.props.onBlur?.(event)
|
|
331
|
+
tooltipManager.hideTooltip(tooltipId.current)
|
|
332
|
+
}
|
|
304
333
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
334
|
+
const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
|
|
335
|
+
onMouseEnter: handleMouseEnter,
|
|
336
|
+
onMouseLeave: handleMouseLeave,
|
|
337
|
+
onFocus: handleFocus,
|
|
338
|
+
onBlur: handleBlur,
|
|
339
|
+
})
|
|
311
340
|
|
|
312
|
-
|
|
313
|
-
}
|
|
341
|
+
return childrenWithHandlers
|
|
342
|
+
}
|
|
343
|
+
)
|
|
@@ -1,10 +1,60 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import { Slot } from 'radix-ui'
|
|
3
|
-
import { HTMLAttributes, ReactNode, forwardRef } from 'react'
|
|
3
|
+
import { HTMLAttributes, ReactNode, createContext, forwardRef, useContext } from 'react'
|
|
4
|
+
|
|
5
|
+
/** @public */
|
|
6
|
+
export interface TldrawUiOrientationContext {
|
|
7
|
+
orientation: 'horizontal' | 'vertical'
|
|
8
|
+
tooltipSide: 'top' | 'right' | 'bottom' | 'left'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const TldrawUiOrientationContext = createContext<TldrawUiOrientationContext>({
|
|
12
|
+
orientation: 'horizontal',
|
|
13
|
+
tooltipSide: 'bottom',
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
/** @public */
|
|
17
|
+
export interface TldrawUiOrientationProviderProps {
|
|
18
|
+
children: ReactNode
|
|
19
|
+
orientation: 'horizontal' | 'vertical'
|
|
20
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
21
|
+
}
|
|
22
|
+
/** @public @react */
|
|
23
|
+
export function TldrawUiOrientationProvider({
|
|
24
|
+
children,
|
|
25
|
+
orientation,
|
|
26
|
+
tooltipSide,
|
|
27
|
+
}: TldrawUiOrientationProviderProps) {
|
|
28
|
+
const prevContext = useTldrawUiOrientation()
|
|
29
|
+
// generally, we want tooltip side to cascade down through the layout - apart from when the
|
|
30
|
+
// orientation changes. If the tooltip side is "bottom", and then I include some vertical layout
|
|
31
|
+
// elements, keeping the tooltip side as bottom will cause the tooltip to overlap elements
|
|
32
|
+
// stacked on top of each other. In the absence of a tooltip side, we pick a default side based
|
|
33
|
+
// on the orientation whenever the orientation changes.
|
|
34
|
+
const tooltipSideToUse =
|
|
35
|
+
tooltipSide ??
|
|
36
|
+
(orientation === prevContext.orientation
|
|
37
|
+
? prevContext.tooltipSide
|
|
38
|
+
: orientation === 'horizontal'
|
|
39
|
+
? 'bottom'
|
|
40
|
+
: 'right')
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<TldrawUiOrientationContext.Provider value={{ orientation, tooltipSide: tooltipSideToUse }}>
|
|
44
|
+
{children}
|
|
45
|
+
</TldrawUiOrientationContext.Provider>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @public */
|
|
50
|
+
export function useTldrawUiOrientation() {
|
|
51
|
+
return useContext(TldrawUiOrientationContext)
|
|
52
|
+
}
|
|
4
53
|
|
|
5
54
|
/** @public */
|
|
6
55
|
export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
7
56
|
children: ReactNode
|
|
57
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
8
58
|
asChild?: boolean
|
|
9
59
|
}
|
|
10
60
|
|
|
@@ -14,9 +64,29 @@ export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
14
64
|
* @public @react
|
|
15
65
|
*/
|
|
16
66
|
export const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
17
|
-
({ asChild, className, ...props }, ref) => {
|
|
67
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
68
|
+
const Component = asChild ? Slot.Root : 'div'
|
|
69
|
+
return (
|
|
70
|
+
<TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
|
|
71
|
+
<Component ref={ref} className={classNames('tlui-row', className)} {...props} />
|
|
72
|
+
</TldrawUiOrientationProvider>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A column, usually of UI controls like buttons, select dropdown, checkboxes, etc.
|
|
79
|
+
*
|
|
80
|
+
* @public @react
|
|
81
|
+
*/
|
|
82
|
+
export const TldrawUiColumn = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
83
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
18
84
|
const Component = asChild ? Slot.Root : 'div'
|
|
19
|
-
return
|
|
85
|
+
return (
|
|
86
|
+
<TldrawUiOrientationProvider orientation="vertical" tooltipSide={tooltipSide}>
|
|
87
|
+
<Component ref={ref} className={classNames('tlui-column', className)} {...props} />
|
|
88
|
+
</TldrawUiOrientationProvider>
|
|
89
|
+
)
|
|
20
90
|
}
|
|
21
91
|
)
|
|
22
92
|
|
|
@@ -26,8 +96,12 @@ export const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
|
26
96
|
*
|
|
27
97
|
* @public @react */
|
|
28
98
|
export const TldrawUiGrid = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
29
|
-
({ asChild, className, ...props }, ref) => {
|
|
99
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
30
100
|
const Component = asChild ? Slot.Root : 'div'
|
|
31
|
-
return
|
|
101
|
+
return (
|
|
102
|
+
<TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
|
|
103
|
+
<Component ref={ref} className={classNames('tlui-grid', className)} {...props} />
|
|
104
|
+
</TldrawUiOrientationProvider>
|
|
105
|
+
)
|
|
32
106
|
}
|
|
33
107
|
)
|
|
@@ -3,6 +3,7 @@ import { ReactNode } from 'react'
|
|
|
3
3
|
import { unwrapLabel } from '../../../context/actions'
|
|
4
4
|
import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
|
|
5
5
|
import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
|
|
6
|
+
import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from '../layout'
|
|
6
7
|
import { TldrawUiDropdownMenuGroup } from '../TldrawUiDropdownMenu'
|
|
7
8
|
import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
|
|
8
9
|
|
|
@@ -19,17 +20,18 @@ export interface TLUiMenuGroupProps<TranslationKey extends string = string> {
|
|
|
19
20
|
|
|
20
21
|
/** @public @react */
|
|
21
22
|
export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGroupProps) {
|
|
22
|
-
const
|
|
23
|
+
const menu = useTldrawUiMenuContext()
|
|
24
|
+
const { orientation } = useTldrawUiOrientation()
|
|
23
25
|
const msg = useTranslation()
|
|
24
|
-
const labelToUse = unwrapLabel(label,
|
|
26
|
+
const labelToUse = unwrapLabel(label, menu.type)
|
|
25
27
|
const labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined
|
|
26
28
|
|
|
27
|
-
switch (
|
|
29
|
+
switch (menu.type) {
|
|
28
30
|
case 'panel': {
|
|
29
31
|
return (
|
|
30
32
|
<div
|
|
31
33
|
className={classNames('tlui-menu__group', className)}
|
|
32
|
-
data-testid={`${sourceId}-group.${id}`}
|
|
34
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
33
35
|
>
|
|
34
36
|
{children}
|
|
35
37
|
</div>
|
|
@@ -37,7 +39,10 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
37
39
|
}
|
|
38
40
|
case 'menu': {
|
|
39
41
|
return (
|
|
40
|
-
<TldrawUiDropdownMenuGroup
|
|
42
|
+
<TldrawUiDropdownMenuGroup
|
|
43
|
+
className={className}
|
|
44
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
45
|
+
>
|
|
41
46
|
{children}
|
|
42
47
|
</TldrawUiDropdownMenuGroup>
|
|
43
48
|
)
|
|
@@ -47,7 +52,7 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
47
52
|
<div
|
|
48
53
|
dir="ltr"
|
|
49
54
|
className={classNames('tlui-menu__group', className)}
|
|
50
|
-
data-testid={`${sourceId}-group.${id}`}
|
|
55
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
51
56
|
>
|
|
52
57
|
{children}
|
|
53
58
|
</div>
|
|
@@ -56,12 +61,30 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
56
61
|
case 'keyboard-shortcuts': {
|
|
57
62
|
// todo: if groups need a label, let's give em a label
|
|
58
63
|
return (
|
|
59
|
-
<div className="tlui-shortcuts-dialog__group" data-testid={`${sourceId}-group.${id}`}>
|
|
64
|
+
<div className="tlui-shortcuts-dialog__group" data-testid={`${menu.sourceId}-group.${id}`}>
|
|
60
65
|
<h2 className="tlui-shortcuts-dialog__group__title">{labelStr}</h2>
|
|
61
66
|
<div className="tlui-shortcuts-dialog__group__content">{children}</div>
|
|
62
67
|
</div>
|
|
63
68
|
)
|
|
64
69
|
}
|
|
70
|
+
case 'toolbar': {
|
|
71
|
+
const Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn
|
|
72
|
+
return (
|
|
73
|
+
<Layout className="tlui-main-toolbar__group" data-testid={`${menu.sourceId}-group.${id}`}>
|
|
74
|
+
{children}
|
|
75
|
+
</Layout>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
case 'toolbar-overflow': {
|
|
79
|
+
return (
|
|
80
|
+
<TldrawUiGrid
|
|
81
|
+
className="tlui-main-toolbar__group"
|
|
82
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
</TldrawUiGrid>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
65
88
|
default: {
|
|
66
89
|
return children
|
|
67
90
|
}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
exhaustiveSwitchError,
|
|
3
|
+
getPointerInfo,
|
|
4
|
+
preventDefault,
|
|
5
|
+
TLPointerEventInfo,
|
|
6
|
+
useEditor,
|
|
7
|
+
Vec,
|
|
8
|
+
VecModel,
|
|
9
|
+
} from '@tldraw/editor'
|
|
2
10
|
import { ContextMenu as _ContextMenu } from 'radix-ui'
|
|
3
|
-
import { useState } from 'react'
|
|
11
|
+
import { useMemo, useState } from 'react'
|
|
4
12
|
import { unwrapLabel } from '../../../context/actions'
|
|
5
13
|
import { TLUiEventSource } from '../../../context/events'
|
|
6
14
|
import { useReadonly } from '../../../hooks/useReadonly'
|
|
15
|
+
import { TLUiToolItem } from '../../../hooks/useTools'
|
|
7
16
|
import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
|
|
8
17
|
import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
|
|
9
18
|
import { kbdStr } from '../../../kbd-utils'
|
|
@@ -15,6 +24,7 @@ import { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'
|
|
|
15
24
|
import { TLUiIconJsx } from '../TldrawUiIcon'
|
|
16
25
|
import { TldrawUiKbd } from '../TldrawUiKbd'
|
|
17
26
|
import { TldrawUiToolbarButton } from '../TldrawUiToolbar'
|
|
27
|
+
import { tooltipManager } from '../TldrawUiTooltip'
|
|
18
28
|
import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
|
|
19
29
|
|
|
20
30
|
/** @public */
|
|
@@ -63,6 +73,10 @@ export interface TLUiMenuItemProps<
|
|
|
63
73
|
* Whether the item is selected.
|
|
64
74
|
*/
|
|
65
75
|
isSelected?: boolean
|
|
76
|
+
/**
|
|
77
|
+
* The function to call when the item is dragged. If this is provided, the item will be draggable.
|
|
78
|
+
*/
|
|
79
|
+
onDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void
|
|
66
80
|
}
|
|
67
81
|
|
|
68
82
|
/** @public @react */
|
|
@@ -81,6 +95,7 @@ export function TldrawUiMenuItem<
|
|
|
81
95
|
onSelect,
|
|
82
96
|
noClose,
|
|
83
97
|
isSelected,
|
|
98
|
+
onDragStart,
|
|
84
99
|
}: TLUiMenuItemProps<TranslationKey, IconType>) {
|
|
85
100
|
const { type: menuType, sourceId } = useTldrawUiMenuContext()
|
|
86
101
|
|
|
@@ -207,6 +222,20 @@ export function TldrawUiMenuItem<
|
|
|
207
222
|
)
|
|
208
223
|
}
|
|
209
224
|
case 'toolbar': {
|
|
225
|
+
if (onDragStart) {
|
|
226
|
+
return (
|
|
227
|
+
<DraggableToolbarButton
|
|
228
|
+
id={id}
|
|
229
|
+
icon={icon}
|
|
230
|
+
onSelect={onSelect}
|
|
231
|
+
onDragStart={onDragStart}
|
|
232
|
+
labelToUse={labelToUse}
|
|
233
|
+
titleStr={titleStr}
|
|
234
|
+
disabled={disabled}
|
|
235
|
+
isSelected={isSelected}
|
|
236
|
+
/>
|
|
237
|
+
)
|
|
238
|
+
}
|
|
210
239
|
return (
|
|
211
240
|
<TldrawUiToolbarButton
|
|
212
241
|
aria-label={labelStr}
|
|
@@ -227,6 +256,21 @@ export function TldrawUiMenuItem<
|
|
|
227
256
|
)
|
|
228
257
|
}
|
|
229
258
|
case 'toolbar-overflow': {
|
|
259
|
+
if (onDragStart) {
|
|
260
|
+
return (
|
|
261
|
+
<DraggableToolbarButton
|
|
262
|
+
id={id}
|
|
263
|
+
icon={icon}
|
|
264
|
+
onSelect={onSelect}
|
|
265
|
+
onDragStart={onDragStart}
|
|
266
|
+
labelToUse={labelToUse}
|
|
267
|
+
titleStr={titleStr}
|
|
268
|
+
disabled={disabled}
|
|
269
|
+
isSelected={isSelected}
|
|
270
|
+
overflow
|
|
271
|
+
/>
|
|
272
|
+
)
|
|
273
|
+
}
|
|
230
274
|
return (
|
|
231
275
|
<TldrawUiToolbarButton
|
|
232
276
|
aria-label={labelStr}
|
|
@@ -248,3 +292,175 @@ export function TldrawUiMenuItem<
|
|
|
248
292
|
}
|
|
249
293
|
}
|
|
250
294
|
}
|
|
295
|
+
|
|
296
|
+
function useDraggableEvents(
|
|
297
|
+
onDragStart: TLUiToolItem['onDragStart'],
|
|
298
|
+
onSelect: TLUiToolItem['onSelect']
|
|
299
|
+
) {
|
|
300
|
+
const editor = useEditor()
|
|
301
|
+
const events = useMemo(() => {
|
|
302
|
+
let state = { name: 'idle' } as
|
|
303
|
+
| {
|
|
304
|
+
name: 'idle'
|
|
305
|
+
}
|
|
306
|
+
| {
|
|
307
|
+
name: 'pointing'
|
|
308
|
+
screenSpaceStart: VecModel
|
|
309
|
+
}
|
|
310
|
+
| {
|
|
311
|
+
name: 'dragging'
|
|
312
|
+
screenSpaceStart: VecModel
|
|
313
|
+
}
|
|
314
|
+
| {
|
|
315
|
+
name: 'dragged'
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function handlePointerDown(e: React.PointerEvent<HTMLButtonElement>) {
|
|
319
|
+
state = {
|
|
320
|
+
name: 'pointing',
|
|
321
|
+
screenSpaceStart: { x: e.clientX, y: e.clientY },
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
e.currentTarget.setPointerCapture(e.pointerId)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function handlePointerMove(e: React.PointerEvent<HTMLButtonElement>) {
|
|
328
|
+
if ((e as any).isSpecialRedispatchedEvent) return
|
|
329
|
+
|
|
330
|
+
if (state.name === 'pointing') {
|
|
331
|
+
const distanceSq = Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY })
|
|
332
|
+
if (
|
|
333
|
+
distanceSq >
|
|
334
|
+
(editor.getInstanceState().isCoarsePointer
|
|
335
|
+
? editor.options.coarseDragDistanceSquared
|
|
336
|
+
: editor.options.dragDistanceSquared)
|
|
337
|
+
) {
|
|
338
|
+
const screenSpaceStart = state.screenSpaceStart
|
|
339
|
+
state = {
|
|
340
|
+
name: 'dragging',
|
|
341
|
+
screenSpaceStart,
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
editor.run(() => {
|
|
345
|
+
// Set origin point
|
|
346
|
+
editor.dispatch({
|
|
347
|
+
type: 'pointer',
|
|
348
|
+
target: 'canvas',
|
|
349
|
+
name: 'pointer_down',
|
|
350
|
+
...getPointerInfo(e),
|
|
351
|
+
point: screenSpaceStart,
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
// Pointer down potentially selects shapes, so we need to deselect them.
|
|
355
|
+
editor.selectNone()
|
|
356
|
+
|
|
357
|
+
// start drag
|
|
358
|
+
onDragStart?.('toolbar', {
|
|
359
|
+
type: 'pointer',
|
|
360
|
+
target: 'canvas',
|
|
361
|
+
name: 'pointer_move',
|
|
362
|
+
...getPointerInfo(e),
|
|
363
|
+
point: screenSpaceStart,
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
tooltipManager.hideAllTooltips()
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function handlePointerUp(e: React.PointerEvent<HTMLButtonElement>) {
|
|
373
|
+
if ((e as any).isSpecialRedispatchedEvent) return
|
|
374
|
+
|
|
375
|
+
e.currentTarget.releasePointerCapture(e.pointerId)
|
|
376
|
+
|
|
377
|
+
editor.dispatch({
|
|
378
|
+
type: 'pointer',
|
|
379
|
+
target: 'canvas',
|
|
380
|
+
name: 'pointer_up',
|
|
381
|
+
...getPointerInfo(e),
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function handleClick() {
|
|
386
|
+
if (state.name === 'dragging' || state.name === 'dragged') {
|
|
387
|
+
state = { name: 'idle' }
|
|
388
|
+
return true
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
state = { name: 'idle' }
|
|
392
|
+
onSelect?.('toolbar')
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
onPointerDown: handlePointerDown,
|
|
397
|
+
onPointerMove: handlePointerMove,
|
|
398
|
+
onPointerUp: handlePointerUp,
|
|
399
|
+
onClick: handleClick,
|
|
400
|
+
}
|
|
401
|
+
}, [onDragStart, editor, onSelect])
|
|
402
|
+
|
|
403
|
+
return events
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function DraggableToolbarButton({
|
|
407
|
+
id,
|
|
408
|
+
labelToUse,
|
|
409
|
+
titleStr,
|
|
410
|
+
disabled,
|
|
411
|
+
isSelected,
|
|
412
|
+
icon,
|
|
413
|
+
onSelect,
|
|
414
|
+
onDragStart,
|
|
415
|
+
overflow,
|
|
416
|
+
}: {
|
|
417
|
+
id: string
|
|
418
|
+
disabled: boolean
|
|
419
|
+
labelToUse?: string
|
|
420
|
+
titleStr?: string
|
|
421
|
+
isSelected?: boolean
|
|
422
|
+
icon: TLUiMenuItemProps['icon']
|
|
423
|
+
onSelect: TLUiMenuItemProps['onSelect']
|
|
424
|
+
onDragStart: TLUiMenuItemProps['onDragStart']
|
|
425
|
+
overflow?: boolean
|
|
426
|
+
}) {
|
|
427
|
+
const events = useDraggableEvents(onDragStart, onSelect)
|
|
428
|
+
|
|
429
|
+
if (overflow) {
|
|
430
|
+
return (
|
|
431
|
+
<TldrawUiToolbarButton
|
|
432
|
+
aria-label={labelToUse}
|
|
433
|
+
aria-pressed={isSelected ? 'true' : 'false'}
|
|
434
|
+
isActive={isSelected}
|
|
435
|
+
className="tlui-button-grid__button"
|
|
436
|
+
data-testid={`tools.more.${id}`}
|
|
437
|
+
data-value={id}
|
|
438
|
+
disabled={disabled}
|
|
439
|
+
title={titleStr}
|
|
440
|
+
type="icon"
|
|
441
|
+
{...events}
|
|
442
|
+
>
|
|
443
|
+
<TldrawUiButtonIcon icon={icon!} />
|
|
444
|
+
</TldrawUiToolbarButton>
|
|
445
|
+
)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return (
|
|
449
|
+
<TldrawUiToolbarButton
|
|
450
|
+
aria-label={labelToUse}
|
|
451
|
+
aria-pressed={isSelected ? 'true' : 'false'}
|
|
452
|
+
data-testid={`tools.${id}`}
|
|
453
|
+
data-value={id}
|
|
454
|
+
disabled={disabled}
|
|
455
|
+
onTouchStart={(e) => {
|
|
456
|
+
preventDefault(e)
|
|
457
|
+
onSelect('toolbar')
|
|
458
|
+
}}
|
|
459
|
+
title={titleStr}
|
|
460
|
+
type="tool"
|
|
461
|
+
{...events}
|
|
462
|
+
>
|
|
463
|
+
<TldrawUiButtonIcon icon={icon!} />
|
|
464
|
+
</TldrawUiToolbarButton>
|
|
465
|
+
)
|
|
466
|
+
}
|