@tldraw/editor 3.16.0-next.df90ce0ff566 → 3.16.0-next.e57e478c23e0

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 (175) hide show
  1. package/dist-cjs/index.d.ts +134 -110
  2. package/dist-cjs/index.js +3 -5
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +8 -6
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/Shape.js +7 -10
  9. package/dist-cjs/lib/components/Shape.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
  11. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
  14. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  17. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  19. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  20. package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
  21. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  22. package/dist-cjs/lib/editor/Editor.js +77 -133
  23. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +9 -4
  25. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  27. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  29. package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
  30. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  31. package/dist-cjs/lib/hooks/useCanvasEvents.js +31 -25
  32. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  33. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
  34. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  35. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  36. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  37. package/dist-cjs/lib/{utils/nearestMultiple.js → hooks/useStateAttribute.js} +15 -14
  38. package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
  39. package/dist-cjs/lib/license/LicenseManager.js +17 -22
  40. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  41. package/dist-cjs/lib/license/LicenseProvider.js +5 -0
  42. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  43. package/dist-cjs/lib/license/Watermark.js +8 -8
  44. package/dist-cjs/lib/license/Watermark.js.map +1 -1
  45. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  46. package/dist-cjs/lib/options.js +7 -0
  47. package/dist-cjs/lib/options.js.map +2 -2
  48. package/dist-cjs/lib/primitives/Box.js +3 -0
  49. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  50. package/dist-cjs/lib/primitives/Vec.js +0 -4
  51. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  52. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +26 -18
  53. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  54. package/dist-cjs/lib/primitives/geometry/Group2d.js +3 -0
  55. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  56. package/dist-cjs/lib/utils/EditorAtom.js +45 -0
  57. package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
  58. package/dist-cjs/lib/utils/reparenting.js +2 -35
  59. package/dist-cjs/lib/utils/reparenting.js.map +3 -3
  60. package/dist-cjs/version.js +3 -3
  61. package/dist-cjs/version.js.map +1 -1
  62. package/dist-esm/index.d.mts +134 -110
  63. package/dist-esm/index.mjs +3 -5
  64. package/dist-esm/index.mjs.map +2 -2
  65. package/dist-esm/lib/TldrawEditor.mjs +8 -6
  66. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  67. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  68. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  69. package/dist-esm/lib/components/Shape.mjs +7 -10
  70. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  71. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
  72. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  73. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  74. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
  75. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  76. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  77. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  78. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  79. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  80. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  81. package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
  82. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  83. package/dist-esm/lib/editor/Editor.mjs +77 -133
  84. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  85. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +9 -4
  86. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  87. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  88. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  89. package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
  90. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  91. package/dist-esm/lib/hooks/useCanvasEvents.mjs +32 -26
  92. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  93. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
  94. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  95. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  96. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  97. package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
  98. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
  99. package/dist-esm/lib/license/LicenseManager.mjs +17 -22
  100. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  101. package/dist-esm/lib/license/LicenseProvider.mjs +5 -0
  102. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  103. package/dist-esm/lib/license/Watermark.mjs +8 -8
  104. package/dist-esm/lib/license/Watermark.mjs.map +1 -1
  105. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  106. package/dist-esm/lib/options.mjs +7 -0
  107. package/dist-esm/lib/options.mjs.map +2 -2
  108. package/dist-esm/lib/primitives/Box.mjs +4 -1
  109. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  110. package/dist-esm/lib/primitives/Vec.mjs +0 -4
  111. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  112. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +29 -19
  113. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  114. package/dist-esm/lib/primitives/geometry/Group2d.mjs +3 -0
  115. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  116. package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
  117. package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
  118. package/dist-esm/lib/utils/reparenting.mjs +3 -40
  119. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  120. package/dist-esm/version.mjs +3 -3
  121. package/dist-esm/version.mjs.map +1 -1
  122. package/editor.css +301 -288
  123. package/package.json +14 -37
  124. package/src/index.ts +3 -9
  125. package/src/lib/TldrawEditor.tsx +13 -17
  126. package/src/lib/components/MenuClickCapture.tsx +0 -8
  127. package/src/lib/components/Shape.tsx +6 -12
  128. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
  129. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  130. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  131. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  132. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
  133. package/src/lib/config/TLUserPreferences.ts +8 -1
  134. package/src/lib/editor/Editor.test.ts +12 -11
  135. package/src/lib/editor/Editor.ts +108 -193
  136. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  137. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  138. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  139. package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
  140. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  141. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  142. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  143. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  144. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  145. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +34 -26
  146. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +6 -1
  147. package/src/lib/editor/shapes/ShapeUtil.ts +35 -0
  148. package/src/lib/editor/types/misc-types.ts +54 -7
  149. package/src/lib/exports/getSvgJsx.test.ts +868 -0
  150. package/src/lib/exports/getSvgJsx.tsx +78 -21
  151. package/src/lib/hooks/useCanvasEvents.ts +45 -38
  152. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
  153. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  154. package/src/lib/hooks/useStateAttribute.ts +15 -0
  155. package/src/lib/license/LicenseManager.test.ts +61 -52
  156. package/src/lib/license/LicenseManager.ts +32 -24
  157. package/src/lib/license/LicenseProvider.tsx +8 -0
  158. package/src/lib/license/Watermark.test.tsx +2 -1
  159. package/src/lib/license/Watermark.tsx +8 -8
  160. package/src/lib/license/useLicenseManagerState.ts +2 -2
  161. package/src/lib/options.ts +8 -0
  162. package/src/lib/primitives/Box.test.ts +126 -0
  163. package/src/lib/primitives/Box.ts +10 -1
  164. package/src/lib/primitives/Vec.ts +0 -5
  165. package/src/lib/primitives/geometry/Geometry2d.ts +49 -19
  166. package/src/lib/primitives/geometry/Group2d.ts +4 -0
  167. package/src/lib/utils/EditorAtom.ts +37 -0
  168. package/src/lib/utils/reparenting.ts +3 -69
  169. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  170. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  171. package/src/version.ts +3 -3
  172. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  173. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  174. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  175. package/src/lib/utils/nearestMultiple.ts +0 -13
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/editor",
3
3
  "description": "tldraw infinite canvas SDK (editor).",
