@tldraw/editor 3.16.0-canary.ffdf566dd0a8 → 3.16.0-internal.a478398270c6

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 (179) hide show
  1. package/dist-cjs/index.d.ts +16 -213
  2. package/dist-cjs/index.js +1 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +0 -2
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/SVGContainer.js +1 -1
  7. package/dist-cjs/lib/components/SVGContainer.js.map +2 -2
  8. package/dist-cjs/lib/components/Shape.js +26 -4
  9. package/dist-cjs/lib/components/Shape.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultBrush.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
  17. package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultGrid.js +1 -1
  19. package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
  20. package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
  21. package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +2 -2
  22. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
  23. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  24. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +1 -1
  25. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
  26. package/dist-cjs/lib/components/default-components/DefaultSpinner.js +15 -27
  27. package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +3 -3
  28. package/dist-cjs/lib/config/TLUserPreferences.js +2 -14
  29. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  30. package/dist-cjs/lib/editor/Editor.js +52 -107
  31. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  32. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +3 -13
  33. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/editor/tools/StateNode.js +1 -20
  36. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  37. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  38. package/dist-cjs/lib/hooks/useEditor.js +4 -1
  39. package/dist-cjs/lib/hooks/useEditor.js.map +2 -2
  40. package/dist-cjs/lib/hooks/useEditorComponents.js +0 -2
  41. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  42. package/dist-cjs/lib/license/Watermark.js +2 -2
  43. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  44. package/dist-cjs/lib/options.js +0 -1
  45. package/dist-cjs/lib/options.js.map +2 -2
  46. package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
  47. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  48. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
  49. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  50. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -3
  51. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  52. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
  53. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  54. package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
  55. package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
  56. package/dist-cjs/lib/primitives/intersect.js +4 -4
  57. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  58. package/dist-cjs/lib/primitives/utils.js +0 -4
  59. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  60. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +1 -0
  61. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  62. package/dist-cjs/version.js +3 -3
  63. package/dist-cjs/version.js.map +1 -1
  64. package/dist-esm/index.d.mts +16 -213
  65. package/dist-esm/index.mjs +2 -16
  66. package/dist-esm/index.mjs.map +2 -2
  67. package/dist-esm/lib/TldrawEditor.mjs +0 -2
  68. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  69. package/dist-esm/lib/components/SVGContainer.mjs +1 -1
  70. package/dist-esm/lib/components/SVGContainer.mjs.map +2 -2
  71. package/dist-esm/lib/components/Shape.mjs +26 -4
  72. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  73. package/dist-esm/lib/components/default-components/DefaultBrush.mjs +1 -1
  74. package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
  75. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  76. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  77. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  78. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
  79. package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
  80. package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
  81. package/dist-esm/lib/components/default-components/DefaultGrid.mjs +1 -1
  82. package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
  83. package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
  84. package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +2 -2
  85. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
  86. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  87. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +1 -1
  88. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
  89. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +15 -17
  90. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
  91. package/dist-esm/lib/config/TLUserPreferences.mjs +2 -14
  92. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  93. package/dist-esm/lib/editor/Editor.mjs +52 -107
  94. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  95. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +3 -13
  96. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  97. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  98. package/dist-esm/lib/editor/tools/StateNode.mjs +1 -20
  99. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  100. package/dist-esm/lib/hooks/useEditor.mjs +4 -1
  101. package/dist-esm/lib/hooks/useEditor.mjs.map +2 -2
  102. package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -4
  103. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  104. package/dist-esm/lib/license/Watermark.mjs +2 -2
  105. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  106. package/dist-esm/lib/options.mjs +0 -1
  107. package/dist-esm/lib/options.mjs.map +2 -2
  108. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  109. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  110. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
  111. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  112. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -3
  113. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  114. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
  115. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  116. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
  117. package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
  118. package/dist-esm/lib/primitives/intersect.mjs +5 -5
  119. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  120. package/dist-esm/lib/primitives/utils.mjs +0 -4
  121. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  122. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +1 -0
  123. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  124. package/dist-esm/version.mjs +3 -3
  125. package/dist-esm/version.mjs.map +1 -1
  126. package/editor.css +27 -23
  127. package/package.json +8 -9
  128. package/src/index.ts +1 -15
  129. package/src/lib/TldrawEditor.tsx +0 -2
  130. package/src/lib/components/SVGContainer.tsx +1 -1
  131. package/src/lib/components/Shape.tsx +21 -6
  132. package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
  133. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  134. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  135. package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
  136. package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
  137. package/src/lib/components/default-components/DefaultHandles.tsx +1 -5
  138. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +1 -1
  139. package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
  140. package/src/lib/components/default-components/DefaultSpinner.tsx +12 -12
  141. package/src/lib/config/TLUserPreferences.ts +0 -14
  142. package/src/lib/editor/Editor.test.ts +0 -407
  143. package/src/lib/editor/Editor.ts +72 -140
  144. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +0 -34
  145. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +0 -13
  146. package/src/lib/editor/shapes/ShapeUtil.ts +0 -57
  147. package/src/lib/editor/tools/StateNode.ts +1 -27
  148. package/src/lib/editor/types/misc-types.ts +1 -73
  149. package/src/lib/hooks/useEditor.tsx +5 -6
  150. package/src/lib/hooks/useEditorComponents.tsx +2 -8
  151. package/src/lib/license/Watermark.tsx +2 -2
  152. package/src/lib/options.ts +0 -2
  153. package/src/lib/primitives/geometry/Arc2d.ts +2 -2
  154. package/src/lib/primitives/geometry/Circle2d.ts +2 -2
  155. package/src/lib/primitives/geometry/CubicBezier2d.ts +1 -4
  156. package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
  157. package/src/lib/primitives/geometry/geometry-constants.ts +1 -2
  158. package/src/lib/primitives/intersect.ts +5 -12
  159. package/src/lib/primitives/utils.ts +0 -11
  160. package/src/lib/test/currentToolIdMask.test.ts +49 -0
  161. package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
  162. package/src/version.ts +3 -3
  163. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +0 -53
  164. package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +0 -7
  165. package/dist-cjs/lib/hooks/useStateAttribute.js +0 -35
  166. package/dist-cjs/lib/hooks/useStateAttribute.js.map +0 -7
  167. package/dist-cjs/lib/utils/EditorAtom.js +0 -45
  168. package/dist-cjs/lib/utils/EditorAtom.js.map +0 -7
  169. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +0 -23
  170. package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +0 -7
  171. package/dist-esm/lib/hooks/useStateAttribute.mjs +0 -15
  172. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +0 -7
  173. package/dist-esm/lib/utils/EditorAtom.mjs +0 -25
  174. package/dist-esm/lib/utils/EditorAtom.mjs.map +0 -7
  175. package/src/lib/components/default-components/DefaultShapeWrapper.tsx +0 -35
  176. package/src/lib/editor/tools/StateNode.test.ts +0 -285
  177. package/src/lib/hooks/useStateAttribute.ts +0 -15
  178. package/src/lib/primitives/intersect.test.ts +0 -946
  179. package/src/lib/utils/EditorAtom.ts +0 -37
