@tldraw/editor 4.5.2 → 4.6.0-canary.4ec045c286e1

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.
Files changed (226) hide show
  1. package/dist-cjs/index.d.ts +37 -6
  2. package/dist-cjs/index.js +6 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +7 -5
  5. package/dist-cjs/lib/TldrawEditor.js.map +3 -3
  6. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -2
  7. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +8 -5
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  12. package/dist-cjs/lib/config/TLSessionStateSnapshot.js +8 -5
  13. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +2 -2
  14. package/dist-cjs/lib/config/TLUserPreferences.js +3 -2
  15. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  16. package/dist-cjs/lib/config/createTLStore.js +1 -0
  17. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  18. package/dist-cjs/lib/editor/Editor.js +52 -16
  19. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +62 -6
  21. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +4 -3
  23. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +5 -0
  25. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  26. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -2
  27. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +3 -2
  29. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  30. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  31. package/dist-cjs/lib/exports/FontEmbedder.js +9 -8
  32. package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
  33. package/dist-cjs/lib/exports/StyleEmbedder.js +27 -15
  34. package/dist-cjs/lib/exports/StyleEmbedder.js.map +3 -3
  35. package/dist-cjs/lib/exports/domUtils.js +15 -0
  36. package/dist-cjs/lib/exports/domUtils.js.map +2 -2
  37. package/dist-cjs/lib/exports/embedMedia.js +15 -12
  38. package/dist-cjs/lib/exports/embedMedia.js.map +2 -2
  39. package/dist-cjs/lib/exports/exportToSvg.js +8 -7
  40. package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
  41. package/dist-cjs/lib/exports/getSvgAsImage.js +181 -29
  42. package/dist-cjs/lib/exports/getSvgAsImage.js.map +3 -3
  43. package/dist-cjs/lib/exports/getSvgJsx.js +21 -9
  44. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  45. package/dist-cjs/lib/globals/environment.js +4 -3
  46. package/dist-cjs/lib/globals/environment.js.map +2 -2
  47. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
  48. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  49. package/dist-cjs/lib/hooks/useDocumentEvents.js +13 -11
  50. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +3 -2
  52. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  53. package/dist-cjs/lib/hooks/useScreenBounds.js +10 -6
  54. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  55. package/dist-cjs/lib/hooks/useViewportHeight.js +13 -11
  56. package/dist-cjs/lib/hooks/useViewportHeight.js.map +3 -3
  57. package/dist-cjs/lib/license/Watermark.js +10 -0
  58. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  59. package/dist-cjs/lib/primitives/Vec.js +35 -22
  60. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  61. package/dist-cjs/lib/primitives/geometry/Arc2d.js +6 -13
  62. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  63. package/dist-cjs/lib/primitives/geometry/Circle2d.js +31 -2
  64. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  65. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +9 -0
  66. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  67. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +9 -0
  68. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  69. package/dist-cjs/lib/primitives/geometry/Edge2d.js +32 -18
  70. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  71. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +12 -0
  72. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  73. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +51 -12
  74. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  75. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +12 -0
  76. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  77. package/dist-cjs/lib/primitives/geometry/geometry.bench.js +133 -0
  78. package/dist-cjs/lib/primitives/geometry/geometry.bench.js.map +7 -0
  79. package/dist-cjs/lib/primitives/intersect.js +16 -15
  80. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  81. package/dist-cjs/lib/primitives/utils.js +0 -1
  82. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  83. package/dist-cjs/lib/utils/browserCanvasMaxSize.js +3 -2
  84. package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
  85. package/dist-cjs/lib/utils/dom.js +15 -2
  86. package/dist-cjs/lib/utils/dom.js.map +2 -2
  87. package/dist-cjs/version.js +3 -3
  88. package/dist-cjs/version.js.map +1 -1
  89. package/dist-esm/index.d.mts +37 -6
  90. package/dist-esm/index.mjs +8 -1
  91. package/dist-esm/index.mjs.map +2 -2
  92. package/dist-esm/lib/TldrawEditor.mjs +7 -5
  93. package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
  94. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +2 -1
  95. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
  96. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  97. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  98. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +8 -5
  99. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  100. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +8 -5
  101. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  102. package/dist-esm/lib/config/TLUserPreferences.mjs +3 -2
  103. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  104. package/dist-esm/lib/config/createTLStore.mjs +1 -0
  105. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  106. package/dist-esm/lib/editor/Editor.mjs +53 -17
  107. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  108. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +64 -6
  109. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
  110. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +4 -3
  111. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  112. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +5 -0
  113. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  114. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -2
  115. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  116. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +3 -2
  117. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  118. package/dist-esm/lib/exports/FontEmbedder.mjs +9 -8
  119. package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
  120. package/dist-esm/lib/exports/StyleEmbedder.mjs +29 -16
  121. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +3 -3
  122. package/dist-esm/lib/exports/domUtils.mjs +15 -0
  123. package/dist-esm/lib/exports/domUtils.mjs.map +2 -2
  124. package/dist-esm/lib/exports/embedMedia.mjs +16 -13
  125. package/dist-esm/lib/exports/embedMedia.mjs.map +2 -2
  126. package/dist-esm/lib/exports/exportToSvg.mjs +8 -7
  127. package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
  128. package/dist-esm/lib/exports/getSvgAsImage.mjs +181 -29
  129. package/dist-esm/lib/exports/getSvgAsImage.mjs.map +3 -3
  130. package/dist-esm/lib/exports/getSvgJsx.mjs +21 -9
  131. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  132. package/dist-esm/lib/globals/environment.mjs +4 -3
  133. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  134. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
  135. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  136. package/dist-esm/lib/hooks/useDocumentEvents.mjs +13 -11
  137. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  138. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +3 -2
  139. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  140. package/dist-esm/lib/hooks/useScreenBounds.mjs +10 -6
  141. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  142. package/dist-esm/lib/hooks/useViewportHeight.mjs +13 -11
  143. package/dist-esm/lib/hooks/useViewportHeight.mjs.map +3 -3
  144. package/dist-esm/lib/license/Watermark.mjs +10 -0
  145. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  146. package/dist-esm/lib/primitives/Vec.mjs +35 -22
  147. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  148. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +6 -13
  149. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  150. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +31 -2
  151. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  152. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +9 -0
  153. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  154. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +9 -0
  155. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  156. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +32 -18
  157. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  158. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +13 -1
  159. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  160. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +51 -12
  161. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  162. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +13 -1
  163. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  164. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs +132 -0
  165. package/dist-esm/lib/primitives/geometry/geometry.bench.mjs.map +7 -0
  166. package/dist-esm/lib/primitives/intersect.mjs +17 -16
  167. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  168. package/dist-esm/lib/primitives/utils.mjs +0 -1
  169. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  170. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +3 -2
  171. package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
  172. package/dist-esm/lib/utils/dom.mjs +15 -2
  173. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  174. package/dist-esm/version.mjs +3 -3
  175. package/dist-esm/version.mjs.map +1 -1
  176. package/package.json +7 -7
  177. package/src/index.ts +3 -0
  178. package/src/lib/TldrawEditor.tsx +7 -5
  179. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +2 -1
  180. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  181. package/src/lib/components/default-components/DefaultErrorFallback.tsx +8 -5
  182. package/src/lib/config/TLSessionStateSnapshot.ts +8 -5
  183. package/src/lib/config/TLUserPreferences.ts +3 -2
  184. package/src/lib/config/createTLStore.ts +3 -0
  185. package/src/lib/editor/Editor.ts +53 -15
  186. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +7 -6
  187. package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -7
  188. package/src/lib/editor/managers/FontManager/FontManager.test.ts +1 -0
  189. package/src/lib/editor/managers/FontManager/FontManager.ts +4 -3
  190. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +16 -0
  191. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +7 -2
  192. package/src/lib/editor/managers/TextManager/TextManager.test.ts +4 -5
  193. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -2
  194. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +3 -2
  195. package/src/lib/editor/types/misc-types.ts +8 -2
  196. package/src/lib/exports/FontEmbedder.ts +10 -9
  197. package/src/lib/exports/StyleEmbedder.ts +33 -15
  198. package/src/lib/exports/domUtils.ts +20 -0
  199. package/src/lib/exports/embedMedia.ts +23 -17
  200. package/src/lib/exports/exportToSvg.tsx +8 -7
  201. package/src/lib/exports/getSvgAsImage.ts +292 -32
  202. package/src/lib/exports/getSvgJsx.test.ts +103 -101
  203. package/src/lib/exports/getSvgJsx.tsx +33 -10
  204. package/src/lib/globals/environment.ts +4 -3
  205. package/src/lib/hooks/useCanvasEvents.ts +2 -3
  206. package/src/lib/hooks/useDocumentEvents.ts +16 -11
  207. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +3 -3
  208. package/src/lib/hooks/useScreenBounds.ts +10 -6
  209. package/src/lib/hooks/useViewportHeight.ts +13 -11
  210. package/src/lib/license/Watermark.tsx +10 -0
  211. package/src/lib/primitives/Vec.ts +51 -24
  212. package/src/lib/primitives/geometry/Arc2d.ts +10 -15
  213. package/src/lib/primitives/geometry/Circle2d.ts +40 -2
  214. package/src/lib/primitives/geometry/CubicBezier2d.ts +10 -0
  215. package/src/lib/primitives/geometry/CubicSpline2d.ts +10 -0
  216. package/src/lib/primitives/geometry/Edge2d.ts +41 -18
  217. package/src/lib/primitives/geometry/Ellipse2d.ts +14 -1
  218. package/src/lib/primitives/geometry/Polyline2d.ts +60 -12
  219. package/src/lib/primitives/geometry/Stadium2d.ts +14 -1
  220. package/src/lib/primitives/geometry/geometry.bench.ts +179 -0
  221. package/src/lib/primitives/intersect.ts +27 -27
  222. package/src/lib/primitives/utils.ts +4 -4
  223. package/src/lib/test/TestEditor.ts +1 -0
  224. package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
  225. package/src/lib/utils/dom.ts +34 -2
  226. package/src/version.ts +3 -3
