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.
Files changed (202) hide show
  1. package/dist-cjs/index.d.ts +5 -14
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  5. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  7. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  9. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
  10. package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  12. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  13. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
  14. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  15. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  16. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  17. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  18. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  19. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  20. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  21. package/dist-cjs/lib/shapes/shared/crop.js +0 -1
  22. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  23. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  24. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  25. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  26. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  27. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  28. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +4 -1
  29. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  30. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  31. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  32. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
  33. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  34. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  35. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  36. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  37. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  38. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  39. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  40. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  42. package/dist-cjs/lib/ui/components/EditLinkDialog.js +1 -11
  43. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  44. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  46. package/dist-cjs/lib/ui/context/actions.js +2 -1
  47. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  48. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  49. package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
  50. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  51. package/dist-cjs/lib/ui/version.js +3 -3
  52. package/dist-cjs/lib/ui/version.js.map +1 -1
  53. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +0 -8
  54. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  55. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  56. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  57. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  58. package/dist-esm/index.d.mts +5 -14
  59. package/dist-esm/index.mjs +1 -1
  60. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  61. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  62. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  63. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  64. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  65. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  66. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
  67. package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
  68. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  69. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  70. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
  71. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  72. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  73. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  74. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  75. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  76. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  77. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  78. package/dist-esm/lib/shapes/shared/crop.mjs +0 -1
  79. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  80. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  81. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  82. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  83. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  84. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +4 -1
  85. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  86. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +4 -1
  87. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  88. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  89. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  90. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
  91. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  92. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  93. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  94. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  95. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +4 -1
  96. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  97. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  98. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  99. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  100. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  101. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +1 -11
  102. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  103. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  104. package/dist-esm/lib/ui/components/menu-items.mjs +4 -1
  105. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  106. package/dist-esm/lib/ui/context/actions.mjs +2 -1
  107. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  108. package/dist-esm/lib/ui/hooks/menu-hooks.mjs +4 -1
  109. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  110. package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
  111. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  112. package/dist-esm/lib/ui/version.mjs +3 -3
  113. package/dist-esm/lib/ui/version.mjs.map +1 -1
  114. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +0 -8
  115. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  116. package/dist-esm/lib/utils/export/exportAs.mjs +3 -1
  117. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  118. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  119. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  120. package/package.json +10 -10
  121. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
  122. package/src/lib/canvas/TldrawSelectionForeground.tsx +9 -4
  123. package/src/lib/defaultExternalContentHandlers.ts +4 -3
  124. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
  125. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +1 -1
  126. package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
  127. package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
  128. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
  129. package/src/lib/shapes/arrow/shared.ts +4 -4
  130. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
  131. package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
  132. package/src/lib/shapes/draw/toolStates/Drawing.ts +4 -4
  133. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  134. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  135. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +2 -10
  136. package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
  137. package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
  138. package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
  139. package/src/lib/shapes/line/toolStates/Pointing.ts +1 -1
  140. package/src/lib/shapes/note/NoteShapeTool.test.ts +1 -2
  141. package/src/lib/shapes/note/noteHelpers.ts +2 -2
  142. package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -2
  143. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -2
  144. package/src/lib/shapes/shared/crop.ts +0 -1
  145. package/src/lib/shapes/shared/useEditablePlainText.ts +3 -7
  146. package/src/lib/shapes/shared/useEditableRichText.ts +3 -7
  147. package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
  148. package/src/lib/shapes/text/toolStates/Pointing.ts +1 -1
  149. package/src/lib/tools/EraserTool/childStates/Erasing.ts +5 -3
  150. package/src/lib/tools/EraserTool/childStates/Pointing.ts +16 -3
  151. package/src/lib/tools/SelectTool/DragAndDropManager.ts +4 -2
  152. package/src/lib/tools/SelectTool/childStates/Brushing.ts +6 -2
  153. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +3 -2
  154. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +7 -4
  155. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +4 -2
  156. package/src/lib/tools/SelectTool/childStates/Idle.ts +10 -6
  157. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
  158. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +12 -4
  159. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
  160. package/src/lib/tools/SelectTool/childStates/Resizing.ts +4 -2
  161. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +4 -2
  162. package/src/lib/tools/SelectTool/childStates/Translating.ts +3 -1
  163. package/src/lib/ui/components/EditLinkDialog.tsx +6 -16
  164. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
  165. package/src/lib/ui/components/menu-items.tsx +14 -6
  166. package/src/lib/ui/context/actions.tsx +13 -9
  167. package/src/lib/ui/hooks/menu-hooks.ts +19 -9
  168. package/src/lib/ui/hooks/useFlatten.ts +2 -1
  169. package/src/lib/ui/hooks/useTools.tsx +2 -1
  170. package/src/lib/ui/version.ts +3 -3
  171. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +0 -8
  172. package/src/lib/utils/export/exportAs.ts +9 -2
  173. package/src/lib/utils/frames/frames.ts +1 -1
  174. package/src/lib/utils/tldr/buildFromV1Document.ts +17 -12
  175. package/src/test/Editor.test.tsx +12 -38
  176. package/src/test/SelectTool.test.ts +19 -11
  177. package/src/test/TestEditor.ts +4 -1
  178. package/src/test/TldrawEditor.test.tsx +16 -18
  179. package/src/test/bindings.test.tsx +25 -29
  180. package/src/test/bindingsIndex.test.tsx +4 -4
  181. package/src/test/commands/createShapes.test.ts +1 -15
  182. package/src/test/commands/getSvgString.test.ts +2 -2
  183. package/src/test/commands/putContent.test.ts +0 -1
  184. package/src/test/commands/updateShapes.test.ts +5 -21
  185. package/src/test/custom-clipping.test.ts +35 -36
  186. package/src/test/customSnapping.test.tsx +62 -77
  187. package/src/test/duplicate.test.ts +1 -1
  188. package/src/test/frames.test.ts +2 -2
  189. package/src/test/getCulledShapes.test.tsx +3 -11
  190. package/src/test/getShapeAtPoint.test.ts +2 -2
  191. package/src/test/groups.test.tsx +3 -6
  192. package/src/test/resizing.test.ts +13 -9
  193. package/src/test/selection-omnibus.test.ts +11 -11
  194. package/src/test/shapeutils.test.ts +1 -1
  195. package/src/test/styles2.test.tsx +1 -1
  196. package/src/test/styles3.test.ts +5 -5
  197. package/src/test/test-jsx.tsx +57 -69
  198. package/src/test/text.test.ts +17 -15
  199. package/src/test/translating.test.ts +8 -6
  200. package/src/test/commands/createShape.test.ts +0 -64
  201. package/src/test/commands/isShapeOfType.test.ts +0 -44
  202. package/src/test/commands/updateShape.test.ts +0 -67
