@tldraw/editor 3.16.0-canary.e9c30b532b82 → 3.16.0-canary.eb9a487b3293

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 (146) hide show
  1. package/dist-cjs/index.d.ts +54 -101
  2. package/dist-cjs/index.js +1 -5
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +5 -5
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/Shape.js +7 -10
  7. package/dist-cjs/lib/components/Shape.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  12. package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
  13. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  14. package/dist-cjs/lib/editor/Editor.js +41 -110
  15. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  16. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -1
  17. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  18. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  19. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  21. package/dist-cjs/lib/exports/getSvgJsx.js +34 -14
  22. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  23. package/dist-cjs/lib/hooks/useCanvasEvents.js +7 -5
  24. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  25. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
  26. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  27. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  28. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  29. package/dist-cjs/lib/license/LicenseManager.js +17 -22
  30. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  31. package/dist-cjs/lib/license/LicenseProvider.js +5 -0
  32. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  33. package/dist-cjs/lib/license/Watermark.js +4 -4
  34. package/dist-cjs/lib/license/Watermark.js.map +1 -1
  35. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  36. package/dist-cjs/lib/options.js +6 -0
  37. package/dist-cjs/lib/options.js.map +2 -2
  38. package/dist-cjs/lib/primitives/Box.js +3 -0
  39. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  40. package/dist-cjs/lib/primitives/Vec.js +0 -4
  41. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  42. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +26 -18
  43. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  44. package/dist-cjs/lib/primitives/geometry/Group2d.js +3 -0
  45. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  46. package/dist-cjs/lib/utils/reparenting.js +2 -35
  47. package/dist-cjs/lib/utils/reparenting.js.map +3 -3
  48. package/dist-cjs/version.js +3 -3
  49. package/dist-cjs/version.js.map +1 -1
  50. package/dist-esm/index.d.mts +54 -101
  51. package/dist-esm/index.mjs +1 -5
  52. package/dist-esm/index.mjs.map +2 -2
  53. package/dist-esm/lib/TldrawEditor.mjs +5 -5
  54. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  55. package/dist-esm/lib/components/Shape.mjs +7 -10
  56. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  57. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
  58. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  59. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  60. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  61. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
  62. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  63. package/dist-esm/lib/editor/Editor.mjs +41 -110
  64. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  65. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -1
  66. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  67. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  68. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  69. package/dist-esm/lib/exports/getSvgJsx.mjs +34 -14
  70. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  71. package/dist-esm/lib/hooks/useCanvasEvents.mjs +7 -5
  72. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  73. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
  74. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  75. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  76. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  77. package/dist-esm/lib/license/LicenseManager.mjs +17 -22
  78. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  79. package/dist-esm/lib/license/LicenseProvider.mjs +5 -0
  80. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  81. package/dist-esm/lib/license/Watermark.mjs +4 -4
  82. package/dist-esm/lib/license/Watermark.mjs.map +1 -1
  83. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  84. package/dist-esm/lib/options.mjs +6 -0
  85. package/dist-esm/lib/options.mjs.map +2 -2
  86. package/dist-esm/lib/primitives/Box.mjs +4 -1
  87. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  88. package/dist-esm/lib/primitives/Vec.mjs +0 -4
  89. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  90. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +29 -19
  91. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  92. package/dist-esm/lib/primitives/geometry/Group2d.mjs +3 -0
  93. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  94. package/dist-esm/lib/utils/reparenting.mjs +3 -40
  95. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  96. package/dist-esm/version.mjs +3 -3
  97. package/dist-esm/version.mjs.map +1 -1
  98. package/editor.css +8 -0
  99. package/package.json +14 -37
  100. package/src/index.ts +1 -9
  101. package/src/lib/TldrawEditor.tsx +6 -12
  102. package/src/lib/components/Shape.tsx +6 -12
  103. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
  104. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  105. package/src/lib/config/TLUserPreferences.ts +1 -1
  106. package/src/lib/editor/Editor.test.ts +12 -11
  107. package/src/lib/editor/Editor.ts +49 -147
  108. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  109. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  110. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  111. package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
  112. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  113. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  114. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  115. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  116. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  117. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +21 -26
  118. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
  119. package/src/lib/editor/shapes/ShapeUtil.ts +35 -0
  120. package/src/lib/editor/types/misc-types.ts +0 -6
  121. package/src/lib/exports/getSvgJsx.test.ts +868 -0
  122. package/src/lib/exports/getSvgJsx.tsx +76 -19
  123. package/src/lib/hooks/useCanvasEvents.ts +6 -6
  124. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
  125. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  126. package/src/lib/license/LicenseManager.test.ts +61 -52
  127. package/src/lib/license/LicenseManager.ts +32 -24
  128. package/src/lib/license/LicenseProvider.tsx +8 -0
  129. package/src/lib/license/Watermark.test.tsx +2 -1
  130. package/src/lib/license/Watermark.tsx +4 -4
  131. package/src/lib/license/useLicenseManagerState.ts +2 -2
  132. package/src/lib/options.ts +6 -0
  133. package/src/lib/primitives/Box.test.ts +126 -0
  134. package/src/lib/primitives/Box.ts +10 -1
  135. package/src/lib/primitives/Vec.ts +0 -5
  136. package/src/lib/primitives/geometry/Geometry2d.ts +49 -19
  137. package/src/lib/primitives/geometry/Group2d.ts +4 -0
  138. package/src/lib/utils/reparenting.ts +3 -69
  139. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  140. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  141. package/src/version.ts +3 -3
  142. package/dist-cjs/lib/utils/nearestMultiple.js +0 -34
  143. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  144. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  145. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  146. package/src/lib/utils/nearestMultiple.ts +0 -13
