@tldraw/editor 3.14.0-canary.f907ed7d9ee5 → 3.14.0-canary.fb0390b30559

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 (75) hide show
  1. package/dist-cjs/index.d.ts +149 -50
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +82 -25
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +3 -1
  7. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +73 -42
  9. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
  11. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +13 -6
  13. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +3 -3
  14. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  15. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  16. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  17. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  18. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  19. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  20. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  21. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  22. package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -6
  23. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  24. package/dist-cjs/lib/utils/dom.js +1 -1
  25. package/dist-cjs/lib/utils/dom.js.map +2 -2
  26. package/dist-cjs/lib/utils/reparenting.js +232 -0
  27. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  28. package/dist-cjs/version.js +3 -3
  29. package/dist-cjs/version.js.map +1 -1
  30. package/dist-esm/index.d.mts +149 -50
  31. package/dist-esm/index.mjs +4 -1
  32. package/dist-esm/index.mjs.map +2 -2
  33. package/dist-esm/lib/editor/Editor.mjs +82 -25
  34. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  35. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +3 -1
  36. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  37. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +73 -42
  38. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  39. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  40. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  41. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +13 -6
  42. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
  43. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  44. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  45. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  46. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  47. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  48. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  49. package/dist-esm/lib/primitives/geometry/Group2d.mjs +11 -6
  50. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  51. package/dist-esm/lib/utils/dom.mjs +1 -1
  52. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  53. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  54. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  55. package/dist-esm/version.mjs +3 -3
  56. package/dist-esm/version.mjs.map +1 -1
  57. package/editor.css +446 -489
  58. package/package.json +7 -7
  59. package/src/index.ts +7 -0
  60. package/src/lib/editor/Editor.ts +103 -36
  61. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +3 -1
  62. package/src/lib/editor/managers/TextManager/TextManager.test.ts +1 -5
  63. package/src/lib/editor/managers/TextManager/TextManager.ts +118 -86
  64. package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
  65. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +25 -17
  66. package/src/lib/editor/tools/StateNode.ts +3 -3
  67. package/src/lib/editor/types/emit-types.ts +4 -0
  68. package/src/lib/editor/types/external-content.ts +11 -2
  69. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  70. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  71. package/src/lib/primitives/geometry/Group2d.ts +11 -5
  72. package/src/lib/utils/dom.ts +1 -1
  73. package/src/lib/utils/reparenting.ts +383 -0
  74. package/src/version.ts +3 -3
  75. package/CHANGELOG.md +0 -4327
@@ -4,12 +4,15 @@ import { LegacyMigrations, MigrationSequence } from '@tldraw/store'
4
4
  import {
5
5
  RecordProps,
6
6
  TLHandle,
7
+ TLParentId,
7
8
  TLPropsMigrations,
8
9
  TLShape,
9
10
  TLShapeCrop,
11
+ TLShapeId,
10
12
  TLShapePartial,
11
13
  TLUnknownShape,
12
14
  } from '@tldraw/tlschema'
15
+ import { IndexKey } from '@tldraw/utils'
13
16
  import { ReactElement } from 'react'
14
17
  import { Box, SelectionHandle } from '../../primitives/Box'
15
18
  import { Vec } from '../../primitives/Vec'
@@ -387,17 +390,6 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
387
390
  return false
388
391
  }
389
392
 
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
-
401
393
  /**
402
394
  * Get the shape as an SVG object.
403
395
  *
@@ -517,7 +509,16 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
517
509
  ): Omit<TLShapePartial<Shape>, 'id' | 'type'> | undefined | void
518
510
 
519
511
  /**
520
- * A callback called when some other shapes are dragged over this one.
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.
521
522
  *
522
523
  * @example
523
524
  *
@@ -531,7 +532,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
531
532
  * @param shapes - The shapes that are being dragged over this one.
532
533
  * @public
533
534
  */
534
- onDragShapesOver?(shape: Shape, shapes: TLShape[]): void
535
+ onDragShapesOver?(shape: Shape, shapes: TLShape[], info: TLDragShapesOverInfo): void
535
536
 
