tldraw 3.16.0-canary.fa3749606e52 → 3.16.0-next.282b7be564ae
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 +100 -5
- package/dist-cjs/index.js +13 -1
- package/dist-cjs/index.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/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -12
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
- package/dist-cjs/lib/ui/TldrawUi.js +14 -0
- package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.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 +5 -3
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +2 -0
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +171 -140
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +6 -0
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +5 -16
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +30 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +268 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +11 -26
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +15 -0
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +21 -3
- 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 +3 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.d.mts +100 -5
- package/dist-esm/index.mjs +23 -1
- package/dist-esm/index.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/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
- package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.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 +6 -3
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +3 -1
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +171 -140
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +6 -6
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +30 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +245 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +11 -26
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +15 -0
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +22 -3
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +3 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +18 -0
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- package/src/lib/shapes/arrow/arrowTargetState.ts +2 -1
- package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
- package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
- package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
- package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
- package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
- package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
- package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
- package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
- package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
- package/src/lib/ui/TldrawUi.tsx +17 -2
- package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
- package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
- package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
- package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
- package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
- package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
- package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +3 -1
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +146 -107
- package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
- package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +14 -11
- package/src/lib/ui/components/menu-items.tsx +8 -0
- package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +40 -37
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
- package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +51 -12
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +327 -0
- package/src/lib/ui/components/primitives/layout.tsx +107 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +15 -25
- package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
- package/src/lib/ui/context/actions.tsx +15 -0
- package/src/lib/ui/context/events.tsx +1 -0
- package/src/lib/ui/hooks/useTools.tsx +25 -3
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +3 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +3 -0
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +406 -292
- package/src/test/arrows-megabus.test.tsx +12 -6
- package/src/test/inner-outer-margin.test.ts +315 -0
- package/tldraw.css +699 -580
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import classnames from 'classnames'
|
|
2
2
|
import { Toolbar as _Toolbar } from 'radix-ui'
|
|
3
3
|
import React from 'react'
|
|
4
|
+
import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow } from './layout'
|
|
5
|
+
import { TldrawUiTooltip } from './TldrawUiTooltip'
|
|
4
6
|
|
|
5
7
|
/** @public */
|
|
6
8
|
export interface TLUiToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
@@ -8,20 +10,42 @@ export interface TLUiToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
8
10
|
className?: string
|
|
9
11
|
dir?: 'ltr' | 'rtl'
|
|
10
12
|
label: string
|
|
13
|
+
orientation?: 'horizontal' | 'vertical' | 'grid'
|
|
14
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const LayoutByOrientation = {
|
|
18
|
+
horizontal: TldrawUiRow,
|
|
19
|
+
vertical: TldrawUiColumn,
|
|
20
|
+
grid: TldrawUiGrid,
|
|
11
21
|
}
|
|
12
22
|
|
|
13
23
|
/** @public @react */
|
|
14
24
|
export const TldrawUiToolbar = React.forwardRef<HTMLDivElement, TLUiToolbarProps>(
|
|
15
|
-
(
|
|
25
|
+
(
|
|
26
|
+
{
|
|
27
|
+
children,
|
|
28
|
+
className,
|
|
29
|
+
label,
|
|
30
|
+
orientation = 'horizontal',
|
|
31
|
+
tooltipSide,
|
|
32
|
+
...props
|
|
33
|
+
}: TLUiToolbarProps,
|
|
34
|
+
ref
|
|
35
|
+
) => {
|
|
36
|
+
const Layout = LayoutByOrientation[orientation]
|
|
16
37
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
<Layout asChild tooltipSide={tooltipSide}>
|
|
39
|
+
<_Toolbar.Root
|
|
40
|
+
ref={ref}
|
|
41
|
+
{...props}
|
|
42
|
+
className={classnames('tlui-toolbar', className)}
|
|
43
|
+
aria-label={label}
|
|
44
|
+
orientation={orientation === 'grid' ? 'horizontal' : orientation}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</_Toolbar.Root>
|
|
48
|
+
</Layout>
|
|
25
49
|
)
|
|
26
50
|
}
|
|
27
51
|
)
|
|
@@ -34,23 +58,30 @@ export interface TLUiToolbarButtonProps extends React.HTMLAttributes<HTMLButtonE
|
|
|
34
58
|
disabled?: boolean
|
|
35
59
|
isActive?: boolean
|
|
36
60
|
type: 'icon' | 'tool' | 'menu'
|
|
61
|
+
tooltip?: string
|
|
37
62
|
}
|
|
38
63
|
|
|
39
64
|
/** @public @react */
|
|
40
65
|
export const TldrawUiToolbarButton = React.forwardRef<HTMLButtonElement, TLUiToolbarButtonProps>(
|
|
41
|
-
({ asChild, children, type, isActive, ...props }: TLUiToolbarButtonProps, ref) => {
|
|
42
|
-
|
|
66
|
+
({ asChild, children, type, isActive, tooltip, ...props }: TLUiToolbarButtonProps, ref) => {
|
|
67
|
+
const button = (
|
|
43
68
|
<_Toolbar.Button
|
|
44
69
|
ref={ref}
|
|
45
70
|
asChild={asChild}
|
|
46
71
|
draggable={false}
|
|
47
72
|
data-isactive={isActive}
|
|
48
73
|
{...props}
|
|
74
|
+
// The tooltip takes care of this.
|
|
75
|
+
title={undefined}
|
|
49
76
|
className={classnames('tlui-button', `tlui-button__${type}`, props.className)}
|
|
50
77
|
>
|
|
51
78
|
{children}
|
|
52
79
|
</_Toolbar.Button>
|
|
53
80
|
)
|
|
81
|
+
|
|
82
|
+
const tooltipContent = tooltip || props.title
|
|
83
|
+
|
|
84
|
+
return <TldrawUiTooltip content={tooltipContent}>{button}</TldrawUiTooltip>
|
|
54
85
|
}
|
|
55
86
|
)
|
|
56
87
|
|
|
@@ -93,6 +124,7 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes<HTMLBut
|
|
|
93
124
|
className?: string
|
|
94
125
|
type: 'icon' | 'tool'
|
|
95
126
|
value: string
|
|
127
|
+
tooltip?: string
|
|
96
128
|
}
|
|
97
129
|
|
|
98
130
|
/** @public @react */
|
|
@@ -101,11 +133,14 @@ export const TldrawUiToolbarToggleItem = ({
|
|
|
101
133
|
className,
|
|
102
134
|
type,
|
|
103
135
|
value,
|
|
136
|
+
tooltip,
|
|
104
137
|
...props
|
|
105
138
|
}: TLUiToolbarToggleItemProps) => {
|
|
106
|
-
|
|
139
|
+
const toggleItem = (
|
|
107
140
|
<_Toolbar.ToggleItem
|
|
108
141
|
{...props}
|
|
142
|
+
// The tooltip takes care of this.
|
|
143
|
+
title={undefined}
|
|
109
144
|
className={classnames(
|
|
110
145
|
'tlui-button',
|
|
111
146
|
`tlui-button__${type}`,
|
|
@@ -117,4 +152,8 @@ export const TldrawUiToolbarToggleItem = ({
|
|
|
117
152
|
{children}
|
|
118
153
|
</_Toolbar.ToggleItem>
|
|
119
154
|
)
|
|
155
|
+
|
|
156
|
+
const tooltipContent = tooltip || props.title
|
|
157
|
+
|
|
158
|
+
return <TldrawUiTooltip content={tooltipContent}>{toggleItem}</TldrawUiTooltip>
|
|
120
159
|
}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'
|
|
2
|
+
import { Tooltip as _Tooltip } from 'radix-ui'
|
|
3
|
+
import React, {
|
|
4
|
+
createContext,
|
|
5
|
+
forwardRef,
|
|
6
|
+
ReactNode,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
11
|
+
} from 'react'
|
|
12
|
+
import { useTldrawUiOrientation } from './layout'
|
|
13
|
+
|
|
14
|
+
const DEFAULT_TOOLTIP_DELAY_MS = 700
|
|
15
|
+
|
|
16
|
+
/** @public */
|
|
17
|
+
export interface TldrawUiTooltipProps {
|
|
18
|
+
children: React.ReactNode
|
|
19
|
+
content?: string | React.ReactNode
|
|
20
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
21
|
+
sideOffset?: number
|
|
22
|
+
disabled?: boolean
|
|
23
|
+
showOnMobile?: boolean
|
|
24
|
+
delayDuration?: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Singleton tooltip manager
|
|
28
|
+
class TooltipManager {
|
|
29
|
+
private static instance: TooltipManager | null = null
|
|
30
|
+
private currentTooltip = atom<{
|
|
31
|
+
id: string
|
|
32
|
+
content: ReactNode
|
|
33
|
+
side: 'top' | 'right' | 'bottom' | 'left'
|
|
34
|
+
sideOffset: number
|
|
35
|
+
showOnMobile: boolean
|
|
36
|
+
targetElement: HTMLElement
|
|
37
|
+
delayDuration: number | undefined
|
|
38
|
+
} | null>('current tooltip', null)
|
|
39
|
+
private destroyTimeoutId: number | null = null
|
|
40
|
+
|
|
41
|
+
static getInstance(): TooltipManager {
|
|
42
|
+
if (!TooltipManager.instance) {
|
|
43
|
+
TooltipManager.instance = new TooltipManager()
|
|
44
|
+
}
|
|
45
|
+
return TooltipManager.instance
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
showTooltip(
|
|
49
|
+
tooltipId: string,
|
|
50
|
+
content: string | React.ReactNode,
|
|
51
|
+
targetElement: HTMLElement,
|
|
52
|
+
side: 'top' | 'right' | 'bottom' | 'left',
|
|
53
|
+
sideOffset: number,
|
|
54
|
+
showOnMobile: boolean,
|
|
55
|
+
delayDuration: number | undefined
|
|
56
|
+
) {
|
|
57
|
+
// Clear any existing destroy timeout
|
|
58
|
+
if (this.destroyTimeoutId) {
|
|
59
|
+
clearTimeout(this.destroyTimeoutId)
|
|
60
|
+
this.destroyTimeoutId = null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Update current tooltip
|
|
64
|
+
this.currentTooltip.set({
|
|
65
|
+
id: tooltipId,
|
|
66
|
+
content,
|
|
67
|
+
side,
|
|
68
|
+
sideOffset,
|
|
69
|
+
showOnMobile,
|
|
70
|
+
targetElement,
|
|
71
|
+
delayDuration,
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
|
|
76
|
+
const hide = () => {
|
|
77
|
+
// Only hide if this is the current tooltip
|
|
78
|
+
if (this.currentTooltip.get()?.id === tooltipId) {
|
|
79
|
+
this.currentTooltip.set(null)
|
|
80
|
+
this.destroyTimeoutId = null
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (editor && !instant) {
|
|
85
|
+
// Start destroy timeout (1 second)
|
|
86
|
+
this.destroyTimeoutId = editor.timers.setTimeout(hide, 300)
|
|
87
|
+
} else {
|
|
88
|
+
hide()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
hideAllTooltips() {
|
|
93
|
+
this.currentTooltip.set(null)
|
|
94
|
+
this.destroyTimeoutId = null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getCurrentTooltipData() {
|
|
98
|
+
const currentTooltip = this.currentTooltip.get()
|
|
99
|
+
if (!currentTooltip) return null
|
|
100
|
+
if (!this.supportsHover() && !currentTooltip.showOnMobile) return null
|
|
101
|
+
return currentTooltip
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private supportsHoverAtom: Atom<boolean> | null = null
|
|
105
|
+
supportsHover() {
|
|
106
|
+
if (!this.supportsHoverAtom) {
|
|
107
|
+
const mediaQuery = window.matchMedia('(hover: hover)')
|
|
108
|
+
const supportsHover = atom('has hover', mediaQuery.matches)
|
|
109
|
+
this.supportsHoverAtom = supportsHover
|
|
110
|
+
mediaQuery.addEventListener('change', (e) => {
|
|
111
|
+
supportsHover.set(e.matches)
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
return this.supportsHoverAtom.get()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export const tooltipManager = TooltipManager.getInstance()
|
|
119
|
+
|
|
120
|
+
// Context for the tooltip singleton
|
|
121
|
+
const TooltipSingletonContext = createContext<boolean>(false)
|
|
122
|
+
|
|
123
|
+
/** @public */
|
|
124
|
+
export interface TldrawUiTooltipProviderProps {
|
|
125
|
+
children: React.ReactNode
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @public @react */
|
|
129
|
+
export function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderProps) {
|
|
130
|
+
return (
|
|
131
|
+
<_Tooltip.Provider skipDelayDuration={700}>
|
|
132
|
+
<TooltipSingletonContext.Provider value={true}>
|
|
133
|
+
{children}
|
|
134
|
+
<TooltipSingleton />
|
|
135
|
+
</TooltipSingletonContext.Provider>
|
|
136
|
+
</_Tooltip.Provider>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// The singleton tooltip component that renders once
|
|
141
|
+
function TooltipSingleton() {
|
|
142
|
+
const editor = useMaybeEditor()
|
|
143
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
144
|
+
const triggerRef = useRef<HTMLDivElement>(null)
|
|
145
|
+
const isFirstShowRef = useRef(true)
|
|
146
|
+
const showTimeoutRef = useRef<number | null>(null)
|
|
147
|
+
|
|
148
|
+
const currentTooltip = useValue(
|
|
149
|
+
'current tooltip',
|
|
150
|
+
() => tooltipManager.getCurrentTooltipData(),
|
|
151
|
+
[]
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
// Update open state and trigger position
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
// Clear any existing show timeout
|
|
157
|
+
if (showTimeoutRef.current) {
|
|
158
|
+
clearTimeout(showTimeoutRef.current)
|
|
159
|
+
showTimeoutRef.current = null
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (currentTooltip && triggerRef.current) {
|
|
163
|
+
// Position the invisible trigger element over the active element
|
|
164
|
+
const activeRect = currentTooltip.targetElement.getBoundingClientRect()
|
|
165
|
+
const trigger = triggerRef.current
|
|
166
|
+
|
|
167
|
+
trigger.style.position = 'fixed'
|
|
168
|
+
trigger.style.left = `${activeRect.left}px`
|
|
169
|
+
trigger.style.top = `${activeRect.top}px`
|
|
170
|
+
trigger.style.width = `${activeRect.width}px`
|
|
171
|
+
trigger.style.height = `${activeRect.height}px`
|
|
172
|
+
trigger.style.pointerEvents = 'none'
|
|
173
|
+
trigger.style.zIndex = '9999'
|
|
174
|
+
|
|
175
|
+
// Handle delay for first show
|
|
176
|
+
if (isFirstShowRef.current && editor) {
|
|
177
|
+
showTimeoutRef.current = editor.timers.setTimeout(() => {
|
|
178
|
+
setIsOpen(true)
|
|
179
|
+
isFirstShowRef.current = false
|
|
180
|
+
}, currentTooltip.delayDuration ?? editor.options.tooltipDelayMs)
|
|
181
|
+
} else {
|
|
182
|
+
// Subsequent tooltips show immediately
|
|
183
|
+
setIsOpen(true)
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
// Hide tooltip immediately
|
|
187
|
+
setIsOpen(false)
|
|
188
|
+
// Reset first show state after tooltip is hidden
|
|
189
|
+
isFirstShowRef.current = true
|
|
190
|
+
}
|
|
191
|
+
}, [editor, currentTooltip])
|
|
192
|
+
|
|
193
|
+
if (!currentTooltip) {
|
|
194
|
+
return null
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<_Tooltip.Root open={isOpen} delayDuration={0}>
|
|
199
|
+
<_Tooltip.Trigger asChild>
|
|
200
|
+
<div ref={triggerRef} />
|
|
201
|
+
</_Tooltip.Trigger>
|
|
202
|
+
<_Tooltip.Content
|
|
203
|
+
className="tlui-tooltip"
|
|
204
|
+
side={currentTooltip.side}
|
|
205
|
+
sideOffset={currentTooltip.sideOffset}
|
|
206
|
+
avoidCollisions
|
|
207
|
+
collisionPadding={8}
|
|
208
|
+
dir="ltr"
|
|
209
|
+
>
|
|
210
|
+
{currentTooltip.content}
|
|
211
|
+
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
212
|
+
</_Tooltip.Content>
|
|
213
|
+
</_Tooltip.Root>
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** @public @react */
|
|
218
|
+
export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
|
|
219
|
+
(
|
|
220
|
+
{
|
|
221
|
+
children,
|
|
222
|
+
content,
|
|
223
|
+
side,
|
|
224
|
+
sideOffset = 5,
|
|
225
|
+
disabled = false,
|
|
226
|
+
showOnMobile = false,
|
|
227
|
+
delayDuration,
|
|
228
|
+
},
|
|
229
|
+
ref
|
|
230
|
+
) => {
|
|
231
|
+
const editor = useMaybeEditor()
|
|
232
|
+
const tooltipId = useRef<string>(uniqueId())
|
|
233
|
+
const hasProvider = useContext(TooltipSingletonContext)
|
|
234
|
+
|
|
235
|
+
const orientationCtx = useTldrawUiOrientation()
|
|
236
|
+
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
237
|
+
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
const currentTooltipId = tooltipId.current
|
|
240
|
+
return () => {
|
|
241
|
+
if (hasProvider) {
|
|
242
|
+
tooltipManager.hideTooltip(editor, currentTooltipId, true)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, [editor, hasProvider])
|
|
246
|
+
|
|
247
|
+
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
248
|
+
if (disabled || !content) {
|
|
249
|
+
return <>{children}</>
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Fallback to old behavior if no provider
|
|
253
|
+
if (!hasProvider) {
|
|
254
|
+
return (
|
|
255
|
+
<_Tooltip.Root
|
|
256
|
+
delayDuration={
|
|
257
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
258
|
+
}
|
|
259
|
+
disableHoverableContent
|
|
260
|
+
>
|
|
261
|
+
<_Tooltip.Trigger asChild ref={ref}>
|
|
262
|
+
{children}
|
|
263
|
+
</_Tooltip.Trigger>
|
|
264
|
+
<_Tooltip.Content
|
|
265
|
+
className="tlui-tooltip"
|
|
266
|
+
side={sideToUse}
|
|
267
|
+
sideOffset={sideOffset}
|
|
268
|
+
avoidCollisions
|
|
269
|
+
collisionPadding={8}
|
|
270
|
+
dir="ltr"
|
|
271
|
+
>
|
|
272
|
+
{content}
|
|
273
|
+
<_Tooltip.Arrow className="tlui-tooltip__arrow" />
|
|
274
|
+
</_Tooltip.Content>
|
|
275
|
+
</_Tooltip.Root>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const child = React.Children.only(children)
|
|
280
|
+
assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
|
|
281
|
+
|
|
282
|
+
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
|
|
283
|
+
child.props.onMouseEnter?.(event)
|
|
284
|
+
tooltipManager.showTooltip(
|
|
285
|
+
tooltipId.current,
|
|
286
|
+
content,
|
|
287
|
+
event.currentTarget as HTMLElement,
|
|
288
|
+
sideToUse,
|
|
289
|
+
sideOffset,
|
|
290
|
+
showOnMobile,
|
|
291
|
+
delayDuration
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
|
|
296
|
+
child.props.onMouseLeave?.(event)
|
|
297
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
|
|
301
|
+
child.props.onFocus?.(event)
|
|
302
|
+
tooltipManager.showTooltip(
|
|
303
|
+
tooltipId.current,
|
|
304
|
+
content,
|
|
305
|
+
event.currentTarget as HTMLElement,
|
|
306
|
+
sideToUse,
|
|
307
|
+
sideOffset,
|
|
308
|
+
showOnMobile,
|
|
309
|
+
delayDuration
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
|
|
314
|
+
child.props.onBlur?.(event)
|
|
315
|
+
tooltipManager.hideTooltip(editor, tooltipId.current)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
|
|
319
|
+
onMouseEnter: handleMouseEnter,
|
|
320
|
+
onMouseLeave: handleMouseLeave,
|
|
321
|
+
onFocus: handleFocus,
|
|
322
|
+
onBlur: handleBlur,
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
return childrenWithHandlers
|
|
326
|
+
}
|
|
327
|
+
)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import classNames from 'classnames'
|
|
2
|
+
import { Slot } from 'radix-ui'
|
|
3
|
+
import { HTMLAttributes, ReactNode, createContext, forwardRef, useContext } from 'react'
|
|
4
|
+
|
|
5
|
+
/** @public */
|
|
6
|
+
export interface TldrawUiOrientationContext {
|
|
7
|
+
orientation: 'horizontal' | 'vertical'
|
|
8
|
+
tooltipSide: 'top' | 'right' | 'bottom' | 'left'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const TldrawUiOrientationContext = createContext<TldrawUiOrientationContext>({
|
|
12
|
+
orientation: 'horizontal',
|
|
13
|
+
tooltipSide: 'bottom',
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
/** @public */
|
|
17
|
+
export interface TldrawUiOrientationProviderProps {
|
|
18
|
+
children: ReactNode
|
|
19
|
+
orientation: 'horizontal' | 'vertical'
|
|
20
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
21
|
+
}
|
|
22
|
+
/** @public @react */
|
|
23
|
+
export function TldrawUiOrientationProvider({
|
|
24
|
+
children,
|
|
25
|
+
orientation,
|
|
26
|
+
tooltipSide,
|
|
27
|
+
}: TldrawUiOrientationProviderProps) {
|
|
28
|
+
const prevContext = useTldrawUiOrientation()
|
|
29
|
+
// generally, we want tooltip side to cascade down through the layout - apart from when the
|
|
30
|
+
// orientation changes. If the tooltip side is "bottom", and then I include some vertical layout
|
|
31
|
+
// elements, keeping the tooltip side as bottom will cause the tooltip to overlap elements
|
|
32
|
+
// stacked on top of each other. In the absence of a tooltip side, we pick a default side based
|
|
33
|
+
// on the orientation whenever the orientation changes.
|
|
34
|
+
const tooltipSideToUse =
|
|
35
|
+
tooltipSide ??
|
|
36
|
+
(orientation === prevContext.orientation
|
|
37
|
+
? prevContext.tooltipSide
|
|
38
|
+
: orientation === 'horizontal'
|
|
39
|
+
? 'bottom'
|
|
40
|
+
: 'right')
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<TldrawUiOrientationContext.Provider value={{ orientation, tooltipSide: tooltipSideToUse }}>
|
|
44
|
+
{children}
|
|
45
|
+
</TldrawUiOrientationContext.Provider>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @public */
|
|
50
|
+
export function useTldrawUiOrientation() {
|
|
51
|
+
return useContext(TldrawUiOrientationContext)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @public */
|
|
55
|
+
export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
56
|
+
children: ReactNode
|
|
57
|
+
tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
|
|
58
|
+
asChild?: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A row, usually of UI controls like buttons, select dropdown, checkboxes, etc.
|
|
63
|
+
*
|
|
64
|
+
* @public @react
|
|
65
|
+
*/
|
|
66
|
+
export const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
67
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
68
|
+
const Component = asChild ? Slot.Root : 'div'
|
|
69
|
+
return (
|
|
70
|
+
<TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
|
|
71
|
+
<Component ref={ref} className={classNames('tlui-row', className)} {...props} />
|
|
72
|
+
</TldrawUiOrientationProvider>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A column, usually of UI controls like buttons, select dropdown, checkboxes, etc.
|
|
79
|
+
*
|
|
80
|
+
* @public @react
|
|
81
|
+
*/
|
|
82
|
+
export const TldrawUiColumn = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
83
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
84
|
+
const Component = asChild ? Slot.Root : 'div'
|
|
85
|
+
return (
|
|
86
|
+
<TldrawUiOrientationProvider orientation="vertical" tooltipSide={tooltipSide}>
|
|
87
|
+
<Component ref={ref} className={classNames('tlui-column', className)} {...props} />
|
|
88
|
+
</TldrawUiOrientationProvider>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* A tight grid 4 elements wide, usually of UI controls like buttons, select dropdown, checkboxes,
|
|
95
|
+
* etc.
|
|
96
|
+
*
|
|
97
|
+
* @public @react */
|
|
98
|
+
export const TldrawUiGrid = forwardRef<HTMLDivElement, TLUiLayoutProps>(
|
|
99
|
+
({ asChild, className, tooltipSide, ...props }, ref) => {
|
|
100
|
+
const Component = asChild ? Slot.Root : 'div'
|
|
101
|
+
return (
|
|
102
|
+
<TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
|
|
103
|
+
<Component ref={ref} className={classNames('tlui-grid', className)} {...props} />
|
|
104
|
+
</TldrawUiOrientationProvider>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
)
|
|
@@ -3,6 +3,7 @@ import { ReactNode } from 'react'
|
|
|
3
3
|
import { unwrapLabel } from '../../../context/actions'
|
|
4
4
|
import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
|
|
5
5
|
import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
|
|
6
|
+
import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from '../layout'
|
|
6
7
|
import { TldrawUiDropdownMenuGroup } from '../TldrawUiDropdownMenu'
|
|
7
8
|
import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
|
|
8
9
|
|
|
@@ -19,25 +20,19 @@ export interface TLUiMenuGroupProps<TranslationKey extends string = string> {
|
|
|
19
20
|
|
|
20
21
|
/** @public @react */
|
|
21
22
|
export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGroupProps) {
|
|
22
|
-
const
|
|
23
|
+
const menu = useTldrawUiMenuContext()
|
|
24
|
+
const { orientation } = useTldrawUiOrientation()
|
|
23
25
|
const msg = useTranslation()
|
|
24
|
-
const labelToUse = unwrapLabel(label,
|
|
26
|
+
const labelToUse = unwrapLabel(label, menu.type)
|
|
25
27
|
const labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined
|
|
26
28
|
|
|
27
|
-
switch (
|
|
28
|
-
case 'panel': {
|
|
29
|
-
return (
|
|
30
|
-
<div
|
|
31
|
-
className={classNames('tlui-menu__group', className)}
|
|
32
|
-
data-testid={`${sourceId}-group.${id}`}
|
|
33
|
-
>
|
|
34
|
-
{children}
|
|
35
|
-
</div>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
29
|
+
switch (menu.type) {
|
|
38
30
|
case 'menu': {
|
|
39
31
|
return (
|
|
40
|
-
<TldrawUiDropdownMenuGroup
|
|
32
|
+
<TldrawUiDropdownMenuGroup
|
|
33
|
+
className={className}
|
|
34
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
35
|
+
>
|
|
41
36
|
{children}
|
|
42
37
|
</TldrawUiDropdownMenuGroup>
|
|
43
38
|
)
|
|
@@ -47,7 +42,7 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
47
42
|
<div
|
|
48
43
|
dir="ltr"
|
|
49
44
|
className={classNames('tlui-menu__group', className)}
|
|
50
|
-
data-testid={`${sourceId}-group.${id}`}
|
|
45
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
51
46
|
>
|
|
52
47
|
{children}
|
|
53
48
|
</div>
|
|
@@ -56,12 +51,30 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
|
|
|
56
51
|
case 'keyboard-shortcuts': {
|
|
57
52
|
// todo: if groups need a label, let's give em a label
|
|
58
53
|
return (
|
|
59
|
-
<div className="tlui-shortcuts-dialog__group" data-testid={`${sourceId}-group.${id}`}>
|
|
54
|
+
<div className="tlui-shortcuts-dialog__group" data-testid={`${menu.sourceId}-group.${id}`}>
|
|
60
55
|
<h2 className="tlui-shortcuts-dialog__group__title">{labelStr}</h2>
|
|
61
56
|
<div className="tlui-shortcuts-dialog__group__content">{children}</div>
|
|
62
57
|
</div>
|
|
63
58
|
)
|
|
64
59
|
}
|
|
60
|
+
case 'toolbar': {
|
|
61
|
+
const Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn
|
|
62
|
+
return (
|
|
63
|
+
<Layout className="tlui-main-toolbar__group" data-testid={`${menu.sourceId}-group.${id}`}>
|
|
64
|
+
{children}
|
|
65
|
+
</Layout>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
case 'toolbar-overflow': {
|
|
69
|
+
return (
|
|
70
|
+
<TldrawUiGrid
|
|
71
|
+
className="tlui-main-toolbar__group"
|
|
72
|
+
data-testid={`${menu.sourceId}-group.${id}`}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</TldrawUiGrid>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
65
78
|
default: {
|
|
66
79
|
return children
|
|
67
80
|
}
|