@@ -0,0 +1,179 @@
1
+ import { bench, describe } from 'vitest'
2
+ import { Vec } from '../Vec'
3
+ import { Arc2d } from './Arc2d'
4
+ import { Circle2d } from './Circle2d'
5
+ import { Edge2d } from './Edge2d'
6
+ import { Polyline2d } from './Polyline2d'
7
+ import { Rectangle2d } from './Rectangle2d'
8
+
9
+ // --- Vec line segment utilities ---
10
+
11
+ const lsA = new Vec(0, 0)
12
+ const lsB = new Vec(100, 50)
13
+ const lsP = new Vec(30, 60)
14
+
15
+ describe('Vec line segment', () => {
16
+ bench('NearestPointOnLineSegment', () => {
17
+ Vec.NearestPointOnLineSegment(lsA, lsB, lsP, true)
18
+ })
19
+
20
+ bench('DistanceToLineSegment', () => {
21
+ Vec.DistanceToLineSegment(lsA, lsB, lsP, true)
22
+ })
23
+ })
24
+
25
+ // --- Vec utilities ---
26
+
27
+ const vecA = new Vec(3, 4)
28
+ const vecB = new Vec(-1, 2)
29
+ const lineOrigin = new Vec(10, 10)
30
+ const lineDir = new Vec(0.7071, 0.7071) // ~unit vector at 45°
31
+ const lineTestP = new Vec(20, 15)
32
+
33
+ describe('Vec utilities', () => {
34
+ bench('Lrp', () => {
35
+ Vec.Lrp(lsA, lsB, 0.35)
36
+ })
37
+
38
+ bench('AngleBetween', () => {
39
+ Vec.AngleBetween(vecA, vecB)
40
+ })
41
+
42
+ bench('NearestPointOnLineThroughPoint', () => {
43
+ Vec.NearestPointOnLineThroughPoint(lineOrigin, lineDir, lineTestP)
44
+ })
45
+
46
+ bench('DistanceToLineThroughPoint', () => {
47
+ Vec.DistanceToLineThroughPoint(lineOrigin, lineDir, lineTestP)
48
+ })
49
+ })
50
+
51
+ // --- Intersections ---
52
+
53
+ import { intersectLineSegmentCircle, intersectLineSegmentLineSegment } from '../intersect'
54
+
55
+ const intA1 = new Vec(0, 0)
56
+ const intA2 = new Vec(100, 100)
57
+ const intB1 = new Vec(100, 0)
58
+ const intB2 = new Vec(0, 100)
59
+ const intB1Miss = new Vec(200, 0)
60
+ const intB2Miss = new Vec(200, 100)
61
+ const intCenter = new Vec(50, 50)
62
+
63
+ describe('Intersections', () => {
64
+ bench('lineSegment-lineSegment (hit)', () => {
65
+ intersectLineSegmentLineSegment(intA1, intA2, intB1, intB2)
66
+ })
67
+
68
+ bench('lineSegment-lineSegment (miss)', () => {
69
+ intersectLineSegmentLineSegment(intA1, intA2, intB1Miss, intB2Miss)
70
+ })
71
+
72
+ bench('lineSegment-circle (hit)', () => {
73
+ intersectLineSegmentCircle(intA1, intA2, intCenter, 30)
74
+ })
75
+
76
+ bench('lineSegment-circle (miss)', () => {
77
+ intersectLineSegmentCircle(intA1, intA2, intCenter, 5)
78
+ })
79
+ })
80
+
81
+ // --- Edge2d ---
82
+
83
+ const edge = new Edge2d({ start: new Vec(0, 0), end: new Vec(100, 50) })
84
+ const edgePoint = new Vec(30, 60)
85
+
86
+ describe('Edge2d', () => {
87
+ bench('nearestPoint', () => {
88
+ edge.nearestPoint(edgePoint)
89
+ })
90
+
91
+ bench('distanceToPoint', () => {
92
+ edge.distanceToPoint(edgePoint)
93
+ })
94
+ })
95
+
96
+ // --- Circle2d ---
97
+
98
+ const circle = new Circle2d({ radius: 50, isFilled: true })
99
+ const circlePoint = new Vec(80, 60)
100
+ const circlePointInside = new Vec(50, 50)
101
+
102
+ describe('Circle2d', () => {
103
+ bench('nearestPoint', () => {
104
+ circle.nearestPoint(circlePoint)
105
+ })
106
+
107
+ bench('distanceToPoint', () => {
108
+ circle.distanceToPoint(circlePoint)
109
+ })
110
+
111
+ bench('hitTestPoint (outside)', () => {
112
+ circle.hitTestPoint(circlePoint, 5)
113
+ })
114
+
115
+ bench('hitTestPoint (inside)', () => {
116
+ circle.hitTestPoint(circlePointInside, 5, true)
117
+ })
118
+ })
119
+
120
+ // --- Arc2d ---
121
+
122
+ const arc = new Arc2d({
123
+ center: new Vec(50, 50),
124
+ start: new Vec(100, 50),
125
+ end: new Vec(50, 100),
126
+ sweepFlag: 1,
127
+ largeArcFlag: 0,
128
+ })
129
+ const arcPoint = new Vec(90, 90)
130
+
131
+ describe('Arc2d', () => {
132
+ bench('nearestPoint', () => {
133
+ arc.nearestPoint(arcPoint)
134
+ })
135
+ })
136
+
137
+ // --- Polyline2d (20 segments) ---
138
+
139
+ const polyPoints: Vec[] = []
140
+ for (let i = 0; i <= 20; i++) {
141
+ const t = i / 20
142
+ polyPoints.push(new Vec(t * 200, Math.sin(t * Math.PI * 2) * 50 + 50))
143
+ }
144
+ const polyline = new Polyline2d({ points: polyPoints })
145
+ const polyPoint = new Vec(100, 80)
146
+
147
+ describe('Polyline2d', () => {
148
+ bench('nearestPoint', () => {
149
+ polyline.nearestPoint(polyPoint)
150
+ })
151
+
152
+ bench('distanceToPoint', () => {
153
+ polyline.distanceToPoint(polyPoint)
154
+ })
155
+ })
156
+
157
+ // --- Rectangle2d (Geometry2d base) ---
158
+
159
+ const rect = new Rectangle2d({ width: 100, height: 80, isFilled: true })
160
+ const rectPointOutside = new Vec(120, 40)
161
+ const rectPointInside = new Vec(50, 40)
162
+
163
+ describe('Rectangle2d (Geometry2d)', () => {
164
+ bench('hitTestPoint (outside)', () => {
165
+ rect.hitTestPoint(rectPointOutside, 5)
166
+ })
167
+
168
+ bench('hitTestPoint (inside)', () => {
169
+ rect.hitTestPoint(rectPointInside, 5, true)
170
+ })
171
+
172
+ bench('distanceToPoint (outside)', () => {
173
+ rect.distanceToPoint(rectPointOutside)
174
+ })
175
+
176
+ bench('distanceToPoint (inside)', () => {
177
+ rect.distanceToPoint(rectPointInside, true)
178
+ })
179
+ })
@@ -1,5 +1,5 @@
1
1
  import { Box } from './Box'
