@tldraw/editor 3.16.0-canary.ffdf566dd0a8 → 3.16.0-internal.71f83a8a571b

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 (218) hide show
  1. package/dist-cjs/index.d.ts +137 -126
  2. package/dist-cjs/index.js +6 -6
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +8 -8
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/Shape.js +7 -10
  9. package/dist-cjs/lib/components/Shape.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +14 -23
  11. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
  14. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  17. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  18. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  19. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  20. package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
  21. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  22. package/dist-cjs/lib/editor/Editor.js +67 -128
  23. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  24. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +4 -0
  25. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
  26. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  27. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -1
  28. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  29. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  30. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +23 -0
  31. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  32. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  33. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  34. package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
  35. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  36. package/dist-cjs/lib/hooks/useCanvasEvents.js +44 -35
  37. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  38. package/dist-cjs/lib/hooks/useDocumentEvents.js +5 -5
  39. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  40. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -2
  41. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  42. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  43. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  44. package/dist-cjs/lib/hooks/useHandleEvents.js +3 -3
  45. package/dist-cjs/lib/hooks/useHandleEvents.js.map +2 -2
  46. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
  47. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  48. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  49. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  50. package/dist-cjs/lib/hooks/useSelectionEvents.js +4 -4
  51. package/dist-cjs/lib/hooks/useSelectionEvents.js.map +2 -2
  52. package/dist-cjs/lib/license/LicenseManager.js +140 -53
  53. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  54. package/dist-cjs/lib/license/LicenseProvider.js +39 -1
  55. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  56. package/dist-cjs/lib/license/Watermark.js +73 -11
  57. package/dist-cjs/lib/license/Watermark.js.map +3 -3
  58. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  59. package/dist-cjs/lib/options.js +6 -0
  60. package/dist-cjs/lib/options.js.map +2 -2
  61. package/dist-cjs/lib/primitives/Box.js +3 -0
  62. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  63. package/dist-cjs/lib/primitives/Vec.js +0 -4
  64. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  65. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +50 -20
  66. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  67. package/dist-cjs/lib/primitives/geometry/Group2d.js +8 -1
  68. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  69. package/dist-cjs/lib/utils/dom.js +12 -1
  70. package/dist-cjs/lib/utils/dom.js.map +2 -2
  71. package/dist-cjs/lib/utils/getPointerInfo.js +2 -2
  72. package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
  73. package/dist-cjs/lib/utils/reparenting.js +2 -35
  74. package/dist-cjs/lib/utils/reparenting.js.map +3 -3
  75. package/dist-cjs/version.js +3 -3
  76. package/dist-cjs/version.js.map +1 -1
  77. package/dist-esm/index.d.mts +137 -126
  78. package/dist-esm/index.mjs +9 -7
  79. package/dist-esm/index.mjs.map +2 -2
  80. package/dist-esm/lib/TldrawEditor.mjs +9 -9
  81. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  82. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  83. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  84. package/dist-esm/lib/components/Shape.mjs +7 -10
  85. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  86. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +15 -24
  87. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  88. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  89. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
  90. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  91. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  92. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  93. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  94. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  95. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  96. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
  97. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  98. package/dist-esm/lib/editor/Editor.mjs +67 -128
  99. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  100. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +4 -0
  101. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
  102. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  103. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -1
  104. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  105. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  106. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +23 -0
  107. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  108. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  109. package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
  110. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  111. package/dist-esm/lib/hooks/useCanvasEvents.mjs +47 -37
  112. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  113. package/dist-esm/lib/hooks/useDocumentEvents.mjs +11 -6
  114. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  115. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +2 -3
  116. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  117. package/dist-esm/lib/hooks/useGestureEvents.mjs +2 -2
  118. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  119. package/dist-esm/lib/hooks/useHandleEvents.mjs +9 -4
  120. package/dist-esm/lib/hooks/useHandleEvents.mjs.map +2 -2
  121. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
  122. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  123. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  124. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  125. package/dist-esm/lib/hooks/useSelectionEvents.mjs +6 -5
  126. package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +2 -2
  127. package/dist-esm/lib/license/LicenseManager.mjs +141 -54
  128. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  129. package/dist-esm/lib/license/LicenseProvider.mjs +39 -2
  130. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  131. package/dist-esm/lib/license/Watermark.mjs +74 -12
  132. package/dist-esm/lib/license/Watermark.mjs.map +3 -3
  133. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  134. package/dist-esm/lib/options.mjs +6 -0
  135. package/dist-esm/lib/options.mjs.map +2 -2
  136. package/dist-esm/lib/primitives/Box.mjs +4 -1
  137. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  138. package/dist-esm/lib/primitives/Vec.mjs +0 -4
  139. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  140. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +53 -21
  141. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  142. package/dist-esm/lib/primitives/geometry/Group2d.mjs +8 -1
  143. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  144. package/dist-esm/lib/utils/dom.mjs +12 -1
  145. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  146. package/dist-esm/lib/utils/getPointerInfo.mjs +2 -2
  147. package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
  148. package/dist-esm/lib/utils/reparenting.mjs +3 -40
  149. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  150. package/dist-esm/version.mjs +3 -3
  151. package/dist-esm/version.mjs.map +1 -1
  152. package/editor.css +308 -292
  153. package/package.json +14 -37
  154. package/src/index.ts +4 -9
  155. package/src/lib/TldrawEditor.tsx +14 -21
  156. package/src/lib/components/MenuClickCapture.tsx +0 -8
  157. package/src/lib/components/Shape.tsx +6 -12
  158. package/src/lib/components/default-components/DefaultCanvas.tsx +12 -23
  159. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  160. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  161. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  162. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
  163. package/src/lib/config/TLUserPreferences.ts +1 -1
  164. package/src/lib/editor/Editor.test.ts +108 -11
  165. package/src/lib/editor/Editor.ts +112 -195
  166. package/src/lib/editor/derivations/notVisibleShapes.ts +6 -0
  167. package/src/lib/editor/derivations/parentsToChildren.ts +1 -1
  168. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  169. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  170. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  171. package/src/lib/editor/managers/FontManager/FontManager.test.ts +38 -27
  172. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  173. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  174. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  175. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  176. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  177. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +21 -26
  178. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
  179. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  180. package/src/lib/editor/shapes/ShapeUtil.ts +51 -8
  181. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
  182. package/src/lib/editor/types/misc-types.ts +0 -6
  183. package/src/lib/exports/getSvgJsx.test.ts +874 -0
  184. package/src/lib/exports/getSvgJsx.tsx +78 -21
  185. package/src/lib/hooks/useCanvasEvents.ts +60 -47
  186. package/src/lib/hooks/useDocumentEvents.ts +11 -6
  187. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +2 -2
  188. package/src/lib/hooks/useGestureEvents.ts +2 -2
  189. package/src/lib/hooks/useHandleEvents.ts +9 -4
  190. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
  191. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  192. package/src/lib/hooks/useSelectionEvents.ts +6 -5
  193. package/src/lib/license/LicenseManager.test.ts +724 -383
  194. package/src/lib/license/LicenseManager.ts +201 -58
  195. package/src/lib/license/LicenseProvider.tsx +74 -2
  196. package/src/lib/license/Watermark.test.tsx +2 -1
  197. package/src/lib/license/Watermark.tsx +79 -12
  198. package/src/lib/license/useLicenseManagerState.ts +2 -2
  199. package/src/lib/options.ts +6 -0
  200. package/src/lib/primitives/Box.test.ts +126 -0
  201. package/src/lib/primitives/Box.ts +10 -1
  202. package/src/lib/primitives/Vec.ts +0 -5
  203. package/src/lib/primitives/geometry/Geometry2d.test.ts +420 -0
  204. package/src/lib/primitives/geometry/Geometry2d.ts +78 -21
  205. package/src/lib/primitives/geometry/Group2d.ts +10 -1
  206. package/src/lib/test/InFrontOfTheCanvas.test.tsx +187 -0
  207. package/src/lib/utils/dom.test.ts +94 -0
  208. package/src/lib/utils/dom.ts +38 -1
  209. package/src/lib/utils/getPointerInfo.ts +2 -1
  210. package/src/lib/utils/reparenting.ts +3 -69
  211. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  212. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  213. package/src/version.ts +3 -3
  214. package/dist-cjs/lib/utils/nearestMultiple.js +0 -34
  215. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  216. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  217. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  218. package/src/lib/utils/nearestMultiple.ts +0 -13
