@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,22 +1,12 @@
1
- import { useAtom, useComputed, useValue } from '@tldraw/state-react'
2
- import { useEffect } from 'react'
3
- import {
4
- getCollaboratorStateFromElapsedTime,
5
- shouldShowCollaborator,
6
- } from '../utils/collaboratorState'
1
+ import { useComputed, useValue } from '@tldraw/state-react'
7
2
  import { uniq } from '../utils/uniq'
8
3
  import { useEditor } from './useEditor'
9
4
 
10
- function setsEqual<T>(a: Set<T>, b: Set<T>): boolean {
11
- if (a.size !== b.size) return false
12
- for (const item of a) {
13
- if (!b.has(item)) return false
14
- }
15
- return true
16
- }
17
-
18
- // TODO: maybe move this to a computed property on the App class?
19
5
  /**
6
+ * Reactive list of peer user IDs for collaborators currently shown in the UI.
7
+ * Mirrors {@link Editor.getVisibleCollaborators} — peers fade out as they
8
+ * transition to idle/inactive, without requiring a manual re-render.
9
+ *
20
10
  * @returns The list of peer UserIDs
21
11
  * @public
22
12
  */
@@ -25,49 +15,10 @@ export function usePeerIds() {
25
15
 
26
16
  const $userIds = useComputed(
27
17
  'userIds',
28
- () => uniq(editor.getCollaborators().map((p) => p.userId)).sort(),
18
+ () => uniq(editor.getVisibleCollaborators().map((p) => p.userId)).sort(),
29
19
  { isEqual: (a, b) => a.join(',') === b.join?.(',') },
30
20
  [editor]
31
21
  )
32
22
 
33
23
  return useValue($userIds)
34
24
  }
35
-
36
- /**
37
- * Returns a computed signal of active peer user IDs that should be shown.
38
- * Automatically re-evaluates on an interval to handle time-based state transitions
39
- * (active -> idle -> inactive).
40
- *
41
- * @returns A computed signal containing a Set of active peer user IDs
42
- * @internal
43
- */
44
- export function useActivePeerIds$() {
45
- const $time = useAtom('peerIdsTime', Date.now())
46
- const editor = useEditor()
47
- useEffect(() => {
48
- const interval = editor.timers.setInterval(() => {
49
- $time.set(Date.now())
50
- }, editor.options.collaboratorCheckIntervalMs)
51
-
52
- return () => clearInterval(interval)
53
- }, [editor, $time])
54
-
55
- return useComputed(
56
- 'activePeerIds',
57
- () => {
58
- const now = $time.get()
59
- return new Set(
60
- editor
61
- .getCollaborators()
62
- .filter((p) => {
63
- const elapsed = Math.max(0, now - (p.lastActivityTimestamp ?? Infinity))
64
- const state = getCollaboratorStateFromElapsedTime(editor, elapsed)
65
- return shouldShowCollaborator(editor, p, state)
66
- })
67
- .map((p) => p.userId)
68
- )
69
- },
70
- { isEqual: setsEqual },
71
- [editor]
72
- )
73
- }
@@ -61,8 +61,10 @@ export function ShapeCullingProvider({ children }: ShapeCullingProviderProps) {
61
61
  }, [])
62
62
 
