tldraw 5.4.0-next.ebc95cf01337 → 5.4.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/DOCS.md +2826 -3226
- package/RELEASE_NOTES.md +190 -2
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/defaultExternalContentHandlers.js +30 -14
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/curved-arrow.js +2 -2
- package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/getArrowInfo.js +1 -1
- package/dist-cjs/lib/shapes/arrow/getArrowInfo.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/straight-arrow.js +2 -2
- package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +2 -3
- package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +7 -5
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +8 -6
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/getGeoShapePath.js +3 -1
- package/dist-cjs/lib/shapes/geo/getGeoShapePath.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +2 -3
- package/dist-cjs/lib/shapes/geo/toolStates/Idle.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +2 -6
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js +6 -5
- package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +1 -1
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/crop.js +1 -1
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Idle.js +1 -1
- package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +1 -0
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +2 -0
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js +6 -0
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/SelectTool.js +3 -0
- package/dist-cjs/lib/tools/SelectTool/SelectTool.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +6 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +3 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +1 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +22 -30
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +1 -3
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +4 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +10 -0
- package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +1 -8
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +6 -1
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/Dialogs.js +8 -0
- package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
- package/dist-cjs/lib/ui/components/EditLinkDialog.js +5 -5
- package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +4 -20
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +2 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +1 -0
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +10 -8
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +20 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +8 -7
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useCommentingEnabled.js +1 -1
- package/dist-cjs/lib/ui/hooks/useCommentingEnabled.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +30 -14
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/getArrowInfo.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/getArrowInfo.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +2 -2
- package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +3 -4
- package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +7 -5
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +8 -6
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/getGeoShapePath.mjs +3 -1
- package/dist-esm/lib/shapes/geo/getGeoShapePath.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +3 -4
- package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +1 -1
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +2 -7
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +4 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs +6 -5
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +1 -1
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +1 -1
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +1 -0
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +2 -0
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs +6 -0
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/SelectTool.mjs +3 -0
- package/dist-esm/lib/tools/SelectTool/SelectTool.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +1 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs +1 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -3
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +6 -3
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +3 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +5 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +22 -31
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +1 -3
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +4 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +10 -0
- package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +1 -8
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +7 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Dialogs.mjs +9 -1
- package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs +5 -5
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +5 -22
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +2 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +1 -0
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +10 -8
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +20 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +8 -7
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useCommentingEnabled.mjs +2 -2
- package/dist-esm/lib/ui/hooks/useCommentingEnabled.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +12 -6
- package/src/lib/defaultExternalContentHandlers.test.ts +43 -0
- package/src/lib/defaultExternalContentHandlers.ts +38 -16
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +17 -0
- package/src/lib/shapes/arrow/curved-arrow.ts +2 -2
- package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx +5 -3
- package/src/lib/shapes/arrow/getArrowInfo.ts +2 -1
- package/src/lib/shapes/arrow/straight-arrow.ts +2 -2
- package/src/lib/shapes/arrow/toolStates/Idle.tsx +3 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +10 -6
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +19 -0
- package/src/lib/shapes/draw/toolStates/Drawing.ts +12 -6
- package/src/lib/shapes/frame/FrameShapeTool.test.ts +17 -0
- package/src/lib/shapes/geo/GeoShapeTool.test.ts +28 -0
- package/src/lib/shapes/geo/getGeoShapePath.ts +3 -1
- package/src/lib/shapes/geo/toolStates/Idle.ts +3 -4
- package/src/lib/shapes/geo/toolStates/Pointing.ts +2 -1
- package/src/lib/shapes/line/LineShapeTool.test.ts +30 -1
- package/src/lib/shapes/line/toolStates/Pointing.ts +6 -7
- package/src/lib/shapes/note/NoteShapeTool.test.ts +45 -0
- package/src/lib/shapes/note/NoteShapeUtil.tsx +7 -4
- package/src/lib/shapes/note/noteHelpers.ts +18 -8
- package/src/lib/shapes/note/toolStates/Pointing.ts +2 -1
- package/src/lib/shapes/shared/crop.ts +7 -1
- package/src/lib/shapes/text/TextShapeTool.test.ts +33 -0
- package/src/lib/shapes/text/toolStates/Idle.ts +2 -2
- package/src/lib/shapes/text/toolStates/Pointing.ts +3 -0
- package/src/lib/shapes/video/VideoShapeUtil.tsx +4 -2
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +5 -0
- package/src/lib/tools/HandTool/childStates/OneFingerZooming.ts +10 -0
- package/src/lib/tools/SelectTool/SelectTool.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/Brushing.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/Crop/Crop.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +3 -4
- package/src/lib/tools/SelectTool/childStates/Idle.ts +10 -3
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +4 -0
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +6 -1
- package/src/lib/tools/SelectTool/childStates/PointingShape.ts +4 -1
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +30 -33
- package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +3 -3
- package/src/lib/tools/SelectTool/childStates/Translating.ts +6 -0
- package/src/lib/tools/SelectTool/selectHelpers.ts +21 -0
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +3 -9
- package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +8 -2
- package/src/lib/ui/components/Dialogs.tsx +17 -1
- package/src/lib/ui/components/EditLinkDialog.tsx +8 -7
- package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +5 -23
- package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +2 -0
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +1 -0
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +13 -8
- package/src/lib/ui/components/primitives/TldrawUiSlider.test.tsx +92 -0
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +25 -1
- package/src/lib/ui/context/actions.tsx +25 -7
- package/src/lib/ui/hooks/useCommentingEnabled.ts +5 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/test/ClickManager.test.ts +18 -0
- package/src/test/Editor.test.tsx +3 -0
- package/src/test/EraserTool.test.ts +18 -2
- package/src/test/HandTool.test.ts +21 -0
- package/src/test/LaserTool.test.ts +46 -0
- package/src/test/ScribbleManager.test.ts +19 -0
- package/src/test/SelectTool.test.ts +110 -0
- package/src/test/TldrawEditor.test.tsx +18 -0
- package/src/test/VideoShapeUtil.test.tsx +126 -0
- package/src/test/actions-menu-readonly.test.tsx +37 -0
- package/src/test/commands/__snapshots__/packShapes.test.ts.snap +6 -6
- package/src/test/commands/lockShapes.test.ts +11 -0
- package/src/test/commands/packShapes.test.ts +20 -0
- package/src/test/commands/putContent.test.ts +35 -1
- package/src/test/commands/setCamera.test.ts +69 -0
- package/src/test/commands/stackShapes.test.ts +12 -0
- package/src/test/commands/updateViewportPageBounds.test.ts +8 -0
- package/src/test/cropping.test.ts +162 -0
- package/src/test/customSnapping.test.tsx +32 -0
- package/src/test/defaultHandleExternalFileContent.test.ts +86 -0
- package/src/test/drawing.test.ts +60 -1
- package/src/test/duplicate.test.ts +22 -0
- package/src/test/frames.test.ts +51 -0
- package/src/test/getShapeAtPoint.test.ts +44 -1
- package/src/test/handleDeepLink.test.tsx +15 -0
- package/src/test/minimap-wheel.test.tsx +48 -0
- package/src/test/resizing.test.ts +46 -0
- package/src/test/selection-omnibus.test.ts +50 -0
- package/src/test/spacebarPanning.test.ts +58 -0
- package/src/test/translating.test.ts +42 -0
- package/src/test/ui/AltTextEditor.test.tsx +51 -0
- package/src/test/ui/ContextMenu.test.tsx +61 -2
- package/src/test/ui/EditLinkDialog.test.tsx +77 -0
- package/src/test/ui/ImageToolbar.test.tsx +58 -0
- package/src/test/ui/StylePanel.test.tsx +33 -2
- package/src/test/ui/keyboardShortcuts.test.tsx +27 -0
- package/src/test/ui/presenceActivity.test.tsx +44 -0
- package/src/test/ui/unlockAll.test.tsx +55 -0
- package/src/test/ui-outside-editor.test.tsx +74 -0
- package/src/test/viewport-following.test.ts +29 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/tools/SelectTool/childStates/Translating.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBoundsSnapPoint,\n\tEditor,\n\tMat,\n\tMatModel,\n\tPageRecordType,\n\tStateNode,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLTickEventInfo,\n\tVec,\n\tbind,\n\tcompact,\n\tisPageId,\n\tkickoutOccludedShapes,\n} from '@tldraw/editor'\nimport {\n\tNOTE_ADJACENT_POSITION_SNAP_RADIUS,\n\tgetAvailableNoteAdjacentPositions,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { DragAndDropManager } from '../DragAndDropManager'\n\nexport type TranslatingInfo = TLPointerEventInfo & {\n\ttarget: 'shape'\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n\tonCreate?(): void\n\tonInteractionEnd?: string | (() => void)\n}\n\nexport class Translating extends StateNode {\n\tstatic override id = 'translating'\n\tstatic override trackPerformance = true\n\n\tinfo = {} as TranslatingInfo\n\n\tselectionSnapshot: TranslatingSnapshot = {} as any\n\n\tsnapshot: TranslatingSnapshot = {} as any\n\n\tmarkId = ''\n\n\tisCloning = false\n\tisCreating = false\n\tonCreate(_shape: TLShape | null): void {\n\t\treturn\n\t}\n\n\tdragAndDropManager = new DragAndDropManager(this.editor)\n\n\toverride onEnter(info: TranslatingInfo) {\n\t\tconst { isCreating = false, creatingMarkId, onCreate = () => void null } = info\n\n\t\tif (!this.editor.getSelectedShapeIds()?.length) {\n\t\t\tthis.parent.transition('idle')\n\t\t\treturn\n\t\t}\n\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.isCreating = isCreating\n\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('translating')\n\t\t}\n\n\t\tthis.onCreate = onCreate\n\n\t\tthis.isCloning = false\n\t\tthis.info = info\n\n\t\tthis.editor.setCursor({ type: 'move', rotation: 0 })\n\t\tthis.selectionSnapshot = getTranslatingSnapshot(this.editor)\n\n\t\t// Don't clone on create; otherwise clone on altKey\n\t\tif (!this.isCreating) {\n\t\t\tif (this.editor.inputs.getAltKey()) {\n\t\t\t\tthis.startCloning()\n\t\t\t\tif (this.isCloning) return\n\t\t\t}\n\t\t}\n\n\t\tthis.snapshot = this.selectionSnapshot\n\t\tthis.handleStart()\n\t\tthis.updateShapes()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.selectionSnapshot = {} as any\n\t\tthis.snapshot = {} as any\n\t\tthis.editor.snaps.clearIndicators()\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t\tthis.dragAndDropManager.clear()\n\t}\n\n\toverride onTick({ elapsed }: TLTickEventInfo) {\n\t\tconst { editor } = this\n\t\tif (!editor.inputs.getIsDragging() || editor.inputs.getIsPanning()) return\n\t\teditor.edgeScrollManager.updateEdgeScrolling(elapsed)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyDown() {\n\t\tif (this.editor.inputs.getAltKey() && !this.isCloning) {\n\t\t\tthis.startCloning()\n\t\t\tif (this.isCloning) return\n\t\t}\n\n\t\t// need to update in case user pressed a different modifier key\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyUp() {\n\t\tif (!this.editor.inputs.getAltKey() && this.isCloning) {\n\t\t\tthis.stopCloning()\n\t\t\treturn\n\t\t}\n\n\t\t// need to update in case user pressed a different modifier key\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\tprotected startCloning() {\n\t\tif (this.isCreating) return\n\t\tconst shapeIds = Array.from(this.editor.getSelectedShapeIds())\n\n\t\t// If we can't create the shapes, don't even start cloning\n\t\tif (!this.editor.canCreateShapes(shapeIds)) return\n\n\t\tthis.isCloning = true\n\t\tthis.reset()\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('translate cloning')\n\n\t\tthis.editor.duplicateShapes(Array.from(this.editor.getSelectedShapeIds()))\n\n\t\tthis.snapshot = getTranslatingSnapshot(this.editor)\n\t\tthis.handleStart()\n\t\tthis.updateShapes()\n\t}\n\n\tprotected stopCloning() {\n\t\tthis.isCloning = false\n\t\tthis.snapshot = this.selectionSnapshot\n\t\tthis.reset()\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('translate')\n\t\tthis.updateShapes()\n\t}\n\n\treset() {\n\t\tthis.editor.bailToMark(this.markId)\n\t}\n\n\tprotected complete() {\n\t\tthis.updateShapes()\n\t\tthis.dragAndDropManager.dropShapes(this.snapshot.movingShapes)\n\t\tthis.handleEnd()\n\t\tkickoutOccludedShapes(\n\t\t\tthis.editor,\n\t\t\tthis.snapshot.movingShapes.map((s) => s.id)\n\t\t)\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (this.isCreating) {\n\t\t\tthis.onCreate?.(this.editor.getOnlySelectedShape())\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\t// Call onTranslateCancel callback before resetting\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)\n\t\t\tif (current) {\n\t\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\t\tutil.onTranslateCancel?.(shape, current)\n\t\t\t}\n\t\t})\n\n\t\tthis.reset()\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd)\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\tprotected handleStart() {\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslateStart?.(shape)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\n\t\tthis.dragAndDropManager.startDraggingShapes(\n\t\t\t// Get fresh shapes from the snapshot, in case onTranslateStart mutates the shape\n\t\t\tcompact(this.snapshot.movingShapes.map((s) => this.editor.getShape(s.id))),\n\t\t\t// Start from the place where the user started dragging\n\t\t\tthis.editor.inputs.getOriginPagePoint(),\n\t\t\tthis.updateParentTransforms\n\t\t)\n\n\t\tthis.editor.setHoveredShape(null)\n\t}\n\n\tprotected handleEnd() {\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tif (this.isCloning && movingShapes.length > 0) {\n\t\t\tconst currentAveragePagePoint = Vec.Average(\n\t\t\t\tmovingShapes.map((s) => this.editor.getShapePageTransform(s.id)!.point())\n\t\t\t)\n\t\t\tconst offset = Vec.Sub(currentAveragePagePoint, this.selectionSnapshot.averagePagePoint)\n\t\t\tif (!Vec.IsNaN(offset)) {\n\t\t\t\tthis.editor.updateInstanceState({\n\t\t\t\t\tduplicateProps: {\n\t\t\t\t\t\tshapeIds: movingShapes.map((s) => s.id),\n\t\t\t\t\t\toffset: { x: offset.x, y: offset.y },\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslateEnd?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprotected updateShapes() {\n\t\tconst { snapshot } = this\n\n\t\t// We should have started already, but hey\n\t\tthis.dragAndDropManager.startDraggingShapes(\n\t\t\tsnapshot.movingShapes,\n\t\t\tthis.editor.inputs.getOriginPagePoint(),\n\t\t\tthis.updateParentTransforms\n\t\t)\n\n\t\tmoveShapesToPoint({\n\t\t\teditor: this.editor,\n\t\t\tsnapshot,\n\t\t})\n\n\t\tconst { movingShapes } = snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslate?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\t@bind\n\tprotected updateParentTransforms() {\n\t\tconst {\n\t\t\teditor,\n\t\t\tsnapshot: { shapeSnapshots },\n\t\t} = this\n\t\tconst movingShapes: TLShape[] = []\n\n\t\tshapeSnapshots.forEach((shapeSnapshot) => {\n\t\t\tconst shape = editor.getShape(shapeSnapshot.shape.id)\n\t\t\tif (!shape) return\n\t\t\tmovingShapes.push(shape)\n\n\t\t\tconst parentTransform = isPageId(shape.parentId)\n\t\t\t\t? null\n\t\t\t\t: Mat.Inverse(editor.getShapePageTransform(shape.parentId)!)\n\n\t\t\tshapeSnapshot.parentTransform = parentTransform\n\t\t})\n\t}\n}\n\nfunction getTranslatingSnapshot(editor: Editor) {\n\tconst movingShapes: TLShape[] = []\n\tconst pagePoints: Vec[] = []\n\n\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\tconst shapeSnapshots = compact(\n\t\tselectedShapeIds.map((id): null | MovingShapeSnapshot => {\n\t\t\tconst shape = editor.getShape(id)\n\t\t\tif (!shape) return null\n\t\t\tmovingShapes.push(shape)\n\n\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\tconst pagePoint = pageTransform.point()\n\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\tpagePoints.push(pagePoint)\n\n\t\t\tconst parentTransform = PageRecordType.isId(shape.parentId)\n\t\t\t\t? null\n\t\t\t\t: Mat.Inverse(editor.getShapePageTransform(shape.parentId)!)\n\n\t\t\treturn {\n\t\t\t\tshape,\n\t\t\t\tpagePoint,\n\t\t\t\tpageRotation,\n\t\t\t\tparentTransform,\n\t\t\t}\n\t\t})\n\t)\n\n\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\n\tlet initialSnapPoints: BoundsSnapPoint[] = []\n\n\tif (onlySelectedShape) {\n\t\tinitialSnapPoints = editor.snaps.shapeBounds.getSnapPoints(onlySelectedShape.id)!\n\t} else {\n\t\tconst selectionPageBounds = editor.getSelectionPageBounds()\n\t\tif (selectionPageBounds) {\n\t\t\tinitialSnapPoints = selectionPageBounds.cornersAndCenter.map((p, i) => ({\n\t\t\t\tid: 'selection:' + i,\n\t\t\t\tx: p.x,\n\t\t\t\ty: p.y,\n\t\t\t}))\n\t\t}\n\t}\n\n\tlet noteAdjacentPositions: Vec[] | undefined\n\tlet noteSnapshot: (MovingShapeSnapshot & { shape: TLNoteShape }) | undefined\n\tlet noteCenterOffset: Vec | undefined\n\n\tconst originPagePoint = editor.inputs.getOriginPagePoint()\n\n\tconst allHoveredNotes = shapeSnapshots.filter(\n\t\t(s) => editor.isShapeOfType(s.shape, 'note') && editor.isPointInShape(s.shape, originPagePoint)\n\t) as (MovingShapeSnapshot & { shape: TLNoteShape })[]\n\n\tif (allHoveredNotes.length === 0) {\n\t\t// noop\n\t} else if (allHoveredNotes.length === 1) {\n\t\t// just one, easy\n\t\tnoteSnapshot = allHoveredNotes[0]\n\t} else {\n\t\t// More than one under the cursor, so we need to find the highest shape in z-order\n\t\tconst allShapesSorted = editor.getCurrentPageShapesSorted()\n\t\tnoteSnapshot = allHoveredNotes\n\t\t\t.map((s) => ({\n\t\t\t\tsnapshot: s,\n\t\t\t\tindex: allShapesSorted.findIndex((shape) => shape.id === s.shape.id),\n\t\t\t}))\n\t\t\t.sort((a, b) => b.index - a.index)[0]?.snapshot // highest up first\n\t}\n\n\tif (noteSnapshot) {\n\t\tconst noteUtil = editor.getShapeUtil(noteSnapshot.shape) as NoteShapeUtil\n\t\tconst dv = getDisplayValues(noteUtil, noteSnapshot.shape)\n\t\tnoteAdjacentPositions = getAvailableNoteAdjacentPositions(editor, {\n\t\t\trotation: noteSnapshot.pageRotation,\n\t\t\tscale: noteSnapshot.shape.props.scale,\n\t\t\textraHeight: noteSnapshot.shape.props.growY ?? 0,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t})\n\t\tnoteCenterOffset = new Vec(dv.noteWidth / 2, dv.noteHeight / 2)\n\t}\n\n\treturn {\n\t\taveragePagePoint: Vec.Average(pagePoints),\n\t\tmovingShapes,\n\t\tshapeSnapshots,\n\t\tinitialPageBounds: editor.getSelectionPageBounds()!,\n\t\tinitialSnapPoints,\n\t\tnoteAdjacentPositions,\n\t\tnoteSnapshot,\n\t\tnoteCenterOffset,\n\t}\n}\n\nexport type TranslatingSnapshot = ReturnType<typeof getTranslatingSnapshot>\n\nexport interface MovingShapeSnapshot {\n\tshape: TLShape\n\tpagePoint: Vec\n\tpageRotation: number\n\tparentTransform: MatModel | null\n}\n\nexport function moveShapesToPoint({\n\teditor,\n\tsnapshot,\n}: {\n\teditor: Editor\n\tsnapshot: TranslatingSnapshot\n}) {\n\tconst { inputs } = editor\n\n\tconst {\n\t\tnoteSnapshot,\n\t\tnoteAdjacentPositions,\n\t\tnoteCenterOffset,\n\t\tinitialPageBounds,\n\t\tinitialSnapPoints,\n\t\tshapeSnapshots,\n\t\taveragePagePoint,\n\t} = snapshot\n\n\tconst shiftKey = editor.inputs.getShiftKey()\n\tconst accelKey = editor.inputs.getAccelKey()\n\n\tconst isGridMode = editor.getInstanceState().isGridMode\n\n\tconst gridSize = editor.getDocumentSettings().gridSize\n\n\tconst delta = Vec.Sub(inputs.getCurrentPagePoint(), inputs.getOriginPagePoint())\n\n\tconst flatten: 'x' | 'y' | null = shiftKey\n\t\t? Math.abs(delta.x) < Math.abs(delta.y)\n\t\t\t? 'x'\n\t\t\t: 'y'\n\t\t: null\n\n\tif (flatten === 'x') {\n\t\tdelta.x = 0\n\t} else if (flatten === 'y') {\n\t\tdelta.y = 0\n\t}\n\n\t// Provisional snapping\n\teditor.snaps.clearIndicators()\n\n\t// If the user isn't moving super quick\n\tconst isSnapping = editor.user.getIsSnapMode() ? !accelKey : accelKey\n\tlet snappedToPit = false\n\tif (isSnapping && editor.inputs.getPointerVelocity().len() < 0.5) {\n\t\t// snapping\n\t\tconst { nudge } = editor.snaps.shapeBounds.snapTranslateShapes({\n\t\t\tdragDelta: delta,\n\t\t\tinitialSelectionPageBounds: initialPageBounds,\n\t\t\tlockedAxis: flatten,\n\t\t\tinitialSelectionSnapPoints: initialSnapPoints,\n\t\t})\n\n\t\tdelta.add(nudge)\n\t} else {\n\t\t// for sticky notes, snap to grid position next to other notes\n\t\tif (noteSnapshot && noteAdjacentPositions && noteCenterOffset) {\n\t\t\tconst { scale } = noteSnapshot.shape.props\n\t\t\tconst pageCenter = noteSnapshot.pagePoint\n\t\t\t\t.clone()\n\t\t\t\t.add(delta)\n\t\t\t\t// use the middle of the note, disregarding extra height\n\t\t\t\t.add(noteCenterOffset.clone().mul(scale).rot(noteSnapshot.pageRotation))\n\n\t\t\t// Find the pit with the center closest to the put center\n\t\t\tlet min = NOTE_ADJACENT_POSITION_SNAP_RADIUS / editor.getZoomLevel() // in screen space\n\t\t\tlet offset = new Vec(0, 0)\n\t\t\tfor (const pit of noteAdjacentPositions) {\n\t\t\t\t// We've already filtered pits with the same page rotation\n\t\t\t\tconst deltaToPit = Vec.Sub(pageCenter, pit)\n\t\t\t\tconst dist = deltaToPit.len()\n\t\t\t\tif (dist < min) {\n\t\t\t\t\tsnappedToPit = true\n\t\t\t\t\tmin = dist\n\t\t\t\t\toffset = deltaToPit\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdelta.sub(offset)\n\t\t}\n\t}\n\n\tconst averageSnappedPoint = Vec.Add(averagePagePoint, delta)\n\n\t// we don't want to snap to the grid if we're holding the accel key, if we've already snapped into a pit, or if we're showing snapping indicators\n\tconst snapIndicators = editor.snaps.getIndicators()\n\tif (isGridMode && !accelKey && !snappedToPit && snapIndicators.length === 0) {\n\t\taverageSnappedPoint.snapToGrid(gridSize)\n\t}\n\n\tconst averageSnap = Vec.Sub(averageSnappedPoint, averagePagePoint)\n\n\teditor.updateShapes(\n\t\tcompact(\n\t\t\tshapeSnapshots.map(({ shape, pagePoint, parentTransform }): TLShapePartial | null => {\n\t\t\t\tconst newPagePoint = Vec.Add(pagePoint, averageSnap)\n\n\t\t\t\tconst newLocalPoint = parentTransform\n\t\t\t\t\t? Mat.applyToPoint(parentTransform, newPagePoint)\n\t\t\t\t\t: newPagePoint\n\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: newLocalPoint.x,\n\t\t\t\t\ty: newLocalPoint.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t)\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import {\n\tBoundsSnapPoint,\n\tEditor,\n\tMat,\n\tMatModel,\n\tPageRecordType,\n\tStateNode,\n\tTLNoteShape,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLTickEventInfo,\n\tVec,\n\tbind,\n\tcompact,\n\tisPageId,\n\tkickoutOccludedShapes,\n} from '@tldraw/editor'\nimport {\n\tNOTE_ADJACENT_POSITION_SNAP_RADIUS,\n\tgetAvailableNoteAdjacentPositions,\n} from '../../../shapes/note/noteHelpers'\nimport type { NoteShapeUtil } from '../../../shapes/note/NoteShapeUtil'\nimport { getDisplayValues } from '../../../shapes/shared/getDisplayValues'\nimport { DragAndDropManager } from '../DragAndDropManager'\n\nexport type TranslatingInfo = TLPointerEventInfo & {\n\ttarget: 'shape'\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n\tonCreate?(): void\n\tonInteractionEnd?: string | (() => void)\n}\n\nexport class Translating extends StateNode {\n\tstatic override id = 'translating'\n\tstatic override trackPerformance = true\n\n\tinfo = {} as TranslatingInfo\n\n\tselectionSnapshot: TranslatingSnapshot = {} as any\n\n\tsnapshot: TranslatingSnapshot = {} as any\n\n\tmarkId = ''\n\n\tisCloning = false\n\tisCreating = false\n\tonCreate(_shape: TLShape | null): void {\n\t\treturn\n\t}\n\n\tdragAndDropManager = new DragAndDropManager(this.editor)\n\n\toverride onEnter(info: TranslatingInfo) {\n\t\tconst { isCreating = false, creatingMarkId, onCreate = () => void null } = info\n\n\t\tif (!this.editor.getSelectedShapeIds()?.length) {\n\t\t\tthis.parent.transition('idle')\n\t\t\treturn\n\t\t}\n\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.isCreating = isCreating\n\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('translating')\n\t\t}\n\n\t\tthis.onCreate = onCreate\n\n\t\tthis.isCloning = false\n\t\tthis.info = info\n\n\t\tthis.editor.setCursor({ type: 'move', rotation: 0 })\n\t\tthis.selectionSnapshot = getTranslatingSnapshot(this.editor)\n\n\t\t// Don't clone on create; otherwise clone on altKey\n\t\tif (!this.isCreating) {\n\t\t\tif (this.editor.inputs.getAltKey()) {\n\t\t\t\tthis.startCloning()\n\t\t\t\tif (this.isCloning) return\n\t\t\t}\n\t\t}\n\n\t\tthis.snapshot = this.selectionSnapshot\n\t\tthis.handleStart()\n\t\tthis.updateShapes()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.selectionSnapshot = {} as any\n\t\tthis.snapshot = {} as any\n\t\tthis.editor.snaps.clearIndicators()\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t\tthis.dragAndDropManager.clear()\n\t}\n\n\toverride onTick({ elapsed }: TLTickEventInfo) {\n\t\tconst { editor } = this\n\t\tif (!editor.inputs.getIsDragging() || editor.inputs.getIsPanning()) return\n\t\teditor.edgeScrollManager.updateEdgeScrolling(elapsed)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyDown() {\n\t\tif (this.editor.inputs.getAltKey() && !this.isCloning) {\n\t\t\tthis.startCloning()\n\t\t\tif (this.isCloning) return\n\t\t}\n\n\t\t// need to update in case user pressed a different modifier key\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyUp() {\n\t\tif (!this.editor.inputs.getAltKey() && this.isCloning) {\n\t\t\tthis.stopCloning()\n\t\t\treturn\n\t\t}\n\n\t\t// need to update in case user pressed a different modifier key\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\tprotected startCloning() {\n\t\tif (this.isCreating) return\n\t\tconst shapeIds = Array.from(this.editor.getSelectedShapeIds())\n\n\t\t// If we can't create the shapes, don't even start cloning\n\t\tif (!this.editor.canCreateShapes(shapeIds)) return\n\n\t\tthis.isCloning = true\n\t\tthis.reset()\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('translate cloning')\n\n\t\tthis.editor.duplicateShapes(Array.from(this.editor.getSelectedShapeIds()))\n\n\t\tthis.snapshot = getTranslatingSnapshot(this.editor)\n\t\t// The manager ignores startDraggingShapes while it is running, so it has to be\n\t\t// cleared or it keeps reparenting the originals instead of the clones\n\t\tthis.dragAndDropManager.clear()\n\t\tthis.handleStart()\n\t\tthis.updateShapes()\n\t}\n\n\tprotected stopCloning() {\n\t\tthis.isCloning = false\n\t\tthis.snapshot = this.selectionSnapshot\n\t\tthis.reset()\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('translate')\n\t\t// Same as in startCloning: the manager is still tracking the (now deleted) clones\n\t\tthis.dragAndDropManager.clear()\n\t\tthis.updateShapes()\n\t}\n\n\treset() {\n\t\tthis.editor.bailToMark(this.markId)\n\t}\n\n\tprotected complete() {\n\t\tthis.updateShapes()\n\t\tthis.dragAndDropManager.dropShapes(this.snapshot.movingShapes)\n\t\tthis.handleEnd()\n\t\tkickoutOccludedShapes(\n\t\t\tthis.editor,\n\t\t\tthis.snapshot.movingShapes.map((s) => s.id)\n\t\t)\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (this.isCreating) {\n\t\t\tthis.onCreate?.(this.editor.getOnlySelectedShape())\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\t// Call onTranslateCancel callback before resetting\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)\n\t\t\tif (current) {\n\t\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\t\tutil.onTranslateCancel?.(shape, current)\n\t\t\t}\n\t\t})\n\n\t\tthis.reset()\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd)\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle', this.info)\n\t}\n\n\tprotected handleStart() {\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslateStart?.(shape)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\n\t\tthis.dragAndDropManager.startDraggingShapes(\n\t\t\t// Get fresh shapes from the snapshot, in case onTranslateStart mutates the shape\n\t\t\tcompact(this.snapshot.movingShapes.map((s) => this.editor.getShape(s.id))),\n\t\t\t// Start from the place where the user started dragging\n\t\t\tthis.editor.inputs.getOriginPagePoint(),\n\t\t\tthis.updateParentTransforms\n\t\t)\n\n\t\tthis.editor.setHoveredShape(null)\n\t}\n\n\tprotected handleEnd() {\n\t\tconst { movingShapes } = this.snapshot\n\n\t\tif (this.isCloning && movingShapes.length > 0) {\n\t\t\tconst currentAveragePagePoint = Vec.Average(\n\t\t\t\tmovingShapes.map((s) => this.editor.getShapePageTransform(s.id)!.point())\n\t\t\t)\n\t\t\tconst offset = Vec.Sub(currentAveragePagePoint, this.selectionSnapshot.averagePagePoint)\n\t\t\tif (!Vec.IsNaN(offset)) {\n\t\t\t\tthis.editor.updateInstanceState({\n\t\t\t\t\tduplicateProps: {\n\t\t\t\t\t\tshapeIds: movingShapes.map((s) => s.id),\n\t\t\t\t\t\toffset: { x: offset.x, y: offset.y },\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslateEnd?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprotected updateShapes() {\n\t\tconst { snapshot } = this\n\n\t\t// We should have started already, but hey\n\t\tthis.dragAndDropManager.startDraggingShapes(\n\t\t\tsnapshot.movingShapes,\n\t\t\tthis.editor.inputs.getOriginPagePoint(),\n\t\t\tthis.updateParentTransforms\n\t\t)\n\n\t\tmoveShapesToPoint({\n\t\t\teditor: this.editor,\n\t\t\tsnapshot,\n\t\t})\n\n\t\tconst { movingShapes } = snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tmovingShapes.forEach((shape) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onTranslate?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\t@bind\n\tprotected updateParentTransforms() {\n\t\tconst {\n\t\t\teditor,\n\t\t\tsnapshot: { shapeSnapshots },\n\t\t} = this\n\t\tconst movingShapes: TLShape[] = []\n\n\t\tshapeSnapshots.forEach((shapeSnapshot) => {\n\t\t\tconst shape = editor.getShape(shapeSnapshot.shape.id)\n\t\t\tif (!shape) return\n\t\t\tmovingShapes.push(shape)\n\n\t\t\tconst parentTransform = isPageId(shape.parentId)\n\t\t\t\t? null\n\t\t\t\t: Mat.Inverse(editor.getShapePageTransform(shape.parentId)!)\n\n\t\t\tshapeSnapshot.parentTransform = parentTransform\n\t\t})\n\t}\n}\n\nfunction getTranslatingSnapshot(editor: Editor) {\n\tconst movingShapes: TLShape[] = []\n\tconst pagePoints: Vec[] = []\n\n\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\tconst shapeSnapshots = compact(\n\t\tselectedShapeIds.map((id): null | MovingShapeSnapshot => {\n\t\t\tconst shape = editor.getShape(id)\n\t\t\tif (!shape) return null\n\t\t\tmovingShapes.push(shape)\n\n\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\tconst pagePoint = pageTransform.point()\n\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\tpagePoints.push(pagePoint)\n\n\t\t\tconst parentTransform = PageRecordType.isId(shape.parentId)\n\t\t\t\t? null\n\t\t\t\t: Mat.Inverse(editor.getShapePageTransform(shape.parentId)!)\n\n\t\t\treturn {\n\t\t\t\tshape,\n\t\t\t\tpagePoint,\n\t\t\t\tpageRotation,\n\t\t\t\tparentTransform,\n\t\t\t}\n\t\t})\n\t)\n\n\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\n\tlet initialSnapPoints: BoundsSnapPoint[] = []\n\n\tif (onlySelectedShape) {\n\t\tinitialSnapPoints = editor.snaps.shapeBounds.getSnapPoints(onlySelectedShape.id)!\n\t} else {\n\t\tconst selectionPageBounds = editor.getSelectionPageBounds()\n\t\tif (selectionPageBounds) {\n\t\t\tinitialSnapPoints = selectionPageBounds.cornersAndCenter.map((p, i) => ({\n\t\t\t\tid: 'selection:' + i,\n\t\t\t\tx: p.x,\n\t\t\t\ty: p.y,\n\t\t\t}))\n\t\t}\n\t}\n\n\tlet noteAdjacentPositions: Vec[] | undefined\n\tlet noteSnapshot: (MovingShapeSnapshot & { shape: TLNoteShape }) | undefined\n\tlet noteCenterOffset: Vec | undefined\n\n\tconst originPagePoint = editor.inputs.getOriginPagePoint()\n\n\tconst allHoveredNotes = shapeSnapshots.filter(\n\t\t(s) => editor.isShapeOfType(s.shape, 'note') && editor.isPointInShape(s.shape, originPagePoint)\n\t) as (MovingShapeSnapshot & { shape: TLNoteShape })[]\n\n\tif (allHoveredNotes.length === 0) {\n\t\t// noop\n\t} else if (allHoveredNotes.length === 1) {\n\t\t// just one, easy\n\t\tnoteSnapshot = allHoveredNotes[0]\n\t} else {\n\t\t// More than one under the cursor, so we need to find the highest shape in z-order\n\t\tconst allShapesSorted = editor.getCurrentPageShapesSorted()\n\t\tnoteSnapshot = allHoveredNotes\n\t\t\t.map((s) => ({\n\t\t\t\tsnapshot: s,\n\t\t\t\tindex: allShapesSorted.findIndex((shape) => shape.id === s.shape.id),\n\t\t\t}))\n\t\t\t.sort((a, b) => b.index - a.index)[0]?.snapshot // highest up first\n\t}\n\n\tif (noteSnapshot) {\n\t\tconst noteUtil = editor.getShapeUtil(noteSnapshot.shape) as NoteShapeUtil\n\t\tconst dv = getDisplayValues(noteUtil, noteSnapshot.shape)\n\t\tnoteAdjacentPositions = getAvailableNoteAdjacentPositions(editor, {\n\t\t\trotation: noteSnapshot.pageRotation,\n\t\t\tscale: noteSnapshot.shape.props.scale,\n\t\t\textraHeight: noteSnapshot.shape.props.growY ?? 0,\n\t\t\tnoteWidth: dv.noteWidth,\n\t\t\tnoteHeight: dv.noteHeight,\n\t\t\texcludeShapeIds: selectedShapeIds,\n\t\t})\n\t\tnoteCenterOffset = new Vec(dv.noteWidth / 2, dv.noteHeight / 2)\n\t}\n\n\treturn {\n\t\taveragePagePoint: Vec.Average(pagePoints),\n\t\tmovingShapes,\n\t\tshapeSnapshots,\n\t\tinitialPageBounds: editor.getSelectionPageBounds()!,\n\t\tinitialSnapPoints,\n\t\tnoteAdjacentPositions,\n\t\tnoteSnapshot,\n\t\tnoteCenterOffset,\n\t}\n}\n\nexport type TranslatingSnapshot = ReturnType<typeof getTranslatingSnapshot>\n\nexport interface MovingShapeSnapshot {\n\tshape: TLShape\n\tpagePoint: Vec\n\tpageRotation: number\n\tparentTransform: MatModel | null\n}\n\nexport function moveShapesToPoint({\n\teditor,\n\tsnapshot,\n}: {\n\teditor: Editor\n\tsnapshot: TranslatingSnapshot\n}) {\n\tconst { inputs } = editor\n\n\tconst {\n\t\tnoteSnapshot,\n\t\tnoteAdjacentPositions,\n\t\tnoteCenterOffset,\n\t\tinitialPageBounds,\n\t\tinitialSnapPoints,\n\t\tshapeSnapshots,\n\t\taveragePagePoint,\n\t} = snapshot\n\n\tconst shiftKey = editor.inputs.getShiftKey()\n\tconst accelKey = editor.inputs.getAccelKey()\n\n\tconst isGridMode = editor.getInstanceState().isGridMode\n\n\tconst gridSize = editor.getDocumentSettings().gridSize\n\n\tconst delta = Vec.Sub(inputs.getCurrentPagePoint(), inputs.getOriginPagePoint())\n\n\tconst flatten: 'x' | 'y' | null = shiftKey\n\t\t? Math.abs(delta.x) < Math.abs(delta.y)\n\t\t\t? 'x'\n\t\t\t: 'y'\n\t\t: null\n\n\tif (flatten === 'x') {\n\t\tdelta.x = 0\n\t} else if (flatten === 'y') {\n\t\tdelta.y = 0\n\t}\n\n\t// Provisional snapping\n\teditor.snaps.clearIndicators()\n\n\t// If the user isn't moving super quick\n\tconst isSnapping = editor.user.getIsSnapMode() ? !accelKey : accelKey\n\tlet snappedToPit = false\n\tif (isSnapping && editor.inputs.getPointerVelocity().len() < 0.5) {\n\t\t// snapping\n\t\tconst { nudge } = editor.snaps.shapeBounds.snapTranslateShapes({\n\t\t\tdragDelta: delta,\n\t\t\tinitialSelectionPageBounds: initialPageBounds,\n\t\t\tlockedAxis: flatten,\n\t\t\tinitialSelectionSnapPoints: initialSnapPoints,\n\t\t})\n\n\t\tdelta.add(nudge)\n\t} else {\n\t\t// for sticky notes, snap to grid position next to other notes\n\t\tif (noteSnapshot && noteAdjacentPositions && noteCenterOffset) {\n\t\t\tconst { scale } = noteSnapshot.shape.props\n\t\t\tconst pageCenter = noteSnapshot.pagePoint\n\t\t\t\t.clone()\n\t\t\t\t.add(delta)\n\t\t\t\t// use the middle of the note, disregarding extra height\n\t\t\t\t.add(noteCenterOffset.clone().mul(scale).rot(noteSnapshot.pageRotation))\n\n\t\t\t// Find the pit with the center closest to the put center\n\t\t\tlet min = NOTE_ADJACENT_POSITION_SNAP_RADIUS / editor.getZoomLevel() // in screen space\n\t\t\tlet offset = new Vec(0, 0)\n\t\t\tfor (const pit of noteAdjacentPositions) {\n\t\t\t\t// We've already filtered pits with the same page rotation\n\t\t\t\tconst deltaToPit = Vec.Sub(pageCenter, pit)\n\t\t\t\tconst dist = deltaToPit.len()\n\t\t\t\tif (dist < min) {\n\t\t\t\t\tsnappedToPit = true\n\t\t\t\t\tmin = dist\n\t\t\t\t\toffset = deltaToPit\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdelta.sub(offset)\n\t\t}\n\t}\n\n\tconst averageSnappedPoint = Vec.Add(averagePagePoint, delta)\n\n\t// we don't want to snap to the grid if we're holding the accel key, if we've already snapped into a pit, or if we're showing snapping indicators\n\tconst snapIndicators = editor.snaps.getIndicators()\n\tif (isGridMode && !accelKey && !snappedToPit && snapIndicators.length === 0) {\n\t\taverageSnappedPoint.snapToGrid(gridSize)\n\t}\n\n\tconst averageSnap = Vec.Sub(averageSnappedPoint, averagePagePoint)\n\n\teditor.updateShapes(\n\t\tcompact(\n\t\t\tshapeSnapshots.map(({ shape, pagePoint, parentTransform }): TLShapePartial | null => {\n\t\t\t\tconst newPagePoint = Vec.Add(pagePoint, averageSnap)\n\n\t\t\t\tconst newLocalPoint = parentTransform\n\t\t\t\t\t? Mat.applyToPoint(parentTransform, newPagePoint)\n\t\t\t\t\t: newPagePoint\n\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: newLocalPoint.x,\n\t\t\t\t\ty: newLocalPoint.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var selectHelpers_exports = {};
|
|
20
20
|
__export(selectHelpers_exports, {
|
|
21
21
|
hasRichText: () => hasRichText,
|
|
22
|
+
startEditingShape: () => startEditingShape,
|
|
22
23
|
startEditingShapeWithRichText: () => startEditingShapeWithRichText
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(selectHelpers_exports);
|
|
@@ -43,4 +44,13 @@ function startEditingShapeWithRichText(editor, shapeOrId, options = {}) {
|
|
|
43
44
|
editor.emit("select-all-text", { shapeId: shape.id });
|
|
44
45
|
}
|
|
45
46
|
}
|
|
47
|
+
function startEditingShape(editor, shape, options = {}) {
|
|
48
|
+
if (!editor.canEditShape(shape)) return;
|
|
49
|
+
if (hasRichText(shape)) {
|
|
50
|
+
startEditingShapeWithRichText(editor, shape, options);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
editor.setEditingShape(shape);
|
|
54
|
+
editor.setCurrentTool("select.editing_shape", { ...options.info, target: "shape", shape });
|
|
55
|
+
}
|
|
46
56
|
//# sourceMappingURL=selectHelpers.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/tools/SelectTool/selectHelpers.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tExtractShapeByProps,\n\trichTextValidator,\n\tTLEventInfo,\n\tTLRichText,\n\tTLShape,\n\tTLShapeId,\n} from '@tldraw/editor'\n\n/** @internal */\nexport function hasRichText(\n\tshape: TLShape\n): shape is ExtractShapeByProps<{ richText: TLRichText }> {\n\treturn 'richText' in shape.props && richTextValidator.isValid(shape.props.richText)\n}\n/**\n * Start editing a shape that has rich text, such as text, note, geo, or arrow shapes.\n * This will enter the editing state for the shape and optionally select all the text.\n *\n * @param editor - The editor instance.\n * @param shapeOrId - The shape to start editing. This shape must have a richText property with a TLRichText value.\n * @param options - Options: selectAll or info (TLEventInfo)\n *\n * @public\n */\nexport function startEditingShapeWithRichText(\n\teditor: Editor,\n\tshapeOrId: TLShape | TLShapeId,\n\toptions: { selectAll?: boolean; info?: TLEventInfo } = {}\n) {\n\tconst shape = typeof shapeOrId === 'string' ? editor.getShape(shapeOrId) : shapeOrId\n\tif (!shape) return\n\n\tif (!editor.canEditShape(shape)) return\n\n\tif (!hasRichText(shape)) {\n\t\tthrow new Error('Shape does not have rich text')\n\t}\n\t// Finish this shape and start editing the next one\n\teditor.setEditingShape(shape)\n\teditor.setCurrentTool('select.editing_shape', {\n\t\t...options.info,\n\t\ttarget: 'shape',\n\t\tshape: shape,\n\t})\n\tif (options.selectAll) {\n\t\teditor.emit('select-all-text', { shapeId: shape.id })\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAQO;AAGA,SAAS,YACf,OACyD;AACzD,SAAO,cAAc,MAAM,SAAS,gCAAkB,QAAQ,MAAM,MAAM,QAAQ;AACnF;AAWO,SAAS,8BACf,QACA,WACA,UAAuD,CAAC,GACvD;AACD,QAAM,QAAQ,OAAO,cAAc,WAAW,OAAO,SAAS,SAAS,IAAI;AAC3E,MAAI,CAAC,MAAO;AAEZ,MAAI,CAAC,OAAO,aAAa,KAAK,EAAG;AAEjC,MAAI,CAAC,YAAY,KAAK,GAAG;AACxB,UAAM,IAAI,MAAM,+BAA+B;AAAA,EAChD;AAEA,SAAO,gBAAgB,KAAK;AAC5B,SAAO,eAAe,wBAAwB;AAAA,IAC7C,GAAG,QAAQ;AAAA,IACX,QAAQ;AAAA,IACR;AAAA,EACD,CAAC;AACD,MAAI,QAAQ,WAAW;AACtB,WAAO,KAAK,mBAAmB,EAAE,SAAS,MAAM,GAAG,CAAC;AAAA,EACrD;AACD;",
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tExtractShapeByProps,\n\trichTextValidator,\n\tTLEventInfo,\n\tTLRichText,\n\tTLShape,\n\tTLShapeId,\n} from '@tldraw/editor'\n\n/** @internal */\nexport function hasRichText(\n\tshape: TLShape\n): shape is ExtractShapeByProps<{ richText: TLRichText }> {\n\treturn 'richText' in shape.props && richTextValidator.isValid(shape.props.richText)\n}\n/**\n * Start editing a shape that has rich text, such as text, note, geo, or arrow shapes.\n * This will enter the editing state for the shape and optionally select all the text.\n *\n * @param editor - The editor instance.\n * @param shapeOrId - The shape to start editing. This shape must have a richText property with a TLRichText value.\n * @param options - Options: selectAll or info (TLEventInfo)\n *\n * @public\n */\nexport function startEditingShapeWithRichText(\n\teditor: Editor,\n\tshapeOrId: TLShape | TLShapeId,\n\toptions: { selectAll?: boolean; info?: TLEventInfo } = {}\n) {\n\tconst shape = typeof shapeOrId === 'string' ? editor.getShape(shapeOrId) : shapeOrId\n\tif (!shape) return\n\n\tif (!editor.canEditShape(shape)) return\n\n\tif (!hasRichText(shape)) {\n\t\tthrow new Error('Shape does not have rich text')\n\t}\n\t// Finish this shape and start editing the next one\n\teditor.setEditingShape(shape)\n\teditor.setCurrentTool('select.editing_shape', {\n\t\t...options.info,\n\t\ttarget: 'shape',\n\t\tshape: shape,\n\t})\n\tif (options.selectAll) {\n\t\teditor.emit('select-all-text', { shapeId: shape.id })\n\t}\n}\n\n/**\n * Start editing any editable shape. Shapes with rich text go through\n * `startEditingShapeWithRichText`; editable shapes without it (frame, video, embed) would\n * make that helper throw, so they enter the editing state directly.\n *\n * @internal\n */\nexport function startEditingShape(\n\teditor: Editor,\n\tshape: TLShape,\n\toptions: { selectAll?: boolean; info?: TLEventInfo } = {}\n) {\n\tif (!editor.canEditShape(shape)) return\n\tif (hasRichText(shape)) {\n\t\tstartEditingShapeWithRichText(editor, shape, options)\n\t\treturn\n\t}\n\teditor.setEditingShape(shape)\n\teditor.setCurrentTool('select.editing_shape', { ...options.info, target: 'shape', shape })\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAQO;AAGA,SAAS,YACf,OACyD;AACzD,SAAO,cAAc,MAAM,SAAS,gCAAkB,QAAQ,MAAM,MAAM,QAAQ;AACnF;AAWO,SAAS,8BACf,QACA,WACA,UAAuD,CAAC,GACvD;AACD,QAAM,QAAQ,OAAO,cAAc,WAAW,OAAO,SAAS,SAAS,IAAI;AAC3E,MAAI,CAAC,MAAO;AAEZ,MAAI,CAAC,OAAO,aAAa,KAAK,EAAG;AAEjC,MAAI,CAAC,YAAY,KAAK,GAAG;AACxB,UAAM,IAAI,MAAM,+BAA+B;AAAA,EAChD;AAEA,SAAO,gBAAgB,KAAK;AAC5B,SAAO,eAAe,wBAAwB;AAAA,IAC7C,GAAG,QAAQ;AAAA,IACX,QAAQ;AAAA,IACR;AAAA,EACD,CAAC;AACD,MAAI,QAAQ,WAAW;AACtB,WAAO,KAAK,mBAAmB,EAAE,SAAS,MAAM,GAAG,CAAC;AAAA,EACrD;AACD;AASO,SAAS,kBACf,QACA,OACA,UAAuD,CAAC,GACvD;AACD,MAAI,CAAC,OAAO,aAAa,KAAK,EAAG;AACjC,MAAI,YAAY,KAAK,GAAG;AACvB,kCAA8B,QAAQ,OAAO,OAAO;AACpD;AAAA,EACD;AACA,SAAO,gBAAgB,KAAK;AAC5B,SAAO,eAAe,wBAAwB,EAAE,GAAG,QAAQ,MAAM,QAAQ,SAAS,MAAM,CAAC;AAC1F;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -22,7 +22,6 @@ __export(DefaultActionsMenu_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(DefaultActionsMenu_exports);
|
|
24
24
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
|
-
var import_editor = require("@tldraw/editor");
|
|
26
25
|
var import_react = require("react");
|
|
27
26
|
var import_constants = require("../../constants");
|
|
28
27
|
var import_breakpoints = require("../../context/breakpoints");
|
|
@@ -41,14 +40,8 @@ const DefaultActionsMenu = (0, import_react.memo)(function DefaultActionsMenu2({
|
|
|
41
40
|
const breakpoint = (0, import_breakpoints.useBreakpoint)();
|
|
42
41
|
const isReadonlyMode = (0, import_useReadonly.useReadonly)();
|
|
43
42
|
const { orientation } = (0, import_layout.useTldrawUiOrientation)();
|
|
44
|
-
const editor = (0, import_editor.useEditor)();
|
|
45
|
-
const isInAcceptableReadonlyState = (0, import_editor.useValue)(
|
|
46
|
-
"should display quick actions when in readonly",
|
|
47
|
-
() => editor.isInAny("hand", "zoom"),
|
|
48
|
-
[editor]
|
|
49
|
-
);
|
|
50
43
|
const content = children ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_DefaultActionsMenuContent.DefaultActionsMenuContent, {});
|
|
51
|
-
if (isReadonlyMode
|
|
44
|
+
if (isReadonlyMode) return;
|
|
52
45
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_TldrawUiPopover.TldrawUiPopover, { id: "actions-menu", children: [
|
|
53
46
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiPopover.TldrawUiPopoverTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
54
47
|
import_TldrawUiToolbar.TldrawUiToolbarButton,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { ReactNode, memo } from 'react'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { useReadonly } from '../../hooks/useReadonly'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport { useTldrawUiOrientation } from '../primitives/layout'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { DefaultActionsMenuContent } from './DefaultActionsMenuContent'\n\n/** @public */\nexport interface TLUiActionsMenuProps {\n\tchildren?: ReactNode\n}\n\n/** @public @react */\nexport const DefaultActionsMenu = memo(function DefaultActionsMenu({\n\tchildren,\n}: TLUiActionsMenuProps) {\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst { orientation } = useTldrawUiOrientation()\n\n\t// Get the actions menu content, either the default component or the user's\n\t// override. If there's no menu content, then the user has set it to null,\n\t// so skip rendering the menu.\n\n\tconst content = children ?? <DefaultActionsMenuContent />\n\n\t// Every default action edits shapes, so in readonly mode the menu would open empty\n\tif (isReadonlyMode) return\n\n\treturn (\n\t\t<TldrawUiPopover id=\"actions-menu\">\n\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\tdata-testid=\"actions-menu.button\"\n\t\t\t\t\ttitle={msg('actions-menu.title')}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon\n\t\t\t\t\t\ticon={orientation === 'horizontal' ? 'dots-vertical' : 'dots-horizontal'}\n\t\t\t\t\t\tsmall\n\t\t\t\t\t/>\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t<TldrawUiPopoverContent\n\t\t\t\tside={\n\t\t\t\t\torientation === 'horizontal'\n\t\t\t\t\t\t? breakpoint >= PORTRAIT_BREAKPOINT.TABLET\n\t\t\t\t\t\t\t? 'bottom'\n\t\t\t\t\t\t\t: 'top'\n\t\t\t\t\t\t: 'right'\n\t\t\t\t}\n\t\t\t\tsideOffset={6}\n\t\t\t>\n\t\t\t\t<TldrawUiToolbar\n\t\t\t\t\tlabel={msg('actions-menu.title')}\n\t\t\t\t\tclassName=\"tlui-actions-menu\"\n\t\t\t\t\tdata-testid=\"actions-menu.content\"\n\t\t\t\t\torientation=\"grid\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"icons\" sourceId=\"actions-menu\">\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t</TldrawUiToolbar>\n\t\t\t</TldrawUiPopoverContent>\n\t\t</TldrawUiPopover>\n\t)\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkC6B;AAlC7B,mBAAgC;AAChC,uBAAoC;AACpC,yBAA8B;AAC9B,yBAA4B;AAC5B,4BAA+B;AAC/B,gCAAmC;AACnC,oBAAuC;AACvC,iCAA4C;AAC5C,6BAIO;AACP,6BAAuD;AACvD,uCAA0C;AAQnC,MAAM,yBAAqB,mBAAK,SAASA,oBAAmB;AAAA,EAClE;AACD,GAAyB;AACxB,QAAM,UAAM,sCAAe;AAC3B,QAAM,iBAAa,kCAAc;AACjC,QAAM,qBAAiB,gCAAY;AACnC,QAAM,EAAE,YAAY,QAAI,sCAAuB;AAM/C,QAAM,UAAU,YAAY,4CAAC,8DAA0B;AAGvD,MAAI,eAAgB;AAEpB,SACC,6CAAC,0CAAgB,IAAG,gBACnB;AAAA,gDAAC,iDACA;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,OAAO,IAAI,oBAAoB;AAAA,QAE/B;AAAA,UAAC;AAAA;AAAA,YACA,MAAM,gBAAgB,eAAe,kBAAkB;AAAA,YACvD,OAAK;AAAA;AAAA,QACN;AAAA;AAAA,IACD,GACD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,MACC,gBAAgB,eACb,cAAc,qCAAoB,SACjC,WACA,QACD;AAAA,QAEJ,YAAY;AAAA,QAEZ;AAAA,UAAC;AAAA;AAAA,YACA,OAAO,IAAI,oBAAoB;AAAA,YAC/B,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,aAAY;AAAA,YAEZ,sDAAC,0DAA4B,MAAK,SAAQ,UAAS,gBACjD,mBACF;AAAA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,KACD;AAEF,CAAC;",
|
|
6
6
|
"names": ["DefaultActionsMenu"]
|
|
7
7
|
}
|
|
@@ -25,6 +25,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
25
25
|
var import_editor = require("@tldraw/editor");
|
|
26
26
|
var import_radix_ui = require("radix-ui");
|
|
27
27
|
var import_react = require("react");
|
|
28
|
+
var import_actions = require("../../context/actions");
|
|
28
29
|
var import_useMenuIsOpen = require("../../hooks/useMenuIsOpen");
|
|
29
30
|
var import_useTranslation = require("../../hooks/useTranslation/useTranslation");
|
|
30
31
|
var import_TldrawUiMenuContext = require("../primitives/menus/TldrawUiMenuContext");
|
|
@@ -59,9 +60,13 @@ const DefaultContextMenu = (0, import_react.memo)(function DefaultContextMenu2({
|
|
|
59
60
|
};
|
|
60
61
|
}, [editor, preventEscapeFromLosingShapeFocus]);
|
|
61
62
|
const suppressDismissUntilRef = (0, import_react.useRef)(0);
|
|
63
|
+
const rContextMenuPagePoint = (0, import_react.useContext)(import_actions.ContextMenuPagePointContext);
|
|
62
64
|
const cb = (0, import_react.useCallback)(
|
|
63
65
|
(isOpen2) => {
|
|
64
66
|
const body = editor.getContainerDocument().body;
|
|
67
|
+
if (rContextMenuPagePoint) {
|
|
68
|
+
rContextMenuPagePoint.current = isOpen2 ? editor.inputs.getCurrentPagePoint().clone() : null;
|
|
69
|
+
}
|
|
65
70
|
if (!isOpen2) {
|
|
66
71
|
const onlySelectedShape = editor.getOnlySelectedShape();
|
|
67
72
|
if (onlySelectedShape && editor.isShapeOrAncestorLocked(onlySelectedShape)) {
|
|
@@ -94,7 +99,7 @@ const DefaultContextMenu = (0, import_react.memo)(function DefaultContextMenu2({
|
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
},
|
|
97
|
-
[editor, preventEscapeFromLosingShapeFocus]
|
|
102
|
+
[editor, preventEscapeFromLosingShapeFocus, rContextMenuPagePoint]
|
|
98
103
|
);
|
|
99
104
|
const container = (0, import_editor.useContainer)();
|
|
100
105
|
const dir = (0, import_useTranslation.useDirection)();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tpreventDefault,\n\tuseContainer,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseValue,\n} from '@tldraw/editor'\nimport { ContextMenu as _ContextMenu } from 'radix-ui'\nimport { ReactNode, memo, useCallback, useEffect, useRef } from 'react'\nimport { useMenuIsOpen } from '../../hooks/useMenuIsOpen'\nimport { useDirection, useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\nimport { DefaultContextMenuContent } from './DefaultContextMenuContent'\n\n/** @public */\nexport interface TLUiContextMenuProps {\n\tchildren?: ReactNode\n\tdisabled?: boolean\n}\n\n/** @public @react */\nexport const DefaultContextMenu = memo(function DefaultContextMenu({\n\tchildren,\n\tdisabled = false,\n}: TLUiContextMenuProps) {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\n\tconst { Canvas } = useEditorComponents()\n\n\t// The context menu opens from a right-click in any tool, and from a touch\n\t// long-press only in the select tool (where it acts on the selection). A\n\t// right-click (fine pointer) is routed through the select tool by the editor; a\n\t// long-press in any other tool belongs to that tool's gesture (creating, erasing,\n\t// drawing, panning), so it opens nothing.\n\t//\n\t// The right-click case keys off the pointer type, not the tool, on purpose: a\n\t// right-click switches to select synchronously within the same gesture, so gating\n\t// it on the tool would race the React render and wrongly suppress the menu. The\n\t// select-tool long-press case is safe to gate on the tool \u2014 a long-press never\n\t// switches tools, so there is nothing to race.\n\tconst menuCanOpen = useValue(\n\t\t'context menu can open',\n\t\t() => !editor.getInstanceState().isCoarsePointer || editor.isIn('select'),\n\t\t[editor]\n\t)\n\n\t// When hitting `Escape` while the context menu is open, we want to prevent\n\t// the default behavior of losing focus on the shape. Otherwise,\n\t// it's pretty annoying from an accessibility perspective.\n\tconst preventEscapeFromLosingShapeFocus = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.stopPropagation()\n\t\t\t\teditor.getContainer().focus()\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\tuseEffect(() => {\n\t\tconst body = editor.getContainerDocument().body\n\t\treturn () => {\n\t\t\tbody.removeEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\tcapture: true,\n\t\t\t})\n\t\t}\n\t}, [editor, preventEscapeFromLosingShapeFocus])\n\n\t// On touch devices, the same touch that triggers Radix's long-press open is still\n\t// down when the menu mounts. The release fires events the dismissable layer treats\n\t// as an outside interaction and closes the menu. We swallow dismissals during a\n\t// short grace window after open so the menu stays put until the user actually\n\t// interacts again.\n\tconst suppressDismissUntilRef = useRef(0)\n\n\tconst cb = useCallback(\n\t\t(isOpen: boolean) => {\n\t\t\tconst body = editor.getContainerDocument().body\n\t\t\tif (!isOpen) {\n\t\t\t\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\n\t\t\t\tif (onlySelectedShape && editor.isShapeOrAncestorLocked(onlySelectedShape)) {\n\t\t\t\t\teditor.setSelectedShapes([])\n\t\t\t\t}\n\n\t\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\t\tbody.removeEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\t\t\tcapture: true,\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tbody.addEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\t\tcapture: true,\n\t\t\t\t})\n\n\t\t\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\t\t\tsuppressDismissUntilRef.current = Date.now() + 500\n\n\t\t\t\t\t// Weird route: selecting locked shapes on long press\n\t\t\t\t\tconst selectedShapes = editor.getSelectedShapes()\n\t\t\t\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\n\t\t\t\t\t// get all of the shapes under the current pointer\n\t\t\t\t\tconst shapesAtPoint = editor.getShapesAtPoint(currentPagePoint)\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t// if there are no selected shapes\n\t\t\t\t\t\t!editor.getSelectedShapes().length ||\n\t\t\t\t\t\t// OR if none of the shapes at the point include the selected shape\n\t\t\t\t\t\t!shapesAtPoint.some((s) => selectedShapes.includes(s))\n\t\t\t\t\t) {\n\t\t\t\t\t\t// then are there any locked shapes under the current pointer?\n\t\t\t\t\t\tconst lockedShapes = shapesAtPoint.filter((s) => editor.isShapeOrAncestorLocked(s))\n\n\t\t\t\t\t\tif (lockedShapes.length) {\n\t\t\t\t\t\t\t// nice, let's select them\n\t\t\t\t\t\t\teditor.select(...lockedShapes.map((s) => s.id))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, preventEscapeFromLosingShapeFocus]\n\t)\n\n\tconst container = useContainer()\n\tconst dir = useDirection()\n\tconst [isOpen, handleOpenChange] = useMenuIsOpen('context menu', cb)\n\n\t// Get the context menu content, either the default component or the user's\n\t// override. If there's no menu content, then the user has set it to null,\n\t// so skip rendering the menu.\n\tconst content = children ?? <DefaultContextMenuContent />\n\n\treturn (\n\t\t<_ContextMenu.Root dir={dir} onOpenChange={handleOpenChange} modal={false}>\n\t\t\t<_ContextMenu.Trigger\n\t\t\t\t// When suppressed, disabling the trigger stops Radix from opening the\n\t\t\t\t// menu, but it also stops Radix from preventing the native contextmenu \u2014\n\t\t\t\t// so prevent the browser's own menu ourselves in that case.\n\t\t\t\tonContextMenu={menuCanOpen ? undefined : preventDefault}\n\t\t\t\tdir=\"ltr\"\n\t\t\t\tdisabled={disabled || !menuCanOpen}\n\t\t\t>\n\t\t\t\t{Canvas ? <Canvas /> : null}\n\t\t\t</_ContextMenu.Trigger>\n\t\t\t{isOpen && (\n\t\t\t\t<_ContextMenu.Portal container={container}>\n\t\t\t\t\t<_ContextMenu.Content\n\t\t\t\t\t\tclassName=\"tlui-menu tlui-scrollable\"\n\t\t\t\t\t\tdata-testid=\"context-menu\"\n\t\t\t\t\t\taria-label={msg('context-menu.title')}\n\t\t\t\t\t\talignOffset={-4}\n\t\t\t\t\t\tcollisionPadding={4}\n\t\t\t\t\t\tonContextMenu={preventDefault}\n\t\t\t\t\t\tonPointerDownOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonInteractOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocusOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiMenuContextProvider type=\"context-menu\" sourceId=\"context-menu\">\n\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t\t</_ContextMenu.Content>\n\t\t\t\t</_ContextMenu.Portal>\n\t\t\t)}\n\t\t</_ContextMenu.Root>\n\t)\n})\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tpreventDefault,\n\tuseContainer,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseValue,\n} from '@tldraw/editor'\nimport { ContextMenu as _ContextMenu } from 'radix-ui'\nimport { ReactNode, memo, useCallback, useContext, useEffect, useRef } from 'react'\nimport { ContextMenuPagePointContext } from '../../context/actions'\nimport { useMenuIsOpen } from '../../hooks/useMenuIsOpen'\nimport { useDirection, useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\nimport { DefaultContextMenuContent } from './DefaultContextMenuContent'\n\n/** @public */\nexport interface TLUiContextMenuProps {\n\tchildren?: ReactNode\n\tdisabled?: boolean\n}\n\n/** @public @react */\nexport const DefaultContextMenu = memo(function DefaultContextMenu({\n\tchildren,\n\tdisabled = false,\n}: TLUiContextMenuProps) {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\n\tconst { Canvas } = useEditorComponents()\n\n\t// The context menu opens from a right-click in any tool, and from a touch\n\t// long-press only in the select tool (where it acts on the selection). A\n\t// right-click (fine pointer) is routed through the select tool by the editor; a\n\t// long-press in any other tool belongs to that tool's gesture (creating, erasing,\n\t// drawing, panning), so it opens nothing.\n\t//\n\t// The right-click case keys off the pointer type, not the tool, on purpose: a\n\t// right-click switches to select synchronously within the same gesture, so gating\n\t// it on the tool would race the React render and wrongly suppress the menu. The\n\t// select-tool long-press case is safe to gate on the tool \u2014 a long-press never\n\t// switches tools, so there is nothing to race.\n\tconst menuCanOpen = useValue(\n\t\t'context menu can open',\n\t\t() => !editor.getInstanceState().isCoarsePointer || editor.isIn('select'),\n\t\t[editor]\n\t)\n\n\t// When hitting `Escape` while the context menu is open, we want to prevent\n\t// the default behavior of losing focus on the shape. Otherwise,\n\t// it's pretty annoying from an accessibility perspective.\n\tconst preventEscapeFromLosingShapeFocus = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.stopPropagation()\n\t\t\t\teditor.getContainer().focus()\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\tuseEffect(() => {\n\t\tconst body = editor.getContainerDocument().body\n\t\treturn () => {\n\t\t\tbody.removeEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\tcapture: true,\n\t\t\t})\n\t\t}\n\t}, [editor, preventEscapeFromLosingShapeFocus])\n\n\t// On touch devices, the same touch that triggers Radix's long-press open is still\n\t// down when the menu mounts. The release fires events the dismissable layer treats\n\t// as an outside interaction and closes the menu. We swallow dismissals during a\n\t// short grace window after open so the menu stays put until the user actually\n\t// interacts again.\n\tconst suppressDismissUntilRef = useRef(0)\n\n\tconst rContextMenuPagePoint = useContext(ContextMenuPagePointContext)\n\n\tconst cb = useCallback(\n\t\t(isOpen: boolean) => {\n\t\t\tconst body = editor.getContainerDocument().body\n\t\t\tif (rContextMenuPagePoint) {\n\t\t\t\trContextMenuPagePoint.current = isOpen ? editor.inputs.getCurrentPagePoint().clone() : null\n\t\t\t}\n\t\t\tif (!isOpen) {\n\t\t\t\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\n\t\t\t\tif (onlySelectedShape && editor.isShapeOrAncestorLocked(onlySelectedShape)) {\n\t\t\t\t\teditor.setSelectedShapes([])\n\t\t\t\t}\n\n\t\t\t\teditor.timers.requestAnimationFrame(() => {\n\t\t\t\t\tbody.removeEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\t\t\tcapture: true,\n\t\t\t\t\t})\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tbody.addEventListener('keydown', preventEscapeFromLosingShapeFocus, {\n\t\t\t\t\tcapture: true,\n\t\t\t\t})\n\n\t\t\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\t\t\tsuppressDismissUntilRef.current = Date.now() + 500\n\n\t\t\t\t\t// Weird route: selecting locked shapes on long press\n\t\t\t\t\tconst selectedShapes = editor.getSelectedShapes()\n\t\t\t\t\tconst currentPagePoint = editor.inputs.getCurrentPagePoint()\n\n\t\t\t\t\t// get all of the shapes under the current pointer\n\t\t\t\t\tconst shapesAtPoint = editor.getShapesAtPoint(currentPagePoint)\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t// if there are no selected shapes\n\t\t\t\t\t\t!editor.getSelectedShapes().length ||\n\t\t\t\t\t\t// OR if none of the shapes at the point include the selected shape\n\t\t\t\t\t\t!shapesAtPoint.some((s) => selectedShapes.includes(s))\n\t\t\t\t\t) {\n\t\t\t\t\t\t// then are there any locked shapes under the current pointer?\n\t\t\t\t\t\tconst lockedShapes = shapesAtPoint.filter((s) => editor.isShapeOrAncestorLocked(s))\n\n\t\t\t\t\t\tif (lockedShapes.length) {\n\t\t\t\t\t\t\t// nice, let's select them\n\t\t\t\t\t\t\teditor.select(...lockedShapes.map((s) => s.id))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, preventEscapeFromLosingShapeFocus, rContextMenuPagePoint]\n\t)\n\n\tconst container = useContainer()\n\tconst dir = useDirection()\n\tconst [isOpen, handleOpenChange] = useMenuIsOpen('context menu', cb)\n\n\t// Get the context menu content, either the default component or the user's\n\t// override. If there's no menu content, then the user has set it to null,\n\t// so skip rendering the menu.\n\tconst content = children ?? <DefaultContextMenuContent />\n\n\treturn (\n\t\t<_ContextMenu.Root dir={dir} onOpenChange={handleOpenChange} modal={false}>\n\t\t\t<_ContextMenu.Trigger\n\t\t\t\t// When suppressed, disabling the trigger stops Radix from opening the\n\t\t\t\t// menu, but it also stops Radix from preventing the native contextmenu \u2014\n\t\t\t\t// so prevent the browser's own menu ourselves in that case.\n\t\t\t\tonContextMenu={menuCanOpen ? undefined : preventDefault}\n\t\t\t\tdir=\"ltr\"\n\t\t\t\tdisabled={disabled || !menuCanOpen}\n\t\t\t>\n\t\t\t\t{Canvas ? <Canvas /> : null}\n\t\t\t</_ContextMenu.Trigger>\n\t\t\t{isOpen && (\n\t\t\t\t<_ContextMenu.Portal container={container}>\n\t\t\t\t\t<_ContextMenu.Content\n\t\t\t\t\t\tclassName=\"tlui-menu tlui-scrollable\"\n\t\t\t\t\t\tdata-testid=\"context-menu\"\n\t\t\t\t\t\taria-label={msg('context-menu.title')}\n\t\t\t\t\t\talignOffset={-4}\n\t\t\t\t\t\tcollisionPadding={4}\n\t\t\t\t\t\tonContextMenu={preventDefault}\n\t\t\t\t\t\tonPointerDownOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonInteractOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFocusOutside={(e) => {\n\t\t\t\t\t\t\tif (Date.now() < suppressDismissUntilRef.current) e.preventDefault()\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiMenuContextProvider type=\"context-menu\" sourceId=\"context-menu\">\n\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t\t</_ContextMenu.Content>\n\t\t\t\t</_ContextMenu.Portal>\n\t\t\t)}\n\t\t</_ContextMenu.Root>\n\t)\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["DefaultContextMenu", "isOpen", "_ContextMenu"]
|
|
7
7
|
}
|
|
@@ -31,6 +31,7 @@ const TldrawUiDialog = ({ id, component: ModalContent, preventBackgroundClose })
|
|
|
31
31
|
const { removeDialog } = (0, import_dialogs.useDialogs)();
|
|
32
32
|
const container = (0, import_editor.useContainer)();
|
|
33
33
|
const dir = (0, import_useTranslation.useDirection)();
|
|
34
|
+
const contentRef = (0, import_react.useRef)(null);
|
|
34
35
|
const handleOpenChange = (0, import_react.useCallback)(
|
|
35
36
|
(isOpen) => {
|
|
36
37
|
if (!isOpen) {
|
|
@@ -44,10 +45,17 @@ const TldrawUiDialog = ({ id, component: ModalContent, preventBackgroundClose })
|
|
|
44
45
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { dir, className: "tlui-dialog__positioner", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
45
46
|
import_radix_ui.Dialog.Content,
|
|
46
47
|
{
|
|
48
|
+
ref: contentRef,
|
|
47
49
|
dir,
|
|
48
50
|
className: "tlui-dialog__content",
|
|
49
51
|
"aria-describedby": void 0,
|
|
50
52
|
onInteractOutside: (e) => {
|
|
53
|
+
const target = e.detail.originalEvent.target;
|
|
54
|
+
const pressedDialog = target instanceof Element ? target.closest(".tlui-dialog__content") : null;
|
|
55
|
+
if (pressedDialog && pressedDialog !== contentRef.current) {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
51
59
|
if (preventBackgroundClose) {
|
|
52
60
|
e.preventDefault();
|
|
53
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/ui/components/Dialogs.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useContainer, useValue } from '@tldraw/editor'\nimport { Dialog as _Dialog } from 'radix-ui'\nimport { memo, useCallback } from 'react'\nimport { TLUiDialog, useDialogs } from '../context/dialogs'\nimport { useDirection } from '../hooks/useTranslation/useTranslation'\n\n/** @internal */\nconst TldrawUiDialog = ({ id, component: ModalContent, preventBackgroundClose }: TLUiDialog) => {\n\tconst { removeDialog } = useDialogs()\n\n\tconst container = useContainer()\n\tconst dir = useDirection()\n\n\tconst handleOpenChange = useCallback(\n\t\t(isOpen: boolean) => {\n\t\t\tif (!isOpen) {\n\t\t\t\tremoveDialog(id)\n\t\t\t}\n\t\t},\n\t\t[id, removeDialog]\n\t)\n\n\treturn (\n\t\t<_Dialog.Root onOpenChange={handleOpenChange} defaultOpen>\n\t\t\t<_Dialog.Portal container={container}>\n\t\t\t\t{/* Radix renders the scrim and content as siblings. The positioner sits on\n\t\t\t\t top of the scrim and centers the content, scrolling and padding it when\n\t\t\t\t it's taller than the viewport. */}\n\t\t\t\t<_Dialog.Overlay dir={dir} className=\"tlui-dialog__overlay\" />\n\t\t\t\t<div dir={dir} className=\"tlui-dialog__positioner\">\n\t\t\t\t\t<_Dialog.Content\n\t\t\t\t\t\tdir={dir}\n\t\t\t\t\t\tclassName=\"tlui-dialog__content\"\n\t\t\t\t\t\taria-describedby={undefined}\n\t\t\t\t\t\tonInteractOutside={(e) => {\n\t\t\t\t\t\t\t// Radix's dismissable layers are layer-aware: an interaction outside the\n\t\t\t\t\t\t\t// topmost layer dismisses only that layer \u2014 an open select, or a dialog\n\t\t\t\t\t\t\t// stacked on top \u2014 leaving lower layers open. onInteractOutside fires for\n\t\t\t\t\t\t\t// both a pointer press and a focus shift outside the dialog; opt out of both\n\t\t\t\t\t\t\t// when the dialog asks to stay open on background interactions (escape still\n\t\t\t\t\t\t\t// closes it).\n\t\t\t\t\t\t\tif (preventBackgroundClose) {\n\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ModalContent onClose={() => handleOpenChange(false)} />\n\t\t\t\t\t</_Dialog.Content>\n\t\t\t\t</div>\n\t\t\t</_Dialog.Portal>\n\t\t</_Dialog.Root>\n\t)\n}\n\n/** @public @react */\nexport const DefaultDialogs = memo(function DefaultDialogs() {\n\tconst { dialogs } = useDialogs()\n\tconst dialogsArray = useValue('dialogs', () => dialogs.get(), [dialogs])\n\t// Every stacked dialog stays modal (Radix's default). That's what keeps dismiss\n\t// layer-aware: a background press or escape closes only the topmost layer, because\n\t// Radix's focus-scope stack pauses lower dialogs rather than dismissing them. Don't\n\t// make a lower dialog non-modal to work around anything \u2014 without a focus scope it\n\t// dismisses on the focus shift when a nested dialog or select opens, collapsing the\n\t// whole stack.\n\treturn dialogsArray.map((dialog) => <TldrawUiDialog key={dialog.id} {...dialog} />)\n})\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { useContainer, useValue } from '@tldraw/editor'\nimport { Dialog as _Dialog } from 'radix-ui'\nimport { memo, useCallback, useRef } from 'react'\nimport { TLUiDialog, useDialogs } from '../context/dialogs'\nimport { useDirection } from '../hooks/useTranslation/useTranslation'\n\n/** @internal */\nconst TldrawUiDialog = ({ id, component: ModalContent, preventBackgroundClose }: TLUiDialog) => {\n\tconst { removeDialog } = useDialogs()\n\n\tconst container = useContainer()\n\tconst dir = useDirection()\n\tconst contentRef = useRef<HTMLDivElement>(null)\n\n\tconst handleOpenChange = useCallback(\n\t\t(isOpen: boolean) => {\n\t\t\tif (!isOpen) {\n\t\t\t\tremoveDialog(id)\n\t\t\t}\n\t\t},\n\t\t[id, removeDialog]\n\t)\n\n\treturn (\n\t\t<_Dialog.Root onOpenChange={handleOpenChange} defaultOpen>\n\t\t\t<_Dialog.Portal container={container}>\n\t\t\t\t{/* Radix renders the scrim and content as siblings. The positioner sits on\n\t\t\t\t top of the scrim and centers the content, scrolling and padding it when\n\t\t\t\t it's taller than the viewport. */}\n\t\t\t\t<_Dialog.Overlay dir={dir} className=\"tlui-dialog__overlay\" />\n\t\t\t\t<div dir={dir} className=\"tlui-dialog__positioner\">\n\t\t\t\t\t<_Dialog.Content\n\t\t\t\t\t\tref={contentRef}\n\t\t\t\t\t\tdir={dir}\n\t\t\t\t\t\tclassName=\"tlui-dialog__content\"\n\t\t\t\t\t\taria-describedby={undefined}\n\t\t\t\t\t\tonInteractOutside={(e) => {\n\t\t\t\t\t\t\t// Radix's dismissable layers are layer-aware: an interaction outside the\n\t\t\t\t\t\t\t// topmost layer dismisses only that layer \u2014 an open select, or a dialog\n\t\t\t\t\t\t\t// stacked on top \u2014 leaving lower layers open. onInteractOutside fires for\n\t\t\t\t\t\t\t// both a pointer press and a focus shift outside the dialog; opt out of both\n\t\t\t\t\t\t\t// when the dialog asks to stay open on background interactions (escape still\n\t\t\t\t\t\t\t// closes it).\n\n\t\t\t\t\t\t\t// A touch press is checked against the layers at the following click rather\n\t\t\t\t\t\t\t// than at the press itself, so a press that closes a dialog stacked on top of\n\t\t\t\t\t\t\t// this one arrives here once this one is topmost, and reads as a press\n\t\t\t\t\t\t\t// outside it. A press inside another dialog is never outside this one, and\n\t\t\t\t\t\t\t// stays so after that dialog unmounts and takes the press's target with it.\n\t\t\t\t\t\t\tconst target = e.detail.originalEvent.target\n\t\t\t\t\t\t\tconst pressedDialog =\n\t\t\t\t\t\t\t\ttarget instanceof Element ? target.closest('.tlui-dialog__content') : null\n\t\t\t\t\t\t\tif (pressedDialog && pressedDialog !== contentRef.current) {\n\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (preventBackgroundClose) {\n\t\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ModalContent onClose={() => handleOpenChange(false)} />\n\t\t\t\t\t</_Dialog.Content>\n\t\t\t\t</div>\n\t\t\t</_Dialog.Portal>\n\t\t</_Dialog.Root>\n\t)\n}\n\n/** @public @react */\nexport const DefaultDialogs = memo(function DefaultDialogs() {\n\tconst { dialogs } = useDialogs()\n\tconst dialogsArray = useValue('dialogs', () => dialogs.get(), [dialogs])\n\t// Every stacked dialog stays modal (Radix's default). That's what keeps dismiss\n\t// layer-aware: a background press or escape closes only the topmost layer, because\n\t// Radix's focus-scope stack pauses lower dialogs rather than dismissing them. Don't\n\t// make a lower dialog non-modal to work around anything \u2014 without a focus scope it\n\t// dismisses on the focus shift when a nested dialog or select opens, collapsing the\n\t// whole stack.\n\treturn dialogsArray.map((dialog) => <TldrawUiDialog key={dialog.id} {...dialog} />)\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBG;AAzBH,oBAAuC;AACvC,sBAAkC;AAClC,mBAA0C;AAC1C,qBAAuC;AACvC,4BAA6B;AAG7B,MAAM,iBAAiB,CAAC,EAAE,IAAI,WAAW,cAAc,uBAAuB,MAAkB;AAC/F,QAAM,EAAE,aAAa,QAAI,2BAAW;AAEpC,QAAM,gBAAY,4BAAa;AAC/B,QAAM,UAAM,oCAAa;AACzB,QAAM,iBAAa,qBAAuB,IAAI;AAE9C,QAAM,uBAAmB;AAAA,IACxB,CAAC,WAAoB;AACpB,UAAI,CAAC,QAAQ;AACZ,qBAAa,EAAE;AAAA,MAChB;AAAA,IACD;AAAA,IACA,CAAC,IAAI,YAAY;AAAA,EAClB;AAEA,SACC,4CAAC,gBAAAA,OAAQ,MAAR,EAAa,cAAc,kBAAkB,aAAW,MACxD,uDAAC,gBAAAA,OAAQ,QAAR,EAAe,WAIf;AAAA,gDAAC,gBAAAA,OAAQ,SAAR,EAAgB,KAAU,WAAU,wBAAuB;AAAA,IAC5D,4CAAC,SAAI,KAAU,WAAU,2BACxB;AAAA,MAAC,gBAAAA,OAAQ;AAAA,MAAR;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,WAAU;AAAA,QACV,oBAAkB;AAAA,QAClB,mBAAmB,CAAC,MAAM;AAazB,gBAAM,SAAS,EAAE,OAAO,cAAc;AACtC,gBAAM,gBACL,kBAAkB,UAAU,OAAO,QAAQ,uBAAuB,IAAI;AACvE,cAAI,iBAAiB,kBAAkB,WAAW,SAAS;AAC1D,cAAE,eAAe;AACjB;AAAA,UACD;AAEA,cAAI,wBAAwB;AAC3B,cAAE,eAAe;AAAA,UAClB;AAAA,QACD;AAAA,QAEA,sDAAC,gBAAa,SAAS,MAAM,iBAAiB,KAAK,GAAG;AAAA;AAAA,IACvD,GACD;AAAA,KACD,GACD;AAEF;AAGO,MAAM,qBAAiB,mBAAK,SAASC,kBAAiB;AAC5D,QAAM,EAAE,QAAQ,QAAI,2BAAW;AAC/B,QAAM,mBAAe,wBAAS,WAAW,MAAM,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC;AAOvE,SAAO,aAAa,IAAI,CAAC,WAAW,4CAAC,kBAAgC,GAAG,UAAf,OAAO,EAAgB,CAAE;AACnF,CAAC;",
|
|
6
6
|
"names": ["_Dialog", "DefaultDialogs"]
|
|
7
7
|
}
|
|
@@ -50,7 +50,11 @@ function assertShapeWithUrl(shape) {
|
|
|
50
50
|
const EditLinkDialog = (0, import_editor.track)(function EditLinkDialog2({ onClose }) {
|
|
51
51
|
const editor = (0, import_editor.useEditor)();
|
|
52
52
|
const selectedShape = editor.getOnlySelectedShape();
|
|
53
|
-
|
|
53
|
+
const hasShapeWithUrl = isShapeWithUrl(selectedShape);
|
|
54
|
+
(0, import_react.useEffect)(() => {
|
|
55
|
+
if (!hasShapeWithUrl) onClose();
|
|
56
|
+
}, [hasShapeWithUrl, onClose]);
|
|
57
|
+
if (!hasShapeWithUrl) {
|
|
54
58
|
return null;
|
|
55
59
|
}
|
|
56
60
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EditLinkDialogInner, { onClose, selectedShape });
|
|
@@ -116,10 +120,6 @@ const EditLinkDialogInner = (0, import_editor.track)(function EditLinkDialogInne
|
|
|
116
120
|
const handleCancel = (0, import_react.useCallback)(() => {
|
|
117
121
|
onClose();
|
|
118
122
|
}, [onClose]);
|
|
119
|
-
if (!selectedShape) {
|
|
120
|
-
onClose();
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
123
|
const isRemoving = rInitialValue.current && !urlInputState.valid;
|
|
124
124
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
125
125
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_TldrawUiDialog.TldrawUiDialogHeader, { children: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/ui/components/EditLinkDialog.tsx"],
|
|
4
|
-
"sourcesContent": ["import { ExtractShapeByProps, T, TLShape, track, useEditor } from '@tldraw/editor'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { TLUiDialogProps } from '../context/dialogs'\nimport { useTranslation } from '../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from './primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonLabel } from './primitives/Button/TldrawUiButtonLabel'\nimport {\n\tTldrawUiDialogBody,\n\tTldrawUiDialogCloseButton,\n\tTldrawUiDialogFooter,\n\tTldrawUiDialogHeader,\n\tTldrawUiDialogTitle,\n} from './primitives/TldrawUiDialog'\nimport { TldrawUiInput } from './primitives/TldrawUiInput'\n\n// A url can either be invalid, or valid with a protocol, or valid without a protocol.\n// For example, \"aol.com\" would be valid with a protocol ()\nfunction validateUrl(url: string) {\n\tif (T.linkUrl.isValid(url)) {\n\t\treturn { isValid: true, hasProtocol: true }\n\t}\n\tif (T.linkUrl.isValid('https://' + url)) {\n\t\treturn { isValid: true, hasProtocol: false }\n\t}\n\treturn { isValid: false, hasProtocol: false }\n}\n\ntype ShapeWithUrl = ExtractShapeByProps<{ url: string }>\n\nfunction isShapeWithUrl(shape: TLShape | null | undefined): shape is ShapeWithUrl {\n\treturn !!(shape && 'url' in shape.props && typeof shape.props.url === 'string')\n}\n\nfunction assertShapeWithUrl(shape: TLShape | null | undefined): asserts shape is ShapeWithUrl {\n\tif (!isShapeWithUrl(shape)) {\n\t\tthrow new Error('Shape is not a valid ShapeWithUrl')\n\t}\n}\n\nexport const EditLinkDialog = track(function EditLinkDialog({ onClose }: TLUiDialogProps) {\n\tconst editor = useEditor()\n\n\tconst selectedShape = editor.getOnlySelectedShape()\n\n\tif (!
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { ExtractShapeByProps, T, TLShape, track, useEditor } from '@tldraw/editor'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { TLUiDialogProps } from '../context/dialogs'\nimport { useTranslation } from '../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from './primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonLabel } from './primitives/Button/TldrawUiButtonLabel'\nimport {\n\tTldrawUiDialogBody,\n\tTldrawUiDialogCloseButton,\n\tTldrawUiDialogFooter,\n\tTldrawUiDialogHeader,\n\tTldrawUiDialogTitle,\n} from './primitives/TldrawUiDialog'\nimport { TldrawUiInput } from './primitives/TldrawUiInput'\n\n// A url can either be invalid, or valid with a protocol, or valid without a protocol.\n// For example, \"aol.com\" would be valid with a protocol ()\nfunction validateUrl(url: string) {\n\tif (T.linkUrl.isValid(url)) {\n\t\treturn { isValid: true, hasProtocol: true }\n\t}\n\tif (T.linkUrl.isValid('https://' + url)) {\n\t\treturn { isValid: true, hasProtocol: false }\n\t}\n\treturn { isValid: false, hasProtocol: false }\n}\n\ntype ShapeWithUrl = ExtractShapeByProps<{ url: string }>\n\nfunction isShapeWithUrl(shape: TLShape | null | undefined): shape is ShapeWithUrl {\n\treturn !!(shape && 'url' in shape.props && typeof shape.props.url === 'string')\n}\n\nfunction assertShapeWithUrl(shape: TLShape | null | undefined): asserts shape is ShapeWithUrl {\n\tif (!isShapeWithUrl(shape)) {\n\t\tthrow new Error('Shape is not a valid ShapeWithUrl')\n\t}\n}\n\nexport const EditLinkDialog = track(function EditLinkDialog({ onClose }: TLUiDialogProps) {\n\tconst editor = useEditor()\n\n\tconst selectedShape = editor.getOnlySelectedShape()\n\tconst hasShapeWithUrl = isShapeWithUrl(selectedShape)\n\n\t// The shape can be deleted or deselected from under the open dialog (a collaborator, or a\n\t// keypress reaching the canvas). Returning null on its own would leave an empty dialog frame.\n\tuseEffect(() => {\n\t\tif (!hasShapeWithUrl) onClose()\n\t}, [hasShapeWithUrl, onClose])\n\n\tif (!hasShapeWithUrl) {\n\t\treturn null\n\t}\n\n\treturn <EditLinkDialogInner onClose={onClose} selectedShape={selectedShape} />\n})\n\nexport const EditLinkDialogInner = track(function EditLinkDialogInner({\n\tonClose,\n\tselectedShape,\n}: TLUiDialogProps & { selectedShape: ShapeWithUrl }) {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\n\tconst rInput = useRef<HTMLInputElement>(null)\n\n\tuseEffect(() => {\n\t\teditor.timers.requestAnimationFrame(() => rInput.current?.focus())\n\t}, [editor])\n\n\tconst rInitialValue = useRef(selectedShape.props.url)\n\n\tconst [urlInputState, setUrlInputState] = useState(() => {\n\t\tconst urlValidResult = validateUrl(selectedShape.props.url)\n\n\t\tconst initialValue =\n\t\t\turlValidResult.isValid === true\n\t\t\t\t? urlValidResult.hasProtocol\n\t\t\t\t\t? selectedShape.props.url\n\t\t\t\t\t: 'https://' + selectedShape.props.url\n\t\t\t\t: 'https://'\n\n\t\treturn {\n\t\t\tactual: initialValue,\n\t\t\tsafe: initialValue,\n\t\t\tvalid: true,\n\t\t}\n\t})\n\n\tconst handleChange = useCallback((rawValue: string) => {\n\t\t// Just auto-correct double https:// from a bad paste.\n\t\tconst fixedRawValue = rawValue.replace(/https?:\\/\\/(https?:\\/\\/)/, (_match, arg1) => {\n\t\t\treturn arg1\n\t\t})\n\n\t\tconst urlValidResult = validateUrl(fixedRawValue)\n\n\t\tconst safeValue =\n\t\t\turlValidResult.isValid === true\n\t\t\t\t? urlValidResult.hasProtocol\n\t\t\t\t\t? fixedRawValue\n\t\t\t\t\t: 'https://' + fixedRawValue\n\t\t\t\t: 'https://'\n\n\t\tsetUrlInputState({\n\t\t\tactual: fixedRawValue,\n\t\t\tsafe: safeValue,\n\t\t\tvalid: urlValidResult.isValid,\n\t\t})\n\t}, [])\n\n\tconst handleClear = useCallback(() => {\n\t\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\t\tif (!onlySelectedShape) return\n\t\tassertShapeWithUrl(onlySelectedShape)\n\t\teditor.updateShapes([\n\t\t\t{ id: onlySelectedShape.id, type: onlySelectedShape.type, props: { url: '' } },\n\t\t])\n\t\tonClose()\n\t}, [editor, onClose])\n\n\tconst handleComplete = useCallback(() => {\n\t\tconst onlySelectedShape = editor.getOnlySelectedShape()\n\n\t\tif (!onlySelectedShape) return\n\t\tassertShapeWithUrl(onlySelectedShape)\n\n\t\t// ? URL is a magic value\n\t\tif (onlySelectedShape && 'url' in onlySelectedShape.props) {\n\t\t\t// Here would be a good place to validate the next shape\u2014would setting the empty\n\t\t\tif (onlySelectedShape.props.url !== urlInputState.safe) {\n\t\t\t\teditor.updateShapes([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: onlySelectedShape.id,\n\t\t\t\t\t\ttype: onlySelectedShape.type,\n\t\t\t\t\t\tprops: { url: urlInputState.safe },\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t}\n\t\t}\n\t\tonClose()\n\t}, [editor, onClose, urlInputState])\n\n\tconst handleCancel = useCallback(() => {\n\t\tonClose()\n\t}, [onClose])\n\n\t// Are we going from a valid state to an invalid state?\n\tconst isRemoving = rInitialValue.current && !urlInputState.valid\n\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiDialogHeader>\n\t\t\t\t<TldrawUiDialogTitle>{msg('edit-link-dialog.title')}</TldrawUiDialogTitle>\n\t\t\t\t<TldrawUiDialogCloseButton />\n\t\t\t</TldrawUiDialogHeader>\n\t\t\t<TldrawUiDialogBody>\n\t\t\t\t<div className=\"tlui-edit-link-dialog\">\n\t\t\t\t\t<TldrawUiInput\n\t\t\t\t\t\tref={rInput}\n\t\t\t\t\t\tclassName=\"tlui-edit-link-dialog__input\"\n\t\t\t\t\t\tlabel=\"edit-link-dialog.url\"\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\tautoSelect\n\t\t\t\t\t\tplaceholder=\"https://example.com\"\n\t\t\t\t\t\tvalue={urlInputState.actual}\n\t\t\t\t\t\tonValueChange={handleChange}\n\t\t\t\t\t\tonComplete={handleComplete}\n\t\t\t\t\t\tonCancel={handleCancel}\n\t\t\t\t\t/>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{urlInputState.valid\n\t\t\t\t\t\t\t? msg('edit-link-dialog.detail')\n\t\t\t\t\t\t\t: msg('edit-link-dialog.invalid-url')}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</TldrawUiDialogBody>\n\t\t\t<TldrawUiDialogFooter className=\"tlui-dialog__footer__actions\">\n\t\t\t\t<TldrawUiButton type=\"normal\" onClick={handleCancel} onTouchEnd={handleCancel}>\n\t\t\t\t\t<TldrawUiButtonLabel>{msg('edit-link-dialog.cancel')}</TldrawUiButtonLabel>\n\t\t\t\t</TldrawUiButton>\n\t\t\t\t{isRemoving ? (\n\t\t\t\t\t<TldrawUiButton type={'danger'} onTouchEnd={handleClear} onClick={handleClear}>\n\t\t\t\t\t\t<TldrawUiButtonLabel>{msg('edit-link-dialog.clear')}</TldrawUiButtonLabel>\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t) : (\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"primary\"\n\t\t\t\t\t\tdisabled={!urlInputState.valid}\n\t\t\t\t\t\tonTouchEnd={handleComplete}\n\t\t\t\t\t\tonClick={handleComplete}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiButtonLabel>{msg('edit-link-dialog.save')}</TldrawUiButtonLabel>\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t)}\n\t\t\t</TldrawUiDialogFooter>\n\t\t</>\n\t)\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["EditLinkDialog", "EditLinkDialogInner"]
|
|
7
7
|
}
|
|
@@ -41,6 +41,8 @@ function DefaultMinimap() {
|
|
|
41
41
|
const editor = (0, import_editor.useEditor)();
|
|
42
42
|
const container = (0, import_editor.useContainer)();
|
|
43
43
|
const msg = (0, import_useTranslation.useTranslation)();
|
|
44
|
+
const rMinimap = React.useRef(null);
|
|
45
|
+
(0, import_editor.usePassThroughWheelEvents)(rMinimap);
|
|
44
46
|
const rCanvas = React.useRef(null);
|
|
45
47
|
const rPointing = React.useRef(false);
|
|
46
48
|
const rActivePointerId = React.useRef(null);
|
|
@@ -158,23 +160,6 @@ function DefaultMinimap() {
|
|
|
158
160
|
},
|
|
159
161
|
[editor]
|
|
160
162
|
);
|
|
161
|
-
const onWheel = React.useCallback(
|
|
162
|
-
(e) => {
|
|
163
|
-
const offset = (0, import_editor.normalizeWheel)(e);
|
|
164
|
-
editor.dispatch({
|
|
165
|
-
type: "wheel",
|
|
166
|
-
name: "wheel",
|
|
167
|
-
delta: offset,
|
|
168
|
-
point: new import_editor.Vec(e.clientX, e.clientY),
|
|
169
|
-
shiftKey: e.shiftKey,
|
|
170
|
-
altKey: e.altKey,
|
|
171
|
-
ctrlKey: e.metaKey || e.ctrlKey,
|
|
172
|
-
metaKey: e.metaKey,
|
|
173
|
-
accelKey: (0, import_editor.isAccelKey)(e)
|
|
174
|
-
});
|
|
175
|
-
},
|
|
176
|
-
[editor]
|
|
177
|
-
);
|
|
178
163
|
const colorMode = (0, import_editor.useColorMode)();
|
|
179
164
|
const currentThemeId = (0, import_editor.useValue)("current theme id", () => editor.getCurrentThemeId(), [editor]);
|
|
180
165
|
React.useEffect(() => {
|
|
@@ -183,7 +168,7 @@ function DefaultMinimap() {
|
|
|
183
168
|
minimapRef.current?.render();
|
|
184
169
|
});
|
|
185
170
|
}, [colorMode, currentThemeId, editor]);
|
|
186
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tlui-minimap", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: rMinimap, className: "tlui-minimap", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
187
172
|
"canvas",
|
|
188
173
|
{
|
|
189
174
|
ref: rCanvas,
|
|
@@ -193,8 +178,7 @@ function DefaultMinimap() {
|
|
|
193
178
|
className: "tlui-minimap__canvas",
|
|
194
179
|
onDoubleClick,
|
|
195
180
|
onPointerMove,
|
|
196
|
-
onPointerDown
|
|
197
|
-
onWheelCapture: onWheel
|
|
181
|
+
onPointerDown
|
|
198
182
|
}
|
|
199
183
|
) });
|
|
200
184
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/ui/components/Minimap/DefaultMinimap.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tTLPointerEventInfo,\n\tVec,\n\tgetPointerInfo,\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tTLPointerEventInfo,\n\tVec,\n\tgetPointerInfo,\n\tsetPointerCapture,\n\tuseContainer,\n\tuseColorMode,\n\tuseEditor,\n\tusePassThroughWheelEvents,\n\tuseValue,\n} from '@tldraw/editor'\nimport * as React from 'react'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { MinimapManager } from './MinimapManager'\n\n// Squared distance (in screen pixels) the pointer can move after pointer down before\n// it counts as a drag. Sub-pixel jitter that accompanies a click stays below this, so\n// it doesn't recenter the camera instantly and cut off the easing animation.\nconst CLICK_JITTER_THRESHOLD_SQ = 4\n\n/** @public @react */\nexport function DefaultMinimap() {\n\tconst editor = useEditor()\n\tconst container = useContainer()\n\tconst msg = useTranslation()\n\n\tconst rMinimap = React.useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(rMinimap)\n\n\tconst rCanvas = React.useRef<HTMLCanvasElement>(null!)\n\tconst rPointing = React.useRef(false)\n\tconst rActivePointerId = React.useRef<number | null>(null)\n\tconst rOriginScreenPoint = React.useRef(new Vec())\n\n\tconst minimapRef = React.useRef<MinimapManager | undefined>(undefined)\n\n\tReact.useEffect(() => {\n\t\ttry {\n\t\t\tconst minimap = new MinimapManager(editor, rCanvas.current, container)\n\t\t\tminimapRef.current = minimap\n\t\t\treturn minimapRef.current.close\n\t\t} catch (e) {\n\t\t\teditor.annotateError(e, {\n\t\t\t\torigin: 'minimap',\n\t\t\t\twillCrashApp: false,\n\t\t\t})\n\t\t\teditor.timers.setTimeout(() => {\n\t\t\t\tthrow e\n\t\t\t})\n\t\t\treturn undefined\n\t\t}\n\t}, [editor, container])\n\n\tconst onDoubleClick = React.useCallback(\n\t\t(e: React.MouseEvent<HTMLCanvasElement>) => {\n\t\t\tif (!editor.getCurrentPageShapeIds().size) return\n\t\t\tconst minimap = minimapRef.current\n\t\t\tif (!minimap) return\n\n\t\t\tconst { clientX: x, clientY: y } = e\n\n\t\t\t// Stash the clamped point / clamped viewport page center\n\t\t\tconst clampedPoint = minimap.minimapScreenPointToPagePoint(x, y, false, true)\n\t\t\tminimap.originPagePoint.setTo(clampedPoint)\n\t\t\tminimap.originPageCenter.setTo(editor.getViewportPageBounds().center)\n\n\t\t\t// Then center on the unclamped point\n\t\t\tconst point = minimap.minimapScreenPointToPagePoint(x, y, false, false)\n\t\t\teditor.centerOnPoint(point, { animation: { duration: editor.options.animationMediumMs } })\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst onPointerDown = React.useCallback(\n\t\t(e: React.PointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst minimap = minimapRef.current\n\t\t\tif (!minimap) return\n\t\t\tif (e.button !== 0) return\n\n\t\t\tconst elm = e.currentTarget\n\t\t\tsetPointerCapture(elm, e)\n\t\t\tif (!editor.getCurrentPageShapeIds().size) return\n\n\t\t\tconst { clientX: x, clientY: y } = e\n\n\t\t\trPointing.current = true\n\t\t\trActivePointerId.current = e.pointerId\n\t\t\trOriginScreenPoint.current = new Vec(x, y)\n\n\t\t\tminimap.isInViewport = false\n\n\t\t\tconst point = minimap.minimapScreenPointToPagePoint(x, y, false, false)\n\n\t\t\tconst vpPageBounds = editor.getViewportPageBounds()\n\t\t\tconst commonBounds = minimap.getContentPageBounds()\n\t\t\tconst allowedBounds = new Box(\n\t\t\t\tcommonBounds.x - vpPageBounds.width / 2,\n\t\t\t\tcommonBounds.y - vpPageBounds.height / 2,\n\t\t\t\tcommonBounds.width + vpPageBounds.width,\n\t\t\t\tcommonBounds.height + vpPageBounds.height\n\t\t\t)\n\n\t\t\t// If we clicked inside of the allowed area, but outside of the viewport\n\t\t\tif (allowedBounds.containsPoint(point) && !vpPageBounds.containsPoint(point)) {\n\t\t\t\tconst delta = Vec.Sub(vpPageBounds.center, vpPageBounds.point)\n\t\t\t\tconst pagePoint = Vec.Add(point, delta)\n\t\t\t\tminimap.originPagePoint.setTo(pagePoint)\n\t\t\t\tminimap.originPageCenter.setTo(point)\n\t\t\t\teditor.centerOnPoint(point, { animation: { duration: editor.options.animationMediumMs } })\n\t\t\t} else {\n\t\t\t\tconst clampedPoint = minimap.minimapScreenPointToPagePoint(x, y, false, true)\n\t\t\t\tminimap.isInViewport = vpPageBounds.containsPoint(clampedPoint)\n\t\t\t\tminimap.originPagePoint.setTo(clampedPoint)\n\t\t\t\tminimap.originPageCenter.setTo(vpPageBounds.center)\n\t\t\t}\n\n\t\t\tconst body = editor.getContainerDocument().body\n\n\t\t\tfunction endDrag() {\n\t\t\t\tif (rActivePointerId.current !== null && elm.hasPointerCapture(rActivePointerId.current)) {\n\t\t\t\t\telm.releasePointerCapture(rActivePointerId.current)\n\t\t\t\t}\n\n\t\t\t\trPointing.current = false\n\t\t\t\trActivePointerId.current = null\n\t\t\t\tbody.removeEventListener('pointerup', endDrag)\n\t\t\t\tbody.removeEventListener('pointercancel', endDrag)\n\t\t\t\tbody.removeEventListener('contextmenu', endDrag, true)\n\t\t\t}\n\n\t\t\tbody.addEventListener('pointerup', endDrag)\n\t\t\tbody.addEventListener('pointercancel', endDrag)\n\t\t\tbody.addEventListener('contextmenu', endDrag, true)\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst onPointerMove = React.useCallback(\n\t\t(e: React.PointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst minimap = minimapRef.current\n\t\t\tif (!minimap) return\n\n\t\t\tconst { clientX: x, clientY: y } = e\n\n\t\t\tconst point = minimap.minimapScreenPointToPagePoint(x, y, e.shiftKey, true)\n\n\t\t\tif (rPointing.current) {\n\t\t\t\t// Ignore the sub-pixel pointer jitter that accompanies a click, so it doesn't\n\t\t\t\t// cut off the easing animation started on pointer down.\n\t\t\t\tif (Vec.Dist2(rOriginScreenPoint.current, new Vec(x, y)) <= CLICK_JITTER_THRESHOLD_SQ) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (minimap.isInViewport) {\n\t\t\t\t\tconst delta = minimap.originPagePoint.clone().sub(minimap.originPageCenter)\n\t\t\t\t\teditor.centerOnPoint(Vec.Sub(point, delta))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\teditor.centerOnPoint(point)\n\t\t\t}\n\n\t\t\tconst pagePoint = minimap.getMinimapPagePoint(x, y)\n\n\t\t\tconst screenPoint = editor.pageToScreen(pagePoint)\n\n\t\t\tconst info: TLPointerEventInfo = {\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_move',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\tpoint: screenPoint,\n\t\t\t\tisPen: editor.getInstanceState().isPenMode,\n\t\t\t}\n\n\t\t\teditor.dispatch(info)\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst colorMode = useColorMode()\n\tconst currentThemeId = useValue('current theme id', () => editor.getCurrentThemeId(), [editor])\n\n\tReact.useEffect(() => {\n\t\t// need to wait a tick for next theme css to be applied\n\t\t// otherwise the minimap will render with the wrong colors\n\t\teditor.timers.setTimeout(() => {\n\t\t\tminimapRef.current?.updateColors()\n\t\t\tminimapRef.current?.render()\n\t\t})\n\t}, [colorMode, currentThemeId, editor])\n\n\treturn (\n\t\t<div ref={rMinimap} className=\"tlui-minimap\">\n\t\t\t<canvas\n\t\t\t\tref={rCanvas}\n\t\t\t\trole=\"img\"\n\t\t\t\taria-label={msg('navigation-zone.minimap')}\n\t\t\t\tdata-testid=\"minimap.canvas\"\n\t\t\t\tclassName=\"tlui-minimap__canvas\"\n\t\t\t\tonDoubleClick={onDoubleClick}\n\t\t\t\tonPointerMove={onPointerMove}\n\t\t\t\tonPointerDown={onPointerDown}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -96,6 +96,7 @@ function StylePanelDoubleDropdownPickerInlineInner(props) {
|
|
|
96
96
|
"data-testid": `style.${uiTypeA}.${item.value}`,
|
|
97
97
|
type: "icon",
|
|
98
98
|
onClick: () => {
|
|
99
|
+
ctx.onHistoryMark("select style dropdown item");
|
|
99
100
|
onValueChange(styleA, item.value);
|
|
100
101
|
import_editor.tlmenus.deleteOpenMenu(idA, editor.contextId);
|
|
101
102
|
setIsOpenA(false);
|
|
@@ -125,6 +126,7 @@ function StylePanelDoubleDropdownPickerInlineInner(props) {
|
|
|
125
126
|
title: `${msg(labelB)} \u2014 ${msg(`${uiTypeB}-style.${item.value}`)}`,
|
|
126
127
|
"data-testid": `style.${uiTypeB}.${item.value}`,
|
|
127
128
|
onClick: () => {
|
|
129
|
+
ctx.onHistoryMark("select style dropdown item");
|
|
128
130
|
onValueChange(styleB, item.value);
|
|
129
131
|
import_editor.tlmenus.deleteOpenMenu(idB, editor.contextId);
|
|
130
132
|
setIsOpenB(false);
|