@@ -176,10 +176,8 @@ import {
176
176
  RequiredKeys,
177
177
  TLCameraMoveOptions,
178
178
  TLCameraOptions,
179
- TLGetShapeAtPointOptions,
180
179
  TLImageExportOptions,
181
180
  TLSvgExportOptions,
182
- TLUpdatePointerOptions,
183
181
  } from './types/misc-types'
184
182
  import { TLAdjacentDirection, TLResizeHandle } from './types/selection-types'
185
183
 
@@ -1805,9 +1803,7 @@ export class Editor extends EventEmitter<TLEventMap> {
1805
1803
  }
1806
1804
 
1807
1805
  /**
1808
- * Select all shapes. If the user has selected shapes that share a parent,
1809
- * select all shapes within that parent. If the user has not selected any shapes,
1810
- * or if the shapes shapes are only on select all shapes on the current page.
1806
+ * Select all direct children of the current page.
1811
1807
  *
1812
1808
  * @example
1813
1809
  * ```ts
@@ -1817,34 +1813,11 @@ export class Editor extends EventEmitter<TLEventMap> {
1817
1813
  * @public
1818
1814
  */
1819
1815
  selectAll(): this {
1820
- let parentToSelectWithinId: TLParentId | null = null
1821
-
1822
- const selectedShapeIds = this.getSelectedShapeIds()
1823
-
1824
- // If we have selected shapes, try to find a parent to select within
1825
- if (selectedShapeIds.length > 0) {
1826
- for (const id of selectedShapeIds) {
1827
- const shape = this.getShape(id)
1828
- if (!shape) continue
1829
- if (parentToSelectWithinId === null) {
1830
- // If we haven't found a parent yet, set this parent as the parent to select within
1831
- parentToSelectWithinId = shape.parentId
1832
- } else if (parentToSelectWithinId !== shape.parentId) {
1833
- // If we've found two different parents, we can't select all, do nothing
1834
- return this
1835
- }
1836
- }
1837
- }
1838
-
1839
- // If we haven't found a parent from our selected shapes, select the current page
1840
- if (!parentToSelectWithinId) {
1841
- parentToSelectWithinId = this.getCurrentPageId()
1842
- }
1843
-
1844
- // Select all the unlocked shapes within the parent
1845
- const ids = this.getSortedChildIdsForParent(parentToSelectWithinId)
1816
+ const ids = this.getSortedChildIdsForParent(this.getCurrentPageId())
1817
+ // page might have no shapes
1846
1818
  if (ids.length <= 0) return this
1847
1819
  this.setSelectedShapes(this._getUnlockedShapeIds(ids))
1820
+
1848
1821
  return this
1849
1822
  }
