@tldraw/editor 4.6.0-next.fe1474dc57d8 → 5.0.0

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 (207) hide show
  1. package/dist-cjs/index.d.ts +412 -179
  2. package/dist-cjs/index.js +12 -23
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +3 -0
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/default-components/CanvasOverlays.js +180 -0
  7. package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +7 -0
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +44 -249
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +3 -3
  10. package/dist-cjs/lib/editor/Editor.js +78 -28
  11. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  12. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +98 -0
  13. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +7 -0
  14. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +14 -0
  15. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +2 -2
  16. package/dist-cjs/lib/editor/overlays/OverlayManager.js +154 -0
  17. package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +7 -0
  18. package/dist-cjs/lib/editor/overlays/OverlayUtil.js +92 -0
  19. package/dist-cjs/lib/editor/overlays/OverlayUtil.js.map +7 -0
  20. package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js +161 -0
  21. package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
  22. package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js +39 -0
  23. package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js.map +7 -0
  24. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -0
  25. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +25 -23
  27. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +32 -2
  29. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
  31. package/dist-cjs/lib/exports/fetchCache.js +1 -1
  32. package/dist-cjs/lib/exports/fetchCache.js.map +2 -2
  33. package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
  34. package/dist-cjs/lib/hooks/useCanvasEvents.js +3 -3
  35. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  36. package/dist-cjs/lib/hooks/useEditorComponents.js +0 -28
  37. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  38. package/dist-cjs/lib/hooks/usePeerIds.js +1 -36
  39. package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
  40. package/dist-cjs/lib/hooks/useShapeCulling.js +2 -1
  41. package/dist-cjs/lib/hooks/useShapeCulling.js.map +2 -2
  42. package/dist-cjs/lib/options.js +0 -1
  43. package/dist-cjs/lib/options.js.map +2 -2
  44. package/dist-cjs/lib/utils/reparenting.js +20 -7
  45. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  46. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +3 -0
  47. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  48. package/dist-cjs/version.js +4 -4
  49. package/dist-cjs/version.js.map +1 -1
  50. package/dist-esm/index.d.mts +412 -179
  51. package/dist-esm/index.mjs +19 -41
  52. package/dist-esm/index.mjs.map +2 -2
  53. package/dist-esm/lib/TldrawEditor.mjs +3 -0
  54. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  55. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +160 -0
  56. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +7 -0
  57. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +45 -250
  58. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +3 -3
  59. package/dist-esm/lib/editor/Editor.mjs +78 -29
  60. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  61. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +83 -0
  62. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +7 -0
  63. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +14 -0
  64. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +2 -2
  65. package/dist-esm/lib/editor/overlays/OverlayManager.mjs +136 -0
  66. package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +7 -0
  67. package/dist-esm/lib/editor/overlays/OverlayUtil.mjs +72 -0
  68. package/dist-esm/lib/editor/overlays/OverlayUtil.mjs.map +7 -0
  69. package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs +141 -0
  70. package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
  71. package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs +19 -0
  72. package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs.map +7 -0
  73. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -0
  74. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
  75. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +25 -23
  76. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  77. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +32 -2
  78. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  79. package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
  80. package/dist-esm/lib/exports/fetchCache.mjs +2 -2
  81. package/dist-esm/lib/exports/fetchCache.mjs.map +2 -2
  82. package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
  83. package/dist-esm/lib/hooks/useCanvasEvents.mjs +3 -3
  84. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  85. package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -28
  86. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  87. package/dist-esm/lib/hooks/usePeerIds.mjs +2 -40
  88. package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
  89. package/dist-esm/lib/hooks/useShapeCulling.mjs +2 -1
  90. package/dist-esm/lib/hooks/useShapeCulling.mjs.map +2 -2
  91. package/dist-esm/lib/options.mjs +0 -1
  92. package/dist-esm/lib/options.mjs.map +2 -2
  93. package/dist-esm/lib/utils/reparenting.mjs +20 -7
  94. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  95. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +3 -0
  96. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  97. package/dist-esm/version.mjs +4 -4
  98. package/dist-esm/version.mjs.map +1 -1
  99. package/editor.css +4 -239
  100. package/package.json +7 -7
  101. package/src/index.ts +17 -39
  102. package/src/lib/TldrawEditor.tsx +9 -0
  103. package/src/lib/components/default-components/CanvasOverlays.tsx +208 -0
  104. package/src/lib/components/default-components/DefaultCanvas.tsx +49 -324
  105. package/src/lib/editor/Editor.test.ts +3 -1
  106. package/src/lib/editor/Editor.ts +80 -24
  107. package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +98 -0
  108. package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +14 -0
  109. package/src/lib/editor/overlays/OverlayManager.ts +183 -0
  110. package/src/lib/editor/overlays/OverlayUtil.ts +143 -0
  111. package/src/lib/editor/overlays/ShapeIndicatorOverlayUtil.ts +216 -0
  112. package/src/lib/editor/overlays/getOverlayDisplayValues.ts +51 -0
  113. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +9 -2
  114. package/src/lib/editor/shapes/ShapeUtil.ts +34 -26
  115. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +40 -3
  116. package/src/lib/editor/types/event-types.ts +2 -0
  117. package/src/lib/exports/fetchCache.ts +2 -4
  118. package/src/lib/exports/getSvgJsx.test.ts +3 -1
  119. package/src/lib/hooks/EditorComponentsContext.tsx +0 -27
  120. package/src/lib/hooks/useCanvasEvents.ts +13 -8
  121. package/src/lib/hooks/useEditorComponents.tsx +0 -28
  122. package/src/lib/hooks/usePeerIds.ts +6 -55
  123. package/src/lib/hooks/useShapeCulling.tsx +3 -1
  124. package/src/lib/options.ts +0 -7
  125. package/src/lib/utils/reparenting.ts +22 -9
  126. package/src/lib/utils/sync/TLLocalSyncClient.ts +3 -0
  127. package/src/version.ts +4 -4
  128. package/dist-cjs/lib/components/GeometryDebuggingView.js +0 -115
  129. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +0 -7
  130. package/dist-cjs/lib/components/LiveCollaborators.js +0 -152
  131. package/dist-cjs/lib/components/LiveCollaborators.js.map +0 -7
  132. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +0 -234
  133. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +0 -7
  134. package/dist-cjs/lib/components/default-components/DefaultBrush.js +0 -38
  135. package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +0 -7
  136. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +0 -71
  137. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +0 -7
  138. package/dist-cjs/lib/components/default-components/DefaultCursor.js +0 -59
  139. package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +0 -7
  140. package/dist-cjs/lib/components/default-components/DefaultHandle.js +0 -56
  141. package/dist-cjs/lib/components/default-components/DefaultHandle.js.map +0 -7
  142. package/dist-cjs/lib/components/default-components/DefaultHandles.js +0 -28
  143. package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +0 -7
  144. package/dist-cjs/lib/components/default-components/DefaultScribble.js +0 -51
  145. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +0 -7
  146. package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js +0 -69
  147. package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js.map +0 -7
  148. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +0 -107
  149. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +0 -7
  150. package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js +0 -28
  151. package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js.map +0 -7
  152. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +0 -102
  153. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +0 -7
  154. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +0 -170
  155. package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +0 -7
  156. package/dist-cjs/lib/hooks/useHandleEvents.js +0 -100
  157. package/dist-cjs/lib/hooks/useHandleEvents.js.map +0 -7
  158. package/dist-cjs/lib/hooks/useSelectionEvents.js +0 -98
  159. package/dist-cjs/lib/hooks/useSelectionEvents.js.map +0 -7
  160. package/dist-esm/lib/components/GeometryDebuggingView.mjs +0 -95
  161. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +0 -7
  162. package/dist-esm/lib/components/LiveCollaborators.mjs +0 -135
  163. package/dist-esm/lib/components/LiveCollaborators.mjs.map +0 -7
  164. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +0 -214
  165. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +0 -7
  166. package/dist-esm/lib/components/default-components/DefaultBrush.mjs +0 -18
  167. package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +0 -7
  168. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +0 -41
  169. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +0 -7
  170. package/dist-esm/lib/components/default-components/DefaultCursor.mjs +0 -29
  171. package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +0 -7
  172. package/dist-esm/lib/components/default-components/DefaultHandle.mjs +0 -26
  173. package/dist-esm/lib/components/default-components/DefaultHandle.mjs.map +0 -7
  174. package/dist-esm/lib/components/default-components/DefaultHandles.mjs +0 -8
  175. package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +0 -7
  176. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +0 -21
  177. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +0 -7
  178. package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs +0 -39
  179. package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs.map +0 -7
  180. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +0 -77
  181. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +0 -7
  182. package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs +0 -8
  183. package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs.map +0 -7
  184. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +0 -82
  185. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +0 -7
  186. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +0 -142
  187. package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +0 -7
  188. package/dist-esm/lib/hooks/useHandleEvents.mjs +0 -70
  189. package/dist-esm/lib/hooks/useHandleEvents.mjs.map +0 -7
  190. package/dist-esm/lib/hooks/useSelectionEvents.mjs +0 -78
  191. package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +0 -7
  192. package/src/lib/components/GeometryDebuggingView.tsx +0 -108
  193. package/src/lib/components/LiveCollaborators.tsx +0 -180
  194. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +0 -300
  195. package/src/lib/components/default-components/DefaultBrush.tsx +0 -35
  196. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +0 -52
  197. package/src/lib/components/default-components/DefaultCursor.tsx +0 -59
  198. package/src/lib/components/default-components/DefaultHandle.tsx +0 -42
  199. package/src/lib/components/default-components/DefaultHandles.tsx +0 -15
  200. package/src/lib/components/default-components/DefaultScribble.tsx +0 -31
  201. package/src/lib/components/default-components/DefaultSelectionForeground.tsx +0 -50
  202. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +0 -104
  203. package/src/lib/components/default-components/DefaultShapeIndicatorErrorFallback.tsx +0 -9
  204. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +0 -118
  205. package/src/lib/components/default-components/DefaultSnapIndictor.tsx +0 -174
  206. package/src/lib/hooks/useHandleEvents.ts +0 -88
  207. package/src/lib/hooks/useSelectionEvents.ts +0 -97
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/shapes/group/GroupShapeUtil.tsx"],
4
- "sourcesContent": ["import { TLGroupShape, groupShapeMigrations, groupShapeProps } from '@tldraw/tlschema'\nimport { SVGContainer } from '../../../components/SVGContainer'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../../primitives/geometry/Group2d'\nimport { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'\nimport { ShapeUtil } from '../ShapeUtil'\nimport { DashedOutlineBox } from './DashedOutlineBox'\n\n/** @public */\nexport class GroupShapeUtil extends ShapeUtil<TLGroupShape> {\n\tstatic override type = 'group' as const\n\tstatic override props = groupShapeProps\n\tstatic override migrations = groupShapeMigrations\n\n\toverride hideSelectionBoundsFg(shape: TLGroupShape) {\n\t\treturn true\n\t}\n\n\toverride canBind() {\n\t\treturn false\n\t}\n\n\tcanResize() {\n\t\treturn true\n\t}\n\n\tcanResizeChildren() {\n\t\treturn true\n\t}\n\n\tgetDefaultProps(): TLGroupShape['props'] {\n\t\treturn {}\n\t}\n\n\tgetGeometry(shape: TLGroupShape): Geometry2d {\n\t\tconst children = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tif (children.length === 0) {\n\t\t\treturn new Rectangle2d({ width: 1, height: 1, isFilled: false })\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: children.map((childId) => {\n\t\t\t\tconst shape = this.editor.getShape(childId)!\n\t\t\t\treturn this.editor\n\t\t\t\t\t.getShapeGeometry(childId)\n\t\t\t\t\t.transform(this.editor.getShapeLocalTransform(shape)!, { isLabel: false })\n\t\t\t}),\n\t\t})\n\t}\n\n\tcomponent(shape: TLGroupShape) {\n\t\tconst isErasing = this.editor.getErasingShapeIds().includes(shape.id)\n\n\t\tconst { hintingShapeIds } = this.editor.getCurrentPageState()\n\t\tconst isHintingOtherGroup =\n\t\t\thintingShapeIds.length > 0 &&\n\t\t\thintingShapeIds.some(\n\t\t\t\t(id) => id !== shape.id && this.editor.isShapeOfType(this.editor.getShape(id)!, 'group')\n\t\t\t)\n\n\t\tconst isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id\n\n\t\tif (\n\t\t\t!isErasing && // always show the outline while we're erasing the group\n\t\t\t// show the outline while the group is focused unless something outside of the group is being hinted\n\t\t\t// this happens dropping shapes from a group onto some outside group\n\t\t\t(isFocused || isHintingOtherGroup)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DashedOutlineBox className=\"tl-group\" bounds={bounds} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLGroupShape) {\n\t\t// Not a class component, but eslint can't tell that :(\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\treturn <DashedOutlineBox className=\"\" bounds={bounds} />\n\t}\n\n\toverride onChildrenChange(group: TLGroupShape) {\n\t\tconst children = this.editor.getSortedChildIdsForParent(group.id)\n\t\tif (children.length === 0) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t} else if (children.length === 1) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.reparentShapes(children, group.parentId)\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t}\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2EI;AA3EJ,sBAAoE;AACpE,0BAA6B;AAE7B,qBAAwB;AACxB,yBAA4B;AAC5B,uBAA0B;AAC1B,8BAAiC;AAG1B,MAAM,uBAAuB,2BAAwB;AAAA,EAC3D,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,sBAAsB,OAAqB;AACnD,WAAO;AAAA,EACR;AAAA,EAES,UAAU;AAClB,WAAO;AAAA,EACR;AAAA,EAEA,YAAY;AACX,WAAO;AAAA,EACR;AAAA,EAEA,oBAAoB;AACnB,WAAO;AAAA,EACR;AAAA,EAEA,kBAAyC;AACxC,WAAO,CAAC;AAAA,EACT;AAAA,EAEA,YAAY,OAAiC;AAC5C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO,IAAI,+BAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,MAAM,CAAC;AAAA,IAChE;AAEA,WAAO,IAAI,uBAAQ;AAAA,MAClB,UAAU,SAAS,IAAI,CAAC,YAAY;AACnC,cAAMA,SAAQ,KAAK,OAAO,SAAS,OAAO;AAC1C,eAAO,KAAK,OACV,iBAAiB,OAAO,EACxB,UAAU,KAAK,OAAO,uBAAuBA,MAAK,GAAI,EAAE,SAAS,MAAM,CAAC;AAAA,MAC3E,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AAAA,EAEA,UAAU,OAAqB;AAC9B,UAAM,YAAY,KAAK,OAAO,mBAAmB,EAAE,SAAS,MAAM,EAAE;AAEpE,UAAM,EAAE,gBAAgB,IAAI,KAAK,OAAO,oBAAoB;AAC5D,UAAM,sBACL,gBAAgB,SAAS,KACzB,gBAAgB;AAAA,MACf,CAAC,OAAO,OAAO,MAAM,MAAM,KAAK,OAAO,cAAc,KAAK,OAAO,SAAS,EAAE,GAAI,OAAO;AAAA,IACxF;AAED,UAAM,YAAY,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM;AAE7E,QACC,CAAC;AAAA;AAAA;AAAA,KAGA,aAAa,sBACb;AACD,aAAO;AAAA,IACR;AAEA,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AAEnD,WACC,4CAAC,oCACA,sDAAC,4CAAiB,WAAU,YAAW,QAAgB,GACxD;AAAA,EAEF;AAAA,EAEA,UAAU,OAAqB;AAE9B,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AACnD,WAAO,4CAAC,4CAAiB,WAAU,IAAG,QAAgB;AAAA,EACvD;AAAA,EAES,iBAAiB,OAAqB;AAC9C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD,WAAW,SAAS,WAAW,GAAG;AACjC,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,eAAe,UAAU,MAAM,QAAQ;AACnD,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import { TLGroupShape, groupShapeMigrations, groupShapeProps } from '@tldraw/tlschema'\nimport { SVGContainer } from '../../../components/SVGContainer'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../../primitives/geometry/Group2d'\nimport { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'\nimport { ShapeUtil } from '../ShapeUtil'\nimport { getPerfectDashProps } from '../shared/getPerfectDashProps'\nimport { DashedOutlineBox } from './DashedOutlineBox'\n\n/** @public */\nexport class GroupShapeUtil extends ShapeUtil<TLGroupShape> {\n\tstatic override type = 'group' as const\n\tstatic override props = groupShapeProps\n\tstatic override migrations = groupShapeMigrations\n\n\toverride hideSelectionBoundsFg(shape: TLGroupShape) {\n\t\treturn true\n\t}\n\n\toverride canBind() {\n\t\treturn false\n\t}\n\n\tcanResize() {\n\t\treturn true\n\t}\n\n\tcanResizeChildren() {\n\t\treturn true\n\t}\n\n\tgetDefaultProps(): TLGroupShape['props'] {\n\t\treturn {}\n\t}\n\n\tgetGeometry(shape: TLGroupShape): Geometry2d {\n\t\tconst children = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tif (children.length === 0) {\n\t\t\treturn new Rectangle2d({ width: 1, height: 1, isFilled: false })\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: children.map((childId) => {\n\t\t\t\tconst shape = this.editor.getShape(childId)!\n\t\t\t\treturn this.editor\n\t\t\t\t\t.getShapeGeometry(childId)\n\t\t\t\t\t.transform(this.editor.getShapeLocalTransform(shape)!, { isLabel: false })\n\t\t\t}),\n\t\t})\n\t}\n\n\tcomponent(shape: TLGroupShape) {\n\t\tconst isErasing = this.editor.getErasingShapeIds().includes(shape.id)\n\n\t\tconst { hintingShapeIds } = this.editor.getCurrentPageState()\n\t\tconst isHintingOtherGroup =\n\t\t\thintingShapeIds.length > 0 &&\n\t\t\thintingShapeIds.some(\n\t\t\t\t(id) => id !== shape.id && this.editor.isShapeOfType(this.editor.getShape(id)!, 'group')\n\t\t\t)\n\n\t\tconst isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id\n\n\t\tif (\n\t\t\t!isErasing && // always show the outline while we're erasing the group\n\t\t\t// show the outline while the group is focused unless something outside of the group is being hinted\n\t\t\t// this happens dropping shapes from a group onto some outside group\n\t\t\t(isFocused || isHintingOtherGroup)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DashedOutlineBox className=\"tl-group\" bounds={bounds} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLGroupShape): Path2D {\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\tconst zoomLevel = this.editor.getEfficientZoomLevel()\n\t\tconst path = new Path2D()\n\n\t\tfor (const side of bounds.sides) {\n\t\t\tconst [start, end] = side\n\t\t\tconst length = start.dist(end)\n\t\t\tif (length <= 0) continue\n\n\t\t\tconst { strokeDasharray, strokeDashoffset } = getPerfectDashProps(length, 1 / zoomLevel, {\n\t\t\t\tstyle: 'dashed',\n\t\t\t\tlengthRatio: 4,\n\t\t\t})\n\n\t\t\tif (strokeDasharray === 'none') {\n\t\t\t\tpath.moveTo(start.x, start.y)\n\t\t\t\tpath.lineTo(end.x, end.y)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst [dashLength, gapLength] = strokeDasharray.split(' ').map(Number)\n\t\t\tconst dashOffset = Number(strokeDashoffset)\n\t\t\tconst period = dashLength + gapLength\n\t\t\tif (!Number.isFinite(period) || period <= 0) continue\n\n\t\t\tconst dx = (end.x - start.x) / length\n\t\t\tconst dy = (end.y - start.y) / length\n\n\t\t\tfor (let dashStart = -dashOffset; dashStart < length; dashStart += period) {\n\t\t\t\tconst dashEnd = Math.min(length, dashStart + dashLength)\n\t\t\t\tconst clippedDashStart = Math.max(0, dashStart)\n\t\t\t\tif (dashEnd <= clippedDashStart) continue\n\n\t\t\t\tpath.moveTo(start.x + dx * clippedDashStart, start.y + dy * clippedDashStart)\n\t\t\t\tpath.lineTo(start.x + dx * dashEnd, start.y + dy * dashEnd)\n\t\t\t}\n\t\t}\n\n\t\treturn path\n\t}\n\n\toverride onChildrenChange(group: TLGroupShape) {\n\t\tconst children = this.editor.getSortedChildIdsForParent(group.id)\n\t\tif (children.length === 0) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t} else if (children.length === 1) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.reparentShapes(children, group.parentId)\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["shape"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/types/event-types.ts"],
4
- "sourcesContent": ["import { TLHandle, TLShape, VecModel } from '@tldraw/tlschema'\nimport { VecLike } from '../../primitives/Vec'\nimport { TLSelectionHandle } from './selection-types'\n\n/** @public */\nexport type UiEventType = 'pointer' | 'click' | 'keyboard' | 'wheel' | 'pinch' | 'zoom'\n\n/** @public */\nexport type TLPointerEventTarget =\n\t| { target: 'canvas'; shape?: undefined }\n\t| { target: 'selection'; handle?: TLSelectionHandle; shape?: undefined }\n\t| { target: 'shape'; shape: TLShape }\n\t| { target: 'handle'; shape: TLShape; handle: TLHandle }\n\n/** @public */\nexport type TLPointerEventName =\n\t| 'pointer_down'\n\t| 'pointer_move'\n\t| 'long_press'\n\t| 'pointer_up'\n\t| 'right_click'\n\t| 'middle_click'\n\n/** @public */\nexport type TLCLickEventName = 'double_click' | 'triple_click' | 'quadruple_click'\n\n/** @public */\nexport type TLPinchEventName = 'pinch_start' | 'pinch' | 'pinch_end'\n\n/** @public */\nexport type TLKeyboardEventName = 'key_down' | 'key_up' | 'key_repeat'\n\n/** @public */\nexport type TLEventName =\n\t| TLPointerEventName\n\t| TLCLickEventName\n\t| TLPinchEventName\n\t| TLKeyboardEventName\n\t| 'wheel'\n\t| 'cancel'\n\t| 'complete'\n\t| 'interrupt'\n\t| 'tick'\n\n/** @public */\nexport interface TLBaseEventInfo {\n\ttype: UiEventType\n\tshiftKey: boolean\n\taltKey: boolean\n\tctrlKey: boolean\n\tmetaKey: boolean\n\taccelKey: boolean\n}\n\n/** @public */\nexport type TLPointerEventInfo = TLBaseEventInfo & {\n\ttype: 'pointer'\n\tname: TLPointerEventName\n\t// The pointer position in client space, i.e. clientX / clientY\n\tpoint: VecLike\n\tpointerId: number\n\tbutton: number\n\tisPen: boolean\n} & TLPointerEventTarget\n\n/** @public */\nexport type TLClickEventInfo = TLBaseEventInfo & {\n\ttype: 'click'\n\tname: TLCLickEventName\n\tpoint: VecLike\n\tpointerId: number\n\tbutton: number\n\tphase: 'down' | 'up' | 'settle'\n} & TLPointerEventTarget\n\n/** @public */\nexport type TLKeyboardEventInfo = TLBaseEventInfo & {\n\ttype: 'keyboard'\n\tname: TLKeyboardEventName\n\tkey: string\n\tcode: string\n}\n\n/** @public */\nexport type TLPinchEventInfo = TLBaseEventInfo & {\n\ttype: 'pinch'\n\tname: TLPinchEventName\n\tpoint: VecModel\n\tdelta: VecModel\n}\n\n/** @public */\nexport type TLWheelEventInfo = TLBaseEventInfo & {\n\ttype: 'wheel'\n\tname: 'wheel'\n\tdelta: VecModel\n\tpoint: VecModel\n}\n\n/** @public */\nexport interface TLCancelEventInfo {\n\ttype: 'misc'\n\tname: 'cancel'\n}\n/** @public */\nexport interface TLCompleteEventInfo {\n\ttype: 'misc'\n\tname: 'complete'\n}\n/** @public */\nexport interface TLInterruptEventInfo {\n\ttype: 'misc'\n\tname: 'interrupt'\n}\n/** @public */\nexport interface TLTickEventInfo {\n\ttype: 'misc'\n\tname: 'tick'\n\telapsed: number\n}\n\n/** @public */\nexport type TLEventInfo =\n\t| TLPointerEventInfo\n\t| TLClickEventInfo\n\t| TLKeyboardEventInfo\n\t| TLPinchEventInfo\n\t| TLWheelEventInfo\n\t| TLCancelEventInfo\n\t| TLCompleteEventInfo\n\t| TLInterruptEventInfo\n\t| TLTickEventInfo\n\n/** @public */\nexport type TLPointerEvent = (info: TLPointerEventInfo) => void\n/** @public */\nexport type TLClickEvent = (info: TLClickEventInfo) => void\n/** @public */\nexport type TLKeyboardEvent = (info: TLKeyboardEventInfo) => void\n/** @public */\nexport type TLPinchEvent = (info: TLPinchEventInfo) => void\n/** @public */\nexport type TLWheelEvent = (info: TLWheelEventInfo) => void\n/** @public */\nexport type TLCancelEvent = (info: TLCancelEventInfo) => void\n/** @public */\nexport type TLCompleteEvent = (info: TLCompleteEventInfo) => void\n/** @public */\nexport type TLInterruptEvent = (info: TLInterruptEventInfo) => void\n/** @public */\nexport type TLTickEvent = (info: TLTickEventInfo) => void\n\n/** @public */\nexport type UiEvent =\n\t| TLPointerEvent\n\t| TLClickEvent\n\t| TLKeyboardEvent\n\t| TLPinchEvent\n\t| TLCancelEvent\n\t| TLCompleteEvent\n\n/** @public */\nexport type TLEnterEventHandler = (info: any, from: string) => void\n/** @public */\nexport type TLExitEventHandler = (info: any, to: string) => void\n\n/** @public */\nexport interface TLEventHandlers {\n\tonPointerDown: TLPointerEvent\n\tonPointerMove: TLPointerEvent\n\tonLongPress: TLPointerEvent\n\tonRightClick: TLPointerEvent\n\tonDoubleClick: TLClickEvent\n\tonTripleClick: TLClickEvent\n\tonQuadrupleClick: TLClickEvent\n\tonMiddleClick: TLPointerEvent\n\tonPointerUp: TLPointerEvent\n\tonKeyDown: TLKeyboardEvent\n\tonKeyUp: TLKeyboardEvent\n\tonKeyRepeat: TLKeyboardEvent\n\tonWheel: TLWheelEvent\n\tonCancel: TLCancelEvent\n\tonComplete: TLCompleteEvent\n\tonInterrupt: TLInterruptEvent\n\tonTick: TLTickEvent\n}\n\n/** @public */\nexport const EVENT_NAME_MAP: Record<\n\tExclude<TLEventName, TLPinchEventName>,\n\tkeyof TLEventHandlers\n> = {\n\twheel: 'onWheel',\n\tpointer_down: 'onPointerDown',\n\tpointer_move: 'onPointerMove',\n\tlong_press: 'onLongPress',\n\tpointer_up: 'onPointerUp',\n\tright_click: 'onRightClick',\n\tmiddle_click: 'onMiddleClick',\n\tkey_down: 'onKeyDown',\n\tkey_up: 'onKeyUp',\n\tkey_repeat: 'onKeyRepeat',\n\tcancel: 'onCancel',\n\tcomplete: 'onComplete',\n\tinterrupt: 'onInterrupt',\n\tdouble_click: 'onDoubleClick',\n\ttriple_click: 'onTripleClick',\n\tquadruple_click: 'onQuadrupleClick',\n\ttick: 'onTick',\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4LO,MAAM,iBAGT;AAAA,EACH,OAAO;AAAA,EACP,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,MAAM;AACP;",
4
+ "sourcesContent": ["import { TLHandle, TLShape, VecModel } from '@tldraw/tlschema'\nimport { VecLike } from '../../primitives/Vec'\nimport { TLOverlay } from '../overlays/OverlayUtil'\nimport { TLSelectionHandle } from './selection-types'\n\n/** @public */\nexport type UiEventType = 'pointer' | 'click' | 'keyboard' | 'wheel' | 'pinch' | 'zoom'\n\n/** @public */\nexport type TLPointerEventTarget =\n\t| { target: 'canvas'; shape?: undefined }\n\t| { target: 'selection'; handle?: TLSelectionHandle; shape?: undefined }\n\t| { target: 'shape'; shape: TLShape }\n\t| { target: 'handle'; shape: TLShape; handle: TLHandle }\n\t| { target: 'overlay'; overlay: TLOverlay; shape?: undefined }\n\n/** @public */\nexport type TLPointerEventName =\n\t| 'pointer_down'\n\t| 'pointer_move'\n\t| 'long_press'\n\t| 'pointer_up'\n\t| 'right_click'\n\t| 'middle_click'\n\n/** @public */\nexport type TLCLickEventName = 'double_click' | 'triple_click' | 'quadruple_click'\n\n/** @public */\nexport type TLPinchEventName = 'pinch_start' | 'pinch' | 'pinch_end'\n\n/** @public */\nexport type TLKeyboardEventName = 'key_down' | 'key_up' | 'key_repeat'\n\n/** @public */\nexport type TLEventName =\n\t| TLPointerEventName\n\t| TLCLickEventName\n\t| TLPinchEventName\n\t| TLKeyboardEventName\n\t| 'wheel'\n\t| 'cancel'\n\t| 'complete'\n\t| 'interrupt'\n\t| 'tick'\n\n/** @public */\nexport interface TLBaseEventInfo {\n\ttype: UiEventType\n\tshiftKey: boolean\n\taltKey: boolean\n\tctrlKey: boolean\n\tmetaKey: boolean\n\taccelKey: boolean\n}\n\n/** @public */\nexport type TLPointerEventInfo = TLBaseEventInfo & {\n\ttype: 'pointer'\n\tname: TLPointerEventName\n\t// The pointer position in client space, i.e. clientX / clientY\n\tpoint: VecLike\n\tpointerId: number\n\tbutton: number\n\tisPen: boolean\n} & TLPointerEventTarget\n\n/** @public */\nexport type TLClickEventInfo = TLBaseEventInfo & {\n\ttype: 'click'\n\tname: TLCLickEventName\n\tpoint: VecLike\n\tpointerId: number\n\tbutton: number\n\tphase: 'down' | 'up' | 'settle'\n} & TLPointerEventTarget\n\n/** @public */\nexport type TLKeyboardEventInfo = TLBaseEventInfo & {\n\ttype: 'keyboard'\n\tname: TLKeyboardEventName\n\tkey: string\n\tcode: string\n}\n\n/** @public */\nexport type TLPinchEventInfo = TLBaseEventInfo & {\n\ttype: 'pinch'\n\tname: TLPinchEventName\n\tpoint: VecModel\n\tdelta: VecModel\n}\n\n/** @public */\nexport type TLWheelEventInfo = TLBaseEventInfo & {\n\ttype: 'wheel'\n\tname: 'wheel'\n\tdelta: VecModel\n\tpoint: VecModel\n}\n\n/** @public */\nexport interface TLCancelEventInfo {\n\ttype: 'misc'\n\tname: 'cancel'\n}\n/** @public */\nexport interface TLCompleteEventInfo {\n\ttype: 'misc'\n\tname: 'complete'\n}\n/** @public */\nexport interface TLInterruptEventInfo {\n\ttype: 'misc'\n\tname: 'interrupt'\n}\n/** @public */\nexport interface TLTickEventInfo {\n\ttype: 'misc'\n\tname: 'tick'\n\telapsed: number\n}\n\n/** @public */\nexport type TLEventInfo =\n\t| TLPointerEventInfo\n\t| TLClickEventInfo\n\t| TLKeyboardEventInfo\n\t| TLPinchEventInfo\n\t| TLWheelEventInfo\n\t| TLCancelEventInfo\n\t| TLCompleteEventInfo\n\t| TLInterruptEventInfo\n\t| TLTickEventInfo\n\n/** @public */\nexport type TLPointerEvent = (info: TLPointerEventInfo) => void\n/** @public */\nexport type TLClickEvent = (info: TLClickEventInfo) => void\n/** @public */\nexport type TLKeyboardEvent = (info: TLKeyboardEventInfo) => void\n/** @public */\nexport type TLPinchEvent = (info: TLPinchEventInfo) => void\n/** @public */\nexport type TLWheelEvent = (info: TLWheelEventInfo) => void\n/** @public */\nexport type TLCancelEvent = (info: TLCancelEventInfo) => void\n/** @public */\nexport type TLCompleteEvent = (info: TLCompleteEventInfo) => void\n/** @public */\nexport type TLInterruptEvent = (info: TLInterruptEventInfo) => void\n/** @public */\nexport type TLTickEvent = (info: TLTickEventInfo) => void\n\n/** @public */\nexport type UiEvent =\n\t| TLPointerEvent\n\t| TLClickEvent\n\t| TLKeyboardEvent\n\t| TLPinchEvent\n\t| TLCancelEvent\n\t| TLCompleteEvent\n\n/** @public */\nexport type TLEnterEventHandler = (info: any, from: string) => void\n/** @public */\nexport type TLExitEventHandler = (info: any, to: string) => void\n\n/** @public */\nexport interface TLEventHandlers {\n\tonPointerDown: TLPointerEvent\n\tonPointerMove: TLPointerEvent\n\tonLongPress: TLPointerEvent\n\tonRightClick: TLPointerEvent\n\tonDoubleClick: TLClickEvent\n\tonTripleClick: TLClickEvent\n\tonQuadrupleClick: TLClickEvent\n\tonMiddleClick: TLPointerEvent\n\tonPointerUp: TLPointerEvent\n\tonKeyDown: TLKeyboardEvent\n\tonKeyUp: TLKeyboardEvent\n\tonKeyRepeat: TLKeyboardEvent\n\tonWheel: TLWheelEvent\n\tonCancel: TLCancelEvent\n\tonComplete: TLCompleteEvent\n\tonInterrupt: TLInterruptEvent\n\tonTick: TLTickEvent\n}\n\n/** @public */\nexport const EVENT_NAME_MAP: Record<\n\tExclude<TLEventName, TLPinchEventName>,\n\tkeyof TLEventHandlers\n> = {\n\twheel: 'onWheel',\n\tpointer_down: 'onPointerDown',\n\tpointer_move: 'onPointerMove',\n\tlong_press: 'onLongPress',\n\tpointer_up: 'onPointerUp',\n\tright_click: 'onRightClick',\n\tmiddle_click: 'onMiddleClick',\n\tkey_down: 'onKeyDown',\n\tkey_up: 'onKeyUp',\n\tkey_repeat: 'onKeyRepeat',\n\tcancel: 'onCancel',\n\tcomplete: 'onComplete',\n\tinterrupt: 'onInterrupt',\n\tdouble_click: 'onDoubleClick',\n\ttriple_click: 'onTripleClick',\n\tquadruple_click: 'onQuadrupleClick',\n\ttick: 'onTick',\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8LO,MAAM,iBAGT;AAAA,EACH,OAAO;AAAA,EACP,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,MAAM;AACP;",
6
6
  "names": []
7
7
  }
@@ -24,7 +24,7 @@ __export(fetchCache_exports, {
24
24
  module.exports = __toCommonJS(fetchCache_exports);
25
25
  var import_utils = require("@tldraw/utils");
26
26
  function fetchCache(cb, init) {
27
- const cache = /* @__PURE__ */ new Map();
27
+ const cache = new import_utils.LruCache(100);
28
28
  return async function fetchCached(url) {
29
29
  const existing = cache.get(url);
30
30
  if (existing) return existing;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/exports/fetchCache.ts"],
4
- "sourcesContent": ["import { FileHelpers, assert, fetch } from '@tldraw/utils'\n\n// TODO(alex): currently, this cache will grow unbounded. we should come up with a better strategy\n// for clearing items from the cache over time.\nexport function fetchCache<T>(cb: (response: Response) => Promise<T>, init?: RequestInit) {\n\tconst cache = new Map<string, Promise<T | null>>()\n\n\treturn async function fetchCached(url: string): Promise<T | null> {\n\t\tconst existing = cache.get(url)\n\t\tif (existing) return existing\n\n\t\tconst promise = (async () => {\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(url, init)\n\t\t\t\tassert(response.ok)\n\t\t\t\treturn await cb(response)\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err)\n\t\t\t\treturn null\n\t\t\t}\n\t\t})()\n\t\tcache.set(url, promise)\n\t\treturn promise\n\t}\n}\n\nexport const resourceToDataUrl = fetchCache(async (response) => {\n\treturn await FileHelpers.blobToDataUrl(await response.blob())\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA2C;AAIpC,SAAS,WAAc,IAAwC,MAAoB;AACzF,QAAM,QAAQ,oBAAI,IAA+B;AAEjD,SAAO,eAAe,YAAY,KAAgC;AACjE,UAAM,WAAW,MAAM,IAAI,GAAG;AAC9B,QAAI,SAAU,QAAO;AAErB,UAAM,WAAW,YAAY;AAC5B,UAAI;AACH,cAAM,WAAW,UAAM,oBAAM,KAAK,IAAI;AACtC,iCAAO,SAAS,EAAE;AAClB,eAAO,MAAM,GAAG,QAAQ;AAAA,MACzB,SAAS,KAAK;AACb,gBAAQ,MAAM,GAAG;AACjB,eAAO;AAAA,MACR;AAAA,IACD,GAAG;AACH,UAAM,IAAI,KAAK,OAAO;AACtB,WAAO;AAAA,EACR;AACD;AAEO,MAAM,oBAAoB,WAAW,OAAO,aAAa;AAC/D,SAAO,MAAM,yBAAY,cAAc,MAAM,SAAS,KAAK,CAAC;AAC7D,CAAC;",
4
+ "sourcesContent": ["import { FileHelpers, LruCache, assert, fetch } from '@tldraw/utils'\n\nexport function fetchCache<T>(cb: (response: Response) => Promise<T>, init?: RequestInit) {\n\tconst cache = new LruCache<string, Promise<T | null>>(100)\n\n\treturn async function fetchCached(url: string): Promise<T | null> {\n\t\tconst existing = cache.get(url)\n\t\tif (existing) return existing\n\n\t\tconst promise = (async () => {\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(url, init)\n\t\t\t\tassert(response.ok)\n\t\t\t\treturn await cb(response)\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err)\n\t\t\t\treturn null\n\t\t\t}\n\t\t})()\n\t\tcache.set(url, promise)\n\t\treturn promise\n\t}\n}\n\nexport const resourceToDataUrl = fetchCache(async (response) => {\n\treturn await FileHelpers.blobToDataUrl(await response.blob())\n})\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqD;AAE9C,SAAS,WAAc,IAAwC,MAAoB;AACzF,QAAM,QAAQ,IAAI,sBAAoC,GAAG;AAEzD,SAAO,eAAe,YAAY,KAAgC;AACjE,UAAM,WAAW,MAAM,IAAI,GAAG;AAC9B,QAAI,SAAU,QAAO;AAErB,UAAM,WAAW,YAAY;AAC5B,UAAI;AACH,cAAM,WAAW,UAAM,oBAAM,KAAK,IAAI;AACtC,iCAAO,SAAS,EAAE;AAClB,eAAO,MAAM,GAAG,QAAQ;AAAA,MACzB,SAAS,KAAK;AACb,gBAAQ,MAAM,GAAG;AACjB,eAAO;AAAA,MACR;AAAA,IACD,GAAG;AACH,UAAM,IAAI,KAAK,OAAO;AACtB,WAAO;AAAA,EACR;AACD;AAEO,MAAM,oBAAoB,WAAW,OAAO,aAAa;AAC/D,SAAO,MAAM,yBAAY,cAAc,MAAM,SAAS,KAAK,CAAC;AAC7D,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/EditorComponentsContext.tsx"],
4
- "sourcesContent": ["import { ComponentType, RefAttributes, createContext, useContext } from 'react'\nimport type { TLBrushProps } from '../components/default-components/DefaultBrush'\nimport type { TLCanvasComponentProps } from '../components/default-components/DefaultCanvas'\nimport type { TLCollaboratorHintProps } from '../components/default-components/DefaultCollaboratorHint'\nimport type { TLCursorProps } from '../components/default-components/DefaultCursor'\nimport type { TLErrorFallbackComponent } from '../components/default-components/DefaultErrorFallback'\nimport type { TLGridProps } from '../components/default-components/DefaultGrid'\nimport type { TLHandleProps } from '../components/default-components/DefaultHandle'\nimport type { TLHandlesProps } from '../components/default-components/DefaultHandles'\nimport type { TLScribbleProps } from '../components/default-components/DefaultScribble'\nimport type { TLSelectionBackgroundProps } from '../components/default-components/DefaultSelectionBackground'\nimport type { TLSelectionForegroundProps } from '../components/default-components/DefaultSelectionForeground'\nimport type { TLShapeErrorFallbackComponent } from '../components/default-components/DefaultShapeErrorFallback'\nimport type { TLShapeIndicatorProps } from '../components/default-components/DefaultShapeIndicator'\nimport type { TLShapeIndicatorErrorFallbackComponent } from '../components/default-components/DefaultShapeIndicatorErrorFallback'\nimport type { TLShapeWrapperProps } from '../components/default-components/DefaultShapeWrapper'\nimport type { TLSnapIndicatorProps } from '../components/default-components/DefaultSnapIndictor'\n\n/** @public */\nexport interface TLEditorComponents {\n\tBackground?: ComponentType | null\n\tBrush?: ComponentType<TLBrushProps> | null\n\tCanvas?: ComponentType<TLCanvasComponentProps> | null\n\tCollaboratorBrush?: ComponentType<TLBrushProps> | null\n\tCollaboratorCursor?: ComponentType<TLCursorProps> | null\n\tCollaboratorHint?: ComponentType<TLCollaboratorHintProps> | null\n\tCollaboratorScribble?: ComponentType<TLScribbleProps> | null\n\tCollaboratorShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null\n\tCursor?: ComponentType<TLCursorProps> | null\n\tGrid?: ComponentType<TLGridProps> | null\n\tHandle?: ComponentType<TLHandleProps> | null\n\tHandles?: ComponentType<TLHandlesProps> | null\n\tInFrontOfTheCanvas?: ComponentType | null\n\tLoadingScreen?: ComponentType | null\n\tOnTheCanvas?: ComponentType | null\n\tOverlays?: ComponentType | null\n\tScribble?: ComponentType<TLScribbleProps> | null\n\tSelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null\n\tSelectionForeground?: ComponentType<TLSelectionForegroundProps> | null\n\tShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null\n\tShapeIndicators?: ComponentType | null\n\tShapeWrapper?: ComponentType<TLShapeWrapperProps & RefAttributes<HTMLDivElement>> | null\n\tSnapIndicator?: ComponentType<TLSnapIndicatorProps> | null\n\tSpinner?: ComponentType<React.SVGProps<SVGSVGElement>> | null\n\tSvgDefs?: ComponentType | null\n\tZoomBrush?: ComponentType<TLBrushProps> | null\n\n\t// These will always have defaults\n\tErrorFallback?: TLErrorFallbackComponent\n\tShapeErrorFallback?: TLShapeErrorFallbackComponent\n\tShapeIndicatorErrorFallback?: TLShapeIndicatorErrorFallbackComponent\n}\n\nexport const EditorComponentsContext = createContext<null | Required<TLEditorComponents>>(null)\n\n/** @public */\nexport function useEditorComponents() {\n\tconst components = useContext(EditorComponentsContext)\n\tif (!components) {\n\t\tthrow new Error('useEditorComponents must be used inside of <EditorComponentsProvider />')\n\t}\n\treturn components\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwE;AAqDjE,MAAM,8BAA0B,4BAAmD,IAAI;AAGvF,SAAS,sBAAsB;AACrC,QAAM,iBAAa,yBAAW,uBAAuB;AACrD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC1F;AACA,SAAO;AACR;",
4
+ "sourcesContent": ["import { ComponentType, RefAttributes, createContext, useContext } from 'react'\nimport type { TLCanvasComponentProps } from '../components/default-components/DefaultCanvas'\nimport type { TLErrorFallbackComponent } from '../components/default-components/DefaultErrorFallback'\nimport type { TLGridProps } from '../components/default-components/DefaultGrid'\nimport type { TLSelectionBackgroundProps } from '../components/default-components/DefaultSelectionBackground'\nimport type { TLShapeErrorFallbackComponent } from '../components/default-components/DefaultShapeErrorFallback'\nimport type { TLShapeWrapperProps } from '../components/default-components/DefaultShapeWrapper'\n\n/** @public */\nexport interface TLEditorComponents {\n\tBackground?: ComponentType | null\n\tCanvas?: ComponentType<TLCanvasComponentProps> | null\n\tGrid?: ComponentType<TLGridProps> | null\n\tInFrontOfTheCanvas?: ComponentType | null\n\tLoadingScreen?: ComponentType | null\n\tOnTheCanvas?: ComponentType | null\n\tSelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null\n\tShapeWrapper?: ComponentType<TLShapeWrapperProps & RefAttributes<HTMLDivElement>> | null\n\tSpinner?: ComponentType<React.SVGProps<SVGSVGElement>> | null\n\tSvgDefs?: ComponentType | null\n\n\t// These will always have defaults\n\tErrorFallback?: TLErrorFallbackComponent\n\tShapeErrorFallback?: TLShapeErrorFallbackComponent\n}\n\nexport const EditorComponentsContext = createContext<null | Required<TLEditorComponents>>(null)\n\n/** @public */\nexport function useEditorComponents() {\n\tconst components = useContext(EditorComponentsContext)\n\tif (!components) {\n\t\tthrow new Error('useEditorComponents must be used inside of <EditorComponentsProvider />')\n\t}\n\treturn components\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwE;AA0BjE,MAAM,8BAA0B,4BAAmD,IAAI;AAGvF,SAAS,sBAAsB;AACrC,QAAM,iBAAa,yBAAW,uBAAuB;AACrD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC1F;AACA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -151,9 +151,9 @@ function useCanvasEvents() {
151
151
  }
152
152
  function onContextMenu(e) {
153
153
  if (!editor.options.rightClickPanning) return;
154
- if (e.nativeEvent.isTrusted) {
155
- (0, import_dom.preventDefault)(e);
156
- }
154
+ if (!e.nativeEvent.isTrusted) return;
155
+ if (e.button !== 2 || e.ctrlKey) return;
156
+ (0, import_dom.preventDefault)(e);
157
157
  }
158
158
  return {
159
159
  onPointerDown,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useCanvasEvents.ts"],
4
- "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport React, { useEffect, useMemo } from 'react'\nimport { tlenv } from '../globals/environment'\nimport {\n\telementShouldCaptureKeys,\n\tpreventDefault,\n\treleasePointerCapture,\n\tsetPointerCapture,\n} from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { useEditor } from './useEditor'\n\nexport function useCanvasEvents() {\n\tconst editor = useEditor()\n\tconst ownerDocument = editor.getContainerDocument()\n\tconst currentTool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tconst events = useMemo(\n\t\tfunction canvasEvents() {\n\t\t\tfunction onPointerDown(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\n\t\t\t\t// With right-click panning disabled, fire right_click on press and let the\n\t\t\t\t// native contextmenu through so the menu opens at the pointer-down location.\n\t\t\t\tif (e.button === 2 && !editor.options.rightClickPanning) {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\tname: 'right_click',\n\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tsetPointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfunction onPointerUp(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tconst rightClickPanning = editor.options.rightClickPanning\n\t\t\t\t// Check before dispatch (which resets isPanning)\n\t\t\t\tconst wasRightClickPanning =\n\t\t\t\t\trightClickPanning && e.button === 2 && editor.inputs.getIsPanning()\n\n\t\t\t\treleasePointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_up',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\n\t\t\t\t// Static right-click: fire contextmenu at the pointer-up location\n\t\t\t\tif (rightClickPanning && e.button === 2 && !wasRightClickPanning) {\n\t\t\t\t\tconst contextMenuEvent = new PointerEvent('contextmenu', {\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t})\n\t\t\t\t\te.currentTarget.dispatchEvent(contextMenuEvent)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onPointerEnter(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? true : null })\n\t\t\t}\n\n\t\t\tfunction onPointerLeave(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? false : null })\n\t\t\t}\n\n\t\t\tfunction onTouchStart(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tfunction onTouchEnd(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tif (!(e.target instanceof editor.getContainerWindow().HTMLElement)) return\n\n\t\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\t\tif (\n\t\t\t\t\t// if the target is not inside the editing shape\n\t\t\t\t\t!(editingShapeId && e.target.closest(`[data-shape-id=\"${editingShapeId}\"]`)) &&\n\t\t\t\t\t// and the target is not an clickable element\n\t\t\t\t\te.target.tagName !== 'A' &&\n\t\t\t\t\t// and the target is not an editable element\n\t\t\t\t\t!elementShouldCaptureKeys(e.target, false)\n\t\t\t\t) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onDragOver(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tasync function onDrop(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t\te.stopPropagation()\n\n\t\t\t\tconst pagePoint = editor.screenToPage({ x: e.clientX, y: e.clientY })\n\n\t\t\t\t// Call the custom onDropOnCanvas callback if provided\n\t\t\t\tif (editor.options.experimental__onDropOnCanvas) {\n\t\t\t\t\tconst handled = editor.options.experimental__onDropOnCanvas({\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t\tevent: e,\n\t\t\t\t\t})\n\t\t\t\t\tif (handled) return\n\t\t\t\t}\n\n\t\t\t\tif (e.dataTransfer?.files?.length) {\n\t\t\t\t\tconst files = Array.from(e.dataTransfer.files)\n\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'files',\n\t\t\t\t\t\tfiles,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst url = e.dataTransfer.getData('url')\n\t\t\t\tif (url) {\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'url',\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onClick(e: React.MouseEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\te.stopPropagation()\n\t\t\t}\n\n\t\t\tfunction onContextMenu(e: React.MouseEvent) {\n\t\t\t\t// With right-click panning disabled, let the native contextmenu through so the\n\t\t\t\t// menu opens on press.\n\t\t\t\tif (!editor.options.rightClickPanning) return\n\t\t\t\t// Synthetic events \u2014 our own dispatch from onPointerUp, or tests using\n\t\t\t\t// fireEvent.contextMenu \u2014 pass through so Radix can open the menu. The real\n\t\t\t\t// browser contextmenu is always suppressed: right-click behavior has\n\t\t\t\t// already been decided by our pointer handling (either we dispatched a\n\t\t\t\t// synthetic to open the menu at the release position, or we panned and\n\t\t\t\t// don't want a menu at all).\n\t\t\t\tif (e.nativeEvent.isTrusted) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tonPointerDown,\n\t\t\t\tonPointerUp,\n\t\t\t\tonPointerEnter,\n\t\t\t\tonPointerLeave,\n\t\t\t\tonDragOver,\n\t\t\t\tonDrop,\n\t\t\t\tonTouchStart,\n\t\t\t\tonTouchEnd,\n\t\t\t\tonClick,\n\t\t\t\tonContextMenu,\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t// onPointerMove is special: where we're only interested in the other events when they're\n\t// happening _on_ the canvas (as opposed to outside of it, or on UI floating over it), we want\n\t// the pointer position to be up to date regardless of whether it's over the tldraw canvas or\n\t// not. So instead of returning a listener to be attached to the canvas, we directly attach a\n\t// listener to the whole document instead.\n\tuseEffect(() => {\n\t\tlet lastX: number, lastY: number\n\n\t\tfunction onPointerMove(e: PointerEvent) {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (e.clientX === lastX && e.clientY === lastY) return\n\t\t\tlastX = e.clientX\n\t\t\tlastY = e.clientY\n\n\t\t\t// For tools that benefit from a higher fidelity of events,\n\t\t\t// we dispatch the coalesced events.\n\t\t\t// N.B. Sometimes getCoalescedEvents isn't present on iOS, ugh.\n\t\t\t// Specifically, in local mode (non-https) mode, iOS does not `useCoalescedEvents`\n\t\t\t// so it appears like the ink is working locally, when really it's just that `useCoalescedEvents`\n\t\t\t// is disabled. The intent here is to have `useCoalescedEvents` disabled for iOS.\n\t\t\tconst events =\n\t\t\t\t!tlenv.isIos && currentTool.useCoalescedEvents && e.getCoalescedEvents\n\t\t\t\t\t? e.getCoalescedEvents()\n\t\t\t\t\t: [e]\n\n\t\t\tfor (const singleEvent of events) {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t...getPointerInfo(editor, singleEvent),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\townerDocument.body.addEventListener('pointermove', onPointerMove)\n\t\treturn () => {\n\t\t\townerDocument.body.removeEventListener('pointermove', onPointerMove)\n\t\t}\n\t}, [editor, currentTool, ownerDocument])\n\n\treturn events\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useValue } from '@tldraw/state-react'\nimport React, { useEffect, useMemo } from 'react'\nimport { tlenv } from '../globals/environment'\nimport {\n\telementShouldCaptureKeys,\n\tpreventDefault,\n\treleasePointerCapture,\n\tsetPointerCapture,\n} from '../utils/dom'\nimport { getPointerInfo } from '../utils/getPointerInfo'\nimport { useEditor } from './useEditor'\n\nexport function useCanvasEvents() {\n\tconst editor = useEditor()\n\tconst ownerDocument = editor.getContainerDocument()\n\tconst currentTool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tconst events = useMemo(\n\t\tfunction canvasEvents() {\n\t\t\tfunction onPointerDown(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\n\t\t\t\t// With right-click panning disabled, fire right_click on press and let the\n\t\t\t\t// native contextmenu through so the menu opens at the pointer-down location.\n\t\t\t\tif (e.button === 2 && !editor.options.rightClickPanning) {\n\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\tname: 'right_click',\n\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tsetPointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tfunction onPointerUp(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return\n\n\t\t\t\tconst rightClickPanning = editor.options.rightClickPanning\n\t\t\t\t// Check before dispatch (which resets isPanning)\n\t\t\t\tconst wasRightClickPanning =\n\t\t\t\t\trightClickPanning && e.button === 2 && editor.inputs.getIsPanning()\n\n\t\t\t\treleasePointerCapture(e.currentTarget, e)\n\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_up',\n\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t})\n\n\t\t\t\t// Static right-click: fire contextmenu at the pointer-up location\n\t\t\t\tif (rightClickPanning && e.button === 2 && !wasRightClickPanning) {\n\t\t\t\t\tconst contextMenuEvent = new PointerEvent('contextmenu', {\n\t\t\t\t\t\tbubbles: true,\n\t\t\t\t\t\tclientX: e.clientX,\n\t\t\t\t\t\tclientY: e.clientY,\n\t\t\t\t\t\tbutton: 2,\n\t\t\t\t\t\tbuttons: 0,\n\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\tpointerType: e.pointerType,\n\t\t\t\t\t\tisPrimary: e.isPrimary,\n\t\t\t\t\t})\n\t\t\t\t\te.currentTarget.dispatchEvent(contextMenuEvent)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onPointerEnter(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? true : null })\n\t\t\t}\n\n\t\t\tfunction onPointerLeave(e: React.PointerEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tif (editor.getInstanceState().isPenMode && e.pointerType !== 'pen') return\n\t\t\t\tconst canHover = e.pointerType === 'mouse' || e.pointerType === 'pen'\n\t\t\t\teditor.updateInstanceState({ isHoveringCanvas: canHover ? false : null })\n\t\t\t}\n\n\t\t\tfunction onTouchStart(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tfunction onTouchEnd(e: React.TouchEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\teditor.markEventAsHandled(e)\n\t\t\t\tif (!(e.target instanceof editor.getContainerWindow().HTMLElement)) return\n\n\t\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\t\tif (\n\t\t\t\t\t// if the target is not inside the editing shape\n\t\t\t\t\t!(editingShapeId && e.target.closest(`[data-shape-id=\"${editingShapeId}\"]`)) &&\n\t\t\t\t\t// and the target is not an clickable element\n\t\t\t\t\te.target.tagName !== 'A' &&\n\t\t\t\t\t// and the target is not an editable element\n\t\t\t\t\t!elementShouldCaptureKeys(e.target, false)\n\t\t\t\t) {\n\t\t\t\t\tpreventDefault(e)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onDragOver(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\tasync function onDrop(e: React.DragEvent<Element>) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\tpreventDefault(e)\n\t\t\t\te.stopPropagation()\n\n\t\t\t\tconst pagePoint = editor.screenToPage({ x: e.clientX, y: e.clientY })\n\n\t\t\t\t// Call the custom onDropOnCanvas callback if provided\n\t\t\t\tif (editor.options.experimental__onDropOnCanvas) {\n\t\t\t\t\tconst handled = editor.options.experimental__onDropOnCanvas({\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t\tevent: e,\n\t\t\t\t\t})\n\t\t\t\t\tif (handled) return\n\t\t\t\t}\n\n\t\t\t\tif (e.dataTransfer?.files?.length) {\n\t\t\t\t\tconst files = Array.from(e.dataTransfer.files)\n\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'files',\n\t\t\t\t\t\tfiles,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst url = e.dataTransfer.getData('url')\n\t\t\t\tif (url) {\n\t\t\t\t\tawait editor.putExternalContent({\n\t\t\t\t\t\ttype: 'url',\n\t\t\t\t\t\turl,\n\t\t\t\t\t\tpoint: pagePoint,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onClick(e: React.MouseEvent) {\n\t\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\t\te.stopPropagation()\n\t\t\t}\n\n\t\t\tfunction onContextMenu(e: React.MouseEvent) {\n\t\t\t\t// With right-click panning disabled, let the native contextmenu through so the\n\t\t\t\t// menu opens on press.\n\t\t\t\tif (!editor.options.rightClickPanning) return\n\t\t\t\t// Synthetic events \u2014 our own dispatch from onPointerUp, or tests using\n\t\t\t\t// fireEvent.contextMenu \u2014 pass through so Radix can open the menu.\n\t\t\t\tif (!e.nativeEvent.isTrusted) return\n\t\t\t\t// Only suppress the native browser contextmenu when it follows a real\n\t\t\t\t// right-click (button=2 with no ctrl modifier). For those, our pointer\n\t\t\t\t// handling has already decided what to do (either we'll dispatch a\n\t\t\t\t// synthetic contextmenu on pointerup to open the menu at the release\n\t\t\t\t// position, or we panned and don't want a menu at all).\n\t\t\t\t//\n\t\t\t\t// Other contextmenu sources must reach Radix so the menu opens:\n\t\t\t\t// - ctrl+click on macOS (button=0, or button=2 with ctrlKey=true)\n\t\t\t\t// - long-press on touch devices (button=0, pointerType=touch)\n\t\t\t\tif (e.button !== 2 || e.ctrlKey) return\n\t\t\t\tpreventDefault(e)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tonPointerDown,\n\t\t\t\tonPointerUp,\n\t\t\t\tonPointerEnter,\n\t\t\t\tonPointerLeave,\n\t\t\t\tonDragOver,\n\t\t\t\tonDrop,\n\t\t\t\tonTouchStart,\n\t\t\t\tonTouchEnd,\n\t\t\t\tonClick,\n\t\t\t\tonContextMenu,\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t// onPointerMove is special: where we're only interested in the other events when they're\n\t// happening _on_ the canvas (as opposed to outside of it, or on UI floating over it), we want\n\t// the pointer position to be up to date regardless of whether it's over the tldraw canvas or\n\t// not. So instead of returning a listener to be attached to the canvas, we directly attach a\n\t// listener to the whole document instead.\n\tuseEffect(() => {\n\t\tlet lastX: number, lastY: number\n\n\t\tfunction onPointerMove(e: PointerEvent) {\n\t\t\tif (editor.wasEventAlreadyHandled(e)) return\n\t\t\teditor.markEventAsHandled(e)\n\n\t\t\tif (e.clientX === lastX && e.clientY === lastY) return\n\t\t\tlastX = e.clientX\n\t\t\tlastY = e.clientY\n\n\t\t\t// For tools that benefit from a higher fidelity of events,\n\t\t\t// we dispatch the coalesced events.\n\t\t\t// N.B. Sometimes getCoalescedEvents isn't present on iOS, ugh.\n\t\t\t// Specifically, in local mode (non-https) mode, iOS does not `useCoalescedEvents`\n\t\t\t// so it appears like the ink is working locally, when really it's just that `useCoalescedEvents`\n\t\t\t// is disabled. The intent here is to have `useCoalescedEvents` disabled for iOS.\n\t\t\tconst events =\n\t\t\t\t!tlenv.isIos && currentTool.useCoalescedEvents && e.getCoalescedEvents\n\t\t\t\t\t? e.getCoalescedEvents()\n\t\t\t\t\t: [e]\n\n\t\t\tfor (const singleEvent of events) {\n\t\t\t\teditor.dispatch({\n\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t...getPointerInfo(editor, singleEvent),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\townerDocument.body.addEventListener('pointermove', onPointerMove)\n\t\treturn () => {\n\t\t\townerDocument.body.removeEventListener('pointermove', onPointerMove)\n\t\t}\n\t}, [editor, currentTool, ownerDocument])\n\n\treturn events\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["events"]
7
7
  }
@@ -25,23 +25,12 @@ module.exports = __toCommonJS(useEditorComponents_exports);
25
25
  var import_jsx_runtime = require("react/jsx-runtime");
26
26
  var import_react = require("react");
27
27
  var import_DefaultBackground = require("../components/default-components/DefaultBackground");
28
- var import_DefaultBrush = require("../components/default-components/DefaultBrush");
29
28
  var import_DefaultCanvas = require("../components/default-components/DefaultCanvas");
30
- var import_DefaultCollaboratorHint = require("../components/default-components/DefaultCollaboratorHint");
31
- var import_DefaultCursor = require("../components/default-components/DefaultCursor");
32
29
  var import_DefaultErrorFallback = require("../components/default-components/DefaultErrorFallback");
33
30
  var import_DefaultGrid = require("../components/default-components/DefaultGrid");
34
- var import_DefaultHandle = require("../components/default-components/DefaultHandle");
35
- var import_DefaultHandles = require("../components/default-components/DefaultHandles");
36
31
  var import_DefaultLoadingScreen = require("../components/default-components/DefaultLoadingScreen");
37
- var import_DefaultScribble = require("../components/default-components/DefaultScribble");
38
- var import_DefaultSelectionForeground = require("../components/default-components/DefaultSelectionForeground");
39
32
  var import_DefaultShapeErrorFallback = require("../components/default-components/DefaultShapeErrorFallback");
40
- var import_DefaultShapeIndicator = require("../components/default-components/DefaultShapeIndicator");
41
- var import_DefaultShapeIndicatorErrorFallback = require("../components/default-components/DefaultShapeIndicatorErrorFallback");
42
- var import_DefaultShapeIndicators = require("../components/default-components/DefaultShapeIndicators");
43
33
  var import_DefaultShapeWrapper = require("../components/default-components/DefaultShapeWrapper");
44
- var import_DefaultSnapIndictor = require("../components/default-components/DefaultSnapIndictor");
45
34
  var import_DefaultSpinner = require("../components/default-components/DefaultSpinner");
46
35
  var import_DefaultSvgDefs = require("../components/default-components/DefaultSvgDefs");
47
36
  var import_EditorComponentsContext = require("./EditorComponentsContext");
@@ -55,34 +44,17 @@ function EditorComponentsProvider({
55
44
  const value = (0, import_react.useMemo)(
56
45
  () => ({
57
46
  Background: import_DefaultBackground.DefaultBackground,
58
- Brush: import_DefaultBrush.DefaultBrush,
59
47
  Canvas: import_DefaultCanvas.DefaultCanvas,
60
- CollaboratorBrush: import_DefaultBrush.DefaultBrush,
61
- CollaboratorCursor: import_DefaultCursor.DefaultCursor,
62
- CollaboratorHint: import_DefaultCollaboratorHint.DefaultCollaboratorHint,
63
- CollaboratorScribble: import_DefaultScribble.DefaultScribble,
64
- CollaboratorShapeIndicator: import_DefaultShapeIndicator.DefaultShapeIndicator,
65
- Cursor: import_DefaultCursor.DefaultCursor,
66
48
  Grid: import_DefaultGrid.DefaultGrid,
67
- Handle: import_DefaultHandle.DefaultHandle,
68
- Handles: import_DefaultHandles.DefaultHandles,
69
49
  InFrontOfTheCanvas: null,
70
50
  LoadingScreen: import_DefaultLoadingScreen.DefaultLoadingScreen,
71
51
  OnTheCanvas: null,
72
- Overlays: null,
73
- Scribble: import_DefaultScribble.DefaultScribble,
74
52
  SelectionBackground: null,
75
- SelectionForeground: import_DefaultSelectionForeground.DefaultSelectionForeground,
76
- ShapeIndicator: import_DefaultShapeIndicator.DefaultShapeIndicator,
77
- ShapeIndicators: import_DefaultShapeIndicators.DefaultShapeIndicators,
78
53
  ShapeWrapper: import_DefaultShapeWrapper.DefaultShapeWrapper,
79
- SnapIndicator: import_DefaultSnapIndictor.DefaultSnapIndicator,
80
54
  Spinner: import_DefaultSpinner.DefaultSpinner,
81
55
  SvgDefs: import_DefaultSvgDefs.DefaultSvgDefs,
82
- ZoomBrush: import_DefaultBrush.DefaultBrush,
83
56
  ErrorFallback: import_DefaultErrorFallback.DefaultErrorFallback,
84
57
  ShapeErrorFallback: import_DefaultShapeErrorFallback.DefaultShapeErrorFallback,
85
- ShapeIndicatorErrorFallback: import_DefaultShapeIndicatorErrorFallback.DefaultShapeIndicatorErrorFallback,
86
58
  ..._overrides
87
59
  }),
88
60
  [_overrides]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useEditorComponents.tsx"],
4
- "sourcesContent": ["import { ReactNode, useMemo } from 'react'\nimport { DefaultBackground } from '../components/default-components/DefaultBackground'\nimport { DefaultBrush } from '../components/default-components/DefaultBrush'\nimport { DefaultCanvas } from '../components/default-components/DefaultCanvas'\nimport { DefaultCollaboratorHint } from '../components/default-components/DefaultCollaboratorHint'\nimport { DefaultCursor } from '../components/default-components/DefaultCursor'\nimport { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'\nimport { DefaultGrid } from '../components/default-components/DefaultGrid'\nimport { DefaultHandle } from '../components/default-components/DefaultHandle'\nimport { DefaultHandles } from '../components/default-components/DefaultHandles'\nimport { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'\nimport { DefaultScribble } from '../components/default-components/DefaultScribble'\nimport { DefaultSelectionForeground } from '../components/default-components/DefaultSelectionForeground'\nimport { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'\nimport { DefaultShapeIndicator } from '../components/default-components/DefaultShapeIndicator'\nimport { DefaultShapeIndicatorErrorFallback } from '../components/default-components/DefaultShapeIndicatorErrorFallback'\nimport { DefaultShapeIndicators } from '../components/default-components/DefaultShapeIndicators'\nimport { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'\nimport { DefaultSnapIndicator } from '../components/default-components/DefaultSnapIndictor'\nimport { DefaultSpinner } from '../components/default-components/DefaultSpinner'\nimport { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'\nimport { EditorComponentsContext } from './EditorComponentsContext'\nimport type { TLEditorComponents } from './EditorComponentsContext'\nimport { useShallowObjectIdentity } from './useIdentity'\n\nexport { useEditorComponents } from './EditorComponentsContext'\nexport type { TLEditorComponents } from './EditorComponentsContext'\n\ninterface ComponentsContextProviderProps {\n\toverrides?: TLEditorComponents\n\tchildren: ReactNode\n}\n\nexport function EditorComponentsProvider({\n\toverrides = {},\n\tchildren,\n}: ComponentsContextProviderProps) {\n\tconst _overrides = useShallowObjectIdentity(overrides)\n\tconst value = useMemo(\n\t\t(): Required<TLEditorComponents> => ({\n\t\t\tBackground: DefaultBackground,\n\t\t\tBrush: DefaultBrush,\n\t\t\tCanvas: DefaultCanvas,\n\t\t\tCollaboratorBrush: DefaultBrush,\n\t\t\tCollaboratorCursor: DefaultCursor,\n\t\t\tCollaboratorHint: DefaultCollaboratorHint,\n\t\t\tCollaboratorScribble: DefaultScribble,\n\t\t\tCollaboratorShapeIndicator: DefaultShapeIndicator,\n\t\t\tCursor: DefaultCursor,\n\t\t\tGrid: DefaultGrid,\n\t\t\tHandle: DefaultHandle,\n\t\t\tHandles: DefaultHandles,\n\t\t\tInFrontOfTheCanvas: null,\n\t\t\tLoadingScreen: DefaultLoadingScreen,\n\t\t\tOnTheCanvas: null,\n\t\t\tOverlays: null,\n\t\t\tScribble: DefaultScribble,\n\t\t\tSelectionBackground: null,\n\t\t\tSelectionForeground: DefaultSelectionForeground,\n\t\t\tShapeIndicator: DefaultShapeIndicator,\n\t\t\tShapeIndicators: DefaultShapeIndicators,\n\t\t\tShapeWrapper: DefaultShapeWrapper,\n\t\t\tSnapIndicator: DefaultSnapIndicator,\n\t\t\tSpinner: DefaultSpinner,\n\t\t\tSvgDefs: DefaultSvgDefs,\n\t\t\tZoomBrush: DefaultBrush,\n\n\t\t\tErrorFallback: DefaultErrorFallback,\n\t\t\tShapeErrorFallback: DefaultShapeErrorFallback,\n\t\t\tShapeIndicatorErrorFallback: DefaultShapeIndicatorErrorFallback,\n\n\t\t\t..._overrides,\n\t\t}),\n\t\t[_overrides]\n\t)\n\n\treturn (\n\t\t<EditorComponentsContext.Provider value={value}>{children}</EditorComponentsContext.Provider>\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6EE;AA7EF,mBAAmC;AACnC,+BAAkC;AAClC,0BAA6B;AAC7B,2BAA8B;AAC9B,qCAAwC;AACxC,2BAA8B;AAC9B,kCAAqC;AACrC,yBAA4B;AAC5B,2BAA8B;AAC9B,4BAA+B;AAC/B,kCAAqC;AACrC,6BAAgC;AAChC,wCAA2C;AAC3C,uCAA0C;AAC1C,mCAAsC;AACtC,gDAAmD;AACnD,oCAAuC;AACvC,iCAAoC;AACpC,iCAAqC;AACrC,4BAA+B;AAC/B,4BAA+B;AAC/B,qCAAwC;AAExC,yBAAyC;AAEzC,IAAAA,kCAAoC;AAQ7B,SAAS,yBAAyB;AAAA,EACxC,YAAY,CAAC;AAAA,EACb;AACD,GAAmC;AAClC,QAAM,iBAAa,6CAAyB,SAAS;AACrD,QAAM,YAAQ;AAAA,IACb,OAAqC;AAAA,MACpC,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB,sBAAsB;AAAA,MACtB,4BAA4B;AAAA,MAC5B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,eAAe;AAAA,MACf,SAAS;AAAA,MACT,SAAS;AAAA,MACT,WAAW;AAAA,MAEX,eAAe;AAAA,MACf,oBAAoB;AAAA,MACpB,6BAA6B;AAAA,MAE7B,GAAG;AAAA,IACJ;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,SACC,4CAAC,uDAAwB,UAAxB,EAAiC,OAAe,UAAS;AAE5D;",
4
+ "sourcesContent": ["import { ReactNode, useMemo } from 'react'\nimport { DefaultBackground } from '../components/default-components/DefaultBackground'\nimport { DefaultCanvas } from '../components/default-components/DefaultCanvas'\nimport { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'\nimport { DefaultGrid } from '../components/default-components/DefaultGrid'\nimport { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'\nimport { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'\nimport { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'\nimport { DefaultSpinner } from '../components/default-components/DefaultSpinner'\nimport { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'\nimport { EditorComponentsContext } from './EditorComponentsContext'\nimport type { TLEditorComponents } from './EditorComponentsContext'\nimport { useShallowObjectIdentity } from './useIdentity'\n\nexport { useEditorComponents } from './EditorComponentsContext'\nexport type { TLEditorComponents } from './EditorComponentsContext'\n\ninterface ComponentsContextProviderProps {\n\toverrides?: TLEditorComponents\n\tchildren: ReactNode\n}\n\nexport function EditorComponentsProvider({\n\toverrides = {},\n\tchildren,\n}: ComponentsContextProviderProps) {\n\tconst _overrides = useShallowObjectIdentity(overrides)\n\tconst value = useMemo(\n\t\t(): Required<TLEditorComponents> => ({\n\t\t\tBackground: DefaultBackground,\n\t\t\tCanvas: DefaultCanvas,\n\t\t\tGrid: DefaultGrid,\n\t\t\tInFrontOfTheCanvas: null,\n\t\t\tLoadingScreen: DefaultLoadingScreen,\n\t\t\tOnTheCanvas: null,\n\t\t\tSelectionBackground: null,\n\t\t\tShapeWrapper: DefaultShapeWrapper,\n\t\t\tSpinner: DefaultSpinner,\n\t\t\tSvgDefs: DefaultSvgDefs,\n\n\t\t\tErrorFallback: DefaultErrorFallback,\n\t\t\tShapeErrorFallback: DefaultShapeErrorFallback,\n\n\t\t\t..._overrides,\n\t\t}),\n\t\t[_overrides]\n\t)\n\n\treturn (\n\t\t<EditorComponentsContext.Provider value={value}>{children}</EditorComponentsContext.Provider>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiDE;AAjDF,mBAAmC;AACnC,+BAAkC;AAClC,2BAA8B;AAC9B,kCAAqC;AACrC,yBAA4B;AAC5B,kCAAqC;AACrC,uCAA0C;AAC1C,iCAAoC;AACpC,4BAA+B;AAC/B,4BAA+B;AAC/B,qCAAwC;AAExC,yBAAyC;AAEzC,IAAAA,kCAAoC;AAQ7B,SAAS,yBAAyB;AAAA,EACxC,YAAY,CAAC;AAAA,EACb;AACD,GAAmC;AAClC,QAAM,iBAAa,6CAAyB,SAAS;AACrD,QAAM,YAAQ;AAAA,IACb,OAAqC;AAAA,MACpC,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,qBAAqB;AAAA,MACrB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,SAAS;AAAA,MAET,eAAe;AAAA,MACf,oBAAoB;AAAA,MAEpB,GAAG;AAAA,IACJ;AAAA,IACA,CAAC,UAAU;AAAA,EACZ;AAEA,SACC,4CAAC,uDAAwB,UAAxB,EAAiC,OAAe,UAAS;AAE5D;",
6
6
  "names": ["import_EditorComponentsContext"]
7
7
  }
@@ -18,55 +18,20 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var usePeerIds_exports = {};
20
20
  __export(usePeerIds_exports, {
21
- useActivePeerIds$: () => useActivePeerIds$,
22
21
  usePeerIds: () => usePeerIds
23
22
  });
24
23
  module.exports = __toCommonJS(usePeerIds_exports);
25
24
  var import_state_react = require("@tldraw/state-react");
26
- var import_react = require("react");
27
- var import_collaboratorState = require("../utils/collaboratorState");
28
25
  var import_uniq = require("../utils/uniq");
29
26
  var import_useEditor = require("./useEditor");
30
- function setsEqual(a, b) {
31
- if (a.size !== b.size) return false;
32
- for (const item of a) {
33
- if (!b.has(item)) return false;
34
- }
35
- return true;
36
- }
37
27
  function usePeerIds() {
38
28
  const editor = (0, import_useEditor.useEditor)();
39
29
  const $userIds = (0, import_state_react.useComputed)(
40
30
  "userIds",
41
- () => (0, import_uniq.uniq)(editor.getCollaborators().map((p) => p.userId)).sort(),
31
+ () => (0, import_uniq.uniq)(editor.getVisibleCollaborators().map((p) => p.userId)).sort(),
42
32
  { isEqual: (a, b) => a.join(",") === b.join?.(",") },
43
33
  [editor]
44
34
  );
45
35
  return (0, import_state_react.useValue)($userIds);
46
36
  }
47
- function useActivePeerIds$() {
48
- const $time = (0, import_state_react.useAtom)("peerIdsTime", Date.now());
49
- const editor = (0, import_useEditor.useEditor)();
50
- (0, import_react.useEffect)(() => {
51
- const interval = editor.timers.setInterval(() => {
52
- $time.set(Date.now());
53
- }, editor.options.collaboratorCheckIntervalMs);
54
- return () => clearInterval(interval);
55
- }, [editor, $time]);
56
- return (0, import_state_react.useComputed)(
57
- "activePeerIds",
58
- () => {
59
- const now = $time.get();
60
- return new Set(
61
- editor.getCollaborators().filter((p) => {
62
- const elapsed = Math.max(0, now - (p.lastActivityTimestamp ?? Infinity));
63
- const state = (0, import_collaboratorState.getCollaboratorStateFromElapsedTime)(editor, elapsed);
64
- return (0, import_collaboratorState.shouldShowCollaborator)(editor, p, state);
65
- }).map((p) => p.userId)
66
- );
67
- },
68
- { isEqual: setsEqual },
69
- [editor]
70
- );
71
- }
72
37
  //# sourceMappingURL=usePeerIds.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/usePeerIds.ts"],
4
- "sourcesContent": ["import { useAtom, useComputed, useValue } from '@tldraw/state-react'\nimport { useEffect } from 'react'\nimport {\n\tgetCollaboratorStateFromElapsedTime,\n\tshouldShowCollaborator,\n} from '../utils/collaboratorState'\nimport { uniq } from '../utils/uniq'\nimport { useEditor } from './useEditor'\n\nfunction setsEqual<T>(a: Set<T>, b: Set<T>): boolean {\n\tif (a.size !== b.size) return false\n\tfor (const item of a) {\n\t\tif (!b.has(item)) return false\n\t}\n\treturn true\n}\n\n// TODO: maybe move this to a computed property on the App class?\n/**\n * @returns The list of peer UserIDs\n * @public\n */\nexport function usePeerIds() {\n\tconst editor = useEditor()\n\n\tconst $userIds = useComputed(\n\t\t'userIds',\n\t\t() => uniq(editor.getCollaborators().map((p) => p.userId)).sort(),\n\t\t{ isEqual: (a, b) => a.join(',') === b.join?.(',') },\n\t\t[editor]\n\t)\n\n\treturn useValue($userIds)\n}\n\n/**\n * Returns a computed signal of active peer user IDs that should be shown.\n * Automatically re-evaluates on an interval to handle time-based state transitions\n * (active -> idle -> inactive).\n *\n * @returns A computed signal containing a Set of active peer user IDs\n * @internal\n */\nexport function useActivePeerIds$() {\n\tconst $time = useAtom('peerIdsTime', Date.now())\n\tconst editor = useEditor()\n\tuseEffect(() => {\n\t\tconst interval = editor.timers.setInterval(() => {\n\t\t\t$time.set(Date.now())\n\t\t}, editor.options.collaboratorCheckIntervalMs)\n\n\t\treturn () => clearInterval(interval)\n\t}, [editor, $time])\n\n\treturn useComputed(\n\t\t'activePeerIds',\n\t\t() => {\n\t\t\tconst now = $time.get()\n\t\t\treturn new Set(\n\t\t\t\teditor\n\t\t\t\t\t.getCollaborators()\n\t\t\t\t\t.filter((p) => {\n\t\t\t\t\t\tconst elapsed = Math.max(0, now - (p.lastActivityTimestamp ?? Infinity))\n\t\t\t\t\t\tconst state = getCollaboratorStateFromElapsedTime(editor, elapsed)\n\t\t\t\t\t\treturn shouldShowCollaborator(editor, p, state)\n\t\t\t\t\t})\n\t\t\t\t\t.map((p) => p.userId)\n\t\t\t)\n\t\t},\n\t\t{ isEqual: setsEqual },\n\t\t[editor]\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA+C;AAC/C,mBAA0B;AAC1B,+BAGO;AACP,kBAAqB;AACrB,uBAA0B;AAE1B,SAAS,UAAa,GAAW,GAAoB;AACpD,MAAI,EAAE,SAAS,EAAE,KAAM,QAAO;AAC9B,aAAW,QAAQ,GAAG;AACrB,QAAI,CAAC,EAAE,IAAI,IAAI,EAAG,QAAO;AAAA,EAC1B;AACA,SAAO;AACR;AAOO,SAAS,aAAa;AAC5B,QAAM,aAAS,4BAAU;AAEzB,QAAM,eAAW;AAAA,IAChB;AAAA,IACA,UAAM,kBAAK,OAAO,iBAAiB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK;AAAA,IAChE,EAAE,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,OAAO,GAAG,EAAE;AAAA,IACnD,CAAC,MAAM;AAAA,EACR;AAEA,aAAO,6BAAS,QAAQ;AACzB;AAUO,SAAS,oBAAoB;AACnC,QAAM,YAAQ,4BAAQ,eAAe,KAAK,IAAI,CAAC;AAC/C,QAAM,aAAS,4BAAU;AACzB,8BAAU,MAAM;AACf,UAAM,WAAW,OAAO,OAAO,YAAY,MAAM;AAChD,YAAM,IAAI,KAAK,IAAI,CAAC;AAAA,IACrB,GAAG,OAAO,QAAQ,2BAA2B;AAE7C,WAAO,MAAM,cAAc,QAAQ;AAAA,EACpC,GAAG,CAAC,QAAQ,KAAK,CAAC;AAElB,aAAO;AAAA,IACN;AAAA,IACA,MAAM;AACL,YAAM,MAAM,MAAM,IAAI;AACtB,aAAO,IAAI;AAAA,QACV,OACE,iBAAiB,EACjB,OAAO,CAAC,MAAM;AACd,gBAAM,UAAU,KAAK,IAAI,GAAG,OAAO,EAAE,yBAAyB,SAAS;AACvE,gBAAM,YAAQ,8DAAoC,QAAQ,OAAO;AACjE,qBAAO,iDAAuB,QAAQ,GAAG,KAAK;AAAA,QAC/C,CAAC,EACA,IAAI,CAAC,MAAM,EAAE,MAAM;AAAA,MACtB;AAAA,IACD;AAAA,IACA,EAAE,SAAS,UAAU;AAAA,IACrB,CAAC,MAAM;AAAA,EACR;AACD;",
4
+ "sourcesContent": ["import { useComputed, useValue } from '@tldraw/state-react'\nimport { uniq } from '../utils/uniq'\nimport { useEditor } from './useEditor'\n\n/**\n * Reactive list of peer user IDs for collaborators currently shown in the UI.\n * Mirrors {@link Editor.getVisibleCollaborators} \u2014 peers fade out as they\n * transition to idle/inactive, without requiring a manual re-render.\n *\n * @returns The list of peer UserIDs\n * @public\n */\nexport function usePeerIds() {\n\tconst editor = useEditor()\n\n\tconst $userIds = useComputed(\n\t\t'userIds',\n\t\t() => uniq(editor.getVisibleCollaborators().map((p) => p.userId)).sort(),\n\t\t{ isEqual: (a, b) => a.join(',') === b.join?.(',') },\n\t\t[editor]\n\t)\n\n\treturn useValue($userIds)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAsC;AACtC,kBAAqB;AACrB,uBAA0B;AAUnB,SAAS,aAAa;AAC5B,QAAM,aAAS,4BAAU;AAEzB,QAAM,eAAW;AAAA,IAChB;AAAA,IACA,UAAM,kBAAK,OAAO,wBAAwB,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK;AAAA,IACvE,EAAE,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,OAAO,GAAG,EAAE;AAAA,IACnD,CAAC,MAAM;AAAA,EACR;AAEA,aAAO,6BAAS,QAAQ;AACzB;",
6
6
  "names": []
7
7
  }
@@ -45,8 +45,9 @@ function ShapeCullingProvider({ children }) {
45
45
  containersRef.current.delete(id);
46
46
  }, []);
47
47
  const updateCulling = (0, import_react.useCallback)((culledShapes) => {
48
+ let shouldBeCulled;
48
49
  for (const [id, entry] of containersRef.current) {
49
- const shouldBeCulled = culledShapes.has(id);
50
+ shouldBeCulled = culledShapes.has(id);
50
51
  if (shouldBeCulled !== entry.isCulled) {
51
52
  const display = shouldBeCulled ? "none" : "block";
52
53
  (0, import_dom.setStyleProperty)(entry.container, "display", display);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/hooks/useShapeCulling.tsx"],
4
- "sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { createContext, useCallback, useContext, useMemo, useRef } from 'react'\nimport { setStyleProperty } from '../utils/dom'\n\ninterface ShapeContainerEntry {\n\tcontainer: HTMLDivElement\n\tbgContainer: HTMLDivElement | null\n\tisCulled: boolean\n}\n\ninterface ShapeCullingContextValue {\n\tregister(\n\t\tid: TLShapeId,\n\t\tcontainer: HTMLDivElement,\n\t\tbgContainer: HTMLDivElement | null,\n\t\tisCulled: boolean\n\t): void\n\tunregister(id: TLShapeId): void\n\tupdateCulling(culledShapes: Set<TLShapeId>): void\n}\n\nconst ShapeCullingContext = createContext<ShapeCullingContextValue | null>(null)\n\n/** @internal */\nexport interface ShapeCullingProviderProps {\n\tchildren: React.ReactNode\n}\n\n/**\n * Provides centralized culling management for shape containers.\n * This allows a single reactor to update all shape display states\n * instead of each shape having its own subscription.\n *\n * @internal\n */\nexport function ShapeCullingProvider({ children }: ShapeCullingProviderProps) {\n\tconst containersRef = useRef(new Map<TLShapeId, ShapeContainerEntry>())\n\n\tconst register = useCallback(\n\t\t(\n\t\t\tid: TLShapeId,\n\t\t\tcontainer: HTMLDivElement,\n\t\t\tbgContainer: HTMLDivElement | null,\n\t\t\tisCulled: boolean\n\t\t) => {\n\t\t\tconst display = isCulled ? 'none' : 'block'\n\t\t\tsetStyleProperty(container, 'display', display)\n\t\t\tsetStyleProperty(bgContainer, 'display', display)\n\n\t\t\tcontainersRef.current.set(id, {\n\t\t\t\tcontainer,\n\t\t\t\tbgContainer,\n\t\t\t\tisCulled,\n\t\t\t})\n\t\t},\n\t\t[]\n\t)\n\n\tconst unregister = useCallback((id: TLShapeId) => {\n\t\tcontainersRef.current.delete(id)\n\t}, [])\n\n\tconst updateCulling = useCallback((culledShapes: Set<TLShapeId>) => {\n\t\tfor (const [id, entry] of containersRef.current) {\n\t\t\tconst shouldBeCulled = culledShapes.has(id)\n\t\t\tif (shouldBeCulled !== entry.isCulled) {\n\t\t\t\tconst display = shouldBeCulled ? 'none' : 'block'\n\t\t\t\tsetStyleProperty(entry.container, 'display', display)\n\t\t\t\tsetStyleProperty(entry.bgContainer, 'display', display)\n\t\t\t\tentry.isCulled = shouldBeCulled\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tregister,\n\t\t\tunregister,\n\t\t\tupdateCulling,\n\t\t}),\n\t\t[register, unregister, updateCulling]\n\t)\n\n\treturn <ShapeCullingContext.Provider value={value}>{children}</ShapeCullingContext.Provider>\n}\n\n/**\n * Hook to access the shape culling context for container registration.\n *\n * @internal\n */\nexport function useShapeCulling(): ShapeCullingContextValue {\n\tconst context = useContext(ShapeCullingContext)\n\tif (!context) {\n\t\tthrow new Error('useShapeCulling must be used within ShapeCullingProvider')\n\t}\n\treturn context\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmFQ;AAlFR,mBAAwE;AACxE,iBAAiC;AAmBjC,MAAM,0BAAsB,4BAA+C,IAAI;AAcxE,SAAS,qBAAqB,EAAE,SAAS,GAA8B;AAC7E,QAAM,oBAAgB,qBAAO,oBAAI,IAAoC,CAAC;AAEtE,QAAM,eAAW;AAAA,IAChB,CACC,IACA,WACA,aACA,aACI;AACJ,YAAM,UAAU,WAAW,SAAS;AACpC,uCAAiB,WAAW,WAAW,OAAO;AAC9C,uCAAiB,aAAa,WAAW,OAAO;AAEhD,oBAAc,QAAQ,IAAI,IAAI;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACF;AAEA,QAAM,iBAAa,0BAAY,CAAC,OAAkB;AACjD,kBAAc,QAAQ,OAAO,EAAE;AAAA,EAChC,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,0BAAY,CAAC,iBAAiC;AACnE,eAAW,CAAC,IAAI,KAAK,KAAK,cAAc,SAAS;AAChD,YAAM,iBAAiB,aAAa,IAAI,EAAE;AAC1C,UAAI,mBAAmB,MAAM,UAAU;AACtC,cAAM,UAAU,iBAAiB,SAAS;AAC1C,yCAAiB,MAAM,WAAW,WAAW,OAAO;AACpD,yCAAiB,MAAM,aAAa,WAAW,OAAO;AACtD,cAAM,WAAW;AAAA,MAClB;AAAA,IACD;AAAA,EACD,GAAG,CAAC,CAAC;AAEL,QAAM,YAAQ;AAAA,IACb,OAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,IACA,CAAC,UAAU,YAAY,aAAa;AAAA,EACrC;AAEA,SAAO,4CAAC,oBAAoB,UAApB,EAA6B,OAAe,UAAS;AAC9D;AAOO,SAAS,kBAA4C;AAC3D,QAAM,cAAU,yBAAW,mBAAmB;AAC9C,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC3E;AACA,SAAO;AACR;",
4
+ "sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { createContext, useCallback, useContext, useMemo, useRef } from 'react'\nimport { setStyleProperty } from '../utils/dom'\n\ninterface ShapeContainerEntry {\n\tcontainer: HTMLDivElement\n\tbgContainer: HTMLDivElement | null\n\tisCulled: boolean\n}\n\ninterface ShapeCullingContextValue {\n\tregister(\n\t\tid: TLShapeId,\n\t\tcontainer: HTMLDivElement,\n\t\tbgContainer: HTMLDivElement | null,\n\t\tisCulled: boolean\n\t): void\n\tunregister(id: TLShapeId): void\n\tupdateCulling(culledShapes: Set<TLShapeId>): void\n}\n\nconst ShapeCullingContext = createContext<ShapeCullingContextValue | null>(null)\n\n/** @internal */\nexport interface ShapeCullingProviderProps {\n\tchildren: React.ReactNode\n}\n\n/**\n * Provides centralized culling management for shape containers.\n * This allows a single reactor to update all shape display states\n * instead of each shape having its own subscription.\n *\n * @internal\n */\nexport function ShapeCullingProvider({ children }: ShapeCullingProviderProps) {\n\tconst containersRef = useRef(new Map<TLShapeId, ShapeContainerEntry>())\n\n\tconst register = useCallback(\n\t\t(\n\t\t\tid: TLShapeId,\n\t\t\tcontainer: HTMLDivElement,\n\t\t\tbgContainer: HTMLDivElement | null,\n\t\t\tisCulled: boolean\n\t\t) => {\n\t\t\tconst display = isCulled ? 'none' : 'block'\n\t\t\tsetStyleProperty(container, 'display', display)\n\t\t\tsetStyleProperty(bgContainer, 'display', display)\n\n\t\t\tcontainersRef.current.set(id, {\n\t\t\t\tcontainer,\n\t\t\t\tbgContainer,\n\t\t\t\tisCulled,\n\t\t\t})\n\t\t},\n\t\t[]\n\t)\n\n\tconst unregister = useCallback((id: TLShapeId) => {\n\t\tcontainersRef.current.delete(id)\n\t}, [])\n\n\tconst updateCulling = useCallback((culledShapes: Set<TLShapeId>) => {\n\t\tlet shouldBeCulled: boolean\n\n\t\tfor (const [id, entry] of containersRef.current) {\n\t\t\tshouldBeCulled = culledShapes.has(id)\n\t\t\tif (shouldBeCulled !== entry.isCulled) {\n\t\t\t\tconst display = shouldBeCulled ? 'none' : 'block'\n\t\t\t\tsetStyleProperty(entry.container, 'display', display)\n\t\t\t\tsetStyleProperty(entry.bgContainer, 'display', display)\n\t\t\t\tentry.isCulled = shouldBeCulled\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tregister,\n\t\t\tunregister,\n\t\t\tupdateCulling,\n\t\t}),\n\t\t[register, unregister, updateCulling]\n\t)\n\n\treturn <ShapeCullingContext.Provider value={value}>{children}</ShapeCullingContext.Provider>\n}\n\n/**\n * Hook to access the shape culling context for container registration.\n *\n * @internal\n */\nexport function useShapeCulling(): ShapeCullingContextValue {\n\tconst context = useContext(ShapeCullingContext)\n\tif (!context) {\n\t\tthrow new Error('useShapeCulling must be used within ShapeCullingProvider')\n\t}\n\treturn context\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqFQ;AApFR,mBAAwE;AACxE,iBAAiC;AAmBjC,MAAM,0BAAsB,4BAA+C,IAAI;AAcxE,SAAS,qBAAqB,EAAE,SAAS,GAA8B;AAC7E,QAAM,oBAAgB,qBAAO,oBAAI,IAAoC,CAAC;AAEtE,QAAM,eAAW;AAAA,IAChB,CACC,IACA,WACA,aACA,aACI;AACJ,YAAM,UAAU,WAAW,SAAS;AACpC,uCAAiB,WAAW,WAAW,OAAO;AAC9C,uCAAiB,aAAa,WAAW,OAAO;AAEhD,oBAAc,QAAQ,IAAI,IAAI;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACF;AAEA,QAAM,iBAAa,0BAAY,CAAC,OAAkB;AACjD,kBAAc,QAAQ,OAAO,EAAE;AAAA,EAChC,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,0BAAY,CAAC,iBAAiC;AACnE,QAAI;AAEJ,eAAW,CAAC,IAAI,KAAK,KAAK,cAAc,SAAS;AAChD,uBAAiB,aAAa,IAAI,EAAE;AACpC,UAAI,mBAAmB,MAAM,UAAU;AACtC,cAAM,UAAU,iBAAiB,SAAS;AAC1C,yCAAiB,MAAM,WAAW,WAAW,OAAO;AACpD,yCAAiB,MAAM,aAAa,WAAW,OAAO;AACtD,cAAM,WAAW;AAAA,MAClB;AAAA,IACD;AAAA,EACD,GAAG,CAAC,CAAC;AAEL,QAAM,YAAQ;AAAA,IACb,OAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,IACA,CAAC,UAAU,YAAY,aAAa;AAAA,EACrC;AAEA,SAAO,4CAAC,oBAAoB,UAApB,EAA6B,OAAe,UAAS;AAC9D;AAOO,SAAS,kBAA4C;AAC3D,QAAM,cAAU,yBAAW,mBAAmB;AAC9C,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC3E;AACA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -86,7 +86,6 @@ const defaultTldrawOptions = {
86
86
  camera: import_constants.DEFAULT_CAMERA_OPTIONS,
87
87
  text: {},
88
88
  deepLinks: void 0,
89
- useCanvasIndicators: true,
90
89
  quickZoomPreservesScreenBounds: true,
91
90
  onBeforeCopyToClipboard: void 0,
92
91
  onBeforePasteFromClipboard: void 0,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/options.ts"],
4
- "sourcesContent": ["import { Awaitable } from '@tldraw/utils'\nimport { ComponentType, Fragment } from 'react'\nimport { DEFAULT_CAMERA_OPTIONS } from './constants'\nimport type { Editor } from './editor/Editor'\nimport { TLContent } from './editor/types/clipboard-types'\nimport { TLExternalContent } from './editor/types/external-content'\nimport { TLCameraOptions } from './editor/types/misc-types'\nimport { VecLike } from './primitives/Vec'\nimport { TLDeepLinkOptions } from './utils/deepLinks'\nimport { TLTextOptions } from './utils/richText'\n\n/**\n * Identifies how a clipboard write was triggered (copy vs cut, keyboard vs menu).\n *\n * @public\n */\nexport interface TLClipboardWriteInfo {\n\treadonly operation: 'copy' | 'cut'\n\treadonly source: 'native' | 'menu'\n}\n\n/**\n * Raw clipboard paste payload, before tldraw parses clipboard contents into {@link TLExternalContent}.\n *\n * - `native-event`: from the `paste` event \u2014 `clipboardData` is available synchronously (unlike async\n * `navigator.clipboard.read()`).\n * - `clipboard-read`: from an explicit `navigator.clipboard.read()` call \u2014 only `ClipboardItem[]`\n * exists\n * (no `DataTransfer`).\n *\n * @public\n */\nexport type TLClipboardPasteRawInfo =\n\t| {\n\t\t\treadonly editor: Editor\n\t\t\treadonly source: 'native-event'\n\t\t\treadonly event: ClipboardEvent\n\t\t\treadonly clipboardData: DataTransfer | null\n\t\t\treadonly point: VecLike | undefined\n\t }\n\t| {\n\t\t\treadonly editor: Editor\n\t\t\treadonly source: 'clipboard-read'\n\t\t\treadonly clipboardItems: readonly ClipboardItem[]\n\t\t\treadonly point: VecLike | undefined\n\t }\n\n/**\n * Options for configuring tldraw. For defaults, see {@link defaultTldrawOptions}.\n *\n * @example\n * ```tsx\n * const options: Partial<TldrawOptions> = {\n * maxPages: 3,\n * maxShapesPerPage: 1000,\n * }\n *\n * function MyTldrawComponent() {\n * return <Tldraw options={options} />\n * }\n * ```\n *\n * @public\n */\nexport interface TldrawOptions {\n\treadonly maxShapesPerPage: number\n\treadonly maxFilesAtOnce: number\n\treadonly maxPages: number\n\treadonly animationMediumMs: number\n\treadonly followChaseViewportSnap: number\n\treadonly doubleClickDurationMs: number\n\treadonly multiClickDurationMs: number\n\treadonly coarseDragDistanceSquared: number\n\treadonly dragDistanceSquared: number\n\treadonly uiDragDistanceSquared: number\n\treadonly uiCoarseDragDistanceSquared: number\n\treadonly defaultSvgPadding: number\n\treadonly cameraSlideFriction: number\n\treadonly gridSteps: readonly {\n\t\treadonly min: number\n\t\treadonly mid: number\n\t\treadonly step: number\n\t}[]\n\treadonly collaboratorInactiveTimeoutMs: number\n\treadonly collaboratorIdleTimeoutMs: number\n\treadonly collaboratorCheckIntervalMs: number\n\treadonly cameraMovingTimeoutMs: number\n\treadonly hitTestMargin: number\n\treadonly edgeScrollDelay: number\n\treadonly edgeScrollEaseDuration: number\n\treadonly edgeScrollSpeed: number\n\treadonly edgeScrollDistance: number\n\treadonly coarsePointerWidth: number\n\treadonly coarseHandleRadius: number\n\treadonly handleRadius: number\n\treadonly longPressDurationMs: number\n\treadonly textShadowLod: number\n\treadonly adjacentShapeMargin: number\n\treadonly flattenImageBoundsExpand: number\n\treadonly flattenImageBoundsPadding: number\n\treadonly laserDelayMs: number\n\t/**\n\t * How long (in milliseconds) to fade all laser scribbles after the session ends.\n\t * The total points across all scribbles will be removed proportionally over this duration.\n\t * Defaults to 500ms (0.5 seconds).\n\t */\n\treadonly laserFadeoutMs: number\n\treadonly maxExportDelayMs: number\n\treadonly tooltipDelayMs: number\n\t/**\n\t * How long should previews created by {@link Editor.createTemporaryAssetPreview} last before\n\t * they expire? Defaults to 3 minutes.\n\t */\n\treadonly temporaryAssetPreviewLifetimeMs: number\n\treadonly actionShortcutsLocation: 'menu' | 'toolbar' | 'swap'\n\treadonly createTextOnCanvasDoubleClick: boolean\n\t/**\n\t * The react provider to use when exporting an image. This is useful if your shapes depend on\n\t * external context providers. By default, this is `React.Fragment`.\n\t */\n\treadonly exportProvider: ComponentType<{ children: React.ReactNode }>\n\t/**\n\t * By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.\n\t */\n\treadonly enableToolbarKeyboardShortcuts: boolean\n\t/**\n\t * The maximum number of fonts that will be loaded while blocking the main rendering of the\n\t * canvas. If there are more than this number of fonts needed, we'll just show the canvas right\n\t * away and let the fonts load in in the background.\n\t */\n\treadonly maxFontsToLoadBeforeRender: number\n\t/**\n\t * If you have a CSP policy that blocks inline styles, you can use this prop to provide a\n\t * nonce to use in the editor's styles.\n\t */\n\treadonly nonce: string | undefined\n\t/**\n\t * Branding name of the app, currently only used for adding aria-label for the application.\n\t */\n\treadonly branding?: string\n\t/**\n\t * Whether to use debounced zoom level for certain rendering optimizations. When true,\n\t * `editor.getEfficientZoomLevel()` returns a cached zoom value while the camera is moving,\n\t * reducing re-renders. When false, it always returns the current zoom level.\n\t */\n\treadonly debouncedZoom: boolean\n\t/**\n\t * The number of shapes that must be on the page for the debounced zoom level to be used.\n\t * Defaults to 500 shapes.\n\t */\n\treadonly debouncedZoomThreshold: number\n\t/**\n\t * Whether to allow spacebar panning. When true, the spacebar will pan the camera when held down.\n\t * When false, the spacebar will not pan the camera.\n\t */\n\treadonly spacebarPanning: boolean\n\t/**\n\t * Whether to allow right-click + drag to pan the camera. When true, right-click + drag pans the\n\t * camera and a static right-click opens the context menu at the release position. When false,\n\t * right-click opens the context menu on press (no drag-to-pan).\n\t */\n\treadonly rightClickPanning: boolean\n\t/**\n\t * The default padding (in pixels) used when zooming to fit content in the viewport.\n\t * This affects methods like `zoomToFit()`, `zoomToSelection()`, and `zoomToBounds()`.\n\t * The actual padding used is the minimum of this value and 28% of the viewport width.\n\t * Defaults to 128 pixels.\n\t */\n\treadonly zoomToFitPadding: number\n\t/**\n\t * The distance (in screen pixels) at which shapes snap to guides and other shapes.\n\t */\n\treadonly snapThreshold: number\n\t/**\n\t * Options for the editor's camera. These are the initial camera options.\n\t * Use {@link Editor.setCameraOptions} to update camera options at runtime.\n\t */\n\treadonly camera: Partial<TLCameraOptions>\n\t/**\n\t * Options for the editor's text rendering. These include TipTap configuration and\n\t * font handling. These are the initial text options and cannot be changed at runtime.\n\t */\n\treadonly text: TLTextOptions\n\t/**\n\t * Options for syncing the editor's camera state with the URL. Set to `true` to enable\n\t * with default options, or pass an options object to customize behavior.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Enable with defaults\n\t * <Tldraw options={{ deepLinks: true }} />\n\t *\n\t * // Enable with custom options\n\t * <Tldraw options={{ deepLinks: { param: 'd', debounceMs: 500 } }} />\n\t * ```\n\t */\n\treadonly deepLinks: true | TLDeepLinkOptions | undefined\n\t/**\n\t * Whether the quick-zoom brush preserves its screen-pixel size when the user\n\t * zooms the overview. When true, zooming in shrinks the target viewport (higher\n\t * return zoom); zooming out expands it. When false, the brush keeps the original\n\t * viewport's page dimensions regardless of overview zoom changes.\n\t */\n\treadonly quickZoomPreservesScreenBounds: boolean\n\t/**\n\t * Whether to use 2D canvas rendering for shape indicators. When true (default),\n\t * shapes that support it will render indicators on a 2D canvas for better\n\t * performance. When false, all indicators use legacy SVG rendering.\n\t */\n\treadonly useCanvasIndicators: boolean\n\t/**\n\t * Called before content is written to the clipboard during a copy or cut operation.\n\t * Receives the serialized content (shapes, bindings, assets) and can filter or transform\n\t * it before it reaches the clipboard.\n\t *\n\t * Return a modified `TLContent` object to change what is copied or cut. Return `false` to\n\t * cancel the clipboard write (for cut, the selected shapes are not removed). Return `void`\n\t * (or `undefined`) to pass through unchanged. You may return a `Promise` of those values if\n\t * the hook is async.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Filter out \"locked\" shapes from copy\n\t * onBeforeCopyToClipboard({ content, operation }) {\n\t * return {\n\t * ...content,\n\t * shapes: content.shapes.filter(s => !s.meta.locked),\n\t * rootShapeIds: content.rootShapeIds.filter(id =>\n\t * content.shapes.find(s => s.id === id && !s.meta.locked)\n\t * ),\n\t * }\n\t * }\n\t * ```\n\t */\n\tonBeforeCopyToClipboard?(\n\t\tinfo: { editor: Editor; content: TLContent } & TLClipboardWriteInfo\n\t): Awaitable<TLContent | false | void>\n\t/**\n\t * Called before pasted content is processed and shapes are created. Receives the parsed\n\t * external content from the clipboard and can filter, transform, or cancel it.\n\t *\n\t * Return `false` to cancel the paste. Return a modified content object to transform it.\n\t * Return `void` (or `undefined`) to pass through unchanged. You may return a `Promise` of\n\t * those values if the hook is async.\n\t *\n\t * This only fires for clipboard paste operations (keyboard shortcuts and menu actions),\n\t * not for file drops or programmatic `putExternalContent` calls.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Block pasting of image files\n\t * onBeforePasteFromClipboard({ content }) {\n\t * if (content.type === 'files') {\n\t * const nonImages = content.files.filter(f => !f.type.startsWith('image/'))\n\t * if (nonImages.length === 0) return false\n\t * return { ...content, files: nonImages }\n\t * }\n\t * }\n\t * ```\n\t */\n\tonBeforePasteFromClipboard?(info: {\n\t\teditor: Editor\n\t\tcontent: TLExternalContent<unknown>\n\t\tsource: 'native-event' | 'clipboard-read'\n\t\tpoint?: VecLike\n\t}): Awaitable<TLExternalContent<unknown> | false | void>\n\t/**\n\t * Called first for keyboard and menu paste, **before** tldraw handles or parses clipboard data\n\t * (and before {@link TldrawOptions.onBeforePasteFromClipboard}).\n\t *\n\t * Return `false` to cancel tldraw's default paste handling for this gesture (same convention as\n\t * {@link TldrawOptions.onBeforePasteFromClipboard}). Use this when you handle paste yourself from\n\t * raw clipboard data, or to block the gesture entirely. Return `void` (or `undefined`) to continue.\n\t */\n\tonClipboardPasteRaw?(info: TLClipboardPasteRawInfo): false | void\n\t/**\n\t * Called when content is dropped on the canvas. Provides the page position\n\t * where the drop occurred and the underlying drag event object.\n\t * Return true to prevent default drop handling (files, URLs, etc.)\n\t */\n\texperimental__onDropOnCanvas?(options: {\n\t\tpoint: VecLike\n\t\tevent: React.DragEvent<Element>\n\t}): boolean\n}\n\n/** @public */\nexport const defaultTldrawOptions = {\n\tmaxShapesPerPage: 4000,\n\tmaxFilesAtOnce: 100,\n\tmaxPages: 40,\n\tanimationMediumMs: 320,\n\tfollowChaseViewportSnap: 2,\n\tdoubleClickDurationMs: 450,\n\tmultiClickDurationMs: 200,\n\tcoarseDragDistanceSquared: 36, // 6 squared\n\tdragDistanceSquared: 16, // 4 squared\n\tuiDragDistanceSquared: 16, // 4 squared\n\t// it's really easy to accidentally drag from the toolbar on mobile, so we use a much larger\n\t// threshold than usual here to try and prevent accidental drags.\n\tuiCoarseDragDistanceSquared: 625, // 25 squared\n\tdefaultSvgPadding: 32,\n\tcameraSlideFriction: 0.09,\n\tgridSteps: [\n\t\t{ min: -1, mid: 0.15, step: 64 },\n\t\t{ min: 0.05, mid: 0.375, step: 16 },\n\t\t{ min: 0.15, mid: 1, step: 4 },\n\t\t{ min: 0.7, mid: 2.5, step: 1 },\n\t],\n\tcollaboratorInactiveTimeoutMs: 60000,\n\tcollaboratorIdleTimeoutMs: 3000,\n\tcollaboratorCheckIntervalMs: 1200,\n\tcameraMovingTimeoutMs: 64,\n\thitTestMargin: 8,\n\tedgeScrollDelay: 200,\n\tedgeScrollEaseDuration: 200,\n\tedgeScrollSpeed: 25,\n\tedgeScrollDistance: 8,\n\tcoarsePointerWidth: 12,\n\tcoarseHandleRadius: 20,\n\thandleRadius: 12,\n\tlongPressDurationMs: 500,\n\ttextShadowLod: 0.35,\n\tadjacentShapeMargin: 10,\n\tflattenImageBoundsExpand: 64,\n\tflattenImageBoundsPadding: 16,\n\tlaserDelayMs: 1200,\n\tlaserFadeoutMs: 500,\n\tmaxExportDelayMs: 5000,\n\ttooltipDelayMs: 700,\n\ttemporaryAssetPreviewLifetimeMs: 180000,\n\tactionShortcutsLocation: 'swap',\n\tcreateTextOnCanvasDoubleClick: true,\n\texportProvider: Fragment,\n\tenableToolbarKeyboardShortcuts: true,\n\tmaxFontsToLoadBeforeRender: Infinity,\n\tnonce: undefined,\n\tdebouncedZoom: true,\n\tdebouncedZoomThreshold: 500,\n\tspacebarPanning: true,\n\trightClickPanning: true,\n\tzoomToFitPadding: 128,\n\tsnapThreshold: 8,\n\tcamera: DEFAULT_CAMERA_OPTIONS,\n\ttext: {},\n\tdeepLinks: undefined,\n\tuseCanvasIndicators: true,\n\tquickZoomPreservesScreenBounds: true,\n\tonBeforeCopyToClipboard: undefined,\n\tonBeforePasteFromClipboard: undefined,\n\tonClipboardPasteRaw: undefined,\n\texperimental__onDropOnCanvas: undefined,\n} as const satisfies TldrawOptions\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAwC;AACxC,uBAAuC;AA6RhC,MAAM,uBAAuB;AAAA,EACnC,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,2BAA2B;AAAA;AAAA,EAC3B,qBAAqB;AAAA;AAAA,EACrB,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAGvB,6BAA6B;AAAA;AAAA,EAC7B,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,WAAW;AAAA,IACV,EAAE,KAAK,IAAI,KAAK,MAAM,MAAM,GAAG;AAAA,IAC/B,EAAE,KAAK,MAAM,KAAK,OAAO,MAAM,GAAG;AAAA,IAClC,EAAE,KAAK,MAAM,KAAK,GAAG,MAAM,EAAE;AAAA,IAC7B,EAAE,KAAK,KAAK,KAAK,KAAK,MAAM,EAAE;AAAA,EAC/B;AAAA,EACA,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,iCAAiC;AAAA,EACjC,yBAAyB;AAAA,EACzB,+BAA+B;AAAA,EAC/B,gBAAgB;AAAA,EAChB,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,OAAO;AAAA,EACP,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,MAAM,CAAC;AAAA,EACP,WAAW;AAAA,EACX,qBAAqB;AAAA,EACrB,gCAAgC;AAAA,EAChC,yBAAyB;AAAA,EACzB,4BAA4B;AAAA,EAC5B,qBAAqB;AAAA,EACrB,8BAA8B;AAC/B;",
4
+ "sourcesContent": ["import { Awaitable } from '@tldraw/utils'\nimport { ComponentType, Fragment } from 'react'\nimport { DEFAULT_CAMERA_OPTIONS } from './constants'\nimport type { Editor } from './editor/Editor'\nimport { TLContent } from './editor/types/clipboard-types'\nimport { TLExternalContent } from './editor/types/external-content'\nimport { TLCameraOptions } from './editor/types/misc-types'\nimport { VecLike } from './primitives/Vec'\nimport { TLDeepLinkOptions } from './utils/deepLinks'\nimport { TLTextOptions } from './utils/richText'\n\n/**\n * Identifies how a clipboard write was triggered (copy vs cut, keyboard vs menu).\n *\n * @public\n */\nexport interface TLClipboardWriteInfo {\n\treadonly operation: 'copy' | 'cut'\n\treadonly source: 'native' | 'menu'\n}\n\n/**\n * Raw clipboard paste payload, before tldraw parses clipboard contents into {@link TLExternalContent}.\n *\n * - `native-event`: from the `paste` event \u2014 `clipboardData` is available synchronously (unlike async\n * `navigator.clipboard.read()`).\n * - `clipboard-read`: from an explicit `navigator.clipboard.read()` call \u2014 only `ClipboardItem[]`\n * exists\n * (no `DataTransfer`).\n *\n * @public\n */\nexport type TLClipboardPasteRawInfo =\n\t| {\n\t\t\treadonly editor: Editor\n\t\t\treadonly source: 'native-event'\n\t\t\treadonly event: ClipboardEvent\n\t\t\treadonly clipboardData: DataTransfer | null\n\t\t\treadonly point: VecLike | undefined\n\t }\n\t| {\n\t\t\treadonly editor: Editor\n\t\t\treadonly source: 'clipboard-read'\n\t\t\treadonly clipboardItems: readonly ClipboardItem[]\n\t\t\treadonly point: VecLike | undefined\n\t }\n\n/**\n * Options for configuring tldraw. For defaults, see {@link defaultTldrawOptions}.\n *\n * @example\n * ```tsx\n * const options: Partial<TldrawOptions> = {\n * maxPages: 3,\n * maxShapesPerPage: 1000,\n * }\n *\n * function MyTldrawComponent() {\n * return <Tldraw options={options} />\n * }\n * ```\n *\n * @public\n */\nexport interface TldrawOptions {\n\treadonly maxShapesPerPage: number\n\treadonly maxFilesAtOnce: number\n\treadonly maxPages: number\n\treadonly animationMediumMs: number\n\treadonly followChaseViewportSnap: number\n\treadonly doubleClickDurationMs: number\n\treadonly multiClickDurationMs: number\n\treadonly coarseDragDistanceSquared: number\n\treadonly dragDistanceSquared: number\n\treadonly uiDragDistanceSquared: number\n\treadonly uiCoarseDragDistanceSquared: number\n\treadonly defaultSvgPadding: number\n\treadonly cameraSlideFriction: number\n\treadonly gridSteps: readonly {\n\t\treadonly min: number\n\t\treadonly mid: number\n\t\treadonly step: number\n\t}[]\n\treadonly collaboratorInactiveTimeoutMs: number\n\treadonly collaboratorIdleTimeoutMs: number\n\treadonly collaboratorCheckIntervalMs: number\n\treadonly cameraMovingTimeoutMs: number\n\treadonly hitTestMargin: number\n\treadonly edgeScrollDelay: number\n\treadonly edgeScrollEaseDuration: number\n\treadonly edgeScrollSpeed: number\n\treadonly edgeScrollDistance: number\n\treadonly coarsePointerWidth: number\n\treadonly coarseHandleRadius: number\n\treadonly handleRadius: number\n\treadonly longPressDurationMs: number\n\treadonly textShadowLod: number\n\treadonly adjacentShapeMargin: number\n\treadonly flattenImageBoundsExpand: number\n\treadonly flattenImageBoundsPadding: number\n\treadonly laserDelayMs: number\n\t/**\n\t * How long (in milliseconds) to fade all laser scribbles after the session ends.\n\t * The total points across all scribbles will be removed proportionally over this duration.\n\t * Defaults to 500ms (0.5 seconds).\n\t */\n\treadonly laserFadeoutMs: number\n\treadonly maxExportDelayMs: number\n\treadonly tooltipDelayMs: number\n\t/**\n\t * How long should previews created by {@link Editor.createTemporaryAssetPreview} last before\n\t * they expire? Defaults to 3 minutes.\n\t */\n\treadonly temporaryAssetPreviewLifetimeMs: number\n\treadonly actionShortcutsLocation: 'menu' | 'toolbar' | 'swap'\n\treadonly createTextOnCanvasDoubleClick: boolean\n\t/**\n\t * The react provider to use when exporting an image. This is useful if your shapes depend on\n\t * external context providers. By default, this is `React.Fragment`.\n\t */\n\treadonly exportProvider: ComponentType<{ children: React.ReactNode }>\n\t/**\n\t * By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.\n\t */\n\treadonly enableToolbarKeyboardShortcuts: boolean\n\t/**\n\t * The maximum number of fonts that will be loaded while blocking the main rendering of the\n\t * canvas. If there are more than this number of fonts needed, we'll just show the canvas right\n\t * away and let the fonts load in in the background.\n\t */\n\treadonly maxFontsToLoadBeforeRender: number\n\t/**\n\t * If you have a CSP policy that blocks inline styles, you can use this prop to provide a\n\t * nonce to use in the editor's styles.\n\t */\n\treadonly nonce: string | undefined\n\t/**\n\t * Branding name of the app, currently only used for adding aria-label for the application.\n\t */\n\treadonly branding?: string\n\t/**\n\t * Whether to use debounced zoom level for certain rendering optimizations. When true,\n\t * `editor.getEfficientZoomLevel()` returns a cached zoom value while the camera is moving,\n\t * reducing re-renders. When false, it always returns the current zoom level.\n\t */\n\treadonly debouncedZoom: boolean\n\t/**\n\t * The number of shapes that must be on the page for the debounced zoom level to be used.\n\t * Defaults to 500 shapes.\n\t */\n\treadonly debouncedZoomThreshold: number\n\t/**\n\t * Whether to allow spacebar panning. When true, the spacebar will pan the camera when held down.\n\t * When false, the spacebar will not pan the camera.\n\t */\n\treadonly spacebarPanning: boolean\n\t/**\n\t * Whether to allow right-click + drag to pan the camera. When true, right-click + drag pans the\n\t * camera and a static right-click opens the context menu at the release position. When false,\n\t * right-click opens the context menu on press (no drag-to-pan).\n\t */\n\treadonly rightClickPanning: boolean\n\t/**\n\t * The default padding (in pixels) used when zooming to fit content in the viewport.\n\t * This affects methods like `zoomToFit()`, `zoomToSelection()`, and `zoomToBounds()`.\n\t * The actual padding used is the minimum of this value and 28% of the viewport width.\n\t * Defaults to 128 pixels.\n\t */\n\treadonly zoomToFitPadding: number\n\t/**\n\t * The distance (in screen pixels) at which shapes snap to guides and other shapes.\n\t */\n\treadonly snapThreshold: number\n\t/**\n\t * Options for the editor's camera. These are the initial camera options.\n\t * Use {@link Editor.setCameraOptions} to update camera options at runtime.\n\t */\n\treadonly camera: Partial<TLCameraOptions>\n\t/**\n\t * Options for the editor's text rendering. These include TipTap configuration and\n\t * font handling. These are the initial text options and cannot be changed at runtime.\n\t */\n\treadonly text: TLTextOptions\n\t/**\n\t * Options for syncing the editor's camera state with the URL. Set to `true` to enable\n\t * with default options, or pass an options object to customize behavior.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Enable with defaults\n\t * <Tldraw options={{ deepLinks: true }} />\n\t *\n\t * // Enable with custom options\n\t * <Tldraw options={{ deepLinks: { param: 'd', debounceMs: 500 } }} />\n\t * ```\n\t */\n\treadonly deepLinks: true | TLDeepLinkOptions | undefined\n\t/**\n\t * Whether the quick-zoom brush preserves its screen-pixel size when the user\n\t * zooms the overview. When true, zooming in shrinks the target viewport (higher\n\t * return zoom); zooming out expands it. When false, the brush keeps the original\n\t * viewport's page dimensions regardless of overview zoom changes.\n\t */\n\treadonly quickZoomPreservesScreenBounds: boolean\n\t/**\n\t * Called before content is written to the clipboard during a copy or cut operation.\n\t * Receives the serialized content (shapes, bindings, assets) and can filter or transform\n\t * it before it reaches the clipboard.\n\t *\n\t * Return a modified `TLContent` object to change what is copied or cut. Return `false` to\n\t * cancel the clipboard write (for cut, the selected shapes are not removed). Return `void`\n\t * (or `undefined`) to pass through unchanged. You may return a `Promise` of those values if\n\t * the hook is async.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Filter out \"locked\" shapes from copy\n\t * onBeforeCopyToClipboard({ content, operation }) {\n\t * return {\n\t * ...content,\n\t * shapes: content.shapes.filter(s => !s.meta.locked),\n\t * rootShapeIds: content.rootShapeIds.filter(id =>\n\t * content.shapes.find(s => s.id === id && !s.meta.locked)\n\t * ),\n\t * }\n\t * }\n\t * ```\n\t */\n\tonBeforeCopyToClipboard?(\n\t\tinfo: { editor: Editor; content: TLContent } & TLClipboardWriteInfo\n\t): Awaitable<TLContent | false | void>\n\t/**\n\t * Called before pasted content is processed and shapes are created. Receives the parsed\n\t * external content from the clipboard and can filter, transform, or cancel it.\n\t *\n\t * Return `false` to cancel the paste. Return a modified content object to transform it.\n\t * Return `void` (or `undefined`) to pass through unchanged. You may return a `Promise` of\n\t * those values if the hook is async.\n\t *\n\t * This only fires for clipboard paste operations (keyboard shortcuts and menu actions),\n\t * not for file drops or programmatic `putExternalContent` calls.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Block pasting of image files\n\t * onBeforePasteFromClipboard({ content }) {\n\t * if (content.type === 'files') {\n\t * const nonImages = content.files.filter(f => !f.type.startsWith('image/'))\n\t * if (nonImages.length === 0) return false\n\t * return { ...content, files: nonImages }\n\t * }\n\t * }\n\t * ```\n\t */\n\tonBeforePasteFromClipboard?(info: {\n\t\teditor: Editor\n\t\tcontent: TLExternalContent<unknown>\n\t\tsource: 'native-event' | 'clipboard-read'\n\t\tpoint?: VecLike\n\t}): Awaitable<TLExternalContent<unknown> | false | void>\n\t/**\n\t * Called first for keyboard and menu paste, **before** tldraw handles or parses clipboard data\n\t * (and before {@link TldrawOptions.onBeforePasteFromClipboard}).\n\t *\n\t * Return `false` to cancel tldraw's default paste handling for this gesture (same convention as\n\t * {@link TldrawOptions.onBeforePasteFromClipboard}). Use this when you handle paste yourself from\n\t * raw clipboard data, or to block the gesture entirely. Return `void` (or `undefined`) to continue.\n\t */\n\tonClipboardPasteRaw?(info: TLClipboardPasteRawInfo): false | void\n\t/**\n\t * Called when content is dropped on the canvas. Provides the page position\n\t * where the drop occurred and the underlying drag event object.\n\t * Return true to prevent default drop handling (files, URLs, etc.)\n\t */\n\texperimental__onDropOnCanvas?(options: {\n\t\tpoint: VecLike\n\t\tevent: React.DragEvent<Element>\n\t}): boolean\n}\n\n/** @public */\nexport const defaultTldrawOptions = {\n\tmaxShapesPerPage: 4000,\n\tmaxFilesAtOnce: 100,\n\tmaxPages: 40,\n\tanimationMediumMs: 320,\n\tfollowChaseViewportSnap: 2,\n\tdoubleClickDurationMs: 450,\n\tmultiClickDurationMs: 200,\n\tcoarseDragDistanceSquared: 36, // 6 squared\n\tdragDistanceSquared: 16, // 4 squared\n\tuiDragDistanceSquared: 16, // 4 squared\n\t// it's really easy to accidentally drag from the toolbar on mobile, so we use a much larger\n\t// threshold than usual here to try and prevent accidental drags.\n\tuiCoarseDragDistanceSquared: 625, // 25 squared\n\tdefaultSvgPadding: 32,\n\tcameraSlideFriction: 0.09,\n\tgridSteps: [\n\t\t{ min: -1, mid: 0.15, step: 64 },\n\t\t{ min: 0.05, mid: 0.375, step: 16 },\n\t\t{ min: 0.15, mid: 1, step: 4 },\n\t\t{ min: 0.7, mid: 2.5, step: 1 },\n\t],\n\tcollaboratorInactiveTimeoutMs: 60000,\n\tcollaboratorIdleTimeoutMs: 3000,\n\tcollaboratorCheckIntervalMs: 1200,\n\tcameraMovingTimeoutMs: 64,\n\thitTestMargin: 8,\n\tedgeScrollDelay: 200,\n\tedgeScrollEaseDuration: 200,\n\tedgeScrollSpeed: 25,\n\tedgeScrollDistance: 8,\n\tcoarsePointerWidth: 12,\n\tcoarseHandleRadius: 20,\n\thandleRadius: 12,\n\tlongPressDurationMs: 500,\n\ttextShadowLod: 0.35,\n\tadjacentShapeMargin: 10,\n\tflattenImageBoundsExpand: 64,\n\tflattenImageBoundsPadding: 16,\n\tlaserDelayMs: 1200,\n\tlaserFadeoutMs: 500,\n\tmaxExportDelayMs: 5000,\n\ttooltipDelayMs: 700,\n\ttemporaryAssetPreviewLifetimeMs: 180000,\n\tactionShortcutsLocation: 'swap',\n\tcreateTextOnCanvasDoubleClick: true,\n\texportProvider: Fragment,\n\tenableToolbarKeyboardShortcuts: true,\n\tmaxFontsToLoadBeforeRender: Infinity,\n\tnonce: undefined,\n\tdebouncedZoom: true,\n\tdebouncedZoomThreshold: 500,\n\tspacebarPanning: true,\n\trightClickPanning: true,\n\tzoomToFitPadding: 128,\n\tsnapThreshold: 8,\n\tcamera: DEFAULT_CAMERA_OPTIONS,\n\ttext: {},\n\tdeepLinks: undefined,\n\tquickZoomPreservesScreenBounds: true,\n\tonBeforeCopyToClipboard: undefined,\n\tonBeforePasteFromClipboard: undefined,\n\tonClipboardPasteRaw: undefined,\n\texperimental__onDropOnCanvas: undefined,\n} as const satisfies TldrawOptions\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAwC;AACxC,uBAAuC;AAuRhC,MAAM,uBAAuB;AAAA,EACnC,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,2BAA2B;AAAA;AAAA,EAC3B,qBAAqB;AAAA;AAAA,EACrB,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAGvB,6BAA6B;AAAA;AAAA,EAC7B,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,WAAW;AAAA,IACV,EAAE,KAAK,IAAI,KAAK,MAAM,MAAM,GAAG;AAAA,IAC/B,EAAE,KAAK,MAAM,KAAK,OAAO,MAAM,GAAG;AAAA,IAClC,EAAE,KAAK,MAAM,KAAK,GAAG,MAAM,EAAE;AAAA,IAC7B,EAAE,KAAK,KAAK,KAAK,KAAK,MAAM,EAAE;AAAA,EAC/B;AAAA,EACA,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,iCAAiC;AAAA,EACjC,yBAAyB;AAAA,EACzB,+BAA+B;AAAA,EAC/B,gBAAgB;AAAA,EAChB,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,OAAO;AAAA,EACP,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,MAAM,CAAC;AAAA,EACP,WAAW;AAAA,EACX,gCAAgC;AAAA,EAChC,yBAAyB;AAAA,EACzB,4BAA4B;AAAA,EAC5B,qBAAqB;AAAA,EACrB,8BAA8B;AAC/B;",
6
6
  "names": []
7
7
  }
@@ -43,10 +43,16 @@ function kickoutOccludedShapes(editor, shapeIds, opts) {
43
43
  } else {
44
44
  const overlappingChildren = getOverlappingShapes(editor, parent.id, childIds);
45
45
  if (overlappingChildren.length < childIds.length) {
46
- parentsToLostChildren.set(
47
- parent,
48
- childIds.filter((id) => !overlappingChildren.includes(id))
49
- );
46
+ const parentUtil = editor.getShapeUtil(parent);
47
+ const lostChildIds = childIds.filter((id) => {
48
+ if (overlappingChildren.includes(id)) return false;
49
+ const child = editor.getShape(id);
50
+ if (!child) return false;
51
+ return parentUtil.canRemoveChildrenOfType(parent, child.type);
52
+ });
53
+ if (lostChildIds.length > 0) {
54
+ parentsToLostChildren.set(parent, lostChildIds);
55
+ }
50
56
  }
51
57
  }
52
58
  }
@@ -150,9 +156,16 @@ function getDroppedShapesToNewParents(editor, shapes, cb) {
150
156
  const shapeGroupIds = /* @__PURE__ */ new Map();
151
157
  const reparenting = /* @__PURE__ */ new Map();
152
158
  const remainingShapesToReparent = new Set(shapesToActuallyCheck);
153
- const potentialParentShapes = editor.getCurrentPageShapesSorted().filter(
154
- (s) => editor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) && !remainingShapesToReparent.has(s)
155
- );
159
+ const potentialParentShapes = editor.getCurrentPageShapesSorted().filter((parentShape) => {
160
+ if (remainingShapesToReparent.has(parentShape)) return false;
161
+ const parentUtil = editor.getShapeUtil(parentShape);
162
+ for (const childShape of remainingShapesToReparent) {
163
+ if (parentUtil.canReceiveNewChildrenOfType(parentShape, childShape.type)) {
164
+ return true;
165
+ }
166
+ }
167
+ return false;
168
+ });
156
169
  parentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {
157
170
  const parentShape = potentialParentShapes[i];
158
171
  const parentShapeContainingGroupId = editor.findShapeAncestor(