@tldraw/editor 3.14.0-canary.ff61ab6deaa2 → 3.14.0-internal.eada756f6aa0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +166 -59
- package/dist-cjs/index.js +4 -3
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +113 -45
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +1 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +3 -1
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +73 -42
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +10 -6
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +3 -3
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +0 -6
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
- package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
- package/dist-cjs/lib/utils/dom.js +1 -1
- package/dist-cjs/lib/utils/dom.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.js +232 -0
- package/dist-cjs/lib/utils/reparenting.js.map +7 -0
- package/dist-cjs/lib/utils/richText.js +7 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +166 -59
- package/dist-esm/index.mjs +4 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +113 -45
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +1 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +3 -1
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +73 -42
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +10 -6
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +0 -6
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
- package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
- package/dist-esm/lib/utils/dom.mjs +1 -1
- package/dist-esm/lib/utils/dom.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs +216 -0
- package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
- package/dist-esm/lib/utils/richText.mjs +8 -3
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +442 -492
- package/package.json +8 -9
- package/src/index.ts +7 -1
- package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
- package/src/lib/editor/Editor.test.ts +252 -3
- package/src/lib/editor/Editor.ts +129 -52
- package/src/lib/editor/bindings/BindingUtil.ts +6 -0
- package/src/lib/editor/managers/FontManager/FontManager.ts +1 -2
- package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +3 -1
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +1 -5
- package/src/lib/editor/managers/TextManager/TextManager.ts +118 -86
- package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +22 -17
- package/src/lib/editor/tools/StateNode.ts +3 -3
- package/src/lib/editor/types/emit-types.ts +4 -0
- package/src/lib/editor/types/external-content.ts +11 -2
- package/src/lib/hooks/useCanvasEvents.ts +0 -1
- package/src/lib/primitives/Box.ts +0 -8
- package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
- package/src/lib/utils/areShapesContentEqual.ts +1 -2
- package/src/lib/utils/dom.ts +1 -1
- package/src/lib/utils/reparenting.ts +383 -0
- package/src/lib/utils/richText.ts +9 -3
- package/src/version.ts +3 -3
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -348,6 +348,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
348
348
|
this.getContainer = getContainer
|
|
349
349
|
|
|
350
350
|
this.textMeasure = new TextManager(this)
|
|
351
|
+
this.disposables.add(() => this.textMeasure.dispose())
|
|
352
|
+
|
|
351
353
|
this.fonts = new FontManager(this, fontAssetUrls)
|
|
352
354
|
|
|
353
355
|
this._tickManager = new TickManager(this)
|
|
@@ -506,14 +508,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
506
508
|
shape: {
|
|
507
509
|
afterChange: (shapeBefore, shapeAfter) => {
|
|
508
510
|
for (const binding of this.getBindingsInvolvingShape(shapeAfter)) {
|
|
509
|
-
if (areShapesContentEqual(shapeBefore, shapeAfter)) continue
|
|
510
|
-
|
|
511
511
|
invalidBindingTypes.add(binding.type)
|
|
512
512
|
if (binding.fromId === shapeAfter.id) {
|
|
513
513
|
this.getBindingUtil(binding).onAfterChangeFromShape?.({
|
|
514
514
|
binding,
|
|
515
515
|
shapeBefore,
|
|
516
516
|
shapeAfter,
|
|
517
|
+
reason: 'self',
|
|
517
518
|
})
|
|
518
519
|
}
|
|
519
520
|
if (binding.toId === shapeAfter.id) {
|
|
@@ -521,6 +522,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
521
522
|
binding,
|
|
522
523
|
shapeBefore,
|
|
523
524
|
shapeAfter,
|
|
525
|
+
reason: 'self',
|
|
524
526
|
})
|
|
525
527
|
}
|
|
526
528
|
}
|
|
@@ -539,6 +541,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
539
541
|
binding,
|
|
540
542
|
shapeBefore: descendantShape,
|
|
541
543
|
shapeAfter: descendantShape,
|
|
544
|
+
reason: 'ancestry',
|
|
542
545
|
})
|
|
543
546
|
}
|
|
544
547
|
if (binding.toId === descendantShape.id) {
|
|
@@ -546,6 +549,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
546
549
|
binding,
|
|
547
550
|
shapeBefore: descendantShape,
|
|
548
551
|
shapeAfter: descendantShape,
|
|
552
|
+
reason: 'ancestry',
|
|
549
553
|
})
|
|
550
554
|
}
|
|
551
555
|
}
|
|
@@ -2118,6 +2122,20 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2118
2122
|
return this.getShapesPageBounds(this.getSelectedShapeIds())
|
|
2119
2123
|
}
|
|
2120
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
|
+
|
|
2121
2139
|
/**
|
|
2122
2140
|
* @internal
|
|
2123
2141
|
*/
|
|
@@ -3644,7 +3662,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3644
3662
|
* @public
|
|
3645
3663
|
*/
|
|
3646
3664
|
updateViewportScreenBounds(screenBounds: Box | HTMLElement, center = false): this {
|
|
3647
|
-
if (screenBounds instanceof
|
|
3665
|
+
if (!(screenBounds instanceof Box)) {
|
|
3648
3666
|
const rect = screenBounds.getBoundingClientRect()
|
|
3649
3667
|
screenBounds = new Box(
|
|
3650
3668
|
rect.left || rect.x,
|
|
@@ -5035,28 +5053,33 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5035
5053
|
*
|
|
5036
5054
|
* @public
|
|
5037
5055
|
*/
|
|
5038
|
-
isShapeOrAncestorLocked(shape?: TLShape): boolean
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
if (shape.isLocked) return true
|
|
5044
|
-
return this.isShapeOrAncestorLocked(this.getShapeParent(shape))
|
|
5056
|
+
isShapeOrAncestorLocked(shape?: TLShape | TLShapeId): boolean {
|
|
5057
|
+
const _shape = shape && this.getShape(shape)
|
|
5058
|
+
if (_shape === undefined) return false
|
|
5059
|
+
if (_shape.isLocked) return true
|
|
5060
|
+
return this.isShapeOrAncestorLocked(this.getShapeParent(_shape))
|
|
5045
5061
|
}
|
|
5046
5062
|
|
|
5063
|
+
/**
|
|
5064
|
+
* Get shapes that are outside of the viewport.
|
|
5065
|
+
*
|
|
5066
|
+
* @public
|
|
5067
|
+
*/
|
|
5047
5068
|
@computed
|
|
5048
|
-
|
|
5049
|
-
return
|
|
5069
|
+
getNotVisibleShapes() {
|
|
5070
|
+
return this._notVisibleShapes.get()
|
|
5050
5071
|
}
|
|
5051
5072
|
|
|
5073
|
+
private _notVisibleShapes = notVisibleShapes(this)
|
|
5074
|
+
|
|
5052
5075
|
/**
|
|
5053
|
-
* Get culled shapes.
|
|
5076
|
+
* Get culled shapes (those that should not render), taking into account which shapes are selected or editing.
|
|
5054
5077
|
*
|
|
5055
5078
|
* @public
|
|
5056
5079
|
*/
|
|
5057
5080
|
@computed
|
|
5058
5081
|
getCulledShapes() {
|
|
5059
|
-
const notVisibleShapes = this.
|
|
5082
|
+
const notVisibleShapes = this.getNotVisibleShapes()
|
|
5060
5083
|
const selectedShapeIds = this.getSelectedShapeIds()
|
|
5061
5084
|
const editingId = this.getEditingShapeId()
|
|
5062
5085
|
const culledShapes = new Set<TLShapeId>(notVisibleShapes)
|
|
@@ -5305,21 +5328,23 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5305
5328
|
* @example
|
|
5306
5329
|
* ```ts
|
|
5307
5330
|
* editor.getShapesAtPoint({ x: 100, y: 100 })
|
|
5308
|
-
* editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true,
|
|
5331
|
+
* editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, margin: 8 })
|
|
5309
5332
|
* ```
|
|
5310
5333
|
*
|
|
5311
5334
|
* @param point - The page point to test.
|
|
5312
5335
|
* @param opts - The options for the hit point testing.
|
|
5313
5336
|
*
|
|
5337
|
+
* @returns An array of shapes at the given point, sorted in reverse order of their absolute z-index (top-most shape first).
|
|
5338
|
+
*
|
|
5314
5339
|
* @public
|
|
5315
5340
|
*/
|
|
5316
5341
|
getShapesAtPoint(
|
|
5317
5342
|
point: VecLike,
|
|
5318
5343
|
opts = {} as { margin?: number; hitInside?: boolean }
|
|
5319
5344
|
): TLShape[] {
|
|
5320
|
-
return this.
|
|
5321
|
-
(shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)
|
|
5322
|
-
|
|
5345
|
+
return this.getCurrentPageShapesSorted()
|
|
5346
|
+
.filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts))
|
|
5347
|
+
.reverse()
|
|
5323
5348
|
}
|
|
5324
5349
|
|
|
5325
5350
|
/**
|
|
@@ -5503,7 +5528,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5503
5528
|
if (!id) return undefined
|
|
5504
5529
|
const freshShape = this.getShape(id)
|
|
5505
5530
|
if (freshShape === undefined || !isShapeId(freshShape.parentId)) return undefined
|
|
5506
|
-
return this.
|
|
5531
|
+
return this.getShape(freshShape.parentId)
|
|
5507
5532
|
}
|
|
5508
5533
|
|
|
5509
5534
|
/**
|
|
@@ -5686,6 +5711,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5686
5711
|
const newPoint = invertedParentTransform.applyToPoint(pagePoint)
|
|
5687
5712
|
const newRotation = pageTransform.rotation() - parentPageRotation
|
|
5688
5713
|
|
|
5714
|
+
if (shape.id === parentId) {
|
|
5715
|
+
throw Error('Attempted to reparent a shape to itself!')
|
|
5716
|
+
}
|
|
5717
|
+
|
|
5689
5718
|
changes.push({
|
|
5690
5719
|
id: shape.id,
|
|
5691
5720
|
type: shape.type,
|
|
@@ -5789,6 +5818,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5789
5818
|
return shapeIds
|
|
5790
5819
|
}
|
|
5791
5820
|
|
|
5821
|
+
/** @deprecated Use {@link Editor.getDraggingOverShape} instead */
|
|
5822
|
+
getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
|
|
5823
|
+
return this.getDraggingOverShape(point, droppingShapes)
|
|
5824
|
+
}
|
|
5825
|
+
|
|
5792
5826
|
/**
|
|
5793
5827
|
* Get the shape that some shapes should be dropped on at a given point.
|
|
5794
5828
|
*
|
|
@@ -5799,35 +5833,33 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5799
5833
|
*
|
|
5800
5834
|
* @public
|
|
5801
5835
|
*/
|
|
5802
|
-
|
|
5803
|
-
//
|
|
5804
|
-
const
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
if (
|
|
5809
|
-
// ignore hidden shapes
|
|
5810
|
-
this.isShapeHidden(shape) ||
|
|
5811
|
-
// don't allow dropping on selected shapes
|
|
5812
|
-
this.getSelectedShapeIds().includes(shape.id) ||
|
|
5813
|
-
// only allow shapes that can receive children
|
|
5814
|
-
!this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) ||
|
|
5815
|
-
// don't allow dropping a shape on itself or one of it's children
|
|
5816
|
-
droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
|
|
5817
|
-
) {
|
|
5818
|
-
continue
|
|
5819
|
-
}
|
|
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
|
+
)
|
|
5820
5841
|
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
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
|
+
)
|
|
5824
5852
|
|
|
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
|
|
5825
5856
|
if (
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5857
|
+
shapeUtil.onDragShapesOver ||
|
|
5858
|
+
shapeUtil.onDragShapesIn ||
|
|
5859
|
+
shapeUtil.onDragShapesOut ||
|
|
5860
|
+
shapeUtil.onDropShapesOver
|
|
5829
5861
|
) {
|
|
5830
|
-
return
|
|
5862
|
+
return maybeDraggingOverShape
|
|
5831
5863
|
}
|
|
5832
5864
|
}
|
|
5833
5865
|
}
|
|
@@ -6186,11 +6218,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6186
6218
|
*/
|
|
6187
6219
|
duplicateShapes(shapes: TLShapeId[] | TLShape[], offset?: VecLike): this {
|
|
6188
6220
|
this.run(() => {
|
|
6189
|
-
const
|
|
6221
|
+
const _ids =
|
|
6190
6222
|
typeof shapes[0] === 'string'
|
|
6191
6223
|
? (shapes as TLShapeId[])
|
|
6192
6224
|
: (shapes as TLShape[]).map((s) => s.id)
|
|
6193
6225
|
|
|
6226
|
+
const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids)
|
|
6194
6227
|
if (ids.length <= 0) return this
|
|
6195
6228
|
|
|
6196
6229
|
const initialIds = new Set(ids)
|
|
@@ -6270,10 +6303,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6270
6303
|
})
|
|
6271
6304
|
const shapesToCreate = shapesToCreateWithOriginals.map(({ shape }) => shape)
|
|
6272
6305
|
|
|
6273
|
-
|
|
6274
|
-
shapesToCreate.length + this.getCurrentPageShapeIds().size > this.options.maxShapesPerPage
|
|
6275
|
-
|
|
6276
|
-
if (maxShapesReached) {
|
|
6306
|
+
if (!this.canCreateShapes(shapesToCreate)) {
|
|
6277
6307
|
alertMaxShapes(this)
|
|
6278
6308
|
return
|
|
6279
6309
|
}
|
|
@@ -7702,6 +7732,32 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7702
7732
|
return {}
|
|
7703
7733
|
}
|
|
7704
7734
|
|
|
7735
|
+
/**
|
|
7736
|
+
* Get whether the provided shape can be created.
|
|
7737
|
+
*
|
|
7738
|
+
* @param shape - The shape or shape IDs to check.
|
|
7739
|
+
*
|
|
7740
|
+
* @public
|
|
7741
|
+
*/
|
|
7742
|
+
canCreateShape<T extends TLUnknownShape>(
|
|
7743
|
+
shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']
|
|
7744
|
+
): boolean {
|
|
7745
|
+
return this.canCreateShapes([shape])
|
|
7746
|
+
}
|
|
7747
|
+
|
|
7748
|
+
/**
|
|
7749
|
+
* Get whether the provided shapes can be created.
|
|
7750
|
+
*
|
|
7751
|
+
* @param shapes - The shapes or shape IDs to create.
|
|
7752
|
+
*
|
|
7753
|
+
* @public
|
|
7754
|
+
*/
|
|
7755
|
+
canCreateShapes<T extends TLUnknownShape>(
|
|
7756
|
+
shapes: (T['id'] | OptionalKeys<TLShapePartial<T>, 'id'>)[]
|
|
7757
|
+
): boolean {
|
|
7758
|
+
return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage
|
|
7759
|
+
}
|
|
7760
|
+
|
|
7705
7761
|
/**
|
|
7706
7762
|
* Create a single shape.
|
|
7707
7763
|
*
|
|
@@ -7748,6 +7804,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7748
7804
|
if (maxShapesReached) {
|
|
7749
7805
|
// can't create more shapes than fit on the page
|
|
7750
7806
|
alertMaxShapes(this)
|
|
7807
|
+
// todo: throw an error here? Otherwise we'll need to check every time whether the shapes were actually created
|
|
7751
7808
|
return this
|
|
7752
7809
|
}
|
|
7753
7810
|
|
|
@@ -7780,9 +7837,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7780
7837
|
|
|
7781
7838
|
for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
|
|
7782
7839
|
const parent = currentPageShapesSorted[i]
|
|
7840
|
+
const util = this.getShapeUtil(parent)
|
|
7783
7841
|
if (
|
|
7842
|
+
util.canReceiveNewChildrenOfType(parent, partial.type) &&
|
|
7784
7843
|
!this.isShapeHidden(parent) &&
|
|
7785
|
-
this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) &&
|
|
7786
7844
|
this.isPointInShape(
|
|
7787
7845
|
parent,
|
|
7788
7846
|
// If no parent is provided, then we can treat the
|
|
@@ -7911,6 +7969,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7911
7969
|
}
|
|
7912
7970
|
})
|
|
7913
7971
|
|
|
7972
|
+
this.emit('created-shapes', shapeRecordsToCreate)
|
|
7973
|
+
this.emit('edit')
|
|
7914
7974
|
this.store.put(shapeRecordsToCreate)
|
|
7915
7975
|
})
|
|
7916
7976
|
|
|
@@ -8305,6 +8365,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8305
8365
|
updates.push(updated)
|
|
8306
8366
|
}
|
|
8307
8367
|
|
|
8368
|
+
this.emit('edited-shapes', updates)
|
|
8369
|
+
this.emit('edit')
|
|
8308
8370
|
this.store.put(updates)
|
|
8309
8371
|
})
|
|
8310
8372
|
}
|
|
@@ -8354,6 +8416,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8354
8416
|
})
|
|
8355
8417
|
}
|
|
8356
8418
|
|
|
8419
|
+
this.emit('deleted-shapes', [...allShapeIdsToDelete])
|
|
8420
|
+
this.emit('edit')
|
|
8357
8421
|
return this.run(() => this.store.remove([...allShapeIdsToDelete]))
|
|
8358
8422
|
}
|
|
8359
8423
|
|
|
@@ -8802,6 +8866,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8802
8866
|
} = {
|
|
8803
8867
|
text: null,
|
|
8804
8868
|
files: null,
|
|
8869
|
+
'file-replace': null,
|
|
8805
8870
|
embed: null,
|
|
8806
8871
|
'svg-text': null,
|
|
8807
8872
|
url: null,
|
|
@@ -8851,6 +8916,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8851
8916
|
return this.externalContentHandlers[info.type]?.(info as any)
|
|
8852
8917
|
}
|
|
8853
8918
|
|
|
8919
|
+
/**
|
|
8920
|
+
* Handle replacing external content.
|
|
8921
|
+
*
|
|
8922
|
+
* @param info - Info about the external content.
|
|
8923
|
+
*/
|
|
8924
|
+
async replaceExternalContent<E>(info: TLExternalContent<E>): Promise<void> {
|
|
8925
|
+
return this.externalContentHandlers[info.type]?.(info as any)
|
|
8926
|
+
}
|
|
8927
|
+
|
|
8854
8928
|
/**
|
|
8855
8929
|
* Get content that can be exported for the given shape ids.
|
|
8856
8930
|
*
|
|
@@ -9268,6 +9342,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9268
9342
|
if (rootShapes.length === 1) {
|
|
9269
9343
|
const onlyRoot = rootShapes[0] as TLFrameShape
|
|
9270
9344
|
// If the old bounds are in the viewport...
|
|
9345
|
+
// todo: replace frame references with shapes that can accept children
|
|
9271
9346
|
if (this.isShapeOfType<TLFrameShape>(onlyRoot, 'frame')) {
|
|
9272
9347
|
while (
|
|
9273
9348
|
this.getShapesAtPoint(point).some(
|
|
@@ -9469,6 +9544,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9469
9544
|
previousPagePoint,
|
|
9470
9545
|
currentScreenPoint,
|
|
9471
9546
|
currentPagePoint,
|
|
9547
|
+
originScreenPoint,
|
|
9548
|
+
originPagePoint,
|
|
9472
9549
|
} = this.inputs
|
|
9473
9550
|
|
|
9474
9551
|
const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
|
|
@@ -9497,8 +9574,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9497
9574
|
// Reset velocity on pointer down, or when a pinch starts or ends
|
|
9498
9575
|
if (info.name === 'pointer_down' || this.inputs.isPinching) {
|
|
9499
9576
|
pointerVelocity.set(0, 0)
|
|
9500
|
-
|
|
9501
|
-
|
|
9577
|
+
originScreenPoint.setTo(currentScreenPoint)
|
|
9578
|
+
originPagePoint.setTo(currentPagePoint)
|
|
9502
9579
|
}
|
|
9503
9580
|
|
|
9504
9581
|
// todo: We only have to do this if there are multiple users in the document
|
|
@@ -62,6 +62,12 @@ export interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {
|
|
|
62
62
|
shapeBefore: TLShape
|
|
63
63
|
/** The shape record after the change is made. */
|
|
64
64
|
shapeAfter: TLShape
|
|
65
|
+
/**
|
|
66
|
+
* Why did this shape change?
|
|
67
|
+
* - 'self': the shape itself changed
|
|
68
|
+
* - 'ancestry': the ancestry of the shape changed, but the shape itself may not have done
|
|
69
|
+
*/
|
|
70
|
+
reason: 'self' | 'ancestry'
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
/**
|
|
@@ -96,8 +96,7 @@ export class FontManager {
|
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
areResultsEqual: areArraysShallowEqual,
|
|
99
|
-
|
|
100
|
-
areRecordsEqual: (a, b) => a.props.richText === b.props.richText,
|
|
99
|
+
areRecordsEqual: (a, b) => a.props === b.props && a.meta === b.meta,
|
|
101
100
|
}
|
|
102
101
|
)
|
|
103
102
|
|
|
@@ -241,7 +241,9 @@ export class HistoryManager<R extends UnknownRecord> {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
bailToMark(id: string) {
|
|
244
|
-
|
|
244
|
+
if (id) {
|
|
245
|
+
this._undo({ pushToRedoStack: false, toMark: id })
|
|
246
|
+
}
|
|
245
247
|
|
|
246
248
|
return this
|
|
247
249
|
}
|
|
@@ -99,7 +99,7 @@ describe('TextManager', () => {
|
|
|
99
99
|
})
|
|
100
100
|
|
|
101
101
|
it('should handle empty text', () => {
|
|
102
|
-
const result = textManager.measureText('', defaultOpts)
|
|
102
|
+
const result = textManager.measureText('', { ...defaultOpts, measureScrollWidth: true })
|
|
103
103
|
expect(result).toHaveProperty('x', 0)
|
|
104
104
|
expect(result).toHaveProperty('y', 0)
|
|
105
105
|
expect(result).toHaveProperty('w')
|
|
@@ -128,7 +128,6 @@ describe('TextManager', () => {
|
|
|
128
128
|
y: 0,
|
|
129
129
|
w: expect.any(Number),
|
|
130
130
|
h: expect.any(Number),
|
|
131
|
-
scrollWidth: expect.any(Number),
|
|
132
131
|
})
|
|
133
132
|
})
|
|
134
133
|
|
|
@@ -141,7 +140,6 @@ describe('TextManager', () => {
|
|
|
141
140
|
y: 0,
|
|
142
141
|
w: expect.any(Number),
|
|
143
142
|
h: expect.any(Number),
|
|
144
|
-
scrollWidth: expect.any(Number),
|
|
145
143
|
})
|
|
146
144
|
})
|
|
147
145
|
|
|
@@ -154,7 +152,6 @@ describe('TextManager', () => {
|
|
|
154
152
|
y: 0,
|
|
155
153
|
w: expect.any(Number),
|
|
156
154
|
h: expect.any(Number),
|
|
157
|
-
scrollWidth: expect.any(Number),
|
|
158
155
|
})
|
|
159
156
|
})
|
|
160
157
|
|
|
@@ -173,7 +170,6 @@ describe('TextManager', () => {
|
|
|
173
170
|
y: 0,
|
|
174
171
|
w: expect.any(Number),
|
|
175
172
|
h: expect.any(Number),
|
|
176
|
-
scrollWidth: expect.any(Number),
|
|
177
173
|
})
|
|
178
174
|
})
|
|
179
175
|
})
|