@tldraw/editor 3.15.0 → 3.16.0-canary.01f62b6d4455

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 (124) hide show
  1. package/dist-cjs/index.d.ts +185 -9
  2. package/dist-cjs/index.js +5 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +3 -1
  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 +4 -26
  9. package/dist-cjs/lib/components/Shape.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
  12. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  17. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +53 -0
  19. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +7 -0
  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 +110 -59
  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.map +2 -2
  27. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  28. package/dist-cjs/lib/exports/getSvgJsx.js +1 -2
  29. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  30. package/dist-cjs/lib/hooks/useCanvasEvents.js +24 -20
  31. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  32. package/dist-cjs/lib/hooks/useEditorComponents.js +2 -0
  33. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  34. package/dist-cjs/lib/hooks/useStateAttribute.js +35 -0
  35. package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
  36. package/dist-cjs/lib/license/Watermark.js +6 -6
  37. package/dist-cjs/lib/license/Watermark.js.map +1 -1
  38. package/dist-cjs/lib/options.js +7 -0
  39. package/dist-cjs/lib/options.js.map +2 -2
  40. package/dist-cjs/lib/utils/EditorAtom.js +45 -0
  41. package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
  42. package/dist-cjs/version.js +3 -3
  43. package/dist-cjs/version.js.map +1 -1
  44. package/dist-esm/index.d.mts +185 -9
  45. package/dist-esm/index.mjs +7 -1
  46. package/dist-esm/index.mjs.map +2 -2
  47. package/dist-esm/lib/TldrawEditor.mjs +3 -1
  48. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  49. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  50. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  51. package/dist-esm/lib/components/Shape.mjs +4 -26
  52. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  53. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  54. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
  55. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  56. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  57. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  58. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  59. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  60. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  61. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +23 -0
  62. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +7 -0
  63. package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
  64. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  65. package/dist-esm/lib/editor/Editor.mjs +110 -59
  66. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  67. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +9 -4
  68. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  69. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  70. package/dist-esm/lib/exports/getSvgJsx.mjs +2 -2
  71. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  72. package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -21
  73. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  74. package/dist-esm/lib/hooks/useEditorComponents.mjs +4 -0
  75. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  76. package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
  77. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
  78. package/dist-esm/lib/license/Watermark.mjs +6 -6
  79. package/dist-esm/lib/license/Watermark.mjs.map +1 -1
  80. package/dist-esm/lib/options.mjs +7 -0
  81. package/dist-esm/lib/options.mjs.map +2 -2
  82. package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
  83. package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
  84. package/dist-esm/version.mjs +3 -3
  85. package/dist-esm/version.mjs.map +1 -1
  86. package/editor.css +297 -311
  87. package/package.json +12 -36
  88. package/src/index.ts +7 -0
  89. package/src/lib/TldrawEditor.tsx +7 -5
  90. package/src/lib/components/MenuClickCapture.tsx +0 -8
  91. package/src/lib/components/Shape.tsx +6 -21
  92. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  93. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  94. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  95. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
  96. package/src/lib/components/default-components/DefaultShapeWrapper.tsx +35 -0
  97. package/src/lib/config/TLUserPreferences.ts +8 -1
  98. package/src/lib/editor/Editor.test.ts +12 -11
  99. package/src/lib/editor/Editor.ts +141 -82
  100. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  101. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  102. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  103. package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
  104. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  105. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  106. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  107. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  108. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  109. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +34 -26
  110. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +6 -1
  111. package/src/lib/editor/shapes/ShapeUtil.ts +57 -0
  112. package/src/lib/editor/types/misc-types.ts +73 -1
  113. package/src/lib/exports/getSvgJsx.tsx +2 -2
  114. package/src/lib/hooks/useCanvasEvents.ts +39 -32
  115. package/src/lib/hooks/useEditorComponents.tsx +7 -1
  116. package/src/lib/hooks/useStateAttribute.ts +15 -0
  117. package/src/lib/license/LicenseManager.test.ts +3 -1
  118. package/src/lib/license/Watermark.test.tsx +2 -1
  119. package/src/lib/license/Watermark.tsx +6 -6
  120. package/src/lib/options.ts +8 -0
  121. package/src/lib/utils/EditorAtom.ts +37 -0
  122. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  123. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  124. package/src/version.ts +3 -3
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.15.0",
4
+ "version": "3.16.0-canary.01f62b6d4455",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -34,10 +34,10 @@
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",
@@ -49,12 +49,12 @@
49
49
  "@tiptap/core": "^2.9.1",