4
- "version": "3.16.0-next.df90ce0ff566",
4
+ "version": "3.16.0-next.e57e478c23e0",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -34,27 +34,28 @@
34
34
  "src"
35
35
  ],
36
36
  "scripts": {
37
- "test-ci": "lazy inherit",
38
- "test": "yarn run -T jest",
37
+ "test-ci": "yarn run -T vitest run --passWithNoTests",
38
+ "test": "yarn run -T vitest --passWithNoTests",
39
39
  "benchmark": "yarn run -T tsx ./internal/scripts/benchmark.ts",
40
- "test-coverage": "lazy inherit",
40
+ "test-coverage": "yarn run -T vitest run --coverage --passWithNoTests",
41
41
  "build": "yarn run -T tsx ../../internal/scripts/build-package.ts",
42
42
  "build-api": "yarn run -T tsx ../../internal/scripts/build-api.ts",
43
43
  "prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
44
44
  "postpack": "../../internal/scripts/postpack.sh",
45
45
  "pack-tarball": "yarn pack",
46
- "lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
46
+ "lint": "yarn run -T tsx ../../internal/scripts/lint.ts",
47
+ "context": "yarn run -T tsx ../../internal/scripts/context.ts"
47
48
  },
48
49
  "dependencies": {
49
50
  "@tiptap/core": "^2.9.1",
50
51
  "@tiptap/pm": "^2.9.1",
51
52
  "@tiptap/react": "^2.9.1",
52
- "@tldraw/state": "3.16.0-next.df90ce0ff566",
53
- "@tldraw/state-react": "3.16.0-next.df90ce0ff566",
54
- "@tldraw/store": "3.16.0-next.df90ce0ff566",
55
- "@tldraw/tlschema": "3.16.0-next.df90ce0ff566",
56
- "@tldraw/utils": "3.16.0-next.df90ce0ff566",
57
- "@tldraw/validate": "3.16.0-next.df90ce0ff566",
53
+ "@tldraw/state": "3.16.0-next.e57e478c23e0",
54
+ "@tldraw/state-react": "3.16.0-next.e57e478c23e0",
55
+ "@tldraw/store": "3.16.0-next.e57e478c23e0",
56
+ "@tldraw/tlschema": "3.16.0-next.e57e478c23e0",
57
+ "@tldraw/utils": "3.16.0-next.e57e478c23e0",
58
+ "@tldraw/validate": "3.16.0-next.e57e478c23e0",
58
59
  "@types/core-js": "^2.5.8",
59
60
  "@use-gesture/react": "^10.3.1",
60
61
  "classnames": "^2.5.1",
@@ -69,41 +70,17 @@
69
70
  },
