@tldraw/editor 4.3.0-canary.da35795ba8e2 → 4.3.0-canary.e1766dd4eab3
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 +111 -37
- package/dist-cjs/index.js +2 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +3 -3
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +47 -15
- 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/DashedOutlineBox.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.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/editor/types/emit-types.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +45 -9
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/globals/menus.js +1 -1
- package/dist-cjs/lib/globals/menus.js.map +2 -2
- package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
- package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
- package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
- package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
- package/dist-cjs/lib/options.js +3 -1
- package/dist-cjs/lib/options.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 +111 -37
- package/dist-esm/index.mjs +3 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +3 -3
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +47 -15
- 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/DashedOutlineBox.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.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/globals/environment.mjs +45 -9
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/globals/menus.mjs +1 -1
- package/dist-esm/lib/globals/menus.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
- package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
- package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
- package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +3 -1
- package/dist-esm/lib/options.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/editor.css +8 -4
- package/package.json +10 -10
- package/src/index.ts +1 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +4 -3
- package/src/lib/editor/Editor.test.ts +10 -10
- package/src/lib/editor/Editor.ts +159 -63
- 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/DashedOutlineBox.tsx +1 -1
- 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/editor/types/emit-types.ts +3 -1
- package/src/lib/exports/getSvgJsx.test.ts +10 -19
- package/src/lib/exports/getSvgJsx.tsx +2 -5
- package/src/lib/globals/environment.ts +65 -10
- package/src/lib/globals/menus.ts +1 -1
- package/src/lib/hooks/useCoarsePointer.ts +16 -59
- package/src/lib/hooks/useZoomCss.ts +3 -8
- package/src/lib/options.ts +13 -0
- 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) {
|
|
@@ -973,6 +969,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
973
969
|
this.disposables.clear()
|
|
974
970
|
this.store.dispose()
|
|
975
971
|
this.isDisposed = true
|
|
972
|
+
this.emit('dispose')
|
|
976
973
|
}
|
|
977
974
|
|
|
978
975
|
/* ------------------- Shape Utils ------------------ */
|
|
@@ -982,7 +979,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
982
979
|
*
|
|
983
980
|
* @public
|
|
984
981
|
*/
|
|
985
|
-
shapeUtils: { readonly [K in string]?: ShapeUtil<
|
|
982
|
+
shapeUtils: { readonly [K in string]?: ShapeUtil<TLShape> }
|
|
986
983
|
|
|
987
984
|
styleProps: { [key: string]: Map<StyleProp<any>, string> }
|
|
988
985
|
|
|
@@ -1001,8 +998,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1001
998
|
*
|
|
1002
999
|
* @public
|
|
1003
1000
|
*/
|
|
1004
|
-
getShapeUtil<
|
|
1005
|
-
getShapeUtil<S extends
|
|
1001
|
+
getShapeUtil<K extends TLShape['type']>(type: K): ShapeUtil<Extract<TLShape, { type: K }>>
|
|
1002
|
+
getShapeUtil<S extends TLShape>(shape: S | TLShapePartial<S> | S['type']): ShapeUtil<S>
|
|
1006
1003
|
getShapeUtil<T extends ShapeUtil>(type: T extends ShapeUtil<infer R> ? R['type'] : string): T
|
|
1007
1004
|
getShapeUtil(arg: string | { type: string }) {
|
|
1008
1005
|
const type = typeof arg === 'string' ? arg : arg.type
|
|
@@ -1016,8 +1013,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1016
1013
|
*
|
|
1017
1014
|
* @param shape - A shape, shape partial, or shape type.
|
|
1018
1015
|
*/
|
|
1019
|
-
hasShapeUtil
|
|
1020
|
-
hasShapeUtil
|
|
1016
|
+
hasShapeUtil(shape: TLShape | TLShapePartial<TLShape>): boolean
|
|
1017
|
+
hasShapeUtil(type: TLShape['type']): boolean
|
|
1021
1018
|
hasShapeUtil<T extends ShapeUtil>(
|
|
1022
1019
|
type: T extends ShapeUtil<infer R> ? R['type'] : string
|
|
1023
1020
|
): boolean
|
|
@@ -1032,7 +1029,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1032
1029
|
*
|
|
1033
1030
|
* @public
|
|
1034
1031
|
*/
|
|
1035
|
-
bindingUtils: { readonly [K in string]?: BindingUtil<
|
|
1032
|
+
bindingUtils: { readonly [K in string]?: BindingUtil<TLBinding> }
|
|
1036
1033
|
|
|
1037
1034
|
/**
|
|
1038
1035
|
* Get a binding util from a binding itself.
|
|
@@ -1049,8 +1046,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1049
1046
|
*
|
|
1050
1047
|
* @public
|
|
1051
1048
|
*/
|
|
1052
|
-
getBindingUtil<
|
|
1053
|
-
getBindingUtil<S extends
|
|
1049
|
+
getBindingUtil<K extends TLBinding['type']>(type: K): BindingUtil<Extract<TLBinding, { type: K }>>
|
|
1050
|
+
getBindingUtil<S extends TLBinding>(binding: S | { type: S['type'] }): BindingUtil<S>
|
|
1054
1051
|
getBindingUtil<T extends BindingUtil>(
|
|
1055
1052
|
type: T extends BindingUtil<infer R> ? R['type'] : string
|
|
1056
1053
|
): T
|
|
@@ -2220,7 +2217,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2220
2217
|
throw Error(`Editor.setFocusedGroup: Shape with id ${id} does not exist`)
|
|
2221
2218
|
}
|
|
2222
2219
|
|
|
2223
|
-
if (!this.isShapeOfType
|
|
2220
|
+
if (!this.isShapeOfType(shape, 'group')) {
|
|
2224
2221
|
throw Error(
|
|
2225
2222
|
`Editor.setFocusedGroup: Cannot set focused group to shape of type ${shape.type}`
|
|
2226
2223
|
)
|
|
@@ -2248,7 +2245,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2248
2245
|
if (focusedGroup) {
|
|
2249
2246
|
// If we have a focused layer, look for an ancestor of the focused shape that is a group
|
|
2250
2247
|
const match = this.findShapeAncestor(focusedGroup, (shape) =>
|
|
2251
|
-
this.isShapeOfType
|
|
2248
|
+
this.isShapeOfType(shape, 'group')
|
|
2252
2249
|
)
|
|
2253
2250
|
// If we have an ancestor that can become a focused layer, set it as the focused layer
|
|
2254
2251
|
this.setFocusedGroup(match?.id ?? null)
|
|
@@ -2673,6 +2670,52 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2673
2670
|
return this.getCamera().z
|
|
2674
2671
|
}
|
|
2675
2672
|
|
|
2673
|
+
private _debouncedZoomLevel = atom('debounced zoom level', 1)
|
|
2674
|
+
|
|
2675
|
+
/**
|
|
2676
|
+
* Get the debounced zoom level. When the camera is moving, this returns the zoom level
|
|
2677
|
+
* from when the camera started moving rather than the current zoom level. This can be
|
|
2678
|
+
* used to avoid expensive re-renders during camera movements.
|
|
2679
|
+
*
|
|
2680
|
+
* This behavior is controlled by the `useDebouncedZoom` option. When `useDebouncedZoom`
|
|
2681
|
+
* is `false`, this method always returns the current zoom level.
|
|
2682
|
+
*
|
|
2683
|
+
* @public
|
|
2684
|
+
*/
|
|
2685
|
+
@computed getDebouncedZoomLevel() {
|
|
2686
|
+
if (this.options.debouncedZoom) {
|
|
2687
|
+
if (this.getCameraState() === 'idle') {
|
|
2688
|
+
return this.getZoomLevel()
|
|
2689
|
+
} else {
|
|
2690
|
+
return this._debouncedZoomLevel.get()
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
return this.getZoomLevel()
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
@computed private _getAboveDebouncedZoomThreshold() {
|
|
2698
|
+
return this.getCurrentPageShapeIds().size > this.options.debouncedZoomThreshold
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
/**
|
|
2702
|
+
* Get the efficient zoom level. This returns the current zoom level if there are less than 300 shapes on the page,
|
|
2703
|
+
* otherwise it returns the debounced zoom level. This can be used to avoid expensive re-renders during camera movements.
|
|
2704
|
+
*
|
|
2705
|
+
* @public
|
|
2706
|
+
* @example
|
|
2707
|
+
* ```ts
|
|
2708
|
+
* editor.getEfficientZoomLevel()
|
|
2709
|
+
* ```
|
|
2710
|
+
*
|
|
2711
|
+
* @public
|
|
2712
|
+
*/
|
|
2713
|
+
@computed getEfficientZoomLevel() {
|
|
2714
|
+
return this._getAboveDebouncedZoomThreshold()
|
|
2715
|
+
? this.getDebouncedZoomLevel()
|
|
2716
|
+
: this.getZoomLevel()
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2676
2719
|
/**
|
|
2677
2720
|
* Get the camera's initial or reset zoom level.
|
|
2678
2721
|
*
|
|
@@ -3635,22 +3678,23 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3635
3678
|
if (_willSetInitialBounds) {
|
|
3636
3679
|
// If we have just received the initial bounds, don't center the camera.
|
|
3637
3680
|
this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets })
|
|
3681
|
+
this.emit('resize', screenBounds.toJson())
|
|
3638
3682
|
this.setCamera(this.getCamera())
|
|
3639
3683
|
} else {
|
|
3640
3684
|
if (center && !this.getInstanceState().followingUserId) {
|
|
3641
3685
|
// Get the page center before the change, make the change, and restore it
|
|
3642
3686
|
const before = this.getViewportPageBounds().center
|
|
3643
3687
|
this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets })
|
|
3688
|
+
this.emit('resize', screenBounds.toJson())
|
|
3644
3689
|
this.centerOnPoint(before)
|
|
3645
3690
|
} else {
|
|
3646
3691
|
// Otherwise,
|
|
3647
3692
|
this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets })
|
|
3693
|
+
this.emit('resize', screenBounds.toJson())
|
|
3648
3694
|
this._setCamera(Vec.From({ ...this.getCamera() }))
|
|
3649
3695
|
}
|
|
3650
3696
|
}
|
|
3651
3697
|
|
|
3652
|
-
this._tickCameraState()
|
|
3653
|
-
|
|
3654
3698
|
return this
|
|
3655
3699
|
}
|
|
3656
3700
|
|
|
@@ -4056,18 +4100,19 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4056
4100
|
// box just for rendering, and we only update after the camera stops moving.
|
|
4057
4101
|
private _cameraState = atom('camera state', 'idle' as 'idle' | 'moving')
|
|
4058
4102
|
private _cameraStateTimeoutRemaining = 0
|
|
4059
|
-
_decayCameraStateTimeout(elapsed: number) {
|
|
4103
|
+
private _decayCameraStateTimeout(elapsed: number) {
|
|
4060
4104
|
this._cameraStateTimeoutRemaining -= elapsed
|
|
4061
4105
|
if (this._cameraStateTimeoutRemaining > 0) return
|
|
4062
4106
|
this.off('tick', this._decayCameraStateTimeout)
|
|
4063
4107
|
this._cameraState.set('idle')
|
|
4064
4108
|
}
|
|
4065
|
-
_tickCameraState() {
|
|
4109
|
+
private _tickCameraState() {
|
|
4066
4110
|
// always reset the timeout
|
|
4067
4111
|
this._cameraStateTimeoutRemaining = this.options.cameraMovingTimeoutMs
|
|
4068
4112
|
// If the state is idle, then start the tick
|
|
4069
4113
|
if (this._cameraState.__unsafe__getWithoutCapture() !== 'idle') return
|
|
4070
4114
|
this._cameraState.set('moving')
|
|
4115
|
+
this._debouncedZoomLevel.set(unsafe__withoutCapture(() => this.getCamera().z))
|
|
4071
4116
|
this.on('tick', this._decayCameraStateTimeout)
|
|
4072
4117
|
}
|
|
4073
4118
|
|
|
@@ -5127,10 +5172,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5127
5172
|
|
|
5128
5173
|
// Check labels first
|
|
5129
5174
|
if (
|
|
5130
|
-
this.isShapeOfType
|
|
5131
|
-
((this.isShapeOfType
|
|
5132
|
-
this.isShapeOfType
|
|
5133
|
-
(this.isShapeOfType
|
|
5175
|
+
this.isShapeOfType(shape, 'frame') ||
|
|
5176
|
+
((this.isShapeOfType(shape, 'note') ||
|
|
5177
|
+
this.isShapeOfType(shape, 'arrow') ||
|
|
5178
|
+
(this.isShapeOfType(shape, 'geo') && shape.props.fill === 'none')) &&
|
|
5134
5179
|
this.getShapeUtil(shape).getText(shape)?.trim())
|
|
5135
5180
|
) {
|
|
5136
5181
|
for (const childGeometry of (geometry as Group2d).children) {
|
|
@@ -5140,7 +5185,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5140
5185
|
}
|
|
5141
5186
|
}
|
|
5142
5187
|
|
|
5143
|
-
if (this.isShapeOfType
|
|
5188
|
+
if (this.isShapeOfType(shape, 'frame')) {
|
|
5144
5189
|
// On the rare case that we've hit a frame (not its label), test again hitInside to be forced true;
|
|
5145
5190
|
// this prevents clicks from passing through the body of a frame to shapes behind it.
|
|
5146
5191
|
|
|
@@ -5421,7 +5466,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5421
5466
|
*
|
|
5422
5467
|
* @example
|
|
5423
5468
|
* ```ts
|
|
5424
|
-
* const isArrowShape = isShapeOfType
|
|
5469
|
+
* const isArrowShape = isShapeOfType(someShape, 'arrow')
|
|
5425
5470
|
* ```
|
|
5426
5471
|
*
|
|
5427
5472
|
* @param util - the TLShapeUtil constructor to test against
|
|
@@ -5429,15 +5474,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5429
5474
|
*
|
|
5430
5475
|
* @public
|
|
5431
5476
|
*/
|
|
5432
|
-
isShapeOfType<
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
arg: TLUnknownShape | TLUnknownShape['id'],
|
|
5477
|
+
isShapeOfType<K extends TLShape['type']>(
|
|
5478
|
+
shape: TLShape,
|
|
5479
|
+
type: K
|
|
5480
|
+
): shape is Extract<TLShape, { type: K }>
|
|
5481
|
+
isShapeOfType<T extends TLShape>(
|
|
5482
|
+
shape: TLShape,
|
|
5439
5483
|
type: T['type']
|
|
5440
|
-
) {
|
|
5484
|
+
): shape is Extract<TLShape, { type: T['type'] }>
|
|
5485
|
+
isShapeOfType<T extends TLShape = TLShape>(shapeId: TLShapeId, type: T['type']): boolean
|
|
5486
|
+
isShapeOfType(arg: TLShape | TLShapeId, type: TLShape['type']) {
|
|
5441
5487
|
const shape = typeof arg === 'string' ? this.getShape(arg) : arg
|
|
5442
5488
|
if (!shape) return false
|
|
5443
5489
|
return shape.type === type
|
|
@@ -5833,7 +5879,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5833
5879
|
|
|
5834
5880
|
while (node) {
|
|
5835
5881
|
if (
|
|
5836
|
-
this.isShapeOfType
|
|
5882
|
+
this.isShapeOfType(node, 'group') &&
|
|
5837
5883
|
focusedGroup?.id !== node.id &&
|
|
5838
5884
|
!this.hasAncestor(focusedGroup, node.id) &&
|
|
5839
5885
|
(filter?.(node) ?? true)
|
|
@@ -5875,7 +5921,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5875
5921
|
* Get all bindings of a certain type _from_ a particular shape. These are the bindings whose
|
|
5876
5922
|
* `fromId` matched the shape's ID.
|
|
5877
5923
|
*/
|
|
5878
|
-
getBindingsFromShape<
|
|
5924
|
+
getBindingsFromShape<K extends TLBinding['type']>(
|
|
5925
|
+
shape: TLShape | TLShapeId,
|
|
5926
|
+
type: K
|
|
5927
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5928
|
+
getBindingsFromShape<Binding extends TLBinding = TLBinding>(
|
|
5929
|
+
shape: TLShape | TLShapeId,
|
|
5930
|
+
type: Binding['type']
|
|
5931
|
+
): Binding[]
|
|
5932
|
+
getBindingsFromShape<Binding extends TLBinding = TLBinding>(
|
|
5879
5933
|
shape: TLShape | TLShapeId,
|
|
5880
5934
|
type: Binding['type']
|
|
5881
5935
|
): Binding[] {
|
|
@@ -5889,7 +5943,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5889
5943
|
* Get all bindings of a certain type _to_ a particular shape. These are the bindings whose
|
|
5890
5944
|
* `toId` matches the shape's ID.
|
|
5891
5945
|
*/
|
|
5892
|
-
getBindingsToShape<
|
|
5946
|
+
getBindingsToShape<K extends TLBinding['type']>(
|
|
5947
|
+
shape: TLShape | TLShapeId,
|
|
5948
|
+
type: K
|
|
5949
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5950
|
+
getBindingsToShape<Binding extends TLBinding = TLBinding>(
|
|
5951
|
+
shape: TLShape | TLShapeId,
|
|
5952
|
+
type: Binding['type']
|
|
5953
|
+
): Binding[]
|
|
5954
|
+
getBindingsToShape<Binding extends TLBinding = TLBinding>(
|
|
5893
5955
|
shape: TLShape | TLShapeId,
|
|
5894
5956
|
type: Binding['type']
|
|
5895
5957
|
): Binding[] {
|
|
@@ -5903,7 +5965,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5903
5965
|
* Get all bindings involving a particular shape. This includes bindings where the shape is the
|
|
5904
5966
|
* `fromId` or `toId`. If a type is provided, only bindings of that type are returned.
|
|
5905
5967
|
*/
|
|
5906
|
-
getBindingsInvolvingShape<
|
|
5968
|
+
getBindingsInvolvingShape<K extends TLBinding['type']>(
|
|
5969
|
+
shape: TLShape | TLShapeId,
|
|
5970
|
+
type: K
|
|
5971
|
+
): Extract<TLBinding, { type: K }>[]
|
|
5972
|
+
getBindingsInvolvingShape<Binding extends TLBinding = TLBinding>(
|
|
5973
|
+
shape: TLShape | TLShapeId,
|
|
5974
|
+
type?: Binding['type']
|
|
5975
|
+
): Binding[]
|
|
5976
|
+
getBindingsInvolvingShape<Binding extends TLBinding = TLBinding>(
|
|
5907
5977
|
shape: TLShape | TLShapeId,
|
|
5908
5978
|
type?: Binding['type']
|
|
5909
5979
|
): Binding[] {
|
|
@@ -5925,7 +5995,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5925
5995
|
if (!fromShape || !toShape) continue
|
|
5926
5996
|
if (!this.canBindShapes({ fromShape, toShape, binding: partial })) continue
|
|
5927
5997
|
|
|
5928
|
-
const util = this.getBindingUtil
|
|
5998
|
+
const util = this.getBindingUtil(partial.type)
|
|
5929
5999
|
const defaultProps = util.getDefaultProps()
|
|
5930
6000
|
const binding = this.store.schema.types.binding.create({
|
|
5931
6001
|
...partial,
|
|
@@ -6030,7 +6100,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6030
6100
|
const toShapeType = typeof toShape === 'string' ? toShape : toShape.type
|
|
6031
6101
|
const bindingType = typeof binding === 'string' ? binding : binding.type
|
|
6032
6102
|
|
|
6033
|
-
const canBindOpts = { fromShapeType, toShapeType, bindingType }
|
|
6103
|
+
const canBindOpts = { fromShapeType, toShapeType, bindingType } as const
|
|
6034
6104
|
|
|
6035
6105
|
if (fromShapeType === toShapeType) {
|
|
6036
6106
|
return this.getShapeUtil(fromShapeType).canBind(canBindOpts)
|
|
@@ -6571,7 +6641,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6571
6641
|
const shapesToFlipFirstPass = compact(ids.map((id) => this.getShape(id)))
|
|
6572
6642
|
|
|
6573
6643
|
for (const shape of shapesToFlipFirstPass) {
|
|
6574
|
-
if (this.isShapeOfType
|
|
6644
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
6575
6645
|
const childrenOfGroups = compact(
|
|
6576
6646
|
this.getSortedChildIdsForParent(shape.id).map((id) => this.getShape(id))
|
|
6577
6647
|
)
|
|
@@ -7692,9 +7762,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7692
7762
|
*
|
|
7693
7763
|
* @public
|
|
7694
7764
|
*/
|
|
7695
|
-
canCreateShape<
|
|
7696
|
-
shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']
|
|
7697
|
-
): boolean {
|
|
7765
|
+
canCreateShape(shape: OptionalKeys<TLShapePartial<TLShape>, 'id'> | TLShape['id']): boolean {
|
|
7698
7766
|
return this.canCreateShapes([shape])
|
|
7699
7767
|
}
|
|
7700
7768
|
|
|
@@ -7705,8 +7773,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7705
7773
|
*
|
|
7706
7774
|
* @public
|
|
7707
7775
|
*/
|
|
7708
|
-
canCreateShapes
|
|
7709
|
-
shapes: (
|
|
7776
|
+
canCreateShapes(
|
|
7777
|
+
shapes: (TLShape['id'] | OptionalKeys<TLShapePartial<TLShape>, 'id'>)[]
|
|
7710
7778
|
): boolean {
|
|
7711
7779
|
return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage
|
|
7712
7780
|
}
|
|
@@ -7724,7 +7792,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7724
7792
|
*
|
|
7725
7793
|
* @public
|
|
7726
7794
|
*/
|
|
7727
|
-
createShape<
|
|
7795
|
+
createShape<TShape extends TLShape>(shape: TLCreateShapePartial<TShape>): this {
|
|
7728
7796
|
this.createShapes([shape])
|
|
7729
7797
|
return this
|
|
7730
7798
|
}
|
|
@@ -7742,7 +7810,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7742
7810
|
*
|
|
7743
7811
|
* @public
|
|
7744
7812
|
*/
|
|
7745
|
-
createShapes<
|
|
7813
|
+
createShapes<TShape extends TLShape = TLShape>(shapes: TLCreateShapePartial<TShape>[]): this {
|
|
7746
7814
|
if (!Array.isArray(shapes)) {
|
|
7747
7815
|
throw Error('Editor.createShapes: must provide an array of shapes or shape partials')
|
|
7748
7816
|
}
|
|
@@ -8123,7 +8191,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8123
8191
|
const highestIndex = shapesWithRootParent[shapesWithRootParent.length - 1]?.index
|
|
8124
8192
|
|
|
8125
8193
|
this.run(() => {
|
|
8126
|
-
this.createShapes
|
|
8194
|
+
this.createShapes([
|
|
8127
8195
|
{
|
|
8128
8196
|
id: groupId,
|
|
8129
8197
|
type: 'group',
|
|
@@ -8193,7 +8261,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8193
8261
|
const groups: TLGroupShape[] = []
|
|
8194
8262
|
|
|
8195
8263
|
shapesToUngroup.forEach((shape) => {
|
|
8196
|
-
if (this.isShapeOfType
|
|
8264
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8197
8265
|
groups.push(shape)
|
|
8198
8266
|
} else {
|
|
8199
8267
|
idsToSelect.add(shape.id)
|
|
@@ -8239,7 +8307,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8239
8307
|
*
|
|
8240
8308
|
* @public
|
|
8241
8309
|
*/
|
|
8242
|
-
updateShape<T extends
|
|
8310
|
+
updateShape<T extends TLShape = TLShape>(partial: TLShapePartial<T> | null | undefined) {
|
|
8243
8311
|
this.updateShapes([partial])
|
|
8244
8312
|
return this
|
|
8245
8313
|
}
|
|
@@ -8256,7 +8324,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8256
8324
|
*
|
|
8257
8325
|
* @public
|
|
8258
8326
|
*/
|
|
8259
|
-
updateShapes<T extends
|
|
8327
|
+
updateShapes<T extends TLShape>(partials: (TLShapePartial<T> | null | undefined)[]) {
|
|
8260
8328
|
const compactedPartials: TLShapePartial<T>[] = Array(partials.length)
|
|
8261
8329
|
|
|
8262
8330
|
for (let i = 0, n = partials.length; i < n; i++) {
|
|
@@ -8408,7 +8476,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8408
8476
|
* @internal
|
|
8409
8477
|
*/
|
|
8410
8478
|
private _extractSharedStyles(shape: TLShape, sharedStyleMap: SharedStyleMap) {
|
|
8411
|
-
if (this.isShapeOfType
|
|
8479
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8412
8480
|
// For groups, ignore the styles of the group shape and instead include the styles of the
|
|
8413
8481
|
// group's children. These are the shapes that would have their styles changed if the
|
|
8414
8482
|
// user called `setStyle` on the current selection.
|
|
@@ -8528,7 +8596,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8528
8596
|
// For groups, ignore the opacity of the group shape and instead include
|
|
8529
8597
|
// the opacity of the group's children. These are the shapes that would have
|
|
8530
8598
|
// their opacity changed if the user called `setOpacity` on the current selection.
|
|
8531
|
-
if (this.isShapeOfType
|
|
8599
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8532
8600
|
for (const childId of this.getSortedChildIdsForParent(shape.id)) {
|
|
8533
8601
|
addShape(childId)
|
|
8534
8602
|
}
|
|
@@ -8589,7 +8657,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8589
8657
|
// We can have many deep levels of grouped shape
|
|
8590
8658
|
// Making a recursive function to look through all the levels
|
|
8591
8659
|
const addShapeById = (shape: TLShape) => {
|
|
8592
|
-
if (this.isShapeOfType
|
|
8660
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8593
8661
|
const childIds = this.getSortedChildIdsForParent(shape)
|
|
8594
8662
|
for (const childId of childIds) {
|
|
8595
8663
|
addShapeById(this.getShape(childId)!)
|
|
@@ -8673,7 +8741,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8673
8741
|
// We can have many deep levels of grouped shape
|
|
8674
8742
|
// Making a recursive function to look through all the levels
|
|
8675
8743
|
const addShapeById = (shape: TLShape) => {
|
|
8676
|
-
if (this.isShapeOfType
|
|
8744
|
+
if (this.isShapeOfType(shape, 'group')) {
|
|
8677
8745
|
const childIds = this.getSortedChildIdsForParent(shape.id)
|
|
8678
8746
|
for (const childId of childIds) {
|
|
8679
8747
|
addShapeById(this.getShape(childId)!)
|
|
@@ -9098,7 +9166,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9098
9166
|
for (const shape of this.getSelectedShapes()) {
|
|
9099
9167
|
if (lowestDepth === 0) break
|
|
9100
9168
|
|
|
9101
|
-
const isFrame = this.isShapeOfType
|
|
9169
|
+
const isFrame = this.isShapeOfType(shape, 'frame')
|
|
9102
9170
|
const ancestors = this.getShapeAncestors(shape)
|
|
9103
9171
|
if (isFrame) ancestors.push(shape)
|
|
9104
9172
|
|
|
@@ -9126,6 +9194,30 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9126
9194
|
}
|
|
9127
9195
|
}
|
|
9128
9196
|
|
|
9197
|
+
if (point) {
|
|
9198
|
+
const shapesById = new Map<TLShapeId, TLShape>(shapes.map((shape) => [shape.id, shape]))
|
|
9199
|
+
const rootShapesFromContent = compact(rootShapeIds.map((id) => shapesById.get(id)))
|
|
9200
|
+
if (rootShapesFromContent.length > 0) {
|
|
9201
|
+
const targetParent = this.getShapeAtPoint(point, {
|
|
9202
|
+
hitInside: true,
|
|
9203
|
+
hitFrameInside: true,
|
|
9204
|
+
hitLocked: true,
|
|
9205
|
+
filter: (shape) => {
|
|
9206
|
+
const util = this.getShapeUtil(shape)
|
|
9207
|
+
if (!util.canReceiveNewChildrenOfType) return false
|
|
9208
|
+
return rootShapesFromContent.every((rootShape) =>
|
|
9209
|
+
util.canReceiveNewChildrenOfType!(shape, rootShape.type)
|
|
9210
|
+
)
|
|
9211
|
+
},
|
|
9212
|
+
})
|
|
9213
|
+
|
|
9214
|
+
// When pasting at a specific point (e.g. paste-at-cursor) prefer the
|
|
9215
|
+
// parent under the pointer so that we don't keep using the original
|
|
9216
|
+
// selection's parent (which can keep shapes clipped inside frames).
|
|
9217
|
+
pasteParentId = targetParent ? targetParent.id : currentPageId
|
|
9218
|
+
}
|
|
9219
|
+
}
|
|
9220
|
+
|
|
9129
9221
|
let isDuplicating = false
|
|
9130
9222
|
|
|
9131
9223
|
if (!isPageId(pasteParentId)) {
|
|
@@ -9137,8 +9229,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9137
9229
|
if (rootShapeIds.length === 1) {
|
|
9138
9230
|
const rootShape = shapes.find((s) => s.id === rootShapeIds[0])!
|
|
9139
9231
|
if (
|
|
9140
|
-
this.isShapeOfType
|
|
9141
|
-
this.isShapeOfType
|
|
9232
|
+
this.isShapeOfType(parent, 'frame') &&
|
|
9233
|
+
this.isShapeOfType(rootShape, 'frame') &&
|
|
9142
9234
|
rootShape.props.w === parent?.props.w &&
|
|
9143
9235
|
rootShape.props.h === parent?.props.h
|
|
9144
9236
|
) {
|
|
@@ -9313,11 +9405,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9313
9405
|
const onlyRoot = rootShapes[0] as TLFrameShape
|
|
9314
9406
|
// If the old bounds are in the viewport...
|
|
9315
9407
|
// todo: replace frame references with shapes that can accept children
|
|
9316
|
-
if (this.isShapeOfType
|
|
9408
|
+
if (this.isShapeOfType(onlyRoot, 'frame')) {
|
|
9317
9409
|
while (
|
|
9318
9410
|
this.getShapesAtPoint(point).some(
|
|
9319
9411
|
(shape) =>
|
|
9320
|
-
this.isShapeOfType
|
|
9412
|
+
this.isShapeOfType(shape, 'frame') &&
|
|
9321
9413
|
shape.props.w === onlyRoot.props.w &&
|
|
9322
9414
|
shape.props.h === onlyRoot.props.h
|
|
9323
9415
|
)
|
|
@@ -10233,6 +10325,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10233
10325
|
}
|
|
10234
10326
|
|
|
10235
10327
|
this.root.handleEvent(info)
|
|
10328
|
+
this.emit('event', info)
|
|
10236
10329
|
return
|
|
10237
10330
|
}
|
|
10238
10331
|
|
|
@@ -10730,7 +10823,10 @@ function alertMaxShapes(editor: Editor, pageId = editor.getCurrentPageId()) {
|
|
|
10730
10823
|
|
|
10731
10824
|
function applyPartialToRecordWithProps<
|
|
10732
10825
|
T extends UnknownRecord & { type: string; props: object; meta: object },
|
|
10733
|
-
>(
|
|
10826
|
+
>(
|
|
10827
|
+
prev: T,
|
|
10828
|
+
partial?: T extends T ? Omit<Partial<T>, 'props'> & { props?: Partial<T['props']> } : never
|
|
10829
|
+
): T {
|
|
10734
10830
|
if (!partial) return prev
|
|
10735
10831
|
let next = null as null | T
|
|
10736
10832
|
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()
|