@tldraw/editor 3.14.0-canary.faba3f64c07f → 3.14.0-canary.fc011e3d07ba

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 (53) hide show
  1. package/dist-cjs/index.d.ts +16 -106
  2. package/dist-cjs/index.js +1 -4
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +22 -59
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +2 -3
  7. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +10 -0
  9. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  11. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  12. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  13. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  14. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -1
  15. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  16. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -6
  17. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  18. package/dist-cjs/version.js +3 -3
  19. package/dist-cjs/version.js.map +1 -1
  20. package/dist-esm/index.d.mts +16 -106
  21. package/dist-esm/index.mjs +1 -4
  22. package/dist-esm/index.mjs.map +2 -2
  23. package/dist-esm/lib/editor/Editor.mjs +22 -59
  24. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  25. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
  26. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  27. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +10 -0
  28. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  29. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  30. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  31. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -1
  32. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  33. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -6
  34. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  35. package/dist-esm/version.mjs +3 -3
  36. package/dist-esm/version.mjs.map +1 -1
  37. package/editor.css +12 -27
  38. package/package.json +7 -7
  39. package/src/index.ts +0 -6
  40. package/src/lib/editor/Editor.ts +30 -71
  41. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -4
  42. package/src/lib/editor/shapes/ShapeUtil.ts +15 -47
  43. package/src/lib/editor/tools/StateNode.ts +3 -3
  44. package/src/lib/editor/types/emit-types.ts +0 -4
  45. package/src/lib/editor/types/external-content.ts +2 -11
  46. package/src/lib/hooks/useCanvasEvents.ts +1 -0
  47. package/src/lib/primitives/geometry/Geometry2d.ts +2 -7
  48. package/src/version.ts +3 -3
  49. package/dist-cjs/lib/utils/reparenting.js +0 -232
  50. package/dist-cjs/lib/utils/reparenting.js.map +0 -7
  51. package/dist-esm/lib/utils/reparenting.mjs +0 -216
  52. package/dist-esm/lib/utils/reparenting.mjs.map +0 -7
  53. package/src/lib/utils/reparenting.ts +0 -383
package/editor.css CHANGED
@@ -176,7 +176,8 @@
176
176
  --color-success: hsl(123, 46%, 34%);
177
177
  --color-info: hsl(201, 98%, 41%);
178
178
  --color-warning: hsl(27, 98%, 47%);
179
- --color-danger: hsl(0, 90%, 43%);
179
+ --color-error: hsl(0, 65%, 51%);
180
+ --color-warn: hsl(0, 90%, 43%);
180
181
  --color-laser: hsl(0, 100%, 50%);
181
182
  /* Shadows */
182
183
  --shadow-1: 0px 1px 2px hsl(0, 0%, 0%, 25%), 0px 1px 3px hsl(0, 0%, 0%, 9%);
@@ -231,7 +232,8 @@
231
232
  --color-success: hsl(123, 38%, 57%);
232
233
  --color-info: hsl(199, 92%, 56%);
233
234
  --color-warning: hsl(36, 100%, 57%);
234
- --color-danger: hsl(0, 82%, 66%);
235
+ --color-error: hsl(4, 90%, 58%);
236
+ --color-warn: hsl(0, 81%, 66%);
235
237
  --color-laser: hsl(0, 100%, 50%);
236
238
  /* Shadows */
237
239
  --shadow-1:
@@ -573,23 +575,6 @@ input,
573
575
 
574
576
  /* ---------------------- Text ---------------------- */
575
577
 
576
- .tl-text-shape-label {
577
- position: relative;
578
- font-weight: normal;
579
- min-width: 1px;
580
- padding: 0px;
581
- margin: 0px;
582
- border: none;
583
- width: fit-content;
584
- height: fit-content;
585
- font-variant: normal;
586
- font-style: normal;
587
- pointer-events: all;
588
- white-space: pre-wrap;
589
- overflow-wrap: break-word;
590
- text-shadow: var(--tl-text-outline);
591
- }
592
-
593
578
  .tl-text-wrapper[data-font='draw'] {
594
579
  font-family: var(--tl-font-draw);
595
580
  }
