tldraw 3.16.0-canary.5dac57cf9465 → 3.16.0-canary.5f82fb812214
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +170 -7
- package/dist-cjs/index.js +13 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/Tldraw.js +12 -2
- package/dist-cjs/lib/Tldraw.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +18 -12
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +6 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.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/shared/ShapeFill.js +4 -4
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +27 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
- package/dist-cjs/lib/ui/assetUrls.js +13 -10
- package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +10 -2
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +39 -10
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -22
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +188 -78
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +15 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +159 -160
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/layout.js +30 -5
- package/dist-cjs/lib/ui/components/primitives/layout.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +154 -19
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +16 -2
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/components.js +2 -0
- package/dist-cjs/lib/ui/context/components.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +94 -9
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +9 -3
- package/dist-cjs/lib/ui/kbd-utils.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.d.mts +170 -7
- package/dist-esm/index.mjs +20 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/Tldraw.mjs +14 -4
- package/dist-esm/lib/Tldraw.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +19 -12
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +6 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +29 -14
- package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
- package/dist-esm/lib/ui/assetUrls.mjs +13 -10
- package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +10 -2
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +1 -1
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +39 -10
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -22
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -80
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +2 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +16 -4
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +168 -162
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/layout.mjs +31 -6
- package/dist-esm/lib/ui/components/primitives/layout.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +162 -21
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +16 -2
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/components.mjs +2 -0
- package/dist-esm/lib/ui/context/components.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +102 -10
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
- package/dist-esm/lib/ui/kbd-utils.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 +11 -34
- package/src/index.ts +13 -1
- package/src/lib/Tldraw.tsx +15 -2
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/defaultExternalContentHandlers.ts +12 -4
- package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +29 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
- package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
- package/src/lib/shapes/image/ImageShapeUtil.tsx +6 -3
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
- package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
- package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
- package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
- package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
- package/src/lib/shapes/shared/freehand/svg.ts +2 -0
- package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
- package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
- package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
- package/src/lib/tools/SelectTool/childStates/Translating.ts +0 -1
- package/src/lib/ui/TldrawUi.tsx +33 -12
- package/src/lib/ui/assetUrls.ts +13 -10
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +13 -2
- package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +1 -1
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +33 -16
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -24
- package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +208 -56
- package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +3 -2
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +22 -5
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +202 -184
- package/src/lib/ui/components/primitives/layout.tsx +79 -5
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +221 -18
- package/src/lib/ui/context/actions.tsx +16 -2
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/context/events.tsx +2 -1
- package/src/lib/ui/hooks/useTools.tsx +140 -10
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +349 -243
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
- package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
- package/src/test/A11y.test.tsx +3 -2
- package/src/test/ClickManager.test.ts +7 -6
- package/src/test/Editor.test.tsx +20 -19
- package/src/test/EraserTool.test.ts +184 -13
- package/src/test/HandTool.test.ts +10 -9
- package/src/test/HighlightShape.test.ts +2 -1
- package/src/test/SelectTool.test.ts +3 -2
- package/src/test/TLUserPreferences.test.ts +4 -3
- package/src/test/TestEditor.ts +13 -15
- package/src/test/TldrawEditor.test.tsx +11 -10
- package/src/test/ZoomTool.test.ts +7 -6
- package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
- package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
- package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
- package/src/test/arrows-megabus.test.tsx +5 -4
- package/src/test/bindings.test.tsx +24 -37
- package/src/test/bookmark-shapes.test.ts +1 -8
- package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
- package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
- package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
- package/src/test/commands/alignShapes.test.tsx +25 -24
- package/src/test/commands/animationSpeed.test.ts +2 -1
- package/src/test/commands/centerOnPoint.test.ts +3 -2
- package/src/test/commands/clipboard.test.ts +3 -2
- package/src/test/commands/createShapes.test.ts +2 -1
- package/src/test/commands/deleteShapes.test.ts +2 -1
- package/src/test/commands/distributeShapes.test.tsx +11 -10
- package/src/test/commands/getSvgString.test.ts +2 -1
- package/src/test/commands/packShapes.test.ts +5 -4
- package/src/test/commands/resizeShape.test.ts +2 -1
- package/src/test/commands/rotateShapes.test.ts +7 -6
- package/src/test/commands/setCamera.test.ts +4 -3
- package/src/test/commands/setCurrentPage.test.ts +3 -2
- package/src/test/commands/stackShapes.test.ts +11 -10
- package/src/test/commands/stretch.test.tsx +13 -12
- package/src/test/createDeepLink.test.tsx +2 -1
- package/src/test/cropping.test.ts +3 -2
- package/src/test/custom-clipping.test.ts +436 -0
- package/src/test/drawing.test.ts +2 -1
- package/src/test/flipShapes.test.ts +4 -3
- package/src/test/frames.test.ts +25 -24
- package/src/test/getCulledShapes.test.tsx +3 -2
- package/src/test/groups.test.tsx +1 -1
- package/src/test/handleDeepLink.test.tsx +2 -1
- package/src/test/maxShapes.test.ts +3 -2
- package/src/test/modifiers.test.ts +5 -4
- package/src/test/navigation.test.ts +12 -11
- package/src/test/panning.test.ts +2 -1
- package/src/test/perf/perf.test.ts +2 -1
- package/src/test/registerDeepLinkListener.test.tsx +10 -9
- package/src/test/resizing.test.ts +39 -38
- package/src/test/select.test.tsx +4 -3
- package/src/test/selection-omnibus.test.ts +11 -10
- package/src/test/shapeutils.test.ts +4 -3
- package/src/test/translating.test.ts +9 -8
- package/tldraw.css +650 -533
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DefaultColorStyle,
|
|
3
|
+
getColorValue,
|
|
3
4
|
SharedStyle,
|
|
4
5
|
StyleProp,
|
|
5
6
|
TLDefaultColorStyle,
|
|
6
7
|
TLDefaultColorTheme,
|
|
7
8
|
useEditor,
|
|
8
9
|
} from '@tldraw/editor'
|
|
9
|
-
import {
|
|
10
|
+
import { memo, ReactElement, useMemo, useRef } from 'react'
|
|
10
11
|
import { StyleValuesForUi } from '../../../styles'
|
|
11
12
|
import { PORTRAIT_BREAKPOINT } from '../../constants'
|
|
12
13
|
import { useBreakpoint } from '../../context/breakpoints'
|
|
@@ -140,7 +141,7 @@ export const TldrawUiButtonPicker = memo(function TldrawUiButtonPicker<T extends
|
|
|
140
141
|
title={label}
|
|
141
142
|
style={
|
|
142
143
|
style === (DefaultColorStyle as StyleProp<unknown>)
|
|
143
|
-
? { color: theme
|
|
144
|
+
? { color: getColorValue(theme, item.value as TLDefaultColorStyle, 'solid') }
|
|
144
145
|
: undefined
|
|
145
146
|
}
|
|
146
147
|
onPointerEnter={handleButtonPointerEnter}
|
|
@@ -172,7 +172,12 @@ export const TldrawUiContextualToolbar = ({
|
|
|
172
172
|
className={classNames('tlui-contextual-toolbar', className)}
|
|
173
173
|
onPointerDown={stopEventPropagation}
|
|
174
174
|
>
|
|
175
|
-
<TldrawUiToolbar
|
|
175
|
+
<TldrawUiToolbar
|
|
176
|
+
orientation="horizontal"
|
|
177
|
+
className="tlui-menu"
|
|
178
|
+
label={label}
|
|
179
|
+
tooltipSide="top"
|
|
180
|
+
>
|
|
176
181
|
{children}
|
|
177
182
|
</TldrawUiToolbar>
|
|
178
183
|
</div>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { tltime } from '@tldraw/editor'
|
|
1
2
|
import { Slider as _Slider } from 'radix-ui'
|
|
2
3
|
import React, { useCallback, useEffect, useState } from 'react'
|
|
3
4
|
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
|
4
5
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
6
|
+
import { TldrawUiTooltip, tooltipManager } from './TldrawUiTooltip'
|
|
5
7
|
|
|
6
8
|
/** @public */
|
|
7
9
|
export interface TLUiSliderProps {
|
|
@@ -32,6 +34,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
32
34
|
ref
|
|
33
35
|
) {
|
|
34
36
|
const msg = useTranslation()
|
|
37
|
+
const [titleAndLabel, setTitleAndLabel] = useState('')
|
|
35
38
|
|
|
36
39
|
// XXX: Radix starts out our slider with a tabIndex of 0
|
|
37
40
|
// This causes some tab focusing issues, most prevelant in MobileStylePanel,
|
|
@@ -49,9 +52,25 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
49
52
|
)
|
|
50
53
|
|
|
51
54
|
const handlePointerDown = useCallback(() => {
|
|
55
|
+
tooltipManager.hideAllTooltips()
|
|
52
56
|
onHistoryMark('click slider')
|
|
53
57
|
}, [onHistoryMark])
|
|
54
58
|
|
|
59
|
+
// N.B. This is a bit silly. The Radix slider auto-focuses which
|
|
60
|
+
// triggers TldrawUiTooltip handleFocus when we dbl-click to edit an image,
|
|
61
|
+
// which in turn makes the tooltip display prematurely.
|
|
62
|
+
// This makes it wait until we've focused to show the tooltip.
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const timeout = tltime.setTimeout(
|
|
65
|
+
'set title and label',
|
|
66
|
+
() => {
|
|
67
|
+
setTitleAndLabel(title + ' — ' + msg(label as TLUiTranslationKey))
|
|
68
|
+
},
|
|
69
|
+
0
|
|
70
|
+
)
|
|
71
|
+
return () => clearTimeout(timeout)
|
|
72
|
+
}, [label, msg, title])
|
|
73
|
+
|
|
55
74
|
// N.B. Annoying. For a11y purposes, we need Tab to work.
|
|
56
75
|
// For some reason, Radix has some custom behavior here
|
|
57
76
|
// that interferes with tabbing past the slider and then
|
|
@@ -64,36 +83,37 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
64
83
|
|
|
65
84
|
return (
|
|
66
85
|
<div className="tlui-slider__container">
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
<TldrawUiTooltip content={titleAndLabel}>
|
|
87
|
+
<_Slider.Root
|
|
88
|
+
data-testid={testId}
|
|
89
|
+
className="tlui-slider"
|
|
90
|
+
dir="ltr"
|
|
91
|
+
min={min ?? 0}
|
|
92
|
+
max={steps}
|
|
93
|
+
step={1}
|
|
94
|
+
value={value !== null ? [value] : undefined}
|
|
95
|
+
onPointerDown={handlePointerDown}
|
|
96
|
+
onValueChange={handleValueChange}
|
|
97
|
+
onKeyDownCapture={handleKeyEvent}
|
|
98
|
+
onKeyUpCapture={handleKeyEvent}
|
|
99
|
+
>
|
|
100
|
+
<_Slider.Track className="tlui-slider__track" dir="ltr">
|
|
101
|
+
{value !== null && <_Slider.Range className="tlui-slider__range" dir="ltr" />}
|
|
102
|
+
</_Slider.Track>
|
|
103
|
+
{value !== null && (
|
|
104
|
+
<_Slider.Thumb
|
|
105
|
+
aria-valuemin={(min ?? 0) * ariaValueModifier}
|
|
106
|
+
aria-valuenow={value * ariaValueModifier}
|
|
107
|
+
aria-valuemax={steps * ariaValueModifier}
|
|
108
|
+
aria-label={titleAndLabel}
|
|
109
|
+
className="tlui-slider__thumb"
|
|
110
|
+
dir="ltr"
|
|
111
|
+
ref={ref}
|
|
112
|
+
tabIndex={tabIndex}
|
|
113
|
+
/>
|
|
114
|
+
)}
|
|
115
|
+
</_Slider.Root>
|
|
116
|
+
</TldrawUiTooltip>
|
|
97
117
|
</div>
|
|
98
118
|
)
|
|
99
119
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import classnames from 'classnames'
|
|
2
2
|
import { Toolbar as _Toolbar } from 'radix-ui'
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import { TldrawUiGrid, TldrawUiRow } from './layout'
|
|
4
|
+
import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow } from './layout'
|
|
5
5
|
import { TldrawUiTooltip } from './TldrawUiTooltip'
|
|
6
6
|
|
|
7
7
|
/** @public */
|
|
@@ -10,15 +10,32 @@ export interface TLUiToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
10
10
|
className?: string
|
|
11
11
|
dir?: 'ltr' | 'rtl'
|
|
12
12
|
label: string
|
|
13
|
-
orientation?: 'horizontal' | 'grid'
|
|
13
|
+
orientation?: 'horizontal' | 'vertical' | 'grid'
|
|
14
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const LayoutByOrientation = {
|
|
18
|
+
horizontal: TldrawUiRow,
|
|
19
|
+
vertical: TldrawUiColumn,
|
|
20
|
+
grid: TldrawUiGrid,
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
/** @public @react */
|
|
17
24
|
export const TldrawUiToolbar = React.forwardRef<HTMLDivElement, TLUiToolbarProps>(
|
|
18
|
-
(
|
|
19
|
-
|
|
25
|
+
(
|
|
26
|
+
{
|
|
27
|
+
children,
|
|
28
|
+
className,
|
|
29
|
+
label,
|
|
30
|
+
orientation = 'horizontal',
|
|
31
|
+
tooltipSide,
|
|
32
|
+
...props
|
|
33
|
+
}: TLUiToolbarProps,
|
|
34
|
+
ref
|
|
35
|
+
) => {
|
|
36
|
+
const Layout = LayoutByOrientation[orientation]
|
|
20
37
|
return (
|
|
21
|
-
<Layout asChild>
|
|
38
|
+
<Layout asChild tooltipSide={tooltipSide}>
|
|
22
39
|
<_Toolbar.Root
|
|
23
40
|
ref={ref}
|
|
24
41
|
{...props}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { Editor, uniqueId, useMaybeEditor,
|
|
1
|
+
import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'
|
|
2
2
|
import { Tooltip as _Tooltip } from 'radix-ui'
|
|
3
|
-
import React, {
|
|
4
|
-
|
|
3
|
+
import React, {
|
|
4
|
+
createContext,
|
|
5
|
+
forwardRef,
|
|
6
|
+
ReactNode,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
11
|
+
} from 'react'
|
|
12
|
+
import { useTldrawUiOrientation } from './layout'
|
|
5
13
|
|
|
6
14
|
const DEFAULT_TOOLTIP_DELAY_MS = 700
|
|
7
15
|
|
|
@@ -12,19 +20,23 @@ export interface TldrawUiTooltipProps {
|
|
|
12
20
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
13
21
|
sideOffset?: number
|
|
14
22
|
disabled?: boolean
|
|
23
|
+
showOnMobile?: boolean
|
|
24
|
+
delayDuration?: number
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
// Singleton tooltip manager
|
|
18
28
|
class TooltipManager {
|
|
19
29
|
private static instance: TooltipManager | null = null
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
private currentTooltip = atom<{
|
|
31
|
+
id: string
|
|
32
|
+
content: ReactNode
|
|
33
|
+
side: 'top' | 'right' | 'bottom' | 'left'
|
|
34
|
+
sideOffset: number
|
|
35
|
+
showOnMobile: boolean
|
|
36
|
+
targetElement: HTMLElement
|
|
37
|
+
delayDuration: number
|
|
38
|
+
} | null>('current tooltip', null)
|
|
24
39
|
private destroyTimeoutId: number | null = null
|
|
25
|
-
private subscribers: Set<() => void> = new Set()
|
|
26
|
-
private activeElement: HTMLElement | null = null
|
|
27
|
-
private editor: Editor | null = null
|
|
28
40
|
|
|
29
41
|
static getInstance(): TooltipManager {
|
|
30
42
|
if (!TooltipManager.instance) {
|
|
@@ -33,25 +45,14 @@ class TooltipManager {
|
|
|
33
45
|
return TooltipManager.instance
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
setEditor(editor: Editor | null) {
|
|
37
|
-
this.editor = editor
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
subscribe(callback: () => void): () => void {
|
|
41
|
-
this.subscribers.add(callback)
|
|
42
|
-
return () => this.subscribers.delete(callback)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private notify() {
|
|
46
|
-
this.subscribers.forEach((callback) => callback())
|
|
47
|
-
}
|
|
48
|
-
|
|
49
48
|
showTooltip(
|
|
50
49
|
tooltipId: string,
|
|
51
50
|
content: string | React.ReactNode,
|
|
52
|
-
|
|
53
|
-
side: 'top' | 'right' | 'bottom' | 'left'
|
|
54
|
-
sideOffset: number
|
|
51
|
+
targetElement: HTMLElement,
|
|
52
|
+
side: 'top' | 'right' | 'bottom' | 'left',
|
|
53
|
+
sideOffset: number,
|
|
54
|
+
showOnMobile: boolean,
|
|
55
|
+
delayDuration: number
|
|
55
56
|
) {
|
|
56
57
|
// Clear any existing destroy timeout
|
|
57
58
|
if (this.destroyTimeoutId) {
|
|
@@ -60,43 +61,61 @@ class TooltipManager {
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// Update current tooltip
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
this.currentTooltip.set({
|
|
65
|
+
id: tooltipId,
|
|
66
|
+
content,
|
|
67
|
+
side,
|
|
68
|
+
sideOffset,
|
|
69
|
+
showOnMobile,
|
|
70
|
+
targetElement,
|
|
71
|
+
delayDuration,
|
|
72
|
+
})
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
hideTooltip(tooltipId: string) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.destroyTimeoutId =
|
|
78
|
-
this.currentTooltipId = null
|
|
79
|
-
this.currentContent = ''
|
|
80
|
-
this.activeElement = null
|
|
81
|
-
this.destroyTimeoutId = null
|
|
82
|
-
this.notify()
|
|
83
|
-
}, 300)
|
|
75
|
+
hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
|
|
76
|
+
const hide = () => {
|
|
77
|
+
// Only hide if this is the current tooltip
|
|
78
|
+
if (this.currentTooltip.get()?.id === tooltipId) {
|
|
79
|
+
this.currentTooltip.set(null)
|
|
80
|
+
this.destroyTimeoutId = null
|
|
84
81
|
}
|
|
85
82
|
}
|
|
83
|
+
|
|
84
|
+
if (editor && !instant) {
|
|
85
|
+
// Start destroy timeout (1 second)
|
|
86
|
+
this.destroyTimeoutId = editor.timers.setTimeout(hide, 300)
|
|
87
|
+
} else {
|
|
88
|
+
hide()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
hideAllTooltips() {
|
|
93
|
+
this.currentTooltip.set(null)
|
|
94
|
+
this.destroyTimeoutId = null
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
getCurrentTooltipData() {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
const currentTooltip = this.currentTooltip.get()
|
|
99
|
+
if (!currentTooltip) return null
|
|
100
|
+
if (!this.supportsHover() && !currentTooltip.showOnMobile) return null
|
|
101
|
+
return currentTooltip
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private supportsHoverAtom: Atom<boolean> | null = null
|
|
105
|
+
supportsHover() {
|
|
106
|
+
if (!this.supportsHoverAtom) {
|
|
107
|
+
const mediaQuery = window.matchMedia('(hover: hover)')
|
|
108
|
+
const supportsHover = atom('has hover', mediaQuery.matches)
|
|
109
|
+
this.supportsHoverAtom = supportsHover
|
|
110
|
+
mediaQuery.addEventListener('change', (e) => {
|
|
111
|
+
supportsHover.set(e.matches)
|
|
112
|
+
})
|
|
95
113
|
}
|
|
114
|
+
return this.supportsHoverAtom.get()
|
|
96
115
|
}
|
|
97
116
|
}
|
|
98
117
|
|
|
99
|
-
const tooltipManager = TooltipManager.getInstance()
|
|
118
|
+
export const tooltipManager = TooltipManager.getInstance()
|
|
100
119
|
|
|
101
120
|
// Context for the tooltip singleton
|
|
102
121
|
const TooltipSingletonContext = createContext<boolean>(false)
|
|
@@ -120,66 +139,24 @@ export function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderPro
|
|
|
120
139
|
|
|
121
140
|
// The singleton tooltip component that renders once
|
|
122
141
|
function TooltipSingleton() {
|
|
123
|
-
const editor = useMaybeEditor()
|
|
124
|
-
const [, forceUpdate] = useState({})
|
|
125
142
|
const [isOpen, setIsOpen] = useState(false)
|
|
126
143
|
const triggerRef = useRef<HTMLDivElement>(null)
|
|
127
|
-
const previousPositionRef = useRef<{ x: number; y: number } | null>(null)
|
|
128
|
-
const prefersReducedMotion = usePrefersReducedMotion()
|
|
129
|
-
const [shouldAnimate, setShouldAnimate] = useState(false)
|
|
130
144
|
const isFirstShowRef = useRef(true)
|
|
131
|
-
const showTimeoutRef = useRef<number | null>(null)
|
|
132
|
-
|
|
133
|
-
// Set editor in tooltip manager
|
|
134
|
-
useEffect(() => {
|
|
135
|
-
tooltipManager.setEditor(editor)
|
|
136
|
-
}, [editor])
|
|
137
|
-
|
|
138
|
-
// Subscribe to tooltip manager updates
|
|
139
|
-
useEffect(() => {
|
|
140
|
-
const unsubscribe = tooltipManager.subscribe(() => {
|
|
141
|
-
forceUpdate({})
|
|
142
|
-
})
|
|
143
|
-
return unsubscribe
|
|
144
|
-
}, [])
|
|
145
145
|
|
|
146
|
-
const
|
|
146
|
+
const currentTooltip = useValue(
|
|
147
|
+
'current tooltip',
|
|
148
|
+
() => tooltipManager.getCurrentTooltipData(),
|
|
149
|
+
[]
|
|
150
|
+
)
|
|
147
151
|
|
|
148
152
|
// Update open state and trigger position
|
|
149
153
|
useEffect(() => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// Clear any existing show timeout
|
|
153
|
-
if (showTimeoutRef.current) {
|
|
154
|
-
clearTimeout(showTimeoutRef.current)
|
|
155
|
-
showTimeoutRef.current = null
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (shouldBeOpen && tooltipData.element && triggerRef.current) {
|
|
154
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
155
|
+
if (currentTooltip && triggerRef.current) {
|
|
159
156
|
// Position the invisible trigger element over the active element
|
|
160
|
-
const activeRect =
|
|
157
|
+
const activeRect = currentTooltip.targetElement.getBoundingClientRect()
|
|
161
158
|
const trigger = triggerRef.current
|
|
162
159
|
|
|
163
|
-
const newPosition = {
|
|
164
|
-
x: activeRect.left + activeRect.width / 2,
|
|
165
|
-
y: activeRect.top + activeRect.height / 2,
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Determine if we should animate
|
|
169
|
-
let shouldAnimateCheck = false
|
|
170
|
-
if (previousPositionRef.current) {
|
|
171
|
-
const isNearPrevious = Vec.DistMin(previousPositionRef.current, newPosition, 200)
|
|
172
|
-
// Only animate if the distance is less than 200px (nearby tooltips)
|
|
173
|
-
shouldAnimateCheck =
|
|
174
|
-
!prefersReducedMotion &&
|
|
175
|
-
isNearPrevious &&
|
|
176
|
-
Math.abs(newPosition.y - previousPositionRef.current.y) < 50
|
|
177
|
-
}
|
|
178
|
-
// Don't animate on initial show (previousPositionRef.current is null)
|
|
179
|
-
|
|
180
|
-
setShouldAnimate(isFirstShowRef.current ? false : shouldAnimateCheck)
|
|
181
|
-
previousPositionRef.current = newPosition
|
|
182
|
-
|
|
183
160
|
trigger.style.position = 'fixed'
|
|
184
161
|
trigger.style.left = `${activeRect.left}px`
|
|
185
162
|
trigger.style.top = `${activeRect.top}px`
|
|
@@ -189,27 +166,31 @@ function TooltipSingleton() {
|
|
|
189
166
|
trigger.style.zIndex = '9999'
|
|
190
167
|
|
|
191
168
|
// Handle delay for first show
|
|
192
|
-
if (isFirstShowRef.current
|
|
193
|
-
|
|
169
|
+
if (isFirstShowRef.current) {
|
|
170
|
+
// eslint-disable-next-line no-restricted-globals
|
|
171
|
+
timer = setTimeout(() => {
|
|
194
172
|
setIsOpen(true)
|
|
195
173
|
isFirstShowRef.current = false
|
|
196
|
-
},
|
|
174
|
+
}, currentTooltip.delayDuration)
|
|
197
175
|
} else {
|
|
198
176
|
// Subsequent tooltips show immediately
|
|
199
177
|
setIsOpen(true)
|
|
200
178
|
}
|
|
201
|
-
} else
|
|
179
|
+
} else {
|
|
202
180
|
// Hide tooltip immediately
|
|
203
181
|
setIsOpen(false)
|
|
204
|
-
// Reset position tracking when tooltip closes
|
|
205
|
-
previousPositionRef.current = null
|
|
206
|
-
setShouldAnimate(false)
|
|
207
182
|
// Reset first show state after tooltip is hidden
|
|
208
183
|
isFirstShowRef.current = true
|
|
209
184
|
}
|
|
210
|
-
}, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion])
|
|
211
185
|
|
|
212
|
-
|
|
186
|
+
return () => {
|
|
187
|
+
if (timer !== null) {
|
|
188
|
+
clearTimeout(timer)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}, [currentTooltip])
|
|
192
|
+
|
|
193
|
+
if (!currentTooltip) {
|
|
213
194
|
return null
|
|
214
195
|
}
|
|
215
196
|
|
|
@@ -220,14 +201,13 @@ function TooltipSingleton() {
|
|
|
220
201
|
</_Tooltip.Trigger>
|
|
221
202
|
<_Tooltip.Content
|
|
222
203
|
className="tlui-tooltip"
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
sideOffset={tooltipData.sideOffset}
|
|
204
|
+
side={currentTooltip.side}
|
|
205
|
+
sideOffset={currentTooltip.sideOffset}
|
|
226
206
|
avoidCollisions
|
|
227
207
|
collisionPadding={8}
|
|
228
208
|
dir="ltr"
|
|
229
209
|
>
|
|
230
|
-
{
|
|
210
|
+
{currentTooltip.content}
|
|
231
211
|
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
232
212
|
</_Tooltip.Content>
|
|
233
213
|
</_Tooltip.Root>
|
|
@@ -235,79 +215,117 @@ function TooltipSingleton() {
|
|
|
235
215
|
}
|
|
236
216
|
|
|
237
217
|
/** @public @react */
|
|
238
|
-
export
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
sideOffset = 5,
|
|
243
|
-
disabled = false,
|
|
244
|
-
}: TldrawUiTooltipProps) {
|
|
245
|
-
const editor = useMaybeEditor()
|
|
246
|
-
const tooltipId = useRef<string>(uniqueId())
|
|
247
|
-
const hasProvider = useContext(TooltipSingletonContext)
|
|
248
|
-
|
|
249
|
-
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
250
|
-
if (disabled || !content) {
|
|
251
|
-
return <>{children}</>
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Fallback to old behavior if no provider
|
|
255
|
-
if (!hasProvider) {
|
|
256
|
-
return (
|
|
257
|
-
<_Tooltip.Root
|
|
258
|
-
delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
|
|
259
|
-
disableHoverableContent
|
|
260
|
-
>
|
|
261
|
-
<_Tooltip.Trigger asChild>{children}</_Tooltip.Trigger>
|
|
262
|
-
<_Tooltip.Content
|
|
263
|
-
className="tlui-tooltip"
|
|
264
|
-
side={side}
|
|
265
|
-
sideOffset={sideOffset}
|
|
266
|
-
avoidCollisions
|
|
267
|
-
collisionPadding={8}
|
|
268
|
-
dir="ltr"
|
|
269
|
-
>
|
|
270
|
-
{content}
|
|
271
|
-
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
272
|
-
</_Tooltip.Content>
|
|
273
|
-
</_Tooltip.Root>
|
|
274
|
-
)
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
|
|
278
|
-
tooltipManager.showTooltip(
|
|
279
|
-
tooltipId.current,
|
|
218
|
+
export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
|
|
219
|
+
(
|
|
220
|
+
{
|
|
221
|
+
children,
|
|
280
222
|
content,
|
|
281
|
-
event.currentTarget as HTMLElement,
|
|
282
223
|
side,
|
|
283
|
-
sideOffset
|
|
284
|
-
|
|
285
|
-
|
|
224
|
+
sideOffset = 5,
|
|
225
|
+
disabled = false,
|
|
226
|
+
showOnMobile = false,
|
|
227
|
+
delayDuration,
|
|
228
|
+
},
|
|
229
|
+
ref
|
|
230
|
+
) => {
|
|
231
|
+
const editor = useMaybeEditor()
|
|
232
|
+
const tooltipId = useRef<string>(uniqueId())
|
|
233
|
+
const hasProvider = useContext(TooltipSingletonContext)
|
|
234
|
+
|
|
235
|
+
const orientationCtx = useTldrawUiOrientation()
|
|
236
|
+
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
237
|
+
|
|
238
|
+
const camera = useValue('camera', () => editor?.getCamera(), [])
|
|
239
|
+
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
const currentTooltipId = tooltipId.current
|
|
242
|
+
return () => {
|
|
243
|
+
if (hasProvider) {
|
|
244
|
+
tooltipManager.hideTooltip(editor, currentTooltipId, true)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}, [editor, hasProvider])
|
|
286
248
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
tooltipManager.hideTooltip(editor, tooltipId.current, true)
|
|
251
|
+
}, [editor, camera])
|
|
290
252
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
event.currentTarget as HTMLElement,
|
|
296
|
-
side,
|
|
297
|
-
sideOffset
|
|
298
|
-
)
|
|
299
|
-
}
|
|
253
|
+
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
254
|
+
if (disabled || !content) {
|
|
255
|
+
return <>{children}</>
|
|
256
|
+
}
|
|
300
257
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
258
|
+
const delayDurationToUse =
|
|
259
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
260
|
+
|
|
261
|
+
// Fallback to old behavior if no provider
|
|
262
|
+
if (!hasProvider) {
|
|
263
|
+
return (
|
|
264
|
+
<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>
|
|
265
|
+
<_Tooltip.Trigger asChild ref={ref}>
|
|
266
|
+
{children}
|
|
267
|
+
</_Tooltip.Trigger>
|
|
268
|
+
<_Tooltip.Content
|
|
269
|
+
className="tlui-tooltip"
|
|
270
|
+
side={sideToUse}
|
|
271
|
+
sideOffset={sideOffset}
|
|
272
|
+
avoidCollisions
|
|
273
|
+
collisionPadding={8}
|
|
274
|
+
dir="ltr"
|
|
275
|
+
>
|
|
276
|
+
{content}
|
|
277
|
+
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
278
|
+
</_Tooltip.Content>
|
|
279
|
+
</_Tooltip.Root>
|
|
280
|
+
)
|
|
281
|
+
}
|
|
304
282
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
283
|
+
const child = React.Children.only(children)
|
|
284
|
+
assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
|
|
285
|
+
|
|
286
|
+
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
|
|
287
|
+
child.props.onMouseEnter?.(event)
|
|
288
|
+
tooltipManager.showTooltip(
|
|
289
|
+
tooltipId.current,
|
|
290
|
+
content,
|
|
291
|
+
event.currentTarget as HTMLElement,
|
|
292
|
+
sideToUse,
|
|
293
|
+
sideOffset,
|
|
294
|
+
showOnMobile,
|
|
295
|
+
delayDurationToUse
|
|
296
|
+
)
|
|
297
|
+
}
|
|
311
298
|
|
|
312
|
-
|
|
313
|
-
|
|
299
|
+
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
|
300
|
+
child.props.onMouseLeave?.(event)
|
|
301
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
|
305
|
+
child.props.onFocus?.(event)
|
|
306
|
+
tooltipManager.showTooltip(
|
|
307
|
+
tooltipId.current,
|
|
308
|
+
content,
|
|
309
|
+
event.currentTarget as HTMLElement,
|
|
310
|
+
sideToUse,
|
|
311
|
+
sideOffset,
|
|
312
|
+
showOnMobile,
|
|
313
|
+
delayDurationToUse
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
|
|
318
|
+
child.props.onBlur?.(event)
|
|
319
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
|
|
323
|
+
onMouseEnter: handleMouseEnter,
|
|
324
|
+
onMouseLeave: handleMouseLeave,
|
|
325
|
+
onFocus: handleFocus,
|
|
326
|
+
onBlur: handleBlur,
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
return childrenWithHandlers
|
|
330
|
+
}
|
|
331
|
+
)
|