@@ -55,7 +55,6 @@ import {
55
55
  TLStore,
56
56
  TLStoreSnapshot,
57
57
  TLUnknownBinding,
58
- TLUnknownShape,
59
58
  TLVideoAsset,
60
59
  createBindingId,
61
60
  createShapeId,
@@ -116,7 +115,6 @@ import {
116
115
  } from '../constants'
117
116
  import { exportToSvg } from '../exports/exportToSvg'
118
117
  import { getSvgAsImage } from '../exports/getSvgAsImage'
119
- import { tlenv } from '../globals/environment'
120
118
  import { tlmenus } from '../globals/menus'
121
119
  import { tltime } from '../globals/time'
122
120
  import { TldrawOptions, defaultTldrawOptions } from '../options'
@@ -244,16 +242,6 @@ export interface TLEditorOptions {
244
242
  options?: Partial<TldrawOptions>
245
243
  licenseKey?: string
246
244
  fontAssetUrls?: { [key: string]: string | undefined }
247
- /**
248
- * A predicate that should return true if the given shape should be hidden.
249
- *
250
- * @deprecated Use {@link Editor#getShapeVisibility} instead.
251
- *
252
- * @param shape - The shape to check.
253
- * @param editor - The editor instance.
254
- */
255
- isShapeHidden?(shape: TLShape, editor: Editor): boolean
256
-
257
245
  /**
258
246
  * Provides a way to hide shapes.
259
247
  *
@@ -309,21 +297,12 @@ export class Editor extends EventEmitter<TLEventMap> {
309
297
  autoFocus,
310
298
  inferDarkMode,
311
299
  options,
312
- // eslint-disable-next-line @typescript-eslint/no-deprecated
313
- isShapeHidden,
314
300
  getShapeVisibility,
315
301
  fontAssetUrls,
316
302
  }: TLEditorOptions) {
317
303
  super()
318
- assert(
319
- !(isShapeHidden && getShapeVisibility),
320
- 'Cannot use both isShapeHidden and getShapeVisibility'
321
- )
322
304
 
323
- this._getShapeVisibility = isShapeHidden
324
- ? // eslint-disable-next-line @typescript-eslint/no-deprecated
325
- (shape: TLShape, editor: Editor) => (isShapeHidden(shape, editor) ? 'hidden' : 'inherit')
326
- : getShapeVisibility
305
+ this._getShapeVisibility = getShapeVisibility
327
306
 
328
307
  this.options = { ...defaultTldrawOptions, ...options }
329
308
 
@@ -907,14 +886,6 @@ export class Editor extends EventEmitter<TLEventMap> {
907
886
  */
908
887
  readonly fonts: FontManager
909
888
 
910
- /**
911
- * A manager for the editor's environment.
912
- *
913
- * @deprecated This is deprecated and will be removed in a future version. Use the `tlenv` global export instead.
914
- * @public
915
- */
916
- readonly environment = tlenv
917
-
918
889
  /**
919
890
  * A manager for the editor's scribbles.
920
891
  *
@@ -974,7 +945,7 @@ export class Editor extends EventEmitter<TLEventMap> {
974
945
  *
975
946
  * @public
976
947
  */
977
- shapeUtils: { readonly [K in string]?: ShapeUtil<TLUnknownShape> }
948
+ shapeUtils: { readonly [K in string]?: ShapeUtil<TLShape> }
978
949
 
979
950
  styleProps: { [key: string]: Map<StyleProp<any>, string> }
980
951
 
@@ -993,8 +964,8 @@ export class Editor extends EventEmitter<TLEventMap> {
993
964
  *
994
965
  * @public
995
966
  */
996
- getShapeUtil<S extends TLUnknownShape>(shape: S | TLShapePartial<S>): ShapeUtil<S>
997
- getShapeUtil<S extends TLUnknownShape>(type: S['type']): ShapeUtil<S>
967
+ getShapeUtil<S extends TLShape>(shape: S | TLShapePartial<S>): ShapeUtil<S>
968
+ getShapeUtil<S extends TLShape>(type: S['type']): ShapeUtil<S>
998
969
  getShapeUtil<T extends ShapeUtil>(type: T extends ShapeUtil<infer R> ? R['type'] : string): T
999
970
  getShapeUtil(arg: string | { type: string }) {
1000
971
  const type = typeof arg === 'string' ? arg : arg.type
@@ -1008,8 +979,8 @@ export class Editor extends EventEmitter<TLEventMap> {
1008
979
  *
1009
980
  * @param shape - A shape, shape partial, or shape type.
1010
981
  */
1011
- hasShapeUtil<S extends TLUnknownShape>(shape: S | TLShapePartial<S>): boolean
1012
- hasShapeUtil<S extends TLUnknownShape>(type: S['type']): boolean
982
+ hasShapeUtil(shape: TLShape | TLShapePartial<TLShape>): boolean
983
+ hasShapeUtil(type: TLShape['type']): boolean
1013
984
  hasShapeUtil<T extends ShapeUtil>(
1014
985
  type: T extends ShapeUtil<infer R> ? R['type'] : string
1015
986
  ): boolean
@@ -1119,35 +1090,6 @@ export class Editor extends EventEmitter<TLEventMap> {
1119
1090
  return this.history.getNumRedos() > 0
1120
1091
  }
1121
1092
 
1122
- /**
1123
- * Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
1124
- * any redos.
1125
- *
1126
- * @example
1127
- * ```ts
1128
- * editor.mark()
1129
- * editor.mark('flip shapes')
1130
- * ```
1131
- *
1132
- * @param markId - The mark's id, usually the reason for adding the mark.
1133
- *
1134
- * @public
1135
- * @deprecated use {@link Editor.markHistoryStoppingPoint} instead
1136
- */
1137
- mark(markId?: string): this {
1138
- if (typeof markId === 'string') {
1139
- console.warn(
1140
- `[tldraw] \`editor.history.mark("${markId}")\` is deprecated. Please use \`const myMarkId = editor.markHistoryStoppingPoint()\` instead.`
1141
- )
1142
- } else {
1143
- console.warn(
1144
- '[tldraw] `editor.mark()` is deprecated. Use `editor.markHistoryStoppingPoint()` instead.'
1145
- )
1146
- }
1147
- this.history._mark(markId ?? uniqueId())
1148
- return this
1149
- }
1150
-
1151
1093
  /**
1152
1094
  * Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
1153
1095
  * any redos. You typically want to do this just before a user interaction begins or is handled.
@@ -1272,13 +1214,6 @@ export class Editor extends EventEmitter<TLEventMap> {
1272
1214
  return this
1273
1215
  }
1274
1216
 
1275
- /**
1276
- * @deprecated Use `Editor.run` instead.
1277
- */
1278
- batch(fn: () => void, opts?: TLEditorRunOptions): this {
1279
- return this.run(fn, opts)
1280
- }
1281
-
1282
1217
  /* --------------------- Errors --------------------- */
1283
1218
 
1284
1219
  /** @internal */
@@ -1580,54 +1515,6 @@ export class Editor extends EventEmitter<TLEventMap> {
1580
1515
 
1581
1516
  menus = tlmenus.forContext(this.contextId)
1582
1517
 
1583
- /**
1584
- * @deprecated Use `editor.menus.getOpenMenus` instead.
1585
- *
1586
- * @public
1587
- */
1588
- @computed getOpenMenus(): string[] {
1589
- return this.menus.getOpenMenus()
1590
- }
1591
-
1592
- /**
1593
- * @deprecated Use `editor.menus.addOpenMenu` instead.
1594
- *
1595
- * @public
1596
- */
1597
- addOpenMenu(id: string): this {
1598
- this.menus.addOpenMenu(id)
1599
- return this
1600
- }
1601
-
1602
- /**
1603
- * @deprecated Use `editor.menus.deleteOpenMenu` instead.
1604
- *
1605
- * @public
1606
- */
1607
- deleteOpenMenu(id: string): this {
1608
- this.menus.deleteOpenMenu(id)
1609
- return this
1610
- }
1611
-
1612
- /**
1613
- * @deprecated Use `editor.menus.clearOpenMenus` instead.
1614
- *
1615
- * @public
1616
- */
1617
- clearOpenMenus(): this {
1618
- this.menus.clearOpenMenus()
1619
- return this
1620
- }
1621
-
1622
- /**
1623
- * @deprecated Use `editor.menus.hasAnyOpenMenus` instead.
1624
- *
1625
- * @public
1626
- */
1627
- @computed getIsMenuOpen(): boolean {
1628
- return this.menus.hasAnyOpenMenus()
1629
- }
1630
-
1631
1518
  /* --------------------- Cursor --------------------- */
1632
1519
 
1633
1520
  /**
@@ -4792,8 +4679,10 @@ export class Editor extends EventEmitter<TLEventMap> {
4792
4679
  return this.store.createComputedCache<Box, TLShape>('pageBoundsCache', (shape) => {
4793
4680
  const pageTransform = this.getShapePageTransform(shape)
4794
4681
  if (!pageTransform) return undefined
4795
- const geometry = this.getShapeGeometry(shape)
4796
- return Box.FromPoints(pageTransform.applyToPoints(geometry.vertices))
4682
+
4683
+ return Box.FromPoints(
4684
+ pageTransform.applyToPoints(this.getShapeGeometry(shape).boundsVertices)
4685
+ )
4797
4686
  })
4798
4687
  }
4799
4688
 
@@ -4860,27 +4749,25 @@ export class Editor extends EventEmitter<TLEventMap> {
4860
4749
  return this.store.createComputedCache('pageMaskCache', (shape) => {
4861
4750
  if (isPageId(shape.parentId)) return undefined
4862
4751
 
4863
- const frameAncestors = this.getShapeAncestors(shape.id).filter((shape) =>
4864
- this.isShapeOfType<TLFrameShape>(shape, 'frame')
4865
- )
4866
-
4867
- if (frameAncestors.length === 0) return undefined
4868
-
4869
- const pageMask = frameAncestors
4870
- .map<Vec[] | undefined>((s) => {
4871
- // Apply the frame transform to the frame outline to get the frame outline in the current page space
4872
- const geometry = this.getShapeGeometry(s.id)
4873
- const pageTransform = this.getShapePageTransform(s.id)
4874
- return pageTransform.applyToPoints(geometry.vertices)
4875
- })
4876
- .reduce((acc, b) => {
4877
- if (!(b && acc)) return undefined
4878
- const intersection = intersectPolygonPolygon(acc, b)
4879
- if (intersection) {
4880
- return intersection.map(Vec.Cast)
4881
- }
4882
- return []
4883
- })
4752
+ const clipPaths: Vec[][] = []
4753
+ // Get all ancestors that can potentially clip this shape
4754
+ for (const ancestor of this.getShapeAncestors(shape.id)) {
4755
+ const util = this.getShapeUtil(ancestor)
4756
+ const clipPath = util.getClipPath?.(ancestor)
4757
+ if (!clipPath) continue
4758
+ if (util.shouldClipChild?.(shape) === false) continue
4759
+ const pageTransform = this.getShapePageTransform(ancestor.id)
4760
+ clipPaths.push(pageTransform.applyToPoints(clipPath))
4761
+ }
4762
+ if (clipPaths.length === 0) return undefined
4763
+
4764
+ const pageMask = clipPaths.reduce((acc, b) => {
4765
+ const intersection = intersectPolygonPolygon(acc, b)
4766
+ if (intersection) {
4767
+ return intersection.map(Vec.Cast)
4768
+ }
4769
+ return []
4770
+ })
4884
4771
 
4885
4772
  return pageMask
4886
4773
  })
@@ -5503,15 +5390,9 @@ export class Editor extends EventEmitter<TLEventMap> {
5503
5390
  *
5504
5391
  * @public
5505
5392
  */
5506
- isShapeOfType<T extends TLUnknownShape>(shape: TLUnknownShape, type: T['type']): shape is T
5507
- isShapeOfType<T extends TLUnknownShape>(
5508
- shapeId: TLUnknownShape['id'],
5509
- type: T['type']
5510
- ): shapeId is T['id']
5511
- isShapeOfType<T extends TLUnknownShape>(
5512
- arg: TLUnknownShape | TLUnknownShape['id'],
5513
- type: T['type']
5514
- ) {
5393
+ isShapeOfType<T extends TLShape>(shape: TLShape, type: T['type']): shape is T
5394
+ isShapeOfType<T extends TLShape = TLShape>(shapeId: TLShapeId, type: T['type']): boolean
5395
+ isShapeOfType(arg: TLShape | TLShapeId, type: TLShape['type']) {
5515
5396
  const shape = typeof arg === 'string' ? this.getShape(arg) : arg
5516
5397
  if (!shape) return false
5517
5398
  return shape.type === type
@@ -5841,11 +5722,6 @@ export class Editor extends EventEmitter<TLEventMap> {
5841
5722
  return shapeIds
5842
5723
  }
5843
5724
 
5844
- /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
5845
- getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
5846
- return this.getDraggingOverShape(point, droppingShapes)
5847
- }
5848
-
5849
5725
  /**
5850
5726
  * Get the shape that some shapes should be dropped on at a given point.
5851
5727
  *
@@ -6333,7 +6209,17 @@ export class Editor extends EventEmitter<TLEventMap> {
6333
6209
 
6334
6210
  this.createShapes(shapesToCreate)
6335
6211
  this.createBindings(bindingsToCreate)
6336
- this.setSelectedShapes(compact(ids.map((id) => shapeIds.get(id))))
6212
+
6213
+ this.setSelectedShapes(
6214
+ compact(
6215
+ ids.map((oldId) => {
6216
+ const newId = shapeIds.get(oldId)
6217
+ if (!newId) return null
6218
+ if (!this.getShape(newId)) return null
6219
+ return newId
6220
+ })
6221
+ )
6222
+ )
6337
6223
 
6338
6224
  if (offset !== undefined) {
6339
6225
  // If we've offset the duplicated shapes, check to see whether their new bounds is entirely
@@ -7761,9 +7647,7 @@ export class Editor extends EventEmitter<TLEventMap> {
7761
7647
  *
7762
7648
  * @public
7763
7649
  */
7764
- canCreateShape<T extends TLUnknownShape>(
7765
- shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']
7766
- ): boolean {
7650
+ canCreateShape(shape: OptionalKeys<TLShapePartial<TLShape>, 'id'> | TLShape['id']): boolean {
7767
7651
  return this.canCreateShapes([shape])
7768
7652
  }
7769
7653
 
@@ -7774,8 +7658,8 @@ export class Editor extends EventEmitter<TLEventMap> {
7774
7658
  *
7775
7659
  * @public
7776
7660
  */
7777
- canCreateShapes<T extends TLUnknownShape>(
7778
- shapes: (T['id'] | OptionalKeys<TLShapePartial<T>, 'id'>)[]
7661
+ canCreateShapes(
7662
+ shapes: (TLShape['id'] | OptionalKeys<TLShapePartial<TLShape>, 'id'>)[]
7779
7663
  ): boolean {
7780
7664
  return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage
7781
7665
  }
@@ -7793,7 +7677,7 @@ export class Editor extends EventEmitter<TLEventMap> {
7793
7677
  *
7794
7678
  * @public
7795
7679
  */
7796
- createShape<T extends TLUnknownShape>(shape: OptionalKeys<TLShapePartial<T>, 'id'>): this {
7680
+ createShape<TShape extends TLShape>(shape: OptionalKeys<TLShapePartial<TShape>, 'id'>): this {
7797
7681
  this.createShapes([shape])
7798
7682
  return this
7799
7683
  }
@@ -7811,7 +7695,9 @@ export class Editor extends EventEmitter<TLEventMap> {
7811
7695
  *
7812
7696
  * @public
7813
7697
  */
7814
- createShapes<T extends TLUnknownShape>(shapes: OptionalKeys<TLShapePartial<T>, 'id'>[]): this {
7698
+ createShapes<TShape extends TLShape = TLShape>(
7699
+ shapes: OptionalKeys<TLShapePartial<TShape>, 'id'>[]
7700
+ ): this {
7815
7701
  if (!Array.isArray(shapes)) {
7816
7702
  throw Error('Editor.createShapes: must provide an array of shapes or shape partials')
7817
7703
  }
@@ -7857,25 +7743,32 @@ export class Editor extends EventEmitter<TLEventMap> {
7857
7743
  ) {
7858
7744
  let parentId: TLParentId = this.getFocusedGroupId()
7859
7745
 
7860
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
7861
- const parent = currentPageShapesSorted[i]
7862
- const util = this.getShapeUtil(parent)
7863
- if (
7864
- util.canReceiveNewChildrenOfType(parent, partial.type) &&
7865
- !this.isShapeHidden(parent) &&
7866
- this.isPointInShape(
7867
- parent,
7868
- // If no parent is provided, then we can treat the
7869
- // shape's provided x/y as being in the page's space.
7870
- { x: partial.x ?? 0, y: partial.y ?? 0 },
7871
- {
7872
- margin: 0,
7873
- hitInside: true,
7874
- }
7875
- )
7876
- ) {
7877
- parentId = parent.id
7878
- break
7746
+ const isPositioned = partial.x !== undefined && partial.y !== undefined
7747
+
7748
+ // If the shape has been explicitly positioned, we'll try to find a parent at
7749
+ // that position. If not, we'll assume the user isn't deliberately placing the
7750
+ // shape and the positioning will be handled later by another system.
7751
+ if (isPositioned) {
7752
+ for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
7753
+ const parent = currentPageShapesSorted[i]
7754
+ const util = this.getShapeUtil(parent)
7755
+ if (
7756
+ util.canReceiveNewChildrenOfType(parent, partial.type) &&
7757
+ !this.isShapeHidden(parent) &&
7758
+ this.isPointInShape(
7759
+ parent,
7760
+ // If no parent is provided, then we can treat the
7761
+ // shape's provided x/y as being in the page's space.
7762
+ { x: partial.x ?? 0, y: partial.y ?? 0 },
7763
+ {
7764
+ margin: 0,
7765
+ hitInside: true,
7766
+ }
7767
+ )
7768
+ ) {
7769
+ parentId = parent.id
7770
+ break
7771
+ }
7879
7772
  }
7880
7773
  }
7881
7774
 
@@ -8301,7 +8194,7 @@ export class Editor extends EventEmitter<TLEventMap> {
8301
8194
  *
8302
8195
  * @public
8303
8196
  */
8304
- updateShape<T extends TLUnknownShape>(partial: TLShapePartial<T> | null | undefined) {
8197
+ updateShape<T extends TLShape = TLShape>(partial: TLShapePartial<T> | null | undefined) {
8305
8198
  this.updateShapes([partial])
8306
8199
  return this
8307
8200
  }
@@ -8318,7 +8211,7 @@ export class Editor extends EventEmitter<TLEventMap> {
8318
8211
  *
8319
8212
  * @public
8320
8213
  */
8321
- updateShapes<T extends TLUnknownShape>(partials: (TLShapePartial<T> | null | undefined)[]) {
8214
+ updateShapes<T extends TLShape>(partials: (TLShapePartial<T> | null | undefined)[]) {
8322
8215
  const compactedPartials: TLShapePartial<T>[] = Array(partials.length)
8323
8216
 
8324
8217
  for (let i = 0, n = partials.length; i < n; i++) {
@@ -8933,8 +8826,13 @@ export class Editor extends EventEmitter<TLEventMap> {
8933
8826
  * Handle external content, such as files, urls, embeds, or plain text which has been put into the app, for example by pasting external text or dropping external images onto canvas.
8934
8827
  *
8935
8828
  * @param info - Info about the external content.
8829
+ * @param opts - Options for handling external content, including force flag to bypass readonly checks.
8936
8830
  */
8937
- async putExternalContent<E>(info: TLExternalContent<E>): Promise<void> {
8831
+ async putExternalContent<E>(
8832
+ info: TLExternalContent<E>,
8833
+ opts = {} as { force?: boolean }
8834
+ ): Promise<void> {
8835
+ if (!opts.force && this.getIsReadonly()) return
8938
8836
  return this.externalContentHandlers[info.type]?.(info as any)
8939
8837
  }
8940
8838
 
@@ -8942,8 +8840,13 @@ export class Editor extends EventEmitter<TLEventMap> {
8942
8840
  * Handle replacing external content.
8943
8841
  *
8944
8842
  * @param info - Info about the external content.
8843
+ * @param opts - Options for handling external content, including force flag to bypass readonly checks.
8945
8844
  */
8946
- async replaceExternalContent<E>(info: TLExternalContent<E>): Promise<void> {
8845
+ async replaceExternalContent<E>(
8846
+ info: TLExternalContent<E>,
8847
+ opts = {} as { force?: boolean }
8848
+ ): Promise<void> {
8849
+ if (!opts.force && this.getIsReadonly()) return
8947
8850
  return this.externalContentHandlers[info.type]?.(info as any)
8948
8851
  }
8949
8852
 
@@ -9444,13 +9347,6 @@ export class Editor extends EventEmitter<TLEventMap> {
9444
9347
  }
9445
9348
  }
9446
9349
 
9447
- /** @deprecated Use {@link Editor.getSvgString} or {@link Editor.getSvgElement} instead. */
9448
- async getSvg(shapes: TLShapeId[] | TLShape[], opts: TLSvgExportOptions = {}) {
9449
- const result = await this.getSvgElement(shapes, opts)
9450
- if (!result) return undefined
9451
- return result.svg
9452
- }
9453
-
9454
9350
  /**
9455
9351
  * Get an exported image of the given shapes.
9456
9352
  *
@@ -9502,6 +9398,24 @@ export class Editor extends EventEmitter<TLEventMap> {
9502
9398
  }
9503
9399
  }
9504
9400
 
9401
+ /**
9402
+ * Get an exported image of the given shapes as a data URL.
9403
+ *
9404
+ * @param shapes - The shapes (or shape ids) to export.
9405
+ * @param opts - Options for the export.
9406
+ *
9407
+ * @returns A data URL of the image.
9408
+ * @public
9409
+ */
9410
+ async toImageDataUrl(shapes: TLShapeId[] | TLShape[], opts: TLImageExportOptions = {}) {
9411
+ const { blob, width, height } = await this.toImage(shapes, opts)
9412
+ return {
9413
+ url: await FileHelpers.blobToDataUrl(blob),
9414
+ width,
9415
+ height,
9416
+ }
9417
+ }
9418
+
9505
9419
  /* --------------------- Events --------------------- */
9506
9420
 
9507
9421
  /**
@@ -10733,7 +10647,10 @@ function alertMaxShapes(editor: Editor, pageId = editor.getCurrentPageId()) {
10733
10647
 
10734
10648
  function applyPartialToRecordWithProps<
10735
10649
  T extends UnknownRecord & { type: string; props: object; meta: object },
10736
- >(prev: T, partial?: Partial<T> & { props?: Partial<T['props']> }): T {
10650
+ >(
10651
+ prev: T,
10652
+ partial?: T extends T ? Omit<Partial<T>, 'props'> & { props?: Partial<T['props']> } : never
10653
+ ): T {
10737
10654
  if (!partial) return prev
10738
10655
  let next = null as null | T
10739
10656
  const entries = Object.entries(partial)
@@ -7,6 +7,12 @@ function fromScratch(editor: Editor): Set<TLShapeId> {
7
7
  const viewportPageBounds = editor.getViewportPageBounds()
8
8
  const notVisibleShapes = new Set<TLShapeId>()
9
9
  shapesIds.forEach((id) => {
10
+ const shape = editor.getShape(id)
11
+ if (!shape) return
12
+
13
+ const canCull = editor.getShapeUtil(shape.type).canCull(shape)
14
+ if (!canCull) return
15
+
10
16
  // If the shape is fully outside of the viewport page bounds, add it to the set.
11
17
  // We'll ignore masks here, since they're more expensive to compute and the overhead is not worth it.
12
18
  const pageBounds = editor.getShapePageBounds(id)
@@ -11,7 +11,7 @@ function fromScratch(
11
11
  ) {
12
12
  const result: ParentShapeIdsToChildShapeIds = {}
13
13
  const shapeIds = shapeIdsQuery.get()
14
- const shapes = Array(shapeIds.size) as TLShape[]
14
+ const shapes = Array<TLShape>(shapeIds.size)
15
15
  shapeIds.forEach((id) => shapes.push(store.get(id)!))
16
16
 
17
17
  // Sort the shapes by index
@@ -1,12 +1,13 @@
1
+ import { Mocked, vi } from 'vitest'
1
2
  import { Editor } from '../../Editor'
2
3
  import { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'
3
4
  import { ClickManager } from './ClickManager'
4
5
 
5
6
  // Mock the Editor class
6
- jest.mock('../../Editor')
7
+ vi.mock('../../Editor')
7
8
 
8
9
  describe('ClickManager', () => {
9
- let editor: jest.Mocked<Editor>
10
+ let editor: Mocked<Editor>
10
11
  let clickManager: ClickManager
11
12
  let mockTimers: any
12
13
 
@@ -29,14 +30,14 @@ describe('ClickManager', () => {
29
30
  })
30
31
 
31
32
  beforeEach(() => {
32
- jest.useFakeTimers()
33
+ vi.useFakeTimers()
33
34
  mockTimers = {
34
- setTimeout: jest.fn((fn, delay) => setTimeout(fn, delay)),
35
+ setTimeout: vi.fn((fn, delay) => setTimeout(fn, delay)),
35
36
  }
36
37
 
37
38
  editor = {
38
39
  timers: mockTimers,
39
- dispatch: jest.fn(),
40
+ dispatch: vi.fn(),
40
41
  options: {
41
42
  doubleClickDurationMs: 300,
42
43
  multiClickDurationMs: 300,
@@ -46,7 +47,7 @@ describe('ClickManager', () => {
46
47
  inputs: {
47
48
  currentScreenPoint: { x: 0, y: 0 },
48
49
  },
49
- getInstanceState: jest.fn(() => ({
50
+ getInstanceState: vi.fn(() => ({
50
51
  isCoarsePointer: false,
51
52
  })),
52
53
  } as any
@@ -55,8 +56,8 @@ describe('ClickManager', () => {
55
56
  })
56
57
 
57
58
  afterEach(() => {
58
- jest.useRealTimers()
59
- jest.clearAllMocks()
59
+ vi.useRealTimers()
60
+ vi.clearAllMocks()
60
61
  })
61
62
 
62
63
  describe('constructor and initial state', () => {
@@ -100,7 +101,7 @@ describe('ClickManager', () => {
100
101
  clickManager.handlePointerEvent(pointerEvent)
101
102
  expect(clickManager.clickState).toBe('pendingDouble')
102
103
 
103
- jest.advanceTimersByTime(350)
104
+ vi.advanceTimersByTime(350)
104
105
 
105
106
  expect(clickManager.clickState).toBe('idle')
106
107
  })
@@ -141,7 +142,7 @@ describe('ClickManager', () => {
141
142
  clickManager.handlePointerEvent(firstDown)
142
143
  clickManager.handlePointerEvent(secondDown)
143
144
 
144
- jest.advanceTimersByTime(350)
145
+ vi.advanceTimersByTime(350)
145
146
 
146
147
  expect(editor.dispatch).toHaveBeenCalledWith(
147
148
  expect.objectContaining({
@@ -235,7 +236,7 @@ describe('ClickManager', () => {
235
236
  clickManager.handlePointerEvent(pointerDown) // second
236
237
  clickManager.handlePointerEvent(pointerDown) // third
237
238
 
238
- jest.advanceTimersByTime(350)
239
+ vi.advanceTimersByTime(350)
239
240
 
240
241
  expect(editor.dispatch).toHaveBeenCalledWith(
241
242
  expect.objectContaining({
@@ -255,7 +256,7 @@ describe('ClickManager', () => {
255
256
  clickManager.handlePointerEvent(pointerDown) // third
256
257
  clickManager.handlePointerEvent(pointerDown) // fourth
257
258
 
258
- jest.advanceTimersByTime(350)
259
+ vi.advanceTimersByTime(350)
259
260
 
260
261
  expect(editor.dispatch).toHaveBeenCalledWith(
261
262
  expect.objectContaining({
@@ -277,7 +278,7 @@ describe('ClickManager', () => {
277
278
  editor.options.doubleClickDurationMs
278
279
  )
279
280
 
280
- jest.clearAllMocks()
281
+ vi.clearAllMocks()
281
282
 
282
283
  // Second click - should use multiClickDurationMs
283
284
  clickManager.handlePointerEvent(pointerDown)
@@ -392,7 +393,7 @@ describe('ClickManager', () => {
392
393
  clickManager.cancelDoubleClickTimeout()
393
394
 
394
395
  // Advance time - should not dispatch settle event
395
- jest.advanceTimersByTime(350)
396
+ vi.advanceTimersByTime(350)
396
397
 
397
398
  expect(editor.dispatch).not.toHaveBeenCalled()
398
399
  expect(clickManager.clickState).toBe('idle')