@tldraw/editor 3.16.0-internal.51e99e128bd4 → 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 (166) hide show
  1. package/dist-cjs/index.d.ts +133 -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 +7 -7
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/Shape.js +7 -10
  7. package/dist-cjs/lib/components/Shape.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +14 -23
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/editor/Editor.js +40 -113
  11. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  12. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +4 -0
  13. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
  14. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  15. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  16. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +23 -0
  17. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  19. package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
  20. package/dist-cjs/lib/exports/getSvgJsx.js +34 -14
  21. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  22. package/dist-cjs/lib/hooks/useCanvasEvents.js +22 -17
  23. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  24. package/dist-cjs/lib/hooks/useDocumentEvents.js +5 -5
  25. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  26. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -2
  27. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  28. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  29. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  30. package/dist-cjs/lib/hooks/useHandleEvents.js +3 -3
  31. package/dist-cjs/lib/hooks/useHandleEvents.js.map +2 -2
  32. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +4 -1
  33. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  34. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  35. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  36. package/dist-cjs/lib/hooks/useSelectionEvents.js +4 -4
  37. package/dist-cjs/lib/hooks/useSelectionEvents.js.map +2 -2
  38. package/dist-cjs/lib/license/LicenseManager.js +140 -53
  39. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  40. package/dist-cjs/lib/license/LicenseProvider.js +39 -1
  41. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  42. package/dist-cjs/lib/license/Watermark.js +69 -7
  43. package/dist-cjs/lib/license/Watermark.js.map +3 -3
  44. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  45. package/dist-cjs/lib/primitives/Box.js +3 -0
  46. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  47. package/dist-cjs/lib/primitives/Vec.js +0 -4
  48. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  49. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +50 -20
  50. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  51. package/dist-cjs/lib/primitives/geometry/Group2d.js +8 -1
  52. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  53. package/dist-cjs/lib/utils/dom.js +12 -1
  54. package/dist-cjs/lib/utils/dom.js.map +2 -2
  55. package/dist-cjs/lib/utils/getPointerInfo.js +2 -2
  56. package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
  57. package/dist-cjs/lib/utils/reparenting.js +2 -35
  58. package/dist-cjs/lib/utils/reparenting.js.map +3 -3
  59. package/dist-cjs/version.js +3 -3
  60. package/dist-cjs/version.js.map +1 -1
  61. package/dist-esm/index.d.mts +133 -126
  62. package/dist-esm/index.mjs +9 -7
  63. package/dist-esm/index.mjs.map +2 -2
  64. package/dist-esm/lib/TldrawEditor.mjs +8 -8
  65. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  66. package/dist-esm/lib/components/Shape.mjs +7 -10
  67. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  68. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +15 -24
  69. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  70. package/dist-esm/lib/editor/Editor.mjs +40 -113
  71. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  72. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +4 -0
  73. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
  74. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  75. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  76. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +23 -0
  77. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  78. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  79. package/dist-esm/lib/exports/getSvgJsx.mjs +34 -14
  80. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  81. package/dist-esm/lib/hooks/useCanvasEvents.mjs +24 -18
  82. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  83. package/dist-esm/lib/hooks/useDocumentEvents.mjs +11 -6
  84. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  85. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +2 -3
  86. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  87. package/dist-esm/lib/hooks/useGestureEvents.mjs +2 -2
  88. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  89. package/dist-esm/lib/hooks/useHandleEvents.mjs +9 -4
  90. package/dist-esm/lib/hooks/useHandleEvents.mjs.map +2 -2
  91. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +4 -1
  92. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  93. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  94. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  95. package/dist-esm/lib/hooks/useSelectionEvents.mjs +6 -5
  96. package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +2 -2
  97. package/dist-esm/lib/license/LicenseManager.mjs +141 -54
  98. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  99. package/dist-esm/lib/license/LicenseProvider.mjs +39 -2
  100. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  101. package/dist-esm/lib/license/Watermark.mjs +70 -8
  102. package/dist-esm/lib/license/Watermark.mjs.map +3 -3
  103. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  104. package/dist-esm/lib/primitives/Box.mjs +4 -1
  105. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  106. package/dist-esm/lib/primitives/Vec.mjs +0 -4
  107. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  108. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +53 -21
  109. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  110. package/dist-esm/lib/primitives/geometry/Group2d.mjs +8 -1
  111. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  112. package/dist-esm/lib/utils/dom.mjs +12 -1
  113. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  114. package/dist-esm/lib/utils/getPointerInfo.mjs +2 -2
  115. package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
  116. package/dist-esm/lib/utils/reparenting.mjs +3 -40
  117. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  118. package/dist-esm/version.mjs +3 -3
  119. package/dist-esm/version.mjs.map +1 -1
  120. package/editor.css +16 -3
  121. package/package.json +7 -7
  122. package/src/index.ts +4 -9
  123. package/src/lib/TldrawEditor.tsx +9 -16
  124. package/src/lib/components/Shape.tsx +6 -12
  125. package/src/lib/components/default-components/DefaultCanvas.tsx +12 -23
  126. package/src/lib/editor/Editor.test.ts +96 -0
  127. package/src/lib/editor/Editor.ts +75 -175
  128. package/src/lib/editor/derivations/notVisibleShapes.ts +6 -0
  129. package/src/lib/editor/derivations/parentsToChildren.ts +1 -1
  130. package/src/lib/editor/managers/FontManager/FontManager.test.ts +14 -4
  131. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  132. package/src/lib/editor/shapes/ShapeUtil.ts +51 -8
  133. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
  134. package/src/lib/editor/types/misc-types.ts +0 -6
  135. package/src/lib/exports/getSvgJsx.test.ts +874 -0
  136. package/src/lib/exports/getSvgJsx.tsx +76 -19
  137. package/src/lib/hooks/useCanvasEvents.ts +23 -17
  138. package/src/lib/hooks/useDocumentEvents.ts +11 -6
  139. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +2 -2
  140. package/src/lib/hooks/useGestureEvents.ts +2 -2
  141. package/src/lib/hooks/useHandleEvents.ts +9 -4
  142. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +4 -1
  143. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  144. package/src/lib/hooks/useSelectionEvents.ts +6 -5
  145. package/src/lib/license/LicenseManager.test.ts +721 -382
  146. package/src/lib/license/LicenseManager.ts +201 -58
  147. package/src/lib/license/LicenseProvider.tsx +74 -2
  148. package/src/lib/license/Watermark.tsx +75 -8
  149. package/src/lib/license/useLicenseManagerState.ts +2 -2
  150. package/src/lib/primitives/Box.test.ts +126 -0
  151. package/src/lib/primitives/Box.ts +10 -1
  152. package/src/lib/primitives/Vec.ts +0 -5
  153. package/src/lib/primitives/geometry/Geometry2d.test.ts +420 -0
  154. package/src/lib/primitives/geometry/Geometry2d.ts +78 -21
  155. package/src/lib/primitives/geometry/Group2d.ts +10 -1
  156. package/src/lib/test/InFrontOfTheCanvas.test.tsx +187 -0
  157. package/src/lib/utils/dom.test.ts +94 -0
  158. package/src/lib/utils/dom.ts +38 -1
  159. package/src/lib/utils/getPointerInfo.ts +2 -1
  160. package/src/lib/utils/reparenting.ts +3 -69
  161. package/src/version.ts +3 -3
  162. package/dist-cjs/lib/utils/nearestMultiple.js +0 -34
  163. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  164. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  165. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  166. package/src/lib/utils/nearestMultiple.ts +0 -13