70
71
  "devDependencies": {
71
72
  "@peculiar/webcrypto": "^1.5.0",
72
- "@testing-library/jest-dom": "^5.17.0",
73
73
  "@testing-library/react": "^15.0.7",
74
74
  "@types/benchmark": "^2.1.5",
75
75
  "@types/react": "^18.3.18",
76
76
  "@types/wicg-file-system-access": "^2020.9.8",
77
77
  "benchmark": "^2.1.4",
78
78
  "fake-indexeddb": "^4.0.2",
79
- "jest-canvas-mock": "^2.5.2",
80
- "jest-environment-jsdom": "^29.7.0",
81
79
  "lazyrepo": "0.0.0-alpha.27",
82
80
  "react": "^18.3.1",
83
81
  "react-dom": "^18.3.1",
84
- "resize-observer-polyfill": "^1.5.1"
85
- },
86
- "jest": {
87
- "preset": "../../internal/config/jest/node/jest-preset.js",
88
- "testEnvironment": "../../../packages/utils/patchedJestJsDom.js",
89
- "fakeTimers": {
90
- "enableGlobally": true
91
- },
92
- "testPathIgnorePatterns": [
93
- "^.+\\.*.css$"
94
- ],
95
- "moduleNameMapper": {
96
- "^~(.*)": "<rootDir>/src/$1",
97
- "\\.(css|less|scss|sass)$": "identity-obj-proxy"
98
- },
99
- "setupFiles": [
100
- "raf/polyfill",
101
- "jest-canvas-mock",
102
- "<rootDir>/setupTests.js"
103
- ],
104
- "setupFilesAfterEnv": [
105
- "../../internal/config/setupJest.ts"
106
- ]
82
+ "resize-observer-polyfill": "^1.5.1",
83
+ "vitest": "^3.2.4"
107
84
  },
108
85
  "module": "dist-esm/index.mjs",
109
86
  "source": "src/index.ts",
package/src/index.ts CHANGED
@@ -265,9 +265,9 @@ export {
265
265
  type TLCameraMoveOptions,
266
266
  type TLCameraOptions,
267
267
  type TLExportType,
268
+ type TLGetShapeAtPointOptions,
268
269
  type TLImageExportOptions,
269
270
  type TLSvgExportOptions,
270
- type TLSvgOptions,
271
271
  type TLUpdatePointerOptions,
272
272
  } from './lib/editor/types/misc-types'