@@ -1055,8 +1040,8 @@ input,
1055
1040
  }
1056
1041
 
1057
1042
  .tl-hyperlink__icon {
1058
- width: 15px;
1059
- height: 15px;
1043
+ width: 16px;
1044
+ height: 16px;
1060
1045
  background-color: currentColor;
1061
1046
  pointer-events: none;
1062
1047
  }
@@ -1155,7 +1140,7 @@ input,
1155
1140
  stroke-linejoin: round;
1156
1141
  /* content-visibility: auto; */
1157
1142
  transform-origin: top left;
1158
- color: var(--color-text-1);
1143
+ color: inherit;
1159
1144
  }
1160
1145
 
1161
1146
  /* -------------------- Group shape ------------------ */
@@ -1270,7 +1255,6 @@ input,
1270
1255
  display: flex;
1271
1256
  justify-content: flex-end;
1272
1257
  align-items: flex-start;
1273
- box-shadow: inset 0px 0px 0px 1px var(--color-divider);
1274
1258
  }
1275
1259
 
1276
1260
  .tl-bookmark__image_container > .tl-hyperlink-button::after {
@@ -1293,7 +1277,7 @@ input,
1293
1277
  }
1294
1278
 
1295
1279
  .tl-bookmark__copy_container {
1296
- background-color: var(--color-muted-0);
1280
+ background-color: var(--color-muted);
1297
1281
  padding: var(--space-4);
1298
1282
  pointer-events: all;
1299
1283
  display: flex;
@@ -1312,11 +1296,11 @@ input,
1312
1296
 
1313
1297
  .tl-bookmark__heading {
1314
1298
  font-size: 16px;
1315
- line-height: 1.6;
1299
+ line-height: 1.5;
1316
1300
  font-weight: bold;
1317
1301
  padding-bottom: var(--space-2);
1318
1302
  overflow: hidden;
1319
- max-height: calc((16px * 1.6) * 2);
1303
+ max-height: calc((16px * 1.5) * 2);
1320
1304
  -webkit-box-orient: vertical;
1321
1305
  -webkit-line-clamp: 2;
1322
1306
  line-clamp: 2;
@@ -1397,6 +1381,7 @@ input,
1397
1381
 
1398
1382
  .tl-image-container {
1399
1383
  position: relative;
1384
+ overflow: hidden;
1400
1385
  }
1401
1386
 
1402
1387
  .tl-image {
@@ -1705,7 +1690,7 @@ it from receiving any pointer events or affecting the cursor. */
1705
1690
  gap: var(--space-4);
1706
1691
  }
1707
1692
  .tl-error-boundary__content .tl-error-boundary__reset {
1708
- color: var(--color-danger);
1693
+ color: var(--color-warn);
1709
1694
  }
1710
1695
  .tl-error-boundary__content .tl-error-boundary__refresh {
1711
1696
  background-color: var(--color-primary);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/editor",
3
3
  "description": "A tiny little drawing app (editor).",
4
- "version": "3.14.0-canary.faba3f64c07f",
4
+ "version": "3.14.0-canary.fc011e3d07ba",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -48,12 +48,12 @@
48
48
  "@tiptap/core": "^2.9.1",
49
49
  "@tiptap/pm": "^2.9.1",
50
50
  "@tiptap/react": "^2.9.1",
51
- "@tldraw/state": "3.14.0-canary.faba3f64c07f",
52
- "@tldraw/state-react": "3.14.0-canary.faba3f64c07f",
53
- "@tldraw/store": "3.14.0-canary.faba3f64c07f",
54
- "@tldraw/tlschema": "3.14.0-canary.faba3f64c07f",
55
- "@tldraw/utils": "3.14.0-canary.faba3f64c07f",
56
- "@tldraw/validate": "3.14.0-canary.faba3f64c07f",
51
+ "@tldraw/state": "3.14.0-canary.fc011e3d07ba",
52
+ "@tldraw/state-react": "3.14.0-canary.fc011e3d07ba",
53
+ "@tldraw/store": "3.14.0-canary.fc011e3d07ba",
54
+ "@tldraw/tlschema": "3.14.0-canary.fc011e3d07ba",
55
+ "@tldraw/utils": "3.14.0-canary.fc011e3d07ba",
56
+ "@tldraw/validate": "3.14.0-canary.fc011e3d07ba",
57
57
  "@types/core-js": "^2.5.8",
58
58
  "@use-gesture/react": "^10.3.1",
59
59
  "classnames": "^2.5.1",
package/src/index.ts CHANGED
@@ -182,10 +182,6 @@ export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseB
182
182
  export {
183
183
  ShapeUtil,
184
184
  type TLCropInfo,
185
- type TLDragShapesInInfo,
186
- type TLDragShapesOutInfo,
187
- type TLDragShapesOverInfo,
188
- type TLDropShapesOverInfo,
189
185
  type TLGeometryOpts,
190
186
  type TLHandleDragInfo,
191
187
  type TLResizeInfo,
@@ -257,7 +253,6 @@ export {
257
253
  type TLExternalContent,
258
254
  type TLExternalContentSource,
259
255
  type TLFileExternalAsset,
260
- type TLFileReplaceExternalContent,
261
256
  type TLFilesExternalContent,
262
257
  type TLSvgTextExternalContent,
263
258
  type TLTextExternalContent,
@@ -450,7 +445,6 @@ export { hardResetEditor } from './lib/utils/hardResetEditor'
450
445
  export { isAccelKey } from './lib/utils/keyboard'
451
446
  export { normalizeWheel } from './lib/utils/normalizeWheel'
452
447
  export { refreshPage } from './lib/utils/refreshPage'
453
- export { getDroppedShapesToNewParents, kickoutOccludedShapes } from './lib/utils/reparenting'
454
448
  export {
455
449
  getFontsFromRichText,
456
450
  type RichTextFontVisitor,
@@ -2122,20 +2122,6 @@ export class Editor extends EventEmitter<TLEventMap> {
2122
2122
  return this.getShapesPageBounds(this.getSelectedShapeIds())
2123
2123
  }
2124
2124
 
2125
- /**
2126
- * The bounds of the selection bounding box in the current page space.
2127
- *
2128
- * @readonly
2129
- * @public
2130
- */
2131
- getSelectionScreenBounds(): Box | undefined {
2132
- const bounds = this.getSelectionPageBounds()
2133
- if (!bounds) return undefined
2134
- const { x, y } = this.pageToScreen(bounds.point)
2135
- const zoom = this.getZoomLevel()
2136
- return new Box(x, y, bounds.width * zoom, bounds.height * zoom)
2137
- }
2138
-
2139
2125
  /**
2140
2126
  * @internal
2141
2127
  */
@@ -5528,7 +5514,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5528
5514
  if (!id) return undefined
5529
5515
  const freshShape = this.getShape(id)
5530
5516
  if (freshShape === undefined || !isShapeId(freshShape.parentId)) return undefined
5531
- return this.getShape(freshShape.parentId)
5517
+ return this.store.get(freshShape.parentId)
5532
5518
  }
5533
5519
 
5534
5520
  /**
@@ -5711,10 +5697,6 @@ export class Editor extends EventEmitter<TLEventMap> {
5711
5697
  const newPoint = invertedParentTransform.applyToPoint(pagePoint)
5712
5698
  const newRotation = pageTransform.rotation() - parentPageRotation
5713
5699
 
5714
- if (shape.id === parentId) {
5715
- throw Error('Attempted to reparent a shape to itself!')
5716
- }
5717
-
5718
5700
  changes.push({
5719
5701
  id: shape.id,
5720
5702
  type: shape.type,
@@ -5818,11 +5800,6 @@ export class Editor extends EventEmitter<TLEventMap> {
5818
5800
  return shapeIds
5819
5801
  }
5820
5802
 
5821
- /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
5822
- getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
5823
- return this.getDraggingOverShape(point, droppingShapes)
5824
- }
5825
-
5826
5803
  /**
5827
5804
  * Get the shape that some shapes should be dropped on at a given point.
5828
5805
  *
@@ -5833,33 +5810,35 @@ export class Editor extends EventEmitter<TLEventMap> {
5833
5810
  *
5834
5811
  * @public
5835
5812
  */
5836
- getDraggingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
5837
- // get fresh moving shapes
5838
- const draggingShapes = compact(droppingShapes.map((s) => this.getShape(s))).filter(
5839
- (s) => !s.isLocked && !this.isShapeHidden(s)
5840
- )
5813
+ getDroppingOverShape(point: VecLike, droppingShapes: TLShape[] = []) {
5814
+ // starting from the top...
5815
+ const currentPageShapesSorted = this.getCurrentPageShapesSorted()
5816
+ for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5817
+ const shape = currentPageShapesSorted[i]
5841
5818
 
5842
- const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
5843
- hitInside: true,
5844
- margin: 0,
5845
- }).filter(
5846
- (s) =>
5847
- !droppingShapes.includes(s) &&
5848
- !s.isLocked &&
5849
- !this.isShapeHidden(s) &&
5850
- !draggingShapes.includes(s)
5851
- )
5819
+ if (
5820
+ // ignore hidden shapes
5821
+ this.isShapeHidden(shape) ||
5822
+ // don't allow dropping on selected shapes
5823
+ this.getSelectedShapeIds().includes(shape.id) ||
5824
+ // only allow shapes that can receive children
5825
+ !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) ||
5826
+ // don't allow dropping a shape on itself or one of it's children
5827
+ droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
5828
+ ) {
5829
+ continue
5830
+ }
5831
+
5832
+ // Only allow dropping into the masked page bounds of the shape, e.g. when a frame is
5833
+ // partially clipped by its own parent frame
5834
+ const maskedPageBounds = this.getShapeMaskedPageBounds(shape.id)
5852
5835
 
5853
- for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
5854
- const shapeUtil = this.getShapeUtil(maybeDraggingOverShape)
5855
- // Any shape that can handle any dragging interactions is a valid target
5856
5836
  if (
5857
- shapeUtil.onDragShapesOver ||
5858
- shapeUtil.onDragShapesIn ||
5859
- shapeUtil.onDragShapesOut ||
5860
- shapeUtil.onDropShapesOver
5837
+ maskedPageBounds &&
5838
+ maskedPageBounds.containsPoint(point) &&
5839
+ this.getShapeGeometry(shape).hitTestPoint(this.getPointInShapeSpace(shape, point), 0, true)
5861
5840
  ) {
5862
- return maybeDraggingOverShape
5841
+ return shape
5863
5842
  }
5864
5843
  }
5865
5844
  }
@@ -6218,12 +6197,11 @@ export class Editor extends EventEmitter<TLEventMap> {
6218
6197
  */
6219
6198
  duplicateShapes(shapes: TLShapeId[] | TLShape[], offset?: VecLike): this {
6220
6199
  this.run(() => {
6221
- const _ids =
6200
+ const ids =
6222
6201
  typeof shapes[0] === 'string'
6223
6202
  ? (shapes as TLShapeId[])
6224
6203
  : (shapes as TLShape[]).map((s) => s.id)
6225
6204
 
6226
- const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids)
6227
6205
  if (ids.length <= 0) return this
6228
6206
 
6229
6207
  const initialIds = new Set(ids)
@@ -7813,10 +7791,9 @@ export class Editor extends EventEmitter<TLEventMap> {
7813
7791
 
7814
7792
  for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
7815
7793
  const parent = currentPageShapesSorted[i]
7816
- const util = this.getShapeUtil(parent)
7817
7794
  if (
7818
- util.canReceiveNewChildrenOfType(parent, partial.type) &&
7819
7795
  !this.isShapeHidden(parent) &&
7796
+ this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) &&
7820
7797
  this.isPointInShape(
7821
7798
  parent,
7822
7799
  // If no parent is provided, then we can treat the
@@ -7945,8 +7922,6 @@ export class Editor extends EventEmitter<TLEventMap> {
7945
7922
  }
7946
7923
  })
7947
7924
 
7948
- this.emit('created-shapes', shapeRecordsToCreate)
7949
- this.emit('edit')
7950
7925
  this.store.put(shapeRecordsToCreate)
7951
7926
  })
7952
7927
 
@@ -8341,8 +8316,6 @@ export class Editor extends EventEmitter<TLEventMap> {
8341
8316
  updates.push(updated)
8342
8317
  }
8343
8318
 
8344
- this.emit('edited-shapes', updates)
8345
- this.emit('edit')
8346
8319
  this.store.put(updates)
8347
8320
  })