@@ -1,28 +1,29 @@
1
+ import { Mock, Mocked, vi } from 'vitest'
1
2
  import { Vec } from '../../../primitives/Vec'
2
3
  import { Editor } from '../../Editor'
3
4
  import { TickManager } from './TickManager'
4
5
 
5
6
  // Mock the Editor class
6
- jest.mock('../../Editor')
7
+ vi.mock('../../Editor')
7
8
 
8
9
  // Mock Date.now to control time
9
- const mockDateNow = jest.fn()
10
+ const mockDateNow = vi.fn()
10
11
  Date.now = mockDateNow
11
12
 
12
13
  // Mock requestAnimationFrame and cancelAnimationFrame
13
- const mockRequestAnimationFrame = jest.fn()
14
- const mockCancelAnimationFrame = jest.fn()
14
+ const mockRequestAnimationFrame = vi.fn()
15
+ const mockCancelAnimationFrame = vi.fn()
15
16
  global.requestAnimationFrame = mockRequestAnimationFrame
16
17
  global.cancelAnimationFrame = mockCancelAnimationFrame
17
18
 
18
19
  describe('TickManager', () => {
19
- let editor: jest.Mocked<Editor>
20
+ let editor: Mocked<Editor>
20
21
  let tickManager: TickManager
21
- let mockEmit: jest.Mock
22
- let mockDisposablesAdd: jest.Mock
22
+ let mockEmit: Mock
23
+ let mockDisposablesAdd: Mock
23
24
 
24
25
  beforeEach(() => {
25
- jest.clearAllMocks()
26
+ vi.clearAllMocks()
26
27
 
27
28
  // Reset time
28
29
  mockDateNow.mockReturnValue(1000)
@@ -37,8 +38,8 @@ describe('TickManager', () => {
37
38
 
38
39
  mockCancelAnimationFrame.mockImplementation(() => {})
39
40
 
40
- mockEmit = jest.fn()
41
- mockDisposablesAdd = jest.fn()
41
+ mockEmit = vi.fn()
42
+ mockDisposablesAdd = vi.fn()
42
43
 
43
44
  editor = {
44
45
  emit: mockEmit,
@@ -90,7 +91,7 @@ describe('TickManager', () => {
90
91
  })
91
92
 
92
93
  it('should cancel existing RAF before starting new one', () => {
93
- const mockCancel = jest.fn()
94
+ const mockCancel = vi.fn()
94
95
  tickManager.cancelRaf = mockCancel
95
96
 
96
97
  tickManager.start()
@@ -143,7 +144,7 @@ describe('TickManager', () => {
143
144
  })
144
145
 
145
146
  it('should update pointer velocity', () => {
146
- const updatePointerVelocitySpy = jest.spyOn(tickManager as any, 'updatePointerVelocity')
147
+ const updatePointerVelocitySpy = vi.spyOn(tickManager as any, 'updatePointerVelocity')
147
148
  tickManager.now = 1000
148
149
  mockDateNow.mockReturnValue(1016)
149
150
 
@@ -176,7 +177,7 @@ describe('TickManager', () => {
176
177
  })
177
178
 
178
179
  it('should cancel RAF if exists', () => {
179
- const mockCancel = jest.fn()
180
+ const mockCancel = vi.fn()
180
181
  tickManager.cancelRaf = mockCancel
181
182
 
182
183
  tickManager.dispose()
@@ -1,17 +1,15 @@
1
1
  import { atom } from '@tldraw/state'
2
+ import { Mocked, vi } from 'vitest'
2
3
  import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
3
4
  import { TLUser } from '../../../config/createTLUser'
4
5
  import { UserPreferencesManager } from './UserPreferencesManager'
5
6
 
6
7
  // Mock window.matchMedia
7
- const mockMatchMedia = jest.fn()
8
- Object.defineProperty(window, 'matchMedia', {
9
- writable: true,
10
- value: mockMatchMedia,
11
- })
8
+ const mockMatchMedia = vi.fn()
9
+ window.matchMedia = mockMatchMedia
12
10
 
13
11
  describe('UserPreferencesManager', () => {
14
- let mockUser: jest.Mocked<TLUser>
12
+ let mockUser: Mocked<TLUser>
15
13
  let mockUserPreferences: TLUserPreferences
16
14
  let userPreferencesAtom: any
17
15
  let userPreferencesManager: UserPreferencesManager
@@ -36,14 +34,14 @@ describe('UserPreferencesManager', () => {
36
34
  })
37
35
 
38
36
  beforeEach(() => {
39
- jest.clearAllMocks()
37
+ vi.clearAllMocks()
40
38
 
41
39
  mockUserPreferences = createMockUserPreferences()
42
40
  userPreferencesAtom = atom('userPreferences', mockUserPreferences)
43
41
 
44
42
  mockUser = {
45
43
  userPreferences: userPreferencesAtom,
46
- setUserPreferences: jest.fn((prefs) => {
44
+ setUserPreferences: vi.fn((prefs) => {
47
45
  userPreferencesAtom.set(prefs)
48
46
  }),
49
47
  }
@@ -51,8 +49,8 @@ describe('UserPreferencesManager', () => {
51
49
  // Default matchMedia mock - no dark mode preference
52
50
  mockMatchMedia.mockReturnValue({
53
51
  matches: false,
54
- addEventListener: jest.fn(),
55
- removeEventListener: jest.fn(),
52
+ addEventListener: vi.fn(),
53
+ removeEventListener: vi.fn(),
56
54
  })
57
55
  })
58
56
 
@@ -66,17 +64,14 @@ describe('UserPreferencesManager', () => {
66
64
  expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
67
65
 
68
66
  // Restore matchMedia
69
- Object.defineProperty(window, 'matchMedia', {
70
- writable: true,
71
- value: mockMatchMedia,
72
- })
67
+ window.matchMedia = mockMatchMedia
73
68
  })
74
69
 
75
70
  it('should initialize with light system color scheme when dark mode not preferred', () => {
76
71
  mockMatchMedia.mockReturnValue({
77
72
  matches: false,
78
- addEventListener: jest.fn(),
79
- removeEventListener: jest.fn(),
73
+ addEventListener: vi.fn(),
74
+ removeEventListener: vi.fn(),
80
75
  })
81
76
 
82
77
  userPreferencesManager = new UserPreferencesManager(mockUser, false)
@@ -87,8 +82,8 @@ describe('UserPreferencesManager', () => {
87
82
  it('should initialize with dark system color scheme when dark mode preferred', () => {
88
83
  mockMatchMedia.mockReturnValue({
89
84
  matches: true,
90
- addEventListener: jest.fn(),
91
- removeEventListener: jest.fn(),
85
+ addEventListener: vi.fn(),
86
+ removeEventListener: vi.fn(),
92
87
  })
93
88
 
94
89
  userPreferencesManager = new UserPreferencesManager(mockUser, false)
@@ -97,8 +92,8 @@ describe('UserPreferencesManager', () => {
97
92
  })
98
93
 
99
94
  it('should set up media query listener for color scheme changes', () => {
100
- const mockAddEventListener = jest.fn()
101
- const mockRemoveEventListener = jest.fn()
95
+ const mockAddEventListener = vi.fn()
96
+ const mockRemoveEventListener = vi.fn()
102
97
 
103
98
  mockMatchMedia.mockReturnValue({
104
99
  matches: false,
@@ -112,7 +107,7 @@ describe('UserPreferencesManager', () => {
112
107
  })
113
108
 
114
109
  it('should handle media query change events', () => {
115
- const mockAddEventListener = jest.fn()
110
+ const mockAddEventListener = vi.fn()
116
111
  let changeHandler: (e: MediaQueryListEvent) => void
117
112
 
118
113
  mockMatchMedia.mockReturnValue({
@@ -123,7 +118,7 @@ describe('UserPreferencesManager', () => {
123
118
  }
124
119
  mockAddEventListener(event, handler)
125
120
  },
126
- removeEventListener: jest.fn(),
121
+ removeEventListener: vi.fn(),
127
122
  })
128
123
 
129
124
  userPreferencesManager = new UserPreferencesManager(mockUser, false)
@@ -153,11 +148,11 @@ describe('UserPreferencesManager', () => {
153
148
 
154
149
  describe('dispose', () => {
155
150
  it('should remove media query listener on dispose', () => {
156
- const mockRemoveEventListener = jest.fn()
151
+ const mockRemoveEventListener = vi.fn()
157
152
 
158
153
  mockMatchMedia.mockReturnValue({
159
154
  matches: false,
160
- addEventListener: jest.fn(),
155
+ addEventListener: vi.fn(),
161
156
  removeEventListener: mockRemoveEventListener,
162
157
  })
163
158
 
@@ -170,8 +165,8 @@ describe('UserPreferencesManager', () => {
170
165
  it('should call all disposables', () => {
171
166
  userPreferencesManager = new UserPreferencesManager(mockUser, false)
172
167
 
173
- const mockDisposable1 = jest.fn()
174
- const mockDisposable2 = jest.fn()
168
+ const mockDisposable1 = vi.fn()
169
+ const mockDisposable2 = vi.fn()
175
170
 
176
171
  userPreferencesManager.disposables.add(mockDisposable1)
177
172
  userPreferencesManager.disposables.add(mockDisposable2)
@@ -13,7 +13,7 @@ export class UserPreferencesManager {
13
13
  private readonly user: TLUser,
14
14
  private readonly inferDarkMode: boolean
15
15
  ) {
16
- if (typeof window === 'undefined' || !('matchMedia' in window)) return
16
+ if (typeof window === 'undefined' || !window.matchMedia) return
17
17
 
18
18
  const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
19
19
  if (darkModeMediaQuery?.matches) {
@@ -296,6 +296,27 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
296
296
  return false
297
297
  }
298
298
 
299
+ /**
300
+ * Get the clip path to apply to this shape's children.
301
+ *
302
+ * @param shape - The shape to get the clip path for
303
+ * @returns Array of points defining the clipping polygon in local coordinates, or undefined if no clipping
304
+ * @public
305
+ */
306
+ getClipPath?(shape: Shape): Vec[] | undefined
307
+
308
+ /**
309
+ * Whether a specific child shape should be clipped by this shape.
310
+ * Only called if getClipPath returns a valid polygon.
311
+ *
312
+ * If not defined, the default behavior is to clip all children.
313
+ *
314
+ * @param child - The child shape to check
315
+ * @returns boolean indicating if this child should be clipped
316
+ * @public
317
+ */
318
+ shouldClipChild?(child: TLShape): boolean
319
+
299
320
  /**
300
321
  * Whether the shape should hide its resize handles when selected.
301
322
  *
@@ -341,6 +362,20 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
341
362
  return false
342
363
  }
343
364
 
365
+ /**
366
+ * By default, the bounds of an image export are the bounds of all the shapes it contains, plus
367
+ * some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
368
+ * padding is skipped _if the bounds of that shape contains all the other shapes_. This is
369
+ * useful in cases like annotating on top of an image, where you usually want to avoid extra
370
+ * padding around the image if you don't need it.
371
+ *
372
+ * @param _shape - The shape to check
373
+ * @returns True if this shape should be treated as an export bounds container
374
+ */
375
+ isExportBoundsContainer(_shape: Shape): boolean {
376
+ return false
377
+ }
378
+
344
379
  /**
345
380
  * Get a JSX element for the shape (as an HTML element) to be rendered as part of the canvas background - behind any other shape content.
346
381
  *
@@ -72,12 +72,6 @@ export interface TLImageExportOptions extends TLSvgExportOptions {
72
72
  format?: TLExportType
73
73
  }
74
74
 
75
- /**
76
- * @public
77
- * @deprecated use {@link TLImageExportOptions} instead
78
- */
79
- export type TLSvgOptions = TLImageExportOptions
80
-
81
75
  /** @public */
82
76
  export interface TLCameraMoveOptions {
83
77
  /** Whether to move the camera immediately, rather than on the next tick. */