@tldraw/editor 3.16.0-internal.a478398270c6 → 3.16.0-next.15f085081fd5
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 +243 -16
- package/dist-cjs/index.js +8 -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/SVGContainer.js +1 -1
- package/dist-cjs/lib/components/SVGContainer.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/DefaultBrush.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +5 -24
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
- 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/DefaultGrid.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultHandles.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/components/default-components/DefaultSnapIndictor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js +27 -15
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +3 -3
- package/dist-cjs/lib/config/TLUserPreferences.js +15 -3
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +151 -67
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +14 -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/tools/StateNode.js +20 -1
- package/dist-cjs/lib/editor/tools/StateNode.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/useEditor.js +1 -4
- package/dist-cjs/lib/hooks/useEditor.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 +8 -8
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- 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/primitives/geometry/Arc2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +3 -1
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +4 -4
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +4 -0
- package/dist-cjs/lib/primitives/utils.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/lib/utils/sync/TLLocalSyncClient.js +0 -1
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +243 -16
- package/dist-esm/index.mjs +16 -2
- 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/SVGContainer.mjs +1 -1
- package/dist-esm/lib/components/SVGContainer.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/DefaultBrush.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -24
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
- 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/DefaultGrid.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultHandles.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/components/default-components/DefaultSnapIndictor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +17 -15
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +15 -3
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +151 -67
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +14 -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/editor/tools/StateNode.mjs +20 -1
- package/dist-esm/lib/editor/tools/StateNode.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/useEditor.mjs +1 -4
- package/dist-esm/lib/hooks/useEditor.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 +8 -8
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- 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/primitives/geometry/Arc2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +3 -1
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +5 -5
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +4 -0
- package/dist-esm/lib/primitives/utils.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/lib/utils/sync/TLLocalSyncClient.mjs +0 -1
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +320 -313
- package/package.json +16 -38
- package/src/index.ts +15 -1
- package/src/lib/TldrawEditor.tsx +13 -6
- package/src/lib/components/MenuClickCapture.tsx +0 -8
- package/src/lib/components/SVGContainer.tsx +1 -1
- package/src/lib/components/Shape.tsx +12 -33
- package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +6 -23
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +2 -2
- package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
- package/src/lib/components/default-components/DefaultHandles.tsx +5 -1
- package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +6 -2
- package/src/lib/components/default-components/DefaultShapeWrapper.tsx +35 -0
- package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
- package/src/lib/components/default-components/DefaultSpinner.tsx +12 -12
- package/src/lib/config/TLUserPreferences.ts +15 -1
- package/src/lib/editor/Editor.test.ts +416 -8
- package/src/lib/editor/Editor.ts +195 -92
- 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 +55 -26
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +14 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +71 -0
- package/src/lib/editor/tools/StateNode.test.ts +285 -0
- package/src/lib/editor/tools/StateNode.ts +27 -1
- 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/useEditor.tsx +6 -5
- package/src/lib/hooks/useEditorComponents.tsx +8 -2
- 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 +8 -8
- 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/primitives/geometry/Arc2d.ts +2 -2
- package/src/lib/primitives/geometry/Circle2d.ts +2 -2
- package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -1
- package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
- package/src/lib/primitives/geometry/geometry-constants.ts +2 -1
- package/src/lib/primitives/intersect.test.ts +946 -0
- package/src/lib/primitives/intersect.ts +12 -5
- package/src/lib/primitives/utils.ts +11 -0
- 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/lib/utils/sync/TLLocalSyncClient.ts +0 -1
- 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/test/currentToolIdMask.test.ts +0 -49
- package/src/lib/utils/nearestMultiple.ts +0 -13
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import { vi } from 'vitest'
|
|
1
2
|
import { Editor } from '../../Editor'
|
|
2
3
|
import { TextManager, TLMeasureTextSpanOpts } from './TextManager'
|
|
3
4
|
|
|
4
5
|
// Create a simple mock DOM environment
|
|
5
6
|
const mockElement = {
|
|
6
|
-
classList: { add:
|
|
7
|
+
classList: { add: vi.fn() },
|
|
7
8
|
tabIndex: -1,
|
|
8
|
-
cloneNode:
|
|
9
|
+
cloneNode: vi.fn(),
|
|
9
10
|
innerHTML: '',
|
|
10
11
|
textContent: '',
|
|
11
|
-
setAttribute:
|
|
12
|
-
style: {
|
|
12
|
+
setAttribute: vi.fn(),
|
|
13
|
+
style: {
|
|
14
|
+
setProperty: vi.fn(),
|
|
15
|
+
getPropertyValue: vi.fn(() => ''),
|
|
16
|
+
},
|
|
13
17
|
scrollWidth: 100,
|
|
14
|
-
getBoundingClientRect:
|
|
18
|
+
getBoundingClientRect: vi.fn(() => ({
|
|
15
19
|
width: 100,
|
|
16
20
|
height: 20,
|
|
17
21
|
left: 0,
|
|
@@ -19,22 +23,44 @@ const mockElement = {
|
|
|
19
23
|
right: 100,
|
|
20
24
|
bottom: 20,
|
|
21
25
|
})),
|
|
22
|
-
remove:
|
|
23
|
-
insertAdjacentElement:
|
|
26
|
+
remove: vi.fn(),
|
|
27
|
+
insertAdjacentElement: vi.fn(),
|
|
24
28
|
childNodes: [],
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
// Mock document.createElement to return our mock element
|
|
28
|
-
const mockCreateElement =
|
|
32
|
+
const mockCreateElement = vi.fn(() => {
|
|
29
33
|
const element = { ...mockElement }
|
|
30
|
-
element.cloneNode =
|
|
34
|
+
element.cloneNode = vi.fn(() => ({ ...element }))
|
|
35
|
+
|
|
36
|
+
// Make textContent and innerHTML reactive like real DOM elements
|
|
37
|
+
let _textContent = ''
|
|
38
|
+
let _innerHTML = ''
|
|
39
|
+
|
|
40
|
+
Object.defineProperty(element, 'textContent', {
|
|
41
|
+
get: () => _textContent,
|
|
42
|
+
set: (value) => {
|
|
43
|
+
_textContent = value || ''
|
|
44
|
+
// When textContent is set, innerHTML should be the escaped version
|
|
45
|
+
_innerHTML = _textContent
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
Object.defineProperty(element, 'innerHTML', {
|
|
50
|
+
get: () => _innerHTML,
|
|
51
|
+
set: (value) => {
|
|
52
|
+
_innerHTML = value || ''
|
|
53
|
+
_textContent = _innerHTML // Simple approximation
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
|
|
31
57
|
return element
|
|
32
58
|
})
|
|
33
59
|
|
|
34
60
|
// Mock editor
|
|
35
61
|
const mockEditor = {
|
|
36
|
-
getContainer:
|
|
37
|
-
appendChild:
|
|
62
|
+
getContainer: vi.fn(() => ({
|
|
63
|
+
appendChild: vi.fn(),
|
|
38
64
|
})),
|
|
39
65
|
} as unknown as Editor
|
|
40
66
|
|
|
@@ -43,10 +69,10 @@ global.document = {
|
|
|
43
69
|
createElement: mockCreateElement,
|
|
44
70
|
} as any
|
|
45
71
|
|
|
46
|
-
global.Range =
|
|
47
|
-
setStart:
|
|
48
|
-
setEnd:
|
|
49
|
-
getClientRects:
|
|
72
|
+
global.Range = vi.fn(() => ({
|
|
73
|
+
setStart: vi.fn(),
|
|
74
|
+
setEnd: vi.fn(),
|
|
75
|
+
getClientRects: vi.fn(() => [
|
|
50
76
|
{
|
|
51
77
|
width: 10,
|
|
52
78
|
height: 16,
|
|
@@ -62,7 +88,7 @@ describe('TextManager', () => {
|
|
|
62
88
|
let textManager: TextManager
|
|
63
89
|
|
|
64
90
|
beforeEach(() => {
|
|
65
|
-
|
|
91
|
+
vi.clearAllMocks()
|
|
66
92
|
textManager = new TextManager(mockEditor)
|
|
67
93
|
})
|
|
68
94
|
|
|
@@ -86,13 +112,13 @@ describe('TextManager', () => {
|
|
|
86
112
|
}
|
|
87
113
|
|
|
88
114
|
it('should call measureHtml with normalized text', () => {
|
|
89
|
-
const spy =
|
|
115
|
+
const spy = vi.spyOn(textManager, 'measureHtml')
|
|
90
116
|
textManager.measureText('Hello World', defaultOpts)
|
|
91
117
|
expect(spy).toHaveBeenCalledWith('Hello World', defaultOpts)
|
|
92
118
|
})
|
|
93
119
|
|
|
94
120
|
it('should normalize line breaks', () => {
|
|
95
|
-
const spy =
|
|
121
|
+
const spy = vi.spyOn(textManager, 'measureHtml')
|
|
96
122
|
textManager.measureText('Hello\nWorld\r\nTest', defaultOpts)
|
|
97
123
|
// The text should be normalized to use consistent line breaks
|
|
98
124
|
expect(spy).toHaveBeenCalled()
|
|
@@ -247,7 +273,7 @@ describe('TextManager', () => {
|
|
|
247
273
|
|
|
248
274
|
it('should return array of text spans for non-empty text', () => {
|
|
249
275
|
// Mock measureElementTextNodeSpans to return some spans
|
|
250
|
-
|
|
276
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
251
277
|
spans: [
|
|
252
278
|
{
|
|
253
279
|
text: 'Hello World',
|
|
@@ -266,7 +292,7 @@ describe('TextManager', () => {
|
|
|
266
292
|
})
|
|
267
293
|
|
|
268
294
|
it('should handle wrap overflow', () => {
|
|
269
|
-
|
|
295
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
270
296
|
spans: [
|
|
271
297
|
{
|
|
272
298
|
text: 'Hello World',
|
|
@@ -284,8 +310,7 @@ describe('TextManager', () => {
|
|
|
284
310
|
|
|
285
311
|
it('should handle truncate-ellipsis overflow', () => {
|
|
286
312
|
// Mock the calls for ellipsis handling
|
|
287
|
-
|
|
288
|
-
.spyOn(textManager, 'measureElementTextNodeSpans')
|
|
313
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans')
|
|
289
314
|
.mockReturnValueOnce({
|
|
290
315
|
spans: [
|
|
291
316
|
{
|
|
@@ -321,7 +346,7 @@ describe('TextManager', () => {
|
|
|
321
346
|
})
|
|
322
347
|
|
|
323
348
|
it('should handle truncate-clip overflow', () => {
|
|
324
|
-
|
|
349
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
325
350
|
spans: [
|
|
326
351
|
{
|
|
327
352
|
text: 'Hello Wo',
|
|
@@ -338,7 +363,7 @@ describe('TextManager', () => {
|
|
|
338
363
|
})
|
|
339
364
|
|
|
340
365
|
it('should handle different text alignments', () => {
|
|
341
|
-
|
|
366
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
342
367
|
spans: [
|
|
343
368
|
{
|
|
344
369
|
text: 'Test',
|
|
@@ -358,7 +383,7 @@ describe('TextManager', () => {
|
|
|
358
383
|
})
|
|
359
384
|
|
|
360
385
|
it('should handle custom font properties', () => {
|
|
361
|
-
|
|
386
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
362
387
|
spans: [
|
|
363
388
|
{
|
|
364
389
|
text: 'Test',
|
|
@@ -382,7 +407,7 @@ describe('TextManager', () => {
|
|
|
382
407
|
})
|
|
383
408
|
|
|
384
409
|
it('should handle other styles', () => {
|
|
385
|
-
|
|
410
|
+
vi.spyOn(textManager, 'measureElementTextNodeSpans').mockReturnValue({
|
|
386
411
|
spans: [
|
|
387
412
|
{
|
|
388
413
|
text: 'Test',
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
+
import { Mock, Mocked, vi } from 'vitest'
|
|
1
2
|
import { Vec } from '../../../primitives/Vec'
|
|
2
3
|
import { Editor } from '../../Editor'
|
|
3
4
|
import { TickManager } from './TickManager'
|
|
4
5
|
|
|
5
6
|
// Mock the Editor class
|
|
6
|
-
|
|
7
|
+
vi.mock('../../Editor')
|
|
7
8
|
|
|
8
9
|
// Mock Date.now to control time
|
|
9
|
-
const mockDateNow =
|
|
10
|
+
const mockDateNow = vi.fn()
|
|
10
11
|
Date.now = mockDateNow
|
|
11
12
|
|
|
12
13
|
// Mock requestAnimationFrame and cancelAnimationFrame
|
|
13
|
-
const mockRequestAnimationFrame =
|
|
14
|
-
const mockCancelAnimationFrame =
|
|
14
|
+
const mockRequestAnimationFrame = vi.fn()
|
|
15
|
+
const mockCancelAnimationFrame = vi.fn()
|
|
15
16
|
global.requestAnimationFrame = mockRequestAnimationFrame
|
|
16
17
|
global.cancelAnimationFrame = mockCancelAnimationFrame
|
|
17
18
|
|
|
18
19
|
describe('TickManager', () => {
|
|
19
|
-
let editor:
|
|
20
|
+
let editor: Mocked<Editor>
|
|
20
21
|
let tickManager: TickManager
|
|
21
|
-
let mockEmit:
|
|
22
|
-
let mockDisposablesAdd:
|
|
22
|
+
let mockEmit: Mock
|
|
23
|
+
let mockDisposablesAdd: Mock
|
|
23
24
|
|
|
24
25
|
beforeEach(() => {
|
|
25
|
-
|
|
26
|
+
vi.clearAllMocks()
|
|
26
27
|
|
|
27
28
|
// Reset time
|
|
28
29
|
mockDateNow.mockReturnValue(1000)
|
|
@@ -37,8 +38,8 @@ describe('TickManager', () => {
|
|
|
37
38
|
|
|
38
39
|
mockCancelAnimationFrame.mockImplementation(() => {})
|
|
39
40
|
|
|
40
|
-
mockEmit =
|
|
41
|
-
mockDisposablesAdd =
|
|
41
|
+
mockEmit = vi.fn()
|
|
42
|
+
mockDisposablesAdd = vi.fn()
|
|
42
43
|
|
|
43
44
|
editor = {
|
|
44
45
|
emit: mockEmit,
|
|
@@ -90,7 +91,7 @@ describe('TickManager', () => {
|
|
|
90
91
|
})
|
|
91
92
|
|
|
92
93
|
it('should cancel existing RAF before starting new one', () => {
|
|
93
|
-
const mockCancel =
|
|
94
|
+
const mockCancel = vi.fn()
|
|
94
95
|
tickManager.cancelRaf = mockCancel
|
|
95
96
|
|
|
96
97
|
tickManager.start()
|
|
@@ -143,7 +144,7 @@ describe('TickManager', () => {
|
|
|
143
144
|
})
|
|
144
145
|
|
|
145
146
|
it('should update pointer velocity', () => {
|
|
146
|
-
const updatePointerVelocitySpy =
|
|
147
|
+
const updatePointerVelocitySpy = vi.spyOn(tickManager as any, 'updatePointerVelocity')
|
|
147
148
|
tickManager.now = 1000
|
|
148
149
|
mockDateNow.mockReturnValue(1016)
|
|
149
150
|
|
|
@@ -176,7 +177,7 @@ describe('TickManager', () => {
|
|
|
176
177
|
})
|
|
177
178
|
|
|
178
179
|
it('should cancel RAF if exists', () => {
|
|
179
|
-
const mockCancel =
|
|
180
|
+
const mockCancel = vi.fn()
|
|
180
181
|
tickManager.cancelRaf = mockCancel
|
|
181
182
|
|
|
182
183
|
tickManager.dispose()
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { atom } from '@tldraw/state'
|
|
2
|
+
import { Mocked, vi } from 'vitest'
|
|
2
3
|
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
3
4
|
import { TLUser } from '../../../config/createTLUser'
|
|
4
5
|
import { UserPreferencesManager } from './UserPreferencesManager'
|
|
5
6
|
|
|
6
7
|
// Mock window.matchMedia
|
|
7
|
-
const mockMatchMedia =
|
|
8
|
-
|
|
9
|
-
writable: true,
|
|
10
|
-
value: mockMatchMedia,
|
|
11
|
-
})
|
|
8
|
+
const mockMatchMedia = vi.fn()
|
|
9
|
+
window.matchMedia = mockMatchMedia
|
|
12
10
|
|
|
13
11
|
describe('UserPreferencesManager', () => {
|
|
14
|
-
let mockUser:
|
|
12
|
+
let mockUser: Mocked<TLUser>
|
|
15
13
|
let mockUserPreferences: TLUserPreferences
|
|
16
14
|
let userPreferencesAtom: any
|
|
17
15
|
let userPreferencesManager: UserPreferencesManager
|
|
@@ -24,6 +22,8 @@ describe('UserPreferencesManager', () => {
|
|
|
24
22
|
color: '#FF802B',
|
|
25
23
|
locale: 'en',
|
|
26
24
|
animationSpeed: 1,
|
|
25
|
+
areKeyboardShortcutsEnabled: true,
|
|
26
|
+
showUiLabels: false,
|
|
27
27
|
edgeScrollSpeed: 1,
|
|
28
28
|
colorScheme: 'light',
|
|
29
29
|
isSnapMode: false,
|
|
@@ -34,14 +34,14 @@ describe('UserPreferencesManager', () => {
|
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
beforeEach(() => {
|
|
37
|
-
|
|
37
|
+
vi.clearAllMocks()
|
|
38
38
|
|
|
39
39
|
mockUserPreferences = createMockUserPreferences()
|
|
40
40
|
userPreferencesAtom = atom('userPreferences', mockUserPreferences)
|
|
41
41
|
|
|
42
42
|
mockUser = {
|
|
43
43
|
userPreferences: userPreferencesAtom,
|
|
44
|
-
setUserPreferences:
|
|
44
|
+
setUserPreferences: vi.fn((prefs) => {
|
|
45
45
|
userPreferencesAtom.set(prefs)
|
|
46
46
|
}),
|
|
47
47
|
}
|
|
@@ -49,8 +49,8 @@ describe('UserPreferencesManager', () => {
|
|
|
49
49
|
// Default matchMedia mock - no dark mode preference
|
|
50
50
|
mockMatchMedia.mockReturnValue({
|
|
51
51
|
matches: false,
|
|
52
|
-
addEventListener:
|
|
53
|
-
removeEventListener:
|
|
52
|
+
addEventListener: vi.fn(),
|
|
53
|
+
removeEventListener: vi.fn(),
|
|
54
54
|
})
|
|
55
55
|
})
|
|
56
56
|
|
|
@@ -64,17 +64,14 @@ describe('UserPreferencesManager', () => {
|
|
|
64
64
|
expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
|
|
65
65
|
|
|
66
66
|
// Restore matchMedia
|
|
67
|
-
|
|
68
|
-
writable: true,
|
|
69
|
-
value: mockMatchMedia,
|
|
70
|
-
})
|
|
67
|
+
window.matchMedia = mockMatchMedia
|
|
71
68
|
})
|
|
72
69
|
|
|
73
70
|
it('should initialize with light system color scheme when dark mode not preferred', () => {
|
|
74
71
|
mockMatchMedia.mockReturnValue({
|
|
75
72
|
matches: false,
|
|
76
|
-
addEventListener:
|
|
77
|
-
removeEventListener:
|
|
73
|
+
addEventListener: vi.fn(),
|
|
74
|
+
removeEventListener: vi.fn(),
|
|
78
75
|
})
|
|
79
76
|
|
|
80
77
|
userPreferencesManager = new UserPreferencesManager(mockUser, false)
|
|
@@ -85,8 +82,8 @@ describe('UserPreferencesManager', () => {
|
|
|
85
82
|
it('should initialize with dark system color scheme when dark mode preferred', () => {
|
|
86
83
|
mockMatchMedia.mockReturnValue({
|
|
87
84
|
matches: true,
|
|
88
|
-
addEventListener:
|
|
89
|
-
removeEventListener:
|
|
85
|
+
addEventListener: vi.fn(),
|
|
86
|
+
removeEventListener: vi.fn(),
|
|
90
87
|
})
|
|
91
88
|
|
|
92
89
|
userPreferencesManager = new UserPreferencesManager(mockUser, false)
|
|
@@ -95,8 +92,8 @@ describe('UserPreferencesManager', () => {
|
|
|
95
92
|
})
|
|
96
93
|
|
|
97
94
|
it('should set up media query listener for color scheme changes', () => {
|
|
98
|
-
const mockAddEventListener =
|
|
99
|
-
const mockRemoveEventListener =
|
|
95
|
+
const mockAddEventListener = vi.fn()
|
|
96
|
+
const mockRemoveEventListener = vi.fn()
|
|
100
97
|
|
|
101
98
|
mockMatchMedia.mockReturnValue({
|
|
102
99
|
matches: false,
|
|
@@ -110,7 +107,7 @@ describe('UserPreferencesManager', () => {
|
|
|
110
107
|
})
|
|
111
108
|
|
|
112
109
|
it('should handle media query change events', () => {
|
|
113
|
-
const mockAddEventListener =
|
|
110
|
+
const mockAddEventListener = vi.fn()
|
|
114
111
|
let changeHandler: (e: MediaQueryListEvent) => void
|
|
115
112
|
|
|
116
113
|
mockMatchMedia.mockReturnValue({
|
|
@@ -121,7 +118,7 @@ describe('UserPreferencesManager', () => {
|
|
|
121
118
|
}
|
|
122
119
|
mockAddEventListener(event, handler)
|
|
123
120
|
},
|
|
124
|
-
removeEventListener:
|
|
121
|
+
removeEventListener: vi.fn(),
|
|
125
122
|
})
|
|
126
123
|
|
|
127
124
|
userPreferencesManager = new UserPreferencesManager(mockUser, false)
|
|
@@ -151,11 +148,11 @@ describe('UserPreferencesManager', () => {
|
|
|
151
148
|
|
|
152
149
|
describe('dispose', () => {
|
|
153
150
|
it('should remove media query listener on dispose', () => {
|
|
154
|
-
const mockRemoveEventListener =
|
|
151
|
+
const mockRemoveEventListener = vi.fn()
|
|
155
152
|
|
|
156
153
|
mockMatchMedia.mockReturnValue({
|
|
157
154
|
matches: false,
|
|
158
|
-
addEventListener:
|
|
155
|
+
addEventListener: vi.fn(),
|
|
159
156
|
removeEventListener: mockRemoveEventListener,
|
|
160
157
|
})
|
|
161
158
|
|
|
@@ -168,8 +165,8 @@ describe('UserPreferencesManager', () => {
|
|
|
168
165
|
it('should call all disposables', () => {
|
|
169
166
|
userPreferencesManager = new UserPreferencesManager(mockUser, false)
|
|
170
167
|
|
|
171
|
-
const mockDisposable1 =
|
|
172
|
-
const mockDisposable2 =
|
|
168
|
+
const mockDisposable1 = vi.fn()
|
|
169
|
+
const mockDisposable2 = vi.fn()
|
|
173
170
|
|
|
174
171
|
userPreferencesManager.disposables.add(mockDisposable1)
|
|
175
172
|
userPreferencesManager.disposables.add(mockDisposable2)
|
|
@@ -229,6 +226,8 @@ describe('UserPreferencesManager', () => {
|
|
|
229
226
|
locale: mockUserPreferences.locale,
|
|
230
227
|
color: mockUserPreferences.color,
|
|
231
228
|
animationSpeed: mockUserPreferences.animationSpeed,
|
|
229
|
+
areKeyboardShortcutsEnabled: mockUserPreferences.areKeyboardShortcutsEnabled,
|
|
230
|
+
showUiLabels: mockUserPreferences.showUiLabels,
|
|
232
231
|
isSnapMode: mockUserPreferences.isSnapMode,
|
|
233
232
|
colorScheme: mockUserPreferences.colorScheme,
|
|
234
233
|
isDarkMode: false, // light mode
|
|
@@ -362,6 +361,32 @@ describe('UserPreferencesManager', () => {
|
|
|
362
361
|
})
|
|
363
362
|
})
|
|
364
363
|
|
|
364
|
+
describe('getAreKeyboardShortcutsEnabled', () => {
|
|
365
|
+
it('should return user keyboard shortcuts', () => {
|
|
366
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
367
|
+
mockUserPreferences.areKeyboardShortcutsEnabled
|
|
368
|
+
)
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
it('should return default keyboard shortcuts when null', () => {
|
|
372
|
+
userPreferencesAtom.set({ ...mockUserPreferences, areKeyboardShortcutsEnabled: null })
|
|
373
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
374
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
375
|
+
)
|
|
376
|
+
})
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
describe('getShowUiLabels', () => {
|
|
380
|
+
it('should return user show ui labels setting', () => {
|
|
381
|
+
expect(userPreferencesManager.getShowUiLabels()).toBe(mockUserPreferences.showUiLabels)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
it('should return default show ui labels when null', () => {
|
|
385
|
+
userPreferencesAtom.set({ ...mockUserPreferences, showUiLabels: null })
|
|
386
|
+
expect(userPreferencesManager.getShowUiLabels()).toBe(defaultUserPreferences.showUiLabels)
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
|
|
365
390
|
describe('getEdgeScrollSpeed', () => {
|
|
366
391
|
it('should return user edge scroll speed', () => {
|
|
367
392
|
expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
|
|
@@ -483,6 +508,7 @@ describe('UserPreferencesManager', () => {
|
|
|
483
508
|
color: null,
|
|
484
509
|
locale: null,
|
|
485
510
|
animationSpeed: null,
|
|
511
|
+
areKeyboardShortcutsEnabled: null,
|
|
486
512
|
edgeScrollSpeed: null,
|
|
487
513
|
isSnapMode: null,
|
|
488
514
|
isWrapMode: null,
|
|
@@ -496,6 +522,9 @@ describe('UserPreferencesManager', () => {
|
|
|
496
522
|
expect(userPreferencesManager.getColor()).toBe(defaultUserPreferences.color)
|
|
497
523
|
expect(userPreferencesManager.getLocale()).toBe(defaultUserPreferences.locale)
|
|
498
524
|
expect(userPreferencesManager.getAnimationSpeed()).toBe(defaultUserPreferences.animationSpeed)
|
|
525
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
526
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
527
|
+
)
|
|
499
528
|
expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
|
|
500
529
|
defaultUserPreferences.edgeScrollSpeed
|
|
501
530
|
)
|
|
@@ -13,7 +13,7 @@ export class UserPreferencesManager {
|
|
|
13
13
|
private readonly user: TLUser,
|
|
14
14
|
private readonly inferDarkMode: boolean
|
|
15
15
|
) {
|
|
16
|
-
if (typeof window === 'undefined' || !
|
|
16
|
+
if (typeof window === 'undefined' || !window.matchMedia) return
|
|
17
17
|
|
|
18
18
|
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
19
19
|
if (darkModeMediaQuery?.matches) {
|
|
@@ -43,11 +43,13 @@ export class UserPreferencesManager {
|
|
|
43
43
|
locale: this.getLocale(),
|
|
44
44
|
color: this.getColor(),
|
|
45
45
|
animationSpeed: this.getAnimationSpeed(),
|
|
46
|
+
areKeyboardShortcutsEnabled: this.getAreKeyboardShortcutsEnabled(),
|
|
46
47
|
isSnapMode: this.getIsSnapMode(),
|
|
47
48
|
colorScheme: this.user.userPreferences.get().colorScheme,
|
|
48
49
|
isDarkMode: this.getIsDarkMode(),
|
|
49
50
|
isWrapMode: this.getIsWrapMode(),
|
|
50
51
|
isDynamicResizeMode: this.getIsDynamicResizeMode(),
|
|
52
|
+
showUiLabels: this.getShowUiLabels(),
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -75,6 +77,13 @@ export class UserPreferencesManager {
|
|
|
75
77
|
return this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
@computed getAreKeyboardShortcutsEnabled() {
|
|
81
|
+
return (
|
|
82
|
+
this.user.userPreferences.get().areKeyboardShortcutsEnabled ??
|
|
83
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
78
87
|
@computed getId() {
|
|
79
88
|
return this.user.userPreferences.get().id
|
|
80
89
|
}
|
|
@@ -111,4 +120,8 @@ export class UserPreferencesManager {
|
|
|
111
120
|
defaultUserPreferences.isPasteAtCursorMode
|
|
112
121
|
)
|
|
113
122
|
}
|
|
123
|
+
|
|
124
|
+
@computed getShowUiLabels() {
|
|
125
|
+
return this.user.userPreferences.get().showUiLabels ?? defaultUserPreferences.showUiLabels
|
|
126
|
+
}
|
|
114
127
|
}
|
|
@@ -341,6 +341,20 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
341
341
|
return false
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
+
/**
|
|
345
|
+
* By default, the bounds of an image export are the bounds of all the shapes it contains, plus
|
|
346
|
+
* some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
|
|
347
|
+
* padding is skipped _if the bounds of that shape contains all the other shapes_. This is
|
|
348
|
+
* useful in cases like annotating on top of an image, where you usually want to avoid extra
|
|
349
|
+
* padding around the image if you don't need it.
|
|
350
|
+
*
|
|
351
|
+
* @param _shape - The shape to check
|
|
352
|
+
* @returns True if this shape should be treated as an export bounds container
|
|
353
|
+
*/
|
|
354
|
+
isExportBoundsContainer(_shape: Shape): boolean {
|
|
355
|
+
return false
|
|
356
|
+
}
|
|
357
|
+
|
|
344
358
|
/**
|
|
345
359
|
* Get a JSX element for the shape (as an HTML element) to be rendered as part of the canvas background - behind any other shape content.
|
|
346
360
|
*
|
|
@@ -584,6 +598,15 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
584
598
|
*/
|
|
585
599
|
onResizeEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
|
|
586
600
|
|
|
601
|
+
/**
|
|
602
|
+
* A callback called when a shape resize is cancelled.
|
|
603
|
+
*
|
|
604
|
+
* @param initial - The shape at the start of the resize.
|
|
605
|
+
* @param current - The current shape.
|
|
606
|
+
* @public
|
|
607
|
+
*/
|
|
608
|
+
onResizeCancel?(initial: Shape, current: Shape): void
|
|
609
|
+
|
|
587
610
|
/**
|
|
588
611
|
* A callback called when a shape starts being translated.
|
|
589
612
|
*
|
|
@@ -613,6 +636,25 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
613
636
|
*/
|
|
614
637
|
onTranslateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
|
|
615
638
|
|
|
639
|
+
/**
|
|
640
|
+
* A callback called when a shape translation is cancelled.
|
|
641
|
+
*
|
|
642
|
+
* @param initial - The shape at the start of the translation.
|
|
643
|
+
* @param current - The current shape.
|
|
644
|
+
* @public
|
|
645
|
+
*/
|
|
646
|
+
onTranslateCancel?(initial: Shape, current: Shape): void
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* A callback called when a shape's handle starts being dragged.
|
|
650
|
+
*
|
|
651
|
+
* @param shape - The shape.
|
|
652
|
+
* @param info - An object containing the handle and whether the handle is 'precise' or not.
|
|
653
|
+
* @returns A change to apply to the shape, or void.
|
|
654
|
+
* @public
|
|
655
|
+
*/
|
|
656
|
+
onHandleDragStart?(shape: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
|
|
657
|
+
|
|
616
658
|
/**
|
|
617
659
|
* A callback called when a shape's handle changes.
|
|
618
660
|
*
|
|
@@ -623,6 +665,25 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
623
665
|
*/
|
|
624
666
|
onHandleDrag?(shape: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
|
|
625
667
|
|
|
668
|
+
/**
|
|
669
|
+
* A callback called when a shape's handle finishes being dragged.
|
|
670
|
+
*
|
|
671
|
+
* @param current - The current shape.
|
|
672
|
+
* @param info - An object containing the handle and whether the handle is 'precise' or not.
|
|
673
|
+
* @returns A change to apply to the shape, or void.
|
|
674
|
+
* @public
|
|
675
|
+
*/
|
|
676
|
+
onHandleDragEnd?(current: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* A callback called when a shape's handle drag is cancelled.
|
|
680
|
+
*
|
|
681
|
+
* @param current - The current shape.
|
|
682
|
+
* @param info - An object containing the handle and whether the handle is 'precise' or not.
|
|
683
|
+
* @public
|
|
684
|
+
*/
|
|
685
|
+
onHandleDragCancel?(current: Shape, info: TLHandleDragInfo<Shape>): void
|
|
686
|
+
|
|
626
687
|
/**
|
|
627
688
|
* A callback called when a shape starts being rotated.
|
|
628
689
|
*
|
|
@@ -652,6 +713,15 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
652
713
|
*/
|
|
653
714
|
onRotateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
|
|
654
715
|
|
|
716
|
+
/**
|
|
717
|
+
* A callback called when a shape rotation is cancelled.
|
|
718
|
+
*
|
|
719
|
+
* @param initial - The shape at the start of the rotation.
|
|
720
|
+
* @param current - The current shape.
|
|
721
|
+
* @public
|
|
722
|
+
*/
|
|
723
|
+
onRotateCancel?(initial: Shape, current: Shape): void
|
|
724
|
+
|
|
655
725
|
/**
|
|
656
726
|
* Not currently used.
|
|
657
727
|
*
|
|
@@ -819,5 +889,6 @@ export interface TLResizeInfo<T extends TLShape> {
|
|
|
819
889
|
export interface TLHandleDragInfo<T extends TLShape> {
|
|
820
890
|
handle: TLHandle
|
|
821
891
|
isPrecise: boolean
|
|
892
|
+
isCreatingShape: boolean
|
|
822
893
|
initial?: T | undefined
|
|
823
894
|
}
|