tldraw 4.1.0-next.542f014c3fac → 4.1.0-next.58b63dd1ac80

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.
Files changed (149) hide show
  1. package/dist-cjs/index.d.ts +32 -2
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +1 -1
  7. package/dist-cjs/lib/defaultEmbedDefinitions.js +24 -6
  8. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js +2 -2
  10. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
  12. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/curved-arrow.js +8 -2
  14. package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/straight-arrow.js +4 -1
  16. package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
  17. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +14 -2
  18. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  19. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
  20. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +1 -1
  21. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
  22. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
  24. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
  25. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +2 -2
  26. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  28. package/dist-cjs/lib/shapes/text/PlainTextArea.js +1 -1
  29. package/dist-cjs/lib/shapes/text/RichTextArea.js +1 -1
  30. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  31. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  32. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  33. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +9 -1
  34. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  35. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -1
  36. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  37. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  38. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js +1 -1
  39. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog.js +1 -1
  40. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +1 -1
  41. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  42. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  43. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +5 -0
  44. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +1 -1
  46. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -2
  47. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  48. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +1 -1
  49. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +1 -1
  50. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +64 -56
  51. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  52. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +54 -47
  53. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +3 -3
  54. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +63 -56
  55. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
  56. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +13 -6
  57. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +2 -2
  58. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +1 -1
  59. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  60. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +1 -1
  61. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  63. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
  64. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +1 -1
  65. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +1 -1
  66. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  67. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -2
  68. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  69. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -2
  70. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +1 -1
  71. package/dist-cjs/lib/ui/components/primitives/layout.js +1 -1
  72. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +1 -1
  73. package/dist-cjs/lib/ui/context/actions.js +1 -1
  74. package/dist-cjs/lib/ui/context/breakpoints.js +1 -1
  75. package/dist-cjs/lib/ui/context/events.js +1 -1
  76. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  77. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -1
  78. package/dist-cjs/lib/ui/hooks/useLocalStorageState.js +1 -1
  79. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  80. package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -1
  81. package/dist-cjs/lib/ui/version.js +4 -4
  82. package/dist-cjs/lib/ui/version.js.map +1 -1
  83. package/dist-cjs/lib/utils/text/richText.js +4 -4
  84. package/dist-esm/index.d.mts +32 -2
  85. package/dist-esm/index.mjs +10 -4
  86. package/dist-esm/index.mjs.map +2 -2
  87. package/dist-esm/lib/defaultEmbedDefinitions.mjs +24 -6
  88. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  89. package/dist-esm/lib/defaultExternalContentHandlers.mjs +2 -2
  90. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  91. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
  92. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  93. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +8 -2
  94. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
  95. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +4 -1
  96. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
  97. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +13 -1
  98. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
  100. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  101. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -1
  102. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  103. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  104. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  105. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +11 -2
  106. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  107. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +1 -1
  108. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  109. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +1 -1
  110. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  111. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +5 -0
  112. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  113. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -2
  114. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  115. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +68 -57
  116. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  117. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +54 -47
  118. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +3 -3
  119. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +63 -56
  120. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
  121. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs +12 -5
  122. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +2 -2
  123. package/dist-esm/lib/ui/version.mjs +4 -4
  124. package/dist-esm/lib/ui/version.mjs.map +1 -1
  125. package/package.json +11 -11
  126. package/src/index.ts +3 -0
  127. package/src/lib/defaultEmbedDefinitions.ts +19 -0
  128. package/src/lib/defaultExternalContentHandlers.ts +2 -2
  129. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +211 -1
  130. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +3 -0
  131. package/src/lib/shapes/arrow/curved-arrow.ts +8 -2
  132. package/src/lib/shapes/arrow/straight-arrow.ts +5 -1
  133. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +13 -3
  134. package/src/lib/shapes/line/LineShapeUtil.tsx +3 -0
  135. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -1
  136. package/src/lib/shapes/text/TextShapeTool.test.ts +74 -0
  137. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +1 -1
  138. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +13 -1
  139. package/src/lib/tools/SelectTool/childStates/Idle.ts +1 -1
  140. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +1 -1
  141. package/src/lib/ui/components/Minimap/MinimapManager.ts +6 -0
  142. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +6 -2
  143. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +60 -49
  144. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +70 -53
  145. package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +105 -90
  146. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +72 -51
  147. package/src/lib/ui/version.ts +4 -4
  148. package/src/test/customSnapping.test.tsx +55 -11
  149. package/tldraw.css +7 -2