1850
1823
 
@@ -1865,11 +1838,10 @@ export class Editor extends EventEmitter<TLEventMap> {
1865
1838
  firstParentId &&
1866
1839
  selectedShapeIds.every((shapeId) => this.getShape(shapeId)?.parentId === firstParentId) &&
1867
1840
  !isPageId(firstParentId)
1868
- const filteredShapes = isSelectedWithinContainer
1869
- ? this.getCurrentPageShapes().filter((shape) => shape.parentId === firstParentId)
1870
- : this.getCurrentPageShapes().filter((shape) => isPageId(shape.parentId))
1871
1841
  const readingOrderShapes = isSelectedWithinContainer
1872
- ? this._getShapesInReadingOrder(filteredShapes)
1842
+ ? this._getShapesInReadingOrder(
1843
+ this.getCurrentPageShapes().filter((shape) => shape.parentId === firstParentId)
1844
+ )
1873
1845
  : this.getCurrentPageShapesInReadingOrder()
1874
1846
  const currentShapeId: TLShapeId | undefined =
1875
1847
  selectedShapeIds.length === 1
@@ -1886,7 +1858,7 @@ export class Editor extends EventEmitter<TLEventMap> {
1886
1858
  adjacentShapeId = shapeIds[adjacentIndex]
1887
1859
  } else {
1888
1860
  if (!currentShapeId) return
1889
- adjacentShapeId = this.getNearestAdjacentShape(filteredShapes, currentShapeId, direction)
1861
+ adjacentShapeId = this.getNearestAdjacentShape(currentShapeId, direction)
1890
1862
  }
1891
1863
 
1892
1864
  const shape = this.getShape(adjacentShapeId)
@@ -1985,7 +1957,6 @@ export class Editor extends EventEmitter<TLEventMap> {
1985
1957
  * @public
1986
1958
  */
1987
1959
  getNearestAdjacentShape(
1988
- shapes: TLShape[],
1989
1960
  currentShapeId: TLShapeId,
1990
1961
  direction: 'left' | 'right' | 'up' | 'down'
1991
1962
  ): TLShapeId {
@@ -1993,6 +1964,7 @@ export class Editor extends EventEmitter<TLEventMap> {
1993
1964
  const currentShape = this.getShape(currentShapeId)
1994
1965
  if (!currentShape) return currentShapeId
1995
1966
 
1967
+ const shapes = this.getCurrentPageShapes()
1996
1968
  const tabbableShapes = shapes.filter(
1997
1969
  (shape) => this.getShapeUtil(shape).canTabTo(shape) && shape.id !== currentShapeId
1998
1970
  )
@@ -3074,6 +3046,7 @@ export class Editor extends EventEmitter<TLEventMap> {
3074
3046
  // Dispatch a new pointer move because the pointer's page will have changed
3075
3047
  // (its screen position will compute to a new page position given the new camera position)
3076
3048
  const { currentScreenPoint, currentPagePoint } = this.inputs
3049
+ const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
3077
3050
 
3078
3051
  // compare the next page point (derived from the current camera) to the current page point
3079
3052
  if (
@@ -3081,10 +3054,27 @@ export class Editor extends EventEmitter<TLEventMap> {
3081
3054
  currentScreenPoint.y / z - y !== currentPagePoint.y
3082
3055
  ) {
3083
3056
  // If it's changed, dispatch a pointer event
3084
- this.updatePointer({
3085
- immediate: opts?.immediate,
3057
+ const event: TLPointerEventInfo = {
3058
+ type: 'pointer',
3059
+ target: 'canvas',
3060
+ name: 'pointer_move',
3061
+ // weird but true: we need to put the screen point back into client space
3062
+ point: Vec.AddXY(currentScreenPoint, screenBounds.x, screenBounds.y),
3086
3063
  pointerId: INTERNAL_POINTER_IDS.CAMERA_MOVE,
3087
- })
3064
+ ctrlKey: this.inputs.ctrlKey,
3065
+ altKey: this.inputs.altKey,
3066
+ shiftKey: this.inputs.shiftKey,
3067
+ metaKey: this.inputs.metaKey,
3068
+ accelKey: isAccelKey(this.inputs),
3069
+ button: 0,
3070
+ isPen: this.getInstanceState().isPenMode ?? false,
3071
+ }
3072
+
3073
+ if (opts?.immediate) {
3074
+ this._flushEventForTick(event)
3075
+ } else {
3076
+ this.dispatch(event)
3077
+ }
3088
3078
  }
3089
3079
 
3090
3080
  this._tickCameraState()
@@ -4405,28 +4395,21 @@ export class Editor extends EventEmitter<TLEventMap> {
4405
4395
  */
4406
4396
  deletePage(page: TLPageId | TLPage): this {
4407
4397
  const id = typeof page === 'string' ? page : page.id
4408
- this.run(
4409
- () => {
4410
- if (this.getIsReadonly()) return
4411
- const pages = this.getPages()
4412
- if (pages.length === 1) return
4413
-
4414
- const deletedPage = this.getPage(id)
4415
- if (!deletedPage) return
4416
-
4417
- if (id === this.getCurrentPageId()) {
4418
- const index = pages.findIndex((page) => page.id === id)
4419
- const next = pages[index - 1] ?? pages[index + 1]
4420
- this.setCurrentPage(next.id)
4421
- }
4398
+ this.run(() => {
4399
+ if (this.getIsReadonly()) return
4400
+ const pages = this.getPages()
4401
+ if (pages.length === 1) return
4422
4402
 
4423
- const shapes = this.getSortedChildIdsForParent(deletedPage.id)
4424
- this.deleteShapes(shapes)
4403
+ const deletedPage = this.getPage(id)
4404
+ if (!deletedPage) return
4425
4405
 
4426
- this.store.remove([deletedPage.id])
4427
- },
4428
- { ignoreShapeLock: true }
4429
- )
4406
+ if (id === this.getCurrentPageId()) {
4407
+ const index = pages.findIndex((page) => page.id === id)
4408
+ const next = pages[index - 1] ?? pages[index + 1]
4409
+ this.setCurrentPage(next.id)
4410
+ }
4411
+ this.store.remove([deletedPage.id])
4412
+ })
4430
4413
  return this
4431
4414
  }
4432
4415
 
@@ -5155,7 +5138,20 @@ export class Editor extends EventEmitter<TLEventMap> {
5155
5138
  *
5156
5139
  * @returns The shape at the given point, or undefined if there is no shape at the point.
5157
5140
  */
5158
- getShapeAtPoint(point: VecLike, opts: TLGetShapeAtPointOptions = {}): TLShape | undefined {
5141
+ getShapeAtPoint(
5142
+ point: VecLike,
5143
+ opts = {} as {
5144
+ renderingOnly?: boolean
5145
+ margin?: number
5146
+ hitInside?: boolean
5147
+ hitLocked?: boolean
5148
+ // TODO: we probably need to rename this, we don't quite _always_
5149
+ // respect this esp. in the part below that does "Check labels first"
5150
+ hitLabels?: boolean
5151
+ hitFrameInside?: boolean
5152
+ filter?(shape: TLShape): boolean
5153
+ }
5154
+ ): TLShape | undefined {
5159
5155
  const zoomLevel = this.getZoomLevel()
5160
5156
  const viewportPageBounds = this.getViewportPageBounds()
5161
5157
  const {
@@ -5167,8 +5163,6 @@ export class Editor extends EventEmitter<TLEventMap> {
5167
5163
  hitFrameInside = false,
5168
5164
  } = opts
5169
5165
 
5170
- const [innerMargin, outerMargin] = Array.isArray(margin) ? margin : [margin, margin]
5171
-
5172
5166
  let inHollowSmallestArea = Infinity
5173
5167
  let inHollowSmallestAreaHit: TLShape | null = null
5174
5168
 
@@ -5188,7 +5182,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5188
5182
  return false
5189
5183
  const pageMask = this.getShapeMask(shape)
5190
5184
  if (pageMask && !pointInPolygon(point, pageMask)) return false
5191
- if (filter && !filter(shape)) return false
5185
+ if (filter) return filter(shape)
5192
5186
  return true
5193
5187
  })
5194
5188
 
@@ -5202,8 +5196,8 @@ export class Editor extends EventEmitter<TLEventMap> {
5202
5196
  // Check labels first
5203
5197
  if (
5204
5198
  this.isShapeOfType<TLFrameShape>(shape, 'frame') ||
5199
+ (this.isShapeOfType<TLArrowShape>(shape, 'arrow') && shape.props.text.trim()) ||
5205
5200
  ((this.isShapeOfType<TLNoteShape>(shape, 'note') ||
5206
- this.isShapeOfType<TLArrowShape>(shape, 'arrow') ||
5207
5201
  (this.isShapeOfType<TLGeoShape>(shape, 'geo') && shape.props.fill === 'none')) &&
5208
5202
  this.getShapeUtil(shape).getText(shape)?.trim())
5209
5203
  ) {
@@ -5214,18 +5208,13 @@ export class Editor extends EventEmitter<TLEventMap> {
5214
5208
  }
5215
5209
  }
5216
5210
 
5217
- if (this.isShapeOfType<TLFrameShape>(shape, 'frame')) {
5211
+ if (this.isShapeOfType(shape, 'frame')) {
5218
5212
  // On the rare case that we've hit a frame (not its label), test again hitInside to be forced true;
5219
5213
  // this prevents clicks from passing through the body of a frame to shapes behind it.
5220
5214
 
5221
5215
  // If the hit is within the frame's outer margin, then select the frame
5222
- const distance = geometry.distanceToPoint(pointInShapeSpace, hitFrameInside)
5223
- if (
5224
- hitFrameInside
5225
- ? (distance > 0 && distance <= outerMargin) ||
5226
- (distance <= 0 && distance > -innerMargin)
5227
- : distance > 0 && distance <= outerMargin
5228
- ) {
5216
+ const distance = geometry.distanceToPoint(pointInShapeSpace, hitInside)
5217
+ if (Math.abs(distance) <= margin) {
5229
5218
  return inMarginClosestToEdgeHit || shape
5230
5219
  }
5231
5220
 
@@ -5264,11 +5253,11 @@ export class Editor extends EventEmitter<TLEventMap> {
5264
5253
  // If the margin is zero and the geometry has a very small width or height,
5265
5254
  // then check the actual distance. This is to prevent a bug where straight
5266
5255
  // lines would never pass the broad phase (point-in-bounds) check.
5267
- if (outerMargin === 0 && (geometry.bounds.w < 1 || geometry.bounds.h < 1)) {
5256
+ if (margin === 0 && (geometry.bounds.w < 1 || geometry.bounds.h < 1)) {
5268
5257
  distance = geometry.distanceToPoint(pointInShapeSpace, hitInside)
5269
5258
  } else {
5270
5259
  // Broad phase
5271
- if (geometry.bounds.containsPoint(pointInShapeSpace, outerMargin)) {
5260
+ if (geometry.bounds.containsPoint(pointInShapeSpace, margin)) {
5272
5261
  // Narrow phase (actual distance)
5273
5262
  distance = geometry.distanceToPoint(pointInShapeSpace, hitInside)
5274
5263
  } else {
@@ -5283,8 +5272,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5283
5272
  // the shape or negative if inside of the shape. If the distance
5284
5273
  // is greater than the margin, then it's a miss. Otherwise...
5285
5274
 
5286
- // Are we close to the shape's edge?
5287
- if (distance <= outerMargin || (hitInside && distance <= 0 && distance > -innerMargin)) {
5275
+ if (distance <= margin) {
5288
5276
  if (geometry.isFilled || (isGroup && geometry.children[0].isFilled)) {
5289
5277
  // If the shape is filled, then it's a hit. Remember, we're
5290
5278
  // starting from the TOP-MOST shape in z-index order, so any
@@ -5294,21 +5282,11 @@ export class Editor extends EventEmitter<TLEventMap> {
5294
5282
  // If the shape is bigger than the viewport, then skip it.
5295
5283
  if (this.getShapePageBounds(shape)!.contains(viewportPageBounds)) continue
5296
5284
 
5297
- // If we're close to the edge of the shape, and if it's the closest edge among
5298
- // all the edges that we've gotten close to so far, then we will want to hit the
5299
- // shape unless we hit something else or closer in later iterations.
5300
- if (
5301
- hitInside
5302
- ? // On hitInside, the distance will be negative for hits inside
5303
- // If the distance is positive, check against the outer margin
5304
- (distance > 0 && distance <= outerMargin) ||
5305
- // If the distance is negative, check against the inner margin
5306
- (distance <= 0 && distance > -innerMargin)
5307
- : // If hitInside is false, then sadly _we do not know_ whether the
5308
- // point is inside or outside of the shape, so we check against
5309
- // the max of the two margins
5310
- Math.abs(distance) <= Math.max(innerMargin, outerMargin)
5311
- ) {
5285
+ // For hollow shapes...
5286
+ if (Math.abs(distance) < margin) {
5287
+ // We want to preference shapes where we're inside of the
5288
+ // shape margin; and we would want to hit the shape with the
5289
+ // edge closest to the point.
5312
5290
  if (Math.abs(distance) < inMarginClosestToEdgeDistance) {
5313
5291
  inMarginClosestToEdgeDistance = Math.abs(distance)
5314
5292
  inMarginClosestToEdgeHit = shape
@@ -5330,7 +5308,6 @@ export class Editor extends EventEmitter<TLEventMap> {
5330
5308
  } else {
5331
5309
  // For open shapes (e.g. lines or draw shapes) always use the margin.
5332
5310
  // If the distance is less than the margin, return the shape as the hit.
5333
- // Use the editor's configurable hit test margin.
5334
5311
  if (distance < this.options.hitTestMargin / zoomLevel) {
5335
5312
  return shape
5336
5313
  }
@@ -7387,6 +7364,7 @@ export class Editor extends EventEmitter<TLEventMap> {
7387
7364
  if (
7388
7365
  !this.getShapeUtil(shape).canBeLaidOut?.(shape, {
7389
7366
  type: 'stretch',
7367
+ shapes: shapesToStretchFirstPass,
7390
7368
  })
7391
7369
  ) {
7392
7370
  continue
@@ -7881,7 +7859,7 @@ export class Editor extends EventEmitter<TLEventMap> {
7881
7859
 
7882
7860
  const prevParentId = partial.parentId
7883
7861
 
7884
- // a shape cannot be its own parent. This was a rare issue with frames/groups in the syncFuzz tests.
7862
+ // a shape cannot be it's own parent. This was a rare issue with frames/groups in the syncFuzz tests.
7885
7863
  if (parentId === partial.id) {
7886
7864
  parentId = focusedGroupId
7887
7865
  }
@@ -9669,52 +9647,6 @@ export class Editor extends EventEmitter<TLEventMap> {
9669
9647
  return this
9670
9648
  }
9671
9649
 
9672
- /**
9673
- * Dispatch a pointer move event in the current position of the pointer. This is useful when
9674
- * external circumstances have changed (e.g. the camera moved or a shape was moved) and you want
9675
- * the current interaction to respond to that change.
9676
- *
9677
- * @example
9678
- * ```ts
9679
- * editor.updatePointer()
9680
- * ```
9681
- *
9682
- * @param options - The options for updating the pointer.
9683
- * @returns The editor instance.
9684
- * @public
9685
- */
9686
- updatePointer(options?: TLUpdatePointerOptions): this {
9687
- const event: TLPointerEventInfo = {
9688
- type: 'pointer',
9689
- target: 'canvas',
9690
- name: 'pointer_move',
9691
- point:
9692
- options?.point ??
9693
- // weird but true: what `inputs` calls screen-space is actually viewport space. so
9694
- // we need to convert back into true screen space first. we should fix this...
9695
- Vec.Add(
9696
- this.inputs.currentScreenPoint,
9697
- this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!.screenBounds
9698
- ),
9699
- pointerId: options?.pointerId ?? 0,
9700
- button: options?.button ?? 0,
9701
- isPen: options?.isPen ?? this.inputs.isPen,
9702
- shiftKey: options?.shiftKey ?? this.inputs.shiftKey,
9703
- altKey: options?.altKey ?? this.inputs.altKey,
9704
- ctrlKey: options?.ctrlKey ?? this.inputs.ctrlKey,
9705
- metaKey: options?.metaKey ?? this.inputs.metaKey,
9706
- accelKey: options?.accelKey ?? isAccelKey(this.inputs),
9707
- }
9708
-
9709
- if (options?.immediate) {
9710
- this._flushEventForTick(event)
9711
- } else {
9712
- this.dispatch(event)
9713
- }
9714
-
9715
- return this
9716
- }
9717
-
9718
9650
  /**
9719
9651
  * Puts the editor into focused mode.
9720
9652
  *
@@ -24,8 +24,6 @@ describe('UserPreferencesManager', () => {
24
24
  color: '#FF802B',
25
25
  locale: 'en',
26
26
  animationSpeed: 1,
27
- areKeyboardShortcutsEnabled: true,
28
- showUiLabels: false,
29
27
  edgeScrollSpeed: 1,
30
28
  colorScheme: 'light',
31
29
  isSnapMode: false,
@@ -231,8 +229,6 @@ describe('UserPreferencesManager', () => {
231
229
  locale: mockUserPreferences.locale,
232
230
  color: mockUserPreferences.color,
233
231
  animationSpeed: mockUserPreferences.animationSpeed,
234
- areKeyboardShortcutsEnabled: mockUserPreferences.areKeyboardShortcutsEnabled,
235
- showUiLabels: mockUserPreferences.showUiLabels,
236
232
  isSnapMode: mockUserPreferences.isSnapMode,
237
233
  colorScheme: mockUserPreferences.colorScheme,
238
234
  isDarkMode: false, // light mode
@@ -366,32 +362,6 @@ describe('UserPreferencesManager', () => {
366
362
  })
367
363
  })
368
364
 
369
- describe('getAreKeyboardShortcutsEnabled', () => {
370
- it('should return user keyboard shortcuts', () => {
371
- expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
372
- mockUserPreferences.areKeyboardShortcutsEnabled
373
- )
374
- })
375
-
376
- it('should return default keyboard shortcuts when null', () => {
377
- userPreferencesAtom.set({ ...mockUserPreferences, areKeyboardShortcutsEnabled: null })
378
- expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
379
- defaultUserPreferences.areKeyboardShortcutsEnabled
380
- )
381
- })
382
- })
383
-
384
- describe('getShowUiLabels', () => {
385
- it('should return user show ui labels setting', () => {
386
- expect(userPreferencesManager.getShowUiLabels()).toBe(mockUserPreferences.showUiLabels)
387
- })
388
-
389
- it('should return default show ui labels when null', () => {
390
- userPreferencesAtom.set({ ...mockUserPreferences, showUiLabels: null })
391
- expect(userPreferencesManager.getShowUiLabels()).toBe(defaultUserPreferences.showUiLabels)
392
- })
393
- })
394
-
395
365
  describe('getEdgeScrollSpeed', () => {
396
366
  it('should return user edge scroll speed', () => {
397
367
  expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
@@ -513,7 +483,6 @@ describe('UserPreferencesManager', () => {
513
483
  color: null,
514
484
  locale: null,
515
485
  animationSpeed: null,
516
- areKeyboardShortcutsEnabled: null,
517
486
  edgeScrollSpeed: null,
518
487
  isSnapMode: null,
519
488
  isWrapMode: null,
@@ -527,9 +496,6 @@ describe('UserPreferencesManager', () => {
527
496
  expect(userPreferencesManager.getColor()).toBe(defaultUserPreferences.color)
528
497
  expect(userPreferencesManager.getLocale()).toBe(defaultUserPreferences.locale)
529
498
  expect(userPreferencesManager.getAnimationSpeed()).toBe(defaultUserPreferences.animationSpeed)
530
- expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
531
- defaultUserPreferences.areKeyboardShortcutsEnabled
532
- )
533
499
  expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
534
500
  defaultUserPreferences.edgeScrollSpeed
535
501
  )
@@ -43,13 +43,11 @@ export class UserPreferencesManager {
43
43
  locale: this.getLocale(),
44
44
  color: this.getColor(),
45
45
  animationSpeed: this.getAnimationSpeed(),
46
- areKeyboardShortcutsEnabled: this.getAreKeyboardShortcutsEnabled(),
47
46
  isSnapMode: this.getIsSnapMode(),
48
47
  colorScheme: this.user.userPreferences.get().colorScheme,
49
48
  isDarkMode: this.getIsDarkMode(),
50
49
  isWrapMode: this.getIsWrapMode(),
51
50
  isDynamicResizeMode: this.getIsDynamicResizeMode(),
52
- showUiLabels: this.getShowUiLabels(),
53
51
  }
54
52
  }
55
53
 
@@ -77,13 +75,6 @@ export class UserPreferencesManager {
77
75
  return this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed
78
76
  }
79
77
 
80
- @computed getAreKeyboardShortcutsEnabled() {
81
- return (
82
- this.user.userPreferences.get().areKeyboardShortcutsEnabled ??
83
- defaultUserPreferences.areKeyboardShortcutsEnabled
84
- )
85
- }
86
-
87
78
  @computed getId() {
88
79
  return this.user.userPreferences.get().id
89
80
  }
@@ -120,8 +111,4 @@ export class UserPreferencesManager {
120
111
  defaultUserPreferences.isPasteAtCursorMode
121
112
  )
122
113
  }
123
-
124
- @computed getShowUiLabels() {
125
- return this.user.userPreferences.get().showUiLabels ?? defaultUserPreferences.showUiLabels
126
- }
127
114
  }
@@ -584,15 +584,6 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
584
584
  */
585
585
  onResizeEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
586
586
 
587
- /**
588
- * A callback called when a shape resize is cancelled.
589
- *
590
- * @param initial - The shape at the start of the resize.
591
- * @param current - The current shape.
592
- * @public
593
- */
594
- onResizeCancel?(initial: Shape, current: Shape): void
595
-
596
587
  /**
597
588
  * A callback called when a shape starts being translated.
598
589
  *
@@ -622,25 +613,6 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
622
613
  */
623
614
  onTranslateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
624
615
 
625
- /**
626
- * A callback called when a shape translation is cancelled.
627
- *
628
- * @param initial - The shape at the start of the translation.
629
- * @param current - The current shape.
630
- * @public
631
- */
632
- onTranslateCancel?(initial: Shape, current: Shape): void
633
-
634
- /**
635
- * A callback called when a shape's handle starts being dragged.
636
- *
637
- * @param shape - The shape.
638
- * @param info - An object containing the handle and whether the handle is 'precise' or not.
639
- * @returns A change to apply to the shape, or void.
640
- * @public
641
- */
642
- onHandleDragStart?(shape: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
643
-
644
616
  /**
645
617
  * A callback called when a shape's handle changes.
646
618
  *
@@ -651,25 +623,6 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
651
623
  */
652
624
  onHandleDrag?(shape: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
653
625
 
654
- /**
655
- * A callback called when a shape's handle finishes being dragged.
656
- *
657
- * @param current - The current shape.
658
- * @param info - An object containing the handle and whether the handle is 'precise' or not.
659
- * @returns A change to apply to the shape, or void.
660
- * @public
661
- */
662
- onHandleDragEnd?(current: Shape, info: TLHandleDragInfo<Shape>): TLShapePartial<Shape> | void
663
-
664
- /**
665
- * A callback called when a shape's handle drag is cancelled.
666
- *
667
- * @param current - The current shape.
668
- * @param info - An object containing the handle and whether the handle is 'precise' or not.
669
- * @public
670
- */
671
- onHandleDragCancel?(current: Shape, info: TLHandleDragInfo<Shape>): void
672
-
673
626
  /**
674
627
  * A callback called when a shape starts being rotated.
675
628
  *
@@ -699,15 +652,6 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
699
652
  */
700
653
  onRotateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void
701
654
 
702
- /**
703
- * A callback called when a shape rotation is cancelled.
704
- *
705
- * @param initial - The shape at the start of the rotation.
706
- * @param current - The current shape.
707
- * @public
708
- */
709
- onRotateCancel?(initial: Shape, current: Shape): void
710
-
711
655
  /**
712
656
  * Not currently used.
713
657
  *
@@ -875,6 +819,5 @@ export interface TLResizeInfo<T extends TLShape> {
875
819
  export interface TLHandleDragInfo<T extends TLShape> {
876
820
  handle: TLHandle
877
821
  isPrecise: boolean
878
- isCreatingShape: boolean
879
822
  initial?: T | undefined
880
823
  }
@@ -62,7 +62,7 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
62
62
 
63
63
  this.parent = parent ?? ({} as any)
64
64
 
65
- if (parent) {
65
+ if (this.parent) {
66
66
  if (children && initial) {
67
67
  this.type = 'branch'
68
68
  this.initial = initial
@@ -238,32 +238,6 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
238
238
  this._currentToolIdMask.set(id)
239
239
  }
240
240
 
241
- /**
242
- * Add a child node to this state node.
243
- *
244
- * @public
245
- */
246
- addChild(childConstructor: TLStateNodeConstructor): this {
247
- if (this.type === 'leaf') {
248
- throw new Error('StateNode.addChild: cannot add child to a leaf node')
249
- }
250
-
251
- // Initialize children if it's undefined (for root nodes without static children)
252
- if (!this.children) {
253
- this.children = {}
254
- }
255
-
256
- const child = new childConstructor(this.editor, this)
257
-
258
- // Check if a child with this ID already exists
259
- if (this.children[child.id]) {
260
- throw new Error(`StateNode.addChild: a child with id '${child.id}' already exists`)
261
- }
262
-
263
- this.children[child.id] = child
264
- return this
265
- }
266
-
267
241
  onWheel?(info: TLWheelEventInfo): void
268
242
  onPointerDown?(info: TLPointerEventInfo): void
269
243
  onPointerMove?(info: TLPointerEventInfo): void
@@ -1,4 +1,4 @@
1
- import { BoxModel, TLShape } from '@tldraw/tlschema'
1
+ import { BoxModel } from '@tldraw/tlschema'
2
2
  import { Box } from '../../primitives/Box'
3
3
  import { VecLike } from '../../primitives/Vec'
4
4
 
@@ -187,75 +187,3 @@ export interface TLCameraConstraints {
187
187
  y: 'free' | 'fixed' | 'inside' | 'outside' | 'contain'
188
188
  }
189
189
  }
190
-
191
- /** @public */
192
- export interface TLUpdatePointerOptions {
193
- /** Whether to update the pointer immediately, rather than on the next tick. */
194
- immediate?: boolean
195
- /**
196
- * The point, in screen-space, to update the pointer to. Defaults to the position of the last
197
- * pointer event.
198
- */
199
- point?: VecLike
200
- pointerId?: number
201
- ctrlKey?: boolean
202
- altKey?: boolean
203
- shiftKey?: boolean
204
- metaKey?: boolean
205
- accelKey?: boolean
206
- isPen?: boolean
207
- button?: number
208
- }
209
-
210
- /**
211
- * Options to {@link Editor.getShapeAtPoint}.
212
- *
213
- * @public
214
- */
215
- export interface TLGetShapeAtPointOptions {
216
- /**
217
- * The margin to apply to the shape.
218
- * If a number, it will be applied to both the inside and outside of the shape.
219
- * If an array, the first element will be applied to the inside of the shape, and the second element will be applied to the outside.
220
- *
221
- * @example
222
- * ```ts
223
- * // Get the shape at the center of the screen
224
- * const shape = editor.getShapeAtProps({
225
- * margin: 10,
226
- * })
227
- *
228
- * // Get the shape at the center of the screen with a 10px inner margin and a 5px outer margin
229
- * const shape = editor.getShapeAtProps({
230
- * margin: [10, 5],
231
- * })
232
- * ```
233
- */
234
- margin?: number | [number, number]
235
- /**
236
- * Whether to register hits inside of shapes (beyond the margin), such as the inside of a solid shape.
237
- */
238
- hitInside?: boolean
239
- /**
240
- * Whether to register hits on locked shapes.
241
- */
242
- hitLocked?: boolean
243
- /**
244
- * Whether to register hits on labels.
245
- */
246
- hitLabels?: boolean
247
- /**
248
- * Whether to only return hits on shapes that are currently being rendered.
249
- * todo: rename this to hitCulled or hitNotRendering
250
- */
251
- renderingOnly?: boolean
252
- /**
253
- * Whether to register hits on the inside of frame shapes.
254
- * todo: rename this to hitInsideFrames
255
- */
256
- hitFrameInside?: boolean
257
- /**
258
- * A filter function to apply to the shapes.
259
- */
260
- filter?(shape: TLShape): boolean
261
- }