tldraw 3.16.0-canary.a2491e00987a → 3.16.0-canary.a675c73ef29d
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 +230 -106
- package/dist-cjs/index.js +33 -14
- 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/defaultExternalContentHandlers.js +5 -4
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -5
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
- package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
- 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/shared/useEditablePlainText.js +3 -4
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
- package/dist-cjs/lib/shapes/text/PlainTextArea.js +2 -2
- package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
- package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
- package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
- 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/ui/TldrawUi.js +13 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
- 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/A11y.js +1 -1
- package/dist-cjs/lib/ui/components/A11y.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/PageMenu/DefaultPageMenu.js +1 -1
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
- 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 +38 -9
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- 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/primitives/TldrawUiContextualToolbar.js +11 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +125 -122
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.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 +0 -10
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +8 -24
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +23 -10
- 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 +1 -1
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +22 -4
- 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 +4 -2
- 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-cjs/lib/utils/export/copyAs.js +1 -2
- package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
- package/dist-cjs/lib/utils/export/export.js +0 -20
- package/dist-cjs/lib/utils/export/export.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js +1 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-esm/index.d.mts +230 -106
- package/dist-esm/index.mjs +61 -29
- 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/defaultExternalContentHandlers.mjs +5 -4
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +12 -5
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +3 -3
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
- package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +1 -1
- 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/shared/useEditablePlainText.mjs +4 -5
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -3
- package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
- package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
- 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/ui/TldrawUi.mjs +13 -12
- package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
- 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/A11y.mjs +2 -2
- package/dist-esm/lib/ui/components/A11y.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/PageMenu/DefaultPageMenu.mjs +2 -2
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
- 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 +38 -9
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.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/primitives/TldrawUiContextualToolbar.mjs +12 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +3 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +135 -124
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.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 +0 -10
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +8 -24
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +23 -10
- 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 +1 -1
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +23 -4
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -2
- 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/dist-esm/lib/utils/export/copyAs.mjs +1 -2
- package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
- package/dist-esm/lib/utils/export/export.mjs +0 -20
- package/dist-esm/lib/utils/export/export.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/package.json +11 -34
- package/src/index.ts +44 -22
- package/src/lib/Tldraw.tsx +15 -2
- 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 +6 -5
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +48 -6
- package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
- package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -4
- package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
- package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
- package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
- package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
- package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
- package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
- package/src/lib/shapes/shared/ShapeFill.tsx +1 -1
- package/src/lib/shapes/shared/freehand/svg.ts +2 -0
- package/src/lib/shapes/shared/useEditablePlainText.ts +5 -9
- package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
- package/src/lib/shapes/text/PlainTextArea.tsx +3 -3
- package/src/lib/shapes/text/RichTextArea.tsx +3 -4
- package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
- package/src/lib/ui/TldrawUi.tsx +16 -10
- package/src/lib/ui/assetUrls.ts +13 -10
- package/src/lib/ui/components/A11y.tsx +2 -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/PageMenu/DefaultPageMenu.tsx +2 -2
- package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
- package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
- package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
- package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
- package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
- package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
- 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/primitives/TldrawUiContextualToolbar.tsx +8 -3
- package/src/lib/ui/components/primitives/TldrawUiInput.tsx +3 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +146 -124
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +0 -10
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +11 -24
- package/src/lib/ui/context/actions.tsx +23 -10
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/context/events.tsx +1 -1
- package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
- package/src/lib/ui/hooks/useExportAs.ts +3 -2
- package/src/lib/ui/hooks/useTools.tsx +26 -4
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -2
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +24 -8
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
- package/src/lib/utils/export/copyAs.ts +1 -24
- package/src/lib/utils/export/export.ts +0 -36
- package/src/lib/utils/export/exportAs.ts +1 -32
- 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 +74 -4
- 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 +40 -11
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
|
@@ -118,7 +118,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
118
118
|
// `onChange` with a duplicated text value.
|
|
119
119
|
if (isComposing.current) return
|
|
120
120
|
e.currentTarget.blur()
|
|
121
|
-
|
|
121
|
+
e.stopPropagation()
|
|
122
122
|
onComplete?.(e.currentTarget.value)
|
|
123
123
|
break
|
|
124
124
|
}
|
|
@@ -126,7 +126,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
126
126
|
e.currentTarget.value = rInitialValue.current
|
|
127
127
|
onCancel?.(e.currentTarget.value)
|
|
128
128
|
e.currentTarget.blur()
|
|
129
|
-
|
|
129
|
+
e.stopPropagation()
|
|
130
130
|
break
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -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 {
|
|
@@ -11,7 +13,7 @@ export interface TLUiSliderProps {
|
|
|
11
13
|
label: string
|
|
12
14
|
title: string
|
|
13
15
|
onValueChange(value: number): void
|
|
14
|
-
onHistoryMark(id: string): void
|
|
16
|
+
onHistoryMark?(id: string): void
|
|
15
17
|
'data-testid'?: string
|
|
16
18
|
ariaValueModifier?: number
|
|
17
19
|
}
|
|
@@ -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(() => {
|
|
52
|
-
|
|
55
|
+
tooltipManager.hideAllTooltips()
|
|
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
|
})
|
|
@@ -94,6 +94,7 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes<HTMLDi
|
|
|
94
94
|
// TODO: fix up this type later
|
|
95
95
|
defaultValue?: any
|
|
96
96
|
type: 'single' | 'multiple'
|
|
97
|
+
asChild?: boolean
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/** @public @react */
|
|
@@ -101,10 +102,12 @@ export const TldrawUiToolbarToggleGroup = ({
|
|
|
101
102
|
children,
|
|
102
103
|
className,
|
|
103
104
|
type,
|
|
105
|
+
asChild,
|
|
104
106
|
...props
|
|
105
107
|
}: TLUiToolbarToggleGroupProps) => {
|
|
106
108
|
return (
|
|
107
109
|
<_Toolbar.ToggleGroup
|
|
110
|
+
asChild={asChild}
|
|
108
111
|
type={type}
|
|
109
112
|
{...props}
|
|
110
113
|
// TODO: this fixes a bug in Radix until they fix it.
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { assert, 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
|
+
useLayoutEffect,
|
|
10
|
+
useRef,
|
|
11
|
+
useState,
|
|
12
|
+
} from 'react'
|
|
5
13
|
import { useTldrawUiOrientation } from './layout'
|
|
6
14
|
|
|
7
15
|
const DEFAULT_TOOLTIP_DELAY_MS = 700
|
|
@@ -13,19 +21,25 @@ export interface TldrawUiTooltipProps {
|
|
|
13
21
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
14
22
|
sideOffset?: number
|
|
15
23
|
disabled?: boolean
|
|
24
|
+
showOnMobile?: boolean
|
|
25
|
+
delayDuration?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface CurrentTooltip {
|
|
29
|
+
id: string
|
|
30
|
+
content: ReactNode
|
|
31
|
+
side: 'top' | 'right' | 'bottom' | 'left'
|
|
32
|
+
sideOffset: number
|
|
33
|
+
showOnMobile: boolean
|
|
34
|
+
targetElement: HTMLElement
|
|
35
|
+
delayDuration: number
|
|
16
36
|
}
|
|
17
37
|
|
|
18
38
|
// Singleton tooltip manager
|
|
19
39
|
class TooltipManager {
|
|
20
40
|
private static instance: TooltipManager | null = null
|
|
21
|
-
private
|
|
22
|
-
private currentContent: string | React.ReactNode = ''
|
|
23
|
-
private currentSide: 'top' | 'right' | 'bottom' | 'left' = 'bottom'
|
|
24
|
-
private currentSideOffset: number = 5
|
|
41
|
+
private currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)
|
|
25
42
|
private destroyTimeoutId: number | null = null
|
|
26
|
-
private subscribers: Set<() => void> = new Set()
|
|
27
|
-
private activeElement: HTMLElement | null = null
|
|
28
|
-
private editor: Editor | null = null
|
|
29
43
|
|
|
30
44
|
static getInstance(): TooltipManager {
|
|
31
45
|
if (!TooltipManager.instance) {
|
|
@@ -34,25 +48,14 @@ class TooltipManager {
|
|
|
34
48
|
return TooltipManager.instance
|
|
35
49
|
}
|
|
36
50
|
|
|
37
|
-
setEditor(editor: Editor | null) {
|
|
38
|
-
this.editor = editor
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
subscribe(callback: () => void): () => void {
|
|
42
|
-
this.subscribers.add(callback)
|
|
43
|
-
return () => this.subscribers.delete(callback)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private notify() {
|
|
47
|
-
this.subscribers.forEach((callback) => callback())
|
|
48
|
-
}
|
|
49
|
-
|
|
50
51
|
showTooltip(
|
|
51
52
|
tooltipId: string,
|
|
52
53
|
content: string | React.ReactNode,
|
|
53
|
-
|
|
54
|
-
side: 'top' | 'right' | 'bottom' | 'left'
|
|
55
|
-
sideOffset: number
|
|
54
|
+
targetElement: HTMLElement,
|
|
55
|
+
side: 'top' | 'right' | 'bottom' | 'left',
|
|
56
|
+
sideOffset: number,
|
|
57
|
+
showOnMobile: boolean,
|
|
58
|
+
delayDuration: number
|
|
56
59
|
) {
|
|
57
60
|
// Clear any existing destroy timeout
|
|
58
61
|
if (this.destroyTimeoutId) {
|
|
@@ -61,51 +64,66 @@ class TooltipManager {
|
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
// Update current tooltip
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
this.currentTooltip.set({
|
|
68
|
+
id: tooltipId,
|
|
69
|
+
content,
|
|
70
|
+
side,
|
|
71
|
+
sideOffset,
|
|
72
|
+
showOnMobile,
|
|
73
|
+
targetElement,
|
|
74
|
+
delayDuration,
|
|
75
|
+
})
|
|
76
|
+
}
|
|
69
77
|
|
|
70
|
-
|
|
78
|
+
updateCurrentTooltip(tooltipId: string, update: (tooltip: CurrentTooltip) => CurrentTooltip) {
|
|
79
|
+
this.currentTooltip.update((tooltip) => {
|
|
80
|
+
if (tooltip?.id === tooltipId) {
|
|
81
|
+
return update(tooltip)
|
|
82
|
+
}
|
|
83
|
+
return tooltip
|
|
84
|
+
})
|
|
71
85
|
}
|
|
72
86
|
|
|
73
|
-
hideTooltip(tooltipId: string, instant: boolean = false) {
|
|
87
|
+
hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
|
|
74
88
|
const hide = () => {
|
|
75
89
|
// Only hide if this is the current tooltip
|
|
76
|
-
if (this.
|
|
77
|
-
this.
|
|
78
|
-
this.currentContent = ''
|
|
79
|
-
this.activeElement = null
|
|
90
|
+
if (this.currentTooltip.get()?.id === tooltipId) {
|
|
91
|
+
this.currentTooltip.set(null)
|
|
80
92
|
this.destroyTimeoutId = null
|
|
81
|
-
this.notify()
|
|
82
93
|
}
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
if (instant) {
|
|
86
|
-
hide()
|
|
87
|
-
} else if (this.editor) {
|
|
96
|
+
if (editor && !instant) {
|
|
88
97
|
// Start destroy timeout (1 second)
|
|
89
|
-
this.destroyTimeoutId =
|
|
98
|
+
this.destroyTimeoutId = editor.timers.setTimeout(hide, 300)
|
|
99
|
+
} else {
|
|
100
|
+
hide()
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
hideAllTooltips() {
|
|
94
|
-
this.
|
|
95
|
-
this.currentContent = ''
|
|
96
|
-
this.activeElement = null
|
|
105
|
+
this.currentTooltip.set(null)
|
|
97
106
|
this.destroyTimeoutId = null
|
|
98
|
-
this.notify()
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
getCurrentTooltipData() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
const currentTooltip = this.currentTooltip.get()
|
|
111
|
+
if (!currentTooltip) return null
|
|
112
|
+
if (!this.supportsHover() && !currentTooltip.showOnMobile) return null
|
|
113
|
+
return currentTooltip
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private supportsHoverAtom: Atom<boolean> | null = null
|
|
117
|
+
supportsHover() {
|
|
118
|
+
if (!this.supportsHoverAtom) {
|
|
119
|
+
const mediaQuery = window.matchMedia('(hover: hover)')
|
|
120
|
+
const supportsHover = atom('has hover', mediaQuery.matches)
|
|
121
|
+
this.supportsHoverAtom = supportsHover
|
|
122
|
+
mediaQuery.addEventListener('change', (e) => {
|
|
123
|
+
supportsHover.set(e.matches)
|
|
124
|
+
})
|
|
108
125
|
}
|
|
126
|
+
return this.supportsHoverAtom.get()
|
|
109
127
|
}
|
|
110
128
|
}
|
|
111
129
|
|
|
@@ -133,66 +151,34 @@ export function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderPro
|
|
|
133
151
|
|
|
134
152
|
// The singleton tooltip component that renders once
|
|
135
153
|
function TooltipSingleton() {
|
|
136
|
-
const editor = useMaybeEditor()
|
|
137
|
-
const [, forceUpdate] = useState({})
|
|
138
154
|
const [isOpen, setIsOpen] = useState(false)
|
|
139
155
|
const triggerRef = useRef<HTMLDivElement>(null)
|
|
140
|
-
const previousPositionRef = useRef<{ x: number; y: number } | null>(null)
|
|
141
|
-
const prefersReducedMotion = usePrefersReducedMotion()
|
|
142
|
-
const [shouldAnimate, setShouldAnimate] = useState(false)
|
|
143
156
|
const isFirstShowRef = useRef(true)
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
// Set editor in tooltip manager
|
|
147
|
-
useEffect(() => {
|
|
148
|
-
tooltipManager.setEditor(editor)
|
|
149
|
-
}, [editor])
|
|
157
|
+
const editor = useMaybeEditor()
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return unsubscribe
|
|
157
|
-
}, [])
|
|
159
|
+
const currentTooltip = useValue(
|
|
160
|
+
'current tooltip',
|
|
161
|
+
() => tooltipManager.getCurrentTooltipData(),
|
|
162
|
+
[]
|
|
163
|
+
)
|
|
158
164
|
|
|
159
|
-
const
|
|
165
|
+
const cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])
|
|
160
166
|
|
|
161
|
-
//
|
|
167
|
+
// Hide tooltip when camera is moving (panning/zooming)
|
|
162
168
|
useEffect(() => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// Clear any existing show timeout
|
|
166
|
-
if (showTimeoutRef.current) {
|
|
167
|
-
clearTimeout(showTimeoutRef.current)
|
|
168
|
-
showTimeoutRef.current = null
|
|
169
|
+
if (cameraState === 'moving' && isOpen && currentTooltip) {
|
|
170
|
+
tooltipManager.hideTooltip(editor, currentTooltip.id, true)
|
|
169
171
|
}
|
|
172
|
+
}, [cameraState, isOpen, currentTooltip, editor])
|
|
170
173
|
|
|
171
|
-
|
|
174
|
+
// Update open state and trigger position
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
177
|
+
if (currentTooltip && triggerRef.current) {
|
|
172
178
|
// Position the invisible trigger element over the active element
|
|
173
|
-
const activeRect =
|
|
179
|
+
const activeRect = currentTooltip.targetElement.getBoundingClientRect()
|
|
174
180
|
const trigger = triggerRef.current
|
|
175
181
|
|
|
176
|
-
const newPosition = {
|
|
177
|
-
x: activeRect.left + activeRect.width / 2,
|
|
178
|
-
y: activeRect.top + activeRect.height / 2,
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Determine if we should animate
|
|
182
|
-
let shouldAnimateCheck = false
|
|
183
|
-
if (previousPositionRef.current) {
|
|
184
|
-
const isNearPrevious = Vec.DistMin(previousPositionRef.current, newPosition, 200)
|
|
185
|
-
// Only animate if the distance is less than 200px (nearby tooltips)
|
|
186
|
-
shouldAnimateCheck =
|
|
187
|
-
!prefersReducedMotion &&
|
|
188
|
-
isNearPrevious &&
|
|
189
|
-
Math.abs(newPosition.y - previousPositionRef.current.y) < 50
|
|
190
|
-
}
|
|
191
|
-
// Don't animate on initial show (previousPositionRef.current is null)
|
|
192
|
-
|
|
193
|
-
setShouldAnimate(isFirstShowRef.current ? false : shouldAnimateCheck)
|
|
194
|
-
previousPositionRef.current = newPosition
|
|
195
|
-
|
|
196
182
|
trigger.style.position = 'fixed'
|
|
197
183
|
trigger.style.left = `${activeRect.left}px`
|
|
198
184
|
trigger.style.top = `${activeRect.top}px`
|
|
@@ -202,27 +188,31 @@ function TooltipSingleton() {
|
|
|
202
188
|
trigger.style.zIndex = '9999'
|
|
203
189
|
|
|
204
190
|
// Handle delay for first show
|
|
205
|
-
if (isFirstShowRef.current
|
|
206
|
-
|
|
191
|
+
if (isFirstShowRef.current) {
|
|
192
|
+
// eslint-disable-next-line no-restricted-globals
|
|
193
|
+
timer = setTimeout(() => {
|
|
207
194
|
setIsOpen(true)
|
|
208
195
|
isFirstShowRef.current = false
|
|
209
|
-
},
|
|
196
|
+
}, currentTooltip.delayDuration)
|
|
210
197
|
} else {
|
|
211
198
|
// Subsequent tooltips show immediately
|
|
212
199
|
setIsOpen(true)
|
|
213
200
|
}
|
|
214
|
-
} else
|
|
201
|
+
} else {
|
|
215
202
|
// Hide tooltip immediately
|
|
216
203
|
setIsOpen(false)
|
|
217
|
-
// Reset position tracking when tooltip closes
|
|
218
|
-
previousPositionRef.current = null
|
|
219
|
-
setShouldAnimate(false)
|
|
220
204
|
// Reset first show state after tooltip is hidden
|
|
221
205
|
isFirstShowRef.current = true
|
|
222
206
|
}
|
|
223
|
-
}, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion])
|
|
224
207
|
|
|
225
|
-
|
|
208
|
+
return () => {
|
|
209
|
+
if (timer !== null) {
|
|
210
|
+
clearTimeout(timer)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}, [currentTooltip])
|
|
214
|
+
|
|
215
|
+
if (!currentTooltip) {
|
|
226
216
|
return null
|
|
227
217
|
}
|
|
228
218
|
|
|
@@ -233,14 +223,13 @@ function TooltipSingleton() {
|
|
|
233
223
|
</_Tooltip.Trigger>
|
|
234
224
|
<_Tooltip.Content
|
|
235
225
|
className="tlui-tooltip"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
sideOffset={tooltipData.sideOffset}
|
|
226
|
+
side={currentTooltip.side}
|
|
227
|
+
sideOffset={currentTooltip.sideOffset}
|
|
239
228
|
avoidCollisions
|
|
240
229
|
collisionPadding={8}
|
|
241
230
|
dir="ltr"
|
|
242
231
|
>
|
|
243
|
-
{
|
|
232
|
+
{currentTooltip.content}
|
|
244
233
|
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
245
234
|
</_Tooltip.Content>
|
|
246
235
|
</_Tooltip.Root>
|
|
@@ -249,10 +238,22 @@ function TooltipSingleton() {
|
|
|
249
238
|
|
|
250
239
|
/** @public @react */
|
|
251
240
|
export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
|
|
252
|
-
(
|
|
241
|
+
(
|
|
242
|
+
{
|
|
243
|
+
children,
|
|
244
|
+
content,
|
|
245
|
+
side,
|
|
246
|
+
sideOffset = 5,
|
|
247
|
+
disabled = false,
|
|
248
|
+
showOnMobile = false,
|
|
249
|
+
delayDuration,
|
|
250
|
+
},
|
|
251
|
+
ref
|
|
252
|
+
) => {
|
|
253
253
|
const editor = useMaybeEditor()
|
|
254
254
|
const tooltipId = useRef<string>(uniqueId())
|
|
255
255
|
const hasProvider = useContext(TooltipSingletonContext)
|
|
256
|
+
const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
|
|
256
257
|
|
|
257
258
|
const orientationCtx = useTldrawUiOrientation()
|
|
258
259
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
@@ -261,23 +262,40 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
261
262
|
const currentTooltipId = tooltipId.current
|
|
262
263
|
return () => {
|
|
263
264
|
if (hasProvider) {
|
|
264
|
-
tooltipManager.hideTooltip(currentTooltipId, true)
|
|
265
|
+
tooltipManager.hideTooltip(editor, currentTooltipId, true)
|
|
265
266
|
}
|
|
266
267
|
}
|
|
267
|
-
}, [hasProvider])
|
|
268
|
+
}, [editor, hasProvider])
|
|
269
|
+
|
|
270
|
+
useLayoutEffect(() => {
|
|
271
|
+
if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
|
|
272
|
+
tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
|
|
273
|
+
...tooltip,
|
|
274
|
+
content,
|
|
275
|
+
side: sideToUse,
|
|
276
|
+
sideOffset,
|
|
277
|
+
showOnMobile,
|
|
278
|
+
}))
|
|
279
|
+
}
|
|
280
|
+
}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
|
|
268
281
|
|
|
269
282
|
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
270
283
|
if (disabled || !content) {
|
|
271
284
|
return <>{children}</>
|
|
272
285
|
}
|
|
273
286
|
|
|
287
|
+
let delayDurationToUse
|
|
288
|
+
if (showUiLabels) {
|
|
289
|
+
delayDurationToUse = 0
|
|
290
|
+
} else {
|
|
291
|
+
delayDurationToUse =
|
|
292
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
293
|
+
}
|
|
294
|
+
|
|
274
295
|
// Fallback to old behavior if no provider
|
|
275
296
|
if (!hasProvider) {
|
|
276
297
|
return (
|
|
277
|
-
<_Tooltip.Root
|
|
278
|
-
delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
|
|
279
|
-
disableHoverableContent
|
|
280
|
-
>
|
|
298
|
+
<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>
|
|
281
299
|
<_Tooltip.Trigger asChild ref={ref}>
|
|
282
300
|
{children}
|
|
283
301
|
</_Tooltip.Trigger>
|
|
@@ -306,13 +324,15 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
306
324
|
content,
|
|
307
325
|
event.currentTarget as HTMLElement,
|
|
308
326
|
sideToUse,
|
|
309
|
-
sideOffset
|
|
327
|
+
sideOffset,
|
|
328
|
+
showOnMobile,
|
|
329
|
+
delayDurationToUse
|
|
310
330
|
)
|
|
311
331
|
}
|
|
312
332
|
|
|
313
333
|
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
|
314
334
|
child.props.onMouseLeave?.(event)
|
|
315
|
-
tooltipManager.hideTooltip(tooltipId.current)
|
|
335
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
316
336
|
}
|
|
317
337
|
|
|
318
338
|
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
|
@@ -322,13 +342,15 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
322
342
|
content,
|
|
323
343
|
event.currentTarget as HTMLElement,
|
|
324
344
|
sideToUse,
|
|
325
|
-
sideOffset
|
|
345
|
+
sideOffset,
|
|
346
|
+
showOnMobile,
|
|
347
|
+
delayDurationToUse
|
|
326
348
|
)
|
|
327
349
|
}
|
|
328
350
|
|
|
329
351
|
const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
|
|
330
352
|
child.props.onBlur?.(event)
|
|
331
|
-
tooltipManager.hideTooltip(tooltipId.current)
|
|
353
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
332
354
|
}
|
|
333
355
|
|
|
334
356
|
const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
|
|
@@ -27,16 +27,6 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
27
27
|
const labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined
|
|
28
28
|
|
|
29
29
|
switch (menu.type) {
|
|
30
|
-
case 'panel': {
|
|
31
|
-
return (
|
|
32
|
-
<div
|
|
33
|
-
className={classNames('tlui-menu__group', className)}
|
|
34
|
-
data-testid={`${menu.sourceId}-group.${id}`}
|
|
35
|
-
>
|
|
36
|
-
{children}
|
|
37
|
-
</div>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
30
|
case 'menu': {
|
|
41
31
|
return (
|
|
42
32
|
<TldrawUiDropdownMenuGroup
|