package/src/index.ts CHANGED
@@ -268,7 +268,6 @@ export {
268
268
  type TLGetShapeAtPointOptions,
269
269
  type TLImageExportOptions,
270
270
  type TLSvgExportOptions,
271
- type TLSvgOptions,
272
271
  type TLUpdatePointerOptions,
273
272
  } from './lib/editor/types/misc-types'
274
273
  export {
@@ -331,9 +330,11 @@ export {
331
330
  type InvalidLicenseReason,
332
331
  type LicenseFromKeyResult,
333
332
  type LicenseInfo,
333
+ type LicenseState,
334
334
  type TestEnvironment,
335
335
  type ValidLicenseKeyResult,
336
336
  } from './lib/license/LicenseManager'
337
+ export { LICENSE_TIMEOUT } from './lib/license/LicenseProvider'
337
338
  export { defaultTldrawOptions, type TldrawOptions } from './lib/options'
338
339
  export {
339
340
  Box,
@@ -446,10 +447,12 @@ export {
446
447
  export {
447
448
  activeElementShouldCaptureKeys,
448
449
  loopToHtmlElement,
450
+ markEventAsHandled,
449
451
  preventDefault,
450
452
  releasePointerCapture,
451
453
  setPointerCapture,
452
454
  stopEventPropagation,
455
+ wasEventAlreadyHandled,
453
456
  } from './lib/utils/dom'
454
457
  export { EditorAtom } from './lib/utils/EditorAtom'
455
458
  export { getIncrementedName } from './lib/utils/getIncrementedName'
@@ -485,14 +488,6 @@ export { type TLStoreWithStatus } from './lib/utils/sync/StoreWithStatus'
485
488
  export { uniq } from './lib/utils/uniq'
486
489
  export { openWindow } from './lib/utils/window-open'
487
490
 
488
- /**
489
- * @deprecated Licensing is now enabled in the tldraw SDK.
490
- * @public */
491
- export function debugEnableLicensing() {
492
- // noop
493
- return
494
- }
495
-
496
491
  registerTldrawLibraryVersion(
497
492
  (globalThis as any).TLDRAW_LIBRARY_NAME,
498
493
  (globalThis as any).TLDRAW_LIBRARY_VERSION,
@@ -1,6 +1,7 @@
1
1
  import { MigrationSequence, Store } from '@tldraw/store'
2
2
  import { TLShape, TLStore, TLStoreSnapshot } from '@tldraw/tlschema'
3
3
  import { annotateError, Required } from '@tldraw/utils'
4
+ import classNames from 'classnames'
4
5
  import React, {
5
6
  memo,
6
7
  ReactNode,
@@ -12,8 +13,6 @@ import React, {
12
13
  useState,
13
14
  useSyncExternalStore,
14
15
  } from 'react'
15
-
16
- import classNames from 'classnames'
17
16
  import { version } from '../version'
18
17
  import { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback'
19
18
  import { OptionalErrorBoundary } from './components/ErrorBoundary'
@@ -45,7 +44,7 @@ import { LicenseProvider } from './license/LicenseProvider'
45
44
  import { Watermark } from './license/Watermark'
46
45
  import { TldrawOptions } from './options'
47
46
  import { TLDeepLinkOptions } from './utils/deepLinks'
48
- import { stopEventPropagation } from './utils/dom'
47
+ import { markEventAsHandled } from './utils/dom'
49
48
  import { TLTextOptions } from './utils/richText'
50
49
  import { TLStoreWithStatus } from './utils/sync/StoreWithStatus'
51
50
 
@@ -189,13 +188,6 @@ export interface TldrawEditorBaseProps {
189
188
  */
190
189
  deepLinks?: true | TLDeepLinkOptions
191
190
 
192
- /**
193
- * Predicate for whether or not a shape should be hidden.
194
- *
195
- * @deprecated Use {@link TldrawEditorBaseProps#getShapeVisibility} instead.
196
- */
197
- isShapeHidden?(shape: TLShape, editor: Editor): boolean
198
-
199
191
  /**
200
192
  * Provides a way to hide shapes.
201
193
  *
@@ -283,7 +275,7 @@ export const TldrawEditor = memo(function TldrawEditor({
283
275
  data-tldraw={version}
284
276
  draggable={false}
285
277
  className={classNames(`${TL_CONTAINER_CLASS} tl-theme__light`, className)}
286
- onPointerDown={stopEventPropagation}
278
+ onPointerDown={markEventAsHandled}
287
279
  tabIndex={-1}
288
280
  role="application"
289
281
  aria-label={_options?.branding ?? 'tldraw'}
@@ -412,8 +404,6 @@ function TldrawEditorWithReadyStore({
412
404
  options,
413
405
  licenseKey,
414
406
  deepLinks: _deepLinks,
415
- // eslint-disable-next-line @typescript-eslint/no-deprecated
416
- isShapeHidden,
417
407
  getShapeVisibility,
418
408
  assetUrls,
419
409
  }: Required<
@@ -473,7 +463,6 @@ function TldrawEditorWithReadyStore({
473
463
  textOptions,
474
464
  options,
475
465
  licenseKey,
476
- isShapeHidden,
477
466
  getShapeVisibility,
478
467
  fontAssetUrls: assetUrls?.fonts,
479
468
  })
@@ -509,7 +498,6 @@ function TldrawEditorWithReadyStore({
509
498
  user,
510
499
  setEditor,
511
500
  licenseKey,
512
- isShapeHidden,
513
501
  getShapeVisibility,
514
502
  textOptions,
515
503
  assetUrls,
@@ -586,8 +574,13 @@ function TldrawEditorWithReadyStore({
586
574
  if (editor !== fontLoadingState?.editor) {
587
575
  fontLoadingState = null
588
576
  }
589
- useEffect(() => {
577
+ useLayoutEffect(() => {
590
578
  if (!editor) return
579
+ if (editor.options.maxFontsToLoadBeforeRender === 0) {
580
+ setFontLoadingState({ editor, isLoaded: true })
581
+ return
582
+ }
583
+
591
584
  let isCancelled = false
592
585
 
593
586
  setFontLoadingState({ editor, isLoaded: false })
@@ -28,7 +28,6 @@ export const Shape = memo(function Shape({
28
28
  index,
29
29
  backgroundIndex,
30
30
  opacity,
31
- dprMultiple,
32
31
  }: {
33
32
  id: TLShapeId
34
33
  shape: TLShape
@@ -36,7 +35,6 @@ export const Shape = memo(function Shape({
36
35
  index: number
37
36
  backgroundIndex: number
38
37
  opacity: number
39
- dprMultiple: number
40
38
  }) {
41
39
  const editor = useEditor()
42
40
 
@@ -91,18 +89,14 @@ export const Shape = memo(function Shape({
91
89
  }
92
90
 
93
91
  // Width / Height
94
- // We round the shape width and height up to the nearest multiple of dprMultiple
95
- // to avoid the browser making miscalculations when applying the transform.
96
- const widthRemainder = bounds.w % dprMultiple
97
- const heightRemainder = bounds.h % dprMultiple
98
- const width = widthRemainder === 0 ? bounds.w : bounds.w + (dprMultiple - widthRemainder)
99
- const height = heightRemainder === 0 ? bounds.h : bounds.h + (dprMultiple - heightRemainder)
92
+ const width = Math.max(bounds.width, 1)
93
+ const height = Math.max(bounds.height, 1)
100
94
 
101
95
  if (width !== prev.width || height !== prev.height) {
102
- setStyleProperty(containerRef.current, 'width', Math.max(width, dprMultiple) + 'px')
103
- setStyleProperty(containerRef.current, 'height', Math.max(height, dprMultiple) + 'px')
104
- setStyleProperty(bgContainerRef.current, 'width', Math.max(width, dprMultiple) + 'px')
105
- setStyleProperty(bgContainerRef.current, 'height', Math.max(height, dprMultiple) + 'px')
96
+ setStyleProperty(containerRef.current, 'width', width + 'px')
97
+ setStyleProperty(containerRef.current, 'height', height + 'px')
98
+ setStyleProperty(bgContainerRef.current, 'width', width + 'px')
99
+ setStyleProperty(bgContainerRef.current, 'height', height + 'px')
106
100
  prev.width = width
107
101
  prev.height = height
108
102
  }
@@ -21,8 +21,7 @@ import { Mat } from '../../primitives/Mat'
21
21
  import { Vec } from '../../primitives/Vec'
22
22
  import { toDomPrecision } from '../../primitives/utils'
23
23
  import { debugFlags } from '../../utils/debug-flags'
24
- import { setStyleProperty } from '../../utils/dom'
25
- import { nearestMultiple } from '../../utils/nearestMultiple'
24
+ import { markEventAsHandled, setStyleProperty } from '../../utils/dom'
26
25
  import { GeometryDebuggingView } from '../GeometryDebuggingView'
27
26
  import { LiveCollaborators } from '../LiveCollaborators'
28
27
  import { MenuClickCapture } from '../MenuClickCapture'
@@ -173,10 +172,18 @@ export function DefaultCanvas({ className }: TLCanvasComponentProps) {
173
172
  <LiveCollaborators />
174
173
  </div>
175
174
  </div>
175
+ <div
176
+ className="tl-canvas__in-front"
177
+ onPointerDown={markEventAsHandled}
178
+ onPointerUp={markEventAsHandled}
179
+ onTouchStart={markEventAsHandled}
180
+ onTouchEnd={markEventAsHandled}
181
+ >
182
+ <InFrontOfTheCanvasWrapper />
183
+ </div>
176
184
  <MovingCameraHitTestBlocker />
177
185
  </div>
178
186
  <MenuClickCapture />
179
- <InFrontOfTheCanvasWrapper />
180
187
  </>
181
188
  )
182
189
  }
@@ -390,18 +397,9 @@ function ShapesWithSVGs() {
390
397
 
391
398
  const renderingShapes = useValue('rendering shapes', () => editor.getRenderingShapes(), [editor])
392
399
 
393
- const dprMultiple = useValue(
394
- 'dpr multiple',
395
- () =>
396
- // dprMultiple is the smallest number we can multiply dpr by to get an integer
397
- // it's usually 1, 2, or 4 (for e.g. dpr of 2, 2.5 and 2.25 respectively)
398
- nearestMultiple(Math.floor(editor.getInstanceState().devicePixelRatio * 100) / 100),
399
- [editor]
400
- )
401
-
402
400
  return renderingShapes.map((result) => (
403
401
  <Fragment key={result.id + '_fragment'}>
404
- <Shape {...result} dprMultiple={dprMultiple} />
402
+ <Shape {...result} />
405
403
  <DebugSvgCopy id={result.id} mode="iframe" />
406
404
  </Fragment>
407
405
  ))
@@ -436,19 +434,10 @@ function ShapesToDisplay() {
436
434
 
437
435
  const renderingShapes = useValue('rendering shapes', () => editor.getRenderingShapes(), [editor])
438
436
 
439
- const dprMultiple = useValue(
440
- 'dpr multiple',
441
- () =>
442
- // dprMultiple is the smallest number we can multiply dpr by to get an integer
443
- // it's usually 1, 2, or 4 (for e.g. dpr of 2, 2.5 and 2.25 respectively)
444
- nearestMultiple(Math.floor(editor.getInstanceState().devicePixelRatio * 100) / 100),
445
- [editor]
446
- )
447
-
448
437
  return (
449
438
  <>
450
439
  {renderingShapes.map((result) => (
451
- <Shape key={result.id + '_shape'} {...result} dprMultiple={dprMultiple} />
440
+ <Shape key={result.id + '_shape'} {...result} />
452
441
  ))}
453
442
  {tlenv.isSafari && <ReflowIfNeeded />}
454
443
  </>
@@ -12,6 +12,12 @@ import {
12
12
  } from '../..'
13
13
  import { Editor } from './Editor'
14
14
 
15
+ declare module '@tldraw/tlschema' {
16
+ export interface GlobalShapePropsMap {
17
+ 'my-custom-shape': ICustomShape
18
+ }
19
+ }
20
+
15
21
  type ICustomShape = TLBaseShape<
16
22
  'my-custom-shape',
17
23
  {
@@ -833,3 +839,93 @@ describe('selectAll', () => {
833
839
  setSelectedShapesSpy.mockRestore()
834
840
  })
835
841
  })
842
+
843
+ describe('putExternalContent', () => {
844
+ let mockHandler: any
845
+
846
+ beforeEach(() => {
847
+ mockHandler = vi.fn()
848
+ editor.registerExternalContentHandler('text', mockHandler)
849
+ })
850
+
851
+ it('calls external content handler when not readonly', async () => {
852
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(false)
853
+
854
+ const info = { type: 'text' as const, text: 'test-data' }
855
+ await editor.putExternalContent(info)
856
+
857
+ expect(mockHandler).toHaveBeenCalledWith(info)
858
+ })
859
+
860
+ it('does not call external content handler when readonly', async () => {
861
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(true)
862
+
863
+ const info = { type: 'text' as const, text: 'test-data' }
864
+ await editor.putExternalContent(info)
865
+
866
+ expect(mockHandler).not.toHaveBeenCalled()
867
+ })
868
+
869
+ it('calls external content handler when readonly but force is true', async () => {
870
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(true)
871
+
872
+ const info = { type: 'text' as const, text: 'test-data' }
873
+ await editor.putExternalContent(info, { force: true })
874
+
875
+ expect(mockHandler).toHaveBeenCalledWith(info)
876
+ })
877
+
878
+ it('calls external content handler when force is false and not readonly', async () => {
879
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(false)
880
+
881
+ const info = { type: 'text' as const, text: 'test-data' }
882
+ await editor.putExternalContent(info, { force: false })
883
+
884
+ expect(mockHandler).toHaveBeenCalledWith(info)
885
+ })
886
+ })
887
+
888
+ describe('replaceExternalContent', () => {
889
+ let mockHandler: any
890
+
891
+ beforeEach(() => {
892
+ mockHandler = vi.fn()
893
+ editor.registerExternalContentHandler('text', mockHandler)
894
+ })
895
+
896
+ it('calls external content handler when not readonly', async () => {
897
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(false)
898
+
899
+ const info = { type: 'text' as const, text: 'test-data' }
900
+ await editor.replaceExternalContent(info)
901
+
902
+ expect(mockHandler).toHaveBeenCalledWith(info)
903
+ })
904
+
905
+ it('does not call external content handler when readonly', async () => {
906
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(true)
907
+
908
+ const info = { type: 'text' as const, text: 'test-data' }
909
+ await editor.replaceExternalContent(info)
910
+
911
+ expect(mockHandler).not.toHaveBeenCalled()
912
+ })
913
+
914
+ it('calls external content handler when readonly but force is true', async () => {
915
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(true)
916
+
917
+ const info = { type: 'text' as const, text: 'test-data' }
918
+ await editor.replaceExternalContent(info, { force: true })
919
+
920
+ expect(mockHandler).toHaveBeenCalledWith(info)
921
+ })
922
+
923
+ it('calls external content handler when force is false and not readonly', async () => {
924
+ vi.spyOn(editor, 'getIsReadonly').mockReturnValue(false)
925
+
926
+ const info = { type: 'text' as const, text: 'test-data' }
927
+ await editor.replaceExternalContent(info, { force: false })
928
+
929
+ expect(mockHandler).toHaveBeenCalledWith(info)
930
+ })
931
+ })