63
63
  const updateCulling = useCallback((culledShapes: Set<TLShapeId>) => {
64
+ let shouldBeCulled: boolean
65
+
64
66
  for (const [id, entry] of containersRef.current) {
65
- const shouldBeCulled = culledShapes.has(id)
67
+ shouldBeCulled = culledShapes.has(id)
66
68
  if (shouldBeCulled !== entry.isCulled) {
67
69
  const display = shouldBeCulled ? 'none' : 'block'
68
70
  setStyleProperty(entry.container, 'display', display)
@@ -202,12 +202,6 @@ export interface TldrawOptions {
202
202
  * viewport's page dimensions regardless of overview zoom changes.
203
203
  */
204
204
  readonly quickZoomPreservesScreenBounds: boolean
205
- /**
206
- * Whether to use 2D canvas rendering for shape indicators. When true (default),
207
- * shapes that support it will render indicators on a 2D canvas for better
208
- * performance. When false, all indicators use legacy SVG rendering.
209
- */
210
- readonly useCanvasIndicators: boolean
211
205
  /**
212
206
  * Called before content is written to the clipboard during a copy or cut operation.
213
207
  * Receives the serialized content (shapes, bindings, assets) and can filter or transform
@@ -344,7 +338,6 @@ export const defaultTldrawOptions = {
344
338
  camera: DEFAULT_CAMERA_OPTIONS,
345
339
  text: {},
346
340
  deepLinks: undefined,
347
- useCanvasIndicators: true,
348
341
  quickZoomPreservesScreenBounds: true,
349
342
  onBeforeCopyToClipboard: undefined,
350
343
  onBeforePasteFromClipboard: undefined,
@@ -42,10 +42,17 @@ export function kickoutOccludedShapes(
42
42
  } else {
43
43
  const overlappingChildren = getOverlappingShapes(editor, parent.id, childIds)
44
44
  if (overlappingChildren.length < childIds.length) {
45
- parentsToLostChildren.set(
46
- parent,
47
- childIds.filter((id) => !overlappingChildren.includes(id))
48
- )
45
+ const parentUtil = editor.getShapeUtil(parent)
46
+ const lostChildIds = childIds.filter((id) => {
47
+ if (overlappingChildren.includes(id)) return false
48
+ const child = editor.getShape(id)
49
+ if (!child) return false
50
+ // Respect the parent's removal gate: if it pins this child type, don't kick it out.
51
+ return parentUtil.canRemoveChildrenOfType(parent, child.type)
52
+ })
53
+ if (lostChildIds.length > 0) {
54
+ parentsToLostChildren.set(parent, lostChildIds)
55
+ }
49
56
  }
50
57
  }
51
58
  }
@@ -238,11 +245,17 @@ export function getDroppedShapesToNewParents(
238
245
  const potentialParentShapes = editor
239
246
  .getCurrentPageShapesSorted()
240
247
  // filter out any shapes that aren't frames or that are included among the provided shapes
241
- .filter(
242
- (s) =>
243
- editor.getShapeUtil(s).canReceiveNewChildrenOfType?.(s, s.type) &&
244
- !remainingShapesToReparent.has(s)
245
- )
248
+ .filter((parentShape) => {
249
+ if (remainingShapesToReparent.has(parentShape)) return false
250
+
251
+ const parentUtil = editor.getShapeUtil(parentShape)
252
+ for (const childShape of remainingShapesToReparent) {
253
+ if (parentUtil.canReceiveNewChildrenOfType(parentShape, childShape.type)) {
254
+ return true
255
+ }
256
+ }
257
+ return false
258
+ })
246
259
 
247
260
  parentCheck: for (let i = potentialParentShapes.length - 1; i >= 0; i--) {
248
261
  const parentShape = potentialParentShapes[i]
@@ -262,6 +262,9 @@ export class TLLocalSyncClient {
262
262
  this.debug('closing')
263
263
  this.didDispose = true
264
264
  this.disposables.forEach((d) => d())
265
+ if (typeof window !== 'undefined' && (window as any).tlsync === this) {
266
+ delete (window as any).tlsync
267
+ }
265
268
  }
266
269
 
267
270
  private isPersisting = false
package/src/version.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '4.6.0-next.fe1474dc57d8'
4
+ export const version = '5.0.0'
5
5
  export const publishDates = {
6
- major: '2025-09-18T14:39:22.803Z',
7
- minor: '2026-04-28T08:00:30.359Z',
8
- patch: '2026-04-28T08:00:30.359Z',
6
+ major: '2026-05-06T16:21:11.305Z',
7
+ minor: '2026-05-06T16:21:11.305Z',
8
+ patch: '2026-05-06T16:21:11.305Z',
9
9
  }
@@ -1,115 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var GeometryDebuggingView_exports = {};
20
- __export(GeometryDebuggingView_exports, {
21
- GeometryDebuggingView: () => GeometryDebuggingView
22
- });
23
- module.exports = __toCommonJS(GeometryDebuggingView_exports);
24
- var import_jsx_runtime = require("react/jsx-runtime");
25
- var import_state_react = require("@tldraw/state-react");
26
- var import_utils = require("@tldraw/utils");
27
- var import_useEditor = require("../hooks/useEditor");
28
- var import_Group2d = require("../primitives/geometry/Group2d");
29
- const GeometryDebuggingView = (0, import_state_react.track)(function GeometryDebuggingView2({
30
- showStroke = true,
31
- showVertices = true,
32
- showClosestPointOnOutline = true
33
- }) {
34
- const editor = (0, import_useEditor.useEditor)();
35
- const zoomLevel = editor.getZoomLevel();
36
- const renderingShapes = editor.getRenderingShapes();
37
- const currentPagePoint = editor.inputs.getCurrentPagePoint();
38
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
39
- "svg",
40
- {
41
- style: {
42
- position: "absolute",
43
- pointerEvents: "none",
44
- zIndex: 999999999,
45
- top: 0,
46
- left: 0,
47
- overflow: "visible"
48
- },
49
- children: renderingShapes.map((result) => {
50
- const shape = editor.getShape(result.id);
51
- if (shape.type === "group") return null;
52
- const geometry = editor.getShapeGeometry(shape);
53
- const pageTransform = editor.getShapePageTransform(shape);
54
- const pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint);
55
- const nearestPointOnShape = geometry.nearestPoint(pointInShapeSpace);
56
- const distanceToPoint = geometry.distanceToPoint(pointInShapeSpace, true);
57
- const dist = Math.abs(distanceToPoint) * zoomLevel;
58
- const hitInside = distanceToPoint < 0;
59
- const { vertices } = geometry;
60
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
61
- "g",
62
- {
63
- transform: pageTransform.toCssString(),
64
- strokeLinecap: "round",
65
- strokeLinejoin: "round",
66
- children: [
67
- showStroke && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
- "g",
69
- {
70
- stroke: geometry.debugColor ?? "red",
71
- opacity: "1",
72
- strokeWidth: 2 / zoomLevel,
73
- fill: "none",
74
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GeometryStroke, { geometry })
75
- }
76
- ),
77
- showVertices && vertices.map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
- "circle",
79
- {
80
- cx: v.x,
81
- cy: v.y,
82
- r: 2 / zoomLevel,
83
- fill: `hsl(${(0, import_utils.modulate)(i, [0, vertices.length - 1], [120, 200])}, 100%, 50%)`,
84
- stroke: "black",
85
- strokeWidth: 1 / zoomLevel
86
- },
87
- `v${i}`
88
- )),
89
- showClosestPointOnOutline && dist < 150 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
90
- "line",
91
- {
92
- x1: nearestPointOnShape.x,
93
- y1: nearestPointOnShape.y,
94
- x2: pointInShapeSpace.x,
95
- y2: pointInShapeSpace.y,
96
- opacity: 1 - dist / 150,
97
- stroke: hitInside ? "goldenrod" : "dodgerblue",
98
- strokeWidth: 2 / zoomLevel
99
- }
100
- )
101
- ]
102
- },
103
- result.id + "_outline"
104
- );
105
- })
106
- }
107
- );
108
- });
109
- function GeometryStroke({ geometry }) {
110
- if (geometry instanceof import_Group2d.Group2d) {
111
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", { stroke: geometry.debugColor, children: [...geometry.children, ...geometry.ignoredChildren].map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GeometryStroke, { geometry: child }, i)) });
112
- }
113
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: geometry.toSimpleSvgPath(), stroke: geometry.debugColor });
114
- }
115
- //# sourceMappingURL=GeometryDebuggingView.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/lib/components/GeometryDebuggingView.tsx"],
4
- "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { modulate } from '@tldraw/utils'\nimport { useEditor } from '../hooks/useEditor'\nimport { Geometry2d } from '../primitives/geometry/Geometry2d'\nimport { Group2d } from '../primitives/geometry/Group2d'\n\nexport const GeometryDebuggingView = track(function GeometryDebuggingView({\n\tshowStroke = true,\n\tshowVertices = true,\n\tshowClosestPointOnOutline = true,\n}: {\n\tshowStroke?: boolean\n\tshowVertices?: boolean\n\tshowClosestPointOnOutline?: boolean\n}) {\n\tconst editor = useEditor()\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst renderingShapes = editor.getRenderingShapes()\n\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\n\treturn (\n\t\t<svg\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\tpointerEvents: 'none',\n\t\t\t\tzIndex: 999999999,\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\toverflow: 'visible',\n\t\t\t}}\n\t\t>\n\t\t\t{renderingShapes.map((result) => {\n\t\t\t\tconst shape = editor.getShape(result.id)!\n\n\t\t\t\tif (shape.type === 'group') return null\n\n\t\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)!\n\n\t\t\t\tconst pointInShapeSpace = editor.getPointInShapeSpace(shape, currentPagePoint)\n\t\t\t\tconst nearestPointOnShape = geometry.nearestPoint(pointInShapeSpace)\n\t\t\t\tconst distanceToPoint = geometry.distanceToPoint(pointInShapeSpace, true)\n\t\t\t\tconst dist = Math.abs(distanceToPoint) * zoomLevel\n\t\t\t\tconst hitInside = distanceToPoint < 0\n\n\t\t\t\tconst { vertices } = geometry\n\n\t\t\t\treturn (\n\t\t\t\t\t<g\n\t\t\t\t\t\tkey={result.id + '_outline'}\n\t\t\t\t\t\ttransform={pageTransform.toCssString()}\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{showStroke && (\n\t\t\t\t\t\t\t<g\n\t\t\t\t\t\t\t\tstroke={geometry.debugColor ?? 'red'}\n\t\t\t\t\t\t\t\topacity=\"1\"\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<GeometryStroke geometry={geometry} />\n\t\t\t\t\t\t\t</g>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{showVertices &&\n\t\t\t\t\t\t\tvertices.map((v, i) => (\n\t\t\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\t\t\tkey={`v${i}`}\n\t\t\t\t\t\t\t\t\tcx={v.x}\n\t\t\t\t\t\t\t\t\tcy={v.y}\n\t\t\t\t\t\t\t\t\tr={2 / zoomLevel}\n\t\t\t\t\t\t\t\t\tfill={`hsl(${modulate(i, [0, vertices.length - 1], [120, 200])}, 100%, 50%)`}\n\t\t\t\t\t\t\t\t\tstroke=\"black\"\n\t\t\t\t\t\t\t\t\tstrokeWidth={1 / zoomLevel}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t{showClosestPointOnOutline && dist < 150 && (\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\tx1={nearestPointOnShape.x}\n\t\t\t\t\t\t\t\ty1={nearestPointOnShape.y}\n\t\t\t\t\t\t\t\tx2={pointInShapeSpace.x}\n\t\t\t\t\t\t\t\ty2={pointInShapeSpace.y}\n\t\t\t\t\t\t\t\topacity={1 - dist / 150}\n\t\t\t\t\t\t\t\tstroke={hitInside ? 'goldenrod' : 'dodgerblue'}\n\t\t\t\t\t\t\t\tstrokeWidth={2 / zoomLevel}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</g>\n\t\t\t\t)\n\t\t\t})}\n\t\t</svg>\n\t)\n})\n\nfunction GeometryStroke({ geometry }: { geometry: Geometry2d }) {\n\tif (geometry instanceof Group2d) {\n\t\treturn (\n\t\t\t<g stroke={geometry.debugColor}>\n\t\t\t\t{[...geometry.children, ...geometry.ignoredChildren].map((child, i) => (\n\t\t\t\t\t<GeometryStroke geometry={child} key={i} />\n\t\t\t\t))}\n\t\t\t</g>\n\t\t)\n\t}\n\n\treturn <path d={geometry.toSimpleSvgPath()} stroke={geometry.debugColor} />\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiDK;AAjDL,yBAAsB;AACtB,mBAAyB;AACzB,uBAA0B;AAE1B,qBAAwB;AAEjB,MAAM,4BAAwB,0BAAM,SAASA,uBAAsB;AAAA,EACzE,aAAa;AAAA,EACb,eAAe;AAAA,EACf,4BAA4B;AAC7B,GAIG;AACF,QAAM,aAAS,4BAAU;AAEzB,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,kBAAkB,OAAO,mBAAmB;AAClD,QAAM,mBAAmB,OAAO,OAAO,oBAAoB;AAE3D,SACC;AAAA,IAAC;AAAA;AAAA,MACA,OAAO;AAAA,QACN,UAAU;AAAA,QACV,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,MACX;AAAA,MAEC,0BAAgB,IAAI,CAAC,WAAW;AAChC,cAAM,QAAQ,OAAO,SAAS,OAAO,EAAE;AAEvC,YAAI,MAAM,SAAS,QAAS,QAAO;AAEnC,cAAM,WAAW,OAAO,iBAAiB,KAAK;AAC9C,cAAM,gBAAgB,OAAO,sBAAsB,KAAK;AAExD,cAAM,oBAAoB,OAAO,qBAAqB,OAAO,gBAAgB;AAC7E,cAAM,sBAAsB,SAAS,aAAa,iBAAiB;AACnE,cAAM,kBAAkB,SAAS,gBAAgB,mBAAmB,IAAI;AACxE,cAAM,OAAO,KAAK,IAAI,eAAe,IAAI;AACzC,cAAM,YAAY,kBAAkB;AAEpC,cAAM,EAAE,SAAS,IAAI;AAErB,eACC;AAAA,UAAC;AAAA;AAAA,YAEA,WAAW,cAAc,YAAY;AAAA,YACrC,eAAc;AAAA,YACd,gBAAe;AAAA,YAEd;AAAA,4BACA;AAAA,gBAAC;AAAA;AAAA,kBACA,QAAQ,SAAS,cAAc;AAAA,kBAC/B,SAAQ;AAAA,kBACR,aAAa,IAAI;AAAA,kBACjB,MAAK;AAAA,kBAEL,sDAAC,kBAAe,UAAoB;AAAA;AAAA,cACrC;AAAA,cAEA,gBACA,SAAS,IAAI,CAAC,GAAG,MAChB;AAAA,gBAAC;AAAA;AAAA,kBAEA,IAAI,EAAE;AAAA,kBACN,IAAI,EAAE;AAAA,kBACN,GAAG,IAAI;AAAA,kBACP,MAAM,WAAO,uBAAS,GAAG,CAAC,GAAG,SAAS,SAAS,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;AAAA,kBAC9D,QAAO;AAAA,kBACP,aAAa,IAAI;AAAA;AAAA,gBANZ,IAAI,CAAC;AAAA,cAOX,CACA;AAAA,cACD,6BAA6B,OAAO,OACpC;AAAA,gBAAC;AAAA;AAAA,kBACA,IAAI,oBAAoB;AAAA,kBACxB,IAAI,oBAAoB;AAAA,kBACxB,IAAI,kBAAkB;AAAA,kBACtB,IAAI,kBAAkB;AAAA,kBACtB,SAAS,IAAI,OAAO;AAAA,kBACpB,QAAQ,YAAY,cAAc;AAAA,kBAClC,aAAa,IAAI;AAAA;AAAA,cAClB;AAAA;AAAA;AAAA,UApCI,OAAO,KAAK;AAAA,QAsClB;AAAA,MAEF,CAAC;AAAA;AAAA,EACF;AAEF,CAAC;AAED,SAAS,eAAe,EAAE,SAAS,GAA6B;AAC/D,MAAI,oBAAoB,wBAAS;AAChC,WACC,4CAAC,OAAE,QAAQ,SAAS,YAClB,WAAC,GAAG,SAAS,UAAU,GAAG,SAAS,eAAe,EAAE,IAAI,CAAC,OAAO,MAChE,4CAAC,kBAAe,UAAU,SAAY,CAAG,CACzC,GACF;AAAA,EAEF;AAEA,SAAO,4CAAC,UAAK,GAAG,SAAS,gBAAgB,GAAG,QAAQ,SAAS,YAAY;AAC1E;",
6
- "names": ["GeometryDebuggingView"]
7
- }
@@ -1,152 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var LiveCollaborators_exports = {};
20
- __export(LiveCollaborators_exports, {
21
- LiveCollaborators: () => LiveCollaborators
22
- });
23
- module.exports = __toCommonJS(LiveCollaborators_exports);
24
- var import_jsx_runtime = require("react/jsx-runtime");
25
- var import_state_react = require("@tldraw/state-react");
26
- var import_react = require("react");
27
- var import_EditorComponentsContext = require("../hooks/EditorComponentsContext");
28
- var import_useEditor = require("../hooks/useEditor");
29
- var import_usePeerIds = require("../hooks/usePeerIds");
30
- var import_usePresence = require("../hooks/usePresence");
31
- var import_collaboratorState = require("../utils/collaboratorState");
32
- const LiveCollaborators = (0, import_state_react.track)(function Collaborators() {
33
- const peerIds = (0, import_usePeerIds.usePeerIds)();
34
- return peerIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollaboratorGuard, { collaboratorId: id }, id));
35
- });
36
- const CollaboratorGuard = (0, import_state_react.track)(function CollaboratorGuard2({
37
- collaboratorId
38
- }) {
39
- const editor = (0, import_useEditor.useEditor)();
40
- const presence = (0, import_usePresence.usePresence)(collaboratorId);
41
- const collaboratorState = useCollaboratorState(editor, presence);
42
- if (!(presence && presence.currentPageId === editor.getCurrentPageId())) {
43
- return null;
44
- }
45
- if (!(0, import_collaboratorState.shouldShowCollaborator)(editor, presence, collaboratorState)) {
46
- return null;
47
- }
48
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collaborator, { latestPresence: presence });
49
- });
50
- const Collaborator = (0, import_state_react.track)(function Collaborator2({
51
- latestPresence
52
- }) {
53
- const editor = (0, import_useEditor.useEditor)();
54
- const {
55
- CollaboratorBrush,
56
- CollaboratorScribble,
57
- CollaboratorCursor,
58
- CollaboratorHint,
59
- CollaboratorShapeIndicator
60
- } = (0, import_EditorComponentsContext.useEditorComponents)();
61
- const zoomLevel = editor.getZoomLevel();
62
- const viewportPageBounds = editor.getViewportPageBounds();
63
- const { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } = latestPresence;
64
- if (!cursor) return null;
65
- const isCursorInViewport = !(cursor.x < viewportPageBounds.minX - 12 / zoomLevel || cursor.y < viewportPageBounds.minY - 16 / zoomLevel || cursor.x > viewportPageBounds.maxX - 12 / zoomLevel || cursor.y > viewportPageBounds.maxY - 16 / zoomLevel);
66
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
67
- brush && CollaboratorBrush ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
- CollaboratorBrush,
69
- {
70
- className: "tl-collaborator__brush",
71
- userId,
72
- brush,
73
- color,
74
- opacity: 0.1
75
- },
76
- userId + "_brush"
77
- ) : null,
78
- isCursorInViewport && CollaboratorCursor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
79
- CollaboratorCursor,
80
- {
81
- className: "tl-collaborator__cursor",
82
- userId,
83
- point: cursor,
84
- color,
85
- zoom: zoomLevel,
86
- name: userName !== "New User" ? userName : null,
87
- chatMessage: chatMessage ?? ""
88
- },
89
- userId + "_cursor"
90
- ) : CollaboratorHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
91
- CollaboratorHint,
92
- {
93
- className: "tl-collaborator__cursor-hint",
94
- userId,
95
- point: cursor,
96
- color,
97
- zoom: zoomLevel,
98
- viewport: viewportPageBounds
99
- },
100
- userId + "_cursor_hint"
101
- ) : null,
102
- CollaboratorScribble && scribbles.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: scribbles.map((scribble) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
103
- CollaboratorScribble,
104
- {
105
- className: "tl-collaborator__scribble",
106
- userId,
107
- scribble,
108
- color,
109
- zoom: zoomLevel,
110
- opacity: scribble.color === "laser" ? 0.5 : 0.1
111
- },
112
- userId + "_scribble_" + scribble.id
113
- )) }) : null,
114
- CollaboratorShapeIndicator && selectedShapeIds.filter((id) => {
115
- if (editor.isShapeHidden(id)) return false;
116
- if (!editor.options.useCanvasIndicators) return true;
117
- const shape = editor.getShape(id);
118
- if (!shape) return false;
119
- const util = editor.getShapeUtil(shape);
120
- return util.useLegacyIndicator();
121
- }).map((shapeId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
- CollaboratorShapeIndicator,
123
- {
124
- className: "tl-collaborator__shape-indicator",
125
- userId,
126
- shapeId,
127
- color,
128
- opacity: 0.5
129
- },
130
- userId + "_" + shapeId
131
- ))
132
- ] });
133
- });
134
- function useCollaboratorState(editor, latestPresence) {
135
- const rLastActivityTimestamp = (0, import_react.useRef)(latestPresence?.lastActivityTimestamp ?? -1);
136
- const [state, setState] = (0, import_react.useState)(
137
- () => (0, import_collaboratorState.getCollaboratorStateFromElapsedTime)(editor, Date.now() - rLastActivityTimestamp.current)
138
- );
139
- (0, import_react.useEffect)(() => {
140
- const interval = editor.timers.setInterval(() => {
141
- setState(
142
- (0, import_collaboratorState.getCollaboratorStateFromElapsedTime)(editor, Date.now() - rLastActivityTimestamp.current)
143
- );
144
- }, editor.options.collaboratorCheckIntervalMs);
145
- return () => clearInterval(interval);
146
- }, [editor]);
147
- if (latestPresence) {
148
- rLastActivityTimestamp.current = latestPresence.lastActivityTimestamp ?? Infinity;
149
- }
150
- return state;
151
- }
152
- //# sourceMappingURL=LiveCollaborators.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/lib/components/LiveCollaborators.tsx"],
4
- "sourcesContent": ["import { track } from '@tldraw/state-react'\nimport { TLInstancePresence } from '@tldraw/tlschema'\nimport { useEffect, useRef, useState } from 'react'\nimport { Editor } from '../editor/Editor'\nimport { useEditorComponents } from '../hooks/EditorComponentsContext'\nimport { useEditor } from '../hooks/useEditor'\nimport { usePeerIds } from '../hooks/usePeerIds'\nimport { usePresence } from '../hooks/usePresence'\nimport {\n\tCollaboratorState,\n\tgetCollaboratorStateFromElapsedTime,\n\tshouldShowCollaborator,\n} from '../utils/collaboratorState'\n\nexport const LiveCollaborators = track(function Collaborators() {\n\tconst peerIds = usePeerIds()\n\treturn peerIds.map((id) => <CollaboratorGuard key={id} collaboratorId={id} />)\n})\n\nconst CollaboratorGuard = track(function CollaboratorGuard({\n\tcollaboratorId,\n}: {\n\tcollaboratorId: string\n}) {\n\tconst editor = useEditor()\n\tconst presence = usePresence(collaboratorId)\n\tconst collaboratorState = useCollaboratorState(editor, presence)\n\n\tif (!(presence && presence.currentPageId === editor.getCurrentPageId())) {\n\t\t// No need to render if we don't have a presence or if they're on a different page\n\t\treturn null\n\t}\n\n\tif (!shouldShowCollaborator(editor, presence, collaboratorState)) {\n\t\treturn null\n\t}\n\n\treturn <Collaborator latestPresence={presence} />\n})\n\nconst Collaborator = track(function Collaborator({\n\tlatestPresence,\n}: {\n\tlatestPresence: TLInstancePresence\n}) {\n\tconst editor = useEditor()\n\n\tconst {\n\t\tCollaboratorBrush,\n\t\tCollaboratorScribble,\n\t\tCollaboratorCursor,\n\t\tCollaboratorHint,\n\t\tCollaboratorShapeIndicator,\n\t} = useEditorComponents()\n\n\tconst zoomLevel = editor.getZoomLevel()\n\tconst viewportPageBounds = editor.getViewportPageBounds()\n\tconst { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } =\n\t\tlatestPresence\n\n\tif (!cursor) return null\n\n\t// Add a little padding to the top-left of the viewport\n\t// so that the cursor doesn't get cut off\n\tconst isCursorInViewport = !(\n\t\tcursor.x < viewportPageBounds.minX - 12 / zoomLevel ||\n\t\tcursor.y < viewportPageBounds.minY - 16 / zoomLevel ||\n\t\tcursor.x > viewportPageBounds.maxX - 12 / zoomLevel ||\n\t\tcursor.y > viewportPageBounds.maxY - 16 / zoomLevel\n\t)\n\n\treturn (\n\t\t<>\n\t\t\t{brush && CollaboratorBrush ? (\n\t\t\t\t<CollaboratorBrush\n\t\t\t\t\tclassName=\"tl-collaborator__brush\"\n\t\t\t\t\tkey={userId + '_brush'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tbrush={brush}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\topacity={0.1}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{isCursorInViewport && CollaboratorCursor ? (\n\t\t\t\t<CollaboratorCursor\n\t\t\t\t\tclassName=\"tl-collaborator__cursor\"\n\t\t\t\t\tkey={userId + '_cursor'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tname={userName !== 'New User' ? userName : null}\n\t\t\t\t\tchatMessage={chatMessage ?? ''}\n\t\t\t\t/>\n\t\t\t) : CollaboratorHint ? (\n\t\t\t\t<CollaboratorHint\n\t\t\t\t\tclassName=\"tl-collaborator__cursor-hint\"\n\t\t\t\t\tkey={userId + '_cursor_hint'}\n\t\t\t\t\tuserId={userId}\n\t\t\t\t\tpoint={cursor}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\tviewport={viewportPageBounds}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{CollaboratorScribble && scribbles.length ? (\n\t\t\t\t<>\n\t\t\t\t\t{scribbles.map((scribble) => (\n\t\t\t\t\t\t<CollaboratorScribble\n\t\t\t\t\t\t\tkey={userId + '_scribble_' + scribble.id}\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__scribble\"\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tscribble={scribble}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\tzoom={zoomLevel}\n\t\t\t\t\t\t\topacity={scribble.color === 'laser' ? 0.5 : 0.1}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t{CollaboratorShapeIndicator &&\n\t\t\t\tselectedShapeIds\n\t\t\t\t\t.filter((id) => {\n\t\t\t\t\t\t// Skip hidden shapes\n\t\t\t\t\t\tif (editor.isShapeHidden(id)) return false\n\t\t\t\t\t\t// When canvas indicators are disabled, render SVG indicators for\n\t\t\t\t\t\t// every selected shape. Otherwise shapes that opt into the canvas\n\t\t\t\t\t\t// path via useLegacyIndicator() === false would never get a\n\t\t\t\t\t\t// collaborator indicator drawn.\n\t\t\t\t\t\tif (!editor.options.useCanvasIndicators) return true\n\t\t\t\t\t\t// Otherwise, only render SVG indicators for shapes that opt in to\n\t\t\t\t\t\t// the legacy path \u2014 canvas-based indicators are handled by\n\t\t\t\t\t\t// CanvasShapeIndicators.\n\t\t\t\t\t\tconst shape = editor.getShape(id)\n\t\t\t\t\t\tif (!shape) return false\n\t\t\t\t\t\tconst util = editor.getShapeUtil(shape)\n\t\t\t\t\t\treturn util.useLegacyIndicator()\n\t\t\t\t\t})\n\t\t\t\t\t.map((shapeId) => (\n\t\t\t\t\t\t<CollaboratorShapeIndicator\n\t\t\t\t\t\t\tclassName=\"tl-collaborator__shape-indicator\"\n\t\t\t\t\t\t\tkey={userId + '_' + shapeId}\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t\tcolor={color}\n\t\t\t\t\t\t\topacity={0.5}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t</>\n\t)\n})\n\nfunction useCollaboratorState(\n\teditor: Editor,\n\tlatestPresence: TLInstancePresence | null\n): CollaboratorState {\n\tconst rLastActivityTimestamp = useRef(latestPresence?.lastActivityTimestamp ?? -1)\n\n\tconst [state, setState] = useState<CollaboratorState>(() =>\n\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t)\n\n\tuseEffect(() => {\n\t\tconst interval = editor.timers.setInterval(() => {\n\t\t\tsetState(\n\t\t\t\tgetCollaboratorStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)\n\t\t\t)\n\t\t}, editor.options.collaboratorCheckIntervalMs)\n\n\t\treturn () => clearInterval(interval)\n\t}, [editor])\n\n\tif (latestPresence) {\n\t\t// We can do this on every render, it's free and cheaper than an effect\n\t\t// remember, there can be lots and lots of cursors moving around all the time\n\t\trLastActivityTimestamp.current = latestPresence.lastActivityTimestamp ?? Infinity\n\t}\n\n\treturn state\n}\n"],
5
- "mappings": "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",
6
- "names": ["CollaboratorGuard", "Collaborator"]
7
- }