@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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
2
|
+
import { IndexKey, compact } from '@tldraw/utils'
|
|
3
|
+
import { Vec } from '../../primitives/Vec'
|
|
4
|
+
import { BaseBoxShapeUtil, TLBaseBoxShape } from './BaseBoxShapeUtil'
|
|
5
|
+
import { TLDragShapesInInfo, TLDragShapesOutInfo } from './ShapeUtil'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A base class for frame-like shapes — containers that clip their children,
|
|
9
|
+
* require full-brush selection, block erasure from inside, and support
|
|
10
|
+
* drag-and-drop reparenting.
|
|
11
|
+
*
|
|
12
|
+
* Extending this class is the easiest way to create a custom frame-like shape.
|
|
13
|
+
* It provides sensible defaults for all frame-like behaviors:
|
|
14
|
+
*
|
|
15
|
+
* - `isFrameLike()` returns `true`
|
|
16
|
+
* - `providesBackgroundForChildren()` returns `true`
|
|
17
|
+
* - `canReceiveNewChildrenOfType()` returns `true` unless the container is locked
|
|
18
|
+
* - `canRemoveChildrenOfType()` returns `true` unless the container is locked
|
|
19
|
+
* - `getClipPath()` returns the shape geometry's vertices
|
|
20
|
+
* - `onDragShapesIn()` reparents shapes into the frame (with index restoration)
|
|
21
|
+
* - `onDragShapesOut()` reparents shapes back to the page
|
|
22
|
+
*
|
|
23
|
+
* All methods can be overridden for custom behavior.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* class MyContainerUtil extends BaseFrameLikeShapeUtil<MyContainerShape> {
|
|
28
|
+
* static override type = 'my-container' as const
|
|
29
|
+
* static override props = myContainerShapeProps
|
|
30
|
+
*
|
|
31
|
+
* override getDefaultProps() {
|
|
32
|
+
* return { w: 300, h: 200 }
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* override component(shape: MyContainerShape) {
|
|
36
|
+
* return <SVGContainer>...</SVGContainer>
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* override getIndicatorPath(shape: MyContainerShape) {
|
|
40
|
+
* const path = new Path2D()
|
|
41
|
+
* path.rect(0, 0, shape.props.w, shape.props.h)
|
|
42
|
+
* return path
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export abstract class BaseFrameLikeShapeUtil<
|
|
50
|
+
Shape extends TLBaseBoxShape,
|
|
51
|
+
> extends BaseBoxShapeUtil<Shape> {
|
|
52
|
+
override isFrameLike(_shape: Shape): boolean {
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
override providesBackgroundForChildren(): boolean {
|
|
57
|
+
return true
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override canReceiveNewChildrenOfType(shape: Shape, _type: TLShape['type']): boolean {
|
|
61
|
+
return !shape.isLocked
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override canRemoveChildrenOfType(shape: Shape, _type: TLShape['type']): boolean {
|
|
65
|
+
return !shape.isLocked
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override getClipPath(shape: Shape): Vec[] | undefined {
|
|
69
|
+
return this.editor.getShapeGeometry(shape.id).vertices
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override onDragShapesIn(
|
|
73
|
+
shape: Shape,
|
|
74
|
+
draggingShapes: TLShape[],
|
|
75
|
+
{ initialParentIds, initialIndices }: TLDragShapesInInfo
|
|
76
|
+
): void {
|
|
77
|
+
const { editor } = this
|
|
78
|
+
|
|
79
|
+
if (draggingShapes.every((s) => s.parentId === shape.id)) return
|
|
80
|
+
|
|
81
|
+
// Check to see whether any of the shapes can have their old index restored
|
|
82
|
+
let canRestoreOriginalIndices = false
|
|
83
|
+
const previousChildren = draggingShapes.filter(
|
|
84
|
+
(s) => shape.id === (initialParentIds.get(s.id) as TLShapeId)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if (previousChildren.length > 0) {
|
|
88
|
+
const currentChildren = compact(
|
|
89
|
+
editor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))
|
|
90
|
+
)
|
|
91
|
+
if (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {
|
|
92
|
+
canRestoreOriginalIndices = true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// If any of the children are the ancestor of the frame, quit here
|
|
97
|
+
if (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return
|
|
98
|
+
|
|
99
|
+
editor.reparentShapes(draggingShapes, shape.id)
|
|
100
|
+
|
|
101
|
+
if (canRestoreOriginalIndices) {
|
|
102
|
+
for (const s of previousChildren) {
|
|
103
|
+
editor.updateShape({
|
|
104
|
+
id: s.id,
|
|
105
|
+
type: s.type,
|
|
106
|
+
index: initialIndices.get(s.id) as IndexKey,
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override onDragShapesOut(
|
|
113
|
+
shape: Shape,
|
|
114
|
+
draggingShapes: TLShape[],
|
|
115
|
+
info: TLDragShapesOutInfo
|
|
116
|
+
): void {
|
|
117
|
+
const { editor } = this
|
|
118
|
+
// When a user drags shapes out and we're not dragging into a new shape,
|
|
119
|
+
// reparent the dragging shapes onto the current page instead
|
|
120
|
+
if (!info.nextDraggingOverShapeId) {
|
|
121
|
+
// Locked shapes are already filtered out upstream by DragAndDropManager.
|
|
122
|
+
editor.reparentShapes(
|
|
123
|
+
draggingShapes.filter((s) => s.parentId === shape.id),
|
|
124
|
+
editor.getCurrentPageId()
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -218,42 +218,32 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
218
218
|
abstract component(shape: Shape): any
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
* Get
|
|
221
|
+
* Get a Path2D (or a richer object with clip/additional paths) for rendering the
|
|
222
|
+
* shape's indicator on the canvas. Shapes that return `undefined` will not render
|
|
223
|
+
* an indicator.
|
|
222
224
|
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*/
|
|
226
|
-
abstract indicator(shape: Shape): any
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Whether to use the legacy React-based indicator rendering.
|
|
230
|
-
*
|
|
231
|
-
* Override this to return `false` if your shape implements {@link ShapeUtil.getIndicatorPath}
|
|
232
|
-
* for canvas-based indicator rendering.
|
|
225
|
+
* For complex indicators that need clipping (e.g., arrows with labels), return an
|
|
226
|
+
* object with `path`, `clipPath`, and `additionalPaths` properties.
|
|
233
227
|
*
|
|
234
|
-
* @
|
|
228
|
+
* @param shape - The shape.
|
|
229
|
+
* @returns A Path2D to stroke, or an object with clipping info, or undefined to skip.
|
|
235
230
|
* @public
|
|
236
231
|
*/
|
|
237
|
-
|
|
238
|
-
return true
|
|
239
|
-
}
|
|
232
|
+
abstract getIndicatorPath(shape: Shape): TLIndicatorPath | undefined
|
|
240
233
|
|
|
241
234
|
/**
|
|
242
|
-
* Get
|
|
243
|
-
*
|
|
244
|
-
* When implemented, this is used instead of {@link ShapeUtil.indicator} for more
|
|
245
|
-
* efficient canvas-based indicator rendering. Shapes that return `undefined` will
|
|
246
|
-
* fall back to SVG-based rendering via {@link ShapeUtil.indicator}.
|
|
235
|
+
* Get JSX describing the shape's indicator (as an SVG element).
|
|
247
236
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
237
|
+
* @deprecated SVG indicators are no longer rendered. Override
|
|
238
|
+
* {@link ShapeUtil.getIndicatorPath} instead. This stub is retained so legacy
|
|
239
|
+
* subclasses that still call `super.indicator()` keep type-checking; new shapes
|
|
240
|
+
* should not implement it.
|
|
250
241
|
*
|
|
251
242
|
* @param shape - The shape.
|
|
252
|
-
* @returns A Path2D to stroke, or an object with clipping info, or undefined to use SVG fallback.
|
|
253
243
|
* @public
|
|
254
244
|
*/
|
|
255
|
-
|
|
256
|
-
return
|
|
245
|
+
indicator(_shape: Shape): any {
|
|
246
|
+
return null
|
|
257
247
|
}
|
|
258
248
|
|
|
259
249
|
/**
|
|
@@ -492,6 +482,17 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
492
482
|
return false
|
|
493
483
|
}
|
|
494
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Whether the shape behaves like a frame — a container that has child shapes,
|
|
487
|
+
* requires full-brush selection, blocks erasure from inside, etc.
|
|
488
|
+
*
|
|
489
|
+
* @param shape - The shape.
|
|
490
|
+
* @public
|
|
491
|
+
*/
|
|
492
|
+
isFrameLike(_shape: Shape): boolean {
|
|
493
|
+
return false
|
|
494
|
+
}
|
|
495
|
+
|
|
495
496
|
/**
|
|
496
497
|
* By default, the bounds of an image export are the bounds of all the shapes it contains, plus
|
|
497
498
|
* some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
|
|
@@ -545,7 +546,9 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
545
546
|
getHandles?(shape: Shape): TLHandle[]
|
|
546
547
|
|
|
547
548
|
/**
|
|
548
|
-
* Get whether the shape can receive children of a given type.
|
|
549
|
+
* Get whether the shape can receive children of a given type. Used by the drag and drop system
|
|
550
|
+
* to decide whether {@link ShapeUtil.onDragShapesIn} should fire when a shape of the given type
|
|
551
|
+
* is dragged over this one.
|
|
549
552
|
*
|
|
550
553
|
* @param shape - The shape.
|
|
551
554
|
* @param type - The shape type.
|
|
@@ -555,6 +558,22 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
555
558
|
return false
|
|
556
559
|
}
|
|
557
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Get whether children of a given type can be removed from this shape. Used by the drag and
|
|
563
|
+
* drop system to decide whether {@link ShapeUtil.onDragShapesOut} should fire when a child of
|
|
564
|
+
* the given type is dragged out of this shape, and by `kickoutOccludedShapes` to decide
|
|
565
|
+
* whether to auto-reparent a child of the given type when it has moved outside this shape's
|
|
566
|
+
* geometry. Returning `false` therefore "pins" matching children — they stay parented to this
|
|
567
|
+
* shape even when dragged or moved outside it. Defaults to `true`.
|
|
568
|
+
*
|
|
569
|
+
* @param shape - The shape.
|
|
570
|
+
* @param type - The shape type.
|
|
571
|
+
* @public
|
|
572
|
+
*/
|
|
573
|
+
canRemoveChildrenOfType(shape: Shape, type: TLShape['type']) {
|
|
574
|
+
return true
|
|
575
|
+
}
|
|
576
|
+
|
|
558
577
|
/**
|
|
559
578
|
* Get the shape as an SVG object.
|
|
560
579
|
*
|
|
@@ -4,6 +4,7 @@ import { Geometry2d } from '../../../primitives/geometry/Geometry2d'
|
|
|
4
4
|
import { Group2d } from '../../../primitives/geometry/Group2d'
|
|
5
5
|
import { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'
|
|
6
6
|
import { ShapeUtil } from '../ShapeUtil'
|
|
7
|
+
import { getPerfectDashProps } from '../shared/getPerfectDashProps'
|
|
7
8
|
import { DashedOutlineBox } from './DashedOutlineBox'
|
|
8
9
|
|
|
9
10
|
/** @public */
|
|
@@ -78,10 +79,46 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
|
|
78
79
|
)
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
// Not a class component, but eslint can't tell that :(
|
|
82
|
+
override getIndicatorPath(shape: TLGroupShape): Path2D {
|
|
83
83
|
const bounds = this.editor.getShapeGeometry(shape).bounds
|
|
84
|
-
|
|
84
|
+
const zoomLevel = this.editor.getEfficientZoomLevel()
|
|
85
|
+
const path = new Path2D()
|
|
86
|
+
|
|
87
|
+
for (const side of bounds.sides) {
|
|
88
|
+
const [start, end] = side
|
|
89
|
+
const length = start.dist(end)
|
|
90
|
+
if (length <= 0) continue
|
|
91
|
+
|
|
92
|
+
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(length, 1 / zoomLevel, {
|
|
93
|
+
style: 'dashed',
|
|
94
|
+
lengthRatio: 4,
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (strokeDasharray === 'none') {
|
|
98
|
+
path.moveTo(start.x, start.y)
|
|
99
|
+
path.lineTo(end.x, end.y)
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const [dashLength, gapLength] = strokeDasharray.split(' ').map(Number)
|
|
104
|
+
const dashOffset = Number(strokeDashoffset)
|
|
105
|
+
const period = dashLength + gapLength
|
|
106
|
+
if (!Number.isFinite(period) || period <= 0) continue
|
|
107
|
+
|
|
108
|
+
const dx = (end.x - start.x) / length
|
|
109
|
+
const dy = (end.y - start.y) / length
|
|
110
|
+
|
|
111
|
+
for (let dashStart = -dashOffset; dashStart < length; dashStart += period) {
|
|
112
|
+
const dashEnd = Math.min(length, dashStart + dashLength)
|
|
113
|
+
const clippedDashStart = Math.max(0, dashStart)
|
|
114
|
+
if (dashEnd <= clippedDashStart) continue
|
|
115
|
+
|
|
116
|
+
path.moveTo(start.x + dx * clippedDashStart, start.y + dy * clippedDashStart)
|
|
117
|
+
path.lineTo(start.x + dx * dashEnd, start.y + dy * dashEnd)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return path
|
|
85
122
|
}
|
|
86
123
|
|
|
87
124
|
override onChildrenChange(group: TLGroupShape) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TLHandle, TLShape, VecModel } from '@tldraw/tlschema'
|
|
2
2
|
import { VecLike } from '../../primitives/Vec'
|
|
3
|
+
import { TLOverlay } from '../overlays/OverlayUtil'
|
|
3
4
|
import { TLSelectionHandle } from './selection-types'
|
|
4
5
|
|
|
5
6
|
/** @public */
|
|
@@ -11,6 +12,7 @@ export type TLPointerEventTarget =
|
|
|
11
12
|
| { target: 'selection'; handle?: TLSelectionHandle; shape?: undefined }
|
|
12
13
|
| { target: 'shape'; shape: TLShape }
|
|
13
14
|
| { target: 'handle'; shape: TLShape; handle: TLHandle }
|
|
15
|
+
| { target: 'overlay'; overlay: TLOverlay; shape?: undefined }
|
|
14
16
|
|
|
15
17
|
/** @public */
|
|
16
18
|
export type TLPointerEventName =
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { FileHelpers, assert, fetch } from '@tldraw/utils'
|
|
1
|
+
import { FileHelpers, LruCache, assert, fetch } from '@tldraw/utils'
|
|
2
2
|
|
|
3
|
-
// TODO(alex): currently, this cache will grow unbounded. we should come up with a better strategy
|
|
4
|
-
// for clearing items from the cache over time.
|
|
5
3
|
export function fetchCache<T>(cb: (response: Response) => Promise<T>, init?: RequestInit) {
|
|
6
|
-
const cache = new
|
|
4
|
+
const cache = new LruCache<string, Promise<T | null>>(100)
|
|
7
5
|
|
|
8
6
|
return async function fetchCached(url: string): Promise<T | null> {
|
|
9
7
|
const existing = cache.get(url)
|
|
@@ -60,8 +60,9 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
|
|
|
60
60
|
.filter(({ id }) => shapeIdsToInclude.has(id))
|
|
61
61
|
|
|
62
62
|
// --- Common bounding box of all shapes
|
|
63
|
+
const singleFrameShape = ids.length === 1 ? editor.getShape(ids[0]) : null
|
|
63
64
|
const singleFrameShapeId =
|
|
64
|
-
|
|
65
|
+
singleFrameShape && editor.isShapeFrameLike(singleFrameShape) ? ids[0] : null
|
|
65
66
|
|
|
66
67
|
let bbox: null | Box = null
|
|
67
68
|
let paddingWasApplied = false
|
|
@@ -1,54 +1,27 @@
|
|
|
1
1
|
import { ComponentType, RefAttributes, createContext, useContext } from 'react'
|
|
2
|
-
import type { TLBrushProps } from '../components/default-components/DefaultBrush'
|
|
3
2
|
import type { TLCanvasComponentProps } from '../components/default-components/DefaultCanvas'
|
|
4
|
-
import type { TLCollaboratorHintProps } from '../components/default-components/DefaultCollaboratorHint'
|
|
5
|
-
import type { TLCursorProps } from '../components/default-components/DefaultCursor'
|
|
6
3
|
import type { TLErrorFallbackComponent } from '../components/default-components/DefaultErrorFallback'
|
|
7
4
|
import type { TLGridProps } from '../components/default-components/DefaultGrid'
|
|
8
|
-
import type { TLHandleProps } from '../components/default-components/DefaultHandle'
|
|
9
|
-
import type { TLHandlesProps } from '../components/default-components/DefaultHandles'
|
|
10
|
-
import type { TLScribbleProps } from '../components/default-components/DefaultScribble'
|
|
11
5
|
import type { TLSelectionBackgroundProps } from '../components/default-components/DefaultSelectionBackground'
|
|
12
|
-
import type { TLSelectionForegroundProps } from '../components/default-components/DefaultSelectionForeground'
|
|
13
6
|
import type { TLShapeErrorFallbackComponent } from '../components/default-components/DefaultShapeErrorFallback'
|
|
14
|
-
import type { TLShapeIndicatorProps } from '../components/default-components/DefaultShapeIndicator'
|
|
15
|
-
import type { TLShapeIndicatorErrorFallbackComponent } from '../components/default-components/DefaultShapeIndicatorErrorFallback'
|
|
16
7
|
import type { TLShapeWrapperProps } from '../components/default-components/DefaultShapeWrapper'
|
|
17
|
-
import type { TLSnapIndicatorProps } from '../components/default-components/DefaultSnapIndictor'
|
|
18
8
|
|
|
19
9
|
/** @public */
|
|
20
10
|
export interface TLEditorComponents {
|
|
21
11
|
Background?: ComponentType | null
|
|
22
|
-
Brush?: ComponentType<TLBrushProps> | null
|
|
23
12
|
Canvas?: ComponentType<TLCanvasComponentProps> | null
|
|
24
|
-
CollaboratorBrush?: ComponentType<TLBrushProps> | null
|
|
25
|
-
CollaboratorCursor?: ComponentType<TLCursorProps> | null
|
|
26
|
-
CollaboratorHint?: ComponentType<TLCollaboratorHintProps> | null
|
|
27
|
-
CollaboratorScribble?: ComponentType<TLScribbleProps> | null
|
|
28
|
-
CollaboratorShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
|
|
29
|
-
Cursor?: ComponentType<TLCursorProps> | null
|
|
30
13
|
Grid?: ComponentType<TLGridProps> | null
|
|
31
|
-
Handle?: ComponentType<TLHandleProps> | null
|
|
32
|
-
Handles?: ComponentType<TLHandlesProps> | null
|
|
33
14
|
InFrontOfTheCanvas?: ComponentType | null
|
|
34
15
|
LoadingScreen?: ComponentType | null
|
|
35
16
|
OnTheCanvas?: ComponentType | null
|
|
36
|
-
Overlays?: ComponentType | null
|
|
37
|
-
Scribble?: ComponentType<TLScribbleProps> | null
|
|
38
17
|
SelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null
|
|
39
|
-
SelectionForeground?: ComponentType<TLSelectionForegroundProps> | null
|
|
40
|
-
ShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
|
|
41
|
-
ShapeIndicators?: ComponentType | null
|
|
42
18
|
ShapeWrapper?: ComponentType<TLShapeWrapperProps & RefAttributes<HTMLDivElement>> | null
|
|
43
|
-
SnapIndicator?: ComponentType<TLSnapIndicatorProps> | null
|
|
44
19
|
Spinner?: ComponentType<React.SVGProps<SVGSVGElement>> | null
|
|
45
20
|
SvgDefs?: ComponentType | null
|
|
46
|
-
ZoomBrush?: ComponentType<TLBrushProps> | null
|
|
47
21
|
|
|
48
22
|
// These will always have defaults
|
|
49
23
|
ErrorFallback?: TLErrorFallbackComponent
|
|
50
24
|
ShapeErrorFallback?: TLShapeErrorFallbackComponent
|
|
51
|
-
ShapeIndicatorErrorFallback?: TLShapeIndicatorErrorFallbackComponent
|
|
52
25
|
}
|
|
53
26
|
|
|
54
27
|
export const EditorComponentsContext = createContext<null | Required<TLEditorComponents>>(null)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useValue } from '@tldraw/state-react'
|
|
2
2
|
import React, { useEffect, useMemo } from 'react'
|
|
3
|
-
import { RIGHT_MOUSE_BUTTON } from '../constants'
|
|
4
3
|
import { tlenv } from '../globals/environment'
|
|
5
4
|
import {
|
|
6
5
|
elementShouldCaptureKeys,
|
|
@@ -21,7 +20,9 @@ export function useCanvasEvents() {
|
|
|
21
20
|
function onPointerDown(e: React.PointerEvent) {
|
|
22
21
|
if (editor.wasEventAlreadyHandled(e)) return
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
// With right-click panning disabled, fire right_click on press and let the
|
|
24
|
+
// native contextmenu through so the menu opens at the pointer-down location.
|
|
25
|
+
if (e.button === 2 && !editor.options.rightClickPanning) {
|
|
25
26
|
editor.dispatch({
|
|
26
27
|
type: 'pointer',
|
|
27
28
|
target: 'canvas',
|
|
@@ -31,7 +32,7 @@ export function useCanvasEvents() {
|
|
|
31
32
|
return
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
if (e.button !== 0 && e.button !== 1 && e.button !== 5) return
|
|
35
|
+
if (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return
|
|
35
36
|
|
|
36
37
|
setPointerCapture(e.currentTarget, e)
|
|
37
38
|
|
|
@@ -47,6 +48,11 @@ export function useCanvasEvents() {
|
|
|
47
48
|
if (editor.wasEventAlreadyHandled(e)) return
|
|
48
49
|
if (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return
|
|
49
50
|
|
|
51
|
+
const rightClickPanning = editor.options.rightClickPanning
|
|
52
|
+
// Check before dispatch (which resets isPanning)
|
|
53
|
+
const wasRightClickPanning =
|
|
54
|
+
rightClickPanning && e.button === 2 && editor.inputs.getIsPanning()
|
|
55
|
+
|
|
50
56
|
releasePointerCapture(e.currentTarget, e)
|
|
51
57
|
|
|
52
58
|
editor.dispatch({
|
|
@@ -55,6 +61,21 @@ export function useCanvasEvents() {
|
|
|
55
61
|
name: 'pointer_up',
|
|
56
62
|
...getPointerInfo(editor, e),
|
|
57
63
|
})
|
|
64
|
+
|
|
65
|
+
// Static right-click: fire contextmenu at the pointer-up location
|
|
66
|
+
if (rightClickPanning && e.button === 2 && !wasRightClickPanning) {
|
|
67
|
+
const contextMenuEvent = new PointerEvent('contextmenu', {
|
|
68
|
+
bubbles: true,
|
|
69
|
+
clientX: e.clientX,
|
|
70
|
+
clientY: e.clientY,
|
|
71
|
+
button: 2,
|
|
72
|
+
buttons: 0,
|
|
73
|
+
pointerId: e.pointerId,
|
|
74
|
+
pointerType: e.pointerType,
|
|
75
|
+
isPrimary: e.isPrimary,
|
|
76
|
+
})
|
|
77
|
+
e.currentTarget.dispatchEvent(contextMenuEvent)
|
|
78
|
+
}
|
|
58
79
|
}
|
|
59
80
|
|
|
60
81
|
function onPointerEnter(e: React.PointerEvent) {
|
|
@@ -143,6 +164,26 @@ export function useCanvasEvents() {
|
|
|
143
164
|
e.stopPropagation()
|
|
144
165
|
}
|
|
145
166
|
|
|
167
|
+
function onContextMenu(e: React.MouseEvent) {
|
|
168
|
+
// With right-click panning disabled, let the native contextmenu through so the
|
|
169
|
+
// menu opens on press.
|
|
170
|
+
if (!editor.options.rightClickPanning) return
|
|
171
|
+
// Synthetic events — our own dispatch from onPointerUp, or tests using
|
|
172
|
+
// fireEvent.contextMenu — pass through so Radix can open the menu.
|
|
173
|
+
if (!e.nativeEvent.isTrusted) return
|
|
174
|
+
// Only suppress the native browser contextmenu when it follows a real
|
|
175
|
+
// right-click (button=2 with no ctrl modifier). For those, our pointer
|
|
176
|
+
// handling has already decided what to do (either we'll dispatch a
|
|
177
|
+
// synthetic contextmenu on pointerup to open the menu at the release
|
|
178
|
+
// position, or we panned and don't want a menu at all).
|
|
179
|
+
//
|
|
180
|
+
// Other contextmenu sources must reach Radix so the menu opens:
|
|
181
|
+
// - ctrl+click on macOS (button=0, or button=2 with ctrlKey=true)
|
|
182
|
+
// - long-press on touch devices (button=0, pointerType=touch)
|
|
183
|
+
if (e.button !== 2 || e.ctrlKey) return
|
|
184
|
+
preventDefault(e)
|
|
185
|
+
}
|
|
186
|
+
|
|
146
187
|
return {
|
|
147
188
|
onPointerDown,
|
|
148
189
|
onPointerUp,
|
|
@@ -153,6 +194,7 @@ export function useCanvasEvents() {
|
|
|
153
194
|
onTouchStart,
|
|
154
195
|
onTouchEnd,
|
|
155
196
|
onClick,
|
|
197
|
+
onContextMenu,
|
|
156
198
|
}
|
|
157
199
|
},
|
|
158
200
|
[editor]
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { ReactNode, useMemo } from 'react'
|
|
2
2
|
import { DefaultBackground } from '../components/default-components/DefaultBackground'
|
|
3
|
-
import { DefaultBrush } from '../components/default-components/DefaultBrush'
|
|
4
3
|
import { DefaultCanvas } from '../components/default-components/DefaultCanvas'
|
|
5
|
-
import { DefaultCollaboratorHint } from '../components/default-components/DefaultCollaboratorHint'
|
|
6
|
-
import { DefaultCursor } from '../components/default-components/DefaultCursor'
|
|
7
4
|
import { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'
|
|
8
5
|
import { DefaultGrid } from '../components/default-components/DefaultGrid'
|
|
9
|
-
import { DefaultHandle } from '../components/default-components/DefaultHandle'
|
|
10
|
-
import { DefaultHandles } from '../components/default-components/DefaultHandles'
|
|
11
6
|
import { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'
|
|
12
|
-
import { DefaultScribble } from '../components/default-components/DefaultScribble'
|
|
13
|
-
import { DefaultSelectionForeground } from '../components/default-components/DefaultSelectionForeground'
|
|
14
7
|
import { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'
|
|
15
|
-
import { DefaultShapeIndicator } from '../components/default-components/DefaultShapeIndicator'
|
|
16
|
-
import { DefaultShapeIndicatorErrorFallback } from '../components/default-components/DefaultShapeIndicatorErrorFallback'
|
|
17
|
-
import { DefaultShapeIndicators } from '../components/default-components/DefaultShapeIndicators'
|
|
18
8
|
import { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'
|
|
19
|
-
import { DefaultSnapIndicator } from '../components/default-components/DefaultSnapIndictor'
|
|
20
9
|
import { DefaultSpinner } from '../components/default-components/DefaultSpinner'
|
|
21
10
|
import { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'
|
|
22
11
|
import { EditorComponentsContext } from './EditorComponentsContext'
|
|
@@ -39,35 +28,18 @@ export function EditorComponentsProvider({
|
|
|
39
28
|
const value = useMemo(
|
|
40
29
|
(): Required<TLEditorComponents> => ({
|
|
41
30
|
Background: DefaultBackground,
|
|
42
|
-
Brush: DefaultBrush,
|
|
43
31
|
Canvas: DefaultCanvas,
|
|
44
|
-
CollaboratorBrush: DefaultBrush,
|
|
45
|
-
CollaboratorCursor: DefaultCursor,
|
|
46
|
-
CollaboratorHint: DefaultCollaboratorHint,
|
|
47
|
-
CollaboratorScribble: DefaultScribble,
|
|
48
|
-
CollaboratorShapeIndicator: DefaultShapeIndicator,
|
|
49
|
-
Cursor: DefaultCursor,
|
|
50
32
|
Grid: DefaultGrid,
|
|
51
|
-
Handle: DefaultHandle,
|
|
52
|
-
Handles: DefaultHandles,
|
|
53
33
|
InFrontOfTheCanvas: null,
|
|
54
34
|
LoadingScreen: DefaultLoadingScreen,
|
|
55
35
|
OnTheCanvas: null,
|
|
56
|
-
Overlays: null,
|
|
57
|
-
Scribble: DefaultScribble,
|
|
58
36
|
SelectionBackground: null,
|
|
59
|
-
SelectionForeground: DefaultSelectionForeground,
|
|
60
|
-
ShapeIndicator: DefaultShapeIndicator,
|
|
61
|
-
ShapeIndicators: DefaultShapeIndicators,
|
|
62
37
|
ShapeWrapper: DefaultShapeWrapper,
|
|
63
|
-
SnapIndicator: DefaultSnapIndicator,
|
|
64
38
|
Spinner: DefaultSpinner,
|
|
65
39
|
SvgDefs: DefaultSvgDefs,
|
|
66
|
-
ZoomBrush: DefaultBrush,
|
|
67
40
|
|
|
68
41
|
ErrorFallback: DefaultErrorFallback,
|
|
69
42
|
ShapeErrorFallback: DefaultShapeErrorFallback,
|
|
70
|
-
ShapeIndicatorErrorFallback: DefaultShapeIndicatorErrorFallback,
|
|
71
43
|
|
|
72
44
|
..._overrides,
|
|
73
45
|
}),
|
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
import {
|
|
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.
|
|
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
|
-
|
|
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)
|
package/src/lib/options.ts
CHANGED
|
@@ -154,6 +154,12 @@ export interface TldrawOptions {
|
|
|
154
154
|
* When false, the spacebar will not pan the camera.
|
|
155
155
|
*/
|
|
156
156
|
readonly spacebarPanning: boolean
|
|
157
|
+
/**
|
|
158
|
+
* Whether to allow right-click + drag to pan the camera. When true, right-click + drag pans the
|
|
159
|
+
* camera and a static right-click opens the context menu at the release position. When false,
|
|
160
|
+
* right-click opens the context menu on press (no drag-to-pan).
|
|
161
|
+
*/
|
|
162
|
+
readonly rightClickPanning: boolean
|
|
157
163
|
/**
|
|
158
164
|
* The default padding (in pixels) used when zooming to fit content in the viewport.
|
|
159
165
|
* This affects methods like `zoomToFit()`, `zoomToSelection()`, and `zoomToBounds()`.
|
|
@@ -326,6 +332,7 @@ export const defaultTldrawOptions = {
|
|
|
326
332
|
debouncedZoom: true,
|
|
327
333
|
debouncedZoomThreshold: 500,
|
|
328
334
|
spacebarPanning: true,
|
|
335
|
+
rightClickPanning: true,
|
|
329
336
|
zoomToFitPadding: 128,
|
|
330
337
|
snapThreshold: 8,
|
|
331
338
|
camera: DEFAULT_CAMERA_OPTIONS,
|