536
537
  /**
537
538
  * A callback called when some other shapes are dragged out of this one.
@@ -540,7 +541,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
540
541
  * @param shapes - The shapes that are being dragged out.
541
542
  * @public
542
543
  */
543
- onDragShapesOut?(shape: Shape, shapes: TLShape[]): void
544
+ onDragShapesOut?(shape: Shape, shapes: TLShape[], info: TLDragShapesOutInfo): void
544
545
 
545
546
  /**
546
547
  * A callback called when some other shapes are dropped over this one.
@@ -549,7 +550,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
549
550
  * @param shapes - The shapes that are being dropped over this one.
550
551
  * @public
551
552
  */
552
- onDropShapesOver?(shape: Shape, shapes: TLShape[]): void
553
+ onDropShapesOver?(shape: Shape, shapes: TLShape[], info: TLDropShapesOverInfo): void
553
554
 
554
555
  /**
555
556
  * A callback called when a shape starts being resized.
@@ -745,6 +746,37 @@ export interface TLCropInfo<T extends TLShape> {
745
746
  crop: TLShapeCrop
746
747
  uncroppedSize: { w: number; h: number }
747
748
  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>
748
780
  }
749
781
 
750
782
  /**
@@ -11,29 +11,36 @@ export class Pointing extends StateNode {
11
11
  static override id = 'pointing'
12
12
 
13
13
  override onPointerMove(info: TLPointerEventInfo) {
14
- if (this.editor.inputs.isDragging) {
15
- const { originPagePoint } = this.editor.inputs
14
+ const { editor } = this
15
+ if (editor.inputs.isDragging) {
16
+ const { originPagePoint } = editor.inputs
16
17
 
17
18
  const shapeType = (this.parent as BaseBoxShapeTool)!.shapeType
18
19
 
19
20
  const id = createShapeId()
20
21
 
21
- const creatingMarkId = this.editor.markHistoryStoppingPoint(`creating_box:${id}`)
22
- const newPoint = maybeSnapToGrid(originPagePoint, this.editor)
23
- this.editor
24
- .createShapes<TLBaseBoxShape>([
25
- {
26
- id,
27
- type: shapeType,
28
- x: newPoint.x,
29
- y: newPoint.y,
30
- props: {
31
- w: 1,
32
- h: 1,
33
- },
22
+ const creatingMarkId = editor.markHistoryStoppingPoint(`creating_box:${id}`)
23
+ const newPoint = maybeSnapToGrid(originPagePoint, editor)
24
+
25
+ // Allow this to trigger the max shapes reached alert
26
+ this.editor.createShapes<TLBaseBoxShape>([
27
+ {
28
+ id,
29
+ type: shapeType,
30
+ x: newPoint.x,
31
+ y: newPoint.y,
32
+ props: {
33
+ w: 1,
34
+ h: 1,
34
35
  },
35
- ])
36
- .select(id)
36
+ },
37
+ ])
38
+ const shape = editor.getShape(id)
39
+ if (!shape) {
40
+ this.cancel()
41
+ return
42
+ }
43
+ editor.select(id)
37
44
 
38
45
  const parent = this.parent as BaseBoxShapeTool
39
46
  this.editor.setCurrentTool(
@@ -79,6 +86,7 @@ export class Pointing extends StateNode {
79
86
 
80
87
  this.editor.markHistoryStoppingPoint(`creating_box:${id}`)
81
88
 
89
+ // Allow this to trigger the max shapes reached alert
82
90
  // todo: add scale here when dynamic size is enabled (is this still needed?)
83
91
  this.editor.createShapes<TLBaseBoxShape>([
84
92
  {
@@ -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, from: string) {
209
+ exit(info: any, to: 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, from)
214
+ this.onExit?.(info, to)
215
215
 
216
216
  if (!this.getIsActive()) {
217
- this.getCurrent()?.exit(info, from)
217
+ this.getCurrent()?.exit(info, to)
218
218
  }
219
219
  }
220
220
 
@@ -18,6 +18,10 @@ 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: []
21
25
  }
22
26
 
23
27
  /** @public */
@@ -1,4 +1,4 @@
1
- import { TLAssetId } from '@tldraw/tlschema'
1
+ import { TLAssetId, TLShapeId } from '@tldraw/tlschema'
2
2
  import { VecLike } from '../../primitives/Vec'
