tldraw 3.16.0-canary.e455ab838b8f → 3.16.0-canary.e618c2fbc95d
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 +89 -9
- package/dist-cjs/index.js +6 -2
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +3 -2
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +3 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js +1 -1
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/InputModeMenu.js +77 -0
- package/dist-cjs/lib/ui/components/InputModeMenu.js.map +7 -0
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +2 -0
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +4 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +4 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +6 -4
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +32 -21
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +5 -25
- 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/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +8 -2
- 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 +89 -9
- package/dist-esm/index.mjs +11 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +3 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +3 -1
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +3 -3
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/InputModeMenu.mjs +57 -0
- package/dist-esm/lib/ui/components/InputModeMenu.mjs.map +7 -0
- 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/StylePanel/DefaultStylePanel.mjs +4 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +1 -1
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +4 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +6 -4
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +32 -21
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +5 -25
- 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/useTranslation/defaultTranslation.mjs +8 -2
- 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 +3 -3
- package/src/index.ts +8 -1
- package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +83 -13
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +97 -3
- package/src/lib/shapes/arrow/arrow-types.ts +3 -5
- package/src/lib/shapes/arrow/arrowTargetState.ts +34 -3
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +6 -2
- package/src/lib/ui/components/AccessibilityMenu.tsx +2 -2
- package/src/lib/ui/components/InputModeMenu.tsx +65 -0
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -0
- package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +4 -2
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +4 -2
- package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +1 -1
- package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +5 -3
- package/src/lib/ui/components/menu-items.tsx +5 -3
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +12 -5
- package/src/lib/ui/context/actions.tsx +5 -27
- package/src/lib/ui/context/events.tsx +2 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +8 -2
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +8 -2
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +15 -2
- package/src/test/TestEditor.ts +8 -2
- package/src/test/commands/setCamera.test.ts +13 -0
- package/src/test/frames.test.ts +15 -0
- package/tldraw.css +15 -2
|
@@ -163,7 +163,7 @@ export class Pointing extends StateNode {
|
|
|
163
163
|
const endHandle = handles.find((h) => h.id === 'end')!
|
|
164
164
|
const change = util.onHandleDrag?.(this.editor.getShape(shape)!, {
|
|
165
165
|
handle: { ...endHandle, x: point.x, y: point.y },
|
|
166
|
-
isPrecise:
|
|
166
|
+
isPrecise: this.isPrecise,
|
|
167
167
|
isCreatingShape: true,
|
|
168
168
|
initial: initial,
|
|
169
169
|
})
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
sortByIndex,
|
|
14
14
|
structuredClone,
|
|
15
15
|
} from '@tldraw/editor'
|
|
16
|
+
import { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'
|
|
16
17
|
import { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'
|
|
17
18
|
import { getArrowBindings } from '../../../shapes/arrow/shared'
|
|
18
19
|
|
|
@@ -135,10 +136,13 @@ export class DraggingHandle extends StateNode {
|
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
// Only relevant to arrows
|
|
138
|
-
private exactTimeout = -1
|
|
139
|
+
private exactTimeout = -1
|
|
139
140
|
|
|
140
141
|
// Only relevant to arrows
|
|
141
142
|
private resetExactTimeout() {
|
|
143
|
+
const arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')
|
|
144
|
+
const timeoutValue = arrowUtil.options.pointingPreciseTimeout
|
|
145
|
+
|
|
142
146
|
if (this.exactTimeout !== -1) {
|
|
143
147
|
this.clearExactTimeout()
|
|
144
148
|
}
|
|
@@ -150,7 +154,7 @@ export class DraggingHandle extends StateNode {
|
|
|
150
154
|
this.update()
|
|
151
155
|
}
|
|
152
156
|
this.exactTimeout = -1
|
|
153
|
-
},
|
|
157
|
+
}, timeoutValue)
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
// Only relevant to arrows
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ToggleEnhancedA11yModeItem,
|
|
2
3
|
ToggleKeyboardShortcutsItem,
|
|
3
4
|
ToggleReduceMotionItem,
|
|
4
|
-
ToggleUiLabelsItem,
|
|
5
5
|
} from './menu-items'
|
|
6
6
|
import { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'
|
|
7
7
|
import { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'
|
|
@@ -13,7 +13,7 @@ export function AccessibilityMenu() {
|
|
|
13
13
|
<TldrawUiMenuGroup id="accessibility">
|
|
14
14
|
<ToggleReduceMotionItem />
|
|
15
15
|
<ToggleKeyboardShortcutsItem />
|
|
16
|
-
<
|
|
16
|
+
<ToggleEnhancedA11yModeItem />
|
|
17
17
|
</TldrawUiMenuGroup>
|
|
18
18
|
</TldrawUiMenuSubmenu>
|
|
19
19
|
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useEditor, useValue } from '@tldraw/editor'
|
|
2
|
+
import { useUiEvents } from '../context/events'
|
|
3
|
+
import { TldrawUiMenuCheckboxItem } from './primitives/menus/TldrawUiMenuCheckboxItem'
|
|
4
|
+
import { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'
|
|
5
|
+
import { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'
|
|
6
|
+
|
|
7
|
+
const MODES = ['auto', 'trackpad', 'mouse'] as const
|
|
8
|
+
|
|
9
|
+
/** @public @react */
|
|
10
|
+
export function InputModeMenu() {
|
|
11
|
+
const editor = useEditor()
|
|
12
|
+
const trackEvent = useUiEvents()
|
|
13
|
+
|
|
14
|
+
const inputMode = useValue('inputMode', () => editor.user.getUserPreferences().inputMode, [
|
|
15
|
+
editor,
|
|
16
|
+
])
|
|
17
|
+
const wheelBehavior = useValue('wheelBehavior', () => editor.getCameraOptions().wheelBehavior, [
|
|
18
|
+
editor,
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
const isModeChecked = (mode: string) => {
|
|
22
|
+
if (mode === 'auto') {
|
|
23
|
+
return inputMode === null
|
|
24
|
+
}
|
|
25
|
+
return inputMode === mode
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const getLabel = (mode: string, wheelBehavior: 'zoom' | 'pan' | 'none') => {
|
|
29
|
+
if (mode === 'auto') {
|
|
30
|
+
return `action.toggle-auto-${wheelBehavior}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return mode === 'trackpad' ? 'action.toggle-trackpad' : 'action.toggle-mouse'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<TldrawUiMenuSubmenu id="help menu input-mode" label="menu.input-mode">
|
|
38
|
+
<TldrawUiMenuGroup id="peripheral-mode">
|
|
39
|
+
{MODES.map((mode) => (
|
|
40
|
+
<TldrawUiMenuCheckboxItem
|
|
41
|
+
id={`peripheral-mode-${mode}`}
|
|
42
|
+
key={mode}
|
|
43
|
+
label={getLabel(mode, wheelBehavior)}
|
|
44
|
+
checked={isModeChecked(mode)}
|
|
45
|
+
readonlyOk
|
|
46
|
+
onSelect={() => {
|
|
47
|
+
trackEvent('input-mode', { source: 'menu', value: mode })
|
|
48
|
+
switch (mode) {
|
|
49
|
+
case 'auto':
|
|
50
|
+
editor.user.updateUserPreferences({ inputMode: null })
|
|
51
|
+
break
|
|
52
|
+
case 'trackpad':
|
|
53
|
+
editor.user.updateUserPreferences({ inputMode: 'trackpad' })
|
|
54
|
+
break
|
|
55
|
+
case 'mouse':
|
|
56
|
+
editor.user.updateUserPreferences({ inputMode: 'mouse' })
|
|
57
|
+
break
|
|
58
|
+
}
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
))}
|
|
62
|
+
</TldrawUiMenuGroup>
|
|
63
|
+
</TldrawUiMenuSubmenu>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
@@ -2,6 +2,7 @@ import { useCanRedo, useCanUndo } from '../../hooks/menu-hooks'
|
|
|
2
2
|
import { AccessibilityMenu } from '../AccessibilityMenu'
|
|
3
3
|
import { ColorSchemeMenu } from '../ColorSchemeMenu'
|
|
4
4
|
import { KeyboardShortcutsMenuItem } from '../HelpMenu/DefaultHelpMenuContent'
|
|
5
|
+
import { InputModeMenu } from '../InputModeMenu'
|
|
5
6
|
import { LanguageMenu } from '../LanguageMenu'
|
|
6
7
|
import {
|
|
7
8
|
ClipboardMenuGroup,
|
|
@@ -164,6 +165,9 @@ export function PreferencesGroup() {
|
|
|
164
165
|
<TogglePasteAtCursorItem />
|
|
165
166
|
<ToggleDebugModeItem />
|
|
166
167
|
</TldrawUiMenuGroup>
|
|
168
|
+
<TldrawUiMenuGroup id="input-mode">
|
|
169
|
+
<InputModeMenu />
|
|
170
|
+
</TldrawUiMenuGroup>
|
|
167
171
|
<TldrawUiMenuGroup id="color-scheme">
|
|
168
172
|
<ColorSchemeMenu />
|
|
169
173
|
</TldrawUiMenuGroup>
|
|
@@ -24,7 +24,9 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
|
|
|
24
24
|
children,
|
|
25
25
|
}: TLUiStylePanelProps) {
|
|
26
26
|
const editor = useEditor()
|
|
27
|
-
const
|
|
27
|
+
const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
|
|
28
|
+
editor,
|
|
29
|
+
])
|
|
28
30
|
|
|
29
31
|
const ref = useRef<HTMLDivElement>(null)
|
|
30
32
|
usePassThroughWheelEvents(ref)
|
|
@@ -62,7 +64,7 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
|
|
|
62
64
|
data-testid="style.panel"
|
|
63
65
|
className={classNames('tlui-style-panel', { 'tlui-style-panel__wrapper': !isMobile })}
|
|
64
66
|
data-ismobile={isMobile}
|
|
65
|
-
data-
|
|
67
|
+
data-enhanced-a11y-mode={enhancedA11yMode}
|
|
66
68
|
onPointerLeave={handlePointerOut}
|
|
67
69
|
>
|
|
68
70
|
<StylePanelContextProvider styles={styles}>
|
|
@@ -91,7 +91,7 @@ const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const
|
|
|
91
91
|
/** @public @react */
|
|
92
92
|
export function StylePanelOpacityPicker() {
|
|
93
93
|
const editor = useEditor()
|
|
94
|
-
const { onHistoryMark,
|
|
94
|
+
const { onHistoryMark, enhancedA11yMode } = useStylePanelContext()
|
|
95
95
|
|
|
96
96
|
const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor])
|
|
97
97
|
const trackEvent = useUiEvents()
|
|
@@ -126,7 +126,9 @@ export function StylePanelOpacityPicker() {
|
|
|
126
126
|
|
|
127
127
|
return (
|
|
128
128
|
<>
|
|
129
|
-
{
|
|
129
|
+
{enhancedA11yMode && (
|
|
130
|
+
<StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>
|
|
131
|
+
)}
|
|
130
132
|
<TldrawUiSlider
|
|
131
133
|
data-testid="style.opacity"
|
|
132
134
|
value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
|
|
@@ -127,7 +127,7 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
|
|
|
127
127
|
|
|
128
128
|
return (
|
|
129
129
|
<>
|
|
130
|
-
{ctx.
|
|
130
|
+
{ctx.enhancedA11yMode && <StylePanelSubheading>{title}</StylePanelSubheading>}
|
|
131
131
|
<TldrawUiToolbar label={title}>
|
|
132
132
|
<TldrawUiToolbarToggleGroup
|
|
133
133
|
data-testid={`style.${uiType}`}
|
|
@@ -5,7 +5,7 @@ import { useUiEvents } from '../../context/events'
|
|
|
5
5
|
/** @public */
|
|
6
6
|
export interface StylePanelContext {
|
|
7
7
|
styles: ReadonlySharedStyleMap
|
|
8
|
-
|
|
8
|
+
enhancedA11yMode: boolean
|
|
9
9
|
onHistoryMark(id: string): void
|
|
10
10
|
onValueChange<T>(style: StyleProp<T>, value: T): void
|
|
11
11
|
}
|
|
@@ -23,7 +23,9 @@ export function StylePanelContextProvider({ children, styles }: StylePanelContex
|
|
|
23
23
|
const trackEvent = useUiEvents()
|
|
24
24
|
|
|
25
25
|
const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
|
|
26
|
-
const
|
|
26
|
+
const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
|
|
27
|
+
editor,
|
|
28
|
+
])
|
|
27
29
|
const onValueChange = useCallback(
|
|
28
30
|
function <T>(style: StyleProp<T>, value: T) {
|
|
29
31
|
editor.run(() => {
|
|
@@ -43,7 +45,7 @@ export function StylePanelContextProvider({ children, styles }: StylePanelContex
|
|
|
43
45
|
<StylePanelContext.Provider
|
|
44
46
|
value={{
|
|
45
47
|
styles: styles,
|
|
46
|
-
|
|
48
|
+
enhancedA11yMode,
|
|
47
49
|
onHistoryMark,
|
|
48
50
|
onValueChange,
|
|
49
51
|
}}
|
|
@@ -652,11 +652,13 @@ export function ToggleKeyboardShortcutsItem() {
|
|
|
652
652
|
}
|
|
653
653
|
|
|
654
654
|
/** @public @react */
|
|
655
|
-
export function
|
|
655
|
+
export function ToggleEnhancedA11yModeItem() {
|
|
656
656
|
const editor = useEditor()
|
|
657
|
-
const
|
|
657
|
+
const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
|
|
658
|
+
editor,
|
|
659
|
+
])
|
|
658
660
|
|
|
659
|
-
return <TldrawUiMenuActionCheckboxItem actionId="
|
|
661
|
+
return <TldrawUiMenuActionCheckboxItem actionId="enhanced-a11y-mode" checked={enhancedA11yMode} />
|
|
660
662
|
}
|
|
661
663
|
|
|
662
664
|
/** @public @react */
|
|
@@ -267,7 +267,11 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
267
267
|
const editor = useMaybeEditor()
|
|
268
268
|
const tooltipId = useRef<string>(uniqueId())
|
|
269
269
|
const hasProvider = useContext(TooltipSingletonContext)
|
|
270
|
-
const
|
|
270
|
+
const enhancedA11yMode = useValue(
|
|
271
|
+
'enhancedA11yMode',
|
|
272
|
+
() => editor?.user.getEnhancedA11yMode(),
|
|
273
|
+
[editor]
|
|
274
|
+
)
|
|
271
275
|
|
|
272
276
|
const orientationCtx = useTldrawUiOrientation()
|
|
273
277
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
@@ -293,13 +297,13 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
293
297
|
}
|
|
294
298
|
}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
|
|
295
299
|
|
|
296
|
-
// Don't show tooltip if disabled, no content, or
|
|
300
|
+
// Don't show tooltip if disabled, no content, or enhanced accessibility mode is disabled
|
|
297
301
|
if (disabled || !content) {
|
|
298
302
|
return <>{children}</>
|
|
299
303
|
}
|
|
300
304
|
|
|
301
305
|
let delayDurationToUse
|
|
302
|
-
if (
|
|
306
|
+
if (enhancedA11yMode) {
|
|
303
307
|
delayDurationToUse = 0
|
|
304
308
|
} else {
|
|
305
309
|
delayDurationToUse =
|
|
@@ -307,9 +311,12 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
307
311
|
}
|
|
308
312
|
|
|
309
313
|
// Fallback to old behavior if no provider
|
|
310
|
-
if (!hasProvider ||
|
|
314
|
+
if (!hasProvider || enhancedA11yMode) {
|
|
311
315
|
return (
|
|
312
|
-
<_Tooltip.Root
|
|
316
|
+
<_Tooltip.Root
|
|
317
|
+
delayDuration={delayDurationToUse}
|
|
318
|
+
disableHoverableContent={!enhancedA11yMode}
|
|
319
|
+
>
|
|
313
320
|
<_Tooltip.Trigger asChild ref={ref}>
|
|
314
321
|
{children}
|
|
315
322
|
</_Tooltip.Trigger>
|
|
@@ -1270,16 +1270,16 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1270
1270
|
checkbox: true,
|
|
1271
1271
|
},
|
|
1272
1272
|
{
|
|
1273
|
-
id: '
|
|
1273
|
+
id: 'enhanced-a11y-mode',
|
|
1274
1274
|
label: {
|
|
1275
|
-
default: 'action.
|
|
1276
|
-
menu: 'action.
|
|
1275
|
+
default: 'action.enhanced-a11y-mode',
|
|
1276
|
+
menu: 'action.enhanced-a11y-mode.menu',
|
|
1277
1277
|
},
|
|
1278
1278
|
readonlyOk: true,
|
|
1279
1279
|
onSelect(source) {
|
|
1280
|
-
trackEvent('
|
|
1280
|
+
trackEvent('enhanced-a11y-mode', { source })
|
|
1281
1281
|
editor.user.updateUserPreferences({
|
|
1282
|
-
|
|
1282
|
+
enhancedA11yMode: !editor.user.getEnhancedA11yMode(),
|
|
1283
1283
|
})
|
|
1284
1284
|
},
|
|
1285
1285
|
checkbox: true,
|
|
@@ -1344,28 +1344,6 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
1344
1344
|
}
|
|
1345
1345
|
},
|
|
1346
1346
|
},
|
|
1347
|
-
{
|
|
1348
|
-
id: 'toggle-focus-mode',
|
|
1349
|
-
label: {
|
|
1350
|
-
default: 'action.toggle-focus-mode',
|
|
1351
|
-
menu: 'action.toggle-focus-mode.menu',
|
|
1352
|
-
},
|
|
1353
|
-
readonlyOk: true,
|
|
1354
|
-
kbd: 'cmd+.,ctrl+.',
|
|
1355
|
-
checkbox: true,
|
|
1356
|
-
onSelect(source) {
|
|
1357
|
-
// this needs to be deferred because it causes the menu
|
|
1358
|
-
// UI to unmount which puts us in a dodgy state
|
|
1359
|
-
editor.timers.requestAnimationFrame(() => {
|
|
1360
|
-
editor.run(() => {
|
|
1361
|
-
trackEvent('toggle-focus-mode', { source })
|
|
1362
|
-
helpers.clearDialogs()
|
|
1363
|
-
helpers.clearToasts()
|
|
1364
|
-
editor.updateInstanceState({ isFocusMode: !editor.getInstanceState().isFocusMode })
|
|
1365
|
-
})
|
|
1366
|
-
})
|
|
1367
|
-
},
|
|
1368
|
-
},
|
|
1369
1347
|
{
|
|
1370
1348
|
id: 'toggle-grid',
|
|
1371
1349
|
label: {
|
|
@@ -102,13 +102,14 @@ export interface TLUiEventMap {
|
|
|
102
102
|
'toggle-grid-mode': null
|
|
103
103
|
'toggle-wrap-mode': null
|
|
104
104
|
'toggle-focus-mode': null
|
|
105
|
+
'input-mode': { value: string }
|
|
105
106
|
'toggle-debug-mode': null
|
|
106
107
|
'toggle-dynamic-size-mode': null
|
|
107
108
|
'toggle-paste-at-cursor': null
|
|
108
109
|
'toggle-lock': null
|
|
109
110
|
'toggle-reduce-motion': null
|
|
110
111
|
'toggle-keyboard-shortcuts': null
|
|
111
|
-
'
|
|
112
|
+
'enhanced-a11y-mode': null
|
|
112
113
|
'toggle-edge-scrolling': null
|
|
113
114
|
'color-scheme': { value: string }
|
|
114
115
|
'exit-pen-mode': null
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
/** @public */
|
|
5
5
|
export type TLUiTranslationKey =
|
|
6
|
+
| 'action.toggle-auto-pan'
|
|
7
|
+
| 'action.toggle-auto-zoom'
|
|
8
|
+
| 'action.toggle-auto-none'
|
|
9
|
+
| 'action.toggle-mouse'
|
|
10
|
+
| 'action.toggle-trackpad'
|
|
6
11
|
| 'action.convert-to-bookmark'
|
|
7
12
|
| 'action.convert-to-embed'
|
|
8
13
|
| 'action.open-embed-link'
|
|
@@ -93,8 +98,8 @@ export type TLUiTranslationKey =
|
|
|
93
98
|
| 'action.toggle-reduce-motion'
|
|
94
99
|
| 'action.toggle-keyboard-shortcuts.menu'
|
|
95
100
|
| 'action.toggle-keyboard-shortcuts'
|
|
96
|
-
| 'action.
|
|
97
|
-
| 'action.
|
|
101
|
+
| 'action.enhanced-a11y-mode.menu'
|
|
102
|
+
| 'action.enhanced-a11y-mode'
|
|
98
103
|
| 'action.toggle-edge-scrolling.menu'
|
|
99
104
|
| 'action.toggle-edge-scrolling'
|
|
100
105
|
| 'action.toggle-debug-mode.menu'
|
|
@@ -311,6 +316,7 @@ export type TLUiTranslationKey =
|
|
|
311
316
|
| 'menu.language'
|
|
312
317
|
| 'menu.preferences'
|
|
313
318
|
| 'menu.view'
|
|
319
|
+
| 'menu.input-mode'
|
|
314
320
|
| 'context-menu.title'
|
|
315
321
|
| 'context-menu.edit'
|
|
316
322
|
| 'context-menu.arrange'
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
/** @internal */
|
|
5
5
|
export const DEFAULT_TRANSLATION = {
|
|
6
|
+
'action.toggle-auto-pan': 'Auto (trackpad)',
|
|
7
|
+
'action.toggle-auto-zoom': 'Auto (mouse)',
|
|
8
|
+
'action.toggle-auto-none': 'Auto',
|
|
9
|
+
'action.toggle-mouse': 'Mouse',
|
|
10
|
+
'action.toggle-trackpad': 'Trackpad',
|
|
6
11
|
'action.convert-to-bookmark': 'Convert to Bookmark',
|
|
7
12
|
'action.convert-to-embed': 'Convert to Embed',
|
|
8
13
|
'action.open-embed-link': 'Open link',
|
|
@@ -94,8 +99,8 @@ export const DEFAULT_TRANSLATION = {
|
|
|
94
99
|
'action.toggle-reduce-motion': 'Toggle reduce motion',
|
|
95
100
|
'action.toggle-keyboard-shortcuts.menu': 'Enable keyboard shortcuts',
|
|
96
101
|
'action.toggle-keyboard-shortcuts': 'Toggle keyboard shortcuts',
|
|
97
|
-
'action.
|
|
98
|
-
'action.
|
|
102
|
+
'action.enhanced-a11y-mode.menu': 'Enhanced accessibility mode',
|
|
103
|
+
'action.enhanced-a11y-mode': 'Toggle enhanced accessibility mode',
|
|
99
104
|
'action.toggle-edge-scrolling.menu': 'Edge scrolling',
|
|
100
105
|
'action.toggle-edge-scrolling': 'Toggle edge scrolling',
|
|
101
106
|
'action.toggle-debug-mode.menu': 'Debug mode',
|
|
@@ -312,6 +317,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
312
317
|
'menu.language': 'Language',
|
|
313
318
|
'menu.preferences': 'Preferences',
|
|
314
319
|
'menu.view': 'View',
|
|
320
|
+
'menu.input-mode': 'Input mode',
|
|
315
321
|
'context-menu.title': 'Context menu',
|
|
316
322
|
'context-menu.edit': 'Edit',
|
|
317
323
|
'context-menu.arrange': 'Arrange',
|
package/src/lib/ui/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '3.16.0-canary.
|
|
4
|
+
export const version = '3.16.0-canary.e618c2fbc95d'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-09-
|
|
8
|
-
patch: '2025-09-
|
|
7
|
+
minor: '2025-09-18T14:34:09.025Z',
|
|
8
|
+
patch: '2025-09-18T14:34:09.025Z',
|
|
9
9
|
}
|
package/src/lib/ui.css
CHANGED
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
min-height: 40px;
|
|
169
169
|
width: 100%;
|
|
170
170
|
gap: 8px;
|
|
171
|
-
margin: -4px
|
|
171
|
+
margin-top: -4px;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
.tlui-button__menu::after {
|
|
@@ -997,7 +997,7 @@
|
|
|
997
997
|
max-width: 148px;
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
|
-
.tlui-style-panel[data-
|
|
1000
|
+
.tlui-style-panel[data-enhanced-a11y-mode='true'] .tlui-button[data-isactive='true'] {
|
|
1001
1001
|
border-radius: 10px;
|
|
1002
1002
|
outline: 2px solid var(--tl-color-text);
|
|
1003
1003
|
outline-offset: -5px;
|
|
@@ -1039,6 +1039,19 @@ tldraw? probably.
|
|
|
1039
1039
|
display: none;
|
|
1040
1040
|
}
|
|
1041
1041
|
|
|
1042
|
+
/*
|
|
1043
|
+
* This is used in a couple places, like Align and Vertical Align.
|
|
1044
|
+
* It's because we have a toolbar with a Toggle Group but then an adjacent button
|
|
1045
|
+
* next to it that opens a popup.
|
|
1046
|
+
*/
|
|
1047
|
+
.tlui-style-panel__section .tlui-toolbar:has(.tlui-toolbar) {
|
|
1048
|
+
flex-wrap: wrap;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.tlui-style-panel__section .tlui-toolbar:has(.tlui-toolbar) .tlui-style-panel__subheading {
|
|
1052
|
+
margin-left: -2px;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1042
1055
|
.tlui-style-panel__section__common:not(:only-child) {
|
|
1043
1056
|
margin-bottom: 7px;
|
|
1044
1057
|
border-bottom: 1px solid var(--tl-color-divider);
|
package/src/test/TestEditor.ts
CHANGED
|
@@ -86,8 +86,14 @@ export class TestEditor extends Editor {
|
|
|
86
86
|
elm.tabIndex = 0
|
|
87
87
|
elm.getBoundingClientRect = () => bounds as DOMRect
|
|
88
88
|
|
|
89
|
-
const shapeUtilsWithDefaults = [
|
|
90
|
-
|
|
89
|
+
const shapeUtilsWithDefaults = [
|
|
90
|
+
...defaultShapeUtils.filter((s) => !options.shapeUtils?.some((su) => su.type === s.type)),
|
|
91
|
+
...(options.shapeUtils ?? []),
|
|
92
|
+
]
|
|
93
|
+
const bindingUtilsWithDefaults = [
|
|
94
|
+
...defaultBindingUtils.filter((b) => !options.bindingUtils?.some((bu) => bu.type === b.type)),
|
|
95
|
+
...(options.bindingUtils ?? []),
|
|
96
|
+
]
|
|
91
97
|
|
|
92
98
|
super({
|
|
93
99
|
...options,
|
|
@@ -12,6 +12,7 @@ beforeEach(() => {
|
|
|
12
12
|
},
|
|
13
13
|
})
|
|
14
14
|
editor.updateViewportScreenBounds(new Box(0, 0, 1600, 900))
|
|
15
|
+
editor.user.updateUserPreferences({ inputMode: null })
|
|
15
16
|
})
|
|
16
17
|
|
|
17
18
|
const wheelEvent = {
|
|
@@ -204,6 +205,18 @@ describe('CameraOptions.wheelBehavior', () => {
|
|
|
204
205
|
.forceTick()
|
|
205
206
|
expect(editor.getCamera()).toMatchObject({ x: 0, y: 5, z: 1 })
|
|
206
207
|
})
|
|
208
|
+
|
|
209
|
+
it('When input mode is set, camera wheel behavior is ignored', () => {
|
|
210
|
+
editor.user.updateUserPreferences({ inputMode: 'trackpad' })
|
|
211
|
+
editor
|
|
212
|
+
.setCameraOptions({ ...DEFAULT_CAMERA_OPTIONS, wheelBehavior: 'zoom' })
|
|
213
|
+
.dispatch({
|
|
214
|
+
...wheelEvent,
|
|
215
|
+
delta: new Vec(0, 5, 0.01),
|
|
216
|
+
})
|
|
217
|
+
.forceTick()
|
|
218
|
+
expect(editor.getCamera()).toMatchObject({ x: 0, y: 5, z: 1 })
|
|
219
|
+
})
|
|
207
220
|
})
|
|
208
221
|
|
|
209
222
|
describe('CameraOptions.panSpeed', () => {
|
package/src/test/frames.test.ts
CHANGED
|
@@ -1680,3 +1680,18 @@ it('drops into the top-most frame, if there is one', () => {
|
|
|
1680
1680
|
|
|
1681
1681
|
expect(editor.getShape(rect)?.parentId).toBe(editor.getCurrentPageId())
|
|
1682
1682
|
})
|
|
1683
|
+
|
|
1684
|
+
it('does not get drop children of nested frame if they are occluded from the outer frame', () => {
|
|
1685
|
+
const frame1Id = dragCreateFrame({ down: [100, 100], move: [300, 300], up: [300, 300] })
|
|
1686
|
+
const frame2Id = dragCreateFrame({ down: [150, 150], move: [290, 290], up: [290, 290] })
|
|
1687
|
+
|
|
1688
|
+
const rect1 = createRect({ pos: [280, 160], size: [10, 30] })
|
|
1689
|
+
|
|
1690
|
+
expect(editor.getShape(rect1)?.parentId).toBe(frame2Id)
|
|
1691
|
+
expect(editor.getShape(frame2Id)?.parentId).toBe(frame1Id)
|
|
1692
|
+
|
|
1693
|
+
editor.select(frame2Id)
|
|
1694
|
+
editor.translateSelection(30, 0)
|
|
1695
|
+
|
|
1696
|
+
expect(editor.getShape(rect1)?.parentId).toBe(frame2Id)
|
|
1697
|
+
})
|
package/tldraw.css
CHANGED
|
@@ -1964,7 +1964,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
1964
1964
|
min-height: 40px;
|
|
1965
1965
|
width: 100%;
|
|
1966
1966
|
gap: 8px;
|
|
1967
|
-
margin: -4px
|
|
1967
|
+
margin-top: -4px;
|
|
1968
1968
|
}
|
|
1969
1969
|
|
|
1970
1970
|
.tlui-button__menu::after {
|
|
@@ -2793,7 +2793,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
2793
2793
|
max-width: 148px;
|
|
2794
2794
|
}
|
|
2795
2795
|
|
|
2796
|
-
.tlui-style-panel[data-
|
|
2796
|
+
.tlui-style-panel[data-enhanced-a11y-mode='true'] .tlui-button[data-isactive='true'] {
|
|
2797
2797
|
border-radius: 10px;
|
|
2798
2798
|
outline: 2px solid var(--tl-color-text);
|
|
2799
2799
|
outline-offset: -5px;
|
|
@@ -2835,6 +2835,19 @@ tldraw? probably.
|
|
|
2835
2835
|
display: none;
|
|
2836
2836
|
}
|
|
2837
2837
|
|
|
2838
|
+
/*
|
|
2839
|
+
* This is used in a couple places, like Align and Vertical Align.
|
|
2840
|
+
* It's because we have a toolbar with a Toggle Group but then an adjacent button
|
|
2841
|
+
* next to it that opens a popup.
|
|
2842
|
+
*/
|
|
2843
|
+
.tlui-style-panel__section .tlui-toolbar:has(.tlui-toolbar) {
|
|
2844
|
+
flex-wrap: wrap;
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
.tlui-style-panel__section .tlui-toolbar:has(.tlui-toolbar) .tlui-style-panel__subheading {
|
|
2848
|
+
margin-left: -2px;
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2838
2851
|
.tlui-style-panel__section__common:not(:only-child) {
|
|
2839
2852
|
margin-bottom: 7px;
|
|
2840
2853
|
border-bottom: 1px solid var(--tl-color-divider);
|