@tldraw/editor 3.15.4 → 3.16.0-canary.016d4c2889b7
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.
- package/dist-cjs/index.d.ts +180 -9
- package/dist-cjs/index.js +5 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +8 -2
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +11 -36
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +53 -0
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +7 -0
- package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +138 -69
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +9 -4
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +31 -25
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js +2 -0
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/{utils/nearestMultiple.js → hooks/useStateAttribute.js} +15 -14
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +7 -0
- package/dist-cjs/lib/license/Watermark.js +6 -6
- package/dist-cjs/lib/license/Watermark.js.map +1 -1
- package/dist-cjs/lib/options.js +7 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/utils/EditorAtom.js +45 -0
- package/dist-cjs/lib/utils/EditorAtom.js.map +7 -0
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +180 -9
- package/dist-esm/index.mjs +7 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +8 -2
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +11 -36
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +23 -0
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +7 -0
- package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +138 -69
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +9 -4
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +32 -26
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +4 -0
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useStateAttribute.mjs +15 -0
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +7 -0
- package/dist-esm/lib/license/Watermark.mjs +6 -6
- package/dist-esm/lib/license/Watermark.mjs.map +1 -1
- package/dist-esm/lib/options.mjs +7 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +4 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/utils/EditorAtom.mjs +25 -0
- package/dist-esm/lib/utils/EditorAtom.mjs.map +7 -0
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +305 -311
- package/package.json +14 -37
- package/src/index.ts +7 -0
- package/src/lib/TldrawEditor.tsx +13 -6
- package/src/lib/components/MenuClickCapture.tsx +0 -8
- package/src/lib/components/Shape.tsx +12 -33
- package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
- package/src/lib/components/default-components/DefaultShapeWrapper.tsx +35 -0
- package/src/lib/config/TLUserPreferences.ts +8 -1
- package/src/lib/editor/Editor.test.ts +12 -11
- package/src/lib/editor/Editor.ts +178 -103
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
- package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +34 -26
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +6 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +36 -0
- package/src/lib/editor/types/misc-types.ts +73 -1
- package/src/lib/exports/getSvgJsx.test.ts +868 -0
- package/src/lib/exports/getSvgJsx.tsx +78 -21
- package/src/lib/hooks/useCanvasEvents.ts +45 -38
- package/src/lib/hooks/useEditorComponents.tsx +7 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
- package/src/lib/hooks/useStateAttribute.ts +15 -0
- package/src/lib/license/LicenseManager.test.ts +3 -1
- package/src/lib/license/Watermark.test.tsx +2 -1
- package/src/lib/license/Watermark.tsx +6 -6
- package/src/lib/options.ts +8 -0
- package/src/lib/primitives/Box.test.ts +126 -0
- package/src/lib/primitives/Box.ts +10 -1
- package/src/lib/utils/EditorAtom.ts +37 -0
- package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
- package/src/version.ts +3 -3
- package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
- package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
- package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
- 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.
|
|
4
|
+
"version": "3.16.0-canary.016d4c2889b7",
|
|
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": "
|
|
38
|
-
"test": "yarn run -T
|
|
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": "
|
|
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.
|
|
53
|
-
"@tldraw/state-react": "3.
|
|
54
|
-
"@tldraw/store": "3.
|
|
55
|
-
"@tldraw/tlschema": "3.
|
|
56
|
-
"@tldraw/utils": "3.
|
|
57
|
-
"@tldraw/validate": "3.
|
|
53
|
+
"@tldraw/state": "3.16.0-canary.016d4c2889b7",
|
|
54
|
+
"@tldraw/state-react": "3.16.0-canary.016d4c2889b7",
|
|
55
|
+
"@tldraw/store": "3.16.0-canary.016d4c2889b7",
|
|
56
|
+
"@tldraw/tlschema": "3.16.0-canary.016d4c2889b7",
|
|
57
|
+
"@tldraw/utils": "3.16.0-canary.016d4c2889b7",
|
|
58
|
+
"@tldraw/validate": "3.16.0-canary.016d4c2889b7",
|
|
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
|
@@ -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'
|
package/src/lib/TldrawEditor.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { MigrationSequence, Store } from '@tldraw/store'
|
|
2
2
|
import { TLShape, TLStore, TLStoreSnapshot } from '@tldraw/tlschema'
|
|
3
|
-
import {
|
|
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 {
|
|
19
|
+
import { OptionalErrorBoundary } from './components/ErrorBoundary'
|
|
21
20
|
import { TLStoreBaseOptions } from './config/createTLStore'
|
|
22
|
-
import {
|
|
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'
|
|
@@ -585,8 +586,13 @@ function TldrawEditorWithReadyStore({
|
|
|
585
586
|
if (editor !== fontLoadingState?.editor) {
|
|
586
587
|
fontLoadingState = null
|
|
587
588
|
}
|
|
588
|
-
|
|
589
|
+
useLayoutEffect(() => {
|
|
589
590
|
if (!editor) return
|
|
591
|
+
if (editor.options.maxFontsToLoadBeforeRender === 0) {
|
|
592
|
+
setFontLoadingState({ editor, isLoaded: true })
|
|
593
|
+
return
|
|
594
|
+
}
|
|
595
|
+
|
|
590
596
|
let isCancelled = false
|
|
591
597
|
|
|
592
598
|
setFontLoadingState({ editor, isLoaded: false })
|
|
@@ -646,6 +652,7 @@ function Layout({ children, onMount }: { children: ReactNode; onMount?: TLOnMoun
|
|
|
646
652
|
useCursor()
|
|
647
653
|
useDarkMode()
|
|
648
654
|
useForceUpdate()
|
|
655
|
+
useStateAttribute()
|
|
649
656
|
useOnMount((editor) => {
|
|
650
657
|
const teardownStore = editor.store.props.onMount(editor)
|
|
651
658
|
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,11 +35,10 @@ 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
|
|
|
43
|
-
const { ShapeErrorFallback } = useEditorComponents()
|
|
41
|
+
const { ShapeErrorFallback, ShapeWrapper } = useEditorComponents()
|
|
44
42
|
|
|
45
43
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
46
44
|
const bgContainerRef = useRef<HTMLDivElement>(null)
|
|
@@ -91,18 +89,14 @@ export const Shape = memo(function Shape({
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
// Width / Height
|
|
94
|
-
|
|
95
|
-
|
|
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',
|
|
103
|
-
setStyleProperty(containerRef.current, 'height',
|
|
104
|
-
setStyleProperty(bgContainerRef.current, 'width',
|
|
105
|
-
setStyleProperty(bgContainerRef.current, 'height',
|
|
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
|
}
|
|
@@ -145,37 +139,22 @@ export const Shape = memo(function Shape({
|
|
|
145
139
|
[editor]
|
|
146
140
|
)
|
|
147
141
|
|
|
148
|
-
if (!shape) return null
|
|
149
|
-
|
|
150
|
-
const isFilledShape = 'fill' in shape.props && shape.props.fill !== 'none'
|
|
142
|
+
if (!shape || !ShapeWrapper) return null
|
|
151
143
|
|
|
152
144
|
return (
|
|
153
145
|
<>
|
|
154
146
|
{util.backgroundComponent && (
|
|
155
|
-
<
|
|
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
|
-
>
|
|
147
|
+
<ShapeWrapper ref={bgContainerRef} shape={shape} isBackground={true}>
|
|
162
148
|
<OptionalErrorBoundary fallback={ShapeErrorFallback} onError={annotateError}>
|
|
163
149
|
<InnerShapeBackground shape={shape} util={util} />
|
|
164
150
|
</OptionalErrorBoundary>
|
|
165
|
-
</
|
|
151
|
+
</ShapeWrapper>
|
|
166
152
|
)}
|
|
167
|
-
<
|
|
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
|
-
>
|
|
153
|
+
<ShapeWrapper ref={containerRef} shape={shape} isBackground={false}>
|
|
175
154
|
<OptionalErrorBoundary fallback={ShapeErrorFallback as any} onError={annotateError}>
|
|
176
155
|
<InnerShape shape={shape} util={util} />
|
|
177
156
|
</OptionalErrorBoundary>
|
|
178
|
-
</
|
|
157
|
+
</ShapeWrapper>
|
|
179
158
|
</>
|
|
180
159
|
)
|
|
181
160
|
})
|
|
@@ -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}
|
|
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}
|
|
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' &&
|
|
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
|
|
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' &&
|
|
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 =
|
|
63
|
-
editor.user.getAnimationSpeed =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
822
|
+
const setSelectedShapesSpy = vi.spyOn(editor, 'setSelectedShapes')
|
|
822
823
|
|
|
823
824
|
// Call selectAll
|
|
824
825
|
editor.selectAll()
|