2
- import { approximately, approximatelyLte, pointInPolygon } from './utils'
2
+ import { pointInPolygon } from './utils'
3
3
  import { Vec, VecLike } from './Vec'
4
4
 
5
5
  // need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52
@@ -30,21 +30,18 @@ export function intersectLineSegmentLineSegment(
30
30
  const ub_t = AVx * ABy - AVy * ABx
31
31
  const u_b = BVy * AVx - BVx * AVy
32
32
 
33
- if (approximately(ua_t, 0, precision) || approximately(ub_t, 0, precision)) return null // coincident
33
+ // These comparisons inline approximately(x, 0) and approximatelyLte(x, 0/1)
34
+ // to avoid 7+ function calls per invocation.
35
+ if (Math.abs(ua_t) <= precision || Math.abs(ub_t) <= precision) return null // coincident
34
36
 
35
- if (approximately(u_b, 0, precision)) return null // parallel
37
+ if (Math.abs(u_b) <= precision) return null // parallel
36
38
 
37
- if (u_b !== 0) {
38
- const ua = ua_t / u_b
39
- const ub = ub_t / u_b
40
- if (
41
- approximatelyLte(0, ua, precision) &&
42
- approximatelyLte(ua, 1, precision) &&
43
- approximatelyLte(0, ub, precision) &&
44
- approximatelyLte(ub, 1, precision)
45
- ) {
46
- return Vec.AddXY(a1, ua * AVx, ua * AVy)
47
- }
39
+ const ua = ua_t / u_b
40
+ const ub = ub_t / u_b
41
+ // Inlined: approximately(ua, 0) && approximatelyLte(ua, 1) && same for ub
42
+ if (ua >= -precision && ua <= 1 + precision && ub >= -precision && ub <= 1 + precision) {
43
+ // Inlined: Vec.Lrp(a1, a2, ua) — i.e. a1 + ua * (a2 - a1)
44
+ return new Vec(a1.x + ua * AVx, a1.y + ua * AVy)
48
45
  }
49
46
 
50
47
  return null // no intersection
@@ -60,32 +57,35 @@ export function intersectLineSegmentLineSegment(
60
57
  * @public
61
58
  */
62
59
  export function intersectLineSegmentCircle(a1: VecLike, a2: VecLike, c: VecLike, r: number) {
63
- const a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y)
64
- const b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y))
65
- const cc =
66
- c.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r
60
+ // Precompute segment delta (dx, dy) and origin-to-center offset (ocx, ocy)
61
+ // to avoid repeated (a2.x - a1.x) and (a1.x - c.x) subexpressions.
62
+ const dx = a2.x - a1.x
63
+ const dy = a2.y - a1.y
64
+ const ocx = a1.x - c.x
65
+ const ocy = a1.y - c.y
66
+
67
+ const a = dx * dx + dy * dy
68
+ const b = 2 * (dx * ocx + dy * ocy)
69
+ const cc = ocx * ocx + ocy * ocy - r * r
67
70
  const deter = b * b - 4 * a * cc
68
71
 
69
- if (deter < 0) return null // outside
70
- if (deter === 0) return null // tangent
72
+ if (deter <= 0) return null // outside or tangent
71
73
 
72
74
  const e = Math.sqrt(deter)
73
75
  const u1 = (-b + e) / (2 * a)
74
76
  const u2 = (-b - e) / (2 * a)
75
77
 
76
78
  if ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {
77
- return null // outside or inside
78
- // if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {
79
- // return null // outside
80
- // } else return null // inside'
79
+ return null
81
80
  }
82
81
 
83
82
  const result: VecLike[] = []
84
83
 
85
- if (0 <= u1 && u1 <= 1) result.push(Vec.Lrp(a1, a2, u1))
86
- if (0 <= u2 && u2 <= 1) result.push(Vec.Lrp(a1, a2, u2))
84
+ // Inlined: Vec.Lrp(a1, a2, u) — i.e. a1 + u * (a2 - a1)
85
+ if (u1 >= 0 && u1 <= 1) result.push(new Vec(a1.x + dx * u1, a1.y + dy * u1))
86
+ if (u2 >= 0 && u2 <= 1) result.push(new Vec(a1.x + dx * u2, a1.y + dy * u2))
87
87
 
88
- if (result.length === 0) return null // no intersection
88
+ if (result.length === 0) return null
89
89
 
90
90
  return result
91
91
  }