@@ -5,7 +5,8 @@ import {
5
5
  TLBinding,
6
6
  TLBindingCreate,
7
7
  TLBindingId,
8
- TLShape,
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 TLShape['type']> = CommonShapeProps &
45
- FormatShapeProps<TLShape<Type>['props']>
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 BindingReactConnections {
54
+ interface CommonBindingProps {
53
55
  from?: string | TLShapeId
54
56
  to: string | TLShapeId
55
57
  }
56
58
 
57
- interface CommonBindingReactProps extends BindingReactConnections {
58
- ref?: string
59
- id?: TLBindingId
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
- [K in TLBinding['type']]: (props: ReactPropsForBinding<K>) => null
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 TLShape['type']]: (props: PropsForShape<K>) => null
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<BindingToCreate> = []
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 TLBinding['type']
164
- const { id, from, to, ref, ...props } = el.props
165
- const bindingRef: unknown = (el as any).ref || ref
166
- assert(
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 { id, parentId, ref, connections, ...binding } of bindingsToCreate) {
242
+ for (const binding of bindingsToCreate) {
262
243
  let fromId: TLShapeId, toId: TLShapeId
263
- if (connections.from) {
264
- assert(typeof connections.from === 'string', 'from must be a ref string or a shape id')
265
- if (isShapeId(connections.from)) {
266
- fromId = connections.from
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[connections.from], `Ref not found: ${connections.from}`)
269
- fromId = ids[connections.from]
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(connections.to, 'to must be specified')
278
- assert(typeof connections.to === 'string', 'to must be a ref string or a shape id')
279
- if (isShapeId(connections.to)) {
280
- toId = connections.to
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[connections.to], `Ref not found: ${connections.to}`)
283
- toId = ids[connections.to]
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
 
@@ -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([{ id, type: 'text', props: { richText: toRichText('Hello, world!') } }])
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((s) => editor.isShapeOfType(s, 'arrow') && s.id !== arrow1)! as TLArrowShape
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<TLNoteShape>(), props: { growY: 100 } })
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<TLNoteShape>(), props: { growY: 100 } })
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
- })