@tldraw/editor 3.16.0-canary.bf9fb05eb8ef → 3.16.0-canary.c2c4563957ce
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 +24 -101
- package/dist-cjs/index.js +1 -5
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +0 -4
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +14 -109
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- 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/hooks/usePassThroughMouseOverEvents.js +4 -1
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
- package/dist-cjs/lib/license/LicenseManager.js +17 -22
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/license/LicenseProvider.js +5 -0
- package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +4 -4
- package/dist-cjs/lib/license/Watermark.js.map +1 -1
- package/dist-cjs/lib/license/useLicenseManagerState.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 +26 -18
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Group2d.js +3 -0
- 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 +24 -101
- package/dist-esm/index.mjs +1 -5
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +0 -4
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +14 -109
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.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/license/LicenseManager.mjs +17 -22
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/license/LicenseProvider.mjs +5 -0
- package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +4 -4
- package/dist-esm/lib/license/Watermark.mjs.map +1 -1
- package/dist-esm/lib/license/useLicenseManagerState.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 +29 -19
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +3 -0
- 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/package.json +7 -7
- package/src/index.ts +1 -9
- package/src/lib/TldrawEditor.tsx +0 -11
- package/src/lib/editor/Editor.ts +20 -146
- package/src/lib/editor/shapes/ShapeUtil.ts +21 -0
- package/src/lib/editor/types/misc-types.ts +0 -6
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
- package/src/lib/license/LicenseManager.test.ts +58 -51
- package/src/lib/license/LicenseManager.ts +32 -24
- package/src/lib/license/LicenseProvider.tsx +8 -0
- package/src/lib/license/Watermark.tsx +4 -4
- package/src/lib/license/useLicenseManagerState.ts +2 -2
- package/src/lib/primitives/Vec.ts +0 -5
- package/src/lib/primitives/geometry/Geometry2d.ts +49 -19
- package/src/lib/primitives/geometry/Group2d.ts +4 -0
- package/src/lib/utils/reparenting.ts +3 -69
- package/src/version.ts +3 -3
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useValue } from '@tldraw/state-react'
|
|
1
2
|
import { createContext, ReactNode, useContext, useState } from 'react'
|
|
2
3
|
import { LicenseManager } from './LicenseManager'
|
|
3
4
|
|
|
@@ -16,5 +17,12 @@ export function LicenseProvider({
|
|
|
16
17
|
children: ReactNode
|
|
17
18
|
}) {
|
|
18
19
|
const [licenseManager] = useState(() => new LicenseManager(licenseKey))
|
|
20
|
+
const licenseState = useValue(licenseManager.state)
|
|
21
|
+
|
|
22
|
+
// If internal license has expired, don't render the editor at all
|
|
23
|
+
if (licenseState === 'internal-expired') {
|
|
24
|
+
return <div data-testid="tl-license-expired" style={{ display: 'none' }} />
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
return <LicenseContext.Provider value={licenseManager}>{children}</LicenseContext.Provider>
|
|
20
28
|
}
|
|
@@ -86,8 +86,8 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
86
86
|
|
|
87
87
|
.${className} {
|
|
88
88
|
position: absolute;
|
|
89
|
-
bottom: var(--tl-space-2);
|
|
90
|
-
right: var(--tl-space-2);
|
|
89
|
+
bottom: max(var(--tl-space-2), env(safe-area-inset-bottom));
|
|
90
|
+
right: max(var(--tl-space-2), env(safe-area-inset-right));
|
|
91
91
|
width: 96px;
|
|
92
92
|
height: 32px;
|
|
93
93
|
display: flex;
|
|
@@ -116,12 +116,12 @@ To remove the watermark, please purchase a license at tldraw.dev.
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
.${className}[data-debug='true'] {
|
|
119
|
-
bottom: 46px;
|
|
119
|
+
bottom: max(46px, env(safe-area-inset-bottom));
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
.${className}[data-mobile='true'] {
|
|
123
123
|
border-radius: 4px 0px 0px 4px;
|
|
124
|
-
right: -2px;
|
|
124
|
+
right: max(-2px, calc(env(safe-area-inset-right) - 2px));
|
|
125
125
|
width: 8px;
|
|
126
126
|
height: 48px;
|
|
127
127
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useValue } from '@tldraw/state-react'
|
|
2
|
-
import { LicenseManager } from './LicenseManager'
|
|
2
|
+
import { LicenseManager, LicenseState } from './LicenseManager'
|
|
3
3
|
|
|
4
4
|
/** @internal */
|
|
5
|
-
export function useLicenseManagerState(licenseManager: LicenseManager) {
|
|
5
|
+
export function useLicenseManagerState(licenseManager: LicenseManager): LicenseState {
|
|
6
6
|
return useValue('watermarkState', () => licenseManager.state.get(), [licenseManager])
|
|
7
7
|
}
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
intersectLineSegmentPolyline,
|
|
10
10
|
intersectPolys,
|
|
11
11
|
linesIntersect,
|
|
12
|
+
polygonIntersectsPolyline,
|
|
13
|
+
polygonsIntersect,
|
|
12
14
|
} from '../intersect'
|
|
13
15
|
import { approximately, pointInPolygon } from '../utils'
|
|
14
16
|
|
|
@@ -227,25 +229,6 @@ export abstract class Geometry2d {
|
|
|
227
229
|
return distanceAlongRoute / length
|
|
228
230
|
}
|
|
229
231
|
|
|
230
|
-
/** @deprecated Iterate the vertices instead. */
|
|
231
|
-
nearestPointOnLineSegment(A: VecLike, B: VecLike): Vec {
|
|
232
|
-
const { vertices } = this
|
|
233
|
-
let nearest: Vec | undefined
|
|
234
|
-
let dist = Infinity
|
|
235
|
-
let d: number, p: Vec, q: Vec
|
|
236
|
-
for (let i = 0; i < vertices.length; i++) {
|
|
237
|
-
p = vertices[i]
|
|
238
|
-
q = Vec.NearestPointOnLineSegment(A, B, p, true)
|
|
239
|
-
d = Vec.Dist2(p, q)
|
|
240
|
-
if (d < dist) {
|
|
241
|
-
dist = d
|
|
242
|
-
nearest = q
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
if (!nearest) throw Error('nearest point not found')
|
|
246
|
-
return nearest
|
|
247
|
-
}
|
|
248
|
-
|
|
249
232
|
isPointInBounds(point: VecLike, margin = 0) {
|
|
250
233
|
const { bounds } = this
|
|
251
234
|
return !(
|
|
@@ -256,6 +239,53 @@ export abstract class Geometry2d {
|
|
|
256
239
|
)
|
|
257
240
|
}
|
|
258
241
|
|
|
242
|
+
overlapsPolygon(_polygon: VecLike[]): boolean {
|
|
243
|
+
const polygon = _polygon.map((v) => Vec.From(v))
|
|
244
|
+
|
|
245
|
+
// Otherwise, check if the geometry itself overlaps the polygon
|
|
246
|
+
const { vertices, center, isFilled, isEmptyLabel, isClosed } = this
|
|
247
|
+
|
|
248
|
+
// We'll do things in order of cheapest to most expensive checks
|
|
249
|
+
|
|
250
|
+
// Skip empty labels
|
|
251
|
+
if (isEmptyLabel) return false
|
|
252
|
+
|
|
253
|
+
// If any of the geometry's vertices are inside the polygon, it's inside
|
|
254
|
+
if (vertices.some((v) => pointInPolygon(v, polygon))) {
|
|
255
|
+
return true
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// If the geometry is filled and closed and its center is inside the polygon, it's inside
|
|
259
|
+
if (isClosed) {
|
|
260
|
+
if (isFilled) {
|
|
261
|
+
// If closed and filled, check if the center is inside the polygon
|
|
262
|
+
if (pointInPolygon(center, polygon)) {
|
|
263
|
+
return true
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ..then, slightly more expensive check, see the geometry covers the entire polygon but not its center
|
|
267
|
+
if (polygon.every((v) => pointInPolygon(v, vertices))) {
|
|
268
|
+
return true
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// If any the geometry's vertices intersect the edge of the polygon, it's inside.
|
|
273
|
+
// for example when a rotated rectangle is moved over the corner of a parent rectangle
|
|
274
|
+
// If the geometry is closed, intersect as a polygon
|
|
275
|
+
if (polygonsIntersect(polygon, vertices)) {
|
|
276
|
+
return true
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
// If the geometry is not closed, intersect as a polyline
|
|
280
|
+
if (polygonIntersectsPolyline(polygon, vertices)) {
|
|
281
|
+
return true
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// If none of the above checks passed, the geometry is outside the polygon
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
288
|
+
|
|
259
289
|
transform(transform: MatModel, opts?: TransformedGeometry2dOptions): Geometry2d {
|
|
260
290
|
return new TransformedGeometry2d(this, transform, opts)
|
|
261
291
|
}
|
|
@@ -236,4 +236,8 @@ export class Group2d extends Geometry2d {
|
|
|
236
236
|
getSvgPathData(): string {
|
|
237
237
|
return this.children.map((c, i) => (c.isLabel ? '' : c.getSvgPathData(i === 0))).join(' ')
|
|
238
238
|
}
|
|
239
|
+
|
|
240
|
+
overlapsPolygon(polygon: VecLike[]): boolean {
|
|
241
|
+
return this.children.some((child) => child.overlapsPolygon(polygon))
|
|
242
|
+
}
|
|
239
243
|
}
|
|
@@ -2,15 +2,7 @@ import { EMPTY_ARRAY } from '@tldraw/state'
|
|
|
2
2
|
import { TLGroupShape, TLParentId, TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { IndexKey, compact, getIndexAbove, getIndexBetween } from '@tldraw/utils'
|
|
4
4
|
import { Editor } from '../editor/Editor'
|
|
5
|
-
import {
|
|
6
|
-
import { Geometry2d } from '../primitives/geometry/Geometry2d'
|
|
7
|
-
import { Group2d } from '../primitives/geometry/Group2d'
|
|
8
|
-
import {
|
|
9
|
-
intersectPolygonPolygon,
|
|
10
|
-
polygonIntersectsPolyline,
|
|
11
|
-
polygonsIntersect,
|
|
12
|
-
} from '../primitives/intersect'
|
|
13
|
-
import { pointInPolygon } from '../primitives/utils'
|
|
5
|
+
import { intersectPolygonPolygon } from '../primitives/intersect'
|
|
14
6
|
|
|
15
7
|
/**
|
|
16
8
|
* Reparents shapes that are no longer contained within their parent shapes.
|
|
@@ -189,68 +181,10 @@ function getOverlappingShapes<T extends TLShape[] | TLShapeId[]>(
|
|
|
189
181
|
|
|
190
182
|
const geometry = editor.getShapeGeometry(childId)
|
|
191
183
|
|
|
192
|
-
return
|
|
184
|
+
return geometry.overlapsPolygon(parentPolygonInShapeShape)
|
|
193
185
|
})
|
|
194
186
|
}
|
|
195
187
|
|
|
196
|
-
/**
|
|
197
|
-
* @public
|
|
198
|
-
*/
|
|
199
|
-
export function doesGeometryOverlapPolygon(
|
|
200
|
-
geometry: Geometry2d,
|
|
201
|
-
parentCornersInShapeSpace: Vec[]
|
|
202
|
-
): boolean {
|
|
203
|
-
// If the child is a group, check if any of its children overlap the box
|
|
204
|
-
if (geometry instanceof Group2d) {
|
|
205
|
-
return geometry.children.some((childGeometry) =>
|
|
206
|
-
doesGeometryOverlapPolygon(childGeometry, parentCornersInShapeSpace)
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Otherwise, check if the geometry overlaps the box
|
|
211
|
-
const { vertices, center, isFilled, isEmptyLabel, isClosed } = geometry
|
|
212
|
-
|
|
213
|
-
// We'll do things in order of cheapest to most expensive checks
|
|
214
|
-
|
|
215
|
-
// Skip empty labels
|
|
216
|
-
if (isEmptyLabel) return false
|
|
217
|
-
|
|
218
|
-
// If any of the shape's vertices are inside the occluder, it's inside
|
|
219
|
-
if (vertices.some((v) => pointInPolygon(v, parentCornersInShapeSpace))) {
|
|
220
|
-
return true
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// If the shape is filled and closed and its center is inside the parent, it's inside
|
|
224
|
-
if (isClosed) {
|
|
225
|
-
if (isFilled) {
|
|
226
|
-
// If closed and filled, check if the center is inside the parent
|
|
227
|
-
if (pointInPolygon(center, parentCornersInShapeSpace)) {
|
|
228
|
-
return true
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// ..then, slightly more expensive check, see the shape covers the entire parent but not its center
|
|
232
|
-
if (parentCornersInShapeSpace.every((v) => pointInPolygon(v, vertices))) {
|
|
233
|
-
return true
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// If any the shape's vertices intersect the edge of the occluder, it's inside.
|
|
238
|
-
// for example when a rotated rectangle is moved over the corner of a parent rectangle
|
|
239
|
-
// If the child shape is closed, intersect as a polygon
|
|
240
|
-
if (polygonsIntersect(parentCornersInShapeSpace, vertices)) {
|
|
241
|
-
return true
|
|
242
|
-
}
|
|
243
|
-
} else {
|
|
244
|
-
// if the child shape is not closed, intersect as a polyline
|
|
245
|
-
if (polygonIntersectsPolyline(parentCornersInShapeSpace, vertices)) {
|
|
246
|
-
return true
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// If none of the above checks passed, the shape is outside the parent
|
|
251
|
-
return false
|
|
252
|
-
}
|
|
253
|
-
|
|
254
188
|
/**
|
|
255
189
|
* Get the shapes that will be reparented to new parents when the shapes are dropped.
|
|
256
190
|
*
|
|
@@ -354,7 +288,7 @@ export function getDroppedShapesToNewParents(
|
|
|
354
288
|
.applyToPoints(parentPagePolygon)
|
|
355
289
|
|
|
356
290
|
// If the shape overlaps the parent polygon, reparent it to that parent
|
|
357
|
-
if (
|
|
291
|
+
if (editor.getShapeGeometry(shape).overlapsPolygon(parentPolygonInShapeSpace)) {
|
|
358
292
|
// Use the util to check if the shape can be reparented to the parent
|
|
359
293
|
if (
|
|
360
294
|
!editor.getShapeUtil(parentShape).canReceiveNewChildrenOfType?.(parentShape, shape.type)
|
package/src/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '3.16.0-canary.
|
|
4
|
+
export const version = '3.16.0-canary.c2c4563957ce'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-
|
|
8
|
-
patch: '2025-
|
|
7
|
+
minor: '2025-09-03T11:25:43.960Z',
|
|
8
|
+
patch: '2025-09-03T11:25:43.960Z',
|
|
9
9
|
}
|