@tldraw/editor 4.6.0-next.fecc64eee134 → 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.
- package/dist-cjs/index.d.ts +493 -170
- package/dist-cjs/index.js +14 -23
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +3 -0
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +93 -47
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +180 -0
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +7 -0
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +46 -248
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +142 -33
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/assets/AssetUtil.js +1 -0
- package/dist-cjs/lib/editor/assets/AssetUtil.js.map +1 -1
- package/dist-cjs/lib/editor/bindings/BindingUtil.js +1 -0
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -0
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +98 -0
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -0
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -0
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -0
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +2 -0
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +12 -0
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -0
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +1 -0
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +2 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +1 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -0
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +1 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +14 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -0
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +2 -0
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +1 -1
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +154 -0
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/OverlayUtil.js +92 -0
- package/dist-cjs/lib/editor/overlays/OverlayUtil.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js +161 -0
- package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js +39 -0
- package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +79 -0
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +36 -23
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +32 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +1 -0
- package/dist-cjs/lib/editor/tools/StateNode.js.map +1 -1
- package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
- package/dist-cjs/lib/exports/ExportDelay.js +1 -0
- package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -0
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +1 -1
- package/dist-cjs/lib/exports/fetchCache.js +1 -1
- package/dist-cjs/lib/exports/fetchCache.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js +2 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +25 -4
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js +0 -28
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +1 -36
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/hooks/useShapeCulling.js +2 -1
- package/dist-cjs/lib/hooks/useShapeCulling.js.map +2 -2
- package/dist-cjs/lib/options.js +1 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +3 -0
- package/dist-cjs/lib/primitives/Vec.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +1 -1
- package/dist-cjs/lib/utils/EditorAtom.js +2 -0
- package/dist-cjs/lib/utils/EditorAtom.js.map +1 -1
- package/dist-cjs/lib/utils/reparenting.js +20 -7
- package/dist-cjs/lib/utils/reparenting.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +5 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +4 -4
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +493 -170
- package/dist-esm/index.mjs +21 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +3 -0
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +94 -48
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +160 -0
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +7 -0
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +47 -249
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +3 -3
- package/dist-esm/lib/editor/Editor.mjs +143 -35
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/assets/AssetUtil.mjs +1 -0
- package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs +1 -0
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +83 -0
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -0
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +2 -0
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +12 -0
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -0
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +1 -0
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +14 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +2 -0
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +1 -1
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +136 -0
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/OverlayUtil.mjs +72 -0
- package/dist-esm/lib/editor/overlays/OverlayUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs +141 -0
- package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs +19 -0
- package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +59 -0
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +36 -23
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +32 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +1 -0
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +1 -1
- package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
- package/dist-esm/lib/exports/ExportDelay.mjs +1 -0
- package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -0
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +1 -1
- package/dist-esm/lib/exports/fetchCache.mjs +2 -2
- package/dist-esm/lib/exports/fetchCache.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +2 -1
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -4
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -28
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -40
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useShapeCulling.mjs +2 -1
- package/dist-esm/lib/hooks/useShapeCulling.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +1 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +3 -0
- package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +1 -1
- package/dist-esm/lib/utils/EditorAtom.mjs +2 -0
- package/dist-esm/lib/utils/EditorAtom.mjs.map +1 -1
- package/dist-esm/lib/utils/reparenting.mjs +20 -7
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +5 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +4 -4
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +4 -243
- package/package.json +7 -7
- package/src/index.ts +18 -39
- package/src/lib/TldrawEditor.tsx +9 -0
- package/src/lib/components/MenuClickCapture.tsx +124 -64
- package/src/lib/components/default-components/CanvasOverlays.tsx +208 -0
- package/src/lib/components/default-components/DefaultCanvas.tsx +51 -322
- package/src/lib/editor/Editor.test.ts +3 -1
- package/src/lib/editor/Editor.ts +167 -38
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +98 -0
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +12 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -2
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
- package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +14 -0
- package/src/lib/editor/overlays/OverlayManager.ts +183 -0
- package/src/lib/editor/overlays/OverlayUtil.ts +143 -0
- package/src/lib/editor/overlays/ShapeIndicatorOverlayUtil.ts +216 -0
- package/src/lib/editor/overlays/getOverlayDisplayValues.ts +51 -0
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +128 -0
- package/src/lib/editor/shapes/ShapeUtil.ts +45 -26
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +40 -3
- package/src/lib/editor/types/event-types.ts +2 -0
- package/src/lib/exports/fetchCache.ts +2 -4
- package/src/lib/exports/getSvgJsx.test.ts +3 -1
- package/src/lib/exports/getSvgJsx.tsx +2 -1
- package/src/lib/hooks/EditorComponentsContext.tsx +0 -27
- package/src/lib/hooks/useCanvasEvents.ts +45 -3
- package/src/lib/hooks/useEditorComponents.tsx +0 -28
- package/src/lib/hooks/usePeerIds.ts +6 -55
- package/src/lib/hooks/useShapeCulling.tsx +3 -1
- package/src/lib/options.ts +7 -0
- package/src/lib/utils/reparenting.ts +22 -9
- package/src/lib/utils/sync/TLLocalSyncClient.ts +3 -0
- package/src/version.ts +4 -4
- package/dist-cjs/lib/components/GeometryDebuggingView.js +0 -115
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +0 -7
- package/dist-cjs/lib/components/LiveCollaborators.js +0 -151
- package/dist-cjs/lib/components/LiveCollaborators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +0 -227
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultBrush.js +0 -38
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +0 -71
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultCursor.js +0 -59
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultHandle.js +0 -56
- package/dist-cjs/lib/components/default-components/DefaultHandle.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultHandles.js +0 -28
- package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultScribble.js +0 -51
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js +0 -69
- package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +0 -107
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js +0 -28
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +0 -101
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +0 -170
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +0 -7
- package/dist-cjs/lib/hooks/useHandleEvents.js +0 -100
- package/dist-cjs/lib/hooks/useHandleEvents.js.map +0 -7
- package/dist-cjs/lib/hooks/useSelectionEvents.js +0 -98
- package/dist-cjs/lib/hooks/useSelectionEvents.js.map +0 -7
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +0 -95
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +0 -7
- package/dist-esm/lib/components/LiveCollaborators.mjs +0 -134
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +0 -207
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs +0 -18
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +0 -41
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs +0 -29
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultHandle.mjs +0 -26
- package/dist-esm/lib/components/default-components/DefaultHandle.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs +0 -8
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs +0 -21
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs +0 -39
- package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +0 -77
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs +0 -8
- package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +0 -81
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +0 -142
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +0 -7
- package/dist-esm/lib/hooks/useHandleEvents.mjs +0 -70
- package/dist-esm/lib/hooks/useHandleEvents.mjs.map +0 -7
- package/dist-esm/lib/hooks/useSelectionEvents.mjs +0 -78
- package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +0 -7
- package/src/lib/components/GeometryDebuggingView.tsx +0 -108
- package/src/lib/components/LiveCollaborators.tsx +0 -174
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +0 -289
- package/src/lib/components/default-components/DefaultBrush.tsx +0 -35
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +0 -52
- package/src/lib/components/default-components/DefaultCursor.tsx +0 -59
- package/src/lib/components/default-components/DefaultHandle.tsx +0 -42
- package/src/lib/components/default-components/DefaultHandles.tsx +0 -15
- package/src/lib/components/default-components/DefaultScribble.tsx +0 -31
- package/src/lib/components/default-components/DefaultSelectionForeground.tsx +0 -50
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +0 -104
- package/src/lib/components/default-components/DefaultShapeIndicatorErrorFallback.tsx +0 -9
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +0 -116
- package/src/lib/components/default-components/DefaultSnapIndictor.tsx +0 -174
- package/src/lib/hooks/useHandleEvents.ts +0 -88
- package/src/lib/hooks/useSelectionEvents.ts +0 -97
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
ComputedCache,
|
|
12
12
|
RecordType,
|
|
13
|
+
StoreSideEffects,
|
|
14
|
+
StoreSnapshot,
|
|
13
15
|
UnknownRecord,
|
|
14
16
|
reverseRecordsDiff,
|
|
15
|
-
StoreSnapshot,
|
|
16
|
-
StoreSideEffects,
|
|
17
17
|
} from '@tldraw/store'
|
|
18
18
|
import {
|
|
19
19
|
CameraRecordType,
|
|
@@ -89,7 +89,6 @@ import {
|
|
|
89
89
|
hasOwnProperty,
|
|
90
90
|
last,
|
|
91
91
|
lerp,
|
|
92
|
-
maxBy,
|
|
93
92
|
minBy,
|
|
94
93
|
sortById,
|
|
95
94
|
sortByIndex,
|
|
@@ -152,6 +151,7 @@ import { notVisibleShapes } from './derivations/notVisibleShapes'
|
|
|
152
151
|
import { parentsToChildren } from './derivations/parentsToChildren'
|
|
153
152
|
import { deriveShapeIdsInCurrentPage } from './derivations/shapeIdsInCurrentPage'
|
|
154
153
|
import { ClickManager } from './managers/ClickManager/ClickManager'
|
|
154
|
+
import { CollaboratorsManager } from './managers/CollaboratorsManager/CollaboratorsManager'
|
|
155
155
|
import { EdgeScrollManager } from './managers/EdgeScrollManager/EdgeScrollManager'
|
|
156
156
|
import { FocusManager } from './managers/FocusManager/FocusManager'
|
|
157
157
|
import { FontManager } from './managers/FontManager/FontManager'
|
|
@@ -162,9 +162,11 @@ import { ScribbleManager } from './managers/ScribbleManager/ScribbleManager'
|
|
|
162
162
|
import { SnapManager } from './managers/SnapManager/SnapManager'
|
|
163
163
|
import { SpatialIndexManager } from './managers/SpatialIndexManager/SpatialIndexManager'
|
|
164
164
|
import { TextManager } from './managers/TextManager/TextManager'
|
|
165
|
-
import {
|
|
165
|
+
import { ThemeManager, resolveThemes } from './managers/ThemeManager/ThemeManager'
|
|
166
166
|
import { TickManager } from './managers/TickManager/TickManager'
|
|
167
167
|
import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
|
|
168
|
+
import { OverlayManager } from './overlays/OverlayManager'
|
|
169
|
+
import { TLAnyOverlayUtilConstructor } from './overlays/OverlayUtil'
|
|
168
170
|
import {
|
|
169
171
|
ShapeUtil,
|
|
170
172
|
TLEditStartInfo,
|
|
@@ -224,6 +226,11 @@ export interface TLEditorOptions {
|
|
|
224
226
|
* An array of asset utils to use in the editor. These will be used to handle asset-type-specific behavior.
|
|
225
227
|
*/
|
|
226
228
|
assetUtils?: readonly TLAnyAssetUtilConstructor[]
|
|
229
|
+
/**
|
|
230
|
+
* An array of overlay utils to use in the editor. These define canvas overlay UI elements
|
|
231
|
+
* like selection handles, rotation corners, shape handles, etc.
|
|
232
|
+
*/
|
|
233
|
+
overlayUtils?: readonly TLAnyOverlayUtilConstructor[]
|
|
227
234
|
/**
|
|
228
235
|
* An array of tools to use in the editor. These will be used to handle events and manage user interactions in the editor.
|
|
229
236
|
*/
|
|
@@ -330,6 +337,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
330
337
|
shapeUtils,
|
|
331
338
|
bindingUtils,
|
|
332
339
|
assetUtils: assetUtilConstructors,
|
|
340
|
+
overlayUtils: overlayUtilConstructors,
|
|
333
341
|
tools,
|
|
334
342
|
getContainer,
|
|
335
343
|
// needs to be here for backwards compatibility with TldrawEditor
|
|
@@ -410,6 +418,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
410
418
|
this.inputs = new InputsManager(this)
|
|
411
419
|
this.performance = new PerformanceManager(this)
|
|
412
420
|
this.disposables.add(() => this.performance.dispose())
|
|
421
|
+
this.collaborators = new CollaboratorsManager(this)
|
|
413
422
|
|
|
414
423
|
class NewRoot extends RootState {
|
|
415
424
|
static override initial = initialState ?? ''
|
|
@@ -489,6 +498,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
489
498
|
|
|
490
499
|
this.scribbles = new ScribbleManager(this)
|
|
491
500
|
|
|
501
|
+
// Overlay utils
|
|
502
|
+
this.overlays = new OverlayManager(this)
|
|
503
|
+
if (overlayUtilConstructors) {
|
|
504
|
+
for (const Util of overlayUtilConstructors) {
|
|
505
|
+
const util = new Util(this)
|
|
506
|
+
this.overlays.registerUtil(util)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
492
510
|
// Cleanup
|
|
493
511
|
|
|
494
512
|
const cleanupInstancePageState = (
|
|
@@ -1033,6 +1051,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1033
1051
|
*/
|
|
1034
1052
|
readonly timers = tltime.forContext(this.contextId)
|
|
1035
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* A manager for remote peer collaborators connected to this editor.
|
|
1056
|
+
*
|
|
1057
|
+
* @public
|
|
1058
|
+
*/
|
|
1059
|
+
readonly collaborators: CollaboratorsManager
|
|
1060
|
+
|
|
1036
1061
|
/**
|
|
1037
1062
|
* A manager for the user and their preferences.
|
|
1038
1063
|
*
|
|
@@ -1068,6 +1093,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1068
1093
|
*/
|
|
1069
1094
|
readonly scribbles: ScribbleManager
|
|
1070
1095
|
|
|
1096
|
+
/**
|
|
1097
|
+
* A manager for canvas overlay UI elements (selection handles, shape handles, etc.).
|
|
1098
|
+
*
|
|
1099
|
+
* @public
|
|
1100
|
+
*/
|
|
1101
|
+
readonly overlays: OverlayManager
|
|
1102
|
+
|
|
1071
1103
|
/**
|
|
1072
1104
|
* A manager for side effects and correct state enforcement. See {@link @tldraw/store#StoreSideEffects} for details.
|
|
1073
1105
|
*
|
|
@@ -1912,11 +1944,23 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1912
1944
|
/**
|
|
1913
1945
|
* Set the cursor.
|
|
1914
1946
|
*
|
|
1947
|
+
* No-op when the partial wouldn't change the current cursor — `setCursor`
|
|
1948
|
+
* is called from pointer-move hot paths (see `updateHoveredOverlayId`,
|
|
1949
|
+
* various tool states) and skipping redundant writes avoids needlessly
|
|
1950
|
+
* dirtying instance state.
|
|
1951
|
+
*
|
|
1915
1952
|
* @param cursor - The cursor to set.
|
|
1916
1953
|
* @public
|
|
1917
1954
|
*/
|
|
1918
1955
|
setCursor(cursor: Partial<TLCursor>) {
|
|
1919
|
-
|
|
1956
|
+
const current = this.getInstanceState().cursor
|
|
1957
|
+
if (
|
|
1958
|
+
(cursor.type === undefined || cursor.type === current.type) &&
|
|
1959
|
+
(cursor.rotation === undefined || cursor.rotation === current.rotation)
|
|
1960
|
+
) {
|
|
1961
|
+
return this
|
|
1962
|
+
}
|
|
1963
|
+
this.updateInstanceState({ cursor: { ...current, ...cursor } })
|
|
1920
1964
|
return this
|
|
1921
1965
|
}
|
|
1922
1966
|
|
|
@@ -4222,43 +4266,55 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4222
4266
|
}
|
|
4223
4267
|
// Collaborators
|
|
4224
4268
|
|
|
4225
|
-
@computed
|
|
4226
|
-
private _getCollaboratorsQuery() {
|
|
4227
|
-
return this.store.query.records('instance_presence', () => ({
|
|
4228
|
-
userId: { neq: this.user.getId() },
|
|
4229
|
-
}))
|
|
4230
|
-
}
|
|
4231
|
-
|
|
4232
4269
|
/**
|
|
4233
4270
|
* Returns a list of presence records for all peer collaborators.
|
|
4234
4271
|
* This will return the latest presence record for each connected user.
|
|
4235
4272
|
*
|
|
4273
|
+
* Convenience wrapper for {@link CollaboratorsManager.getCollaborators}.
|
|
4274
|
+
*
|
|
4236
4275
|
* @public
|
|
4237
4276
|
*/
|
|
4238
|
-
@computed
|
|
4239
4277
|
getCollaborators() {
|
|
4240
|
-
|
|
4241
|
-
if (!allPresenceRecords.length) return EMPTY_ARRAY
|
|
4242
|
-
const userIds = [...new Set(allPresenceRecords.map((c) => c.userId))].sort()
|
|
4243
|
-
return userIds.map((id) => {
|
|
4244
|
-
const latestPresence = maxBy(
|
|
4245
|
-
allPresenceRecords.filter((c) => c.userId === id),
|
|
4246
|
-
(p) => p.lastActivityTimestamp ?? 0
|
|
4247
|
-
)
|
|
4248
|
-
return latestPresence!
|
|
4249
|
-
})
|
|
4278
|
+
return this.collaborators.getCollaborators()
|
|
4250
4279
|
}
|
|
4251
4280
|
|
|
4252
4281
|
/**
|
|
4253
4282
|
* Returns a list of presence records for all peer collaborators on the current page.
|
|
4254
4283
|
* This will return the latest presence record for each connected user.
|
|
4255
4284
|
*
|
|
4285
|
+
* Convenience wrapper for {@link CollaboratorsManager.getCollaboratorsOnCurrentPage}.
|
|
4286
|
+
*
|
|
4256
4287
|
* @public
|
|
4257
4288
|
*/
|
|
4258
|
-
@computed
|
|
4259
4289
|
getCollaboratorsOnCurrentPage() {
|
|
4260
|
-
|
|
4261
|
-
|
|
4290
|
+
return this.collaborators.getCollaboratorsOnCurrentPage()
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
/**
|
|
4294
|
+
* Returns a list of presence records for peer collaborators who should currently be
|
|
4295
|
+
* shown in the UI. Filters {@link Editor.getCollaborators} by activity state
|
|
4296
|
+
* (active / idle / inactive) and visibility rules such as following and highlighted
|
|
4297
|
+
* users. Re-evaluates on the collaborator visibility clock, so callers don't need to
|
|
4298
|
+
* drive their own activity timer.
|
|
4299
|
+
*
|
|
4300
|
+
* Convenience wrapper for {@link CollaboratorsManager.getVisibleCollaborators}.
|
|
4301
|
+
*
|
|
4302
|
+
* @public
|
|
4303
|
+
*/
|
|
4304
|
+
getVisibleCollaborators() {
|
|
4305
|
+
return this.collaborators.getVisibleCollaborators()
|
|
4306
|
+
}
|
|
4307
|
+
|
|
4308
|
+
/**
|
|
4309
|
+
* Returns a list of presence records for peer collaborators who should currently be
|
|
4310
|
+
* shown in the UI, filtered to those on the current page.
|
|
4311
|
+
*
|
|
4312
|
+
* Convenience wrapper for {@link CollaboratorsManager.getVisibleCollaboratorsOnCurrentPage}.
|
|
4313
|
+
*
|
|
4314
|
+
* @public
|
|
4315
|
+
*/
|
|
4316
|
+
getVisibleCollaboratorsOnCurrentPage() {
|
|
4317
|
+
return this.collaborators.getVisibleCollaboratorsOnCurrentPage()
|
|
4262
4318
|
}
|
|
4263
4319
|
|
|
4264
4320
|
// Attribution
|
|
@@ -5112,7 +5168,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5112
5168
|
const zoomStepFunction = (zoom: number) => Math.pow(2, Math.ceil(Math.log2(zoom)))
|
|
5113
5169
|
const steppedScreenScale = zoomStepFunction(screenScale)
|
|
5114
5170
|
const networkEffectiveType: string | null =
|
|
5115
|
-
'connection' in navigator ? (navigator as any).connection
|
|
5171
|
+
'connection' in navigator ? ((navigator as any).connection?.effectiveType ?? null) : null
|
|
5116
5172
|
|
|
5117
5173
|
return await this.store.props.assets.resolve(asset, {
|
|
5118
5174
|
screenScale: screenScale || 1,
|
|
@@ -5703,8 +5759,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5703
5759
|
? this.getCurrentPageRenderingShapesSorted()
|
|
5704
5760
|
: this.getCurrentPageShapesSorted()
|
|
5705
5761
|
).filter((shape) => {
|
|
5706
|
-
//
|
|
5707
|
-
if (!candidateIds.has(shape.id) && !this.
|
|
5762
|
+
// Frame-like shapes have labels positioned above the shape (outside bounds), so always include them
|
|
5763
|
+
if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false
|
|
5708
5764
|
|
|
5709
5765
|
if (
|
|
5710
5766
|
(shape.isLocked && !hitLocked) ||
|
|
@@ -5726,12 +5782,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5726
5782
|
const pointInShapeSpace = this.getPointInShapeSpace(shape, point)
|
|
5727
5783
|
|
|
5728
5784
|
// Check labels first
|
|
5785
|
+
const shapeUtil = this.getShapeUtil(shape)
|
|
5786
|
+
const isShapeFrameLike = this.isShapeFrameLike(shape)
|
|
5729
5787
|
if (
|
|
5730
|
-
|
|
5788
|
+
isShapeFrameLike ||
|
|
5731
5789
|
((this.isShapeOfType(shape, 'note') ||
|
|
5732
5790
|
this.isShapeOfType(shape, 'arrow') ||
|
|
5733
5791
|
(this.isShapeOfType(shape, 'geo') && shape.props.fill === 'none')) &&
|
|
5734
|
-
|
|
5792
|
+
shapeUtil.getText(shape)?.trim())
|
|
5735
5793
|
) {
|
|
5736
5794
|
for (const childGeometry of (geometry as Group2d).children) {
|
|
5737
5795
|
if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
|
|
@@ -5740,8 +5798,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5740
5798
|
}
|
|
5741
5799
|
}
|
|
5742
5800
|
|
|
5743
|
-
if (
|
|
5744
|
-
// On the rare case that we've hit a frame (not its label), test again hitInside to be forced true;
|
|
5801
|
+
if (isShapeFrameLike) {
|
|
5802
|
+
// On the rare case that we've hit a frame-like shape (not its label), test again hitInside to be forced true;
|
|
5745
5803
|
// this prevents clicks from passing through the body of a frame to shapes behind it.
|
|
5746
5804
|
|
|
5747
5805
|
// If the hit is within the frame's outer margin, then select the frame
|
|
@@ -5900,11 +5958,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5900
5958
|
const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin)
|
|
5901
5959
|
|
|
5902
5960
|
// Get all page shapes in z-index order and filter to candidates that pass isPointInShape
|
|
5903
|
-
//
|
|
5961
|
+
// Frame-like shapes are always checked because their labels can be outside their bounds
|
|
5904
5962
|
return this.getCurrentPageShapesSorted()
|
|
5905
5963
|
.filter((shape) => {
|
|
5906
5964
|
if (this.isShapeHidden(shape)) return false
|
|
5907
|
-
if (!candidateIds.has(shape.id) && !this.
|
|
5965
|
+
if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false
|
|
5908
5966
|
return this.isPointInShape(shape, point, opts)
|
|
5909
5967
|
})
|
|
5910
5968
|
.reverse()
|
|
@@ -6079,6 +6137,25 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6079
6137
|
return shape.type === type
|
|
6080
6138
|
}
|
|
6081
6139
|
|
|
6140
|
+
/**
|
|
6141
|
+
* Get whether a shape behaves like a frame — a container that has child
|
|
6142
|
+
* shapes, requires full-brush selection, blocks erasure from inside, etc.
|
|
6143
|
+
*
|
|
6144
|
+
* @example
|
|
6145
|
+
* ```ts
|
|
6146
|
+
* const isFrameLike = editor.isShapeFrameLike(someShape)
|
|
6147
|
+
* ```
|
|
6148
|
+
*
|
|
6149
|
+
* @param shape - The shape (or shape id) to test.
|
|
6150
|
+
*
|
|
6151
|
+
* @public
|
|
6152
|
+
*/
|
|
6153
|
+
isShapeFrameLike(shape: TLShape | TLShapeId): boolean {
|
|
6154
|
+
const _shape = typeof shape === 'string' ? this.getShape(shape) : shape
|
|
6155
|
+
if (!_shape) return false
|
|
6156
|
+
return this.getShapeUtil(_shape).isFrameLike(_shape)
|
|
6157
|
+
}
|
|
6158
|
+
|
|
6082
6159
|
/**
|
|
6083
6160
|
* Get a shape by its id.
|
|
6084
6161
|
*
|
|
@@ -11036,6 +11113,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
11036
11113
|
}
|
|
11037
11114
|
this.inputs.setIsPanning(true)
|
|
11038
11115
|
clearTimeout(this._longPressTimeout)
|
|
11116
|
+
} else if (info.button === RIGHT_MOUSE_BUTTON && this.options.rightClickPanning) {
|
|
11117
|
+
this.inputs.setIsRightPointing(true)
|
|
11118
|
+
clearTimeout(this._longPressTimeout)
|
|
11119
|
+
return this
|
|
11039
11120
|
}
|
|
11040
11121
|
|
|
11041
11122
|
// We might be panning because we did a middle mouse click, or because we're holding spacebar and started a regular click
|
|
@@ -11054,9 +11135,31 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
11054
11135
|
|
|
11055
11136
|
const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera())
|
|
11056
11137
|
|
|
11138
|
+
// Right-click pointing: waiting to see if this becomes a drag
|
|
11139
|
+
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
11140
|
+
const currentScreenPoint = this.inputs.getCurrentScreenPoint()
|
|
11141
|
+
const originScreenPoint = this.inputs.getOriginScreenPoint()
|
|
11142
|
+
if (
|
|
11143
|
+
Vec.Dist2(originScreenPoint, currentScreenPoint) > this.options.dragDistanceSquared
|
|
11144
|
+
) {
|
|
11145
|
+
// Passed the drag threshold—transition to panning
|
|
11146
|
+
this._prevCursor = this.getInstanceState().cursor.type
|
|
11147
|
+
this.inputs.setIsPanning(true)
|
|
11148
|
+
this.setCursor({ type: 'grabbing', rotation: 0 })
|
|
11149
|
+
this.stopCameraAnimation()
|
|
11150
|
+
// Apply the initial delta from the pointer down origin
|
|
11151
|
+
const offset = Vec.Sub(currentScreenPoint, originScreenPoint)
|
|
11152
|
+
this.setCamera(new Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
|
|
11153
|
+
immediate: true,
|
|
11154
|
+
})
|
|
11155
|
+
this.maybeTrackPerformance('Panning')
|
|
11156
|
+
}
|
|
11157
|
+
return
|
|
11158
|
+
}
|
|
11159
|
+
|
|
11057
11160
|
// If we've started panning, then clear any long press timeout
|
|
11058
11161
|
if (this.inputs.getIsPanning() && this.inputs.getIsPointing()) {
|
|
11059
|
-
// Handle spacebar / middle mouse button panning
|
|
11162
|
+
// Handle spacebar / middle mouse button / right-click panning
|
|
11060
11163
|
const currentScreenPoint = this.inputs.getCurrentScreenPoint()
|
|
11061
11164
|
const previousScreenPoint = this.inputs.getPreviousScreenPoint()
|
|
11062
11165
|
const offset = Vec.Sub(currentScreenPoint, previousScreenPoint)
|
|
@@ -11089,13 +11192,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
11089
11192
|
inputs.setIsDragging(false)
|
|
11090
11193
|
inputs.setIsPointing(false)
|
|
11091
11194
|
clearTimeout(this._longPressTimeout)
|
|
11092
|
-
|
|
11093
11195
|
// Remove the button from the buttons set
|
|
11094
11196
|
inputs.buttons.delete(info.button)
|
|
11095
11197
|
|
|
11096
11198
|
// If we're in pen mode and we're not using a pen, stop here
|
|
11097
11199
|
if (instanceState.isPenMode && !isPen) return
|
|
11098
11200
|
|
|
11201
|
+
// Right-click pointing ended without dragging—this is a static
|
|
11202
|
+
// right-click, so let it through to the state chart as right_click.
|
|
11203
|
+
// Check isPanning first: if we transitioned to panning, isRightPointing
|
|
11204
|
+
// is still true but we want the panning cleanup path instead.
|
|
11205
|
+
if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
|
|
11206
|
+
this.inputs.setIsRightPointing(false)
|
|
11207
|
+
this._selectedShapeIdsAtPointerDown = []
|
|
11208
|
+
break // fall through to state chart dispatch as right_click
|
|
11209
|
+
}
|
|
11210
|
+
|
|
11211
|
+
this.inputs.setIsRightPointing(false)
|
|
11212
|
+
|
|
11099
11213
|
// Firefox bug fix...
|
|
11100
11214
|
// If it's the same pointer that we stored earlier...
|
|
11101
11215
|
// ... then it's probably still a left-mouse-click!
|
|
@@ -11118,11 +11232,26 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
11118
11232
|
break
|
|
11119
11233
|
}
|
|
11120
11234
|
case MIDDLE_MOUSE_BUTTON: {
|
|
11121
|
-
if (this.inputs.keys.has('
|
|
11235
|
+
if (this.inputs.keys.has('Space')) {
|
|
11236
|
+
this.setCursor({ type: 'grab', rotation: 0 })
|
|
11237
|
+
} else {
|
|
11238
|
+
this.setCursor({ type: this._prevCursor, rotation: 0 })
|
|
11239
|
+
}
|
|
11240
|
+
break
|
|
11241
|
+
}
|
|
11242
|
+
case RIGHT_MOUSE_BUTTON: {
|
|
11243
|
+
if (this.inputs.keys.has('Space')) {
|
|
11122
11244
|
this.setCursor({ type: 'grab', rotation: 0 })
|
|
11123
11245
|
} else {
|
|
11124
11246
|
this.setCursor({ type: this._prevCursor, rotation: 0 })
|
|
11125
11247
|
}
|
|
11248
|
+
// Don't pass right-click panning events to the state chart
|
|
11249
|
+
// as it causes unintended shape selection on release
|
|
11250
|
+
if (slideSpeed > 0) {
|
|
11251
|
+
this.slideCamera({ speed: slideSpeed, direction: slideDirection })
|
|
11252
|
+
}
|
|
11253
|
+
this._selectedShapeIdsAtPointerDown = []
|
|
11254
|
+
return this
|
|
11126
11255
|
}
|
|
11127
11256
|
}
|
|
11128
11257
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'
|
|
2
|
+
import { TLInstancePresence } from '@tldraw/tlschema'
|
|
3
|
+
import { maxBy } from '@tldraw/utils'
|
|
4
|
+
import {
|
|
5
|
+
getCollaboratorStateFromElapsedTime,
|
|
6
|
+
shouldShowCollaborator,
|
|
7
|
+
} from '../../../utils/collaboratorState'
|
|
8
|
+
import type { Editor } from '../../Editor'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tracks remote peers and exposes the collaborator-related queries used by the
|
|
12
|
+
* editor and its overlays. Encapsulates the visibility clock that periodically
|
|
13
|
+
* re-evaluates which collaborators should be visible based on activity.
|
|
14
|
+
*
|
|
15
|
+
* Accessed via {@link Editor.collaborators}.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export class CollaboratorsManager {
|
|
20
|
+
constructor(private readonly editor: Editor) {
|
|
21
|
+
// Editor disposes `editor.timers` on its own teardown, so the interval is
|
|
22
|
+
// automatically cleared when the editor is disposed.
|
|
23
|
+
editor.timers.setInterval(() => {
|
|
24
|
+
this._visibilityClock.set(Date.now())
|
|
25
|
+
}, editor.options.collaboratorCheckIntervalMs)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Drives reactive re-evaluation of {@link CollaboratorsManager.getVisibleCollaborators}.
|
|
30
|
+
* Ticked on a fixed interval so callers don't need to manage their own activity timers.
|
|
31
|
+
*/
|
|
32
|
+
private readonly _visibilityClock = atom('collaboratorVisibilityClock', Date.now())
|
|
33
|
+
|
|
34
|
+
@computed
|
|
35
|
+
private _getCollaboratorsQuery() {
|
|
36
|
+
return this.editor.store.query.records('instance_presence', () => ({
|
|
37
|
+
userId: { neq: this.editor.user.getId() },
|
|
38
|
+
}))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns a list of presence records for all peer collaborators.
|
|
43
|
+
* This will return the latest presence record for each connected user.
|
|
44
|
+
*/
|
|
45
|
+
@computed
|
|
46
|
+
getCollaborators(): TLInstancePresence[] {
|
|
47
|
+
const allPresenceRecords = this._getCollaboratorsQuery().get()
|
|
48
|
+
if (!allPresenceRecords.length) return EMPTY_ARRAY
|
|
49
|
+
const userIds = [...new Set(allPresenceRecords.map((c) => c.userId))].sort()
|
|
50
|
+
return userIds.map((id) => {
|
|
51
|
+
const latestPresence = maxBy(
|
|
52
|
+
allPresenceRecords.filter((c) => c.userId === id),
|
|
53
|
+
(p) => p.lastActivityTimestamp ?? 0
|
|
54
|
+
)
|
|
55
|
+
return latestPresence!
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns a list of presence records for all peer collaborators on the current page.
|
|
61
|
+
* This will return the latest presence record for each connected user.
|
|
62
|
+
*/
|
|
63
|
+
@computed
|
|
64
|
+
getCollaboratorsOnCurrentPage(): TLInstancePresence[] {
|
|
65
|
+
const currentPageId = this.editor.getCurrentPageId()
|
|
66
|
+
return this.getCollaborators().filter((c) => c.currentPageId === currentPageId)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Returns a list of presence records for peer collaborators who should currently be
|
|
71
|
+
* shown in the UI. Filters {@link CollaboratorsManager.getCollaborators} by activity
|
|
72
|
+
* state (active / idle / inactive) and visibility rules such as following and
|
|
73
|
+
* highlighted users. Re-evaluates on the visibility clock, so callers don't need to
|
|
74
|
+
* drive their own activity timer.
|
|
75
|
+
*/
|
|
76
|
+
@computed
|
|
77
|
+
getVisibleCollaborators(): TLInstancePresence[] {
|
|
78
|
+
this._visibilityClock.get()
|
|
79
|
+
const now = Date.now()
|
|
80
|
+
return this.getCollaborators().filter((presence) => {
|
|
81
|
+
// Treat a missing `lastActivityTimestamp` as "active right now" (elapsed = 0)
|
|
82
|
+
// so newly-joined peers aren't immediately classified as idle/inactive.
|
|
83
|
+
const elapsed = Math.max(0, now - (presence.lastActivityTimestamp ?? now))
|
|
84
|
+
const state = getCollaboratorStateFromElapsedTime(this.editor, elapsed)
|
|
85
|
+
return shouldShowCollaborator(this.editor, presence, state)
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns a list of presence records for peer collaborators who should currently be
|
|
91
|
+
* shown in the UI, filtered to those on the current page.
|
|
92
|
+
*/
|
|
93
|
+
@computed
|
|
94
|
+
getVisibleCollaboratorsOnCurrentPage(): TLInstancePresence[] {
|
|
95
|
+
const currentPageId = this.editor.getCurrentPageId()
|
|
96
|
+
return this.getVisibleCollaborators().filter((c) => c.currentPageId === currentPageId)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -331,6 +331,18 @@ export class InputsManager {
|
|
|
331
331
|
this._isPointing.set(isPointing)
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
private _isRightPointing = atom<boolean>('isRightPointing', false)
|
|
335
|
+
/**
|
|
336
|
+
* Whether the user is right-click pointing (before drag threshold).
|
|
337
|
+
*/
|
|
338
|
+
getIsRightPointing() {
|
|
339
|
+
return this._isRightPointing.get()
|
|
340
|
+
}
|
|
341
|
+
/** @internal */
|
|
342
|
+
setIsRightPointing(isRightPointing: boolean) {
|
|
343
|
+
this._isRightPointing.set(isRightPointing)
|
|
344
|
+
}
|
|
345
|
+
|
|
334
346
|
private _isPinching = atom<boolean>('isPinching', false)
|
|
335
347
|
/**
|
|
336
348
|
* Whether the user is pinching.
|
|
@@ -77,8 +77,13 @@ describe('SnapManager', () => {
|
|
|
77
77
|
})),
|
|
78
78
|
getShapePageBounds: vi.fn(),
|
|
79
79
|
isShapeOfType: vi.fn(),
|
|
80
|
+
isShapeFrameLike: vi.fn(() => false),
|
|
80
81
|
} as any
|
|
81
82
|
|
|
83
|
+
editor.getShapeUtil.mockReturnValue({
|
|
84
|
+
canSnap: vi.fn(() => true),
|
|
85
|
+
} as any)
|
|
86
|
+
|
|
82
87
|
snapManager = new SnapManager(editor)
|
|
83
88
|
})
|
|
84
89
|
|
|
@@ -351,7 +356,10 @@ describe('SnapManager', () => {
|
|
|
351
356
|
|
|
352
357
|
editor.getSortedChildIdsForParent.mockReturnValue([frameId])
|
|
353
358
|
editor.getShape.mockReturnValue(frameShape)
|
|
354
|
-
editor.
|
|
359
|
+
editor.getShapeUtil.mockReturnValue({
|
|
360
|
+
canSnap: vi.fn(() => true),
|
|
361
|
+
} as any)
|
|
362
|
+
editor.isShapeFrameLike.mockReturnValue(true)
|
|
355
363
|
editor.getShapePageBounds.mockReturnValue(new Box(10, 10, 50, 50))
|
|
356
364
|
|
|
357
365
|
const result = snapManager.getSnappableShapes()
|
|
@@ -401,7 +409,10 @@ describe('SnapManager', () => {
|
|
|
401
409
|
return undefined
|
|
402
410
|
})
|
|
403
411
|
|
|
404
|
-
editor.
|
|
412
|
+
editor.getShapeUtil.mockReturnValue({
|
|
413
|
+
canSnap: vi.fn(() => true),
|
|
414
|
+
} as any)
|
|
415
|
+
editor.isShapeFrameLike.mockReturnValue(true)
|
|
405
416
|
editor.getShapePageBounds.mockReturnValue(new Box(10, 10, 50, 50))
|
|
406
417
|
|
|
407
418
|
const result = snapManager.getSnappableShapes()
|
|
@@ -72,7 +72,7 @@ export class SnapManager {
|
|
|
72
72
|
const collectSnappableShapesFromParent = (parentId: TLParentId) => {
|
|
73
73
|
if (isShapeId(parentId)) {
|
|
74
74
|
const parent = editor.getShape(parentId)
|
|
75
|
-
if (parent && editor.
|
|
75
|
+
if (parent && editor.isShapeFrameLike(parent)) {
|
|
76
76
|
snappableShapes.add(parentId)
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -136,6 +136,13 @@ export const DEFAULT_THEME: TLTheme = {
|
|
|
136
136
|
solid: '#fcfffe',
|
|
137
137
|
cursor: 'black',
|
|
138
138
|
noteBorder: 'rgb(144, 144, 144)',
|
|
139
|
+
snap: 'hsl(0, 76%, 60%)',
|
|
140
|
+
selectionStroke: 'hsl(214, 84%, 56%)',
|
|
141
|
+
selectionFill: 'hsl(210, 100%, 56%, 24%)',
|
|
142
|
+
brushFill: 'hsl(0, 0%, 56%, 10.2%)',
|
|
143
|
+
brushStroke: 'hsl(0, 0%, 56%, 25.1%)',
|
|
144
|
+
selectedContrast: '#ffffff',
|
|
145
|
+
laser: 'hsl(0, 100%, 50%)',
|
|
139
146
|
black: {
|
|
140
147
|
solid: '#1d1d1d',
|
|
141
148
|
fill: '#1d1d1d',
|
|
@@ -351,6 +358,13 @@ export const DEFAULT_THEME: TLTheme = {
|
|
|
351
358
|
negativeSpace: 'hsl(240, 5%, 6.5%)',
|
|
352
359
|
solid: '#010403',
|
|
353
360
|
cursor: 'white',
|
|
361
|
+
snap: 'hsl(0, 76%, 60%)',
|
|
362
|
+
selectionStroke: 'hsl(214, 84%, 56%)',
|
|
363
|
+
selectionFill: 'hsl(209, 100%, 57%, 20%)',
|
|
364
|
+
brushFill: 'hsl(0, 0%, 56%, 10.2%)',
|
|
365
|
+
brushStroke: 'hsl(0, 0%, 56%, 25.1%)',
|
|
366
|
+
selectedContrast: '#ffffff',
|
|
367
|
+
laser: 'hsl(0, 100%, 50%)',
|
|
354
368
|
noteBorder: 'rgb(20, 20, 20)',
|
|
355
369
|
|
|
356
370
|
black: {
|