@tldraw/editor 3.12.0-canary.3e2ed74b5e86 → 3.12.0-canary.423f9b4f2a86
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 +12 -78
- package/dist-cjs/index.js +1 -3
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/GeometryDebuggingView.js +2 -2
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +8 -39
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +13 -1
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +16 -133
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +3 -3
- package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -54
- package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +0 -20
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/utils/reorderShapes.js +8 -2
- package/dist-cjs/lib/utils/reorderShapes.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 +12 -78
- package/dist-esm/index.mjs +2 -8
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +3 -3
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +8 -39
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +13 -1
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +14 -137
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Group2d.mjs +12 -55
- package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +0 -20
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/utils/reorderShapes.mjs +8 -2
- package/dist-esm/lib/utils/reorderShapes.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 -6
- package/src/lib/components/GeometryDebuggingView.tsx +3 -3
- package/src/lib/editor/Editor.ts +15 -44
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +15 -3
- package/src/lib/primitives/geometry/Geometry2d.ts +16 -196
- package/src/lib/primitives/geometry/Group2d.ts +13 -76
- package/src/lib/primitives/intersect.ts +0 -41
- package/src/lib/utils/reorderShapes.ts +9 -2
- package/src/version.ts +3 -3
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { EMPTY_ARRAY } from '@tldraw/state'
|
|
2
1
|
import { Box } from '../Box'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Geometry2d, Geometry2dFilters, Geometry2dOptions } from './Geometry2d'
|
|
2
|
+
import { Vec } from '../Vec'
|
|
3
|
+
import { Geometry2d, Geometry2dOptions } from './Geometry2d'
|
|
6
4
|
|
|
7
5
|
/** @public */
|
|
8
6
|
export class Group2d extends Geometry2d {
|
|
@@ -27,14 +25,11 @@ export class Group2d extends Geometry2d {
|
|
|
27
25
|
if (this.children.length === 0) throw Error('Group2d must have at least one child')
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
override getVertices(
|
|
31
|
-
|
|
32
|
-
return this.children
|
|
33
|
-
.filter((c) => !c.isExcludedByFilter(filters))
|
|
34
|
-
.flatMap((c) => c.getVertices(filters))
|
|
28
|
+
override getVertices(): Vec[] {
|
|
29
|
+
return this.children.filter((c) => !c.isLabel).flatMap((c) => c.vertices)
|
|
35
30
|
}
|
|
36
31
|
|
|
37
|
-
override nearestPoint(point: Vec
|
|
32
|
+
override nearestPoint(point: Vec): Vec {
|
|
38
33
|
let dist = Infinity
|
|
39
34
|
let nearest: Vec | undefined
|
|
40
35
|
|
|
@@ -47,8 +42,7 @@ export class Group2d extends Geometry2d {
|
|
|
47
42
|
let p: Vec
|
|
48
43
|
let d: number
|
|
49
44
|
for (const child of children) {
|
|
50
|
-
|
|
51
|
-
p = child.nearestPoint(point, filters)
|
|
45
|
+
p = child.nearestPoint(point)
|
|
52
46
|
d = Vec.Dist2(p, point)
|
|
53
47
|
if (d < dist) {
|
|
54
48
|
dist = d
|
|
@@ -59,75 +53,18 @@ export class Group2d extends Geometry2d {
|
|
|
59
53
|
return nearest
|
|
60
54
|
}
|
|
61
55
|
|
|
62
|
-
override distanceToPoint(point: Vec, hitInside = false
|
|
63
|
-
|
|
64
|
-
for (const child of this.children) {
|
|
65
|
-
if (child.isExcludedByFilter(filters)) continue
|
|
66
|
-
const distance = child.distanceToPoint(point, hitInside, filters)
|
|
67
|
-
if (distance < smallestDistance) {
|
|
68
|
-
smallestDistance = distance
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return smallestDistance
|
|
56
|
+
override distanceToPoint(point: Vec, hitInside = false) {
|
|
57
|
+
return Math.min(...this.children.map((c, i) => c.distanceToPoint(point, hitInside || i > 0)))
|
|
72
58
|
}
|
|
73
59
|
|
|
74
|
-
override hitTestPoint(
|
|
75
|
-
point: Vec,
|
|
76
|
-
margin: number,
|
|
77
|
-
hitInside: boolean,
|
|
78
|
-
filters = Geometry2dFilters.EXCLUDE_LABELS
|
|
79
|
-
): boolean {
|
|
60
|
+
override hitTestPoint(point: Vec, margin: number, hitInside: boolean): boolean {
|
|
80
61
|
return !!this.children
|
|
81
|
-
.filter((c) => !c.
|
|
62
|
+
.filter((c) => !c.isLabel)
|
|
82
63
|
.find((c) => c.hitTestPoint(point, margin, hitInside))
|
|
83
64
|
}
|
|
84
65
|
|
|
85
|
-
override hitTestLineSegment(
|
|
86
|
-
A
|
|
87
|
-
B: Vec,
|
|
88
|
-
zoom: number,
|
|
89
|
-
filters = Geometry2dFilters.EXCLUDE_LABELS
|
|
90
|
-
): boolean {
|
|
91
|
-
return !!this.children
|
|
92
|
-
.filter((c) => !c.isExcludedByFilter(filters))
|
|
93
|
-
.find((c) => c.hitTestLineSegment(A, B, zoom))
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
override intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {
|
|
97
|
-
return this.children.flatMap((child) => {
|
|
98
|
-
if (child.isExcludedByFilter(filters)) return EMPTY_ARRAY
|
|
99
|
-
return child.intersectLineSegment(A, B, filters)
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
override intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {
|
|
104
|
-
return this.children.flatMap((child) => {
|
|
105
|
-
if (child.isExcludedByFilter(filters)) return EMPTY_ARRAY
|
|
106
|
-
return child.intersectCircle(center, radius, filters)
|
|
107
|
-
})
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
override intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters) {
|
|
111
|
-
return this.children.flatMap((child) => {
|
|
112
|
-
if (child.isExcludedByFilter(filters)) return EMPTY_ARRAY
|
|
113
|
-
return child.intersectPolygon(polygon, filters)
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
override intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters) {
|
|
118
|
-
return this.children.flatMap((child) => {
|
|
119
|
-
if (child.isExcludedByFilter(filters)) return EMPTY_ARRAY
|
|
120
|
-
return child.intersectPolyline(polyline, filters)
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
override transform(transform: Mat): Geometry2d {
|
|
125
|
-
return new Group2d({
|
|
126
|
-
children: this.children.map((c) => c.transform(transform)),
|
|
127
|
-
isLabel: this.isLabel,
|
|
128
|
-
debugColor: this.debugColor,
|
|
129
|
-
ignore: this.ignore,
|
|
130
|
-
})
|
|
66
|
+
override hitTestLineSegment(A: Vec, B: Vec, zoom: number): boolean {
|
|
67
|
+
return !!this.children.filter((c) => !c.isLabel).find((c) => c.hitTestLineSegment(A, B, zoom))
|
|
131
68
|
}
|
|
132
69
|
|
|
133
70
|
getArea() {
|
|
@@ -165,6 +102,6 @@ export class Group2d extends Geometry2d {
|
|
|
165
102
|
}
|
|
166
103
|
|
|
167
104
|
getSvgPathData(): string {
|
|
168
|
-
return this.children.map((c
|
|
105
|
+
return this.children.map((c) => (c.isLabel ? '' : c.getSvgPathData(true))).join(' ')
|
|
169
106
|
}
|
|
170
107
|
}
|
|
@@ -293,47 +293,6 @@ export function intersectPolygonPolygon(
|
|
|
293
293
|
return orderClockwise([...result.values()])
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
/**
|
|
297
|
-
* Find all the points where `polyA` and `polyB` intersect and returns them in an undefined order.
|
|
298
|
-
* To find the polygon that's the intersection of polyA and polyB, use `intersectPolygonPolygon`
|
|
299
|
-
* instead, which orders the points and includes internal points.
|
|
300
|
-
*
|
|
301
|
-
* @param polyA - The first polygon.
|
|
302
|
-
* @param polyB - The second polygon.
|
|
303
|
-
* @param isAClosed - Whether `polyA` is a closed polygon or a polyline.
|
|
304
|
-
* @param isBClosed - Whether `polyB` is a closed polygon or a polyline.
|
|
305
|
-
* @public
|
|
306
|
-
*/
|
|
307
|
-
export function intersectPolys(
|
|
308
|
-
polyA: VecLike[],
|
|
309
|
-
polyB: VecLike[],
|
|
310
|
-
isAClosed: boolean,
|
|
311
|
-
isBClosed: boolean
|
|
312
|
-
): VecLike[] {
|
|
313
|
-
const result: Map<string, VecLike> = new Map()
|
|
314
|
-
|
|
315
|
-
// Add all intersection points to result
|
|
316
|
-
for (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {
|
|
317
|
-
const currentA = polyA[i]
|
|
318
|
-
const nextA = polyA[(i + 1) % polyA.length]
|
|
319
|
-
|
|
320
|
-
for (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {
|
|
321
|
-
const currentB = polyB[j]
|
|
322
|
-
const nextB = polyB[(j + 1) % polyB.length]
|
|
323
|
-
const intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB)
|
|
324
|
-
|
|
325
|
-
if (intersection !== null) {
|
|
326
|
-
const id = getPointId(intersection)
|
|
327
|
-
if (!result.has(id)) {
|
|
328
|
-
result.set(id, intersection)
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
return [...result.values()]
|
|
335
|
-
}
|
|
336
|
-
|
|
337
296
|
function getPointId(point: VecLike) {
|
|
338
297
|
return `${point.x},${point.y}`
|
|
339
298
|
}
|
|
@@ -154,17 +154,24 @@ function reorderToFront(moving: Set<TLShape>, children: TLShape[], changes: TLSh
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
function getVerticesInPageSpace(editor: Editor, shape: TLShape) {
|
|
158
|
+
const geo = editor.getShapeGeometry(shape)
|
|
159
|
+
const pageTransform = editor.getShapePageTransform(shape)
|
|
160
|
+
if (!geo || !pageTransform) return null
|
|
161
|
+
return pageTransform.applyToPoints(geo.vertices)
|
|
162
|
+
}
|
|
163
|
+
|
|
157
164
|
function getOverlapChecker(editor: Editor, moving: Set<TLShape>) {
|
|
158
165
|
const movingVertices = Array.from(moving)
|
|
159
166
|
.map((shape) => {
|
|
160
|
-
const vertices = editor
|
|
167
|
+
const vertices = getVerticesInPageSpace(editor, shape)
|
|
161
168
|
if (!vertices) return null
|
|
162
169
|
return { shape, vertices }
|
|
163
170
|
})
|
|
164
171
|
.filter(Boolean) as { shape: TLShape; vertices: Vec[] }[]
|
|
165
172
|
|
|
166
173
|
const isOverlapping = (child: TLShape) => {
|
|
167
|
-
const vertices = editor
|
|
174
|
+
const vertices = getVerticesInPageSpace(editor, child)
|
|
168
175
|
if (!vertices) return false
|
|
169
176
|
return movingVertices.some((other) => {
|
|
170
177
|
return polygonsIntersect(other.vertices, vertices)
|
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.12.0-canary.
|
|
4
|
+
export const version = '3.12.0-canary.423f9b4f2a86'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-04-03T13:
|
|
8
|
-
patch: '2025-04-03T13:
|
|
7
|
+
minor: '2025-04-03T13:02:18.145Z',
|
|
8
|
+
patch: '2025-04-03T13:02:18.145Z',
|
|
9
9
|
}
|