tldraw 3.15.0-next.f1dfcef63951 → 3.15.1
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
|
@@ -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,
|
|
@@ -55,6 +55,7 @@ export type TLUiTranslationKey =
|
|
|
55
55
|
| 'action.new-project'
|
|
56
56
|
| 'action.new-shared-project'
|
|
57
57
|
| 'action.open-cursor-chat'
|
|
58
|
+
| 'action.open-kbd-shortcuts'
|
|
58
59
|
| 'action.open-file'
|
|
59
60
|
| 'action.pack'
|
|
60
61
|
| 'action.paste'
|
|
@@ -90,6 +91,8 @@ export type TLUiTranslationKey =
|
|
|
90
91
|
| 'action.toggle-wrap-mode'
|
|
91
92
|
| 'action.toggle-reduce-motion.menu'
|
|
92
93
|
| 'action.toggle-reduce-motion'
|
|
94
|
+
| 'action.toggle-keyboard-shortcuts.menu'
|
|
95
|
+
| 'action.toggle-keyboard-shortcuts'
|
|
93
96
|
| 'action.toggle-edge-scrolling.menu'
|
|
94
97
|
| 'action.toggle-edge-scrolling'
|
|
95
98
|
| 'action.toggle-debug-mode.menu'
|
|
@@ -288,6 +291,7 @@ export type TLUiTranslationKey =
|
|
|
288
291
|
| 'a11y.pan-camera'
|
|
289
292
|
| 'a11y.adjust-shape-styles'
|
|
290
293
|
| 'a11y.open-context-menu'
|
|
294
|
+
| 'a11y.open-keyboard-shortcuts'
|
|
291
295
|
| 'menu.title'
|
|
292
296
|
| 'menu.theme'
|
|
293
297
|
| 'menu.copy-as'
|
|
@@ -55,6 +55,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
55
55
|
'action.new-project': 'New project',
|
|
56
56
|
'action.new-shared-project': 'New shared project',
|
|
57
57
|
'action.open-cursor-chat': 'Cursor chat',
|
|
58
|
+
'action.open-kbd-shortcuts': 'Open keyboard shortcuts',
|
|
58
59
|
'action.open-file': 'Open file',
|
|
59
60
|
'action.pack': 'Pack',
|
|
60
61
|
'action.paste': 'Paste',
|
|
@@ -91,6 +92,8 @@ export const DEFAULT_TRANSLATION = {
|
|
|
91
92
|
'action.toggle-wrap-mode': 'Toggle Select on wrap',
|
|
92
93
|
'action.toggle-reduce-motion.menu': 'Reduce motion',
|
|
93
94
|
'action.toggle-reduce-motion': 'Toggle reduce motion',
|
|
95
|
+
'action.toggle-keyboard-shortcuts.menu': 'Keyboard shortcuts',
|
|
96
|
+
'action.toggle-keyboard-shortcuts': 'Toggle keyboard shortcuts',
|
|
94
97
|
'action.toggle-edge-scrolling.menu': 'Edge scrolling',
|
|
95
98
|
'action.toggle-edge-scrolling': 'Toggle edge scrolling',
|
|
96
99
|
'action.toggle-debug-mode.menu': 'Debug mode',
|
|
@@ -289,6 +292,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
289
292
|
'a11y.pan-camera': 'Pan camera',
|
|
290
293
|
'a11y.adjust-shape-styles': 'Adjust shape styles',
|
|
291
294
|
'a11y.open-context-menu': 'Open context menu',
|
|
295
|
+
'a11y.open-keyboard-shortcuts': 'Open keyboard shortcuts',
|
|
292
296
|
'menu.title': 'Menu',
|
|
293
297
|
'menu.theme': 'Theme',
|
|
294
298
|
'menu.copy-as': 'Copy as',
|
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.
|
|
4
|
+
export const version = '3.15.1'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-07-
|
|
8
|
-
patch: '2025-
|
|
7
|
+
minor: '2025-07-30T09:07:27.887Z',
|
|
8
|
+
patch: '2025-08-06T09:33:59.683Z',
|
|
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
|
}
|
package/src/test/Editor.test.tsx
CHANGED
|
@@ -49,7 +49,7 @@ beforeEach(() => {
|
|
|
49
49
|
})
|
|
50
50
|
|
|
51
51
|
const moveShapesToPage2 = () => {
|
|
52
|
-
// directly
|
|
52
|
+
// directly manipulate parentId like would happen in multiplayer situations
|
|
53
53
|
|
|
54
54
|
editor.updateShapes([
|
|
55
55
|
{ id: ids.box1, type: 'geo', parentId: ids.page2 },
|
|
@@ -899,3 +899,70 @@ describe('the geometry cache', () => {
|
|
|
899
899
|
expect(editor.getShapePageBounds(A)!.width).toBe(200)
|
|
900
900
|
})
|
|
901
901
|
})
|
|
902
|
+
describe('editor.getShapePageBounds', () => {
|
|
903
|
+
it('calculates axis aligned bounds correctly', () => {
|
|
904
|
+
editor.createShape({
|
|
905
|
+
type: 'geo',
|
|
906
|
+
x: 99,
|
|
907
|
+
y: 88,
|
|
908
|
+
props: {
|
|
909
|
+
w: 199,
|
|
910
|
+
h: 188,
|
|
911
|
+
},
|
|
912
|
+
})
|
|
913
|
+
const shape = editor.getLastCreatedShape()
|
|
914
|
+
expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
|
|
915
|
+
Box {
|
|
916
|
+
"h": 188,
|
|
917
|
+
"w": 199,
|
|
918
|
+
"x": 99,
|
|
919
|
+
"y": 88,
|
|
920
|
+
}
|
|
921
|
+
`)
|
|
922
|
+
})
|
|
923
|
+
|
|
924
|
+
it('calculates rotated bounds correctly', () => {
|
|
925
|
+
editor.createShape({
|
|
926
|
+
type: 'geo',
|
|
927
|
+
x: 99,
|
|
928
|
+
y: 88,
|
|
929
|
+
rotation: Math.PI / 4,
|
|
930
|
+
props: {
|
|
931
|
+
w: 199,
|
|
932
|
+
h: 188,
|
|
933
|
+
},
|
|
934
|
+
})
|
|
935
|
+
const shape = editor.getLastCreatedShape()
|
|
936
|
+
expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
|
|
937
|
+
Box {
|
|
938
|
+
"h": 273.65032431919394,
|
|
939
|
+
"w": 273.6503243191939,
|
|
940
|
+
"x": -33.93607486307093,
|
|
941
|
+
"y": 88,
|
|
942
|
+
}
|
|
943
|
+
`)
|
|
944
|
+
})
|
|
945
|
+
|
|
946
|
+
it('calculates bounds based on vertices, not corners', () => {
|
|
947
|
+
editor.createShape({
|
|
948
|
+
type: 'geo',
|
|
949
|
+
x: 99,
|
|
950
|
+
y: 88,
|
|
951
|
+
rotation: Math.PI / 4,
|
|
952
|
+
props: {
|
|
953
|
+
geo: 'ellipse',
|
|
954
|
+
w: 199,
|
|
955
|
+
h: 188,
|
|
956
|
+
},
|
|
957
|
+
})
|
|
958
|
+
const shape = editor.getLastCreatedShape()
|
|
959
|
+
expect(editor.getShapePageBounds(shape)!).toMatchInlineSnapshot(`
|
|
960
|
+
Box {
|
|
961
|
+
"h": 193.49999999999997,
|
|
962
|
+
"w": 193.50000000000003,
|
|
963
|
+
"x": 6.139087296526014,
|
|
964
|
+
"y": 128.07516215959694,
|
|
965
|
+
}
|
|
966
|
+
`)
|
|
967
|
+
})
|
|
968
|
+
})
|
|
@@ -414,6 +414,260 @@ describe('Shape navigation', () => {
|
|
|
414
414
|
expect(editor.getSelectedShapeIds()).toEqual([])
|
|
415
415
|
})
|
|
416
416
|
|
|
417
|
+
it('respects container boundaries when navigating with left/right', () => {
|
|
418
|
+
// Create a frame with shapes inside and shapes outside
|
|
419
|
+
editor.createShapes([
|
|
420
|
+
{
|
|
421
|
+
id: ids.frame1,
|
|
422
|
+
type: 'frame',
|
|
423
|
+
x: 0,
|
|
424
|
+
y: 0,
|
|
425
|
+
props: {
|
|
426
|
+
w: 200,
|
|
427
|
+
h: 200,
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
// Shapes inside frame
|
|
431
|
+
{
|
|
432
|
+
id: ids.box1,
|
|
433
|
+
type: 'geo',
|
|
434
|
+
x: 10,
|
|
435
|
+
y: 100,
|
|
436
|
+
parentId: ids.frame1,
|
|
437
|
+
props: {
|
|
438
|
+
w: 30,
|
|
439
|
+
h: 30,
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
id: ids.box2,
|
|
444
|
+
type: 'geo',
|
|
445
|
+
x: 50,
|
|
446
|
+
y: 100,
|
|
447
|
+
parentId: ids.frame1,
|
|
448
|
+
props: {
|
|
449
|
+
w: 30,
|
|
450
|
+
h: 30,
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
id: ids.box3,
|
|
455
|
+
type: 'geo',
|
|
456
|
+
x: 90,
|
|
457
|
+
y: 100,
|
|
458
|
+
parentId: ids.frame1,
|
|
459
|
+
props: {
|
|
460
|
+
w: 30,
|
|
461
|
+
h: 30,
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
// Shapes outside frame
|
|
465
|
+
{
|
|
466
|
+
id: ids.box4,
|
|
467
|
+
type: 'geo',
|
|
468
|
+
x: 300,
|
|
469
|
+
y: 100,
|
|
470
|
+
props: {
|
|
471
|
+
w: 30,
|
|
472
|
+
h: 30,
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: ids.box5,
|
|
477
|
+
type: 'geo',
|
|
478
|
+
x: 350,
|
|
479
|
+
y: 100,
|
|
480
|
+
props: {
|
|
481
|
+
w: 30,
|
|
482
|
+
h: 30,
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
])
|
|
486
|
+
|
|
487
|
+
// Setup shape centers for consistent testing
|
|
488
|
+
jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
|
|
489
|
+
const positions = {
|
|
490
|
+
[ids.box1]: { x: 25, y: 115 },
|
|
491
|
+
[ids.box2]: { x: 65, y: 115 },
|
|
492
|
+
[ids.box3]: { x: 105, y: 115 },
|
|
493
|
+
[ids.box4]: { x: 315, y: 115 },
|
|
494
|
+
[ids.box5]: { x: 365, y: 115 },
|
|
495
|
+
}
|
|
496
|
+
const pos = positions[shape?.id as keyof typeof positions]
|
|
497
|
+
return pos ? ({ center: pos } as any) : ({ center: { x: 0, y: 0 } } as any)
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
// Select a shape inside the frame
|
|
501
|
+
editor.select(ids.box1)
|
|
502
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
|
|
503
|
+
|
|
504
|
+
// Navigate right - should stay within the frame
|
|
505
|
+
editor.selectAdjacentShape('right')
|
|
506
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
|
|
507
|
+
|
|
508
|
+
// Continue navigating right - should still stay within the frame
|
|
509
|
+
editor.selectAdjacentShape('right')
|
|
510
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box3])
|
|
511
|
+
|
|
512
|
+
// Navigate right again - should not leave the frame to go to box4
|
|
513
|
+
editor.selectAdjacentShape('right')
|
|
514
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box3]) // Should stay at box3
|
|
515
|
+
|
|
516
|
+
// Now navigate left to test the other direction
|
|
517
|
+
editor.selectAdjacentShape('left')
|
|
518
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
|
|
519
|
+
|
|
520
|
+
editor.selectAdjacentShape('left')
|
|
521
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
|
|
522
|
+
|
|
523
|
+
// Navigate left again - should not leave the frame
|
|
524
|
+
editor.selectAdjacentShape('left')
|
|
525
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1]) // Should stay at box1
|
|
526
|
+
|
|
527
|
+
// Now test navigation outside the frame
|
|
528
|
+
editor.select(ids.box4)
|
|
529
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box4])
|
|
530
|
+
|
|
531
|
+
// Navigate right - should move to box5
|
|
532
|
+
editor.selectAdjacentShape('right')
|
|
533
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box5])
|
|
534
|
+
|
|
535
|
+
// Navigate left - should move back to box4
|
|
536
|
+
editor.selectAdjacentShape('left')
|
|
537
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box4])
|
|
538
|
+
|
|
539
|
+
// Navigate left again - should select the frame (nearest shape to the left)
|
|
540
|
+
editor.selectAdjacentShape('left')
|
|
541
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.frame1]) // Should select frame1
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
it('respects container boundaries when navigating with up/down', () => {
|
|
545
|
+
// Create a frame with shapes inside and shapes outside
|
|
546
|
+
editor.createShapes([
|
|
547
|
+
{
|
|
548
|
+
id: ids.frame1,
|
|
549
|
+
type: 'frame',
|
|
550
|
+
x: 0,
|
|
551
|
+
y: 0,
|
|
552
|
+
props: {
|
|
553
|
+
w: 200,
|
|
554
|
+
h: 200,
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
// Shapes inside frame - vertically arranged
|
|
558
|
+
{
|
|
559
|
+
id: ids.box1,
|
|
560
|
+
type: 'geo',
|
|
561
|
+
x: 100,
|
|
562
|
+
y: 10,
|
|
563
|
+
parentId: ids.frame1,
|
|
564
|
+
props: {
|
|
565
|
+
w: 30,
|
|
566
|
+
h: 30,
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: ids.box2,
|
|
571
|
+
type: 'geo',
|
|
572
|
+
x: 100,
|
|
573
|
+
y: 50,
|
|
574
|
+
parentId: ids.frame1,
|
|
575
|
+
props: {
|
|
576
|
+
w: 30,
|
|
577
|
+
h: 30,
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
id: ids.box3,
|
|
582
|
+
type: 'geo',
|
|
583
|
+
x: 100,
|
|
584
|
+
y: 90,
|
|
585
|
+
parentId: ids.frame1,
|
|
586
|
+
props: {
|
|
587
|
+
w: 30,
|
|
588
|
+
h: 30,
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
// Shapes outside frame - vertically arranged
|
|
592
|
+
{
|
|
593
|
+
id: ids.box4,
|
|
594
|
+
type: 'geo',
|
|
595
|
+
x: 300,
|
|
596
|
+
y: 10,
|
|
597
|
+
props: {
|
|
598
|
+
w: 30,
|
|
599
|
+
h: 30,
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
id: ids.box5,
|
|
604
|
+
type: 'geo',
|
|
605
|
+
x: 300,
|
|
606
|
+
y: 50,
|
|
607
|
+
props: {
|
|
608
|
+
w: 30,
|
|
609
|
+
h: 30,
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
])
|
|
613
|
+
|
|
614
|
+
// Setup shape centers for consistent testing
|
|
615
|
+
jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
|
|
616
|
+
const positions = {
|
|
617
|
+
[ids.box1]: { x: 115, y: 25 },
|
|
618
|
+
[ids.box2]: { x: 115, y: 65 },
|
|
619
|
+
[ids.box3]: { x: 115, y: 105 },
|
|
620
|
+
[ids.box4]: { x: 315, y: 25 },
|
|
621
|
+
[ids.box5]: { x: 315, y: 65 },
|
|
622
|
+
}
|
|
623
|
+
const pos = positions[shape?.id as keyof typeof positions]
|
|
624
|
+
return pos ? ({ center: pos } as any) : ({ center: { x: 0, y: 0 } } as any)
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
// Select a shape inside the frame
|
|
628
|
+
editor.select(ids.box1)
|
|
629
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
|
|
630
|
+
|
|
631
|
+
// Navigate down - should stay within the frame
|
|
632
|
+
editor.selectAdjacentShape('down')
|
|
633
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
|
|
634
|
+
|
|
635
|
+
// Continue navigating down - should still stay within the frame
|
|
636
|
+
editor.selectAdjacentShape('down')
|
|
637
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box3])
|
|
638
|
+
|
|
639
|
+
// Navigate down again - should not leave the frame
|
|
640
|
+
editor.selectAdjacentShape('down')
|
|
641
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box3]) // Should stay at box3
|
|
642
|
+
|
|
643
|
+
// Now navigate up to test the other direction
|
|
644
|
+
editor.selectAdjacentShape('up')
|
|
645
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
|
|
646
|
+
|
|
647
|
+
editor.selectAdjacentShape('up')
|
|
648
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
|
|
649
|
+
|
|
650
|
+
// Navigate up again - should not leave the frame
|
|
651
|
+
editor.selectAdjacentShape('up')
|
|
652
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box1]) // Should stay at box1
|
|
653
|
+
|
|
654
|
+
// Now test navigation outside the frame
|
|
655
|
+
editor.select(ids.box4)
|
|
656
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box4])
|
|
657
|
+
|
|
658
|
+
// Navigate down - should move to box5
|
|
659
|
+
editor.selectAdjacentShape('down')
|
|
660
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box5])
|
|
661
|
+
|
|
662
|
+
// Navigate up - should move back to box4
|
|
663
|
+
editor.selectAdjacentShape('up')
|
|
664
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box4])
|
|
665
|
+
|
|
666
|
+
// Navigate up again - should not enter the frame
|
|
667
|
+
editor.selectAdjacentShape('up')
|
|
668
|
+
expect(editor.getSelectedShapeIds()).toEqual([ids.box4]) // Should stay at box4
|
|
669
|
+
})
|
|
670
|
+
|
|
417
671
|
it('respects container boundaries when navigating with Tab', () => {
|
|
418
672
|
// Create a frame with shapes inside and shapes outside
|
|
419
673
|
editor.createShapes([
|
package/tldraw.css
CHANGED
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
--color-text: hsl(0, 0%, 0%);
|
|
172
172
|
--color-text-0: hsl(0, 0%, 11%);
|
|
173
173
|
--color-text-1: hsl(0, 0%, 18%);
|
|
174
|
-
--color-text-3: hsl(
|
|
174
|
+
--color-text-3: hsl(204, 4%, 45%);
|
|
175
175
|
--color-text-shadow: hsl(0, 0%, 100%);
|
|
176
176
|
--color-text-highlight: hsl(52, 100%, 50%);
|
|
177
177
|
--color-text-highlight-p3: color(display-p3 0.972 0.8205 0.05);
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
--color-text: hsl(210, 17%, 98%);
|
|
227
227
|
--color-text-0: hsl(0, 9%, 94%);
|
|
228
228
|
--color-text-1: hsl(0, 0%, 85%);
|
|
229
|
-
--color-text-3: hsl(
|
|
229
|
+
--color-text-3: hsl(204, 4%, 75%);
|
|
230
230
|
--color-text-shadow: hsl(210, 13%, 18%);
|
|
231
231
|
--color-text-highlight: hsl(52, 100%, 41%);
|
|
232
232
|
--color-text-highlight-p3: color(display-p3 0.8078 0.6225 0.0312);
|
|
@@ -972,14 +972,14 @@ input,
|
|
|
972
972
|
font-size: 14px;
|
|
973
973
|
font-weight: 500;
|
|
974
974
|
opacity: 0;
|
|
975
|
-
animation: fade-in 0.2s ease-in-out forwards;
|
|
975
|
+
animation: tl-fade-in 0.2s ease-in-out forwards;
|
|
976
976
|
animation-delay: 0.2s;
|
|
977
977
|
position: absolute;
|
|
978
978
|
inset: 0px;
|
|
979
979
|
z-index: var(--layer-canvas-blocker);
|
|
980
980
|
}
|
|
981
981
|
|
|
982
|
-
@keyframes fade-in {
|
|
982
|
+
@keyframes tl-fade-in {
|
|
983
983
|
0% {
|
|
984
984
|
opacity: 0;
|
|
985
985
|
}
|
|
@@ -988,6 +988,19 @@ input,
|
|
|
988
988
|
}
|
|
989
989
|
}
|
|
990
990
|
|
|
991
|
+
.tl-spinner {
|
|
992
|
+
animation: tl-spin 1s linear infinite;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
@keyframes tl-spin {
|
|
996
|
+
0% {
|
|
997
|
+
transform: rotate(0deg);
|
|
998
|
+
}
|
|
999
|
+
100% {
|
|
1000
|
+
transform: rotate(360deg);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
991
1004
|
/* ---------------------- Brush --------------------- */
|
|
992
1005
|
|
|
993
1006
|
.tl-brush {
|
|
@@ -2748,7 +2761,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
2748
2761
|
justify-content: center;
|
|
2749
2762
|
border-radius: 99px;
|
|
2750
2763
|
opacity: 0;
|
|
2751
|
-
animation: fade-in;
|
|
2764
|
+
animation: tl-fade-in;
|
|
2752
2765
|
animation-duration: 0.12s;
|
|
2753
2766
|
animation-delay: 2s;
|
|
2754
2767
|
animation-fill-mode: forwards;
|
|
@@ -2892,20 +2905,6 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
2892
2905
|
display: none;
|
|
2893
2906
|
}
|
|
2894
2907
|
|
|
2895
|
-
.tlui-navigation-panel__toggle .tlui-icon {
|
|
2896
|
-
opacity: 0.24;
|
|
2897
|
-
}
|
|
2898
|
-
|
|
2899
|
-
.tlui-navigation-panel__toggle:active .tlui-icon {
|
|
2900
|
-
opacity: 1;
|
|
2901
|
-
}
|
|
2902
|
-
|
|
2903
|
-
@media (hover: hover) {
|
|
2904
|
-
.tlui-navigation-panel__toggle:hover .tlui-icon {
|
|
2905
|
-
opacity: 1;
|
|
2906
|
-
}
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
2908
|
/* Minimap */
|
|
2910
2909
|
|
|
2911
2910
|
.tlui-minimap {
|
|
@@ -3163,11 +3162,11 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3163
3162
|
|
|
3164
3163
|
@media (prefers-reduced-motion: no-preference) {
|
|
3165
3164
|
.tlui-toast__container[data-state='open'] {
|
|
3166
|
-
animation: slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
|
3165
|
+
animation: tlui-slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
|
3167
3166
|
}
|
|
3168
3167
|
|
|
3169
3168
|
.tlui-toast__container[data-state='closed'] {
|
|
3170
|
-
animation:
|
|
3169
|
+
animation: tlui-fade-out 100ms ease-in;
|
|
3171
3170
|
}
|
|
3172
3171
|
|
|
3173
3172
|
.tlui-toast__container[data-swipe='move'] {
|
|
@@ -3180,7 +3179,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3180
3179
|
}
|
|
3181
3180
|
|
|
3182
3181
|
.tlui-toast__container[data-swipe='end'] {
|
|
3183
|
-
animation:
|
|
3182
|
+
animation: tlui-slide-out 100ms ease-out;
|
|
3184
3183
|
}
|
|
3185
3184
|
}
|
|
3186
3185
|
|
|
@@ -3195,7 +3194,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3195
3194
|
z-index: var(--layer-canvas-overlays);
|
|
3196
3195
|
background-color: var(--color-overlay);
|
|
3197
3196
|
pointer-events: all;
|
|
3198
|
-
animation:
|
|
3197
|
+
animation: tl-fade-in 0.12s ease-out;
|
|
3199
3198
|
display: grid;
|
|
3200
3199
|
place-items: center;
|
|
3201
3200
|
overflow-y: auto;
|
|
@@ -3762,7 +3761,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3762
3761
|
}
|
|
3763
3762
|
|
|
3764
3763
|
/* ------------------- Animations ------------------- */
|
|
3765
|
-
@keyframes
|
|
3764
|
+
@keyframes tlui-fade-out {
|
|
3766
3765
|
0% {
|
|
3767
3766
|
opacity: 1;
|
|
3768
3767
|
}
|
|
@@ -3771,7 +3770,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3771
3770
|
}
|
|
3772
3771
|
}
|
|
3773
3772
|
|
|
3774
|
-
@keyframes slide-in {
|
|
3773
|
+
@keyframes tlui-slide-in {
|
|
3775
3774
|
from {
|
|
3776
3775
|
transform: translateX(calc(100% + var(--space-3)));
|
|
3777
3776
|
}
|
|
@@ -3780,7 +3779,7 @@ it from receiving any pointer events or affecting the cursor. */
|
|
|
3780
3779
|
}
|
|
3781
3780
|
}
|
|
3782
3781
|
|
|
3783
|
-
@keyframes
|
|
3782
|
+
@keyframes tlui-slide-out {
|
|
3784
3783
|
from {
|
|
3785
3784
|
transform: translateX(var(--radix-toast-swipe-end-x));
|
|
3786
3785
|
}
|