@@ -249,6 +249,12 @@ export class MinimapManager {
249
249
 
250
250
  const len = geometry.length
251
251
 
252
+ const shape = this.editor.getShape(shapeId)
253
+ if (shape) {
254
+ const shapeUtil = this.editor.getShapeUtil(shape.type)
255
+ if (shapeUtil.hideInMinimap?.(shape)) continue
256
+ }
257
+
252
258
  if (selectedShapes.has(shapeId)) {
253
259
  appendVertices(this.gl.selectedShapes, selectedShapeOffset, geometry)
254
260
  selectedShapeOffset += len
@@ -1,6 +1,8 @@
1
1
  import { useContainer, useEditor, usePeerIds, useValue } from '@tldraw/editor'
2
2
  import { Popover as _Popover } from 'radix-ui'
3
3
  import { ReactNode } from 'react'
4
+ import { PORTRAIT_BREAKPOINT } from '../../constants'
5
+ import { useBreakpoint } from '../../context/breakpoints'
4
6
  import { useMenuIsOpen } from '../../hooks/useMenuIsOpen'
5
7
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
8
  import { PeopleMenuAvatar } from './PeopleMenuAvatar'
@@ -25,6 +27,8 @@ export function PeopleMenu({ children }: PeopleMenuProps) {
25
27
  const userName = useValue('user', () => editor.user.getName(), [editor])
26
28
 
27
29
  const [isOpen, onOpenChange] = useMenuIsOpen('people menu')
30
+ const breakpoint = useBreakpoint()
31
+ const maxAvatars = breakpoint <= PORTRAIT_BREAKPOINT.MOBILE_XS ? 1 : 5
28
32
 
29
33
  if (!userIds.length) return null
30
34
 
@@ -33,7 +37,7 @@ export function PeopleMenu({ children }: PeopleMenuProps) {
33
37
  <_Popover.Trigger dir="ltr" asChild>
34
38
  <button className="tlui-people-menu__avatars-button" title={msg('people-menu.title')}>
35
39
  <div className="tlui-people-menu__avatars">
36
- {userIds.slice(-5).map((userId) => (
40
+ {userIds.slice(-maxAvatars).map((userId) => (
37
41
  <PeopleMenuAvatar key={userId} userId={userId} />
38
42
  ))}
39
43
  {userIds.length > 0 && (
@@ -46,7 +50,7 @@ export function PeopleMenu({ children }: PeopleMenuProps) {
46
50
  {userName?.[0] ?? ''}
47
51
  </div>
48
52
  )}
49
- {userIds.length > 5 && <PeopleMenuMore count={userIds.length - 5} />}
53
+ {userIds.length > maxAvatars && <PeopleMenuMore count={userIds.length - maxAvatars} />}
50
54
  </div>
51
55
  </button>
52
56
  </_Popover.Trigger>
@@ -25,10 +25,13 @@ import { useTranslation } from '../../hooks/useTranslation/useTranslation'
25
25
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
26
26
  import { TldrawUiSlider } from '../primitives/TldrawUiSlider'
27
27
  import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
28
- import { StylePanelButtonPicker } from './StylePanelButtonPicker'
28
+ import { StylePanelButtonPicker, StylePanelButtonPickerInline } from './StylePanelButtonPicker'
29
29
  import { useStylePanelContext } from './StylePanelContext'
30
30
  import { StylePanelDoubleDropdownPicker } from './StylePanelDoubleDropdownPicker'
31
- import { StylePanelDropdownPicker } from './StylePanelDropdownPicker'
31
+ import {
32
+ StylePanelDropdownPicker,
33
+ StylePanelDropdownPickerInline,
34
+ } from './StylePanelDropdownPicker'
32
35
  import { StylePanelSubheading } from './StylePanelSubheading'
33
36
 
34
37
  /** @public @react */
@@ -225,70 +228,78 @@ export function StylePanelFontPicker() {
225
228
 
226
229
  /** @public @react */
227
230
  export function StylePanelTextAlignPicker() {
228
- const { styles } = useStylePanelContext()
231
+ const { styles, enhancedA11yMode } = useStylePanelContext()
229
232
  const msg = useTranslation()
230
233
  const textAlign = styles.get(DefaultTextAlignStyle)
231
234
  if (textAlign === undefined) return null
235
+ const title = msg('style-panel.align')
232
236
 
233
237
  return (
234
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.align')}>
235
- <StylePanelButtonPicker
236
- title={msg('style-panel.align')}
237
- uiType="align"
238
- style={DefaultTextAlignStyle}
239
- items={STYLES.textAlign}
240
- value={textAlign}
241
- />
242
- <TldrawUiToolbarButton
243
- type="icon"
244
- title={msg('style-panel.vertical-align')}
245
- data-testid="vertical-align"
246
- disabled
247
- >
248
- <TldrawUiButtonIcon icon="vertical-align-middle" />
249
- </TldrawUiToolbarButton>
250
- </TldrawUiToolbar>
238
+ <>
239
+ {enhancedA11yMode && <StylePanelSubheading>{title}</StylePanelSubheading>}
240
+ <TldrawUiToolbar orientation="horizontal" label={title}>
241
+ <StylePanelButtonPickerInline
242
+ title={title}
243
+ uiType="align"
244
+ style={DefaultTextAlignStyle}
245
+ items={STYLES.textAlign}
246
+ value={textAlign}
247
+ />
248
+ <TldrawUiToolbarButton
249
+ type="icon"
250
+ title={msg('style-panel.vertical-align')}
251
+ data-testid="vertical-align"
252
+ disabled
253
+ >
254
+ <TldrawUiButtonIcon icon="vertical-align-middle" />
255
+ </TldrawUiToolbarButton>
256
+ </TldrawUiToolbar>
257
+ </>
251
258
  )
252
259
  }
253
260
 
254
261
  /** @public @react */
255
262
  export function StylePanelLabelAlignPicker() {
256
- const { styles } = useStylePanelContext()
263
+ const { styles, enhancedA11yMode } = useStylePanelContext()
257
264
  const msg = useTranslation()
258
265
  const labelAlign = styles.get(DefaultHorizontalAlignStyle)
259
266
  const verticalLabelAlign = styles.get(DefaultVerticalAlignStyle)
260
267
  if (labelAlign === undefined) return null
268
+ const title = msg('style-panel.label-align')
261
269
 
262
270
  return (
263
- <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.label-align')}>
264
- <StylePanelButtonPicker
265
- title={msg('style-panel.label-align')}
266
- uiType="align"
267
- style={DefaultHorizontalAlignStyle}
268
- items={STYLES.horizontalAlign}
269
- value={labelAlign}
270
- />
271
- {verticalLabelAlign === undefined ? (
272
- <TldrawUiToolbarButton
273
- type="icon"
274
- title={msg('style-panel.vertical-align')}
275
- data-testid="vertical-align"
276
- disabled
277
- >
278
- <TldrawUiButtonIcon icon="vertical-align-middle" />
279
- </TldrawUiToolbarButton>
280
- ) : (
281
- <StylePanelDropdownPicker
282
- type="icon"
283
- id="geo-vertical-alignment"
284
- uiType="verticalAlign"
285
- stylePanelType="vertical-align"
286
- style={DefaultVerticalAlignStyle}
287
- items={STYLES.verticalAlign}
288
- value={verticalLabelAlign}
271
+ <>
272
+ {enhancedA11yMode && <StylePanelSubheading>{title}</StylePanelSubheading>}
273
+ <TldrawUiToolbar orientation="horizontal" label={title}>
274
+ <StylePanelButtonPickerInline
275
+ title={title}
276
+ uiType="align"
277
+ style={DefaultHorizontalAlignStyle}
278
+ items={STYLES.horizontalAlign}
279
+ value={labelAlign}
289
280
  />
290
- )}
291
- </TldrawUiToolbar>
281
+ {verticalLabelAlign === undefined ? (
282
+ <TldrawUiToolbarButton
283
+ type="icon"
284
+ title={msg('style-panel.vertical-align')}
285
+ data-testid="vertical-align"
286
+ disabled
287
+ >
288
+ <TldrawUiButtonIcon icon="vertical-align-middle" />
289
+ </TldrawUiToolbarButton>
290
+ ) : (
291
+ <StylePanelDropdownPickerInline
292
+ type="icon"
293
+ id="geo-vertical-alignment"
294
+ uiType="verticalAlign"
295
+ stylePanelType="vertical-align"
296
+ style={DefaultVerticalAlignStyle}
297
+ items={STYLES.verticalAlign}
298
+ value={verticalLabelAlign}
299
+ />
300
+ )}
301
+ </TldrawUiToolbar>
302
+ </>
292
303
  )
293
304
  }
294
305
 
@@ -6,7 +6,7 @@ import {
6
6
  TLDefaultColorStyle,
7
7
  useEditor,
8
8
  } from '@tldraw/editor'
9
- import { memo, ReactElement, useMemo, useRef } from 'react'
9
+ import { memo, useMemo, useRef } from 'react'
10
10
  import { useDefaultColorTheme } from '../../../shapes/shared/useDefaultColorTheme'
11
11
  import { StyleValuesForUi } from '../../../styles'
12
12
  import { PORTRAIT_BREAKPOINT } from '../../constants'
@@ -34,8 +34,19 @@ export interface StylePanelButtonPickerProps<T extends string> {
34
34
  onHistoryMark?(id: string): void
35
35
  }
36
36
 
37
- /** @public */
38
- export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T extends string>(
37
+ function StylePanelButtonPickerInner<T extends string>(props: StylePanelButtonPickerProps<T>) {
38
+ const { enhancedA11yMode } = useStylePanelContext()
39
+ return (
40
+ <>
41
+ {enhancedA11yMode && <StylePanelSubheading>{props.title}</StylePanelSubheading>}
42
+ <TldrawUiToolbar label={props.title}>
43
+ <StylePanelButtonPickerInline {...props} />
44
+ </TldrawUiToolbar>
45
+ </>
46
+ )
47
+ }
48
+
49
+ function StylePanelButtonPickerInlineInner<T extends string>(
39
50
  props: StylePanelButtonPickerProps<T>
40
51
  ) {
41
52
  const ctx = useStylePanelContext()
@@ -126,54 +137,60 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
126
137
  const Layout = items.length > 4 ? TldrawUiGrid : TldrawUiRow
127
138
 
128
139
  return (
129
- <>
130
- {ctx.enhancedA11yMode && <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
- </>
140
+ <TldrawUiToolbarToggleGroup
141
+ data-testid={`style.${uiType}`}
142
+ type="single"
143
+ value={value.type === 'shared' ? value.value : null}
144
+ asChild
145
+ >
146
+ <Layout>
147
+ {items.map((item) => {
148
+ const isActive = value.type === 'shared' && value.value === item.value
149
+ const label = title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
150
+ return (
151
+ <TldrawUiToolbarToggleItem
152
+ type="icon"
153
+ key={item.value}
154
+ data-id={item.value}
155
+ data-testid={`style.${uiType}.${item.value}`}
156
+ aria-label={label + (isActive ? ` (${msg('style-panel.selected')})` : '')}
157
+ tooltip={
158
+ <>
159
+ <div>{label}</div>
160
+ {isActive ? <div>({msg('style-panel.selected')})</div> : null}
161
+ </>
162
+ }
163
+ value={item.value}
164
+ data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
165
+ data-isactive={isActive}
166
+ title={label}
167
+ style={
168
+ style === (DefaultColorStyle as StyleProp<unknown>)
169
+ ? { color: getColorValue(theme, item.value as TLDefaultColorStyle, 'solid') }
170
+ : undefined
171
+ }
172
+ onPointerEnter={handleButtonPointerEnter}
173
+ onPointerDown={handleButtonPointerDown}
174
+ onPointerUp={handleButtonPointerUp}
175
+ onClick={handleButtonClick}
176
+ >
177
+ <TldrawUiButtonIcon icon={item.icon} />
178
+ </TldrawUiToolbarToggleItem>
179
+ )
180
+ })}
181
+ </Layout>
182
+ </TldrawUiToolbarToggleGroup>
178
183
  )
179
- }) as <T extends string>(props: StylePanelButtonPickerProps<T>) => ReactElement
184
+ }
185
+
186
+ /** @public @react */
187
+ export const StylePanelButtonPicker = memo(StylePanelButtonPickerInner) as <T extends string>(
188
+ props: StylePanelButtonPickerProps<T>
189
+ ) => React.JSX.Element
190
+
191
+ /** @public @react*/
192
+ export const StylePanelButtonPickerInline = memo(StylePanelButtonPickerInlineInner) as <
193
+ T extends string,
194
+ >(
195
+ props: StylePanelButtonPickerProps<T>
196
+ ) => React.JSX.Element
@@ -29,12 +29,27 @@ export interface StylePanelDoubleDropdownPickerProps<T extends string> {
29
29
  onValueChange?(style: StyleProp<T>, value: T): void
30
30
  }
31
31
 
32
- function DoubleDropdownPickerInner<T extends string>(
32
+ function StylePanelDoubleDropdownPickerInner<T extends string>(
33
+ props: StylePanelDoubleDropdownPickerProps<T>
34
+ ) {
35
+ const msg = useTranslation()
36
+ return (
37
+ <div className="tlui-style-panel__double-select-picker">
38
+ <div title={msg(props.label)} className="tlui-style-panel__double-select-picker-label">
39
+ {msg(props.label)}
40
+ </div>
41
+ <TldrawUiToolbar orientation="horizontal" label={msg(props.label)}>
42
+ <StylePanelDoubleDropdownPickerInline {...props} />
43
+ </TldrawUiToolbar>
44
+ </div>
45
+ )
46
+ }
47
+
48
+ function StylePanelDoubleDropdownPickerInlineInner<T extends string>(
33
49
  props: StylePanelDoubleDropdownPickerProps<T>
34
50
  ) {
35
51
  const ctx = useStylePanelContext()
36
52
  const {
37
- label,
38
53
  uiTypeA,
39
54
  uiTypeB,
40
55
  labelA,
@@ -70,100 +85,100 @@ function DoubleDropdownPickerInner<T extends string>(
70
85
  const idA = `style panel ${uiTypeA} A`
71
86
  const idB = `style panel ${uiTypeB} B`
72
87
  return (
73
- <div className="tlui-style-panel__double-select-picker">
74
- <div title={msg(label)} className="tlui-style-panel__double-select-picker-label">
75
- {msg(label)}
76
- </div>
77
- <TldrawUiToolbar orientation="horizontal" label={msg(label)}>
78
- <TldrawUiPopover id={idA} open={isOpenA} onOpenChange={setIsOpenA}>
79
- <TldrawUiPopoverTrigger>
80
- <TldrawUiToolbarButton
81
- type="icon"
82
- data-testid={`style.${uiTypeA}`}
83
- title={
84
- msg(labelA) +
85
- ' — ' +
86
- (valueA === null || valueA.type === 'mixed'
87
- ? msg('style-panel.mixed')
88
- : msg(`${uiTypeA}-style.${valueA.value}` as TLUiTranslationKey))
89
- }
90
- >
91
- <TldrawUiButtonIcon icon={iconA} small invertIcon />
92
- </TldrawUiToolbarButton>
93
- </TldrawUiPopoverTrigger>
94
- <TldrawUiPopoverContent side="left" align="center" sideOffset={80} alignOffset={0}>
95
- <TldrawUiToolbar orientation="grid" label={msg(labelA)}>
96
- <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
97
- {itemsA.map((item) => {
98
- return (
99
- <TldrawUiToolbarButton
100
- data-testid={`style.${uiTypeA}.${item.value}`}
101
- type="icon"
102
- key={item.value}
103
- onClick={() => {
104
- onValueChange(styleA, item.value)
105
- tlmenus.deleteOpenMenu(idA, editor.contextId)
106
- setIsOpenA(false)
107
- }}
108
- title={`${msg(labelA)} — ${msg(`${uiTypeA}-style.${item.value}`)}`}
109
- >
110
- <TldrawUiButtonIcon icon={item.icon} invertIcon />
111
- </TldrawUiToolbarButton>
112
- )
113
- })}
114
- </TldrawUiMenuContextProvider>
115
- </TldrawUiToolbar>
116
- </TldrawUiPopoverContent>
117
- </TldrawUiPopover>
118
- <TldrawUiPopover id={idB} open={isOpenB} onOpenChange={setIsOpenB}>
119
- <TldrawUiPopoverTrigger>
120
- <TldrawUiToolbarButton
121
- type="icon"
122
- data-testid={`style.${uiTypeB}`}
123
- title={
124
- msg(labelB) +
125
- ' — ' +
126
- (valueB === null || valueB.type === 'mixed'
127
- ? msg('style-panel.mixed')
128
- : msg(`${uiTypeB}-style.${valueB.value}` as TLUiTranslationKey))
129
- }
130
- >
131
- <TldrawUiButtonIcon icon={iconB} small />
132
- </TldrawUiToolbarButton>
133
- </TldrawUiPopoverTrigger>
134
- <TldrawUiPopoverContent side="left" align="center" sideOffset={116} alignOffset={0}>
135
- <TldrawUiToolbar orientation="grid" label={msg(labelB)}>
136
- <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
137
- {itemsB.map((item) => {
138
- return (
139
- <TldrawUiToolbarButton
140
- key={item.value}
141
- type="icon"
142
- title={`${msg(labelB)} — ${msg(`${uiTypeB}-style.${item.value}` as TLUiTranslationKey)}`}
143
- data-testid={`style.${uiTypeB}.${item.value}`}
144
- onClick={() => {
145
- onValueChange(styleB, item.value)
146
- tlmenus.deleteOpenMenu(idB, editor.contextId)
147
- setIsOpenB(false)
148
- }}
149
- >
150
- <TldrawUiButtonIcon icon={item.icon} />
151
- </TldrawUiToolbarButton>
152
- )
153
- })}
154
- </TldrawUiMenuContextProvider>
155
- </TldrawUiToolbar>
156
- </TldrawUiPopoverContent>
157
- </TldrawUiPopover>
158
- </TldrawUiToolbar>
159
- </div>
88
+ <>
89
+ <TldrawUiPopover id={idA} open={isOpenA} onOpenChange={setIsOpenA}>
90
+ <TldrawUiPopoverTrigger>
91
+ <TldrawUiToolbarButton
92
+ type="icon"
93
+ data-testid={`style.${uiTypeA}`}
94
+ title={
95
+ msg(labelA) +
96
+ ' — ' +
97
+ (valueA === null || valueA.type === 'mixed'
98
+ ? msg('style-panel.mixed')
99
+ : msg(`${uiTypeA}-style.${valueA.value}` as TLUiTranslationKey))
100
+ }
101
+ >
102
+ <TldrawUiButtonIcon icon={iconA} small invertIcon />
103
+ </TldrawUiToolbarButton>
104
+ </TldrawUiPopoverTrigger>
105
+ <TldrawUiPopoverContent side="left" align="center" sideOffset={80} alignOffset={0}>
106
+ <TldrawUiToolbar orientation="grid" label={msg(labelA)}>
107
+ <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
108
+ {itemsA.map((item) => {
109
+ return (
110
+ <TldrawUiToolbarButton
111
+ data-testid={`style.${uiTypeA}.${item.value}`}
112
+ type="icon"
113
+ key={item.value}
114
+ onClick={() => {
115
+ onValueChange(styleA, item.value)
116
+ tlmenus.deleteOpenMenu(idA, editor.contextId)
117
+ setIsOpenA(false)
118
+ }}
119
+ title={`${msg(labelA)} — ${msg(`${uiTypeA}-style.${item.value}`)}`}
120
+ >
121
+ <TldrawUiButtonIcon icon={item.icon} invertIcon />
122
+ </TldrawUiToolbarButton>
123
+ )
124
+ })}
125
+ </TldrawUiMenuContextProvider>
126
+ </TldrawUiToolbar>
127
+ </TldrawUiPopoverContent>
128
+ </TldrawUiPopover>
129
+ <TldrawUiPopover id={idB} open={isOpenB} onOpenChange={setIsOpenB}>
130
+ <TldrawUiPopoverTrigger>
131
+ <TldrawUiToolbarButton
132
+ type="icon"
133
+ data-testid={`style.${uiTypeB}`}
134
+ title={
135
+ msg(labelB) +
136
+ ' — ' +
137
+ (valueB === null || valueB.type === 'mixed'
138
+ ? msg('style-panel.mixed')
139
+ : msg(`${uiTypeB}-style.${valueB.value}` as TLUiTranslationKey))
140
+ }
141
+ >
142
+ <TldrawUiButtonIcon icon={iconB} small />
143
+ </TldrawUiToolbarButton>
144
+ </TldrawUiPopoverTrigger>
145
+ <TldrawUiPopoverContent side="left" align="center" sideOffset={116} alignOffset={0}>
146
+ <TldrawUiToolbar orientation="grid" label={msg(labelB)}>
147
+ <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
148
+ {itemsB.map((item) => {
149
+ return (
150
+ <TldrawUiToolbarButton
151
+ key={item.value}
152
+ type="icon"
153
+ title={`${msg(labelB)} — ${msg(`${uiTypeB}-style.${item.value}` as TLUiTranslationKey)}`}
154
+ data-testid={`style.${uiTypeB}.${item.value}`}
155
+ onClick={() => {
156
+ onValueChange(styleB, item.value)
157
+ tlmenus.deleteOpenMenu(idB, editor.contextId)
158
+ setIsOpenB(false)
159
+ }}
160
+ >
161
+ <TldrawUiButtonIcon icon={item.icon} />
162
+ </TldrawUiToolbarButton>
163
+ )
164
+ })}
165
+ </TldrawUiMenuContextProvider>
166
+ </TldrawUiToolbar>
167
+ </TldrawUiPopoverContent>
168
+ </TldrawUiPopover>
169
+ </>
160
170
  )
161
171
  }
162
172
 
163
173
  // need to memo like this to get generics
164
174
  /** @public @react */
165
- export const StylePanelDoubleDropdownPicker = React.memo(DoubleDropdownPickerInner) as <
175
+ export const StylePanelDoubleDropdownPicker = React.memo(StylePanelDoubleDropdownPickerInner) as <
166
176
  T extends string,
167
177
  >(
168
178
  props: StylePanelDoubleDropdownPickerProps<T>
169
179
  ) => React.JSX.Element
180
+
181
+ /** @public @react */
182
+ export const StylePanelDoubleDropdownPickerInline = React.memo(
183
+ StylePanelDoubleDropdownPickerInlineInner
184
+ ) as <T extends string>(props: StylePanelDoubleDropdownPickerProps<T>) => React.JSX.Element