tldraw 3.15.0-canary.e3f6387b7e04 → 3.15.0-canary.ef2f8fce47e3

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.
Files changed (121) hide show
  1. package/dist-cjs/index.d.ts +39 -8
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawImage.js +5 -2
  5. package/dist-cjs/lib/TldrawImage.js.map +3 -3
  6. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  7. package/dist-cjs/lib/canvas/TldrawCropHandles.js.map +2 -2
  8. package/dist-cjs/lib/canvas/TldrawHandles.js +1 -1
  9. package/dist-cjs/lib/canvas/TldrawHandles.js.map +2 -2
  10. package/dist-cjs/lib/canvas/TldrawOverlays.js +1 -1
  11. package/dist-cjs/lib/canvas/TldrawOverlays.js.map +2 -2
  12. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +279 -271
  13. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  14. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
  15. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  16. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +15 -1
  17. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -0
  19. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  20. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -0
  21. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  22. package/dist-cjs/lib/styles.js.map +2 -2
  23. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +43 -22
  24. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  25. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +8 -0
  26. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  27. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +8 -0
  28. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  29. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +8 -0
  30. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  31. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +3 -4
  32. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  33. package/dist-cjs/lib/ui/components/Spinner.js +2 -25
  34. package/dist-cjs/lib/ui/components/Spinner.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButtonIcon.js.map +2 -2
  36. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +35 -1
  37. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  39. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  40. package/dist-cjs/lib/ui/context/actions.js.map +1 -1
  41. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  42. package/dist-cjs/lib/ui/version.js +3 -3
  43. package/dist-cjs/lib/ui/version.js.map +1 -1
  44. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +2 -1
  45. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  46. package/dist-esm/index.d.mts +39 -8
  47. package/dist-esm/index.mjs +4 -2
  48. package/dist-esm/index.mjs.map +2 -2
  49. package/dist-esm/lib/TldrawImage.mjs +5 -2
  50. package/dist-esm/lib/TldrawImage.mjs.map +2 -2
  51. package/dist-esm/lib/canvas/TldrawCropHandles.mjs +1 -1
  52. package/dist-esm/lib/canvas/TldrawCropHandles.mjs.map +2 -2
  53. package/dist-esm/lib/canvas/TldrawHandles.mjs +1 -1
  54. package/dist-esm/lib/canvas/TldrawHandles.mjs.map +2 -2
  55. package/dist-esm/lib/canvas/TldrawOverlays.mjs +1 -1
  56. package/dist-esm/lib/canvas/TldrawOverlays.mjs.map +2 -2
  57. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +279 -271
  58. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  59. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +3 -0
  60. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  61. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +15 -1
  62. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  63. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -0
  64. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  65. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -0
  66. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  67. package/dist-esm/lib/styles.mjs.map +2 -2
  68. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +43 -22
  69. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  70. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +8 -0
  71. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  72. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +8 -0
  73. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  74. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +8 -0
  75. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  76. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +3 -4
  77. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  78. package/dist-esm/lib/ui/components/Spinner.mjs +3 -26
  79. package/dist-esm/lib/ui/components/Spinner.mjs.map +2 -2
  80. package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButtonIcon.mjs.map +2 -2
  81. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +36 -2
  82. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
  83. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  84. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  85. package/dist-esm/lib/ui/context/actions.mjs.map +1 -1
  86. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  87. package/dist-esm/lib/ui/version.mjs +3 -3
  88. package/dist-esm/lib/ui/version.mjs.map +1 -1
  89. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +2 -1
  90. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  91. package/package.json +4 -3
  92. package/src/index.ts +5 -1
  93. package/src/lib/TldrawImage.tsx +6 -2
  94. package/src/lib/canvas/TldrawCropHandles.tsx +1 -1
  95. package/src/lib/canvas/TldrawHandles.tsx +5 -1
  96. package/src/lib/canvas/TldrawOverlays.tsx +1 -1
  97. package/src/lib/canvas/TldrawSelectionForeground.tsx +5 -1
  98. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -0
  99. package/src/lib/shapes/line/LineShapeUtil.tsx +19 -2
  100. package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -0
  101. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -0
  102. package/src/lib/styles.tsx +3 -1
  103. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +54 -30
  104. package/src/lib/tools/SelectTool/childStates/Resizing.ts +12 -1
  105. package/src/lib/tools/SelectTool/childStates/Rotating.ts +11 -0
  106. package/src/lib/tools/SelectTool/childStates/Translating.ts +11 -0
  107. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +3 -4
  108. package/src/lib/ui/components/Spinner.tsx +2 -24
  109. package/src/lib/ui/components/primitives/Button/TldrawUiButtonIcon.tsx +2 -2
  110. package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +41 -3
  111. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +2 -2
  112. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -2
  113. package/src/lib/ui/context/actions.tsx +1 -1
  114. package/src/lib/ui/hooks/useTools.tsx +2 -1
  115. package/src/lib/ui/version.ts +3 -3
  116. package/src/lib/ui.css +8 -22
  117. package/src/lib/utils/tldr/buildFromV1Document.ts +1 -0
  118. package/src/test/commands/deletePage.test.ts +84 -1
  119. package/src/test/navigation.test.ts +254 -0
  120. package/src/test/shapeutils.test.ts +394 -45
  121. package/tldraw.css +25 -26