50
50
  "@tiptap/pm": "^2.9.1",
51
51
  "@tiptap/react": "^2.9.1",
52
- "@tldraw/state": "3.15.0",
53
- "@tldraw/state-react": "3.15.0",
54
- "@tldraw/store": "3.15.0",
55
- "@tldraw/tlschema": "3.15.0",
56
- "@tldraw/utils": "3.15.0",
57
- "@tldraw/validate": "3.15.0",
52
+ "@tldraw/state": "3.16.0-canary.01f62b6d4455",
53
+ "@tldraw/state-react": "3.16.0-canary.01f62b6d4455",
54
+ "@tldraw/store": "3.16.0-canary.01f62b6d4455",
55
+ "@tldraw/tlschema": "3.16.0-canary.01f62b6d4455",
56
+ "@tldraw/utils": "3.16.0-canary.01f62b6d4455",
57
+ "@tldraw/validate": "3.16.0-canary.01f62b6d4455",
58
58
  "@types/core-js": "^2.5.8",
59
59
  "@use-gesture/react": "^10.3.1",
60
60
  "classnames": "^2.5.1",
@@ -69,41 +69,17 @@
69
69
  },
70
70
  "devDependencies": {
71
71
  "@peculiar/webcrypto": "^1.5.0",
72
- "@testing-library/jest-dom": "^5.17.0",
73
72
  "@testing-library/react": "^15.0.7",
74
73
  "@types/benchmark": "^2.1.5",
75
74
  "@types/react": "^18.3.18",
76
75
  "@types/wicg-file-system-access": "^2020.9.8",
77
76
  "benchmark": "^2.1.4",
78
77
  "fake-indexeddb": "^4.0.2",
79
- "jest-canvas-mock": "^2.5.2",
80
- "jest-environment-jsdom": "^29.7.0",
81
78
  "lazyrepo": "0.0.0-alpha.27",
82
79
  "react": "^18.3.1",
83
80
  "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
- ]
81
+ "resize-observer-polyfill": "^1.5.1",
82
+ "vitest": "^3.2.4"
107
83
  },
108
84
  "module": "dist-esm/index.mjs",
109
85
  "source": "src/index.ts",
package/src/index.ts CHANGED
@@ -67,6 +67,10 @@ export {
67
67
  DefaultShapeIndicators,
68
68
  type TLShapeIndicatorsProps,
69
69
  } from './lib/components/default-components/DefaultShapeIndicators'