3
3
  import { TLContent } from './clipboard-types'
4
4
 
@@ -52,7 +52,15 @@ export interface TLTextExternalContent extends TLBaseExternalContent {
52
52
  export interface TLFilesExternalContent extends TLBaseExternalContent {
53
53
  type: 'files'
54
54
  files: File[]
55
- ignoreParent: boolean
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
56
64
  }
57
65
 
58
66
  /** @public */
@@ -90,6 +98,7 @@ export interface TLExcalidrawExternalContent extends TLBaseExternalContent {
90
98
  export type TLExternalContent<EmbedDefinition> =
91
99
  | TLTextExternalContent
92
100
  | TLFilesExternalContent
101
+ | TLFileReplaceExternalContent
93
102
  | TLUrlExternalContent
94
103
  | TLSvgTextExternalContent
95
104
  | TLEmbedExternalContent<EmbedDefinition>
@@ -137,7 +137,6 @@ export function useCanvasEvents() {
137
137
  type: 'files',
138
138
  files,
139
139
  point: editor.screenToPage({ x: e.clientX, y: e.clientY }),
140
- ignoreParent: false,
141
140
  })
142
141
  return
143
142
  }
@@ -44,6 +44,7 @@ export const Geometry2dFilters: {
44
44
  /** @public */
45
45
  export interface TransformedGeometry2dOptions {
46
46
  isLabel?: boolean
47
+ isEmptyLabel?: boolean
47
48
  isInternal?: boolean
48
49
  debugColor?: string
49
50
  ignore?: boolean
@@ -57,20 +58,24 @@ export interface Geometry2dOptions extends TransformedGeometry2dOptions {
57
58
 
58
59
  /** @public */
59
60
  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
60
62
  isFilled = false
61
63
  isClosed = true
62
64
  isLabel = false
65
+ isEmptyLabel = false
63
66
  isInternal = false
64
67
  debugColor?: string
65
68
  ignore?: boolean
66
69
 
67
70
  constructor(opts: Geometry2dOptions) {
71
+ const { isLabel = false, isEmptyLabel = false, isInternal = false } = opts
68
72
  this.isFilled = opts.isFilled
69
73
  this.isClosed = opts.isClosed
70
- this.isLabel = opts.isLabel ?? false
71
- this.isInternal = opts.isInternal ?? false
72
74
  this.debugColor = opts.debugColor
73
75
  this.ignore = opts.ignore
76
+ this.isLabel = isLabel
77
+ this.isEmptyLabel = isEmptyLabel
78
+ this.isInternal = isInternal
74
79
  }
75
80
 
76
81
  isExcludedByFilter(filters?: Geometry2dFilters) {
@@ -17,14 +17,20 @@ export class Group2d extends Geometry2d {
17
17
  ) {
18
18
  super({ ...config, isClosed: true, isFilled: false })
19
19
 
20
- for (const child of config.children) {
21
- if (child.ignore) {
22
- this.ignoredChildren.push(child)
23
- } else {
24
- this.children.push(child)
20
+ const addChildren = (children: Geometry2d[]) => {
21
+ for (const child of children) {
22
+ if (child instanceof Group2d) {
23
+ addChildren(child.children)
24
+ } else if (child.ignore) {
25
+ this.ignoredChildren.push(child)
26
+ } else {
27
+ this.children.push(child)
28
+ }
25
29
  }
26
30
  }
27
31
 
32
+ addChildren(config.children)
33
+
28
34
  if (this.children.length === 0) throw Error('Group2d must have at least one child')
29
35
  }
30
36
 
@@ -18,7 +18,7 @@ import { debugFlags, pointerCaptureTrackingObject } from './debug-flags'
18
18
 
19
19
  /** @public */
20
20
  export function loopToHtmlElement(elm: Element): HTMLElement {
21
- if (elm instanceof HTMLElement) return elm
21
+ if (elm.nodeType === Node.ELEMENT_NODE) return elm as HTMLElement
22
22
  if (elm.parentElement) return loopToHtmlElement(elm.parentElement)
23
23
  else throw Error('Could not find a parent element of an HTML type!')
24
24
  }