tldraw 3.15.0-next.d30ed5ad740e → 3.15.0-next.e1af71086875
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 +16 -8
- package/dist-cjs/index.js +2 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawImage.js +5 -2
- package/dist-cjs/lib/TldrawImage.js.map +3 -3
- package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
- package/dist-cjs/lib/canvas/TldrawCropHandles.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawHandles.js +1 -1
- package/dist-cjs/lib/canvas/TldrawHandles.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawOverlays.js +1 -1
- package/dist-cjs/lib/canvas/TldrawOverlays.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +279 -271
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PathBuilder.js +21 -3
- package/dist-cjs/lib/shapes/shared/PathBuilder.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -0
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -0
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/styles.js.map +2 -2
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +3 -4
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/Spinner.js +2 -25
- package/dist-cjs/lib/ui/components/Spinner.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +2 -1
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButtonIcon.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +35 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +5 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js.map +1 -1
- 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 +16 -8
- package/dist-esm/index.mjs +6 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawImage.mjs +5 -2
- package/dist-esm/lib/TldrawImage.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawCropHandles.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawCropHandles.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawHandles.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawHandles.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawOverlays.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawOverlays.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +279 -271
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PathBuilder.mjs +22 -3
- package/dist-esm/lib/shapes/shared/PathBuilder.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -0
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -0
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/styles.mjs.map +2 -2
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +3 -4
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Spinner.mjs +3 -26
- package/dist-esm/lib/ui/components/Spinner.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +2 -1
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButtonIcon.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs +1 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +36 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +5 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs.map +1 -1
- 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 +4 -3
- package/src/index.ts +6 -1
- package/src/lib/TldrawImage.tsx +6 -2
- package/src/lib/canvas/TldrawCropHandles.tsx +1 -1
- package/src/lib/canvas/TldrawHandles.tsx +5 -1
- package/src/lib/canvas/TldrawOverlays.tsx +1 -1
- package/src/lib/canvas/TldrawSelectionForeground.tsx +5 -1
- package/src/lib/shapes/shared/PathBuilder.test.tsx +1 -1
- package/src/lib/shapes/shared/PathBuilder.tsx +35 -1
- package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -0
- package/src/lib/shapes/shared/RichTextLabel.tsx +1 -0
- package/src/lib/styles.tsx +3 -1
- package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +3 -4
- package/src/lib/ui/components/Spinner.tsx +2 -24
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +1 -0
- package/src/lib/ui/components/primitives/Button/TldrawUiButtonIcon.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiDialog.tsx +1 -1
- package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +41 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +5 -1
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +4 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +2 -2
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -2
- package/src/lib/ui/context/actions.tsx +1 -1
- package/src/lib/ui/hooks/useTools.tsx +2 -1
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +8 -22
- package/src/test/navigation.test.ts +254 -0
- package/tldraw.css +25 -26
package/src/lib/TldrawImage.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import { memo, useEffect, useLayoutEffect, useMemo, useState } from 'react'
|
|
|
15
15
|
import { defaultBindingUtils } from './defaultBindingUtils'
|
|
16
16
|
import { defaultShapeUtils } from './defaultShapeUtils'
|
|
17
17
|
import { TLUiAssetUrlOverrides } from './ui/assetUrls'
|
|
18
|
+
import { useDefaultEditorAssetsWithOverrides } from './utils/static-assets/assetUrls'
|
|
18
19
|
import { defaultAddFontsFromNode, tipTapDefaultExtensions } from './utils/text/richText'
|
|
19
20
|
|
|
20
21
|
/** @public */
|
|
@@ -111,6 +112,7 @@ export const TldrawImage = memo(function TldrawImage(props: TldrawImageProps) {
|
|
|
111
112
|
assetUrls,
|
|
112
113
|
textOptions = defaultTextOptions,
|
|
113
114
|
} = props
|
|
115
|
+
const assetUrlsWithOverrides = useDefaultEditorAssetsWithOverrides(assetUrls)
|
|
114
116
|
|
|
115
117
|
useLayoutEffect(() => {
|
|
116
118
|
if (!container) return
|
|
@@ -129,7 +131,7 @@ export const TldrawImage = memo(function TldrawImage(props: TldrawImageProps) {
|
|
|
129
131
|
tools: [],
|
|
130
132
|
getContainer: () => tempElm,
|
|
131
133
|
licenseKey,
|
|
132
|
-
fontAssetUrls:
|
|
134
|
+
fontAssetUrls: assetUrlsWithOverrides.fonts,
|
|
133
135
|
textOptions,
|
|
134
136
|
})
|
|
135
137
|
|
|
@@ -138,6 +140,8 @@ export const TldrawImage = memo(function TldrawImage(props: TldrawImageProps) {
|
|
|
138
140
|
const shapeIds = editor.getCurrentPageShapeIds()
|
|
139
141
|
|
|
140
142
|
async function setSvg() {
|
|
143
|
+
// We have to wait for the fonts to load so that we can correctly measure text sizes
|
|
144
|
+
await editor.fonts.loadRequiredFontsForCurrentPage(editor.options.maxFontsToLoadBeforeRender)
|
|
141
145
|
const imageResult = await editor.toImage([...shapeIds], {
|
|
142
146
|
bounds,
|
|
143
147
|
scale,
|
|
@@ -175,7 +179,7 @@ export const TldrawImage = memo(function TldrawImage(props: TldrawImageProps) {
|
|
|
175
179
|
preserveAspectRatio,
|
|
176
180
|
licenseKey,
|
|
177
181
|
pixelRatio,
|
|
178
|
-
|
|
182
|
+
assetUrlsWithOverrides,
|
|
179
183
|
textOptions,
|
|
180
184
|
])
|
|
181
185
|
|
|
@@ -23,5 +23,9 @@ export function TldrawHandles({ children }: TLHandlesProps) {
|
|
|
23
23
|
|
|
24
24
|
if (!shouldDisplayHandles) return null
|
|
25
25
|
|
|
26
|
-
return
|
|
26
|
+
return (
|
|
27
|
+
<svg className="tl-user-handles tl-overlays__item" aria-hidden="true">
|
|
28
|
+
{children}
|
|
29
|
+
</svg>
|
|
30
|
+
)
|
|
27
31
|
}
|
|
@@ -60,7 +60,7 @@ export function TldrawArrowHints() {
|
|
|
60
60
|
{ShapeIndicator && <ShapeIndicator shapeId={targetInfo.target.id} />}
|
|
61
61
|
|
|
62
62
|
{showEdgeHints && (
|
|
63
|
-
<svg className="tl-overlays__item">
|
|
63
|
+
<svg className="tl-overlays__item" aria-hidden="true">
|
|
64
64
|
<circle
|
|
65
65
|
cx={anchorInPageSpace.x}
|
|
66
66
|
cy={anchorInPageSpace.y}
|
|
@@ -192,7 +192,11 @@ export const TldrawSelectionForeground = track(function TldrawSelectionForegroun
|
|
|
192
192
|
textHandleHeight * zoom >= 4
|
|
193
193
|
|
|
194
194
|
return (
|
|
195
|
-
<svg
|
|
195
|
+
<svg
|
|
196
|
+
className="tl-overlays__item tl-selection__fg"
|
|
197
|
+
data-testid="selection-foreground"
|
|
198
|
+
aria-hidden="true"
|
|
199
|
+
>
|
|
196
200
|
<g ref={rSvg}>
|
|
197
201
|
{shouldDisplayBox && (
|
|
198
202
|
<rect
|
|
@@ -138,7 +138,7 @@ describe('PathBuilder', () => {
|
|
|
138
138
|
.toGeometry()
|
|
139
139
|
|
|
140
140
|
expect(geometry?.toSimpleSvgPath()).toMatchInlineSnapshot(
|
|
141
|
-
`"M0,0L100,100L100,
|
|
141
|
+
`"M0,0L100,100L100,0L84.92197106154207,-11.50593202657044L67.93757691512266,-18.409491194065584L50.000000178767834,-20.71067750830319L32.06242347050369,-18.409490975101022L15.078029408356239,-11.505931600276853L6.103515630684342e-7,6.103515559630068e-7L-11.505931600276849,15.078029408356231L-18.409490975101022,32.062423470503674L-20.710677508303192,50.00000017876782L-18.409491194065588,67.93757691512262L-11.50593202657045,84.92197106154204L-1.4210854715202004e-14,99.99999999999999L0,0Z"`
|
|
142
142
|
)
|
|
143
143
|
})
|
|
144
144
|
})
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
Geometry2dFilters,
|
|
11
11
|
Geometry2dOptions,
|
|
12
12
|
getPerfectDashProps,
|
|
13
|
+
getVerticesCountForArcLength,
|
|
13
14
|
Group2d,
|
|
14
15
|
modulate,
|
|
15
16
|
PerfectDashTerminal,
|
|
@@ -121,6 +122,7 @@ export interface CubicBezierToPathBuilderCommand extends PathBuilderCommandBase
|
|
|
121
122
|
type: 'cubic'
|
|
122
123
|
cp1: VecModel
|
|
123
124
|
cp2: VecModel
|
|
125
|
+
resolution?: number
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
/** @internal */
|
|
@@ -317,8 +319,17 @@ export class PathBuilder {
|
|
|
317
319
|
// Calculate the sweep angle
|
|
318
320
|
const sweepAngle = endAngle - startAngle
|
|
319
321
|
|
|
322
|
+
// Calculate the approximate arc length. General ellipse arc length is expensive - there's
|
|
323
|
+
// no closed form solution, so we have to do iterative numerical approximation. As we only
|
|
324
|
+
// use this to control the resolution of later approximations, let's cheat and just use the
|
|
325
|
+
// circular arc length with the largest radius:
|
|
326
|
+
const approximateArcLength = Math.max(rx1, ry1) * Math.abs(sweepAngle)
|
|
327
|
+
|
|
320
328
|
// Approximate the arc using cubic bezier curves
|
|
321
329
|
const numSegments = Math.min(4, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2)))
|
|
330
|
+
const resolutionPerSegment = Math.ceil(
|
|
331
|
+
getVerticesCountForArcLength(approximateArcLength) / numSegments
|
|
332
|
+
)
|
|
322
333
|
const anglePerSegment = sweepAngle / numSegments
|
|
323
334
|
|
|
324
335
|
// Helper function to compute point on ellipse
|
|
@@ -364,7 +375,16 @@ export class PathBuilder {
|
|
|
364
375
|
const cp2y = end.y - handleScale * d2.y
|
|
365
376
|
|
|
366
377
|
const bezierOpts = i === 0 ? opts : { ...opts, mergeWithPrevious: true }
|
|
367
|
-
this.
|
|
378
|
+
this.cubicBezierToWithResolution(
|
|
379
|
+
end.x,
|
|
380
|
+
end.y,
|
|
381
|
+
cp1x,
|
|
382
|
+
cp1y,
|
|
383
|
+
cp2x,
|
|
384
|
+
cp2y,
|
|
385
|
+
bezierOpts,
|
|
386
|
+
resolutionPerSegment
|
|
387
|
+
)
|
|
368
388
|
}
|
|
369
389
|
|
|
370
390
|
return this
|
|
@@ -378,6 +398,18 @@ export class PathBuilder {
|
|
|
378
398
|
cp2X: number,
|
|
379
399
|
cp2Y: number,
|
|
380
400
|
opts?: PathBuilderCommandOpts
|
|
401
|
+
) {
|
|
402
|
+
return this.cubicBezierToWithResolution(x, y, cp1X, cp1Y, cp2X, cp2Y, opts)
|
|
403
|
+
}
|
|
404
|
+
private cubicBezierToWithResolution(
|
|
405
|
+
x: number,
|
|
406
|
+
y: number,
|
|
407
|
+
cp1X: number,
|
|
408
|
+
cp1Y: number,
|
|
409
|
+
cp2X: number,
|
|
410
|
+
cp2Y: number,
|
|
411
|
+
opts?: PathBuilderCommandOpts,
|
|
412
|
+
resolution?: number
|
|
381
413
|
) {
|
|
382
414
|
this.assertHasMoveTo()
|
|
383
415
|
this.commands.push({
|
|
@@ -388,6 +420,7 @@ export class PathBuilder {
|
|
|
388
420
|
cp2: { x: cp2X, y: cp2Y },
|
|
389
421
|
isClose: false,
|
|
390
422
|
opts,
|
|
423
|
+
resolution,
|
|
391
424
|
})
|
|
392
425
|
return this
|
|
393
426
|
}
|
|
@@ -972,6 +1005,7 @@ export class PathBuilderGeometry2d extends Geometry2d {
|
|
|
972
1005
|
cp1: Vec.From(command.cp1),
|
|
973
1006
|
cp2: Vec.From(command.cp2),
|
|
974
1007
|
end: Vec.From(command),
|
|
1008
|
+
resolution: command.resolution,
|
|
975
1009
|
})
|
|
976
1010
|
)
|
|
977
1011
|
break
|
|
@@ -128,6 +128,7 @@ export const RichTextLabel = React.memo(function RichTextLabel({
|
|
|
128
128
|
return (
|
|
129
129
|
<div
|
|
130
130
|
className={`${cssPrefix}-label tl-text-wrapper tl-rich-text-wrapper`}
|
|
131
|
+
aria-hidden={!isEditing}
|
|
131
132
|
data-font={font}
|
|
132
133
|
data-align={align}
|
|
133
134
|
data-hastext={!isEmpty}
|
package/src/lib/styles.tsx
CHANGED
|
@@ -45,7 +45,7 @@ export const DefaultNavigationPanel = memo(function DefaultNavigationPanel() {
|
|
|
45
45
|
title={`${msg(unwrapLabel(actions['zoom-out'].label))} ${kbdStr(actions['zoom-out'].kbd!)}`}
|
|
46
46
|
onClick={() => actions['zoom-out'].onSelect('navigation-zone')}
|
|
47
47
|
>
|
|
48
|
-
<TldrawUiButtonIcon icon="minus" />
|
|
48
|
+
<TldrawUiButtonIcon small icon="minus" />
|
|
49
49
|
</TldrawUiToolbarButton>
|
|
50
50
|
)}
|
|
51
51
|
{ZoomMenu && <ZoomMenu key="zoom-menu" />}
|
|
@@ -56,7 +56,7 @@ export const DefaultNavigationPanel = memo(function DefaultNavigationPanel() {
|
|
|
56
56
|
title={`${msg(unwrapLabel(actions['zoom-in'].label))} ${kbdStr(actions['zoom-in'].kbd!)}`}
|
|
57
57
|
onClick={() => actions['zoom-in'].onSelect('navigation-zone')}
|
|
58
58
|
>
|
|
59
|
-
<TldrawUiButtonIcon icon="plus" />
|
|
59
|
+
<TldrawUiButtonIcon small icon="plus" />
|
|
60
60
|
</TldrawUiToolbarButton>
|
|
61
61
|
)}
|
|
62
62
|
{Minimap && (
|
|
@@ -64,10 +64,9 @@ export const DefaultNavigationPanel = memo(function DefaultNavigationPanel() {
|
|
|
64
64
|
type="icon"
|
|
65
65
|
data-testid="minimap.toggle-button"
|
|
66
66
|
title={msg('navigation-zone.toggle-minimap')}
|
|
67
|
-
className="tlui-navigation-panel__toggle"
|
|
68
67
|
onClick={toggleMinimap}
|
|
69
68
|
>
|
|
70
|
-
<TldrawUiButtonIcon icon={collapsed ? '
|
|
69
|
+
<TldrawUiButtonIcon small icon={collapsed ? 'chevron-right' : 'chevron-left'} />
|
|
71
70
|
</TldrawUiToolbarButton>
|
|
72
71
|
)}
|
|
73
72
|
</>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DefaultSpinner } from '@tldraw/editor'
|
|
1
2
|
import React from 'react'
|
|
2
3
|
import { useTranslation } from '../hooks/useTranslation/useTranslation'
|
|
3
4
|
|
|
@@ -5,28 +6,5 @@ import { useTranslation } from '../hooks/useTranslation/useTranslation'
|
|
|
5
6
|
export function Spinner(props: React.SVGProps<SVGSVGElement>) {
|
|
6
7
|
const msg = useTranslation()
|
|
7
8
|
|
|
8
|
-
return (
|
|
9
|
-
<svg
|
|
10
|
-
width={16}
|
|
11
|
-
height={16}
|
|
12
|
-
viewBox="0 0 16 16"
|
|
13
|
-
{...props}
|
|
14
|
-
aria-label={msg('app.loading')}
|
|
15
|
-
aria-hidden="false"
|
|
16
|
-
>
|
|
17
|
-
<g strokeWidth={2} fill="none" fillRule="evenodd">
|
|
18
|
-
<circle strokeOpacity={0.25} cx={8} cy={8} r={7} stroke="currentColor" />
|
|
19
|
-
<path strokeLinecap="round" d="M15 8c0-4.5-4.5-7-7-7" stroke="currentColor">
|
|
20
|
-
<animateTransform
|
|
21
|
-
attributeName="transform"
|
|
22
|
-
type="rotate"
|
|
23
|
-
from="0 8 8"
|
|
24
|
-
to="360 8 8"
|
|
25
|
-
dur="1s"
|
|
26
|
-
repeatCount="indefinite"
|
|
27
|
-
/>
|
|
28
|
-
</path>
|
|
29
|
-
</g>
|
|
30
|
-
</svg>
|
|
31
|
-
)
|
|
9
|
+
return <DefaultSpinner aria-label={msg('app.loading')} {...props} />
|
|
32
10
|
}
|
|
@@ -65,7 +65,7 @@ export interface TLUiDialogBodyProps {
|
|
|
65
65
|
/** @public @react */
|
|
66
66
|
export function TldrawUiDialogBody({ className, children, style }: TLUiDialogBodyProps) {
|
|
67
67
|
return (
|
|
68
|
-
<div className={classNames('tlui-dialog__body', className)} style={style}>
|
|
68
|
+
<div className={classNames('tlui-dialog__body', className)} style={style} tabIndex={0}>
|
|
69
69
|
{children}
|
|
70
70
|
</div>
|
|
71
71
|
)
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
|
-
import { memo, useLayoutEffect, useRef } from 'react'
|
|
2
|
+
import { cloneElement, memo, ReactElement, useLayoutEffect, useRef } from 'react'
|
|
3
3
|
import { useAssetUrls } from '../../context/asset-urls'
|
|
4
4
|
import { TLUiIconType } from '../../icon-types'
|
|
5
5
|
|
|
6
|
+
/** @public */
|
|
7
|
+
export type TLUiIconJsx = ReactElement<React.HTMLAttributes<HTMLDivElement>>
|
|
8
|
+
|
|
6
9
|
/** @public */
|
|
7
10
|
export interface TLUiIconProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
8
|
-
icon: TLUiIconType | Exclude<string, TLUiIconType>
|
|
11
|
+
icon: TLUiIconType | Exclude<string, TLUiIconType> | TLUiIconJsx
|
|
9
12
|
label: string
|
|
10
13
|
small?: boolean
|
|
11
14
|
color?: string
|
|
@@ -24,6 +27,41 @@ export const TldrawUiIcon = memo(function TldrawUiIcon({
|
|
|
24
27
|
className,
|
|
25
28
|
...props
|
|
26
29
|
}: TLUiIconProps) {
|
|
30
|
+
if (typeof icon === 'string') {
|
|
31
|
+
return (
|
|
32
|
+
<TldrawUIIconInner
|
|
33
|
+
label={label}
|
|
34
|
+
small={small}
|
|
35
|
+
invertIcon={invertIcon}
|
|
36
|
+
icon={icon}
|
|
37
|
+
color={color}
|
|
38
|
+
className={className}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return cloneElement(icon, {
|
|
45
|
+
...props,
|
|
46
|
+
className: classNames({ 'tlui-icon__small': small }, className, icon.props.className),
|
|
47
|
+
'aria-label': label,
|
|
48
|
+
style: {
|
|
49
|
+
color,
|
|
50
|
+
transform: invertIcon ? 'scale(-1, 1)' : undefined,
|
|
51
|
+
...icon.props.style,
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
function TldrawUIIconInner({
|
|
57
|
+
label,
|
|
58
|
+
small,
|
|
59
|
+
invertIcon,
|
|
60
|
+
icon,
|
|
61
|
+
color,
|
|
62
|
+
className,
|
|
63
|
+
...props
|
|
64
|
+
}: TLUiIconProps & { icon: TLUiIconType | Exclude<string, TLUiIconType> }) {
|
|
27
65
|
const assetUrls = useAssetUrls()
|
|
28
66
|
const asset = assetUrls.icons[icon as TLUiIconType] ?? assetUrls.icons['question-mark-circle']
|
|
29
67
|
const ref = useRef<HTMLDivElement>(null)
|
|
@@ -69,4 +107,4 @@ export const TldrawUiIcon = memo(function TldrawUiIcon({
|
|
|
69
107
|
}}
|
|
70
108
|
/>
|
|
71
109
|
)
|
|
72
|
-
}
|
|
110
|
+
}
|
|
@@ -13,6 +13,7 @@ export interface TLUiSliderProps {
|
|
|
13
13
|
onValueChange(value: number): void
|
|
14
14
|
onHistoryMark(id: string): void
|
|
15
15
|
'data-testid'?: string
|
|
16
|
+
ariaValueModifier?: number
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/** @public @react */
|
|
@@ -26,6 +27,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
26
27
|
label,
|
|
27
28
|
onValueChange,
|
|
28
29
|
['data-testid']: testId,
|
|
30
|
+
ariaValueModifier = 1,
|
|
29
31
|
}: TLUiSliderProps,
|
|
30
32
|
ref
|
|
31
33
|
) {
|
|
@@ -81,7 +83,9 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
81
83
|
</_Slider.Track>
|
|
82
84
|
{value !== null && (
|
|
83
85
|
<_Slider.Thumb
|
|
84
|
-
aria-
|
|
86
|
+
aria-valuemin={(min ?? 0) * ariaValueModifier}
|
|
87
|
+
aria-valuenow={value * ariaValueModifier}
|
|
88
|
+
aria-valuemax={steps * ariaValueModifier}
|
|
85
89
|
className="tlui-slider__thumb"
|
|
86
90
|
dir="ltr"
|
|
87
91
|
ref={ref}
|
|
@@ -76,6 +76,10 @@ export const TldrawUiToolbarToggleGroup = ({
|
|
|
76
76
|
<_Toolbar.ToggleGroup
|
|
77
77
|
type={type}
|
|
78
78
|
{...props}
|
|
79
|
+
// TODO: this fixes a bug in Radix until they fix it.
|
|
80
|
+
// https://github.com/radix-ui/primitives/issues/3188
|
|
81
|
+
// https://github.com/radix-ui/primitives/pull/3189
|
|
82
|
+
role="radiogroup"
|
|
79
83
|
className={classnames('tlui-toolbar-toggle-group', className)}
|
|
80
84
|
>
|
|
81
85
|
{children}
|
|
@@ -5,7 +5,7 @@ import { TLUiEventSource } from '../../../context/events'
|
|
|
5
5
|
import { useReadonly } from '../../../hooks/useReadonly'
|
|
6
6
|
import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
|
|
7
7
|
import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
|
|
8
|
-
import { TldrawUiIcon } from '../TldrawUiIcon'
|
|
8
|
+
import { TldrawUiIcon, TLUiIconJsx } from '../TldrawUiIcon'
|
|
9
9
|
import { TldrawUiKbd } from '../TldrawUiKbd'
|
|
10
10
|
import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ export interface TLUiMenuCheckboxItemProps<
|
|
|
14
14
|
TranslationKey extends string = string,
|
|
15
15
|
IconType extends string = string,
|
|
16
16
|
> {
|
|
17
|
-
icon?: IconType
|
|
17
|
+
icon?: IconType | TLUiIconJsx
|
|
18
18
|
id: string
|
|
19
19
|
kbd?: string
|
|
20
20
|
title?: string
|
|
@@ -12,6 +12,7 @@ import { TldrawUiButton } from '../Button/TldrawUiButton'
|
|
|
12
12
|
import { TldrawUiButtonIcon } from '../Button/TldrawUiButtonIcon'
|
|
13
13
|
import { TldrawUiButtonLabel } from '../Button/TldrawUiButtonLabel'
|
|
14
14
|
import { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'
|
|
15
|
+
import { TLUiIconJsx } from '../TldrawUiIcon'
|
|
15
16
|
import { TldrawUiKbd } from '../TldrawUiKbd'
|
|
16
17
|
import { TldrawUiToolbarButton } from '../TldrawUiToolbar'
|
|
17
18
|
import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
|
|
@@ -25,11 +26,11 @@ export interface TLUiMenuItemProps<
|
|
|
25
26
|
/**
|
|
26
27
|
* The icon to display on the item. Icons are only shown in certain menu types.
|
|
27
28
|
*/
|
|
28
|
-
icon?: IconType
|
|
29
|
+
icon?: IconType | TLUiIconJsx
|
|
29
30
|
/**
|
|
30
31
|
* An icon to display to the left of the menu item.
|
|
31
32
|
*/
|
|
32
|
-
iconLeft?: IconType
|
|
33
|
+
iconLeft?: IconType | TLUiIconJsx
|
|
33
34
|
/**
|
|
34
35
|
* The keyboard shortcut to display on the item.
|
|
35
36
|
*/
|
|
@@ -43,7 +43,7 @@ export interface TLUiActionItem<
|
|
|
43
43
|
TransationKey extends string = string,
|
|
44
44
|
IconType extends string = string,
|
|
45
45
|
> {
|
|
46
|
-
icon?: IconType
|
|
46
|
+
icon?: IconType | React.ReactElement
|
|
47
47
|
id: string
|
|
48
48
|
kbd?: string
|
|
49
49
|
label?: TransationKey | { [key: string]: TransationKey }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Editor, GeoShapeGeoStyle, useMaybeEditor } from '@tldraw/editor'
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
import { EmbedDialog } from '../components/EmbedDialog'
|
|
4
|
+
import { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'
|
|
4
5
|
import { useA11y } from '../context/a11y'
|
|
5
6
|
import { TLUiEventSource, useUiEvents } from '../context/events'
|
|
6
7
|
import { TLUiIconType } from '../icon-types'
|
|
@@ -16,7 +17,7 @@ export interface TLUiToolItem<
|
|
|
16
17
|
id: string
|
|
17
18
|
label: TranslationKey
|
|
18
19
|
shortcutsLabel?: TranslationKey
|
|
19
|
-
icon: IconType
|
|
20
|
+
icon: IconType | TLUiIconJsx
|
|
20
21
|
onSelect(source: TLUiEventSource): void
|
|
21
22
|
/**
|
|
22
23
|
* The keyboard shortcut for this tool. This is a string that can be a single key,
|
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.15.0-next.
|
|
4
|
+
export const version = '3.15.0-next.e1af71086875'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-07-
|
|
8
|
-
patch: '2025-07-
|
|
7
|
+
minor: '2025-07-28T10:38:17.512Z',
|
|
8
|
+
patch: '2025-07-28T10:38:17.512Z',
|
|
9
9
|
}
|
package/src/lib/ui.css
CHANGED
|
@@ -964,7 +964,7 @@
|
|
|
964
964
|
justify-content: center;
|
|
965
965
|
border-radius: 99px;
|
|
966
966
|
opacity: 0;
|
|
967
|
-
animation: fade-in;
|
|
967
|
+
animation: tl-fade-in;
|
|
968
968
|
animation-duration: 0.12s;
|
|
969
969
|
animation-delay: 2s;
|
|
970
970
|
animation-fill-mode: forwards;
|
|
@@ -1108,20 +1108,6 @@
|
|
|
1108
1108
|
display: none;
|
|
1109
1109
|
}
|
|
1110
1110
|
|
|
1111
|
-
.tlui-navigation-panel__toggle .tlui-icon {
|
|
1112
|
-
opacity: 0.24;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
.tlui-navigation-panel__toggle:active .tlui-icon {
|
|
1116
|
-
opacity: 1;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
@media (hover: hover) {
|
|
1120
|
-
.tlui-navigation-panel__toggle:hover .tlui-icon {
|
|
1121
|
-
opacity: 1;
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
1111
|
/* Minimap */
|
|
1126
1112
|
|
|
1127
1113
|
.tlui-minimap {
|
|
@@ -1379,11 +1365,11 @@
|
|
|
1379
1365
|
|
|
1380
1366
|
@media (prefers-reduced-motion: no-preference) {
|
|
1381
1367
|
.tlui-toast__container[data-state='open'] {
|
|
1382
|
-
animation: slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
|
1368
|
+
animation: tlui-slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
|
1383
1369
|
}
|
|
1384
1370
|
|
|
1385
1371
|
.tlui-toast__container[data-state='closed'] {
|
|
1386
|
-
animation:
|
|
1372
|
+
animation: tlui-fade-out 100ms ease-in;
|
|
1387
1373
|
}
|
|
1388
1374
|
|
|
1389
1375
|
.tlui-toast__container[data-swipe='move'] {
|
|
@@ -1396,7 +1382,7 @@
|
|
|
1396
1382
|
}
|
|
1397
1383
|
|
|
1398
1384
|
.tlui-toast__container[data-swipe='end'] {
|
|
1399
|
-
animation:
|
|
1385
|
+
animation: tlui-slide-out 100ms ease-out;
|
|
1400
1386
|
}
|
|
1401
1387
|
}
|
|
1402
1388
|
|
|
@@ -1411,7 +1397,7 @@
|
|
|
1411
1397
|
z-index: var(--layer-canvas-overlays);
|
|
1412
1398
|
background-color: var(--color-overlay);
|
|
1413
1399
|
pointer-events: all;
|
|
1414
|
-
animation:
|
|
1400
|
+
animation: tl-fade-in 0.12s ease-out;
|
|
1415
1401
|
display: grid;
|
|
1416
1402
|
place-items: center;
|
|
1417
1403
|
overflow-y: auto;
|
|
@@ -1978,7 +1964,7 @@
|
|
|
1978
1964
|
}
|
|
1979
1965
|
|
|
1980
1966
|
/* ------------------- Animations ------------------- */
|
|
1981
|
-
@keyframes
|
|
1967
|
+
@keyframes tlui-fade-out {
|
|
1982
1968
|
0% {
|
|
1983
1969
|
opacity: 1;
|
|
1984
1970
|
}
|
|
@@ -1987,7 +1973,7 @@
|
|
|
1987
1973
|
}
|
|
1988
1974
|
}
|
|
1989
1975
|
|
|
1990
|
-
@keyframes slide-in {
|
|
1976
|
+
@keyframes tlui-slide-in {
|
|
1991
1977
|
from {
|
|
1992
1978
|
transform: translateX(calc(100% + var(--space-3)));
|
|
1993
1979
|
}
|
|
@@ -1996,7 +1982,7 @@
|
|
|
1996
1982
|
}
|
|
1997
1983
|
}
|
|
1998
1984
|
|
|
1999
|
-
@keyframes
|
|
1985
|
+
@keyframes tlui-slide-out {
|
|
2000
1986
|
from {
|
|
2001
1987
|
transform: translateX(var(--radix-toast-swipe-end-x));
|
|
2002
1988
|
}
|