@tldraw/editor 4.2.0-next.f100cedfc45b → 4.3.0-canary.03ae87dcc44b
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 +59 -37
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/editor/Editor.js +11 -18
- 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/derivations/bindingsIndex.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +4 -3
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +8 -4
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.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 +59 -37
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/editor/Editor.mjs +11 -18
- 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/derivations/bindingsIndex.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +4 -3
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +8 -4
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +10 -10
- package/src/lib/editor/Editor.test.ts +278 -10
- package/src/lib/editor/Editor.ts +92 -65
- package/src/lib/editor/bindings/BindingUtil.ts +15 -9
- package/src/lib/editor/derivations/bindingsIndex.ts +2 -2
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +14 -4
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +3 -3
- package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
- package/src/lib/editor/shapes/ShapeUtil.ts +5 -8
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -3
- package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
- package/src/lib/exports/getSvgJsx.test.ts +10 -19
- package/src/lib/exports/getSvgJsx.tsx +2 -5
- package/src/lib/hooks/useCanvasEvents.ts +4 -3
- package/src/lib/license/Watermark.tsx +8 -5
- package/src/lib/utils/reparenting.ts +5 -5
- package/src/version.ts +3 -3
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
PageRecordType,
|
|
22
22
|
StyleProp,
|
|
23
23
|
StylePropValue,
|
|
24
|
-
TLArrowShape,
|
|
25
24
|
TLAsset,
|
|
26
25
|
TLAssetId,
|
|
27
26
|
TLAssetPartial,
|
|
@@ -30,12 +29,12 @@ import {
|
|
|
30
29
|
TLBindingId,
|
|
31
30
|
TLBindingUpdate,
|
|
32
31
|
TLCamera,
|
|
32
|
+
TLCreateShapePartial,
|
|
33
33
|
TLCursor,
|
|
34
34
|
TLCursorType,
|
|
35
35
|
TLDOCUMENT_ID,
|
|
36
36
|
TLDocument,
|
|
37
37
|
TLFrameShape,
|
|
38
|
-
TLGeoShape,
|
|
39
38
|
TLGroupShape,
|
|
40
39
|
TLHandle,
|
|
41
40
|
TLINSTANCE_ID,
|
|
@@ -43,7 +42,6 @@ import {
|
|
|
43
42
|
TLInstance,
|
|
44
43
|
TLInstancePageState,
|
|
45
44
|
TLInstancePresence,
|
|
46
|
-
TLNoteShape,
|
|
47
45
|
TLPOINTER_ID,
|
|
48
46
|
TLPage,
|
|
49
47
|
TLPageId,
|
|
@@ -54,8 +52,6 @@ import {
|
|
|
54
52
|
TLShapePartial,
|
|
55
53
|
TLStore,
|
|
56
54
|
TLStoreSnapshot,
|
|
57
|
-
TLUnknownBinding,
|
|
58
|
-
TLUnknownShape,
|
|
59
55
|
TLVideoAsset,
|
|
60
56
|
createBindingId,
|
|
61
57
|
createShapeId,
|
|
@@ -447,7 +443,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
447
443
|
let deletedBindings = new Map<TLBindingId, BindingOnDeleteOptions<any>>()
|
|
448
444
|
const deletedShapeIds = new Set<TLShapeId>()
|
|
449
445
|
const invalidParents = new Set<TLShapeId>()
|
|
450
|
-
let invalidBindingTypes = new Set<
|
|
446
|
+
let invalidBindingTypes = new Set<TLBinding['type']>()
|
|
451
447
|
this.disposables.add(
|
|
452
448
|
this.sideEffects.registerOperationCompleteHandler(() => {
|
|
453
449
|
// this needs to be cleared here because further effects may delete more shapes
|
|
@@ -710,7 +706,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
710
706
|
if (filtered.length > 0) {
|
|
711
707
|
const commonGroupAncestor = this.findCommonAncestor(
|
|
712
708
|
compact(filtered.map((id) => this.getShape(id))),
|
|
713
|
-
(shape) => this.isShapeOfType
|
|
709
|
+
(shape) => this.isShapeOfType(shape, 'group')
|
|
714
710
|
)
|
|
715
711
|
|
|
716
712
|
if (commonGroupAncestor) {
|
|
@@ -842,14 +838,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
842
838
|
* after the editor has already been initialized.
|
|
843
839
|
*
|
|
844
840
|
* @param Tool - The tool to set.
|
|
841
|
+
* @param parent - The parent state node to set the tool on.
|
|
845
842
|
*
|
|
846
843
|
* @public
|
|
847
844
|
*/
|
|
848
|
-
setTool(Tool: TLStateNodeConstructor) {
|
|
849
|
-
|
|
845
|
+
setTool(Tool: TLStateNodeConstructor, parent?: StateNode) {
|
|
846
|
+
parent ??= this.root
|
|
847
|
+
if (hasOwnProperty(parent.children!, Tool.id)) {
|
|
850
848
|
throw Error(`Can't override tool with id "${Tool.id}"`)
|
|
851
849
|
}
|
|
852
|
-
|
|
850
|
+
parent.children![Tool.id] = new Tool(this, parent)
|
|
853
851
|
}
|
|
854
852
|
|
|
855
853
|
/**
|
|
@@ -857,12 +855,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
857
855
|
* after the editor has already been initialized.
|
|
858
856
|
*
|
|
859
857
|
* @param Tool - The tool to delete.
|
|
858
|
+
* @param parent - The parent state node to remove the tool from.
|
|
860
859
|
*
|
|
861
860
|
* @public
|
|
862
861
|
*/
|
|
863
|
-
removeTool(Tool: TLStateNodeConstructor) {
|
|
864
|
-
|
|
865
|
-
|
|
862
|
+
removeTool(Tool: TLStateNodeConstructor, parent?: StateNode) {
|
|
863
|
+
parent ??= this.root
|
|
864
|
+
if (hasOwnProperty(parent.children!, Tool.id)) {
|
|
865
|
+
delete parent.children![Tool.id]
|
|
866
866
|
}
|
|
867
867
|
}
|
|
868
868
|
|
|
@@ -978,7 +978,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
978
978
|
*
|
|
979
979
|
* @public
|
|
980
980
|
*/
|
|
981
|
-
shapeUtils: { readonly [K in string]?: ShapeUtil<
|
|
981
|
+
shapeUtils: { readonly [K in string]?: ShapeUtil<TLShape> }
|
|
982
982
|
|
|
983
983
|
styleProps: { [key: string]: Map<StyleProp<any>, string> }
|
|
984
984
|
|
|
@@ -997,8 +997,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
997
997
|
*
|
|
998
998
|
* @public
|
|
999
999
|
*/
|
|
1000
|
-
getShapeUtil<
|
|
1001
|
-
getShapeUtil<S extends
|
|
1000
|
+
getShapeUtil<K extends TLShape['type']>(type: K): ShapeUtil<Extract<TLShape, { type: K }>>
|
|
1001
|
+
getShapeUtil<S extends TLShape>(shape: S | TLShapePartial<S> | S['type']): ShapeUtil<S>
|
|
1002
1002
|
getShapeUtil<T extends ShapeUtil>(type: T extends ShapeUtil<infer R> ? R['type'] : string): T
|
|
1003
1003
|
getShapeUtil(arg: string | { type: string }) {
|
|
1004
1004
|
const type = typeof arg === 'string' ? arg : arg.type
|
|
@@ -1012,8 +1012,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1012
1012
|
*
|
|
1013
1013
|
* @param shape - A shape, shape partial, or shape type.
|
|
1014
1014
|
*/
|
|
1015
|
-
hasShapeUtil
|
|
1016
|
-
hasShapeUtil
|
|
1015
|
+
hasShapeUtil(shape: TLShape | TLShapePartial<TLShape>): boolean
|
|
1016
|
+
hasShapeUtil(type: TLShape['type']): boolean
|
|
1017
1017
|
hasShapeUtil<T extends ShapeUtil>(
|
|
1018
1018
|
type: T extends ShapeUtil<infer R> ? R['type'] : string
|
|
1019
1019
|
): boolean
|
|
@@ -1028,7 +1028,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1028
1028
|
*
|
|
1029
1029
|
* @public
|
|
1030
1030
|
*/
|
|
1031
|
-
bindingUtils: { readonly [K in string]?: BindingUtil<
|
|
1031
|
+
bindingUtils: { readonly [K in string]?: BindingUtil<TLBinding> }
|
|
1032
1032
|
|
|
1033
1033
|
/**
|
|
1034
1034
|
* Get a binding util from a binding itself.
|
|
@@ -1045,8 +1045,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1045
1045
|
*
|
|
1046
1046
|
* @public
|
|
1047
1047
|
*/
|
|
1048
|
-
getBindingUtil<
|
|
1049
|
-
getBindingUtil<S extends
|
|
1048
|
+
getBindingUtil<K extends TLBinding['type']>(type: K): BindingUtil<Extract<TLBinding, { type: K }>>
|
|
1049
|
+
getBindingUtil<S extends TLBinding>(binding: S | { type: S['type'] }): BindingUtil<S>
|
|
1050
1050
|
getBindingUtil<T extends BindingUtil>(
|
|
1051
1051
|
type: T extends BindingUtil<infer R> ? R['type'] : string
|
|
1052
1052
|
): T
|
|
@@ -2216,7 +2216,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2216
2216
|
throw Error(`Editor.setFocusedGroup: Shape with id ${id} does not exist`)
|
|
2217
2217
|
}
|
|
2218
2218
|
|
|
2219
|
-
if (!this.isShapeOfType
|
|
2219
|
+
if (!this.isShapeOfType(shape, 'group')) {
|
|
2220
2220
|
throw Error(
|
|
2221
2221
|
`Editor.setFocusedGroup: Cannot set focused group to shape of type ${shape.type}`
|
|
2222
2222
|
)
|
|
@@ -2244,7 +2244,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2244
2244
|
if (focusedGroup) {
|
|
2245
2245
|
// If we have a focused layer, look for an ancestor of the focused shape that is a group
|
|
2246
2246
|
const match = this.findShapeAncestor(focusedGroup, (shape) =>
|
|
2247
|
-
this.isShapeOfType
|
|
2247
|
+
this.isShapeOfType(shape, 'group')
|
|
2248
2248
|
)
|
|
2249
2249
|
// If we have an ancestor that can become a focused layer, set it as the focused layer
|
|
2250
2250
|
this.setFocusedGroup(match?.id ?? null)
|
|
@@ -5123,10 +5123,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5123
5123
|
|
|
5124
5124
|
// Check labels first
|
|
5125
5125
|
if (
|
|
5126
|
-
this.isShapeOfType
|
|
5127
|
-
((this.isShapeOfType
|
|
5128
|
-
this.isShapeOfType
|
|
5129
|
-
(this.isShapeOfType
|
|
5126
|
+
this.isShapeOfType(shape, 'frame') ||
|
|
5127
|
+
((this.isShapeOfType(shape, 'note') ||
|
|
5128
|
+
this.isShapeOfType(shape, 'arrow') ||
|
|
5129
|
+
(this.isShapeOfType(shape, 'geo') && shape.props.fill === 'none')) &&
|
|
5130
5130
|
this.getShapeUtil(shape).getText(shape)?.trim())
|
|
5131
5131
|
) {
|
|
5132
5132
|
for (const childGeometry of (geometry as Group2d).children) {
|
|
@@ -5136,7 +5136,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5136
5136
|
}
|
|
5137
5137
|
}
|
|
5138
5138
|
|
|
5139
|
-
if (this.isShapeOfType
|
|
5139
|
+
if (this.isShapeOfType(shape, 'frame')) {
|
|
5140
5140
|
// On the rare case that we've hit a frame (not its label), test again hitInside to be forced true;
|
|
5141
5141
|
// this prevents clicks from passing through the body of a frame to shapes behind it.
|
|
5142
5142
|
|
|
@@ -5417,7 +5417,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5417
5417
|
*
|
|
5418
5418
|
* @example
|
|
5419
5419
|
* ```ts
|
|
5420
|
-
* const isArrowShape = isShapeOfType
|
|
5420
|
+
* const isArrowShape = isShapeOfType(someShape, 'arrow')
|
|
5421
5421
|
* ```
|
|
5422
5422
|
*
|
|
5423
5423
|
* @param util - the TLShapeUtil constructor to test against
|
|
@@ -5425,15 +5425,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5425
5425
|
*
|
|
5426
5426
|
* @public
|
|
5427
5427
|
*/
|
|
5428
|
-
isShapeOfType<
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
arg: TLUnknownShape | TLUnknownShape['id'],
|
|
5428
|
+
isShapeOfType<K extends TLShape['type']>(
|
|
5429
|
+
shape: TLShape,
|
|
5430
|
+
type: K
|
|
5431
|
+
): shape is Extract<TLShape, { type: K }>
|
|
5432
|
+
isShapeOfType<T extends TLShape>(
|
|
5433
|
+
shape: TLShape,
|
|
5435
5434
|
type: T['type']
|
|
5436
|
-
) {
|
|
5435
|
+
): shape is Extract<TLShape, { type: T['type'] }>
|
|
5436
|
+
isShapeOfType<T extends TLShape = TLShape>(shapeId: TLShapeId, type: T['type']): boolean
|
|
5437
|
+
isShapeOfType(arg: TLShape | TLShapeId, type: TLShape['type']) {
|
|
5437
5438
|
const shape = typeof arg === 'string' ? this.getShape(arg) : arg
|
|
5438
5439
|
if (!shape) return false
|
|
5439
5440
|
return shape.type === type
|
|
@@ -5829,7 +5830,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5829
5830
|
|
|
5830
5831
|
while (node) {
|
|
5831
5832
|
if (
|
|
5832
|
-
this.isShapeOfType
|
|
5833
|
+
this.isShapeOfType(node, 'group') &&
|
|
5833
5834
|
focusedGroup?.id !== node.id &&
|
|
5834
5835
|
!this.hasAncestor(focusedGroup, node.id) &&
|
|
5835
5836
|
(filter?.(node) ?? true)
|
|
@@ -5871,7 +5872,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5871
5872
|
* Get all bindings of a certain type _from_ a particular shape. These are the bindings whose
|
|
5872
5873
|
* `fromId` matched the shape's ID.
|
|
5873
5874
|
*/
|
|
5874
|
-
getBindingsFromShape<
|
|
5875
|
+
getBindingsFromShape<K extends TLBinding['type']>(
|
|
5876
|
+
shape: TLShape | TLShapeId,
|
|
5877
|
+
type: K
|
|
5878
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5879
|
+
getBindingsFromShape<Binding extends TLBinding = TLBinding>(
|
|
5880
|
+
shape: TLShape | TLShapeId,
|
|
5881
|
+
type: Binding['type']
|
|
5882
|
+
): Binding[]
|
|
5883
|
+
getBindingsFromShape<Binding extends TLBinding = TLBinding>(
|
|
5875
5884
|
shape: TLShape | TLShapeId,
|
|
5876
5885
|
type: Binding['type']
|
|
5877
5886
|
): Binding[] {
|
|
@@ -5885,7 +5894,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5885
5894
|
* Get all bindings of a certain type _to_ a particular shape. These are the bindings whose
|
|
5886
5895
|
* `toId` matches the shape's ID.
|
|
5887
5896
|
*/
|
|
5888
|
-
getBindingsToShape<
|
|
5897
|
+
getBindingsToShape<K extends TLBinding['type']>(
|
|
5898
|
+
shape: TLShape | TLShapeId,
|
|
5899
|
+
type: K
|
|
5900
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5901
|
+
getBindingsToShape<Binding extends TLBinding = TLBinding>(
|
|
5902
|
+
shape: TLShape | TLShapeId,
|
|
5903
|
+
type: Binding['type']
|
|
5904
|
+
): Binding[]
|
|
5905
|
+
getBindingsToShape<Binding extends TLBinding = TLBinding>(
|
|
5889
5906
|
shape: TLShape | TLShapeId,
|
|
5890
5907
|
type: Binding['type']
|
|
5891
5908
|
): Binding[] {
|
|
@@ -5899,7 +5916,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5899
5916
|
* Get all bindings involving a particular shape. This includes bindings where the shape is the
|
|
5900
5917
|
* `fromId` or `toId`. If a type is provided, only bindings of that type are returned.
|
|
5901
5918
|
*/
|
|
5902
|
-
getBindingsInvolvingShape<
|
|
5919
|
+
getBindingsInvolvingShape<K extends TLBinding['type']>(
|
|
5920
|
+
shape: TLShape | TLShapeId,
|
|
5921
|
+
type: K
|
|
5922
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5923
|
+
getBindingsInvolvingShape<Binding extends TLBinding = TLBinding>(
|
|
5924
|
+
shape: TLShape | TLShapeId,
|
|
5925
|
+
type?: Binding['type']
|
|
5926
|
+
): Binding[]
|
|
5927
|
+
getBindingsInvolvingShape<Binding extends TLBinding = TLBinding>(
|
|
5903
5928
|
shape: TLShape | TLShapeId,
|
|
5904
5929
|
type?: Binding['type']
|
|
5905
5930
|
): Binding[] {
|
|
@@ -5921,7 +5946,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5921
5946
|
if (!fromShape || !toShape) continue
|
|
5922
5947
|
if (!this.canBindShapes({ fromShape, toShape, binding: partial })) continue
|
|
5923
5948
|
|
|
5924
|
-
const util = this.getBindingUtil
|
|
5949
|
+
const util = this.getBindingUtil(partial.type)
|
|
5925
5950
|
const defaultProps = util.getDefaultProps()
|
|
5926
5951
|
const binding = this.store.schema.types.binding.create({
|
|
5927
5952
|
...partial,
|
|
@@ -6026,7 +6051,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6026
6051
|
const toShapeType = typeof toShape === 'string' ? toShape : toShape.type
|
|
6027
6052
|
const bindingType = typeof binding === 'string' ? binding : binding.type
|
|
6028
6053
|
|
|
6029
|
-
const canBindOpts = { fromShapeType, toShapeType, bindingType }
|
|
6054
|
+
const canBindOpts = { fromShapeType, toShapeType, bindingType } as const
|
|
6030
6055
|
|
|
6031
6056
|
if (fromShapeType === toShapeType) {
|
|
6032
6057
|
return this.getShapeUtil(fromShapeType).canBind(canBindOpts)
|
|
@@ -6567,7 +6592,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6567
6592
|
const shapesToFlipFirstPass = compact(ids.map((id) => this.getShape(id)))
|
|
6568
6593
|
|
|
6569
6594
|
for (const shape of shapesToFlipFirstPass) {
|
|
6570
|
-
if (this.isShapeOfType
|
|
6595
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
6571
6596
|
const childrenOfGroups = compact(
|
|
6572
6597
|
this.getSortedChildIdsForParent(shape.id).map((id) => this.getShape(id))
|
|
6573
6598
|
)
|
|
@@ -7688,9 +7713,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7688
7713
|
*
|
|
7689
7714
|
* @public
|
|
7690
7715
|
*/
|
|
7691
|
-
canCreateShape<
|
|
7692
|
-
shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']
|
|
7693
|
-
): boolean {
|
|
7716
|
+
canCreateShape(shape: OptionalKeys<TLShapePartial<TLShape>, 'id'> | TLShape['id']): boolean {
|
|
7694
7717
|
return this.canCreateShapes([shape])
|
|
7695
7718
|
}
|
|
7696
7719
|
|
|
@@ -7701,8 +7724,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7701
7724
|
*
|
|
7702
7725
|
* @public
|
|
7703
7726
|
*/
|
|
7704
|
-
canCreateShapes
|
|
7705
|
-
shapes: (
|
|
7727
|
+
canCreateShapes(
|
|
7728
|
+
shapes: (TLShape['id'] | OptionalKeys<TLShapePartial<TLShape>, 'id'>)[]
|
|
7706
7729
|
): boolean {
|
|
7707
7730
|
return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage
|
|
7708
7731
|
}
|
|
@@ -7720,7 +7743,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7720
7743
|
*
|
|
7721
7744
|
* @public
|
|
7722
7745
|
*/
|
|
7723
|
-
createShape<
|
|
7746
|
+
createShape<TShape extends TLShape>(shape: TLCreateShapePartial<TShape>): this {
|
|
7724
7747
|
this.createShapes([shape])
|
|
7725
7748
|
return this
|
|
7726
7749
|
}
|
|
@@ -7738,7 +7761,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7738
7761
|
*
|
|
7739
7762
|
* @public
|
|
7740
7763
|
*/
|
|
7741
|
-
createShapes<
|
|
7764
|
+
createShapes<TShape extends TLShape = TLShape>(shapes: TLCreateShapePartial<TShape>[]): this {
|
|
7742
7765
|
if (!Array.isArray(shapes)) {
|
|
7743
7766
|
throw Error('Editor.createShapes: must provide an array of shapes or shape partials')
|
|
7744
7767
|
}
|
|
@@ -8119,7 +8142,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8119
8142
|
const highestIndex = shapesWithRootParent[shapesWithRootParent.length - 1]?.index
|
|
8120
8143
|
|
|
8121
8144
|
this.run(() => {
|
|
8122
|
-
this.createShapes
|
|
8145
|
+
this.createShapes([
|
|
8123
8146
|
{
|
|
8124
8147
|
id: groupId,
|
|
8125
8148
|
type: 'group',
|
|
@@ -8189,7 +8212,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8189
8212
|
const groups: TLGroupShape[] = []
|
|
8190
8213
|
|
|
8191
8214
|
shapesToUngroup.forEach((shape) => {
|
|
8192
|
-
if (this.isShapeOfType
|
|
8215
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8193
8216
|
groups.push(shape)
|
|
8194
8217
|
} else {
|
|
8195
8218
|
idsToSelect.add(shape.id)
|
|
@@ -8235,7 +8258,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8235
8258
|
*
|
|
8236
8259
|
* @public
|
|
8237
8260
|
*/
|
|
8238
|
-
updateShape<T extends
|
|
8261
|
+
updateShape<T extends TLShape = TLShape>(partial: TLShapePartial<T> | null | undefined) {
|
|
8239
8262
|
this.updateShapes([partial])
|
|
8240
8263
|
return this
|
|
8241
8264
|
}
|
|
@@ -8252,7 +8275,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8252
8275
|
*
|
|
8253
8276
|
* @public
|
|
8254
8277
|
*/
|
|
8255
|
-
updateShapes<T extends
|
|
8278
|
+
updateShapes<T extends TLShape>(partials: (TLShapePartial<T> | null | undefined)[]) {
|
|
8256
8279
|
const compactedPartials: TLShapePartial<T>[] = Array(partials.length)
|
|
8257
8280
|
|
|
8258
8281
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
@@ -8404,7 +8427,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8404
8427
|
* @internal
|
|
8405
8428
|
*/
|
|
8406
8429
|
private _extractSharedStyles(shape: TLShape, sharedStyleMap: SharedStyleMap) {
|
|
8407
|
-
if (this.isShapeOfType
|
|
8430
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8408
8431
|
// For groups, ignore the styles of the group shape and instead include the styles of the
|
|
8409
8432
|
// group's children. These are the shapes that would have their styles changed if the
|
|
8410
8433
|
// user called `setStyle` on the current selection.
|
|
@@ -8524,7 +8547,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8524
8547
|
// For groups, ignore the opacity of the group shape and instead include
|
|
8525
8548
|
// the opacity of the group's children. These are the shapes that would have
|
|
8526
8549
|
// their opacity changed if the user called `setOpacity` on the current selection.
|
|
8527
|
-
if (this.isShapeOfType
|
|
8550
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8528
8551
|
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
8529
8552
|
addShape(childId)
|
|
8530
8553
|
}
|
|
@@ -8585,7 +8608,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8585
8608
|
// We can have many deep levels of grouped shape
|
|
8586
8609
|
// Making a recursive function to look through all the levels
|
|
8587
8610
|
const addShapeById = (shape: TLShape) => {
|
|
8588
|
-
if (this.isShapeOfType
|
|
8611
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8589
8612
|
const childIds = this.getSortedChildIdsForParent(shape)
|
|
8590
8613
|
for (const childId of childIds) {
|
|
8591
8614
|
addShapeById(this.getShape(childId)!)
|
|
@@ -8669,7 +8692,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8669
8692
|
// We can have many deep levels of grouped shape
|
|
8670
8693
|
// Making a recursive function to look through all the levels
|
|
8671
8694
|
const addShapeById = (shape: TLShape) => {
|
|
8672
|
-
if (this.isShapeOfType
|
|
8695
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8673
8696
|
const childIds = this.getSortedChildIdsForParent(shape.id)
|
|
8674
8697
|
for (const childId of childIds) {
|
|
8675
8698
|
addShapeById(this.getShape(childId)!)
|
|
@@ -9094,7 +9117,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9094
9117
|
for (const shape of this.getSelectedShapes()) {
|
|
9095
9118
|
if (lowestDepth === 0) break
|
|
9096
9119
|
|
|
9097
|
-
const isFrame = this.isShapeOfType
|
|
9120
|
+
const isFrame = this.isShapeOfType(shape, 'frame')
|
|
9098
9121
|
const ancestors = this.getShapeAncestors(shape)
|
|
9099
9122
|
if (isFrame) ancestors.push(shape)
|
|
9100
9123
|
|
|
@@ -9133,8 +9156,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9133
9156
|
if (rootShapeIds.length === 1) {
|
|
9134
9157
|
const rootShape = shapes.find((s) => s.id === rootShapeIds[0])!
|
|
9135
9158
|
if (
|
|
9136
|
-
this.isShapeOfType
|
|
9137
|
-
this.isShapeOfType
|
|
9159
|
+
this.isShapeOfType(parent, 'frame') &&
|
|
9160
|
+
this.isShapeOfType(rootShape, 'frame') &&
|
|
9138
9161
|
rootShape.props.w === parent?.props.w &&
|
|
9139
9162
|
rootShape.props.h === parent?.props.h
|
|
9140
9163
|
) {
|
|
@@ -9309,11 +9332,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9309
9332
|
const onlyRoot = rootShapes[0] as TLFrameShape
|
|
9310
9333
|
// If the old bounds are in the viewport...
|
|
9311
9334
|
// todo: replace frame references with shapes that can accept children
|
|
9312
|
-
if (this.isShapeOfType
|
|
9335
|
+
if (this.isShapeOfType(onlyRoot, 'frame')) {
|
|
9313
9336
|
while (
|
|
9314
9337
|
this.getShapesAtPoint(point).some(
|
|
9315
9338
|
(shape) =>
|
|
9316
|
-
this.isShapeOfType
|
|
9339
|
+
this.isShapeOfType(shape, 'frame') &&
|
|
9317
9340
|
shape.props.w === onlyRoot.props.w &&
|
|
9318
9341
|
shape.props.h === onlyRoot.props.h
|
|
9319
9342
|
)
|
|
@@ -10228,6 +10251,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10228
10251
|
}
|
|
10229
10252
|
}
|
|
10230
10253
|
|
|
10254
|
+
this.emit('event', info)
|
|
10231
10255
|
this.root.handleEvent(info)
|
|
10232
10256
|
return
|
|
10233
10257
|
}
|
|
@@ -10726,7 +10750,10 @@ function alertMaxShapes(editor: Editor, pageId = editor.getCurrentPageId()) {
|
|
|
10726
10750
|
|
|
10727
10751
|
function applyPartialToRecordWithProps<
|
|
10728
10752
|
T extends UnknownRecord & { type: string; props: object; meta: object },
|
|
10729
|
-
>(
|
|
10753
|
+
>(
|
|
10754
|
+
prev: T,
|
|
10755
|
+
partial?: T extends T ? Omit<Partial<T>, 'props'> & { props?: Partial<T['props']> } : never
|
|
10756
|
+
): T {
|
|
10730
10757
|
if (!partial) return prev
|
|
10731
10758
|
let next = null as null | T
|
|
10732
10759
|
const entries = Object.entries(partial)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
RecordProps,
|
|
3
|
+
TLBinding,
|
|
4
|
+
TLPropsMigrations,
|
|
5
|
+
TLShape,
|
|
6
|
+
TLUnknownBinding,
|
|
7
|
+
} from '@tldraw/tlschema'
|
|
2
8
|
import { Editor } from '../Editor'
|
|
3
9
|
|
|
4
10
|
/** @public */
|
|
5
11
|
export interface TLBindingUtilConstructor<
|
|
6
|
-
T extends
|
|
12
|
+
T extends TLBinding,
|
|
7
13
|
U extends BindingUtil<T> = BindingUtil<T>,
|
|
8
14
|
> {
|
|
9
15
|
new (editor: Editor): U
|
|
@@ -20,7 +26,7 @@ export interface TLBindingUtilConstructor<
|
|
|
20
26
|
*
|
|
21
27
|
* @public
|
|
22
28
|
*/
|
|
23
|
-
export interface BindingOnCreateOptions<Binding extends
|
|
29
|
+
export interface BindingOnCreateOptions<Binding extends TLBinding = TLBinding> {
|
|
24
30
|
/** The binding being created. */
|
|
25
31
|
binding: Binding
|
|
26
32
|
}
|
|
@@ -31,7 +37,7 @@ export interface BindingOnCreateOptions<Binding extends TLUnknownBinding> {
|
|
|
31
37
|
*
|
|
32
38
|
* @public
|
|
33
39
|
*/
|
|
34
|
-
export interface BindingOnChangeOptions<Binding extends
|
|
40
|
+
export interface BindingOnChangeOptions<Binding extends TLBinding = TLBinding> {
|
|
35
41
|
/** The binding record before the change is made. */
|
|
36
42
|
bindingBefore: Binding
|
|
37
43
|
/** The binding record after the change is made. */
|
|
@@ -44,7 +50,7 @@ export interface BindingOnChangeOptions<Binding extends TLUnknownBinding> {
|
|
|
44
50
|
*
|
|
45
51
|
* @public
|
|
46
52
|
*/
|
|
47
|
-
export interface BindingOnDeleteOptions<Binding extends
|
|
53
|
+
export interface BindingOnDeleteOptions<Binding extends TLBinding = TLBinding> {
|
|
48
54
|
/** The binding being deleted. */
|
|
49
55
|
binding: Binding
|
|
50
56
|
}
|
|
@@ -55,7 +61,7 @@ export interface BindingOnDeleteOptions<Binding extends TLUnknownBinding> {
|
|
|
55
61
|
*
|
|
56
62
|
* @public
|
|
57
63
|
*/
|
|
58
|
-
export interface BindingOnShapeChangeOptions<Binding extends
|
|
64
|
+
export interface BindingOnShapeChangeOptions<Binding extends TLBinding = TLBinding> {
|
|
59
65
|
/** The binding record linking these two shapes. */
|
|
60
66
|
binding: Binding
|
|
61
67
|
/** The shape record before the change is made. */
|
|
@@ -95,7 +101,7 @@ export interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {
|
|
|
95
101
|
*
|
|
96
102
|
* @public
|
|
97
103
|
*/
|
|
98
|
-
export interface BindingOnShapeIsolateOptions<Binding extends
|
|
104
|
+
export interface BindingOnShapeIsolateOptions<Binding extends TLBinding = TLBinding> {
|
|
99
105
|
/** The binding record that refers to the shape in question. */
|
|
100
106
|
binding: Binding
|
|
101
107
|
/**
|
|
@@ -114,7 +120,7 @@ export interface BindingOnShapeIsolateOptions<Binding extends TLUnknownBinding>
|
|
|
114
120
|
*
|
|
115
121
|
* @public
|
|
116
122
|
*/
|
|
117
|
-
export interface BindingOnShapeDeleteOptions<Binding extends
|
|
123
|
+
export interface BindingOnShapeDeleteOptions<Binding extends TLBinding = TLBinding> {
|
|
118
124
|
/** The binding record that refers to the shape in question. */
|
|
119
125
|
binding: Binding
|
|
120
126
|
/** The shape that is about to be deleted. */
|
|
@@ -122,7 +128,7 @@ export interface BindingOnShapeDeleteOptions<Binding extends TLUnknownBinding> {
|
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
/** @public */
|
|
125
|
-
export abstract class BindingUtil<Binding extends
|
|
131
|
+
export abstract class BindingUtil<Binding extends TLBinding = TLBinding> {
|
|
126
132
|
constructor(public editor: Editor) {}
|
|
127
133
|
static props?: RecordProps<TLUnknownBinding>
|
|
128
134
|
static migrations?: TLPropsMigrations
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'
|
|
2
|
-
import {
|
|
2
|
+
import { TLBinding, TLShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { objectMapValues } from '@tldraw/utils'
|
|
4
4
|
import { Editor } from '../Editor'
|
|
5
5
|
|
|
6
6
|
type TLBindingsIndex = Map<TLShapeId, TLBinding[]>
|
|
7
7
|
|
|
8
|
-
function fromScratch(bindingsQuery: Computed<
|
|
8
|
+
function fromScratch(bindingsQuery: Computed<TLBinding[], unknown>) {
|
|
9
9
|
const allBindings = bindingsQuery.get() as TLBinding[]
|
|
10
10
|
|
|
11
11
|
const shapesToBindings: TLBindingsIndex = new Map()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { TLShape, TLShapeId, createShapeId } from '@tldraw/tlschema'
|
|
1
|
+
import { TLParentId, TLShape, TLShapeId, createShapeId, toRichText } from '@tldraw/tlschema'
|
|
2
|
+
import { IndexKey } from '@tldraw/utils'
|
|
2
3
|
import { Mock, Mocked, vi } from 'vitest'
|
|
3
4
|
import { Editor } from '../../Editor'
|
|
4
5
|
import { FontManager, TLFontFace } from './FontManager'
|
|
@@ -41,12 +42,21 @@ describe('FontManager', () => {
|
|
|
41
42
|
x: 0,
|
|
42
43
|
y: 0,
|
|
43
44
|
rotation: 0,
|
|
44
|
-
index: 'a1' as
|
|
45
|
-
parentId: 'page:page' as
|
|
45
|
+
index: 'a1' as IndexKey,
|
|
46
|
+
parentId: 'page:page' as TLParentId,
|
|
46
47
|
opacity: 1,
|
|
47
48
|
isLocked: false,
|
|
48
49
|
meta: {},
|
|
49
|
-
props: {
|
|
50
|
+
props: {
|
|
51
|
+
color: 'black',
|
|
52
|
+
size: 'xl',
|
|
53
|
+
font: 'serif',
|
|
54
|
+
textAlign: 'middle',
|
|
55
|
+
w: 100,
|
|
56
|
+
richText: toRichText('❤️'),
|
|
57
|
+
scale: 2,
|
|
58
|
+
autoSize: true,
|
|
59
|
+
},
|
|
50
60
|
typeName: 'shape' as const,
|
|
51
61
|
})
|
|
52
62
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'
|
|
2
|
-
import {
|
|
2
|
+
import { TLParentId, TLShapeId, isShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { Vec, VecLike } from '../../../primitives/Vec'
|
|
4
4
|
import type { Editor } from '../../Editor'
|
|
5
5
|
import { BoundsSnaps } from './BoundsSnaps'
|
|
@@ -72,7 +72,7 @@ export class SnapManager {
|
|
|
72
72
|
const collectSnappableShapesFromParent = (parentId: TLParentId) => {
|
|
73
73
|
if (isShapeId(parentId)) {
|
|
74
74
|
const parent = editor.getShape(parentId)
|
|
75
|
-
if (parent && editor.isShapeOfType
|
|
75
|
+
if (parent && editor.isShapeOfType(parent, 'frame')) {
|
|
76
76
|
snappableShapes.add(parentId)
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -89,7 +89,7 @@ export class SnapManager {
|
|
|
89
89
|
const pageBounds = editor.getShapePageBounds(childId)
|
|
90
90
|
if (!(pageBounds && renderingBounds.includes(pageBounds))) continue
|
|
91
91
|
// Snap to children of groups but not group itself
|
|
92
|
-
if (editor.isShapeOfType
|
|
92
|
+
if (editor.isShapeOfType(childShape, 'group')) {
|
|
93
93
|
collectSnappableShapesFromParent(childId)
|
|
94
94
|
continue
|
|
95
95
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtractShapeByProps } from '@tldraw/tlschema'
|
|
2
2
|
import { lerp } from '@tldraw/utils'
|
|
3
3
|
import { Geometry2d } from '../../primitives/geometry/Geometry2d'
|
|
4
4
|
import { Rectangle2d } from '../../primitives/geometry/Rectangle2d'
|
|
@@ -7,7 +7,7 @@ import { ShapeUtil, TLResizeInfo } from './ShapeUtil'
|
|
|
7
7
|
import { resizeBox } from './shared/resizeBox'
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
|
-
export type TLBaseBoxShape =
|
|
10
|
+
export type TLBaseBoxShape = ExtractShapeByProps<{ w: number; h: number }>
|
|
11
11
|
|
|
12
12
|
/** @public */
|
|
13
13
|
export abstract class BaseBoxShapeUtil<Shape extends TLBaseBoxShape> extends ShapeUtil<Shape> {
|
|
@@ -26,10 +26,7 @@ import { TLClickEventInfo } from '../types/event-types'
|
|
|
26
26
|
import { TLResizeHandle } from '../types/selection-types'
|
|
27
27
|
|
|
28
28
|
/** @public */
|
|
29
|
-
export interface TLShapeUtilConstructor<
|
|
30
|
-
T extends TLUnknownShape,
|
|
31
|
-
U extends ShapeUtil<T> = ShapeUtil<T>,
|
|
32
|
-
> {
|
|
29
|
+
export interface TLShapeUtilConstructor<T extends TLShape, U extends ShapeUtil<T> = ShapeUtil<T>> {
|
|
33
30
|
new (editor: Editor): U
|
|
34
31
|
type: T['type']
|
|
35
32
|
props?: RecordProps<T>
|
|
@@ -42,11 +39,11 @@ export interface TLShapeUtilConstructor<
|
|
|
42
39
|
*
|
|
43
40
|
* @public
|
|
44
41
|
*/
|
|
45
|
-
export interface TLShapeUtilCanBindOpts<Shape extends
|
|
42
|
+
export interface TLShapeUtilCanBindOpts<Shape extends TLShape = TLShape> {
|
|
46
43
|
/** The type of shape referenced by the `fromId` of the binding. */
|
|
47
|
-
fromShapeType:
|
|
44
|
+
fromShapeType: TLShape['type']
|
|
48
45
|
/** The type of shape referenced by the `toId` of the binding. */
|
|
49
|
-
toShapeType:
|
|
46
|
+
toShapeType: TLShape['type']
|
|
50
47
|
/** The type of binding. */
|
|
51
48
|
bindingType: string
|
|
52
49
|
}
|
|
@@ -79,7 +76,7 @@ export interface TLShapeUtilCanvasSvgDef {
|
|
|
79
76
|
}
|
|
80
77
|
|
|
81
78
|
/** @public */
|
|
82
|
-
export abstract class ShapeUtil<Shape extends
|
|
79
|
+
export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
83
80
|
/** Configure this shape utils {@link ShapeUtil.options | `options`}. */
|
|
84
81
|
static configure<T extends TLShapeUtilConstructor<any, any>>(
|
|
85
82
|
this: T,
|