tldraw 3.15.0-next.f1dfcef63951 → 3.15.0
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 +93 -92
- package/dist-cjs/index.js +32 -30
- 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/frame/FrameShapeUtil.js +5 -5
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.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/shapes/text/TextShapeUtil.js +5 -11
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/styles.js.map +2 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +11 -1
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +1 -0
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.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/menu-items.js +16 -0
- package/dist-cjs/lib/ui/components/menu-items.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 +0 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +28 -1
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +24 -7
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.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 +93 -92
- package/dist-esm/index.mjs +139 -133
- 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/frame/FrameShapeUtil.mjs +5 -5
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.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/shapes/text/TextShapeUtil.mjs +5 -11
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/styles.mjs.map +2 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +11 -1
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +2 -0
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.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/menu-items.mjs +16 -0
- package/dist-esm/lib/ui/components/menu-items.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 +0 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +28 -1
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +24 -7
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.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 +165 -159
- 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/frame/FrameShapeUtil.tsx +5 -7
- 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/shapes/text/TextShapeUtil.tsx +5 -12
- package/src/lib/styles.tsx +3 -1
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +8 -0
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +2 -0
- 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/menu-items.tsx +17 -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 -4
- package/src/lib/ui/context/actions.tsx +30 -2
- package/src/lib/ui/context/events.tsx +2 -0
- package/src/lib/ui/hooks/useClipboardEvents.ts +31 -10
- package/src/lib/ui/hooks/useKeyboardShortcuts.ts +3 -2
- package/src/lib/ui/hooks/useTools.tsx +2 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +4 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -0
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +8 -22
- package/src/test/Editor.test.tsx +68 -1
- package/src/test/commands/clipboard.test.ts +1 -1
- package/src/test/navigation.test.ts +254 -0
- package/tldraw.css +25 -26
- package/src/test/editor.test.ts +0 -77
|
@@ -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}
|
|
@@ -303,33 +303,26 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
function getTextSize(editor: Editor, props: TLTextShape['props']) {
|
|
306
|
-
const { font, richText,
|
|
306
|
+
const { font, richText, size, w } = props
|
|
307
307
|
|
|
308
|
-
const minWidth =
|
|
308
|
+
const minWidth = 16
|
|
309
309
|
const fontSize = FONT_SIZES[size]
|
|
310
310
|
|
|
311
|
-
const
|
|
312
|
-
? null
|
|
313
|
-
: // `measureText` floors the number so we need to do the same here to avoid issues.
|
|
314
|
-
Math.floor(Math.max(minWidth, w))
|
|
311
|
+
const maybeFixedWidth = props.autoSize ? null : Math.max(minWidth, Math.floor(w))
|
|
315
312
|
|
|
316
313
|
const html = renderHtmlFromRichTextForMeasurement(editor, richText)
|
|
317
314
|
const result = editor.textMeasure.measureHtml(html, {
|
|
318
315
|
...TEXT_PROPS,
|
|
319
316
|
fontFamily: FONT_FAMILIES[font],
|
|
320
317
|
fontSize: fontSize,
|
|
321
|
-
maxWidth:
|
|
318
|
+
maxWidth: maybeFixedWidth,
|
|
322
319
|
})
|
|
323
320
|
|
|
324
321
|
// If we're autosizing the measureText will essentially `Math.floor`
|
|
325
322
|
// the numbers so `19` rather than `19.3`, this means we must +1 to
|
|
326
323
|
// whatever we get to avoid wrapping.
|
|
327
|
-
if (autoSize) {
|
|
328
|
-
result.w += 1
|
|
329
|
-
}
|
|
330
|
-
|
|
331
324
|
return {
|
|
332
|
-
width: Math.max(minWidth, result.w),
|
|
325
|
+
width: maybeFixedWidth ?? Math.max(minWidth, result.w + 1),
|
|
333
326
|
height: Math.max(fontSize, result.h),
|
|
334
327
|
}
|
|
335
328
|
}
|
package/src/lib/styles.tsx
CHANGED
package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx
CHANGED
|
@@ -213,6 +213,14 @@ export function DefaultKeyboardShortcutsDialogContent() {
|
|
|
213
213
|
<TldrawUiMenuActionItem actionId="enlarge-shapes" />
|
|
214
214
|
<TldrawUiMenuActionItem actionId="shrink-shapes" />
|
|
215
215
|
<TldrawUiMenuActionItem actionId="a11y-repeat-shape-announce" />
|
|
216
|
+
<TldrawUiMenuItem
|
|
217
|
+
id="a11y-open-keyboard-shortcuts"
|
|
218
|
+
label="a11y.open-keyboard-shortcuts"
|
|
219
|
+
kbd="cmd+alt+/"
|
|
220
|
+
onSelect={() => {
|
|
221
|
+
/* do nothing */
|
|
222
|
+
}}
|
|
223
|
+
/>
|
|
216
224
|
</TldrawUiMenuGroup>
|
|
217
225
|
{showCollaborationUi && (
|
|
218
226
|
<TldrawUiMenuGroup label="shortcuts-dialog.collaboration" id="collaboration">
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ToggleEdgeScrollingItem,
|
|
20
20
|
ToggleFocusModeItem,
|
|
21
21
|
ToggleGridItem,
|
|
22
|
+
ToggleKeyboardShortcutsItem,
|
|
22
23
|
ToggleLockMenuItem,
|
|
23
24
|
TogglePasteAtCursorItem,
|
|
24
25
|
ToggleReduceMotionItem,
|
|
@@ -161,6 +162,7 @@ export function PreferencesGroup() {
|
|
|
161
162
|
<ToggleFocusModeItem />
|
|
162
163
|
<ToggleEdgeScrollingItem />
|
|
163
164
|
<ToggleReduceMotionItem />
|
|
165
|
+
<ToggleKeyboardShortcutsItem />
|
|
164
166
|
<ToggleDynamicSizeModeItem />
|
|
165
167
|
<TogglePasteAtCursorItem />
|
|
166
168
|
<ToggleDebugModeItem />
|
|
@@ -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
|
}
|
|
@@ -634,6 +634,23 @@ export function ToggleReduceMotionItem() {
|
|
|
634
634
|
)
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
+
/** @public @react */
|
|
638
|
+
export function ToggleKeyboardShortcutsItem() {
|
|
639
|
+
const editor = useEditor()
|
|
640
|
+
const keyboardShortcuts = useValue(
|
|
641
|
+
'keyboardShortcuts',
|
|
642
|
+
() => editor.user.getAreKeyboardShortcutsEnabled(),
|
|
643
|
+
[editor]
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
return (
|
|
647
|
+
<TldrawUiMenuActionCheckboxItem
|
|
648
|
+
actionId="toggle-keyboard-shortcuts"
|
|
649
|
+
checked={keyboardShortcuts}
|
|
650
|
+
/>
|
|
651
|
+
)
|
|
652
|
+
}
|
|
653
|
+
|
|
637
654
|
/** @public @react */
|
|
638
655
|
export function ToggleDebugModeItem() {
|
|
639
656
|
const editor = useEditor()
|
|
@@ -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
|
*/
|
|
@@ -218,7 +219,6 @@ export function TldrawUiMenuItem<
|
|
|
218
219
|
preventDefault(e)
|
|
219
220
|
onSelect('toolbar')
|
|
220
221
|
}}
|
|
221
|
-
role="option"
|
|
222
222
|
title={titleStr}
|
|
223
223
|
type="tool"
|
|
224
224
|
>
|
|
@@ -237,7 +237,6 @@ export function TldrawUiMenuItem<
|
|
|
237
237
|
data-value={id}
|
|
238
238
|
disabled={disabled}
|
|
239
239
|
onClick={() => onSelect('toolbar')}
|
|
240
|
-
role="option"
|
|
241
240
|
title={titleStr}
|
|
242
241
|
type="icon"
|
|
243
242
|
>
|
|
@@ -28,6 +28,7 @@ import { fitFrameToContent, removeFrame } from '../../utils/frames/frames'
|
|
|
28
28
|
import { generateShapeAnnouncementMessage } from '../components/A11y'
|
|
29
29
|
import { EditLinkDialog } from '../components/EditLinkDialog'
|
|
30
30
|
import { EmbedDialog } from '../components/EmbedDialog'
|
|
31
|
+
import { DefaultKeyboardShortcutsDialog } from '../components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog'
|
|
31
32
|
import { useShowCollaborationUi } from '../hooks/useCollaborationStatus'
|
|
32
33
|
import { flattenShapesToImages } from '../hooks/useFlatten'
|
|
33
34
|
import { TLUiTranslationKey } from '../hooks/useTranslation/TLUiTranslationKey'
|
|
@@ -42,12 +43,13 @@ export interface TLUiActionItem<
|
|
|
42
43
|
TransationKey extends string = string,
|
|
43
44
|
IconType extends string = string,
|
|
44
45
|
> {
|
|
45
|
-
icon?: IconType
|
|
46
|
+
icon?: IconType | React.ReactElement
|
|
46
47
|
id: string
|
|
47
48
|
kbd?: string
|
|
48
49
|
label?: TransationKey | { [key: string]: TransationKey }
|
|
49
50
|
readonlyOk?: boolean
|
|
50
51
|
checkbox?: boolean
|
|
52
|
+
isRequiredA11yAction?: boolean
|
|
51
53
|
onSelect(source: TLUiEventSource): Promise<void> | void
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -168,6 +170,15 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
168
170
|
helpers.addDialog({ component: EmbedDialog })
|
|
169
171
|
},
|
|
170
172
|
},
|
|
173
|
+
{
|
|
174
|
+
id: 'open-kbd-shortcuts',
|
|
175
|
+
label: 'action.open-kbd-shortcuts',
|
|
176
|
+
kbd: 'cmd+alt+/,ctrl+alt+/',
|
|
177
|
+
onSelect(source) {
|
|
178
|
+
trackEvent('open-kbd-shortcuts', { source })
|
|
179
|
+
helpers.addDialog({ component: DefaultKeyboardShortcutsDialog })
|
|
180
|
+
},
|
|
181
|
+
},
|
|
171
182
|
{
|
|
172
183
|
id: 'insert-media',
|
|
173
184
|
label: 'action.insert-media',
|
|
@@ -502,7 +513,6 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
502
513
|
}
|
|
503
514
|
}
|
|
504
515
|
|
|
505
|
-
if (!editor.canCreateShapes(ids)) return
|
|
506
516
|
editor.markHistoryStoppingPoint('duplicate shapes')
|
|
507
517
|
editor.duplicateShapes(ids, offset)
|
|
508
518
|
|
|
@@ -1234,6 +1244,21 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1234
1244
|
},
|
|
1235
1245
|
checkbox: true,
|
|
1236
1246
|
},
|
|
1247
|
+
{
|
|
1248
|
+
id: 'toggle-keyboard-shortcuts',
|
|
1249
|
+
label: {
|
|
1250
|
+
default: 'action.toggle-keyboard-shortcuts',
|
|
1251
|
+
menu: 'action.toggle-keyboard-shortcuts.menu',
|
|
1252
|
+
},
|
|
1253
|
+
readonlyOk: true,
|
|
1254
|
+
onSelect(source) {
|
|
1255
|
+
trackEvent('toggle-keyboard-shortcuts', { source })
|
|
1256
|
+
editor.user.updateUserPreferences({
|
|
1257
|
+
areKeyboardShortcutsEnabled: !editor.user.getAreKeyboardShortcutsEnabled(),
|
|
1258
|
+
})
|
|
1259
|
+
},
|
|
1260
|
+
checkbox: true,
|
|
1261
|
+
},
|
|
1237
1262
|
{
|
|
1238
1263
|
id: 'toggle-edge-scrolling',
|
|
1239
1264
|
label: {
|
|
@@ -1530,6 +1555,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1530
1555
|
id: 'adjust-shape-styles',
|
|
1531
1556
|
label: 'a11y.adjust-shape-styles',
|
|
1532
1557
|
kbd: 'cmd+Enter,ctrl+Enter',
|
|
1558
|
+
isRequiredA11yAction: true,
|
|
1533
1559
|
onSelect: async (source) => {
|
|
1534
1560
|
if (!canApplySelectionAction()) return
|
|
1535
1561
|
|
|
@@ -1543,6 +1569,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1543
1569
|
{
|
|
1544
1570
|
id: 'a11y-open-context-menu',
|
|
1545
1571
|
kbd: 'cmd+shift+Enter,ctrl+shift+Enter',
|
|
1572
|
+
isRequiredA11yAction: true,
|
|
1546
1573
|
readonlyOk: true,
|
|
1547
1574
|
onSelect: async (source) => {
|
|
1548
1575
|
if (!canApplySelectionAction()) return
|
|
@@ -1595,6 +1622,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1595
1622
|
id: 'a11y-repeat-shape-announce',
|
|
1596
1623
|
kbd: 'alt+r',
|
|
1597
1624
|
label: 'a11y.repeat-shape',
|
|
1625
|
+
isRequiredA11yAction: true,
|
|
1598
1626
|
readonlyOk: true,
|
|
1599
1627
|
onSelect: async (source) => {
|
|
1600
1628
|
const selectedShapeIds = editor.getSelectedShapeIds()
|
|
@@ -107,6 +107,7 @@ export interface TLUiEventMap {
|
|
|
107
107
|
'toggle-paste-at-cursor': null
|
|
108
108
|
'toggle-lock': null
|
|
109
109
|
'toggle-reduce-motion': null
|
|
110
|
+
'toggle-keyboard-shortcuts': null
|
|
110
111
|
'toggle-edge-scrolling': null
|
|
111
112
|
'color-scheme': { value: string }
|
|
112
113
|
'exit-pen-mode': null
|
|
@@ -127,6 +128,7 @@ export interface TLUiEventMap {
|
|
|
127
128
|
'copy-link': null
|
|
128
129
|
'image-replace': null
|
|
129
130
|
'video-replace': null
|
|
131
|
+
'open-kbd-shortcuts': null
|
|
130
132
|
'rich-text': {
|
|
131
133
|
operation:
|
|
132
134
|
| 'bold'
|
|
@@ -352,7 +352,7 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
|
|
|
352
352
|
|
|
353
353
|
if (tldrawHtmlComment) {
|
|
354
354
|
try {
|
|
355
|
-
// First try parsing as plain JSON (version 2
|
|
355
|
+
// First try parsing as plain JSON (version 2/3 formats)
|
|
356
356
|
let json
|
|
357
357
|
try {
|
|
358
358
|
json = JSON.parse(tldrawHtmlComment)
|
|
@@ -380,19 +380,32 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
|
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
// Handle versioned clipboard format
|
|
383
|
-
if (json.version ===
|
|
384
|
-
// Version
|
|
383
|
+
if (json.version === 3) {
|
|
384
|
+
// Version 3: Assets are plain, decompress only other data
|
|
385
385
|
try {
|
|
386
|
-
|
|
386
|
+
const otherData = JSON.parse(
|
|
387
|
+
lz.decompressFromBase64(json.data.otherCompressed) || '{}'
|
|
388
|
+
)
|
|
389
|
+
const reconstructedData = {
|
|
390
|
+
assets: json.data.assets || [],
|
|
391
|
+
...otherData,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
r({ type: 'tldraw', data: reconstructedData })
|
|
387
395
|
return
|
|
388
396
|
} catch (error) {
|
|
389
397
|
r({
|
|
390
398
|
type: 'error',
|
|
391
399
|
data: json,
|
|
392
|
-
reason: `failed to
|
|
400
|
+
reason: `failed to decompress version 2 clipboard data: ${error}`,
|
|
393
401
|
})
|
|
394
402
|
return
|
|
395
403
|
}
|
|
404
|
+
}
|
|
405
|
+
if (json.version === 2) {
|
|
406
|
+
// Version 2: Everything is plain, this had issues with encoding... :-/
|
|
407
|
+
// TODO: nix this support after some time.
|
|
408
|
+
r({ type: 'tldraw', data: json.data })
|
|
396
409
|
} else {
|
|
397
410
|
// Version 1 or no version: Legacy format
|
|
398
411
|
if (typeof json.data === 'string') {
|
|
@@ -584,13 +597,21 @@ const handleNativeOrMenuCopy = async (editor: Editor) => {
|
|
|
584
597
|
return
|
|
585
598
|
}
|
|
586
599
|
|
|
587
|
-
//
|
|
588
|
-
|
|
600
|
+
// Use versioned clipboard format for better compression
|
|
601
|
+
// Version 3: Don't compress assets, only compress other data
|
|
602
|
+
const { assets, ...otherData } = content
|
|
603
|
+
const clipboardData = {
|
|
589
604
|
type: 'application/tldraw',
|
|
590
605
|
kind: 'content',
|
|
591
|
-
version:
|
|
592
|
-
data:
|
|
593
|
-
|
|
606
|
+
version: 3,
|
|
607
|
+
data: {
|
|
608
|
+
assets: assets || [], // Plain JSON, no compression
|
|
609
|
+
otherCompressed: lz.compressToBase64(JSON.stringify(otherData)), // Only compress non-asset data
|
|
610
|
+
},
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Don't compress the final structure - just use plain JSON
|
|
614
|
+
const stringifiedClipboard = JSON.stringify(clipboardData)
|
|
594
615
|
|
|
595
616
|
if (typeof navigator === 'undefined') {
|
|
596
617
|
return
|
|
@@ -61,7 +61,7 @@ export function useKeyboardShortcuts() {
|
|
|
61
61
|
if (SKIP_KBDS.includes(action.id)) continue
|
|
62
62
|
|
|
63
63
|
hot(getHotkeysStringFromKbd(action.kbd), (event) => {
|
|
64
|
-
if (areShortcutsDisabled(editor)) return
|
|
64
|
+
if (areShortcutsDisabled(editor) && !action.isRequiredA11yAction) return
|
|
65
65
|
preventDefault(event)
|
|
66
66
|
action.onSelect('kbd')
|
|
67
67
|
})
|
|
@@ -149,7 +149,8 @@ export function areShortcutsDisabled(editor: Editor) {
|
|
|
149
149
|
return (
|
|
150
150
|
editor.menus.hasAnyOpenMenus() ||
|
|
151
151
|
editor.getEditingShapeId() !== null ||
|
|
152
|
-
editor.getCrashingError()
|
|
152
|
+
editor.getCrashingError() ||
|
|
153
|
+
!editor.user.getAreKeyboardShortcutsEnabled()
|
|
153
154
|
)
|
|
154
155
|
}
|
|
155
156
|
|