tldraw 3.16.0-canary.7f4043b128a3 → 3.16.0-canary.806d674b7d7a
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 +234 -108
- 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/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +15 -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/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- 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/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- 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/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.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 +6 -3
- 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/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/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/LanguageMenu.js +1 -0
- package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -0
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
- 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 +1 -1
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- 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/StylePanel/StylePanelButtonPicker.js +147 -0
- 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 +2 -0
- 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/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 +2 -1
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.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 +5 -3
- 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 +3 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +137 -122
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +3 -0
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.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 +29 -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 +6 -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 +234 -108
- 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/canvas/TldrawScribble.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +15 -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/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- 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/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- 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/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.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 +6 -3
- 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/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/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/LanguageMenu.mjs +1 -0
- package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -0
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
- 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 +1 -1
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- 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/StylePanel/StylePanelButtonPicker.mjs +135 -0
- 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 +2 -0
- 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/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 +2 -1
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.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 +6 -4
- 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 +3 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +147 -124
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.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 +29 -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 +6 -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/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/defaultExternalContentHandlers.ts +26 -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/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -4
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- 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 +6 -3
- 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/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/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/LanguageMenu.tsx +1 -0
- package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -0
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +1 -1
- 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} +70 -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 +2 -0
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +33 -16
- package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +1 -0
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
- package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +8 -3
- package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +5 -1
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +159 -123
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
- 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 +36 -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 +4 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +6 -2
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +256 -230
- 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 +564 -522
- 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 +0 -131
- 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 +0 -115
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
Box,
|
|
4
4
|
clamp,
|
|
5
5
|
Editor,
|
|
6
|
+
markEventAsHandled,
|
|
6
7
|
react,
|
|
7
|
-
stopEventPropagation,
|
|
8
8
|
useAtom,
|
|
9
9
|
useEditor,
|
|
10
10
|
usePassThroughMouseOverEvents,
|
|
@@ -170,9 +170,14 @@ export const TldrawUiContextualToolbar = ({
|
|
|
170
170
|
data-visible={false}
|
|
171
171
|
data-testid="contextual-toolbar"
|
|
172
172
|
className={classNames('tlui-contextual-toolbar', className)}
|
|
173
|
-
onPointerDown={
|
|
173
|
+
onPointerDown={markEventAsHandled}
|
|
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,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'
|
|
@@ -35,6 +35,7 @@ export interface TLUiInputProps {
|
|
|
35
35
|
shouldManuallyMaintainScrollPositionWhenFocused?: boolean
|
|
36
36
|
value?: string
|
|
37
37
|
'data-testid'?: string
|
|
38
|
+
'aria-label'?: string
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/** @public @react */
|
|
@@ -60,6 +61,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
60
61
|
value,
|
|
61
62
|
'data-testid': dataTestId,
|
|
62
63
|
disabled,
|
|
64
|
+
'aria-label': ariaLabel,
|
|
63
65
|
},
|
|
64
66
|
ref
|
|
65
67
|
) {
|
|
@@ -118,7 +120,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
118
120
|
// `onChange` with a duplicated text value.
|
|
119
121
|
if (isComposing.current) return
|
|
120
122
|
e.currentTarget.blur()
|
|
121
|
-
|
|
123
|
+
e.stopPropagation()
|
|
122
124
|
onComplete?.(e.currentTarget.value)
|
|
123
125
|
break
|
|
124
126
|
}
|
|
@@ -126,7 +128,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
126
128
|
e.currentTarget.value = rInitialValue.current
|
|
127
129
|
onCancel?.(e.currentTarget.value)
|
|
128
130
|
e.currentTarget.blur()
|
|
129
|
-
|
|
131
|
+
e.stopPropagation()
|
|
130
132
|
break
|
|
131
133
|
}
|
|
132
134
|
}
|
|
@@ -198,6 +200,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
198
200
|
onCompositionStart={handleCompositionStart}
|
|
199
201
|
onCompositionEnd={handleCompositionEnd}
|
|
200
202
|
autoFocus={autoFocus}
|
|
203
|
+
aria-label={ariaLabel}
|
|
201
204
|
placeholder={placeholder}
|
|
202
205
|
value={value}
|
|
203
206
|
data-testid={dataTestId}
|
|
@@ -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
|
})
|
|
@@ -71,6 +71,7 @@ export const TldrawUiToolbarButton = React.forwardRef<HTMLButtonElement, TLUiToo
|
|
|
71
71
|
draggable={false}
|
|
72
72
|
data-isactive={isActive}
|
|
73
73
|
{...props}
|
|
74
|
+
aria-label={props.title}
|
|
74
75
|
// The tooltip takes care of this.
|
|
75
76
|
title={undefined}
|
|
76
77
|
className={classnames('tlui-button', `tlui-button__${type}`, props.className)}
|
|
@@ -94,6 +95,7 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes<HTMLDi
|
|
|
94
95
|
// TODO: fix up this type later
|
|
95
96
|
defaultValue?: any
|
|
96
97
|
type: 'single' | 'multiple'
|
|
98
|
+
asChild?: boolean
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
/** @public @react */
|
|
@@ -101,10 +103,12 @@ export const TldrawUiToolbarToggleGroup = ({
|
|
|
101
103
|
children,
|
|
102
104
|
className,
|
|
103
105
|
type,
|
|
106
|
+
asChild,
|
|
104
107
|
...props
|
|
105
108
|
}: TLUiToolbarToggleGroupProps) => {
|
|
106
109
|
return (
|
|
107
110
|
<_Toolbar.ToggleGroup
|
|
111
|
+
asChild={asChild}
|
|
108
112
|
type={type}
|
|
109
113
|
{...props}
|
|
110
114
|
// TODO: this fixes a bug in Radix until they fix it.
|
|
@@ -124,7 +128,7 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes<HTMLBut
|
|
|
124
128
|
className?: string
|
|
125
129
|
type: 'icon' | 'tool'
|
|
126
130
|
value: string
|
|
127
|
-
tooltip?:
|
|
131
|
+
tooltip?: React.ReactNode
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
/** @public @react */
|
|
@@ -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,48 @@ 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
|
|
157
|
+
const editor = useMaybeEditor()
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
tooltipManager.
|
|
149
|
-
|
|
159
|
+
const currentTooltip = useValue(
|
|
160
|
+
'current tooltip',
|
|
161
|
+
() => tooltipManager.getCurrentTooltipData(),
|
|
162
|
+
[]
|
|
163
|
+
)
|
|
150
164
|
|
|
151
|
-
|
|
152
|
-
useEffect(() => {
|
|
153
|
-
const unsubscribe = tooltipManager.subscribe(() => {
|
|
154
|
-
forceUpdate({})
|
|
155
|
-
})
|
|
156
|
-
return unsubscribe
|
|
157
|
-
}, [])
|
|
165
|
+
const cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])
|
|
158
166
|
|
|
159
|
-
|
|
167
|
+
// Hide tooltip when camera is moving (panning/zooming)
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
if (cameraState === 'moving' && isOpen && currentTooltip) {
|
|
170
|
+
tooltipManager.hideTooltip(editor, currentTooltip.id, true)
|
|
171
|
+
}
|
|
172
|
+
}, [cameraState, isOpen, currentTooltip, editor])
|
|
160
173
|
|
|
161
|
-
// Update open state and trigger position
|
|
162
174
|
useEffect(() => {
|
|
163
|
-
|
|
175
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
176
|
+
if (event.key === 'Escape' && currentTooltip && isOpen) {
|
|
177
|
+
tooltipManager.hideTooltip(editor, currentTooltip.id)
|
|
178
|
+
event.stopPropagation()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
164
181
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
showTimeoutRef.current = null
|
|
182
|
+
document.addEventListener('keydown', handleKeyDown, { capture: true })
|
|
183
|
+
return () => {
|
|
184
|
+
document.removeEventListener('keydown', handleKeyDown, { capture: true })
|
|
169
185
|
}
|
|
186
|
+
}, [editor, currentTooltip, isOpen])
|
|
170
187
|
|
|
171
|
-
|
|
188
|
+
// Update open state and trigger position
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
191
|
+
if (currentTooltip && triggerRef.current) {
|
|
172
192
|
// Position the invisible trigger element over the active element
|
|
173
|
-
const activeRect =
|
|
193
|
+
const activeRect = currentTooltip.targetElement.getBoundingClientRect()
|
|
174
194
|
const trigger = triggerRef.current
|
|
175
195
|
|
|
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
196
|
trigger.style.position = 'fixed'
|
|
197
197
|
trigger.style.left = `${activeRect.left}px`
|
|
198
198
|
trigger.style.top = `${activeRect.top}px`
|
|
@@ -202,27 +202,31 @@ function TooltipSingleton() {
|
|
|
202
202
|
trigger.style.zIndex = '9999'
|
|
203
203
|
|
|
204
204
|
// Handle delay for first show
|
|
205
|
-
if (isFirstShowRef.current
|
|
206
|
-
|
|
205
|
+
if (isFirstShowRef.current) {
|
|
206
|
+
// eslint-disable-next-line no-restricted-globals
|
|
207
|
+
timer = setTimeout(() => {
|
|
207
208
|
setIsOpen(true)
|
|
208
209
|
isFirstShowRef.current = false
|
|
209
|
-
},
|
|
210
|
+
}, currentTooltip.delayDuration)
|
|
210
211
|
} else {
|
|
211
212
|
// Subsequent tooltips show immediately
|
|
212
213
|
setIsOpen(true)
|
|
213
214
|
}
|
|
214
|
-
} else
|
|
215
|
+
} else {
|
|
215
216
|
// Hide tooltip immediately
|
|
216
217
|
setIsOpen(false)
|
|
217
|
-
// Reset position tracking when tooltip closes
|
|
218
|
-
previousPositionRef.current = null
|
|
219
|
-
setShouldAnimate(false)
|
|
220
218
|
// Reset first show state after tooltip is hidden
|
|
221
219
|
isFirstShowRef.current = true
|
|
222
220
|
}
|
|
223
|
-
}, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion])
|
|
224
221
|
|
|
225
|
-
|
|
222
|
+
return () => {
|
|
223
|
+
if (timer !== null) {
|
|
224
|
+
clearTimeout(timer)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}, [currentTooltip])
|
|
228
|
+
|
|
229
|
+
if (!currentTooltip) {
|
|
226
230
|
return null
|
|
227
231
|
}
|
|
228
232
|
|
|
@@ -233,14 +237,13 @@ function TooltipSingleton() {
|
|
|
233
237
|
</_Tooltip.Trigger>
|
|
234
238
|
<_Tooltip.Content
|
|
235
239
|
className="tlui-tooltip"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
sideOffset={tooltipData.sideOffset}
|
|
240
|
+
side={currentTooltip.side}
|
|
241
|
+
sideOffset={currentTooltip.sideOffset}
|
|
239
242
|
avoidCollisions
|
|
240
243
|
collisionPadding={8}
|
|
241
244
|
dir="ltr"
|
|
242
245
|
>
|
|
243
|
-
{
|
|
246
|
+
{currentTooltip.content}
|
|
244
247
|
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
245
248
|
</_Tooltip.Content>
|
|
246
249
|
</_Tooltip.Root>
|
|
@@ -249,10 +252,22 @@ function TooltipSingleton() {
|
|
|
249
252
|
|
|
250
253
|
/** @public @react */
|
|
251
254
|
export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
|
|
252
|
-
(
|
|
255
|
+
(
|
|
256
|
+
{
|
|
257
|
+
children,
|
|
258
|
+
content,
|
|
259
|
+
side,
|
|
260
|
+
sideOffset = 5,
|
|
261
|
+
disabled = false,
|
|
262
|
+
showOnMobile = false,
|
|
263
|
+
delayDuration,
|
|
264
|
+
},
|
|
265
|
+
ref
|
|
266
|
+
) => {
|
|
253
267
|
const editor = useMaybeEditor()
|
|
254
268
|
const tooltipId = useRef<string>(uniqueId())
|
|
255
269
|
const hasProvider = useContext(TooltipSingletonContext)
|
|
270
|
+
const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
|
|
256
271
|
|
|
257
272
|
const orientationCtx = useTldrawUiOrientation()
|
|
258
273
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
@@ -261,23 +276,40 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
261
276
|
const currentTooltipId = tooltipId.current
|
|
262
277
|
return () => {
|
|
263
278
|
if (hasProvider) {
|
|
264
|
-
tooltipManager.hideTooltip(currentTooltipId, true)
|
|
279
|
+
tooltipManager.hideTooltip(editor, currentTooltipId, true)
|
|
265
280
|
}
|
|
266
281
|
}
|
|
267
|
-
}, [hasProvider])
|
|
282
|
+
}, [editor, hasProvider])
|
|
283
|
+
|
|
284
|
+
useLayoutEffect(() => {
|
|
285
|
+
if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
|
|
286
|
+
tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
|
|
287
|
+
...tooltip,
|
|
288
|
+
content,
|
|
289
|
+
side: sideToUse,
|
|
290
|
+
sideOffset,
|
|
291
|
+
showOnMobile,
|
|
292
|
+
}))
|
|
293
|
+
}
|
|
294
|
+
}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
|
|
268
295
|
|
|
269
296
|
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
270
297
|
if (disabled || !content) {
|
|
271
298
|
return <>{children}</>
|
|
272
299
|
}
|
|
273
300
|
|
|
301
|
+
let delayDurationToUse
|
|
302
|
+
if (showUiLabels) {
|
|
303
|
+
delayDurationToUse = 0
|
|
304
|
+
} else {
|
|
305
|
+
delayDurationToUse =
|
|
306
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
307
|
+
}
|
|
308
|
+
|
|
274
309
|
// Fallback to old behavior if no provider
|
|
275
|
-
if (!hasProvider) {
|
|
310
|
+
if (!hasProvider || showUiLabels) {
|
|
276
311
|
return (
|
|
277
|
-
<_Tooltip.Root
|
|
278
|
-
delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
|
|
279
|
-
disableHoverableContent
|
|
280
|
-
>
|
|
312
|
+
<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent={!showUiLabels}>
|
|
281
313
|
<_Tooltip.Trigger asChild ref={ref}>
|
|
282
314
|
{children}
|
|
283
315
|
</_Tooltip.Trigger>
|
|
@@ -306,13 +338,15 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
306
338
|
content,
|
|
307
339
|
event.currentTarget as HTMLElement,
|
|
308
340
|
sideToUse,
|
|
309
|
-
sideOffset
|
|
341
|
+
sideOffset,
|
|
342
|
+
showOnMobile,
|
|
343
|
+
delayDurationToUse
|
|
310
344
|
)
|
|
311
345
|
}
|
|
312
346
|
|
|
313
347
|
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
|
314
348
|
child.props.onMouseLeave?.(event)
|
|
315
|
-
tooltipManager.hideTooltip(tooltipId.current)
|
|
349
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
316
350
|
}
|
|
317
351
|
|
|
318
352
|
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
|
@@ -322,13 +356,15 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
322
356
|
content,
|
|
323
357
|
event.currentTarget as HTMLElement,
|
|
324
358
|
sideToUse,
|
|
325
|
-
sideOffset
|
|
359
|
+
sideOffset,
|
|
360
|
+
showOnMobile,
|
|
361
|
+
delayDurationToUse
|
|
326
362
|
)
|
|
327
363
|
}
|
|
328
364
|
|
|
329
365
|
const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
|
|
330
366
|
child.props.onBlur?.(event)
|
|
331
|
-
tooltipManager.hideTooltip(tooltipId.current)
|
|
367
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
332
368
|
}
|
|
333
369
|
|
|
334
370
|
const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
|