tldraw 3.16.0-canary.5170ef6b6e20 → 3.16.0-canary.5462c7eac75a
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 +138 -106
- package/dist-cjs/index.js +25 -14
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -0
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +2 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/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/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/ui/components/A11y.js +1 -1
- package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
- 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/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} +23 -20
- 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 +1 -0
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.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/primitives/TldrawUiContextualToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
- 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 +44 -5
- 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/TldrawUiMenuItem.js +5 -5
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +1 -1
- package/dist-cjs/lib/ui/context/actions.js +13 -8
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- 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 +1 -1
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/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 +138 -106
- package/dist-esm/index.mjs +51 -28
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -0
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +2 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +3 -3
- package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/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/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/ui/components/A11y.mjs +2 -2
- package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
- 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/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} +20 -17
- 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 +1 -0
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.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/primitives/TldrawUiContextualToolbar.mjs +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +1 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +3 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +1 -1
- 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 +45 -5
- 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/TldrawUiMenuItem.mjs +5 -5
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +1 -1
- package/dist-esm/lib/ui/context/actions.mjs +13 -8
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- 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 +1 -1
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/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 +3 -3
- package/src/index.ts +38 -21
- package/src/lib/defaultExternalContentHandlers.ts +14 -0
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +2 -2
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +41 -0
- package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
- package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +1 -0
- package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
- 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/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/ui/components/A11y.tsx +2 -2
- package/src/lib/ui/components/LanguageMenu.tsx +1 -0
- package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -0
- 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 +1 -0
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +1 -0
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiInput.tsx +3 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +5 -1
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +63 -16
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +6 -6
- package/src/lib/ui/context/actions.tsx +20 -8
- 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 +1 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -2
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +26 -2
- 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/test/getCulledShapes.test.tsx +71 -2
- package/tldraw.css +34 -5
- 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/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
|
@@ -4,46 +4,52 @@ import {
|
|
|
4
4
|
SharedStyle,
|
|
5
5
|
StyleProp,
|
|
6
6
|
TLDefaultColorStyle,
|
|
7
|
-
TLDefaultColorTheme,
|
|
8
7
|
useEditor,
|
|
9
8
|
} from '@tldraw/editor'
|
|
10
9
|
import { memo, ReactElement, useMemo, useRef } from 'react'
|
|
10
|
+
import { useDefaultColorTheme } from '../../../shapes/shared/useDefaultColorTheme'
|
|
11
11
|
import { StyleValuesForUi } from '../../../styles'
|
|
12
12
|
import { PORTRAIT_BREAKPOINT } from '../../constants'
|
|
13
13
|
import { useBreakpoint } from '../../context/breakpoints'
|
|
14
14
|
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
|
15
15
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
16
|
-
import { TldrawUiButtonIcon } from '
|
|
17
|
-
import {
|
|
18
|
-
|
|
16
|
+
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
17
|
+
import {
|
|
18
|
+
TldrawUiToolbar,
|
|
19
|
+
TldrawUiToolbarToggleGroup,
|
|
20
|
+
TldrawUiToolbarToggleItem,
|
|
21
|
+
} from '../primitives/TldrawUiToolbar'
|
|
22
|
+
import { TldrawUiGrid, TldrawUiRow } from '../primitives/layout'
|
|
23
|
+
import { useStylePanelContext } from './StylePanelContext'
|
|
24
|
+
import { StylePanelSubheading } from './StylePanelSubheading'
|
|
19
25
|
|
|
20
26
|
/** @public */
|
|
21
|
-
export interface
|
|
27
|
+
export interface StylePanelButtonPickerProps<T extends string> {
|
|
22
28
|
title: string
|
|
23
29
|
uiType: string
|
|
24
30
|
style: StyleProp<T>
|
|
25
31
|
value: SharedStyle<T>
|
|
26
32
|
items: StyleValuesForUi<T>
|
|
27
|
-
|
|
28
|
-
onValueChange(style: StyleProp<T>, value: T): void
|
|
33
|
+
onValueChange?(style: StyleProp<T>, value: T): void
|
|
29
34
|
onHistoryMark?(id: string): void
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
/** @public */
|
|
33
|
-
export const
|
|
34
|
-
props:
|
|
38
|
+
export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T extends string>(
|
|
39
|
+
props: StylePanelButtonPickerProps<T>
|
|
35
40
|
) {
|
|
41
|
+
const ctx = useStylePanelContext()
|
|
42
|
+
|
|
36
43
|
const {
|
|
37
44
|
uiType,
|
|
38
45
|
items,
|
|
39
46
|
title,
|
|
40
47
|
style,
|
|
41
48
|
value,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
onHistoryMark,
|
|
45
|
-
theme,
|
|
49
|
+
onValueChange = ctx.onValueChange,
|
|
50
|
+
onHistoryMark = ctx.onHistoryMark,
|
|
46
51
|
} = props
|
|
52
|
+
const theme = useDefaultColorTheme()
|
|
47
53
|
const editor = useEditor()
|
|
48
54
|
const msg = useTranslation()
|
|
49
55
|
const breakpoint = useBreakpoint()
|
|
@@ -117,43 +123,57 @@ export const TldrawUiButtonPicker = memo(function TldrawUiButtonPicker<T extends
|
|
|
117
123
|
}
|
|
118
124
|
}, [editor, breakpoint, value, onHistoryMark, onValueChange, style])
|
|
119
125
|
|
|
120
|
-
const
|
|
126
|
+
const Layout = items.length > 4 ? TldrawUiGrid : TldrawUiRow
|
|
121
127
|
|
|
122
128
|
return (
|
|
123
|
-
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
129
|
+
<>
|
|
130
|
+
{ctx.showUiLabels && <StylePanelSubheading>{title}</StylePanelSubheading>}
|
|
131
|
+
<TldrawUiToolbar label={title}>
|
|
132
|
+
<TldrawUiToolbarToggleGroup
|
|
133
|
+
data-testid={`style.${uiType}`}
|
|
134
|
+
type="single"
|
|
135
|
+
value={value.type === 'shared' ? value.value : undefined}
|
|
136
|
+
asChild
|
|
137
|
+
>
|
|
138
|
+
<Layout>
|
|
139
|
+
{items.map((item) => {
|
|
140
|
+
const isActive = value.type === 'shared' && value.value === item.value
|
|
141
|
+
const label =
|
|
142
|
+
title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
|
|
143
|
+
return (
|
|
144
|
+
<TldrawUiToolbarToggleItem
|
|
145
|
+
type="icon"
|
|
146
|
+
key={item.value}
|
|
147
|
+
data-id={item.value}
|
|
148
|
+
data-testid={`style.${uiType}.${item.value}`}
|
|
149
|
+
aria-label={label + (isActive ? ` (${msg('style-panel.selected')})` : '')}
|
|
150
|
+
tooltip={
|
|
151
|
+
<>
|
|
152
|
+
<div>{label}</div>
|
|
153
|
+
{isActive ? <div>({msg('style-panel.selected')})</div> : null}
|
|
154
|
+
</>
|
|
155
|
+
}
|
|
156
|
+
value={item.value}
|
|
157
|
+
data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
|
|
158
|
+
data-isactive={isActive}
|
|
159
|
+
title={label}
|
|
160
|
+
style={
|
|
161
|
+
style === (DefaultColorStyle as StyleProp<unknown>)
|
|
162
|
+
? { color: getColorValue(theme, item.value as TLDefaultColorStyle, 'solid') }
|
|
163
|
+
: undefined
|
|
164
|
+
}
|
|
165
|
+
onPointerEnter={handleButtonPointerEnter}
|
|
166
|
+
onPointerDown={handleButtonPointerDown}
|
|
167
|
+
onPointerUp={handleButtonPointerUp}
|
|
168
|
+
onClick={handleButtonClick}
|
|
169
|
+
>
|
|
170
|
+
<TldrawUiButtonIcon icon={item.icon} />
|
|
171
|
+
</TldrawUiToolbarToggleItem>
|
|
172
|
+
)
|
|
173
|
+
})}
|
|
174
|
+
</Layout>
|
|
175
|
+
</TldrawUiToolbarToggleGroup>
|
|
176
|
+
</TldrawUiToolbar>
|
|
177
|
+
</>
|
|
158
178
|
)
|
|
159
|
-
}) as <T extends string>(props:
|
|
179
|
+
}) as <T extends string>(props: StylePanelButtonPickerProps<T>) => ReactElement
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ReadonlySharedStyleMap, StyleProp, useEditor, useValue } from '@tldraw/editor'
|
|
2
|
+
import { createContext, useCallback, useContext } from 'react'
|
|
3
|
+
import { useUiEvents } from '../../context/events'
|
|
4
|
+
|
|
5
|
+
/** @public */
|
|
6
|
+
export interface StylePanelContext {
|
|
7
|
+
styles: ReadonlySharedStyleMap
|
|
8
|
+
showUiLabels: boolean
|
|
9
|
+
onHistoryMark(id: string): void
|
|
10
|
+
onValueChange<T>(style: StyleProp<T>, value: T): void
|
|
11
|
+
}
|
|
12
|
+
const StylePanelContext = createContext<null | StylePanelContext>(null)
|
|
13
|
+
|
|
14
|
+
/** @public */
|
|
15
|
+
export interface StylePanelContextProviderProps {
|
|
16
|
+
children: React.ReactNode
|
|
17
|
+
styles: ReadonlySharedStyleMap
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** @public @react */
|
|
21
|
+
export function StylePanelContextProvider({ children, styles }: StylePanelContextProviderProps) {
|
|
22
|
+
const editor = useEditor()
|
|
23
|
+
const trackEvent = useUiEvents()
|
|
24
|
+
|
|
25
|
+
const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
|
|
26
|
+
const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
|
|
27
|
+
const onValueChange = useCallback(
|
|
28
|
+
function <T>(style: StyleProp<T>, value: T) {
|
|
29
|
+
editor.run(() => {
|
|
30
|
+
if (editor.isIn('select')) {
|
|
31
|
+
editor.setStyleForSelectedShapes(style, value)
|
|
32
|
+
}
|
|
33
|
+
editor.setStyleForNextShapes(style, value)
|
|
34
|
+
editor.updateInstanceState({ isChangingStyle: true })
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string })
|
|
38
|
+
},
|
|
39
|
+
[editor, trackEvent]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<StylePanelContext.Provider
|
|
44
|
+
value={{
|
|
45
|
+
styles: styles,
|
|
46
|
+
showUiLabels,
|
|
47
|
+
onHistoryMark,
|
|
48
|
+
onValueChange,
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
</StylePanelContext.Provider>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** @public */
|
|
57
|
+
export function useStylePanelContext() {
|
|
58
|
+
const context = useContext(StylePanelContext)
|
|
59
|
+
if (!context) {
|
|
60
|
+
throw new Error('useStylePanelContext must be used within a StylePanelContextProvider')
|
|
61
|
+
}
|
|
62
|
+
return context
|
|
63
|
+
}
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
} from '../primitives/TldrawUiPopover'
|
|
12
12
|
import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
13
13
|
import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'
|
|
14
|
+
import { useStylePanelContext } from './StylePanelContext'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
/** @public */
|
|
17
|
+
export interface StylePanelDoubleDropdownPickerProps<T extends string> {
|
|
16
18
|
uiTypeA: string
|
|
17
19
|
uiTypeB: string
|
|
18
20
|
label: TLUiTranslationKey | Exclude<string, TLUiTranslationKey>
|
|
@@ -24,23 +26,27 @@ interface DoubleDropdownPickerProps<T extends string> {
|
|
|
24
26
|
styleB: StyleProp<T>
|
|
25
27
|
valueA: SharedStyle<T>
|
|
26
28
|
valueB: SharedStyle<T>
|
|
27
|
-
onValueChange(style: StyleProp<T>, value: T): void
|
|
29
|
+
onValueChange?(style: StyleProp<T>, value: T): void
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
function DoubleDropdownPickerInner<T extends string>(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
function DoubleDropdownPickerInner<T extends string>(
|
|
33
|
+
props: StylePanelDoubleDropdownPickerProps<T>
|
|
34
|
+
) {
|
|
35
|
+
const ctx = useStylePanelContext()
|
|
36
|
+
const {
|
|
37
|
+
label,
|
|
38
|
+
uiTypeA,
|
|
39
|
+
uiTypeB,
|
|
40
|
+
labelA,
|
|
41
|
+
labelB,
|
|
42
|
+
itemsA,
|
|
43
|
+
itemsB,
|
|
44
|
+
styleA,
|
|
45
|
+
styleB,
|
|
46
|
+
valueA,
|
|
47
|
+
valueB,
|
|
48
|
+
onValueChange = ctx.onValueChange,
|
|
49
|
+
} = props
|
|
44
50
|
const editor = useEditor()
|
|
45
51
|
const msg = useTranslation()
|
|
46
52
|
const [isOpenA, setIsOpenA] = React.useState(false)
|
|
@@ -155,6 +161,9 @@ function DoubleDropdownPickerInner<T extends string>({
|
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
// need to memo like this to get generics
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
/** @public @react */
|
|
165
|
+
export const StylePanelDoubleDropdownPicker = React.memo(DoubleDropdownPickerInner) as <
|
|
166
|
+
T extends string,
|
|
167
|
+
>(
|
|
168
|
+
props: StylePanelDoubleDropdownPickerProps<T>
|
|
169
|
+
) => React.JSX.Element
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { SharedStyle, StyleProp, tlmenus, useEditor } from '@tldraw/editor'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { StyleValuesForUi } from '../../../styles'
|
|
4
|
+
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
|
5
|
+
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
6
|
+
import { TLUiIconType } from '../../icon-types'
|
|
7
|
+
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
8
|
+
import { TldrawUiButtonLabel } from '../primitives/Button/TldrawUiButtonLabel'
|
|
9
|
+
import {
|
|
10
|
+
TldrawUiPopover,
|
|
11
|
+
TldrawUiPopoverContent,
|
|
12
|
+
TldrawUiPopoverTrigger,
|
|
13
|
+
} from '../primitives/TldrawUiPopover'
|
|
14
|
+
import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
15
|
+
import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'
|
|
16
|
+
import { useStylePanelContext } from './StylePanelContext'
|
|
17
|
+
|
|
18
|
+
/** @public */
|
|
19
|
+
export interface StylePanelDropdownPickerProps<T extends string> {
|
|
20
|
+
id: string
|
|
21
|
+
label?: TLUiTranslationKey | Exclude<string, TLUiTranslationKey>
|
|
22
|
+
uiType: string
|
|
23
|
+
stylePanelType: string
|
|
24
|
+
style: StyleProp<T>
|
|
25
|
+
value: SharedStyle<T>
|
|
26
|
+
items: StyleValuesForUi<T>
|
|
27
|
+
type: 'icon' | 'tool' | 'menu'
|
|
28
|
+
onValueChange?(style: StyleProp<T>, value: T): void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function DropdownPickerInner<T extends string>(props: StylePanelDropdownPickerProps<T>) {
|
|
32
|
+
const ctx = useStylePanelContext()
|
|
33
|
+
const {
|
|
34
|
+
id,
|
|
35
|
+
label,
|
|
36
|
+
uiType,
|
|
37
|
+
stylePanelType,
|
|
38
|
+
style,
|
|
39
|
+
items,
|
|
40
|
+
type,
|
|
41
|
+
value,
|
|
42
|
+
onValueChange = ctx.onValueChange,
|
|
43
|
+
} = props
|
|
44
|
+
const msg = useTranslation()
|
|
45
|
+
const editor = useEditor()
|
|
46
|
+
const [isOpen, setIsOpen] = React.useState(false)
|
|
47
|
+
|
|
48
|
+
const icon = React.useMemo(
|
|
49
|
+
() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,
|
|
50
|
+
[items, value]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
const stylePanelName = msg(`style-panel.${stylePanelType}` as TLUiTranslationKey)
|
|
54
|
+
|
|
55
|
+
const titleStr =
|
|
56
|
+
value.type === 'mixed'
|
|
57
|
+
? msg('style-panel.mixed')
|
|
58
|
+
: stylePanelName + ' — ' + msg(`${uiType}-style.${value.value}` as TLUiTranslationKey)
|
|
59
|
+
const labelStr = label ? msg(label) : ''
|
|
60
|
+
|
|
61
|
+
const popoverId = `style panel ${id}`
|
|
62
|
+
return (
|
|
63
|
+
<TldrawUiToolbar label={stylePanelName}>
|
|
64
|
+
<TldrawUiPopover
|
|
65
|
+
id={popoverId}
|
|
66
|
+
open={isOpen}
|
|
67
|
+
onOpenChange={setIsOpen}
|
|
68
|
+
className="tlui-style-panel__dropdown-picker"
|
|
69
|
+
>
|
|
70
|
+
<TldrawUiPopoverTrigger>
|
|
71
|
+
<TldrawUiToolbarButton
|
|
72
|
+
type={type}
|
|
73
|
+
data-testid={`style.${uiType}`}
|
|
74
|
+
data-direction="left"
|
|
75
|
+
title={titleStr}
|
|
76
|
+
>
|
|
77
|
+
{labelStr && <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>}
|
|
78
|
+
<TldrawUiButtonIcon icon={(icon as TLUiIconType) ?? 'mixed'} />
|
|
79
|
+
</TldrawUiToolbarButton>
|
|
80
|
+
</TldrawUiPopoverTrigger>
|
|
81
|
+
<TldrawUiPopoverContent side="left" align="center">
|
|
82
|
+
<TldrawUiToolbar orientation={items.length > 4 ? 'grid' : 'horizontal'} label={labelStr}>
|
|
83
|
+
<TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
|
|
84
|
+
{items.map((item) => {
|
|
85
|
+
return (
|
|
86
|
+
<TldrawUiToolbarButton
|
|
87
|
+
key={item.value}
|
|
88
|
+
type="icon"
|
|
89
|
+
data-testid={`style.${uiType}.${item.value}`}
|
|
90
|
+
title={
|
|
91
|
+
stylePanelName +
|
|
92
|
+
' — ' +
|
|
93
|
+
msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
|
|
94
|
+
}
|
|
95
|
+
isActive={icon === item.icon}
|
|
96
|
+
onClick={() => {
|
|
97
|
+
ctx.onHistoryMark('select style dropdown item')
|
|
98
|
+
onValueChange(style, item.value)
|
|
99
|
+
tlmenus.deleteOpenMenu(popoverId, editor.contextId)
|
|
100
|
+
setIsOpen(false)
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
<TldrawUiButtonIcon icon={item.icon} />
|
|
104
|
+
</TldrawUiToolbarButton>
|
|
105
|
+
)
|
|
106
|
+
})}
|
|
107
|
+
</TldrawUiMenuContextProvider>
|
|
108
|
+
</TldrawUiToolbar>
|
|
109
|
+
</TldrawUiPopoverContent>
|
|
110
|
+
</TldrawUiPopover>
|
|
111
|
+
</TldrawUiToolbar>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// need to export like this to get generics
|
|
116
|
+
/** @public @react */
|
|
117
|
+
export const StylePanelDropdownPicker = React.memo(DropdownPickerInner) as <T extends string>(
|
|
118
|
+
props: StylePanelDropdownPickerProps<T>
|
|
119
|
+
) => React.JSX.Element
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** @public */
|
|
2
|
+
export interface StylePanelSubheadingProps {
|
|
3
|
+
children: React.ReactNode
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** @public @react */
|
|
7
|
+
export function StylePanelSubheading({ children }: StylePanelSubheadingProps) {
|
|
8
|
+
return <h3 className="tlui-style-panel__subheading">{children}</h3>
|
|
9
|
+
}
|
|
@@ -70,6 +70,7 @@ export function AltTextEditor({ shapeId, onClose, source }: AltTextEditorProps)
|
|
|
70
70
|
data-testid="media-toolbar.alt-text-input"
|
|
71
71
|
value={altText}
|
|
72
72
|
placeholder={msg('tool.media-alt-text-desc')}
|
|
73
|
+
aria-label={msg('tool.media-alt-text-desc')}
|
|
73
74
|
onValueChange={handleValueChange}
|
|
74
75
|
onComplete={handleComplete}
|
|
75
76
|
onCancel={handleAltTextCancel}
|
|
@@ -75,6 +75,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
75
75
|
onComplete={handleLinkComplete}
|
|
76
76
|
onCancel={handleLinkCancel}
|
|
77
77
|
placeholder="example.com"
|
|
78
|
+
aria-label="example.com"
|
|
78
79
|
/>
|
|
79
80
|
<TldrawUiToolbarButton
|
|
80
81
|
className="tlui-rich-text__toolbar-link-visit"
|
|
@@ -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,7 +170,7 @@ 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
175
|
<TldrawUiToolbar
|
|
176
176
|
orientation="horizontal"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
|
@@ -118,7 +118,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
118
118
|
// `onChange` with a duplicated text value.
|
|
119
119
|
if (isComposing.current) return
|
|
120
120
|
e.currentTarget.blur()
|
|
121
|
-
|
|
121
|
+
e.stopPropagation()
|
|
122
122
|
onComplete?.(e.currentTarget.value)
|
|
123
123
|
break
|
|
124
124
|
}
|
|
@@ -126,7 +126,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
|
|
|
126
126
|
e.currentTarget.value = rInitialValue.current
|
|
127
127
|
onCancel?.(e.currentTarget.value)
|
|
128
128
|
e.currentTarget.blur()
|
|
129
|
-
|
|
129
|
+
e.stopPropagation()
|
|
130
130
|
break
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -13,7 +13,7 @@ export interface TLUiSliderProps {
|
|
|
13
13
|
label: string
|
|
14
14
|
title: string
|
|
15
15
|
onValueChange(value: number): void
|
|
16
|
-
onHistoryMark(id: string): void
|
|
16
|
+
onHistoryMark?(id: string): void
|
|
17
17
|
'data-testid'?: string
|
|
18
18
|
ariaValueModifier?: number
|
|
19
19
|
}
|
|
@@ -53,7 +53,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
|
|
|
53
53
|
|
|
54
54
|
const handlePointerDown = useCallback(() => {
|
|
55
55
|
tooltipManager.hideAllTooltips()
|
|
56
|
-
onHistoryMark('click slider')
|
|
56
|
+
onHistoryMark?.('click slider')
|
|
57
57
|
}, [onHistoryMark])
|
|
58
58
|
|
|
59
59
|
// N.B. This is a bit silly. The Radix slider auto-focuses which
|
|
@@ -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 */
|
|
@@ -6,6 +6,7 @@ import React, {
|
|
|
6
6
|
ReactNode,
|
|
7
7
|
useContext,
|
|
8
8
|
useEffect,
|
|
9
|
+
useLayoutEffect,
|
|
9
10
|
useRef,
|
|
10
11
|
useState,
|
|
11
12
|
} from 'react'
|
|
@@ -24,18 +25,20 @@ export interface TldrawUiTooltipProps {
|
|
|
24
25
|
delayDuration?: number
|
|
25
26
|
}
|
|
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
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
// Singleton tooltip manager
|
|
28
39
|
class TooltipManager {
|
|
29
40
|
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
|
|
38
|
-
} | null>('current tooltip', null)
|
|
41
|
+
private currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)
|
|
39
42
|
private destroyTimeoutId: number | null = null
|
|
40
43
|
|
|
41
44
|
static getInstance(): TooltipManager {
|
|
@@ -72,6 +75,15 @@ class TooltipManager {
|
|
|
72
75
|
})
|
|
73
76
|
}
|
|
74
77
|
|
|
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
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
|
|
76
88
|
const hide = () => {
|
|
77
89
|
// Only hide if this is the current tooltip
|
|
@@ -142,6 +154,7 @@ function TooltipSingleton() {
|
|
|
142
154
|
const [isOpen, setIsOpen] = useState(false)
|
|
143
155
|
const triggerRef = useRef<HTMLDivElement>(null)
|
|
144
156
|
const isFirstShowRef = useRef(true)
|
|
157
|
+
const editor = useMaybeEditor()
|
|
145
158
|
|
|
146
159
|
const currentTooltip = useValue(
|
|
147
160
|
'current tooltip',
|
|
@@ -149,6 +162,28 @@ function TooltipSingleton() {
|
|
|
149
162
|
[]
|
|
150
163
|
)
|
|
151
164
|
|
|
165
|
+
const cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])
|
|
166
|
+
|
|
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])
|
|
173
|
+
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
176
|
+
if (event.key === 'Escape' && currentTooltip) {
|
|
177
|
+
tooltipManager.hideTooltip(editor, currentTooltip.id)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
182
|
+
return () => {
|
|
183
|
+
document.removeEventListener('keydown', handleKeyDown)
|
|
184
|
+
}
|
|
185
|
+
}, [editor, currentTooltip])
|
|
186
|
+
|
|
152
187
|
// Update open state and trigger position
|
|
153
188
|
useEffect(() => {
|
|
154
189
|
let timer: ReturnType<typeof setTimeout> | null = null
|
|
@@ -231,12 +266,11 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
231
266
|
const editor = useMaybeEditor()
|
|
232
267
|
const tooltipId = useRef<string>(uniqueId())
|
|
233
268
|
const hasProvider = useContext(TooltipSingletonContext)
|
|
269
|
+
const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
|
|
234
270
|
|
|
235
271
|
const orientationCtx = useTldrawUiOrientation()
|
|
236
272
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
237
273
|
|
|
238
|
-
const camera = useValue('camera', () => editor?.getCamera(), [])
|
|
239
|
-
|
|
240
274
|
useEffect(() => {
|
|
241
275
|
const currentTooltipId = tooltipId.current
|
|
242
276
|
return () => {
|
|
@@ -246,17 +280,30 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
246
280
|
}
|
|
247
281
|
}, [editor, hasProvider])
|
|
248
282
|
|
|
249
|
-
|
|
250
|
-
tooltipManager.
|
|
251
|
-
|
|
283
|
+
useLayoutEffect(() => {
|
|
284
|
+
if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
|
|
285
|
+
tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
|
|
286
|
+
...tooltip,
|
|
287
|
+
content,
|
|
288
|
+
side: sideToUse,
|
|
289
|
+
sideOffset,
|
|
290
|
+
showOnMobile,
|
|
291
|
+
}))
|
|
292
|
+
}
|
|
293
|
+
}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
|
|
252
294
|
|
|
253
295
|
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
254
296
|
if (disabled || !content) {
|
|
255
297
|
return <>{children}</>
|
|
256
298
|
}
|
|
257
299
|
|
|
258
|
-
|
|
259
|
-
|
|
300
|
+
let delayDurationToUse
|
|
301
|
+
if (showUiLabels) {
|
|
302
|
+
delayDurationToUse = 0
|
|
303
|
+
} else {
|
|
304
|
+
delayDurationToUse =
|
|
305
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
306
|
+
}
|
|
260
307
|
|
|
261
308
|
// Fallback to old behavior if no provider
|
|
262
309
|
if (!hasProvider) {
|