@@ -122,8 +122,19 @@ export class Resizing extends StateNode {
122
122
  }
123
123
 
124
124
  private cancel() {
125
- // Restore initial models
125
+ // Call onResizeCancel callback before resetting
126
+ const { shapeSnapshots } = this.snapshot
127
+
128
+ shapeSnapshots.forEach(({ shape }) => {
129
+ const current = this.editor.getShape(shape.id)
130
+ if (current) {
131
+ const util = this.editor.getShapeUtil(shape)
132
+ util.onResizeCancel?.(shape, current)
133
+ }
134
+ })
135
+
126
136
  this.editor.bailToMark(this.markId)
137
+
127
138
  if (this.info.onInteractionEnd) {
128
139
  this.editor.setCurrentTool(this.info.onInteractionEnd, {})
129
140
  } else {
@@ -109,6 +109,17 @@ export class Rotating extends StateNode {
109
109
  }
110
110
 
111
111
  private cancel() {
112
+ // Call onRotateCancel callback before bailing to mark
113
+ const { shapeSnapshots } = this.snapshot
114
+
115
+ shapeSnapshots.forEach(({ shape }) => {
116
+ const current = this.editor.getShape(shape.id)
117
+ if (current) {
118
+ const util = this.editor.getShapeUtil(shape)
119
+ util.onRotateCancel?.(shape, current)
120
+ }
121
+ })
122
+
112
123
  this.editor.bailToMark(this.markId)
113
124
  if (this.info.onInteractionEnd) {
114
125
  this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
@@ -203,6 +203,17 @@ export class Translating extends StateNode {
203
203
  }
204
204
 
205
205
  private cancel() {
206
+ // Call onTranslateCancel callback before resetting
207
+ const { movingShapes } = this.snapshot
208
+
209
+ movingShapes.forEach((shape) => {
210
+ const current = this.editor.getShape(shape.id)
211
+ if (current) {
212
+ const util = this.editor.getShapeUtil(shape)
213
+ util.onTranslateCancel?.(shape, current)
214
+ }
215
+ })
216
+
206
217
  this.reset()
207
218
  if (this.info.onInteractionEnd) {
208
219
  this.editor.setCurrentTool(this.info.onInteractionEnd)
@@ -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 ? 'chevrons-ne' : 'chevrons-sw'} />
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
  }
@@ -1,8 +1,8 @@
1
- import { TldrawUiIcon } from '../TldrawUiIcon'
1
+ import { TldrawUiIcon, TLUiIconJsx } from '../TldrawUiIcon'
2
2
 
3
3
  /** @public */
4
4
  export interface TLUiButtonIconProps {
5
- icon: string
5
+ icon: string | TLUiIconJsx
6
6
  small?: boolean
7
7
  invertIcon?: boolean
8
8
  }
@@ -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
+ }
@@ -5,7 +5,7 @@ import { TLUiEventSource } from '../../../context/events'
5
5
  import { useReadonly } from '../../../hooks/useReadonly'
6
6
  import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
7
7
  import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
8
- import { TldrawUiIcon } from '../TldrawUiIcon'
8
+ import { TldrawUiIcon, TLUiIconJsx } from '../TldrawUiIcon'
9
9
  import { TldrawUiKbd } from '../TldrawUiKbd'
10
10
  import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
11
11
 
@@ -14,7 +14,7 @@ export interface TLUiMenuCheckboxItemProps<
14
14
  TranslationKey extends string = string,
15
15
  IconType extends string = string,
16
16
  > {
17
- icon?: IconType
17
+ icon?: IconType | TLUiIconJsx
18
18
  id: string
19
19
  kbd?: string
20
20
  title?: string
@@ -12,6 +12,7 @@ import { TldrawUiButton } from '../Button/TldrawUiButton'
12
12
  import { TldrawUiButtonIcon } from '../Button/TldrawUiButtonIcon'
13
13
  import { TldrawUiButtonLabel } from '../Button/TldrawUiButtonLabel'
14
14
  import { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'
15
+ import { TLUiIconJsx } from '../TldrawUiIcon'
15
16
  import { TldrawUiKbd } from '../TldrawUiKbd'
16
17
  import { TldrawUiToolbarButton } from '../TldrawUiToolbar'
17
18
  import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
@@ -25,11 +26,11 @@ export interface TLUiMenuItemProps<
25
26
  /**
26
27
  * The icon to display on the item. Icons are only shown in certain menu types.
27
28
  */
28
- icon?: IconType
29
+ icon?: IconType | TLUiIconJsx
29
30
  /**
30
31
  * An icon to display to the left of the menu item.
31
32
  */
32
- iconLeft?: IconType
33
+ iconLeft?: IconType | TLUiIconJsx
33
34
  /**
34
35
  * The keyboard shortcut to display on the item.
35
36
  */
@@ -43,7 +43,7 @@ export interface TLUiActionItem<
43
43
  TransationKey extends string = string,
44
44
  IconType extends string = string,
45
45
  > {
46
- icon?: IconType
46
+ icon?: IconType | React.ReactElement
47
47
  id: string
48
48
  kbd?: string
49
49
  label?: TransationKey | { [key: string]: TransationKey }
@@ -1,6 +1,7 @@
1
1
  import { Editor, GeoShapeGeoStyle, useMaybeEditor } from '@tldraw/editor'
2
2
  import * as React from 'react'
3
3
  import { EmbedDialog } from '../components/EmbedDialog'
4
+ import { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'
4
5
  import { useA11y } from '../context/a11y'
5
6
  import { TLUiEventSource, useUiEvents } from '../context/events'
6
7
  import { TLUiIconType } from '../icon-types'
@@ -16,7 +17,7 @@ export interface TLUiToolItem<
16
17
  id: string
17
18
  label: TranslationKey
18
19
  shortcutsLabel?: TranslationKey
19
- icon: IconType
20
+ icon: IconType | TLUiIconJsx
20
21
  onSelect(source: TLUiEventSource): void
21
22
  /**
22
23
  * The keyboard shortcut for this tool. This is a string that can be a single key,
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.15.0-canary.e3f6387b7e04'
4
+ export const version = '3.15.0-canary.ef2f8fce47e3'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-07-14T11:01:29.466Z',
8
- patch: '2025-07-14T11:01:29.466Z',
7
+ minor: '2025-07-28T14:10:47.467Z',
8
+ patch: '2025-07-28T14:10:47.467Z',
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: hide 100ms ease-in;
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: swipe-out 100ms ease-out;
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: fadeIn 0.12s ease-out;
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 hide {
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 swipe-out {
1985
+ @keyframes tlui-slide-out {
2000
1986
  from {
2001
1987
  transform: translateX(var(--radix-toast-swipe-end-x));
2002
1988
  }
@@ -562,6 +562,7 @@ export function buildFromV1Document(editor: Editor, _document: unknown) {
562
562
  y: point.y,
563
563
  },
564
564
  isPrecise: point.x !== 0.5 || point.y !== 0.5,
565
+ isCreatingShape: true,
565
566
  })
566
567
 
567
568
  if (change) {
@@ -1,4 +1,4 @@
1
- import { PageRecordType } from '@tldraw/editor'
1
+ import { PageRecordType, createShapeId } from '@tldraw/editor'
2
2
  import { TestEditor } from '../TestEditor'
3
3
 
4
4
  let editor: TestEditor
@@ -76,4 +76,87 @@ describe('deletePage', () => {
76
76
  expect(editor.getCurrentPageId()).not.toBe(currentPageId)
77
77
  expect(editor.getCurrentPageId()).toBe(editor.getPages()[0].id)
78
78
  })
79
+
80
+ it('deletes all shapes that belong to the deleted page', () => {
81
+ // Create a second page
82
+ const page2Id = PageRecordType.createId('page2')
83
+ editor.createPage({ name: 'Page 2', id: page2Id })
84
+
85
+ // Switch to the second page
86
+ editor.setCurrentPage(page2Id)
87
+
88
+ // Add some shapes to the second page
89
+ const shape1Id = createShapeId('shape1')
90
+ const shape2Id = createShapeId('shape2')
91
+ const shape3Id = createShapeId('shape3')
92
+
93
+ editor.createShape({ id: shape1Id, type: 'text', x: 100, y: 100 })
94
+ editor.createShape({ id: shape2Id, type: 'geo', x: 200, y: 200, props: { geo: 'rectangle' } })
95
+ editor.createShape({ id: shape3Id, type: 'geo', x: 300, y: 300, props: { geo: 'ellipse' } })
96
+
97
+ // Verify shapes were created and belong to the second page
98
+ expect(editor.getShape(shape1Id)).toBeDefined()
99
+ expect(editor.getShape(shape2Id)).toBeDefined()
100
+ expect(editor.getShape(shape3Id)).toBeDefined()
101
+ expect(editor.getShape(shape1Id)?.parentId).toBe(page2Id)
102
+ expect(editor.getShape(shape2Id)?.parentId).toBe(page2Id)
103
+ expect(editor.getShape(shape3Id)?.parentId).toBe(page2Id)
104
+
105
+ // Delete the second page
106
+ editor.deletePage(page2Id)
107
+
108
+ // Verify the page was deleted
109
+ expect(editor.getPages().length).toBe(1)
110
+ expect(editor.getPages()[0].id).not.toBe(page2Id)
111
+
112
+ // Verify all shapes that belonged to the deleted page were also deleted
113
+ expect(editor.getShape(shape1Id)).toBeUndefined()
114
+ expect(editor.getShape(shape2Id)).toBeUndefined()
115
+ expect(editor.getShape(shape3Id)).toBeUndefined()
116
+ })
117
+
118
+ it('deletes locked shapes that belong to the deleted page', () => {
119
+ // Create a second page
120
+ const page2Id = PageRecordType.createId('page2')
121
+ editor.createPage({ name: 'Page 2', id: page2Id })
122
+
123
+ // Switch to the second page
124
+ editor.setCurrentPage(page2Id)
125
+
126
+ // Add some shapes to the second page
127
+ const shape1Id = createShapeId('shape1')
128
+ const shape2Id = createShapeId('shape2')
129
+ const shape3Id = createShapeId('shape3')
130
+
131
+ editor.createShape({ id: shape1Id, type: 'text', x: 100, y: 100 })
132
+ editor.createShape({ id: shape2Id, type: 'geo', x: 200, y: 200, props: { geo: 'rectangle' } })
133
+ editor.createShape({ id: shape3Id, type: 'geo', x: 300, y: 300, props: { geo: 'ellipse' } })
134
+
135
+ // Lock some of the shapes
136
+ editor.updateShape({ id: shape1Id, type: 'text', isLocked: true })
137
+ editor.updateShape({ id: shape2Id, type: 'geo', isLocked: true })
138
+
139
+ // Verify shapes were created and belong to the second page
140
+ expect(editor.getShape(shape1Id)).toBeDefined()
141
+ expect(editor.getShape(shape2Id)).toBeDefined()
142
+ expect(editor.getShape(shape3Id)).toBeDefined()
143
+ expect(editor.getShape(shape1Id)?.parentId).toBe(page2Id)
144
+ expect(editor.getShape(shape2Id)?.parentId).toBe(page2Id)
145
+ expect(editor.getShape(shape3Id)?.parentId).toBe(page2Id)
146
+ expect(editor.getShape(shape1Id)?.isLocked).toBe(true)
147
+ expect(editor.getShape(shape2Id)?.isLocked).toBe(true)
148
+ expect(editor.getShape(shape3Id)?.isLocked).toBe(false)
149
+
150
+ // Delete the second page
151
+ editor.deletePage(page2Id)
152
+
153
+ // Verify the page was deleted
154
+ expect(editor.getPages().length).toBe(1)
155
+ expect(editor.getPages()[0].id).not.toBe(page2Id)
156
+
157
+ // Verify all shapes that belonged to the deleted page were also deleted, including locked ones
158
+ expect(editor.getShape(shape1Id)).toBeUndefined()
159
+ expect(editor.getShape(shape2Id)).toBeUndefined()
160
+ expect(editor.getShape(shape3Id)).toBeUndefined()
161
+ })
79
162
  })