8348
8321
  }
@@ -8392,8 +8365,6 @@ export class Editor extends EventEmitter<TLEventMap> {
8392
8365
  })
8393
8366
  }
8394
8367
 
8395
- this.emit('deleted-shapes', [...allShapeIdsToDelete])
8396
- this.emit('edit')
8397
8368
  return this.run(() => this.store.remove([...allShapeIdsToDelete]))
8398
8369
  }
8399
8370
 
@@ -8842,7 +8813,6 @@ export class Editor extends EventEmitter<TLEventMap> {
8842
8813
  } = {
8843
8814
  text: null,
8844
8815
  files: null,
8845
- 'file-replace': null,
8846
8816
  embed: null,
8847
8817
  'svg-text': null,
8848
8818
  url: null,
@@ -8892,15 +8862,6 @@ export class Editor extends EventEmitter<TLEventMap> {
8892
8862
  return this.externalContentHandlers[info.type]?.(info as any)
8893
8863
  }
8894
8864
 
8895
- /**
8896
- * Handle replacing external content.
8897
- *
8898
- * @param info - Info about the external content.
8899
- */
8900
- async replaceExternalContent<E>(info: TLExternalContent<E>): Promise<void> {
8901
- return this.externalContentHandlers[info.type]?.(info as any)
8902
- }
8903
-
8904
8865
  /**
8905
8866
  * Get content that can be exported for the given shape ids.
8906
8867
  *
@@ -9520,8 +9481,6 @@ export class Editor extends EventEmitter<TLEventMap> {
9520
9481
  previousPagePoint,
9521
9482
  currentScreenPoint,
9522
9483
  currentPagePoint,
9523
- originScreenPoint,
9524
- originPagePoint,
9525
9484
  } = this.inputs
9526
9485
 
9527
9486
  const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
@@ -9550,8 +9509,8 @@ export class Editor extends EventEmitter<TLEventMap> {
9550
9509
  // Reset velocity on pointer down, or when a pinch starts or ends
9551
9510
  if (info.name === 'pointer_down' || this.inputs.isPinching) {
9552
9511
  pointerVelocity.set(0, 0)
9553
- originScreenPoint.setTo(currentScreenPoint)
9554
- originPagePoint.setTo(currentPagePoint)
9512
+ this.inputs.originScreenPoint.setTo(currentScreenPoint)
9513
+ this.inputs.originPagePoint.setTo(currentPagePoint)
9555
9514
  }
9556
9515
 
9557
9516
  // todo: We only have to do this if there are multiple users in the document
@@ -26,7 +26,6 @@ export interface TLMeasureTextOpts {
26
26
  fontWeight: string
27
27
  fontFamily: string
28
28
  fontSize: number
29
- /** This must be a number, e.g. 1.35, not a pixel value. */
30
29
  lineHeight: number
31
30
  /**
32
31
  * When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
@@ -76,7 +75,6 @@ export class TextManager {
76
75
  // we need to save the default styles so that we can restore them when we're done
77
76
  // these must be the css names, not the js names for the styles
78
77
  this.defaultStyles = {
79
- 'overflow-wrap': 'break-word',
80
78
  'word-break': 'auto',
81
79
  width: null,
82
80
  height: null,
@@ -125,7 +123,7 @@ export class TextManager {
125
123
  elm.style.setProperty('font-style', opts.fontStyle)
126
124
  elm.style.setProperty('font-weight', opts.fontWeight)
127
125
  elm.style.setProperty('font-size', opts.fontSize + 'px')
128
- elm.style.setProperty('line-height', opts.lineHeight.toString())
126
+ elm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')
129
127
  elm.style.setProperty('padding', opts.padding)
130
128
 
131
129
  if (opts.maxWidth) {
@@ -289,7 +287,7 @@ export class TextManager {
289
287
  elm.style.setProperty('font-style', opts.fontStyle)
290
288
  elm.style.setProperty('font-weight', opts.fontWeight)
291
289
  elm.style.setProperty('font-size', opts.fontSize + 'px')
292
- elm.style.setProperty('line-height', opts.lineHeight.toString())
290
+ elm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')
293
291
 
294
292
  const elementWidth = Math.ceil(opts.width - opts.padding * 2)
295
293
  elm.style.setProperty('width', `${elementWidth}px`)
@@ -4,15 +4,12 @@ import { LegacyMigrations, MigrationSequence } from '@tldraw/store'
4
4
  import {
5
5
  RecordProps,
6
6
  TLHandle,
7
- TLParentId,
8
7
  TLPropsMigrations,
9
8
  TLShape,
10
9
  TLShapeCrop,
11
- TLShapeId,
12
10
  TLShapePartial,
13
11
  TLUnknownShape,
14
12
  } from '@tldraw/tlschema'
15
- import { IndexKey } from '@tldraw/utils'
16
13
  import { ReactElement } from 'react'
17
14
  import { Box, SelectionHandle } from '../../primitives/Box'
18
15
  import { Vec } from '../../primitives/Vec'
@@ -390,6 +387,17 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
390
387
  return false
391
388
  }
392
389
 
390
+ /**
391
+ * Get whether the shape can receive children of a given type.
392
+ *
393
+ * @param shape - The shape type.
394
+ * @param shapes - The shapes that are being dropped.
395
+ * @public
396
+ */
397
+ canDropShapes(_shape: Shape, _shapes: TLShape[]) {
398
+ return false
399
+ }
400
+
393
401
  /**
394
402
  * Get the shape as an SVG object.
395
403
  *
@@ -509,16 +517,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
509
517
  ): Omit<TLShapePartial<Shape>, 'id' | 'type'> | undefined | void
510
518
 
511
519
  /**
512
- * A callback called when some other shapes are dragged into this one. This fires when the shapes are dragged over the shape for the first time.
513
- *
514
- * @param shape - The shape.
515
- * @param shapes - The shapes that are being dragged in.
516
- * @public
517
- */
518
- onDragShapesIn?(shape: Shape, shapes: TLShape[], info: TLDragShapesInInfo): void
519
-
520
- /**
521
- * A callback called when some other shapes are dragged over this one. This fires when the shapes are dragged over the shape for the first time (after the onDragShapesIn callback), and again on every update while the shapes are being dragged.
520
+ * A callback called when some other shapes are dragged over this one.
522
521
  *
523
522
  * @example
524
523
  *
@@ -532,7 +531,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
532
531
  * @param shapes - The shapes that are being dragged over this one.
533
532
  * @public
534
533
  */
535
- onDragShapesOver?(shape: Shape, shapes: TLShape[], info: TLDragShapesOverInfo): void
534
+ onDragShapesOver?(shape: Shape, shapes: TLShape[]): void
536
535
 
537
536
  /**
538
537
  * A callback called when some other shapes are dragged out of this one.
@@ -541,7 +540,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
541
540
  * @param shapes - The shapes that are being dragged out.
542
541
  * @public
543
542
  */
544
- onDragShapesOut?(shape: Shape, shapes: TLShape[], info: TLDragShapesOutInfo): void
543
+ onDragShapesOut?(shape: Shape, shapes: TLShape[]): void
545
544
 
546
545
  /**
547
546
  * A callback called when some other shapes are dropped over this one.
@@ -550,7 +549,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
550
549
  * @param shapes - The shapes that are being dropped over this one.
551
550
  * @public
552
551
  */
553
- onDropShapesOver?(shape: Shape, shapes: TLShape[], info: TLDropShapesOverInfo): void
552
+ onDropShapesOver?(shape: Shape, shapes: TLShape[]): void
554
553
 
555
554
  /**
556
555
  * A callback called when a shape starts being resized.
@@ -746,37 +745,6 @@ export interface TLCropInfo<T extends TLShape> {
746
745
  crop: TLShapeCrop
747
746
  uncroppedSize: { w: number; h: number }
748
747
  initialShape: T
749
- aspectRatioLocked?: boolean
750
- }
751
-
752
- /** @public */
753
- export interface TLDragShapesInInfo {
754
- initialDraggingOverShapeId: TLShapeId | null
755
- prevDraggingOverShapeId: TLShapeId | null
756
- initialParentIds: Map<TLShapeId, TLParentId>
757
- initialIndices: Map<TLShapeId, IndexKey>
758
- }
759
-
760
- /** @public */
761
- export interface TLDragShapesOverInfo {
762
- initialDraggingOverShapeId: TLShapeId | null
763
- initialParentIds: Map<TLShapeId, TLParentId>
764
- initialIndices: Map<TLShapeId, IndexKey>
765
- }
766
-
767
- /** @public */
768
- export interface TLDragShapesOutInfo {
769
- nextDraggingOverShapeId: TLShapeId | null
770
- initialDraggingOverShapeId: TLShapeId | null
771
- initialParentIds: Map<TLShapeId, TLParentId>
772
- initialIndices: Map<TLShapeId, IndexKey>
773
- }
774
-
775
- /** @public */
776
- export interface TLDropShapesOverInfo {
777
- initialDraggingOverShapeId: TLShapeId | null
778
- initialParentIds: Map<TLShapeId, TLParentId>
779
- initialIndices: Map<TLShapeId, IndexKey>
780
748
  }
781
749
 
782
750
  /**
@@ -206,15 +206,15 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
206
206
  }
207
207
 
208
208
  // todo: move this logic into transition
209
- exit(info: any, to: string) {
209
+ exit(info: any, from: string) {
210
210
  if (debugFlags.measurePerformance.get() && this.performanceTracker.isStarted()) {
211
211
  this.performanceTracker.stop()
212
212
  }
213
213
  this._isActive.set(false)
214
- this.onExit?.(info, to)
214
+ this.onExit?.(info, from)
215
215
 
216
216
  if (!this.getIsActive()) {
217
- this.getCurrent()?.exit(info, to)
217
+ this.getCurrent()?.exit(info, from)
218
218
  }
219
219
  }
220
220
 
@@ -18,10 +18,6 @@ export interface TLEventMap {
18
18
  frame: [number]
19
19
  'select-all-text': [{ shapeId: TLShapeId }]
20
20
  'place-caret': [{ shapeId: TLShapeId; point: { x: number; y: number } }]
21
- 'created-shapes': [TLRecord[]]
22
- 'edited-shapes': [TLRecord[]]
23
- 'deleted-shapes': [TLShapeId[]]
24
- edit: []
25
21
  }
26
22
 
27
23
  /** @public */
@@ -1,4 +1,4 @@
1
- import { TLAssetId, TLShapeId } from '@tldraw/tlschema'
1
+ import { TLAssetId } from '@tldraw/tlschema'
2
2
  import { VecLike } from '../../primitives/Vec'
3
3
  import { TLContent } from './clipboard-types'
4
4
 
@@ -52,15 +52,7 @@ export interface TLTextExternalContent extends TLBaseExternalContent {
52
52
  export interface TLFilesExternalContent extends TLBaseExternalContent {
53
53
  type: 'files'
54
54
  files: File[]
55
- ignoreParent?: boolean
56
- }
57
-
58
- /** @public */
59
- export interface TLFileReplaceExternalContent extends TLBaseExternalContent {
60
- type: 'file-replace'
61
- file: File
62
- shapeId: TLShapeId
63
- isImage: boolean
55
+ ignoreParent: boolean
64
56
  }
65
57
 
66
58
  /** @public */
@@ -98,7 +90,6 @@ export interface TLExcalidrawExternalContent extends TLBaseExternalContent {
98
90
  export type TLExternalContent<EmbedDefinition> =
99
91
  | TLTextExternalContent
100
92
  | TLFilesExternalContent
101
- | TLFileReplaceExternalContent
102
93
  | TLUrlExternalContent
103
94
  | TLSvgTextExternalContent
104
95
  | TLEmbedExternalContent<EmbedDefinition>
@@ -137,6 +137,7 @@ export function useCanvasEvents() {
137
137
  type: 'files',
138
138
  files,
139
139
  point: editor.screenToPage({ x: e.clientX, y: e.clientY }),
140
+ ignoreParent: false,
140
141
  })
141
142
  return
142
143
  }
@@ -44,7 +44,6 @@ export const Geometry2dFilters: {
44
44
  /** @public */
45
45
  export interface TransformedGeometry2dOptions {
46
46
  isLabel?: boolean
47
- isEmptyLabel?: boolean
48
47
  isInternal?: boolean
49
48
  debugColor?: string
50
49
  ignore?: boolean
@@ -58,24 +57,20 @@ export interface Geometry2dOptions extends TransformedGeometry2dOptions {
58
57
 
59
58
  /** @public */
60
59
  export abstract class Geometry2d {
61
- // todo: consider making accessors for these too, so that they can be overridden in subclasses by geometries with more complex logic
62
60
  isFilled = false
63
61
  isClosed = true
64
62
  isLabel = false
65
- isEmptyLabel = false
66
63
  isInternal = false
67
64
  debugColor?: string
68
65
  ignore?: boolean
69
66
 
70
67
  constructor(opts: Geometry2dOptions) {
71
- const { isLabel = false, isEmptyLabel = false, isInternal = false } = opts
72
68
  this.isFilled = opts.isFilled
73
69
  this.isClosed = opts.isClosed
70
+ this.isLabel = opts.isLabel ?? false
71
+ this.isInternal = opts.isInternal ?? false
74
72
  this.debugColor = opts.debugColor
75
73
  this.ignore = opts.ignore
76
- this.isLabel = isLabel
77
- this.isEmptyLabel = isEmptyLabel
78
- this.isInternal = isInternal
79
74
  }
80
75
 
81
76
  isExcludedByFilter(filters?: Geometry2dFilters) {
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.14.0-canary.faba3f64c07f'
4
+ export const version = '3.14.0-canary.fc011e3d07ba'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-06-25T10:22:31.342Z',
8
- patch: '2025-06-25T10:22:31.342Z',
7
+ minor: '2025-06-16T15:32:58.622Z',
8
+ patch: '2025-06-16T15:32:58.622Z',
9
9
  }