@tldraw/editor 3.16.0-canary.e9c30b532b82 → 3.16.0-canary.ea008b31887f
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 +71 -101
- package/dist-cjs/index.js +3 -5
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +6 -6
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +7 -10
- 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/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +44 -112
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +4 -0
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +23 -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 +34 -14
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +7 -5
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.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/license/LicenseManager.js +138 -50
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +39 -1
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +68 -6
- package/dist-cjs/lib/license/Watermark.js.map +3 -3
- package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
- package/dist-cjs/lib/options.js +6 -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/Vec.js +0 -4
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +50 -20
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +8 -1
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.js +2 -35
- package/dist-cjs/lib/utils/reparenting.js.map +3 -3
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +71 -101
- package/dist-esm/index.mjs +3 -5
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +6 -6
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +7 -10
- 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/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +44 -112
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +4 -0
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +23 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +34 -14
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +7 -5
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.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/license/LicenseManager.mjs +139 -51
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +39 -2
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +68 -6
- package/dist-esm/lib/license/Watermark.mjs.map +3 -3
- package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +6 -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/Vec.mjs +0 -4
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +53 -21
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +8 -1
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs +3 -40
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +16 -3
- package/package.json +14 -37
- package/src/index.ts +2 -9
- package/src/lib/TldrawEditor.tsx +7 -14
- package/src/lib/components/Shape.tsx +6 -12
- package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
- package/src/lib/config/TLUserPreferences.ts +1 -1
- package/src/lib/editor/Editor.test.ts +12 -11
- package/src/lib/editor/Editor.ts +53 -149
- package/src/lib/editor/derivations/notVisibleShapes.ts +6 -0
- 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 +21 -26
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +46 -0
- package/src/lib/editor/types/misc-types.ts +0 -6
- package/src/lib/exports/getSvgJsx.test.ts +868 -0
- package/src/lib/exports/getSvgJsx.tsx +76 -19
- package/src/lib/hooks/useCanvasEvents.ts +6 -6
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
- package/src/lib/license/LicenseManager.test.ts +692 -383
- package/src/lib/license/LicenseManager.ts +197 -53
- package/src/lib/license/LicenseProvider.tsx +74 -2
- package/src/lib/license/Watermark.test.tsx +2 -1
- package/src/lib/license/Watermark.tsx +73 -6
- package/src/lib/license/useLicenseManagerState.ts +2 -2
- package/src/lib/options.ts +6 -0
- package/src/lib/primitives/Box.test.ts +126 -0
- package/src/lib/primitives/Box.ts +10 -1
- package/src/lib/primitives/Vec.ts +0 -5
- package/src/lib/primitives/geometry/Geometry2d.test.ts +420 -0
- package/src/lib/primitives/geometry/Geometry2d.ts +78 -21
- package/src/lib/primitives/geometry/Group2d.ts +10 -1
- package/src/lib/utils/reparenting.ts +3 -69
- 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 +0 -34
- 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
|
@@ -57,33 +57,21 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
|
|
|
57
57
|
.filter(({ id }) => shapeIdsToInclude.has(id))
|
|
58
58
|
|
|
59
59
|
// --- Common bounding box of all shapes
|
|
60
|
+
const singleFrameShapeId =
|
|
61
|
+
ids.length === 1 && editor.isShapeOfType<TLFrameShape>(editor.getShape(ids[0])!, 'frame')
|
|
62
|
+
? ids[0]
|
|
63
|
+
: null
|
|
64
|
+
|
|
60
65
|
let bbox: null | Box = null
|
|
61
66
|
if (opts.bounds) {
|
|
62
|
-
bbox = opts.bounds
|
|
67
|
+
bbox = opts.bounds.clone().expandBy(padding)
|
|
63
68
|
} else {
|
|
64
|
-
|
|
65
|
-
const maskedPageBounds = editor.getShapeMaskedPageBounds(id)
|
|
66
|
-
if (!maskedPageBounds) continue
|
|
67
|
-
if (bbox) {
|
|
68
|
-
bbox.union(maskedPageBounds)
|
|
69
|
-
} else {
|
|
70
|
-
bbox = maskedPageBounds.clone()
|
|
71
|
-
}
|
|
72
|
-
}
|
|
69
|
+
bbox = getExportDefaultBounds(editor, renderingShapes, padding, singleFrameShapeId)
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
// no unmasked shapes to export
|
|
76
73
|
if (!bbox) return
|
|
77
74
|
|
|
78
|
-
const singleFrameShapeId =
|
|
79
|
-
ids.length === 1 && editor.isShapeOfType<TLFrameShape>(editor.getShape(ids[0])!, 'frame')
|
|
80
|
-
? ids[0]
|
|
81
|
-
: null
|
|
82
|
-
if (!singleFrameShapeId) {
|
|
83
|
-
// Expand by an extra 32 pixels
|
|
84
|
-
bbox.expandBy(padding)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
75
|
// We want the svg image to be BIGGER THAN USUAL to account for image quality
|
|
88
76
|
const w = bbox.width * scale
|
|
89
77
|
const h = bbox.height * scale
|
|
@@ -120,6 +108,75 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
|
|
|
120
108
|
return { jsx: svg, width: w, height: h, exportDelay }
|
|
121
109
|
}
|
|
122
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Calculates the default bounds for an SVG export. This function handles:
|
|
113
|
+
* 1. Computing masked page bounds for each shape
|
|
114
|
+
* 2. Container logic: if a shape is marked as an export bounds container and it
|
|
115
|
+
* contains all other shapes, use its bounds and skip padding
|
|
116
|
+
* 3. Otherwise, create a union of all shape bounds and apply padding
|
|
117
|
+
*
|
|
118
|
+
* The container logic is useful for cases like annotating on an image - if the image
|
|
119
|
+
* contains all annotations, we want to export exactly the image bounds without extra padding.
|
|
120
|
+
*
|
|
121
|
+
* @param editor - The editor instance
|
|
122
|
+
* @param renderingShapes - The shapes to include in the export
|
|
123
|
+
* @param padding - Padding to add around the bounds (only applied if no container bounds)
|
|
124
|
+
* @param singleFrameShapeId - If exporting a single frame, this is its ID (skips padding)
|
|
125
|
+
* @returns The calculated bounds box, or null if no shapes to export
|
|
126
|
+
*/
|
|
127
|
+
export function getExportDefaultBounds(
|
|
128
|
+
editor: Editor,
|
|
129
|
+
renderingShapes: TLRenderingShape[],
|
|
130
|
+
padding: number,
|
|
131
|
+
singleFrameShapeId: TLShapeId | null
|
|
132
|
+
) {
|
|
133
|
+
let isBoundedByContainer = false
|
|
134
|
+
let bbox: null | Box = null
|
|
135
|
+
|
|
136
|
+
for (const { id } of renderingShapes) {
|
|
137
|
+
const maskedPageBounds = editor.getShapeMaskedPageBounds(id)
|
|
138
|
+
if (!maskedPageBounds) continue
|
|
139
|
+
|
|
140
|
+
// Check if this shape is an export bounds container (e.g., an image being annotated)
|
|
141
|
+
const shape = editor.getShape(id)!
|
|
142
|
+
const isContainer = editor.getShapeUtil(shape).isExportBoundsContainer(shape)
|
|
143
|
+
|
|
144
|
+
if (bbox) {
|
|
145
|
+
// Container logic: if this is a container and it contains all shapes processed so far,
|
|
146
|
+
// use the container's bounds instead of the union. This prevents extra padding around
|
|
147
|
+
// things like annotated images.
|
|
148
|
+
if (isContainer && Box.ContainsApproximately(maskedPageBounds, bbox)) {
|
|
149
|
+
isBoundedByContainer = true
|
|
150
|
+
bbox = maskedPageBounds.clone()
|
|
151
|
+
} else {
|
|
152
|
+
// If we were previously bounded by a container but this shape extends outside it,
|
|
153
|
+
// we're no longer bounded by a container
|
|
154
|
+
if (isBoundedByContainer && !Box.ContainsApproximately(bbox, maskedPageBounds)) {
|
|
155
|
+
isBoundedByContainer = false
|
|
156
|
+
}
|
|
157
|
+
// Expand the bounding box to include this shape
|
|
158
|
+
bbox.union(maskedPageBounds)
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
// First shape sets the initial bounds
|
|
162
|
+
isBoundedByContainer = isContainer
|
|
163
|
+
bbox = maskedPageBounds.clone()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// No unmasked shapes to export
|
|
168
|
+
if (!bbox) return null
|
|
169
|
+
|
|
170
|
+
// Only apply padding if:
|
|
171
|
+
// - Not exporting a single frame (frames have their own padding rules)
|
|
172
|
+
// - Not bounded by a container (containers define their own bounds precisely)
|
|
173
|
+
if (!singleFrameShapeId && !isBoundedByContainer) {
|
|
174
|
+
bbox.expandBy(padding)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return bbox
|
|
178
|
+
}
|
|
179
|
+
|
|
123
180
|
function SvgExport({
|
|
124
181
|
editor,
|
|
125
182
|
preserveAspectRatio,
|
|
@@ -79,15 +79,15 @@ export function useCanvasEvents() {
|
|
|
79
79
|
// check that e.target is an HTMLElement
|
|
80
80
|
if (!(e.target instanceof HTMLElement)) return
|
|
81
81
|
|
|
82
|
+
const editingShapeId = editor.getEditingShape()?.id
|
|
82
83
|
if (
|
|
84
|
+
// if the target is not inside the editing shape
|
|
85
|
+
!(editingShapeId && e.target.closest(`[data-shape-id="${editingShapeId}"]`)) &&
|
|
86
|
+
// and the target is not an clickable element
|
|
83
87
|
e.target.tagName !== 'A' &&
|
|
88
|
+
// or a TextArea.tsx ?
|
|
84
89
|
e.target.tagName !== 'TEXTAREA' &&
|
|
85
|
-
!e.target.isContentEditable
|
|
86
|
-
// When in EditingShape state, we are actually clicking on a 'DIV'
|
|
87
|
-
// not A/TEXTAREA/contenteditable element yet. So, to preserve cursor position
|
|
88
|
-
// for edit mode on mobile we need to not preventDefault.
|
|
89
|
-
// TODO: Find out if we still need this preventDefault in general though.
|
|
90
|
-
!(editor.getEditingShape() && e.target.className.includes('tl-text-content'))
|
|
90
|
+
!e.target.isContentEditable
|
|
91
91
|
) {
|
|
92
92
|
preventDefault(e)
|
|
93
93
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { RefObject, useEffect } from 'react'
|
|
2
2
|
import { preventDefault } from '../utils/dom'
|
|
3
3
|
import { useContainer } from './useContainer'
|
|
4
|
+
import { useMaybeEditor } from './useEditor'
|
|
4
5
|
|
|
5
6
|
/** @public */
|
|
6
7
|
export function usePassThroughMouseOverEvents(ref: RefObject<HTMLElement>) {
|
|
7
8
|
if (!ref) throw Error('usePassThroughWheelEvents must be passed a ref')
|
|
8
9
|
const container = useContainer()
|
|
10
|
+
const editor = useMaybeEditor()
|
|
9
11
|
|
|
10
12
|
useEffect(() => {
|
|
11
13
|
function onMouseOver(e: MouseEvent) {
|
|
14
|
+
if (!editor?.getInstanceState().isFocused) return
|
|
12
15
|
if ((e as any).isSpecialRedispatchedEvent) return
|
|
13
16
|
preventDefault(e)
|
|
14
17
|
const cvs = container.querySelector('.tl-canvas')
|
|
@@ -25,5 +28,5 @@ export function usePassThroughMouseOverEvents(ref: RefObject<HTMLElement>) {
|
|
|
25
28
|
return () => {
|
|
26
29
|
elm.removeEventListener('mouseover', onMouseOver)
|
|
27
30
|
}
|
|
28
|
-
}, [container, ref])
|
|
31
|
+
}, [container, editor, ref])
|
|
29
32
|
}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { RefObject, useEffect } from 'react'
|
|
2
2
|
import { preventDefault } from '../utils/dom'
|
|
3
3
|
import { useContainer } from './useContainer'
|
|
4
|
+
import { useMaybeEditor } from './useEditor'
|
|
4
5
|
|
|
5
6
|
/** @public */
|
|
6
7
|
export function usePassThroughWheelEvents(ref: RefObject<HTMLElement>) {
|
|
7
8
|
if (!ref) throw Error('usePassThroughWheelEvents must be passed a ref')
|
|
8
9
|
const container = useContainer()
|
|
10
|
+
const editor = useMaybeEditor()
|
|
9
11
|
|
|
10
12
|
useEffect(() => {
|
|
11
13
|
function onWheel(e: WheelEvent) {
|
|
14
|
+
// Only pass through wheel events if the editor is focused
|
|
15
|
+
if (!editor?.getInstanceState().isFocused) return
|
|
16
|
+
|
|
12
17
|
if ((e as any).isSpecialRedispatchedEvent) return
|
|
13
18
|
|
|
14
19
|
// if the element is scrollable, don't redispatch the event
|
|
@@ -32,5 +37,5 @@ export function usePassThroughWheelEvents(ref: RefObject<HTMLElement>) {
|
|
|
32
37
|
return () => {
|
|
33
38
|
elm.removeEventListener('wheel', onWheel)
|
|
34
39
|
}
|
|
35
|
-
}, [container, ref])
|
|
40
|
+
}, [container, editor, ref])
|
|
36
41
|
}
|