tldraw 3.16.0-canary.c2c4563957ce → 3.16.0-canary.c360426d8b7a
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 +8 -6
- package/dist-cjs/index.js +1 -1
- 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/useEditablePlainText.js +3 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.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/StylePanelButtonPicker.js +11 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +5 -4
- 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 +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +1 -1
- 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 +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +40 -3
- 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 +6 -0
- 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/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-esm/index.d.mts +8 -6
- package/dist-esm/index.mjs +1 -1
- 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/useEditablePlainText.mjs +4 -3
- package/dist-esm/lib/shapes/shared/useEditablePlainText.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/StylePanelButtonPicker.mjs +11 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +5 -4
- 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 +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +1 -1
- 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 +1 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +41 -3
- 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 +6 -0
- 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/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/package.json +3 -3
- 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/useEditablePlainText.ts +5 -3
- 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/StylePanelButtonPicker.tsx +9 -2
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +6 -5
- 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 +2 -2
- package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +2 -1
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +57 -13
- 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 +13 -0
- package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
- 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 +10 -0
- package/src/test/getCulledShapes.test.tsx +71 -2
- package/tldraw.css +18 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TLFrameShape, TLShapeId,
|
|
1
|
+
import { TLFrameShape, TLShapeId, markEventAsHandled, useEditor } from '@tldraw/editor'
|
|
2
2
|
import { forwardRef, useCallback } from 'react'
|
|
3
3
|
import { defaultEmptyAs } from '../FrameShapeUtil'
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ export const FrameLabelInput = forwardRef<
|
|
|
13
13
|
if (e.key === 'Enter' && !e.nativeEvent.isComposing) {
|
|
14
14
|
// need to prevent the enter keydown making it's way up to the Idle state
|
|
15
15
|
// and sending us back into edit mode
|
|
16
|
-
|
|
16
|
+
markEventAsHandled(e)
|
|
17
17
|
e.currentTarget.blur()
|
|
18
18
|
editor.setEditingShape(null)
|
|
19
19
|
}
|
|
@@ -74,7 +74,7 @@ export const FrameLabelInput = forwardRef<
|
|
|
74
74
|
onKeyDown={handleKeyDown}
|
|
75
75
|
onBlur={handleBlur}
|
|
76
76
|
onChange={handleChange}
|
|
77
|
-
onPointerDown={isEditing ?
|
|
77
|
+
onPointerDown={isEditing ? markEventAsHandled : undefined}
|
|
78
78
|
draggable={false}
|
|
79
79
|
/>
|
|
80
80
|
{defaultEmptyAs(name, 'Frame') + String.fromCharCode(8203)}
|
|
@@ -126,6 +126,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
|
|
|
126
126
|
height: unscaledLabelHeight * shape.props.scale,
|
|
127
127
|
isFilled: true,
|
|
128
128
|
isLabel: true,
|
|
129
|
+
excludeFromShapeBounds: true,
|
|
129
130
|
isEmptyLabel: isEmptyRichText(shape.props.richText),
|
|
130
131
|
}),
|
|
131
132
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { markEventAsHandled, useEditor, useValue } from '@tldraw/editor'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import { PointerEventHandler, useCallback } from 'react'
|
|
4
4
|
|
|
@@ -8,9 +8,9 @@ const LINK_ICON =
|
|
|
8
8
|
export function HyperlinkButton({ url }: { url: string }) {
|
|
9
9
|
const editor = useEditor()
|
|
10
10
|
const hideButton = useValue('zoomLevel', () => editor.getZoomLevel() < 0.32, [editor])
|
|
11
|
-
const
|
|
11
|
+
const markAsHandledOnShiftKey = useCallback<PointerEventHandler>(
|
|
12
12
|
(e) => {
|
|
13
|
-
if (!editor.inputs.shiftKey)
|
|
13
|
+
if (!editor.inputs.shiftKey) markEventAsHandled(e)
|
|
14
14
|
},
|
|
15
15
|
[editor]
|
|
16
16
|
)
|
|
@@ -22,8 +22,8 @@ export function HyperlinkButton({ url }: { url: string }) {
|
|
|
22
22
|
href={url}
|
|
23
23
|
target="_blank"
|
|
24
24
|
rel="noopener noreferrer"
|
|
25
|
-
onPointerDown={
|
|
26
|
-
onPointerUp={
|
|
25
|
+
onPointerDown={markAsHandledOnShiftKey}
|
|
26
|
+
onPointerUp={markAsHandledOnShiftKey}
|
|
27
27
|
title={url}
|
|
28
28
|
draggable={false}
|
|
29
29
|
>
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
TLShapeId,
|
|
4
4
|
TLUnknownShape,
|
|
5
5
|
getPointerInfo,
|
|
6
|
+
markEventAsHandled,
|
|
6
7
|
noop,
|
|
7
8
|
preventDefault,
|
|
8
|
-
stopEventPropagation,
|
|
9
9
|
tlenv,
|
|
10
10
|
useEditor,
|
|
11
11
|
useValue,
|
|
@@ -136,7 +136,7 @@ export function useEditableTextCommon(shapeId: TLShapeId) {
|
|
|
136
136
|
shape: editor.getShape(shapeId)!,
|
|
137
137
|
})
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
e.stopPropagation() // we need to prevent blurring the input
|
|
140
140
|
},
|
|
141
141
|
[editor, shapeId]
|
|
142
142
|
)
|
|
@@ -157,11 +157,13 @@ export function useEditableTextCommon(shapeId: TLShapeId) {
|
|
|
157
157
|
[editor, shapeId]
|
|
158
158
|
)
|
|
159
159
|
|
|
160
|
+
const handleDoubleClick: (e: React.MouseEvent) => void = markEventAsHandled
|
|
161
|
+
|
|
160
162
|
return {
|
|
161
163
|
handleFocus: noop,
|
|
162
164
|
handleBlur: noop,
|
|
163
165
|
handleInputPointerDown,
|
|
164
|
-
handleDoubleClick
|
|
166
|
+
handleDoubleClick,
|
|
165
167
|
handlePaste,
|
|
166
168
|
isEditing,
|
|
167
169
|
isReadyForEditing,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { markEventAsHandled, preventDefault } from '@tldraw/editor'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { TextAreaProps } from './RichTextArea'
|
|
4
4
|
|
|
@@ -46,8 +46,8 @@ export const PlainTextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps
|
|
|
46
46
|
onChange={onChange}
|
|
47
47
|
onKeyDown={(e) => handleKeyDown(e.nativeEvent)}
|
|
48
48
|
onBlur={handleBlur}
|
|
49
|
-
onTouchEnd={
|
|
50
|
-
onContextMenu={isEditing ?
|
|
49
|
+
onTouchEnd={markEventAsHandled}
|
|
50
|
+
onContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}
|
|
51
51
|
onPointerDown={handleInputPointerDown}
|
|
52
52
|
onPaste={handlePaste}
|
|
53
53
|
onDoubleClick={handleDoubleClick}
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
TLRichText,
|
|
11
11
|
TLShapeId,
|
|
12
12
|
preventDefault,
|
|
13
|
-
stopEventPropagation,
|
|
14
13
|
useEditor,
|
|
15
14
|
useEvent,
|
|
16
15
|
useUniqueSafeId,
|
|
@@ -233,13 +232,13 @@ export const RichTextArea = React.forwardRef<HTMLDivElement, TextAreaProps>(func
|
|
|
233
232
|
tabIndex={-1}
|
|
234
233
|
data-testid="rich-text-area"
|
|
235
234
|
className="tl-rich-text tl-text tl-text-input"
|
|
236
|
-
onContextMenu={isEditing ?
|
|
235
|
+
onContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}
|
|
237
236
|
// N.B. When PointerStateExtension was introduced, this was moved there.
|
|
238
237
|
// However, that caused selecting over list items to break.
|
|
239
238
|
// The handleDOMEvents in TipTap don't seem to support the pointerDownCapture event.
|
|
240
|
-
onPointerDownCapture={
|
|
239
|
+
onPointerDownCapture={(e) => e.stopPropagation()}
|
|
241
240
|
// This onTouchEnd is important for Android to be able to change selection on text.
|
|
242
|
-
onTouchEnd={
|
|
241
|
+
onTouchEnd={(e) => e.stopPropagation()}
|
|
243
242
|
// On FF, there's a behavior where dragging a selection will grab that selection into
|
|
244
243
|
// the drag event. However, once the drag is over, and you select away from the textarea,
|
|
245
244
|
// starting a drag over the textarea will restart a selection drag instead of a shape drag.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
debugFlags,
|
|
3
3
|
Editor,
|
|
4
|
-
|
|
4
|
+
markEventAsHandled,
|
|
5
5
|
TLGeoShape,
|
|
6
6
|
TLShapeId,
|
|
7
7
|
unsafe__withoutCapture,
|
|
@@ -23,7 +23,7 @@ export function SkipToMainContent() {
|
|
|
23
23
|
|
|
24
24
|
const handleNavigateToFirstShape = useCallback(
|
|
25
25
|
(e: MouseEvent | KeyboardEvent) => {
|
|
26
|
-
|
|
26
|
+
markEventAsHandled(e)
|
|
27
27
|
button.current?.blur()
|
|
28
28
|
const shapes = editor.getCurrentPageShapesInReadingOrder()
|
|
29
29
|
if (!shapes.length) return
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PageRecordType,
|
|
3
3
|
TLPageId,
|
|
4
|
+
markEventAsHandled,
|
|
4
5
|
releasePointerCapture,
|
|
5
6
|
setPointerCapture,
|
|
6
|
-
stopEventPropagation,
|
|
7
7
|
tlenv,
|
|
8
8
|
useEditor,
|
|
9
9
|
useValue,
|
|
@@ -451,7 +451,7 @@ export const DefaultPageMenu = memo(function DefaultPageMenu() {
|
|
|
451
451
|
if (e.key === 'Enter') {
|
|
452
452
|
if (page.id === currentPage.id) {
|
|
453
453
|
toggleEditing()
|
|
454
|
-
|
|
454
|
+
markEventAsHandled(e)
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
457
|
}}
|
|
@@ -137,6 +137,7 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
|
|
|
137
137
|
>
|
|
138
138
|
<Layout>
|
|
139
139
|
{items.map((item) => {
|
|
140
|
+
const isActive = value.type === 'shared' && value.value === item.value
|
|
140
141
|
const label =
|
|
141
142
|
title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
|
|
142
143
|
return (
|
|
@@ -145,10 +146,16 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
|
|
|
145
146
|
key={item.value}
|
|
146
147
|
data-id={item.value}
|
|
147
148
|
data-testid={`style.${uiType}.${item.value}`}
|
|
148
|
-
aria-label={label}
|
|
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
|
+
}
|
|
149
156
|
value={item.value}
|
|
150
157
|
data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
|
|
151
|
-
data-isactive={
|
|
158
|
+
data-isactive={isActive}
|
|
152
159
|
title={label}
|
|
153
160
|
style={
|
|
154
161
|
style === (DefaultColorStyle as StyleProp<unknown>)
|
|
@@ -2,9 +2,9 @@ import { preventDefault, TLShape, TLShapeId, useEditor } from '@tldraw/editor'
|
|
|
2
2
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
3
|
import { useUiEvents } from '../../context/events'
|
|
4
4
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
5
|
+
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
5
6
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
6
7
|
import { TldrawUiInput } from '../primitives/TldrawUiInput'
|
|
7
|
-
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
10
|
export interface AltTextEditorProps {
|
|
@@ -70,13 +70,14 @@ 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}
|
|
76
77
|
disabled={isReadonly}
|
|
77
78
|
/>
|
|
78
79
|
{!isReadonly && (
|
|
79
|
-
<
|
|
80
|
+
<TldrawUiButton
|
|
80
81
|
title={msg('tool.media-alt-text-confirm')}
|
|
81
82
|
data-testid="tool.media-alt-text-confirm"
|
|
82
83
|
type="icon"
|
|
@@ -84,7 +85,7 @@ export function AltTextEditor({ shapeId, onClose, source }: AltTextEditorProps)
|
|
|
84
85
|
onClick={handleConfirm}
|
|
85
86
|
>
|
|
86
87
|
<TldrawUiButtonIcon small icon="check" />
|
|
87
|
-
</
|
|
88
|
+
</TldrawUiButton>
|
|
88
89
|
)}
|
|
89
90
|
</>
|
|
90
91
|
)
|
|
@@ -2,9 +2,9 @@ import { preventDefault, TiptapEditor, useEditor } from '@tldraw/editor'
|
|
|
2
2
|
import { useEffect, useRef, useState } from 'react'
|
|
3
3
|
import { useUiEvents } from '../../context/events'
|
|
4
4
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
5
|
+
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
5
6
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
6
7
|
import { TldrawUiInput } from '../primitives/TldrawUiInput'
|
|
7
|
-
import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
10
10
|
export interface LinkEditorProps {
|
|
@@ -75,8 +75,9 @@ 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
|
+
<TldrawUiButton
|
|
80
81
|
className="tlui-rich-text__toolbar-link-visit"
|
|
81
82
|
title={msg('tool.rich-text-link-visit')}
|
|
82
83
|
type="icon"
|
|
@@ -85,8 +86,8 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
85
86
|
disabled={!value}
|
|
86
87
|
>
|
|
87
88
|
<TldrawUiButtonIcon small icon="external-link" />
|
|
88
|
-
</
|
|
89
|
-
<
|
|
89
|
+
</TldrawUiButton>
|
|
90
|
+
<TldrawUiButton
|
|
90
91
|
className="tlui-rich-text__toolbar-link-remove"
|
|
91
92
|
title={msg('tool.rich-text-link-remove')}
|
|
92
93
|
data-testid="rich-text.link-remove"
|
|
@@ -95,7 +96,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
|
|
|
95
96
|
onClick={handleRemoveLink}
|
|
96
97
|
>
|
|
97
98
|
<TldrawUiButtonIcon small icon="trash" />
|
|
98
|
-
</
|
|
99
|
+
</TldrawUiButton>
|
|
99
100
|
</>
|
|
100
101
|
)
|
|
101
102
|
}
|
|
@@ -101,7 +101,7 @@ export function OverflowingToolbar({
|
|
|
101
101
|
items: collectItems(child.children),
|
|
102
102
|
element: child as HTMLElement,
|
|
103
103
|
})
|
|
104
|
-
} else {
|
|
104
|
+
} else if (!child.hasAttribute('data-radix-popper-content-wrapper')) {
|
|
105
105
|
items.push({ type: 'item', element: child as HTMLElement })
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useEditor, useValue } from '@tldraw/editor'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import { PORTRAIT_BREAKPOINT } from '../../constants'
|
|
4
|
+
import { useActions } from '../../context/actions'
|
|
4
5
|
import { useBreakpoint } from '../../context/breakpoints'
|
|
5
6
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
|
7
|
+
import { kbdStr } from '../../kbd-utils'
|
|
6
8
|
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
|
7
9
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
|
8
10
|
import { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'
|
|
@@ -17,6 +19,7 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
|
|
|
17
19
|
const editor = useEditor()
|
|
18
20
|
const breakpoint = useBreakpoint()
|
|
19
21
|
const msg = useTranslation()
|
|
22
|
+
const actions = useActions()
|
|
20
23
|
|
|
21
24
|
const isToolLocked = useValue('is tool locked', () => editor.getInstanceState().isToolLocked, [
|
|
22
25
|
editor,
|
|
@@ -25,11 +28,15 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
|
|
|
25
28
|
|
|
26
29
|
if (!activeToolId || !tool.isLockable) return null
|
|
27
30
|
|
|
31
|
+
const toggleLockAction = actions['toggle-tool-lock']
|
|
32
|
+
const tooltipContent = toggleLockAction?.kbd
|
|
33
|
+
? `${msg('action.toggle-tool-lock')} ${kbdStr(toggleLockAction.kbd)}`
|
|
34
|
+
: msg('action.toggle-tool-lock')
|
|
35
|
+
|
|
28
36
|
return (
|
|
29
|
-
<TldrawUiTooltip content={
|
|
37
|
+
<TldrawUiTooltip content={tooltipContent}>
|
|
30
38
|
<TldrawUiButton
|
|
31
39
|
type="normal"
|
|
32
|
-
title={msg('action.toggle-tool-lock')}
|
|
33
40
|
data-testid="tool-lock"
|
|
34
41
|
className={classNames('tlui-main-toolbar__lock-button', {
|
|
35
42
|
'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
|
|
@@ -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'
|
|
@@ -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}
|
|
@@ -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)}
|
|
@@ -127,7 +128,7 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes<HTMLBut
|
|
|
127
128
|
className?: string
|
|
128
129
|
type: 'icon' | 'tool'
|
|
129
130
|
value: string
|
|
130
|
-
tooltip?:
|
|
131
|
+
tooltip?: React.ReactNode
|
|
131
132
|
}
|
|
132
133
|
|
|
133
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
|
|
@@ -159,6 +171,20 @@ function TooltipSingleton() {
|
|
|
159
171
|
}
|
|
160
172
|
}, [cameraState, isOpen, currentTooltip, editor])
|
|
161
173
|
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
176
|
+
if (event.key === 'Escape' && currentTooltip && isOpen) {
|
|
177
|
+
tooltipManager.hideTooltip(editor, currentTooltip.id)
|
|
178
|
+
event.stopPropagation()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
document.addEventListener('keydown', handleKeyDown, { capture: true })
|
|
183
|
+
return () => {
|
|
184
|
+
document.removeEventListener('keydown', handleKeyDown, { capture: true })
|
|
185
|
+
}
|
|
186
|
+
}, [editor, currentTooltip, isOpen])
|
|
187
|
+
|
|
162
188
|
// Update open state and trigger position
|
|
163
189
|
useEffect(() => {
|
|
164
190
|
let timer: ReturnType<typeof setTimeout> | null = null
|
|
@@ -241,6 +267,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
241
267
|
const editor = useMaybeEditor()
|
|
242
268
|
const tooltipId = useRef<string>(uniqueId())
|
|
243
269
|
const hasProvider = useContext(TooltipSingletonContext)
|
|
270
|
+
const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
|
|
244
271
|
|
|
245
272
|
const orientationCtx = useTldrawUiOrientation()
|
|
246
273
|
const sideToUse = side ?? orientationCtx.tooltipSide
|
|
@@ -254,18 +281,35 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
|
|
|
254
281
|
}
|
|
255
282
|
}, [editor, hasProvider])
|
|
256
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])
|
|
295
|
+
|
|
257
296
|
// Don't show tooltip if disabled, no content, or UI labels are disabled
|
|
258
297
|
if (disabled || !content) {
|
|
259
298
|
return <>{children}</>
|
|
260
299
|
}
|
|
261
300
|
|
|
262
|
-
|
|
263
|
-
|
|
301
|
+
let delayDurationToUse
|
|
302
|
+
if (showUiLabels) {
|
|
303
|
+
delayDurationToUse = 0
|
|
304
|
+
} else {
|
|
305
|
+
delayDurationToUse =
|
|
306
|
+
delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
|
|
307
|
+
}
|
|
264
308
|
|
|
265
309
|
// Fallback to old behavior if no provider
|
|
266
|
-
if (!hasProvider) {
|
|
310
|
+
if (!hasProvider || showUiLabels) {
|
|
267
311
|
return (
|
|
268
|
-
<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>
|
|
312
|
+
<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent={!showUiLabels}>
|
|
269
313
|
<_Tooltip.Trigger asChild ref={ref}>
|
|
270
314
|
{children}
|
|
271
315
|
</_Tooltip.Trigger>
|
|
@@ -19,6 +19,7 @@ export interface TLUiMenuCheckboxItemProps<
|
|
|
19
19
|
kbd?: string
|
|
20
20
|
title?: string
|
|
21
21
|
label?: TranslationKey | { [key: string]: TranslationKey }
|
|
22
|
+
lang?: string
|
|
22
23
|
readonlyOk?: boolean
|
|
23
24
|
onSelect(source: TLUiEventSource): Promise<void> | void
|
|
24
25
|
toggle?: boolean
|
|
@@ -34,6 +35,7 @@ export function TldrawUiMenuCheckboxItem<
|
|
|
34
35
|
id,
|
|
35
36
|
kbd,
|
|
36
37
|
label,
|
|
38
|
+
lang,
|
|
37
39
|
readonlyOk,
|
|
38
40
|
onSelect,
|
|
39
41
|
toggle = false,
|
|
@@ -55,6 +57,7 @@ export function TldrawUiMenuCheckboxItem<
|
|
|
55
57
|
return (
|
|
56
58
|
<_DropdownMenu.CheckboxItem
|
|
57
59
|
dir="ltr"
|
|
60
|
+
lang={lang}
|
|
58
61
|
className="tlui-button tlui-button__menu tlui-button__checkbox"
|
|
59
62
|
title={labelStr}
|
|
60
63
|
onSelect={(e) => {
|
|
@@ -84,6 +87,7 @@ export function TldrawUiMenuCheckboxItem<
|
|
|
84
87
|
key={id}
|
|
85
88
|
className="tlui-button tlui-button__menu tlui-button__checkbox"
|
|
86
89
|
dir="ltr"
|
|
90
|
+
lang={lang}
|
|
87
91
|
title={labelStr}
|
|
88
92
|
onSelect={(e) => {
|
|
89
93
|
onSelect(sourceId)
|