tldraw 3.15.0-canary.d48536dd9c3c → 3.15.0-canary.d4fb9a9627c9

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 (83) 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/shapes/arrow/toolStates/Pointing.js +3 -0
  5. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  6. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +15 -1
  7. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  8. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
  9. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  10. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -1
  11. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  12. package/dist-cjs/lib/styles.js.map +2 -2
  13. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +43 -22
  14. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  15. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +8 -0
  16. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  17. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +8 -0
  18. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  19. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +8 -0
  20. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  21. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButtonIcon.js.map +2 -2
  22. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +35 -1
  23. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
  24. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  25. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  26. package/dist-cjs/lib/ui/context/actions.js.map +1 -1
  27. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  28. package/dist-cjs/lib/ui/version.js +3 -3
  29. package/dist-cjs/lib/ui/version.js.map +1 -1
  30. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +2 -1
  31. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  32. package/dist-esm/index.d.mts +39 -8
  33. package/dist-esm/index.mjs +4 -2
  34. package/dist-esm/index.mjs.map +2 -2
  35. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +3 -0
  36. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  37. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +15 -1
  38. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  39. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -1
  40. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  41. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -1
  42. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  43. package/dist-esm/lib/styles.mjs.map +2 -2
  44. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +43 -22
  45. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  46. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +8 -0
  47. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  48. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +8 -0
  49. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  50. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +8 -0
  51. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  52. package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButtonIcon.mjs.map +2 -2
  53. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +36 -2
  54. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
  55. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  56. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  57. package/dist-esm/lib/ui/context/actions.mjs.map +1 -1
  58. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  59. package/dist-esm/lib/ui/version.mjs +3 -3
  60. package/dist-esm/lib/ui/version.mjs.map +1 -1
  61. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +2 -1
  62. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  63. package/package.json +3 -3
  64. package/src/index.ts +5 -1
  65. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -0
  66. package/src/lib/shapes/line/LineShapeUtil.tsx +19 -2
  67. package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -1
  68. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -1
  69. package/src/lib/styles.tsx +3 -1
  70. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +54 -30
  71. package/src/lib/tools/SelectTool/childStates/Resizing.ts +12 -1
  72. package/src/lib/tools/SelectTool/childStates/Rotating.ts +11 -0
  73. package/src/lib/tools/SelectTool/childStates/Translating.ts +11 -0
  74. package/src/lib/ui/components/primitives/Button/TldrawUiButtonIcon.tsx +2 -2
  75. package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +41 -3
  76. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +2 -2
  77. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -2
  78. package/src/lib/ui/context/actions.tsx +1 -1
  79. package/src/lib/ui/hooks/useTools.tsx +2 -1
  80. package/src/lib/ui/version.ts +3 -3
  81. package/src/lib/utils/tldr/buildFromV1Document.ts +1 -0
  82. package/src/test/commands/deletePage.test.ts +84 -1
  83. package/src/test/shapeutils.test.ts +394 -45
@@ -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.d48536dd9c3c'
4
+ export const version = '3.15.0-canary.d4fb9a9627c9'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-07-16T14:24:26.375Z',
8
- patch: '2025-07-16T14:24:26.375Z',
7
+ minor: '2025-07-29T08:36:55.991Z',
8
+ patch: '2025-07-29T08:36:55.991Z',
9
9
  }
@@ -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
  })