@@ -317,20 +317,20 @@ function cross(x: VecLike, y: VecLike, z: VecLike): number {
317
317
  * @public
318
318
  */
319
319
  export function pointInPolygon(A: VecLike, points: VecLike[]): boolean {
320
+ // Uses winding number algorithm. Previously also had a per-edge check:
321
+ // if (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true
322
+ // which tested if A lies exactly on edge (a, b). Removed because it cost 3 sqrts per vertex
323
+ // and exact float equality with sqrt results essentially never fires in practice.
320
324
  let windingNumber = 0
321
325
  let a: VecLike
322
326
  let b: VecLike
323
327
 
324
328
  for (let i = 0; i < points.length; i++) {
325
329
  a = points[i]
326
- // Point is the same as one of the corners of the polygon
327
330
  if (a.x === A.x && a.y === A.y) return true
328
331
 
329
332
  b = points[(i + 1) % points.length]
330
333
 
331
- // Point is on the polygon edge
332
- if (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true
333
-
334
334
  if (a.y <= A.y) {
335
335
  if (b.y > A.y && cross(a, b, A) > 0) {
336
336
  windingNumber += 1
@@ -8,6 +8,7 @@ class CustomTool extends StateNode {
8
8
 
9
9
  export class TestEditor extends Editor {
10
10
  constructor(options: Partial<Omit<TLEditorOptions, 'store'>> = {}) {
11
+ // eslint-disable-next-line no-restricted-globals
11
12
  const elm = document.createElement('div')
12
13
  elm.tabIndex = 0
13
14
 
@@ -1,3 +1,5 @@
1
+ import { getGlobalDocument } from './dom'
2
+
1
3
  /** @internal */
2
4
  export interface CanvasMaxSize {
3
5
  maxWidth: number
@@ -94,7 +96,7 @@ const TEST_SIZES = {
94
96
  * @returns The maximum size of the canvas for the given dimension.
95
97
  */
96
98
  function getCanvasSize(dimension: 'width' | 'height' | 'area'): number {
97
- const cropCvs = document.createElement('canvas')
99
+ const cropCvs = getGlobalDocument().createElement('canvas')
98
100
  cropCvs.width = 1
99
101
  cropCvs.height = 1
100
102
  const cropCtx = cropCvs.getContext('2d')!
@@ -103,7 +105,7 @@ function getCanvasSize(dimension: 'width' | 'height' | 'area'): number {
103
105
  const w = dimension === 'height' ? 1 : size
104
106
  const h = dimension === 'width' ? 1 : size
105
107
 
106
- const testCvs = document.createElement('canvas')
108
+ const testCvs = getGlobalDocument().createElement('canvas')
107
109
  testCvs.width = w
108
110
  testCvs.height = h
109
111
  const testCtx = testCvs.getContext('2d')!
@@ -112,7 +112,39 @@ export function elementShouldCaptureKeys(el: Element | null, includeButtonsAndMe
112
112
  )
113
113
  }
114
114
 
115
+ /**
116
+ * Returns the global `document`. Use this instead of bare `document` to satisfy lint rules.
117
+ *
118
+ * When you have a DOM node or editor instance, prefer the scoped versions instead:
119
+ * - `getOwnerDocument(node)` – the document that owns a specific DOM node
120
+ * - `editor.getContainerDocument()` – the document where the editor is mounted
121
+ *
122
+ * @internal
123
+ */
124
+ export function getGlobalDocument(): Document {
125
+ // eslint-disable-next-line no-restricted-globals
126
+ if (typeof document !== 'undefined') return document
127
+ return globalThis.document
128
+ }
129
+
130
+ /**
131
+ * Returns the global `window`. Use this instead of bare `window` to satisfy lint rules.
132
+ *
133
+ * When you have a DOM node or editor instance, prefer the scoped versions instead:
134
+ * - `getOwnerWindow(node)` – the window that owns a specific DOM node
135
+ * - `editor.getContainerWindow()` – the window where the editor is mounted
136
+ *
137
+ * @internal
138
+ */
139
+ export function getGlobalWindow(): Window & typeof globalThis {
140
+ if (typeof window !== 'undefined') return window as Window & typeof globalThis
141
+ return globalThis as Window & typeof globalThis
142
+ }
143
+
115
144
  /** @internal */
116
- export function activeElementShouldCaptureKeys(includeButtonsAndMenus = true) {
117
- return elementShouldCaptureKeys(document.activeElement, includeButtonsAndMenus)
145
+ export function activeElementShouldCaptureKeys(includeButtonsAndMenus = true, doc?: Document) {
146
+ return elementShouldCaptureKeys(
147
+ (doc ?? getGlobalDocument()).activeElement,
148
+ includeButtonsAndMenus
149
+ )
118
150
  }
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 = '4.5.2'
4
+ export const version = '4.6.0-canary.4ec045c286e1'
5
5
  export const publishDates = {
6
6
  major: '2025-09-18T14:39:22.803Z',
7
- minor: '2026-03-18T11:05:13.340Z',
8
- patch: '2026-03-18T12:00:45.366Z',
7
+ minor: '2026-03-18T11:50:21.657Z',
8
+ patch: '2026-03-18T11:50:21.657Z',
9
9
  }