273
273
  export {
@@ -330,6 +330,7 @@ export {
330
330
  type InvalidLicenseReason,
331
331
  type LicenseFromKeyResult,
332
332
  type LicenseInfo,
333
+ type LicenseState,
333
334
  type TestEnvironment,
334
335
  type ValidLicenseKeyResult,
335
336
  } from './lib/license/LicenseManager'
@@ -450,6 +451,7 @@ export {
450
451
  setPointerCapture,
451
452
  stopEventPropagation,
452
453
  } from './lib/utils/dom'
454
+ export { EditorAtom } from './lib/utils/EditorAtom'
453
455
  export { getIncrementedName } from './lib/utils/getIncrementedName'
454
456
  export { getPointerInfo } from './lib/utils/getPointerInfo'
455
457
  export { getSvgPathFromPoints } from './lib/utils/getSvgPathFromPoints'
@@ -483,14 +485,6 @@ export { type TLStoreWithStatus } from './lib/utils/sync/StoreWithStatus'
483
485
  export { uniq } from './lib/utils/uniq'
484
486
  export { openWindow } from './lib/utils/window-open'
485
487
 
486
- /**
487
- * @deprecated Licensing is now enabled in the tldraw SDK.
488
- * @public */
489
- export function debugEnableLicensing() {
490
- // noop
491
- return
492
- }
493
-
494
488
  registerTldrawLibraryVersion(
495
489
  (globalThis as any).TLDRAW_LIBRARY_NAME,
496
490
  (globalThis as any).TLDRAW_LIBRARY_VERSION,
@@ -1,9 +1,9 @@
1
1
  import { MigrationSequence, Store } from '@tldraw/store'
2
2
  import { TLShape, TLStore, TLStoreSnapshot } from '@tldraw/tlschema'
3
- import { Required, annotateError } from '@tldraw/utils'
3
+ import { annotateError, Required } from '@tldraw/utils'
4
4
  import React, {
5
- ReactNode,
6
5
  memo,
6
+ ReactNode,
7
7
  useCallback,
8
8
  useEffect,
9
9
  useLayoutEffect,
@@ -15,13 +15,13 @@ import React, {
15
15
 
16
16
  import classNames from 'classnames'
17
17
  import { version } from '../version'
18
- import { OptionalErrorBoundary } from './components/ErrorBoundary'
19
18
  import { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback'
20
- import { TLEditorSnapshot } from './config/TLEditorSnapshot'
19
+ import { OptionalErrorBoundary } from './components/ErrorBoundary'
21
20
  import { TLStoreBaseOptions } from './config/createTLStore'
22
- import { TLUser, createTLUser } from './config/createTLUser'
21
+ import { createTLUser, TLUser } from './config/createTLUser'
23
22
  import { TLAnyBindingUtilConstructor } from './config/defaultBindings'
24
23
  import { TLAnyShapeUtilConstructor } from './config/defaultShapes'
24
+ import { TLEditorSnapshot } from './config/TLEditorSnapshot'
25
25
  import { Editor } from './editor/Editor'
26
26
  import { TLStateNodeConstructor } from './editor/tools/StateNode'
27
27
  import { TLCameraOptions } from './editor/types/misc-types'
@@ -39,6 +39,7 @@ import { useForceUpdate } from './hooks/useForceUpdate'
39
39
  import { useShallowObjectIdentity } from './hooks/useIdentity'
40
40
  import { useLocalStore } from './hooks/useLocalStore'
41
41
  import { useRefState } from './hooks/useRefState'
42
+ import { useStateAttribute } from './hooks/useStateAttribute'
42
43
  import { useZoomCss } from './hooks/useZoomCss'
43
44
  import { LicenseProvider } from './license/LicenseProvider'
44
45
  import { Watermark } from './license/Watermark'
@@ -188,13 +189,6 @@ export interface TldrawEditorBaseProps {
188
189
  */
189
190
  deepLinks?: true | TLDeepLinkOptions
190
191
 
191
- /**
192
- * Predicate for whether or not a shape should be hidden.
193
- *
194
- * @deprecated Use {@link TldrawEditorBaseProps#getShapeVisibility} instead.
195
- */
196
- isShapeHidden?(shape: TLShape, editor: Editor): boolean
197
-
198
192
  /**
199
193
  * Provides a way to hide shapes.
200
194
  *
@@ -411,8 +405,6 @@ function TldrawEditorWithReadyStore({
411
405
  options,
412
406
  licenseKey,
413
407
  deepLinks: _deepLinks,
414
- // eslint-disable-next-line @typescript-eslint/no-deprecated
415
- isShapeHidden,
416
408
  getShapeVisibility,
417
409
  assetUrls,
418
410
  }: Required<
@@ -472,7 +464,6 @@ function TldrawEditorWithReadyStore({
472
464
  textOptions,
473
465
  options,
474
466
  licenseKey,
475
- isShapeHidden,
476
467
  getShapeVisibility,
477
468
  fontAssetUrls: assetUrls?.fonts,
478
469
  })
@@ -508,7 +499,6 @@ function TldrawEditorWithReadyStore({
508
499
  user,
509
500
  setEditor,
510
501
  licenseKey,
511
- isShapeHidden,
512
502
  getShapeVisibility,
513
503
  textOptions,
514
504
  assetUrls,
@@ -585,8 +575,13 @@ function TldrawEditorWithReadyStore({
585
575
  if (editor !== fontLoadingState?.editor) {
586
576
  fontLoadingState = null
587
577
  }
588
- useEffect(() => {
578
+ useLayoutEffect(() => {
589
579
  if (!editor) return
580
+ if (editor.options.maxFontsToLoadBeforeRender === 0) {
581
+ setFontLoadingState({ editor, isLoaded: true })
582
+ return
583
+ }
584
+
590
585
  let isCancelled = false
591
586
 
592
587
  setFontLoadingState({ editor, isLoaded: false })
@@ -646,6 +641,7 @@ function Layout({ children, onMount }: { children: ReactNode; onMount?: TLOnMoun
646
641
  useCursor()
647
642
  useDarkMode()
648
643
  useForceUpdate()
644
+ useStateAttribute()
649
645
  useOnMount((editor) => {
650
646
  const teardownStore = editor.store.props.onMount(editor)
651
647
  const teardownCallback = onMount?.(editor)
@@ -50,12 +50,6 @@ export function MenuClickCapture() {
50
50
  // Do nothing unless we're pointing
51
51
  if (!rPointerState.current.isDown) return
52
52
 
53
- // If we're already dragging, pass on the event as it is
54
- if (rPointerState.current.isDragging) {
55
- canvasEvents.onPointerMove?.(e)
56
- return
57
- }
58
-
59
53
  if (
60
54
  // We're pointing, but are we dragging?
61
55
  Vec.Dist2(rPointerState.current.start, new Vec(e.clientX, e.clientY)) >
@@ -75,8 +69,6 @@ export function MenuClickCapture() {
75
69
  clientY: y,
76
70
  button: 0,
77
71
  })
78
- // call the pointer move with the current pointer position
79
- canvasEvents.onPointerMove?.(e)
80
72
  }
81
73
  },
82
74
  [canvasEvents, editor]
@@ -28,7 +28,6 @@ export const Shape = memo(function Shape({
28
28
  index,
29
29
  backgroundIndex,
30
30
  opacity,
31
- dprMultiple,
32
31
  }: {
33
32
  id: TLShapeId
34
33
  shape: TLShape
@@ -36,7 +35,6 @@ export const Shape = memo(function Shape({
36
35
  index: number
37
36
  backgroundIndex: number
38
37
  opacity: number
39
- dprMultiple: number
40
38
  }) {
41
39
  const editor = useEditor()
42
40
 
@@ -91,18 +89,14 @@ export const Shape = memo(function Shape({
91
89
  }
92
90
 
93
91
  // Width / Height
94
- // We round the shape width and height up to the nearest multiple of dprMultiple
95
- // to avoid the browser making miscalculations when applying the transform.
96
- const widthRemainder = bounds.w % dprMultiple
97
- const heightRemainder = bounds.h % dprMultiple
98
- const width = widthRemainder === 0 ? bounds.w : bounds.w + (dprMultiple - widthRemainder)
99
- const height = heightRemainder === 0 ? bounds.h : bounds.h + (dprMultiple - heightRemainder)
92
+ const width = Math.max(bounds.width, 1)
93
+ const height = Math.max(bounds.height, 1)
100
94
 
101
95
  if (width !== prev.width || height !== prev.height) {
102
- setStyleProperty(containerRef.current, 'width', Math.max(width, dprMultiple) + 'px')
103
- setStyleProperty(containerRef.current, 'height', Math.max(height, dprMultiple) + 'px')
104
- setStyleProperty(bgContainerRef.current, 'width', Math.max(width, dprMultiple) + 'px')
105
- setStyleProperty(bgContainerRef.current, 'height', Math.max(height, dprMultiple) + 'px')
96
+ setStyleProperty(containerRef.current, 'width', width + 'px')
97
+ setStyleProperty(containerRef.current, 'height', height + 'px')
98
+ setStyleProperty(bgContainerRef.current, 'width', width + 'px')
99
+ setStyleProperty(bgContainerRef.current, 'height', height + 'px')
106
100
  prev.width = width
107
101
  prev.height = height
108
102
  }
@@ -22,7 +22,6 @@ import { Vec } from '../../primitives/Vec'
22
22
  import { toDomPrecision } from '../../primitives/utils'
23
23
  import { debugFlags } from '../../utils/debug-flags'
24
24
  import { setStyleProperty } from '../../utils/dom'
25
- import { nearestMultiple } from '../../utils/nearestMultiple'
26
25
  import { GeometryDebuggingView } from '../GeometryDebuggingView'
27
26
  import { LiveCollaborators } from '../LiveCollaborators'
28
27
  import { MenuClickCapture } from '../MenuClickCapture'
@@ -173,10 +172,12 @@ export function DefaultCanvas({ className }: TLCanvasComponentProps) {
173
172
  <LiveCollaborators />
174
173
  </div>
175
174
  </div>
175
+ <div className="tl-canvas__in-front">
176
+ <InFrontOfTheCanvasWrapper />
177
+ </div>
176
178
  <MovingCameraHitTestBlocker />
177
179
  </div>
178
180
  <MenuClickCapture />
179
- <InFrontOfTheCanvasWrapper />
180
181
  </>
181
182
  )
182
183
  }
@@ -390,18 +391,9 @@ function ShapesWithSVGs() {
390
391
 
391
392
  const renderingShapes = useValue('rendering shapes', () => editor.getRenderingShapes(), [editor])
392
393
 
393
- const dprMultiple = useValue(
394
- 'dpr multiple',
395
- () =>
396
- // dprMultiple is the smallest number we can multiply dpr by to get an integer
397
- // it's usually 1, 2, or 4 (for e.g. dpr of 2, 2.5 and 2.25 respectively)
398
- nearestMultiple(Math.floor(editor.getInstanceState().devicePixelRatio * 100) / 100),
399
- [editor]
400
- )
401
-
402
394
  return renderingShapes.map((result) => (
403
395
  <Fragment key={result.id + '_fragment'}>
404
- <Shape {...result} dprMultiple={dprMultiple} />
396
+ <Shape {...result} />
405
397
  <DebugSvgCopy id={result.id} mode="iframe" />
406
398
  </Fragment>
407
399
  ))
@@ -436,19 +428,10 @@ function ShapesToDisplay() {
436
428
 
437
429
  const renderingShapes = useValue('rendering shapes', () => editor.getRenderingShapes(), [editor])
438
430
 
439
- const dprMultiple = useValue(
440
- 'dpr multiple',
441
- () =>
442
- // dprMultiple is the smallest number we can multiply dpr by to get an integer
443
- // it's usually 1, 2, or 4 (for e.g. dpr of 2, 2.5 and 2.25 respectively)
444
- nearestMultiple(Math.floor(editor.getInstanceState().devicePixelRatio * 100) / 100),
445
- [editor]
446
- )
447
-
448
431
  return (
449
432
  <>
450
433
  {renderingShapes.map((result) => (
451
- <Shape key={result.id + '_shape'} {...result} dprMultiple={dprMultiple} />
434
+ <Shape key={result.id + '_shape'} {...result} />
452
435
  ))}
453
436
  {tlenv.isSafari && <ReflowIfNeeded />}
454
437
  </>
@@ -44,7 +44,7 @@ export function DefaultCollaboratorHint({
44
44
  href={`#${cursorHintId}`}
45
45
  color={color}
46
46
  strokeWidth={3}
47
- stroke="var(--color-background)"
47
+ stroke="var(--tl-color-background)"
48
48
  />
49
49
  <use href={`#${cursorHintId}`} color={color} opacity={opacity} />
50
50
  </svg>
@@ -75,7 +75,7 @@ export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor }
75
75
 
76
76
  // if we can't find a theme class from the app or from a parent, we have
77
77
  // to fall back on using a media query:
78
- if (typeof window !== 'undefined' && 'matchMedia' in window) {
78
+ if (typeof window !== 'undefined' && window.matchMedia) {
79
79
  setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches)
80
80
  }
81
81
  }, [isDarkModeFromApp])
@@ -21,7 +21,7 @@ export function DefaultScribble({ scribble, zoom, color, opacity, className }: T
21
21
  <path
22
22
  className="tl-scribble"
23
23
  d={getSvgPathFromPoints(scribble.points, false)}
24
- stroke={color ?? `var(--color-${scribble.color})`}
24
+ stroke={color ?? `var(--tl-color-${scribble.color})`}
25
25
  fill="none"
26
26
  strokeWidth={8 / zoom}
27
27
  opacity={opacity ?? scribble.opacity}
@@ -87,7 +87,11 @@ export const DefaultShapeIndicator = memo(function DefaultShapeIndicator({
87
87
 
88
88
  return (
89
89
  <svg ref={rIndicator} className={classNames('tl-overlays__item', className)} aria-hidden="true">
90
- <g className="tl-shape-indicator" stroke={color ?? 'var(--color-selected)'} opacity={opacity}>
90
+ <g
91
+ className="tl-shape-indicator"
92
+ stroke={color ?? 'var(--tl-color-selected)'}
93
+ opacity={opacity}
94
+ >
91
95
  <InnerIndicator editor={editor} id={shapeId} />
92
96
  </g>
93
97
  </svg>
@@ -24,6 +24,7 @@ export interface TLUserPreferences {
24
24
  isWrapMode?: boolean | null
25
25
  isDynamicSizeMode?: boolean | null
26
26
  isPasteAtCursorMode?: boolean | null
27
+ showUiLabels?: boolean | null
27
28
  }
28
29
 
29
30
  interface UserDataSnapshot {
@@ -52,6 +53,7 @@ export const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUser
52
53
  isWrapMode: T.boolean.nullable().optional(),
53
54
  isDynamicSizeMode: T.boolean.nullable().optional(),
54
55
  isPasteAtCursorMode: T.boolean.nullable().optional(),
56
+ showUiLabels: T.boolean.nullable().optional(),
55
57
  })
56
58
 
57
59
  const Versions = {
@@ -64,6 +66,7 @@ const Versions = {
64
66
  AllowSystemColorScheme: 7,
65
67
  AddPasteAtCursor: 8,
66
68
  AddKeyboardShortcuts: 9,
69
+ AddShowUiLabels: 10,
67
70
  } as const
68
71
 
69
72
  const CURRENT_VERSION = Math.max(...Object.values(Versions))
@@ -102,6 +105,9 @@ function migrateSnapshot(data: { version: number; user: any }) {
102
105
  if (data.version < Versions.AddKeyboardShortcuts) {
103
106
  data.user.areKeyboardShortcutsEnabled = true
104
107
  }
108
+ if (data.version < Versions.AddShowUiLabels) {
109
+ data.user.showUiLabels = false
110
+ }
105
111
 
106
112
  // finally
107
113
  data.version = CURRENT_VERSION
@@ -129,7 +135,7 @@ function getRandomColor() {
129
135
 
130
136
  /** @internal */
131
137
  export function userPrefersReducedMotion() {
132
- if (typeof window !== 'undefined' && 'matchMedia' in window) {
138
+ if (typeof window !== 'undefined' && window.matchMedia) {
133
139
  return window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false
134
140
  }
135
141
 
@@ -150,6 +156,7 @@ export const defaultUserPreferences = Object.freeze({
150
156
  isWrapMode: false,
151
157
  isDynamicSizeMode: false,
152
158
  isPasteAtCursorMode: false,
159
+ showUiLabels: false,
153
160
  colorScheme: 'light',
154
161
  }) satisfies Readonly<Omit<TLUserPreferences, 'id'>>
155
162
 
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import {
2
3
  Box,
3
4
  Geometry2d,
@@ -59,8 +60,8 @@ beforeEach(() => {
59
60
  getContainer: () => document.body,
60
61
  })
61
62
  editor.setCameraOptions({ isLocked: true })
62
- editor.setCamera = jest.fn()
63
- editor.user.getAnimationSpeed = jest.fn()
63
+ editor.setCamera = vi.fn()
64
+ editor.user.getAnimationSpeed = vi.fn()
64
65
  })
65
66
 
66
67
  describe('centerOnPoint', () => {
@@ -94,13 +95,13 @@ describe('updateShape', () => {
94
95
 
95
96
  describe('zoomToFit', () => {
96
97
  it('no-op when isLocked is set', () => {
97
- editor.getCurrentPageShapeIds = jest.fn(() => new Set([createShapeId('box1')]))
98
+ editor.getCurrentPageShapeIds = vi.fn(() => new Set([createShapeId('box1')]))
98
99
  editor.zoomToFit()
99
100
  expect(editor.setCamera).not.toHaveBeenCalled()
100
101
  })
101
102
 
102
103
  it('sets camera when isLocked is set and force flag is set', () => {
103
- editor.getCurrentPageShapeIds = jest.fn(() => new Set([createShapeId('box1')]))
104
+ editor.getCurrentPageShapeIds = vi.fn(() => new Set([createShapeId('box1')]))
104
105
  editor.zoomToFit({ force: true })
105
106
  expect(editor.setCamera).toHaveBeenCalled()
106
107
  })
@@ -144,13 +145,13 @@ describe('zoomOut', () => {
144
145
 
145
146
  describe('zoomToSelection', () => {
146
147
  it('no-op when isLocked is set', () => {
147
- editor.getSelectionPageBounds = jest.fn(() => Box.From({ x: 0, y: 0, w: 100, h: 100 }))
148
+ editor.getSelectionPageBounds = vi.fn(() => Box.From({ x: 0, y: 0, w: 100, h: 100 }))
148
149
  editor.zoomToSelection()
149
150
  expect(editor.setCamera).not.toHaveBeenCalled()
150
151
  })
151
152
 
152
153
  it('sets camera when isLocked is set and force flag is set', () => {
153
- editor.getSelectionPageBounds = jest.fn(() => Box.From({ x: 0, y: 0, w: 100, h: 100 }))
154
+ editor.getSelectionPageBounds = vi.fn(() => Box.From({ x: 0, y: 0, w: 100, h: 100 }))
154
155
  editor.zoomToSelection({ force: true })
155
156
  expect(editor.setCamera).toHaveBeenCalled()
156
157
  })
@@ -286,7 +287,7 @@ describe('getShapesAtPoint', () => {
286
287
 
287
288
  it('filters out hidden shapes', () => {
288
289
  // Create a spy to mock isShapeHidden
289
- const isShapeHiddenSpy = jest.spyOn(editor, 'isShapeHidden')
290
+ const isShapeHiddenSpy = vi.spyOn(editor, 'isShapeHidden')
290
291
  isShapeHiddenSpy.mockImplementation((shape) => {
291
292
  return typeof shape === 'string' ? shape === ids.shape3 : shape.id === ids.shape3
292
293
  })
@@ -352,7 +353,7 @@ describe('getShapesAtPoint', () => {
352
353
 
353
354
  it('returns empty array when all shapes are hidden', () => {
354
355
  // Mock all shapes as hidden
355
- const isShapeHiddenSpy = jest.spyOn(editor, 'isShapeHidden')
356
+ const isShapeHiddenSpy = vi.spyOn(editor, 'isShapeHidden')
356
357
  isShapeHiddenSpy.mockReturnValue(true)
357
358
 
358
359
  const shapes = editor.getShapesAtPoint({ x: 50, y: 50 })
@@ -692,7 +693,7 @@ describe('selectAll', () => {
692
693
  const initialSelectedIds = editor.getSelectedShapeIds()
693
694
 
694
695
  // Spy on setSelectedShapes to verify it's not called
695
- const setSelectedShapesSpy = jest.spyOn(editor, 'setSelectedShapes')
696
+ const setSelectedShapesSpy = vi.spyOn(editor, 'setSelectedShapes')
696
697
 
697
698
  // Call selectAll
698
699
  editor.selectAll()
@@ -713,7 +714,7 @@ describe('selectAll', () => {
713
714
  const initialSelectedIds = editor.getSelectedShapeIds()
714
715
 
715
716
  // Spy on setSelectedShapes to verify it's not called
716
- const setSelectedShapesSpy = jest.spyOn(editor, 'setSelectedShapes')
717
+ const setSelectedShapesSpy = vi.spyOn(editor, 'setSelectedShapes')
717
718
 
718
719
  // Call selectAll
719
720
  editor.selectAll()
@@ -818,7 +819,7 @@ describe('selectAll', () => {
818
819
  const initialSelectedIds = Array.from(editor.getSelectedShapeIds())
819
820
 
820
821
  // Spy on setSelectedShapes to verify it's not called
821
- const setSelectedShapesSpy = jest.spyOn(editor, 'setSelectedShapes')
822
+ const setSelectedShapesSpy = vi.spyOn(editor, 'setSelectedShapes')
822
823
 
823
824
  // Call selectAll
824
825
  editor.selectAll()