tldraw 4.3.0-canary.fd6b7f2a8adc → 4.3.0-next.2b3bfbba757b
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 +5 -14
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/crop.js +0 -1
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +4 -1
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/components/EditLinkDialog.js +1 -11
- package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +2 -1
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +0 -8
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
- package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
- package/dist-esm/index.d.mts +5 -14
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +0 -1
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +4 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +4 -1
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +4 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs +1 -11
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +4 -1
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +2 -1
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs +4 -1
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +0 -8
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +3 -1
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
- package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
- package/package.json +10 -10
- package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
- package/src/lib/canvas/TldrawSelectionForeground.tsx +9 -4
- package/src/lib/defaultExternalContentHandlers.ts +4 -3
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +1 -1
- package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
- package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
- package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
- package/src/lib/shapes/arrow/shared.ts +4 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
- package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
- package/src/lib/shapes/draw/toolStates/Drawing.ts +4 -4
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +2 -10
- package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
- package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
- package/src/lib/shapes/line/toolStates/Pointing.ts +1 -1
- package/src/lib/shapes/note/NoteShapeTool.test.ts +1 -2
- package/src/lib/shapes/note/noteHelpers.ts +2 -2
- package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -2
- package/src/lib/shapes/shared/RichTextLabel.tsx +1 -2
- package/src/lib/shapes/shared/crop.ts +0 -1
- package/src/lib/shapes/shared/useEditablePlainText.ts +3 -7
- package/src/lib/shapes/shared/useEditableRichText.ts +3 -7
- package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
- package/src/lib/shapes/text/toolStates/Pointing.ts +1 -1
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +5 -3
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +16 -3
- package/src/lib/tools/SelectTool/DragAndDropManager.ts +4 -2
- package/src/lib/tools/SelectTool/childStates/Brushing.ts +6 -2
- package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +3 -2
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +7 -4
- package/src/lib/tools/SelectTool/childStates/EditingShape.ts +4 -2
- package/src/lib/tools/SelectTool/childStates/Idle.ts +10 -6
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +12 -4
- package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +4 -2
- package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +4 -2
- package/src/lib/tools/SelectTool/childStates/Translating.ts +3 -1
- package/src/lib/ui/components/EditLinkDialog.tsx +6 -16
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
- package/src/lib/ui/components/menu-items.tsx +14 -6
- package/src/lib/ui/context/actions.tsx +13 -9
- package/src/lib/ui/hooks/menu-hooks.ts +19 -9
- package/src/lib/ui/hooks/useFlatten.ts +2 -1
- package/src/lib/ui/hooks/useTools.tsx +2 -1
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/utils/excalidraw/putExcalidrawContent.ts +0 -8
- package/src/lib/utils/export/exportAs.ts +9 -2
- package/src/lib/utils/frames/frames.ts +1 -1
- package/src/lib/utils/tldr/buildFromV1Document.ts +17 -12
- package/src/test/Editor.test.tsx +12 -38
- package/src/test/SelectTool.test.ts +19 -11
- package/src/test/TestEditor.ts +4 -1
- package/src/test/TldrawEditor.test.tsx +16 -18
- package/src/test/bindings.test.tsx +25 -29
- package/src/test/bindingsIndex.test.tsx +4 -4
- package/src/test/commands/createShapes.test.ts +1 -15
- package/src/test/commands/getSvgString.test.ts +2 -2
- package/src/test/commands/putContent.test.ts +0 -1
- package/src/test/commands/updateShapes.test.ts +5 -21
- package/src/test/custom-clipping.test.ts +35 -36
- package/src/test/customSnapping.test.tsx +62 -77
- package/src/test/duplicate.test.ts +1 -1
- package/src/test/frames.test.ts +2 -2
- package/src/test/getCulledShapes.test.tsx +3 -11
- package/src/test/getShapeAtPoint.test.ts +2 -2
- package/src/test/groups.test.tsx +3 -6
- package/src/test/resizing.test.ts +13 -9
- package/src/test/selection-omnibus.test.ts +11 -11
- package/src/test/shapeutils.test.ts +1 -1
- package/src/test/styles2.test.tsx +1 -1
- package/src/test/styles3.test.ts +5 -5
- package/src/test/test-jsx.tsx +57 -69
- package/src/test/text.test.ts +17 -15
- package/src/test/translating.test.ts +8 -6
- package/src/test/commands/createShape.test.ts +0 -64
- package/src/test/commands/isShapeOfType.test.ts +0 -44
- package/src/test/commands/updateShape.test.ts +0 -67
package/src/test/test-jsx.tsx
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
TLBinding,
|
|
6
6
|
TLBindingCreate,
|
|
7
7
|
TLBindingId,
|
|
8
|
-
|
|
8
|
+
TLDefaultBinding,
|
|
9
|
+
TLDefaultShape,
|
|
9
10
|
TLShapeId,
|
|
10
11
|
TLShapePartial,
|
|
11
12
|
ZERO_INDEX_KEY,
|
|
@@ -22,7 +23,6 @@ import React, { Fragment } from 'react'
|
|
|
22
23
|
const shapeTypeSymbol = Symbol('shapeJsx')
|
|
23
24
|
const assetTypeSymbol = Symbol('assetJsx')
|
|
24
25
|
const bindingTypeSymbol = Symbol('bindingJsx')
|
|
25
|
-
|
|
26
26
|
interface CommonShapeProps {
|
|
27
27
|
x?: number
|
|
28
28
|
y?: number
|
|
@@ -34,6 +34,7 @@ interface CommonShapeProps {
|
|
|
34
34
|
opacity?: number
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
type ShapeByType<Type extends TLDefaultShape['type']> = Extract<TLDefaultShape, { type: Type }>
|
|
37
38
|
type FormatShapeProps<Props extends object> = {
|
|
38
39
|
[K in keyof Props]?: Props[K] extends TLAssetId
|
|
39
40
|
? TLAssetId | React.JSX.Element
|
|
@@ -41,39 +42,24 @@ type FormatShapeProps<Props extends object> = {
|
|
|
41
42
|
? TLAssetId | React.JSX.Element | null
|
|
42
43
|
: Props[K]
|
|
43
44
|
}
|
|
44
|
-
type PropsForShape<Type extends
|
|
45
|
-
FormatShapeProps<
|
|
45
|
+
type PropsForShape<Type extends string> = Type extends TLDefaultShape['type']
|
|
46
|
+
? CommonShapeProps & FormatShapeProps<ShapeByType<Type>['props']>
|
|
47
|
+
: CommonShapeProps & Record<string, unknown>
|
|
46
48
|
|
|
47
49
|
type AssetByType<Type extends TLAsset['type']> = Extract<TLAsset, { type: Type }>
|
|
48
50
|
type PropsForAsset<Type extends string> = Type extends TLAsset['type']
|
|
49
51
|
? Partial<AssetByType<Type>['props']>
|
|
50
52
|
: Record<string, unknown>
|
|
51
53
|
|
|
52
|
-
interface
|
|
54
|
+
interface CommonBindingProps {
|
|
53
55
|
from?: string | TLShapeId
|
|
54
56
|
to: string | TLShapeId
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
type ReactPropsForBinding<Type extends TLBinding['type']> = CommonBindingReactProps &
|
|
63
|
-
Partial<TLBinding<Type>['props']>
|
|
64
|
-
|
|
65
|
-
type BindingToCreate = TLBinding extends infer E
|
|
66
|
-
? E extends TLBinding
|
|
67
|
-
? {
|
|
68
|
-
type: E['type']
|
|
69
|
-
props: Partial<TLBinding<E['type']>['props']>
|
|
70
|
-
id: TLBindingId | undefined
|
|
71
|
-
parentId: TLShapeId | undefined
|
|
72
|
-
ref: string | undefined
|
|
73
|
-
connections: BindingReactConnections
|
|
74
|
-
}
|
|
75
|
-
: never
|
|
76
|
-
: never
|
|
59
|
+
type BindingByType<Type extends TLBinding['type']> = Extract<TLBinding, { type: Type }>
|
|
60
|
+
type PropsForBinding<Type extends string> = Type extends TLBinding['type']
|
|
61
|
+
? CommonBindingProps & Partial<BindingByType<Type>['props']>
|
|
62
|
+
: CommonBindingProps & Record<string, unknown>
|
|
77
63
|
|
|
78
64
|
const createElement = (
|
|
79
65
|
type: typeof shapeTypeSymbol | typeof assetTypeSymbol | typeof bindingTypeSymbol,
|
|
@@ -104,9 +90,10 @@ const tlBinding = new Proxy(
|
|
|
104
90
|
return createElement(bindingTypeSymbol, key as string)
|
|
105
91
|
},
|
|
106
92
|
}
|
|
107
|
-
) as {
|
|
108
|
-
|
|
109
|
-
|
|
93
|
+
) as { [K in TLDefaultBinding['type']]: (props: PropsForBinding<K>) => null } & Record<
|
|
94
|
+
string,
|
|
95
|
+
(props: PropsForBinding<string>) => null
|
|
96
|
+
>
|
|
110
97
|
|
|
111
98
|
/**
|
|
112
99
|
* TL - jsx helpers for creating tldraw shapes in test cases
|
|
@@ -125,8 +112,8 @@ export const TL = new Proxy(
|
|
|
125
112
|
},
|
|
126
113
|
}
|
|
127
114
|
) as { asset: typeof tlAsset; binding: typeof tlBinding } & {
|
|
128
|
-
[K in
|
|
129
|
-
}
|
|
115
|
+
[K in TLDefaultShape['type']]: (props: PropsForShape<K>) => null
|
|
116
|
+
} & Record<string, (props: PropsForShape<string>) => null>
|
|
130
117
|
|
|
131
118
|
export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Element>, idPrefix = '') {
|
|
132
119
|
const ids = { bindings: {} } as Record<string, TLShapeId> & {
|
|
@@ -135,7 +122,12 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
135
122
|
const currentPageShapes: Array<TLShapePartial> = []
|
|
136
123
|
const assets: Array<TLAsset> = []
|
|
137
124
|
|
|
138
|
-
const bindingsToCreate: Array<
|
|
125
|
+
const bindingsToCreate: Array<{
|
|
126
|
+
type: string
|
|
127
|
+
props: Record<string, unknown>
|
|
128
|
+
parentId: TLShapeId | undefined
|
|
129
|
+
ref: string | undefined
|
|
130
|
+
}> = []
|
|
139
131
|
|
|
140
132
|
function addChildren(
|
|
141
133
|
children: React.JSX.Element | Array<React.JSX.Element>,
|
|
@@ -160,21 +152,10 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
160
152
|
}
|
|
161
153
|
|
|
162
154
|
if (el.type[bindingTypeSymbol]) {
|
|
163
|
-
const bindingType = (el.type as any)[bindingTypeSymbol] as
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
bindingRef === undefined || typeof bindingRef === 'string',
|
|
168
|
-
'ref must be string or undefined'
|
|
169
|
-
)
|
|
170
|
-
bindingsToCreate.push({
|
|
171
|
-
type: bindingType,
|
|
172
|
-
props,
|
|
173
|
-
id,
|
|
174
|
-
parentId,
|
|
175
|
-
ref: bindingRef,
|
|
176
|
-
connections: { from, to },
|
|
177
|
-
})
|
|
155
|
+
const bindingType = (el.type as any)[bindingTypeSymbol] as string
|
|
156
|
+
const ref = ((el as any).ref || el.props.ref) as string | undefined
|
|
157
|
+
assert(ref === undefined || typeof ref === 'string', 'ref must be string or undefined')
|
|
158
|
+
bindingsToCreate.push({ type: bindingType, props: el.props, parentId, ref })
|
|
178
159
|
} else {
|
|
179
160
|
const shapeType = (el.type as any)[shapeTypeSymbol] as string
|
|
180
161
|
if (!shapeType) {
|
|
@@ -258,48 +239,55 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
258
239
|
addChildren(shapes)
|
|
259
240
|
|
|
260
241
|
const bindings: TLBindingCreate[] = []
|
|
261
|
-
for (const
|
|
242
|
+
for (const binding of bindingsToCreate) {
|
|
262
243
|
let fromId: TLShapeId, toId: TLShapeId
|
|
263
|
-
if (
|
|
264
|
-
assert(typeof
|
|
265
|
-
if (isShapeId(
|
|
266
|
-
fromId =
|
|
244
|
+
if (binding.props.from) {
|
|
245
|
+
assert(typeof binding.props.from === 'string', 'from must be a ref string or a shape id')
|
|
246
|
+
if (isShapeId(binding.props.from)) {
|
|
247
|
+
fromId = binding.props.from
|
|
267
248
|
} else {
|
|
268
|
-
assert(ids[
|
|
269
|
-
fromId = ids[
|
|
249
|
+
assert(ids[binding.props.from], `Ref not found: ${binding.props.from}`)
|
|
250
|
+
fromId = ids[binding.props.from]
|
|
270
251
|
}
|
|
271
|
-
} else if (parentId) {
|
|
272
|
-
fromId = parentId
|
|
252
|
+
} else if (binding.parentId) {
|
|
253
|
+
fromId = binding.parentId
|
|
273
254
|
} else {
|
|
274
255
|
throw new Error('from must be specified, or binding must be a child of a shape')
|
|
275
256
|
}
|
|
276
257
|
|
|
277
|
-
assert(
|
|
278
|
-
assert(typeof
|
|
279
|
-
if (isShapeId(
|
|
280
|
-
toId =
|
|
258
|
+
assert(binding.props.to, 'to must be specified')
|
|
259
|
+
assert(typeof binding.props.to === 'string', 'to must be a ref string or a shape id')
|
|
260
|
+
if (isShapeId(binding.props.to)) {
|
|
261
|
+
toId = binding.props.to
|
|
281
262
|
} else {
|
|
282
|
-
assert(ids[
|
|
283
|
-
toId = ids[
|
|
263
|
+
assert(ids[binding.props.to], `Ref not found: ${binding.props.to}`)
|
|
264
|
+
toId = ids[binding.props.to]
|
|
284
265
|
}
|
|
285
266
|
|
|
286
|
-
let bindingId = id
|
|
287
|
-
if (ref) {
|
|
288
|
-
assert(typeof ref === 'string', 'binding ref must be string')
|
|
289
|
-
assert(!ids.bindings[ref], `Duplicate ref: ${ref}`)
|
|
290
|
-
assert(!bindingId, `Cannot use both ref and id on binding: ${ref}`)
|
|
291
|
-
bindingId = createBindingId(`${idPrefix}${ref}`)
|
|
292
|
-
ids.bindings[ref] = bindingId
|
|
267
|
+
let bindingId: TLBindingId = binding.props.id as TLBindingId
|
|
268
|
+
if (binding.ref) {
|
|
269
|
+
assert(typeof binding.ref === 'string', 'binding ref must be string')
|
|
270
|
+
assert(!ids.bindings[binding.ref], `Duplicate ref: ${binding.ref}`)
|
|
271
|
+
assert(!bindingId, `Cannot use both ref and id on binding: ${binding.ref}`)
|
|
272
|
+
bindingId = createBindingId(`${idPrefix}${binding.ref}`)
|
|
273
|
+
ids.bindings[binding.ref] = bindingId
|
|
293
274
|
}
|
|
294
275
|
if (!bindingId) {
|
|
295
276
|
bindingId = createBindingId()
|
|
296
277
|
}
|
|
297
278
|
|
|
279
|
+
const props = { ...binding.props }
|
|
280
|
+
delete props.ref
|
|
281
|
+
delete props.id
|
|
282
|
+
delete props.from
|
|
283
|
+
delete props.to
|
|
284
|
+
|
|
298
285
|
bindings.push({
|
|
299
|
-
...binding,
|
|
300
286
|
id: bindingId,
|
|
287
|
+
type: binding.type,
|
|
301
288
|
fromId,
|
|
302
289
|
toId,
|
|
290
|
+
props,
|
|
303
291
|
})
|
|
304
292
|
}
|
|
305
293
|
|
package/src/test/text.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createShapeId, toRichText } from '@tldraw/editor'
|
|
1
|
+
import { TLTextShape, createShapeId, toRichText } from '@tldraw/editor'
|
|
2
2
|
import { TestEditor } from './TestEditor'
|
|
3
3
|
|
|
4
4
|
let editor: TestEditor
|
|
@@ -13,7 +13,7 @@ afterEach(() => {
|
|
|
13
13
|
describe('When editing text', () => {
|
|
14
14
|
it('preserves the top center when center aligned', () => {
|
|
15
15
|
const id = createShapeId()
|
|
16
|
-
editor.createShapes([
|
|
16
|
+
editor.createShapes<TLTextShape>([
|
|
17
17
|
{
|
|
18
18
|
id,
|
|
19
19
|
type: 'text',
|
|
@@ -27,7 +27,7 @@ describe('When editing text', () => {
|
|
|
27
27
|
},
|
|
28
28
|
])
|
|
29
29
|
const boundsA = editor.getShapePageBounds(id)
|
|
30
|
-
editor.updateShapes([
|
|
30
|
+
editor.updateShapes<TLTextShape>([
|
|
31
31
|
{
|
|
32
32
|
id,
|
|
33
33
|
type: 'text',
|
|
@@ -47,7 +47,7 @@ describe('When editing text', () => {
|
|
|
47
47
|
|
|
48
48
|
it('preserved the right center when center aligned and rotated 90deg', () => {
|
|
49
49
|
const id = createShapeId()
|
|
50
|
-
editor.createShapes([
|
|
50
|
+
editor.createShapes<TLTextShape>([
|
|
51
51
|
{
|
|
52
52
|
id,
|
|
53
53
|
type: 'text',
|
|
@@ -63,7 +63,9 @@ describe('When editing text', () => {
|
|
|
63
63
|
])
|
|
64
64
|
|
|
65
65
|
const boundsA = editor.getShapePageBounds(id)!
|
|
66
|
-
editor.updateShapes([
|
|
66
|
+
editor.updateShapes<TLTextShape>([
|
|
67
|
+
{ id, type: 'text', props: { richText: toRichText('Hello, world!') } },
|
|
68
|
+
])
|
|
67
69
|
const boundsB = editor.getShapePageBounds(id)!
|
|
68
70
|
expect(boundsA.x).toBeCloseTo(boundsB.x)
|
|
69
71
|
expect(boundsA.y).not.toBeCloseTo(boundsB.y)
|
|
@@ -73,7 +75,7 @@ describe('When editing text', () => {
|
|
|
73
75
|
|
|
74
76
|
it('preserves the top left corner when start aligned', () => {
|
|
75
77
|
const id = createShapeId()
|
|
76
|
-
editor.createShapes([
|
|
78
|
+
editor.createShapes<TLTextShape>([
|
|
77
79
|
{
|
|
78
80
|
id,
|
|
79
81
|
type: 'text',
|
|
@@ -87,7 +89,7 @@ describe('When editing text', () => {
|
|
|
87
89
|
},
|
|
88
90
|
])
|
|
89
91
|
const boundsA = editor.getShapePageBounds(id)
|
|
90
|
-
editor.updateShapes([
|
|
92
|
+
editor.updateShapes<TLTextShape>([
|
|
91
93
|
{
|
|
92
94
|
id,
|
|
93
95
|
type: 'text',
|
|
@@ -107,7 +109,7 @@ describe('When editing text', () => {
|
|
|
107
109
|
|
|
108
110
|
it('preserves the top right edge when end aligned', () => {
|
|
109
111
|
const id = createShapeId()
|
|
110
|
-
editor.createShapes([
|
|
112
|
+
editor.createShapes<TLTextShape>([
|
|
111
113
|
{
|
|
112
114
|
id,
|
|
113
115
|
type: 'text',
|
|
@@ -121,7 +123,7 @@ describe('When editing text', () => {
|
|
|
121
123
|
},
|
|
122
124
|
])
|
|
123
125
|
const boundsA = editor.getShapePageBounds(id)
|
|
124
|
-
editor.updateShapes([
|
|
126
|
+
editor.updateShapes<TLTextShape>([
|
|
125
127
|
{
|
|
126
128
|
id,
|
|
127
129
|
type: 'text',
|
|
@@ -143,7 +145,7 @@ describe('When editing text', () => {
|
|
|
143
145
|
describe('When changing text size', () => {
|
|
144
146
|
it('preserves the center when center aligned', () => {
|
|
145
147
|
const id = createShapeId()
|
|
146
|
-
editor.createShapes([
|
|
148
|
+
editor.createShapes<TLTextShape>([
|
|
147
149
|
{
|
|
148
150
|
id,
|
|
149
151
|
type: 'text',
|
|
@@ -158,7 +160,7 @@ describe('When changing text size', () => {
|
|
|
158
160
|
},
|
|
159
161
|
])
|
|
160
162
|
const boundsA = editor.getShapePageBounds(id)
|
|
161
|
-
editor.updateShapes([
|
|
163
|
+
editor.updateShapes<TLTextShape>([
|
|
162
164
|
{
|
|
163
165
|
id,
|
|
164
166
|
type: 'text',
|
|
@@ -178,7 +180,7 @@ describe('When changing text size', () => {
|
|
|
178
180
|
|
|
179
181
|
it('preserves the center left point when start aligned', () => {
|
|
180
182
|
const id = createShapeId()
|
|
181
|
-
editor.createShapes([
|
|
183
|
+
editor.createShapes<TLTextShape>([
|
|
182
184
|
{
|
|
183
185
|
id,
|
|
184
186
|
type: 'text',
|
|
@@ -193,7 +195,7 @@ describe('When changing text size', () => {
|
|
|
193
195
|
},
|
|
194
196
|
])
|
|
195
197
|
const boundsA = editor.getShapePageBounds(id)
|
|
196
|
-
editor.updateShapes([
|
|
198
|
+
editor.updateShapes<TLTextShape>([
|
|
197
199
|
{
|
|
198
200
|
id,
|
|
199
201
|
type: 'text',
|
|
@@ -213,7 +215,7 @@ describe('When changing text size', () => {
|
|
|
213
215
|
|
|
214
216
|
it('preserves the top right edge when end aligned', () => {
|
|
215
217
|
const id = createShapeId()
|
|
216
|
-
editor.createShapes([
|
|
218
|
+
editor.createShapes<TLTextShape>([
|
|
217
219
|
{
|
|
218
220
|
id,
|
|
219
221
|
type: 'text',
|
|
@@ -228,7 +230,7 @@ describe('When changing text size', () => {
|
|
|
228
230
|
},
|
|
229
231
|
])
|
|
230
232
|
const boundsA = editor.getShapePageBounds(id)
|
|
231
|
-
editor.updateShapes([
|
|
233
|
+
editor.updateShapes<TLTextShape>([
|
|
232
234
|
{
|
|
233
235
|
id,
|
|
234
236
|
type: 'text',
|
|
@@ -1749,7 +1749,9 @@ describe('translating a shape with a bound shape', () => {
|
|
|
1749
1749
|
|
|
1750
1750
|
const newArrow = editor
|
|
1751
1751
|
.getCurrentPageShapes()
|
|
1752
|
-
.find(
|
|
1752
|
+
.find(
|
|
1753
|
+
(s) => editor.isShapeOfType<TLArrowShape>(s, 'arrow') && s.id !== arrow1
|
|
1754
|
+
)! as TLArrowShape
|
|
1753
1755
|
expect(getArrowBindings(editor, newArrow)).toMatchObject({
|
|
1754
1756
|
start: { type: 'arrow' },
|
|
1755
1757
|
end: undefined,
|
|
@@ -2059,7 +2061,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2059
2061
|
editor
|
|
2060
2062
|
.createShape({ type: 'note' })
|
|
2061
2063
|
.createShape({ type: 'note', x: 500, y: 500 })
|
|
2062
|
-
.updateShape({ ...editor.getLastCreatedShape
|
|
2064
|
+
.updateShape({ ...editor.getLastCreatedShape(), props: { growY: 100 } })
|
|
2063
2065
|
.pointerMove(600, 600)
|
|
2064
2066
|
// start translating
|
|
2065
2067
|
.pointerDown()
|
|
@@ -2078,7 +2080,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2078
2080
|
it('Snaps correctly to the bottom when the not-translating shape has growY', () => {
|
|
2079
2081
|
editor
|
|
2080
2082
|
.createShape({ type: 'note' })
|
|
2081
|
-
.updateShape({ ...editor.getLastCreatedShape
|
|
2083
|
+
.updateShape({ ...editor.getLastCreatedShape(), props: { growY: 100 } })
|
|
2082
2084
|
.createShape({ type: 'note', x: 500, y: 500 })
|
|
2083
2085
|
.pointerMove(600, 600)
|
|
2084
2086
|
// start translating
|
|
@@ -2181,7 +2183,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2181
2183
|
|
|
2182
2184
|
describe('cancelling a translate operation', () => {
|
|
2183
2185
|
it('undoes any changes since the start of the translate operation', () => {
|
|
2184
|
-
editor.createShape({
|
|
2186
|
+
editor.createShape<TLGeoShape>({
|
|
2185
2187
|
type: 'geo',
|
|
2186
2188
|
x: 0,
|
|
2187
2189
|
y: 0,
|
|
@@ -2218,7 +2220,7 @@ describe('cancelling a translate operation', () => {
|
|
|
2218
2220
|
const shapeId = createShapeId()
|
|
2219
2221
|
|
|
2220
2222
|
editor
|
|
2221
|
-
.createShape({
|
|
2223
|
+
.createShape<TLGeoShape>({
|
|
2222
2224
|
id: shapeId,
|
|
2223
2225
|
type: 'geo',
|
|
2224
2226
|
x: 0,
|
|
@@ -2266,7 +2268,7 @@ describe('cancelling a translate operation', () => {
|
|
|
2266
2268
|
const shapeId = createShapeId()
|
|
2267
2269
|
|
|
2268
2270
|
editor
|
|
2269
|
-
.createShape({
|
|
2271
|
+
.createShape<TLGeoShape>({
|
|
2270
2272
|
id: shapeId,
|
|
2271
2273
|
type: 'geo',
|
|
2272
2274
|
x: 0,
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { TLArrowShape, TLGeoShape, createShapeId } from '@tldraw/editor'
|
|
2
|
-
import { TestEditor } from '../TestEditor'
|
|
3
|
-
|
|
4
|
-
let editor: TestEditor
|
|
5
|
-
|
|
6
|
-
const ids = {
|
|
7
|
-
box1: createShapeId('box1'),
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
editor = new TestEditor()
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('Uses typescript generics', () => {
|
|
15
|
-
expect(() => {
|
|
16
|
-
editor.createShape(
|
|
17
|
-
//@ts-expect-error Yep error because we are giving the wrong props to the shape
|
|
18
|
-
{
|
|
19
|
-
id: ids.box1,
|
|
20
|
-
type: 'geo',
|
|
21
|
-
props: { w: 'OH NO' },
|
|
22
|
-
}
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
// Errors when creating a shape with unknown props
|
|
26
|
-
editor.createShape({
|
|
27
|
-
id: ids.box1,
|
|
28
|
-
type: 'geo',
|
|
29
|
-
props: {
|
|
30
|
-
// @ts-expect-error
|
|
31
|
-
foo: 'bar',
|
|
32
|
-
},
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
// Yep error here because we are giving the wrong props to the shape
|
|
36
|
-
editor.createShape<TLGeoShape>({
|
|
37
|
-
id: ids.box1,
|
|
38
|
-
type: 'geo',
|
|
39
|
-
//@ts-expect-error
|
|
40
|
-
props: { w: 'OH NO' },
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// Yep error here because we are giving the wrong generic
|
|
44
|
-
editor.createShape<TLArrowShape>({
|
|
45
|
-
id: ids.box1,
|
|
46
|
-
//@ts-expect-error
|
|
47
|
-
type: 'geo',
|
|
48
|
-
//@ts-expect-error
|
|
49
|
-
props: { w: 'OH NO' },
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
// All good, correct match of generic and shape type
|
|
53
|
-
editor.createShape<TLGeoShape>({
|
|
54
|
-
id: ids.box1,
|
|
55
|
-
type: 'geo',
|
|
56
|
-
props: { w: 100 },
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
editor.createShape<TLGeoShape>({
|
|
60
|
-
id: ids.box1,
|
|
61
|
-
type: 'geo',
|
|
62
|
-
})
|
|
63
|
-
}).toThrow()
|
|
64
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { TLArrowShape, createShapeId } from '@tldraw/editor'
|
|
2
|
-
import { TestEditor } from '../TestEditor'
|
|
3
|
-
|
|
4
|
-
let editor: TestEditor
|
|
5
|
-
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
editor = new TestEditor()
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
export declare function assertNever(x: never): never
|
|
11
|
-
|
|
12
|
-
it('narrows down the shape type', () => {
|
|
13
|
-
const id = createShapeId('arrow1')
|
|
14
|
-
editor.createShape({ type: 'arrow', id, x: 0, y: 0 })
|
|
15
|
-
|
|
16
|
-
const shape = editor.getShape(id)!
|
|
17
|
-
if (editor.isShapeOfType(shape, 'arrow')) {
|
|
18
|
-
expect(shape.type === 'arrow').toBe(true)
|
|
19
|
-
expect(
|
|
20
|
-
// @ts-expect-error This comparison appears to be unintentional because the types '"arrow"' and '"card"' have no overlap.
|
|
21
|
-
shape.type === 'card'
|
|
22
|
-
).toBe(false)
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('narrows down the shape type with generic', () => {
|
|
27
|
-
const id = createShapeId('arrow1')
|
|
28
|
-
editor.createShape({ type: 'arrow', id, x: 0, y: 0 })
|
|
29
|
-
|
|
30
|
-
const shape = editor.getShape(id)!
|
|
31
|
-
if (editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) {
|
|
32
|
-
expect(shape.type === 'arrow').toBe(true)
|
|
33
|
-
|
|
34
|
-
expect(
|
|
35
|
-
// @ts-expect-error This comparison appears to be unintentional because the types '"arrow"' and '"card"' have no overlap.
|
|
36
|
-
shape.type === 'card'
|
|
37
|
-
).toBe(false)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// @ts-expect-error mismatch between the generic and the shape type
|
|
41
|
-
if (editor.isShapeOfType<TLArrowShape>(shape, 'card')) {
|
|
42
|
-
assertNever(shape)
|
|
43
|
-
}
|
|
44
|
-
})
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { TLArrowShape, TLGeoShape, createShapeId } from '@tldraw/editor'
|
|
2
|
-
import { TestEditor, createDefaultShapes } from '../TestEditor'
|
|
3
|
-
|
|
4
|
-
let editor: TestEditor
|
|
5
|
-
|
|
6
|
-
const ids = {
|
|
7
|
-
box1: createShapeId('box1'),
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
editor = new TestEditor()
|
|
12
|
-
editor.createShapes(createDefaultShapes())
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('Uses typescript generics', () => {
|
|
16
|
-
expect(() => {
|
|
17
|
-
editor.updateShape({
|
|
18
|
-
id: ids.box1,
|
|
19
|
-
type: 'geo',
|
|
20
|
-
props: {
|
|
21
|
-
// @ts-expect-error
|
|
22
|
-
w: 'OH NO',
|
|
23
|
-
},
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
// Errors when updating a shape with unknown props
|
|
27
|
-
editor.updateShape({
|
|
28
|
-
id: ids.box1,
|
|
29
|
-
type: 'geo',
|
|
30
|
-
props: {
|
|
31
|
-
// @ts-expect-error
|
|
32
|
-
foo: 'bar',
|
|
33
|
-
},
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// error here because we are giving the wrong props to the shape
|
|
37
|
-
editor.updateShape<TLGeoShape>({
|
|
38
|
-
id: ids.box1,
|
|
39
|
-
type: 'geo',
|
|
40
|
-
props: {
|
|
41
|
-
// @ts-expect-error
|
|
42
|
-
w: 'OH NO',
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// Yep error here because we are giving the wrong generic
|
|
47
|
-
editor.updateShape<TLArrowShape>({
|
|
48
|
-
id: ids.box1,
|
|
49
|
-
//@ts-expect-error
|
|
50
|
-
type: 'geo',
|
|
51
|
-
//@ts-expect-error
|
|
52
|
-
props: { w: 'OH NO' },
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
// All good, correct match of generic and shape type
|
|
56
|
-
editor.updateShape<TLGeoShape>({
|
|
57
|
-
id: ids.box1,
|
|
58
|
-
type: 'geo',
|
|
59
|
-
props: { w: 100 },
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
editor.updateShape<TLGeoShape>({
|
|
63
|
-
id: ids.box1,
|
|
64
|
-
type: 'geo',
|
|
65
|
-
})
|
|
66
|
-
}).toThrow()
|
|
67
|
-
})
|