70
+ export {
71
+ DefaultShapeWrapper,
72
+ type TLShapeWrapperProps,
73
+ } from './lib/components/default-components/DefaultShapeWrapper'
70
74
  export {
71
75
  DefaultSnapIndicator,
72
76
  type TLSnapIndicatorProps,
@@ -261,9 +265,11 @@ export {
261
265
  type TLCameraMoveOptions,
262
266
  type TLCameraOptions,
263
267
  type TLExportType,
268
+ type TLGetShapeAtPointOptions,
264
269
  type TLImageExportOptions,
265
270
  type TLSvgExportOptions,
266
271
  type TLSvgOptions,
272
+ type TLUpdatePointerOptions,
267
273
  } from './lib/editor/types/misc-types'
268
274
  export {
269
275
  type TLAdjacentDirection,
@@ -445,6 +451,7 @@ export {
445
451
  setPointerCapture,
446
452
  stopEventPropagation,
447
453
  } from './lib/utils/dom'
454
+ export { EditorAtom } from './lib/utils/EditorAtom'
448
455
  export { getIncrementedName } from './lib/utils/getIncrementedName'
449
456
  export { getPointerInfo } from './lib/utils/getPointerInfo'
450
457
  export { getSvgPathFromPoints } from './lib/utils/getSvgPathFromPoints'
@@ -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'
@@ -646,6 +647,7 @@ function Layout({ children, onMount }: { children: ReactNode; onMount?: TLOnMoun
646
647
  useCursor()
647
648
  useDarkMode()
648
649
  useForceUpdate()
650
+ useStateAttribute()
649
651
  useOnMount((editor) => {
650
652
  const teardownStore = editor.store.props.onMount(editor)
651
653
  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]
@@ -40,7 +40,7 @@ export const Shape = memo(function Shape({
40
40
  }) {
41
41
  const editor = useEditor()
42
42
 
43
- const { ShapeErrorFallback } = useEditorComponents()
43
+ const { ShapeErrorFallback, ShapeWrapper } = useEditorComponents()
44
44
 
45
45
  const containerRef = useRef<HTMLDivElement>(null)
46
46
  const bgContainerRef = useRef<HTMLDivElement>(null)
@@ -145,37 +145,22 @@ export const Shape = memo(function Shape({
145
145
  [editor]
146
146
  )
147
147
 
148
- if (!shape) return null
149
-
150
- const isFilledShape = 'fill' in shape.props && shape.props.fill !== 'none'
148
+ if (!shape || !ShapeWrapper) return null
151
149
 
152
150
  return (
153
151
  <>
154
152
  {util.backgroundComponent && (
155
- <div
156
- ref={bgContainerRef}
157
- className="tl-shape tl-shape-background"
158
- data-shape-type={shape.type}
159
- data-shape-id={shape.id}
160
- draggable={false}
161
- >
153
+ <ShapeWrapper ref={bgContainerRef} shape={shape} isBackground={true}>
162
154
  <OptionalErrorBoundary fallback={ShapeErrorFallback} onError={annotateError}>
163
155
  <InnerShapeBackground shape={shape} util={util} />
164
156
  </OptionalErrorBoundary>
165
- </div>
157
+ </ShapeWrapper>
166
158
  )}
167
- <div
168
- ref={containerRef}
169
- className="tl-shape"
170
- data-shape-type={shape.type}
171
- data-shape-is-filled={isFilledShape}
172
- data-shape-id={shape.id}
173
- draggable={false}
174
- >
159
+ <ShapeWrapper ref={containerRef} shape={shape} isBackground={false}>
175
160
  <OptionalErrorBoundary fallback={ShapeErrorFallback as any} onError={annotateError}>
176
161
  <InnerShape shape={shape} util={util} />
177
162
  </OptionalErrorBoundary>
178
- </div>
163
+ </ShapeWrapper>
179
164
  </>
180
165
  )
181
166
  })
@@ -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>
@@ -0,0 +1,35 @@
1
+ import { TLShape } from '@tldraw/tlschema'
2
+ import classNames from 'classnames'
3
+ import { forwardRef, ReactNode } from 'react'
4
+
5
+ /** @public */
6
+ export interface TLShapeWrapperProps extends React.HTMLAttributes<HTMLDivElement> {
7
+ /** The shape being rendered. */
8
+ shape: TLShape
9
+ /** Whether this is the shapes regular, or background component. */
10
+ isBackground: boolean
11
+ /** The shape's rendered component. */
12
+ children: ReactNode
13
+ }
14
+
15
+ /** @public @react */
16
+ export const DefaultShapeWrapper = forwardRef(function DefaultShapeWrapper(
17
+ { children, shape, isBackground, ...props }: TLShapeWrapperProps,
18
+ ref: React.Ref<HTMLDivElement>
19
+ ) {
20
+ const isFilledShape = 'fill' in shape.props && shape.props.fill !== 'none'
21
+
22
+ return (
23
+ <div
24
+ ref={ref}
25
+ data-shape-type={shape.type}
26
+ data-shape-is-filled={isBackground ? undefined : isFilledShape}
27
+ data-shape-id={shape.id}
28
+ draggable={false}
29
+ {...props}
30
+ className={classNames('tl-shape', isBackground && 'tl-shape-background', props.className)}
31
+ >
32
+ {children}
33
+ </div>
34
+ )
35
+ })
@@ -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()