tldraw 3.16.0-canary.1efac4751756 → 3.16.0-canary.1f09406e5b86

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 (106) hide show
  1. package/dist-cjs/index.d.ts +86 -5
  2. package/dist-cjs/index.js +5 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  5. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +3 -2
  6. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  7. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +1 -1
  8. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  9. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  10. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  11. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +8 -2
  12. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  13. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
  14. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  15. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +2 -3
  16. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  17. package/dist-cjs/lib/shapes/text/PlainTextArea.js +2 -1
  18. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  19. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +3 -1
  20. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  21. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  22. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  23. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  24. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  25. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  26. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  27. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  28. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  29. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
  30. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  31. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  32. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  33. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +2 -2
  34. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +3 -3
  36. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  37. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  38. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  39. package/dist-cjs/lib/ui/version.js +3 -3
  40. package/dist-cjs/lib/ui/version.js.map +1 -1
  41. package/dist-esm/index.d.mts +86 -5
  42. package/dist-esm/index.mjs +9 -1
  43. package/dist-esm/index.mjs.map +2 -2
  44. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +3 -2
  45. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  46. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +1 -1
  47. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  48. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +1 -2
  49. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  50. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +9 -3
  51. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  52. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +2 -2
  53. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  54. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +2 -4
  55. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  56. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -2
  57. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  58. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +3 -1
  59. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  60. package/dist-esm/lib/ui/components/A11y.mjs +1 -2
  61. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  62. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -1
  63. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  64. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +1 -2
  65. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  66. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  67. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  68. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
  69. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  70. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -2
  71. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  72. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +2 -2
  73. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  74. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +3 -3
  75. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  76. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +1 -2
  77. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  78. package/dist-esm/lib/ui/version.mjs +3 -3
  79. package/dist-esm/lib/ui/version.mjs.map +1 -1
  80. package/package.json +3 -3
  81. package/src/index.ts +7 -0
  82. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +83 -13
  83. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +97 -3
  84. package/src/lib/shapes/arrow/arrow-types.ts +3 -5
  85. package/src/lib/shapes/arrow/arrowTargetState.ts +34 -3
  86. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
  87. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +1 -2
  88. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +10 -3
  89. package/src/lib/shapes/shared/HyperlinkButton.tsx +2 -2
  90. package/src/lib/shapes/shared/useEditablePlainText.ts +2 -5
  91. package/src/lib/shapes/text/PlainTextArea.tsx +3 -2
  92. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +6 -2
  93. package/src/lib/ui/components/A11y.tsx +1 -2
  94. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -1
  95. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +1 -2
  96. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  97. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
  98. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -2
  99. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +2 -2
  100. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -3
  101. package/src/lib/ui/hooks/useClipboardEvents.ts +1 -2
  102. package/src/lib/ui/version.ts +3 -3
  103. package/src/lib/ui.css +14 -1
  104. package/src/test/TestEditor.ts +8 -2
  105. package/src/test/frames.test.ts +15 -0
  106. package/tldraw.css +14 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/Toolbar/OverflowingToolbar.tsx"],
4
- "sourcesContent": ["import {\n\tactiveElementShouldCaptureKeys,\n\tassert,\n\tmodulate,\n\tpreventDefault,\n\ttlmenus,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { createContext, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { areShortcutsDisabled } from '../../hooks/useKeyboardShortcuts'\nimport { TLUiToolItem } from '../../hooks/useTools'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { TldrawUiColumn, TldrawUiRow } from '../primitives/layout'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\n\nexport const IsInOverflowContext = createContext(false)\n\nconst NUMBERED_SHORTCUT_KEYS: Record<string, number> = {\n\t'1': 0,\n\t'2': 1,\n\t'3': 2,\n\t'4': 3,\n\t'5': 4,\n\t'6': 5,\n\t'7': 6,\n\t'8': 7,\n\t'9': 8,\n\t'0': 9,\n}\n\n/** @public */\nexport interface OverflowingToolbarProps {\n\tchildren: React.ReactNode\n\torientation: 'horizontal' | 'vertical'\n\tsizingParentClassName: string\n\tminItems: number\n\tminSizePx: number\n\tmaxItems: number\n\tmaxSizePx: number\n}\n\n/** @public @react */\nexport function OverflowingToolbar({\n\tchildren,\n\torientation,\n\tsizingParentClassName,\n\tminItems,\n\tminSizePx,\n\tmaxItems,\n\tmaxSizePx,\n}: OverflowingToolbarProps) {\n\tconst editor = useEditor()\n\tconst id = useUniqueSafeId()\n\tconst breakpoint = useBreakpoint()\n\tconst msg = useTranslation()\n\tconst rButtons = useRef<HTMLElement[]>([])\n\tconst [isOpen, setIsOpen] = useState(false)\n\n\tconst mainToolsRef = useRef<HTMLDivElement>(null)\n\n\t// we have to use state instead of a ref here so that we get\n\t// an update when the overflow popover mounts / unmounts\n\tconst [overflowTools, setOverflowTools] = useState<HTMLDivElement | null>(null)\n\tconst [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)\n\tconst [shouldShowOverflow, setShouldShowOverflow] = useState(false)\n\n\tconst onDomUpdate = useEvent(() => {\n\t\tif (!mainToolsRef.current) return\n\n\t\t// whenever we get an update, we need to re-calculate the number of items to show and update\n\t\t// the component accordingly.\n\t\tconst sizeProp = orientation === 'horizontal' ? 'offsetWidth' : 'offsetHeight'\n\n\t\t// toolbars can contain both single items and groups. we need to keep track of both.\n\t\ttype Items = (\n\t\t\t| { type: 'item'; element: HTMLElement }\n\t\t\t| { type: 'group'; items: Items; element: HTMLElement }\n\t\t)[]\n\n\t\t// walk through the dom and collect items so we can calculate what to show/hide\n\t\tconst mainItems = collectItems(mainToolsRef.current.children)\n\t\tconst overflowItems = overflowTools ? collectItems(overflowTools.children) : null\n\t\tfunction collectItems(collection: HTMLCollection) {\n\t\t\tconst items: Items = []\n\t\t\tfor (const child of collection) {\n\t\t\t\tif (child.classList.contains('tlui-main-toolbar__group')) {\n\t\t\t\t\titems.push({\n\t\t\t\t\t\ttype: 'group',\n\t\t\t\t\t\titems: collectItems(child.children),\n\t\t\t\t\t\telement: child as HTMLElement,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\titems.push({ type: 'item', element: child as HTMLElement })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn items\n\t\t}\n\n\t\t// the number of items to show is based on the space available to the toolbar.\n\t\tconst sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)\n\t\tconst size = sizingParent[sizeProp]\n\t\tconst itemsToShow = Math.floor(\n\t\t\tmodulate(size, [minSizePx, maxSizePx], [minItems, maxItems], true)\n\t\t)\n\n\t\t// now we know how many items to show, we need to walk through the items we found and show /\n\t\t// hide them accordingly. We need to keep track of:\n\t\t// the number of item's we've shown in the main content so far\n\t\tlet mainItemCount = 0\n\t\t// the item that is currently active in the overflow content (if any)\n\t\tlet newActiveOverflowItem: string | null = null\n\t\t// whether the last active overflow item is actually still in the overflow content\n\t\tlet shouldInvalidateLastActiveOverflowItem = false\n\t\t// the buttons visible in the main content\n\t\tconst numberedButtons: HTMLButtonElement[] = []\n\t\tfunction visitItems(\n\t\t\tmainItems: Items,\n\t\t\toverflowItems: Items | null\n\t\t): {\n\t\t\t// for each group of items we visit, we need to know whether we showed anything in\n\t\t\t// either section\n\t\t\tdidShowAnyInMain: boolean\n\t\t\tdidShowAnyInOverflow: boolean\n\t\t} {\n\t\t\tif (overflowItems) assert(mainItems.length === overflowItems.length)\n\n\t\t\tlet didShowAnyInMain = false\n\t\t\tlet didShowAnyInOverflow = false\n\n\t\t\tfor (let i = 0; i < mainItems.length; i++) {\n\t\t\t\tconst mainItem = mainItems[i]\n\t\t\t\tconst overflowItem = overflowItems?.[i]\n\n\t\t\t\tif (mainItem.type === 'item') {\n\t\t\t\t\tconst isLastActiveOverflowItem =\n\t\t\t\t\t\tmainItem.element.getAttribute('data-value') === lastActiveOverflowItem\n\n\t\t\t\t\t// for single items, we show them in main if we have space, or if they're the\n\t\t\t\t\t// last-used item from the overflow.\n\t\t\t\t\tlet shouldShowInMain\n\t\t\t\t\tif (lastActiveOverflowItem) {\n\t\t\t\t\t\tshouldShowInMain = mainItemCount < itemsToShow || isLastActiveOverflowItem\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// we use <= here because if there is no last active overflow item, we want\n\t\t\t\t\t\t// to show at least one item in the main toolbar.\n\t\t\t\t\t\tshouldShowInMain = mainItemCount <= itemsToShow\n\t\t\t\t\t}\n\t\t\t\t\tconst shouldShowInOverflow = mainItemCount >= itemsToShow\n\n\t\t\t\t\tdidShowAnyInMain ||= shouldShowInMain\n\t\t\t\t\tdidShowAnyInOverflow ||= shouldShowInOverflow\n\n\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\tmainItem.element,\n\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\tshouldShowInMain ? 'true' : 'false'\n\t\t\t\t\t)\n\t\t\t\t\tif (overflowItem) {\n\t\t\t\t\t\tassert(overflowItem.type === 'item')\n\t\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\t\toverflowItem.element,\n\t\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\t\tshouldShowInOverflow ? 'true' : 'false'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif (shouldShowInOverflow && mainItem.element.getAttribute('aria-pressed') === 'true') {\n\t\t\t\t\t\tnewActiveOverflowItem = mainItem.element.getAttribute('data-value')\n\t\t\t\t\t}\n\t\t\t\t\tif (shouldShowInMain && mainItem.element.tagName === 'BUTTON') {\n\t\t\t\t\t\tnumberedButtons.push(mainItem.element as HTMLButtonElement)\n\t\t\t\t\t}\n\t\t\t\t\tif (!shouldShowInOverflow && isLastActiveOverflowItem) {\n\t\t\t\t\t\tshouldInvalidateLastActiveOverflowItem = true\n\t\t\t\t\t}\n\t\t\t\t\tmainItemCount++\n\t\t\t\t} else {\n\t\t\t\t\t// for groups, we show them in main if we have space, or if they're the\n\t\t\t\t\t// last-used item from the overflow.\n\t\t\t\t\tlet result, overflowGroup\n\t\t\t\t\tif (overflowItem) {\n\t\t\t\t\t\tassert(overflowItem.type === 'group')\n\t\t\t\t\t\toverflowGroup = overflowItem\n\t\t\t\t\t\tresult = visitItems(mainItem.items, overflowGroup.items)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = visitItems(mainItem.items, null)\n\t\t\t\t\t}\n\n\t\t\t\t\tdidShowAnyInMain ||= result.didShowAnyInMain\n\t\t\t\t\tdidShowAnyInOverflow ||= result.didShowAnyInOverflow\n\n\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\tmainItem.element,\n\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\tresult.didShowAnyInMain ? 'true' : 'false'\n\t\t\t\t\t)\n\t\t\t\t\tif (overflowGroup) {\n\t\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\t\toverflowGroup.element,\n\t\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\t\tresult.didShowAnyInOverflow ? 'true' : 'false'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { didShowAnyInMain, didShowAnyInOverflow }\n\t\t}\n\n\t\tconst { didShowAnyInOverflow } = visitItems(mainItems, overflowItems)\n\t\tsetShouldShowOverflow(didShowAnyInOverflow)\n\t\tif (newActiveOverflowItem) {\n\t\t\tsetLastActiveOverflowItem(newActiveOverflowItem)\n\t\t} else if (shouldInvalidateLastActiveOverflowItem) {\n\t\t\tsetLastActiveOverflowItem(null)\n\t\t}\n\n\t\trButtons.current = numberedButtons\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tonDomUpdate()\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tif (!mainToolsRef.current) return\n\n\t\tconst mutationObserver = new MutationObserver(onDomUpdate)\n\t\tmutationObserver.observe(mainToolsRef.current, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tattributes: true,\n\t\t\tcharacterData: true,\n\t\t})\n\n\t\tconst sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)\n\t\tconst resizeObserver = new ResizeObserver(onDomUpdate)\n\t\tresizeObserver.observe(sizingParent)\n\n\t\treturn () => {\n\t\t\tmutationObserver.disconnect()\n\t\t\tresizeObserver.disconnect()\n\t\t}\n\t}, [onDomUpdate, sizingParentClassName])\n\n\tuseEffect(() => {\n\t\tif (!editor.options.enableToolbarKeyboardShortcuts) return\n\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (\n\t\t\t\tareShortcutsDisabled(editor) ||\n\t\t\t\tactiveElementShouldCaptureKeys(true /* allow buttons */)\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// no accelerator keys\n\t\t\tif (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return\n\t\t\tconst index = NUMBERED_SHORTCUT_KEYS[event.key]\n\t\t\tif (typeof index === 'number') {\n\t\t\t\tpreventDefault(event)\n\t\t\t\trButtons.current[index]?.click()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeyDown)\n\t\t}\n\t}, [editor])\n\n\tconst popoverId = 'toolbar overflow'\n\n\tconst Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiToolbar\n\t\t\t\torientation={orientation}\n\t\t\t\tclassName={classNames('tlui-main-toolbar__tools', {\n\t\t\t\t\t'tlui-main-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t\t})}\n\t\t\t\tlabel={msg('tool-panel.title')}\n\t\t\t>\n\t\t\t\t<Layout id={`${id}_main`} ref={mainToolsRef}>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"toolbar\" sourceId=\"toolbar\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t</Layout>\n\t\t\t\t{shouldShowOverflow && (\n\t\t\t\t\t<IsInOverflowContext.Provider value={true}>\n\t\t\t\t\t\t<TldrawUiPopover id={popoverId} open={isOpen} onOpenChange={setIsOpen}>\n\t\t\t\t\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\t\t\t\t\ttitle={msg('tool-panel.more')}\n\t\t\t\t\t\t\t\t\ttype=\"tool\"\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-main-toolbar__overflow\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"tools.more-button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TldrawUiButtonIcon\n\t\t\t\t\t\t\t\t\t\ticon={orientation === 'horizontal' ? 'chevron-up' : 'chevron-right'}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t\t\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t\t\t\t\t<TldrawUiPopoverContent\n\t\t\t\t\t\t\t\tside={orientation === 'horizontal' ? 'top' : 'right'}\n\t\t\t\t\t\t\t\talign={orientation === 'horizontal' ? 'center' : 'end'}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<TldrawUiToolbar\n\t\t\t\t\t\t\t\t\torientation=\"grid\"\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-main-toolbar__overflow-content\"\n\t\t\t\t\t\t\t\t\tref={setOverflowTools}\n\t\t\t\t\t\t\t\t\tdata-testid=\"tools.more-content\"\n\t\t\t\t\t\t\t\t\tlabel={msg('tool-panel.more')}\n\t\t\t\t\t\t\t\t\tid={`${id}_more`}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\ttlmenus.deleteOpenMenu(popoverId, editor.contextId)\n\t\t\t\t\t\t\t\t\t\tsetIsOpen(false)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TldrawUiMenuContextProvider type=\"toolbar-overflow\" sourceId=\"toolbar\">\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t\t\t\t\t</TldrawUiToolbar>\n\t\t\t\t\t\t\t</TldrawUiPopoverContent>\n\t\t\t\t\t\t</TldrawUiPopover>\n\t\t\t\t\t</IsInOverflowContext.Provider>\n\t\t\t\t)}\n\t\t\t</TldrawUiToolbar>\n\t\t</>\n\t)\n}\n\nexport const isActiveTLUiToolItem = (\n\titem: TLUiToolItem,\n\tactiveToolId: string | undefined,\n\tgeoState: string | null | undefined\n) => {\n\treturn item.meta?.geo\n\t\t? activeToolId === 'geo' && geoState === item.meta?.geo\n\t\t: activeToolId === item.id\n}\n\nfunction findParentWithClassName(startingElement: HTMLElement, className: string): HTMLElement {\n\tlet element: HTMLElement | null = startingElement\n\twhile (element) {\n\t\tif (element.classList.contains(className)) {\n\t\t\treturn element\n\t\t}\n\t\telement = element.parentElement\n\t}\n\tthrow new Error('Could not find parent with class name ' + className)\n}\n\nfunction setAttribute(element: HTMLElement, name: string, value: string) {\n\tif (element.getAttribute(name) === value) return\n\telement.setAttribute(name, value)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tactiveElementShouldCaptureKeys,\n\tassert,\n\tmodulate,\n\tpreventDefault,\n\ttlmenus,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { createContext, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { areShortcutsDisabled } from '../../hooks/useKeyboardShortcuts'\nimport { TLUiToolItem } from '../../hooks/useTools'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { TldrawUiColumn, TldrawUiRow } from '../primitives/layout'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\n\nexport const IsInOverflowContext = createContext(false)\n\nconst NUMBERED_SHORTCUT_KEYS: Record<string, number> = {\n\t'1': 0,\n\t'2': 1,\n\t'3': 2,\n\t'4': 3,\n\t'5': 4,\n\t'6': 5,\n\t'7': 6,\n\t'8': 7,\n\t'9': 8,\n\t'0': 9,\n}\n\n/** @public */\nexport interface OverflowingToolbarProps {\n\tchildren: React.ReactNode\n\torientation: 'horizontal' | 'vertical'\n\tsizingParentClassName: string\n\tminItems: number\n\tminSizePx: number\n\tmaxItems: number\n\tmaxSizePx: number\n}\n\n/** @public @react */\nexport function OverflowingToolbar({\n\tchildren,\n\torientation,\n\tsizingParentClassName,\n\tminItems,\n\tminSizePx,\n\tmaxItems,\n\tmaxSizePx,\n}: OverflowingToolbarProps) {\n\tconst editor = useEditor()\n\tconst id = useUniqueSafeId()\n\tconst breakpoint = useBreakpoint()\n\tconst msg = useTranslation()\n\tconst rButtons = useRef<HTMLElement[]>([])\n\tconst [isOpen, setIsOpen] = useState(false)\n\n\tconst mainToolsRef = useRef<HTMLDivElement>(null)\n\n\t// we have to use state instead of a ref here so that we get\n\t// an update when the overflow popover mounts / unmounts\n\tconst [overflowTools, setOverflowTools] = useState<HTMLDivElement | null>(null)\n\tconst [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)\n\tconst [shouldShowOverflow, setShouldShowOverflow] = useState(false)\n\n\tconst onDomUpdate = useEvent(() => {\n\t\tif (!mainToolsRef.current) return\n\n\t\t// whenever we get an update, we need to re-calculate the number of items to show and update\n\t\t// the component accordingly.\n\t\tconst sizeProp = orientation === 'horizontal' ? 'offsetWidth' : 'offsetHeight'\n\n\t\t// toolbars can contain both single items and groups. we need to keep track of both.\n\t\ttype Items = (\n\t\t\t| { type: 'item'; element: HTMLElement }\n\t\t\t| { type: 'group'; items: Items; element: HTMLElement }\n\t\t)[]\n\n\t\t// walk through the dom and collect items so we can calculate what to show/hide\n\t\tconst mainItems = collectItems(mainToolsRef.current.children)\n\t\tconst overflowItems = overflowTools ? collectItems(overflowTools.children) : null\n\t\tfunction collectItems(collection: HTMLCollection) {\n\t\t\tconst items: Items = []\n\t\t\tfor (const child of collection) {\n\t\t\t\tif (child.classList.contains('tlui-main-toolbar__group')) {\n\t\t\t\t\titems.push({\n\t\t\t\t\t\ttype: 'group',\n\t\t\t\t\t\titems: collectItems(child.children),\n\t\t\t\t\t\telement: child as HTMLElement,\n\t\t\t\t\t})\n\t\t\t\t} else if (!child.hasAttribute('data-radix-popper-content-wrapper')) {\n\t\t\t\t\titems.push({ type: 'item', element: child as HTMLElement })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn items\n\t\t}\n\n\t\t// the number of items to show is based on the space available to the toolbar.\n\t\tconst sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)\n\t\tconst size = sizingParent[sizeProp]\n\t\tconst itemsToShow = Math.floor(\n\t\t\tmodulate(size, [minSizePx, maxSizePx], [minItems, maxItems], true)\n\t\t)\n\n\t\t// now we know how many items to show, we need to walk through the items we found and show /\n\t\t// hide them accordingly. We need to keep track of:\n\t\t// the number of item's we've shown in the main content so far\n\t\tlet mainItemCount = 0\n\t\t// the item that is currently active in the overflow content (if any)\n\t\tlet newActiveOverflowItem: string | null = null\n\t\t// whether the last active overflow item is actually still in the overflow content\n\t\tlet shouldInvalidateLastActiveOverflowItem = false\n\t\t// the buttons visible in the main content\n\t\tconst numberedButtons: HTMLButtonElement[] = []\n\t\tfunction visitItems(\n\t\t\tmainItems: Items,\n\t\t\toverflowItems: Items | null\n\t\t): {\n\t\t\t// for each group of items we visit, we need to know whether we showed anything in\n\t\t\t// either section\n\t\t\tdidShowAnyInMain: boolean\n\t\t\tdidShowAnyInOverflow: boolean\n\t\t} {\n\t\t\tif (overflowItems) assert(mainItems.length === overflowItems.length)\n\n\t\t\tlet didShowAnyInMain = false\n\t\t\tlet didShowAnyInOverflow = false\n\n\t\t\tfor (let i = 0; i < mainItems.length; i++) {\n\t\t\t\tconst mainItem = mainItems[i]\n\t\t\t\tconst overflowItem = overflowItems?.[i]\n\n\t\t\t\tif (mainItem.type === 'item') {\n\t\t\t\t\tconst isLastActiveOverflowItem =\n\t\t\t\t\t\tmainItem.element.getAttribute('data-value') === lastActiveOverflowItem\n\n\t\t\t\t\t// for single items, we show them in main if we have space, or if they're the\n\t\t\t\t\t// last-used item from the overflow.\n\t\t\t\t\tlet shouldShowInMain\n\t\t\t\t\tif (lastActiveOverflowItem) {\n\t\t\t\t\t\tshouldShowInMain = mainItemCount < itemsToShow || isLastActiveOverflowItem\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// we use <= here because if there is no last active overflow item, we want\n\t\t\t\t\t\t// to show at least one item in the main toolbar.\n\t\t\t\t\t\tshouldShowInMain = mainItemCount <= itemsToShow\n\t\t\t\t\t}\n\t\t\t\t\tconst shouldShowInOverflow = mainItemCount >= itemsToShow\n\n\t\t\t\t\tdidShowAnyInMain ||= shouldShowInMain\n\t\t\t\t\tdidShowAnyInOverflow ||= shouldShowInOverflow\n\n\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\tmainItem.element,\n\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\tshouldShowInMain ? 'true' : 'false'\n\t\t\t\t\t)\n\t\t\t\t\tif (overflowItem) {\n\t\t\t\t\t\tassert(overflowItem.type === 'item')\n\t\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\t\toverflowItem.element,\n\t\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\t\tshouldShowInOverflow ? 'true' : 'false'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif (shouldShowInOverflow && mainItem.element.getAttribute('aria-pressed') === 'true') {\n\t\t\t\t\t\tnewActiveOverflowItem = mainItem.element.getAttribute('data-value')\n\t\t\t\t\t}\n\t\t\t\t\tif (shouldShowInMain && mainItem.element.tagName === 'BUTTON') {\n\t\t\t\t\t\tnumberedButtons.push(mainItem.element as HTMLButtonElement)\n\t\t\t\t\t}\n\t\t\t\t\tif (!shouldShowInOverflow && isLastActiveOverflowItem) {\n\t\t\t\t\t\tshouldInvalidateLastActiveOverflowItem = true\n\t\t\t\t\t}\n\t\t\t\t\tmainItemCount++\n\t\t\t\t} else {\n\t\t\t\t\t// for groups, we show them in main if we have space, or if they're the\n\t\t\t\t\t// last-used item from the overflow.\n\t\t\t\t\tlet result, overflowGroup\n\t\t\t\t\tif (overflowItem) {\n\t\t\t\t\t\tassert(overflowItem.type === 'group')\n\t\t\t\t\t\toverflowGroup = overflowItem\n\t\t\t\t\t\tresult = visitItems(mainItem.items, overflowGroup.items)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = visitItems(mainItem.items, null)\n\t\t\t\t\t}\n\n\t\t\t\t\tdidShowAnyInMain ||= result.didShowAnyInMain\n\t\t\t\t\tdidShowAnyInOverflow ||= result.didShowAnyInOverflow\n\n\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\tmainItem.element,\n\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\tresult.didShowAnyInMain ? 'true' : 'false'\n\t\t\t\t\t)\n\t\t\t\t\tif (overflowGroup) {\n\t\t\t\t\t\tsetAttribute(\n\t\t\t\t\t\t\toverflowGroup.element,\n\t\t\t\t\t\t\t'data-toolbar-visible',\n\t\t\t\t\t\t\tresult.didShowAnyInOverflow ? 'true' : 'false'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { didShowAnyInMain, didShowAnyInOverflow }\n\t\t}\n\n\t\tconst { didShowAnyInOverflow } = visitItems(mainItems, overflowItems)\n\t\tsetShouldShowOverflow(didShowAnyInOverflow)\n\t\tif (newActiveOverflowItem) {\n\t\t\tsetLastActiveOverflowItem(newActiveOverflowItem)\n\t\t} else if (shouldInvalidateLastActiveOverflowItem) {\n\t\t\tsetLastActiveOverflowItem(null)\n\t\t}\n\n\t\trButtons.current = numberedButtons\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tonDomUpdate()\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tif (!mainToolsRef.current) return\n\n\t\tconst mutationObserver = new MutationObserver(onDomUpdate)\n\t\tmutationObserver.observe(mainToolsRef.current, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tattributes: true,\n\t\t\tcharacterData: true,\n\t\t})\n\n\t\tconst sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)\n\t\tconst resizeObserver = new ResizeObserver(onDomUpdate)\n\t\tresizeObserver.observe(sizingParent)\n\n\t\treturn () => {\n\t\t\tmutationObserver.disconnect()\n\t\t\tresizeObserver.disconnect()\n\t\t}\n\t}, [onDomUpdate, sizingParentClassName])\n\n\tuseEffect(() => {\n\t\tif (!editor.options.enableToolbarKeyboardShortcuts) return\n\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (\n\t\t\t\tareShortcutsDisabled(editor) ||\n\t\t\t\tactiveElementShouldCaptureKeys(true /* allow buttons */)\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// no accelerator keys\n\t\t\tif (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return\n\t\t\tconst index = NUMBERED_SHORTCUT_KEYS[event.key]\n\t\t\tif (typeof index === 'number') {\n\t\t\t\tpreventDefault(event)\n\t\t\t\trButtons.current[index]?.click()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeyDown)\n\t\t}\n\t}, [editor])\n\n\tconst popoverId = 'toolbar overflow'\n\n\tconst Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiToolbar\n\t\t\t\torientation={orientation}\n\t\t\t\tclassName={classNames('tlui-main-toolbar__tools', {\n\t\t\t\t\t'tlui-main-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t\t})}\n\t\t\t\tlabel={msg('tool-panel.title')}\n\t\t\t>\n\t\t\t\t<Layout id={`${id}_main`} ref={mainToolsRef}>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"toolbar\" sourceId=\"toolbar\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t</Layout>\n\t\t\t\t{shouldShowOverflow && (\n\t\t\t\t\t<IsInOverflowContext.Provider value={true}>\n\t\t\t\t\t\t<TldrawUiPopover id={popoverId} open={isOpen} onOpenChange={setIsOpen}>\n\t\t\t\t\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\t\t\t\t\ttitle={msg('tool-panel.more')}\n\t\t\t\t\t\t\t\t\ttype=\"tool\"\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-main-toolbar__overflow\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"tools.more-button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TldrawUiButtonIcon\n\t\t\t\t\t\t\t\t\t\ticon={orientation === 'horizontal' ? 'chevron-up' : 'chevron-right'}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t\t\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t\t\t\t\t<TldrawUiPopoverContent\n\t\t\t\t\t\t\t\tside={orientation === 'horizontal' ? 'top' : 'right'}\n\t\t\t\t\t\t\t\talign={orientation === 'horizontal' ? 'center' : 'end'}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<TldrawUiToolbar\n\t\t\t\t\t\t\t\t\torientation=\"grid\"\n\t\t\t\t\t\t\t\t\tclassName=\"tlui-main-toolbar__overflow-content\"\n\t\t\t\t\t\t\t\t\tref={setOverflowTools}\n\t\t\t\t\t\t\t\t\tdata-testid=\"tools.more-content\"\n\t\t\t\t\t\t\t\t\tlabel={msg('tool-panel.more')}\n\t\t\t\t\t\t\t\t\tid={`${id}_more`}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\ttlmenus.deleteOpenMenu(popoverId, editor.contextId)\n\t\t\t\t\t\t\t\t\t\tsetIsOpen(false)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TldrawUiMenuContextProvider type=\"toolbar-overflow\" sourceId=\"toolbar\">\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t\t\t\t\t</TldrawUiToolbar>\n\t\t\t\t\t\t\t</TldrawUiPopoverContent>\n\t\t\t\t\t\t</TldrawUiPopover>\n\t\t\t\t\t</IsInOverflowContext.Provider>\n\t\t\t\t)}\n\t\t\t</TldrawUiToolbar>\n\t\t</>\n\t)\n}\n\nexport const isActiveTLUiToolItem = (\n\titem: TLUiToolItem,\n\tactiveToolId: string | undefined,\n\tgeoState: string | null | undefined\n) => {\n\treturn item.meta?.geo\n\t\t? activeToolId === 'geo' && geoState === item.meta?.geo\n\t\t: activeToolId === item.id\n}\n\nfunction findParentWithClassName(startingElement: HTMLElement, className: string): HTMLElement {\n\tlet element: HTMLElement | null = startingElement\n\twhile (element) {\n\t\tif (element.classList.contains(className)) {\n\t\t\treturn element\n\t\t}\n\t\telement = element.parentElement\n\t}\n\tthrow new Error('Could not find parent with class name ' + className)\n}\n\nfunction setAttribute(element: HTMLElement, name: string, value: string) {\n\tif (element.getAttribute(name) === value) return\n\telement.setAttribute(name, value)\n}\n"],
5
+ "mappings": "AA8RE,mBASG,KAMC,YAfJ;AA9RF;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,OAAO,gBAAgB;AACvB,SAAS,eAAe,WAAW,iBAAiB,QAAQ,gBAAgB;AAC5E,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AAErC,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB,6BAA6B;AACvD,SAAS,gBAAgB,mBAAmB;AAC5C,SAAS,mCAAmC;AAErC,MAAM,sBAAsB,cAAc,KAAK;AAEtD,MAAM,yBAAiD;AAAA,EACtD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACN;AAcO,SAAS,mBAAmB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAA4B;AAC3B,QAAM,SAAS,UAAU;AACzB,QAAM,KAAK,gBAAgB;AAC3B,QAAM,aAAa,cAAc;AACjC,QAAM,MAAM,eAAe;AAC3B,QAAM,WAAW,OAAsB,CAAC,CAAC;AACzC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,QAAM,eAAe,OAAuB,IAAI;AAIhD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAgC,IAAI;AAC9E,QAAM,CAAC,wBAAwB,yBAAyB,IAAI,SAAwB,IAAI;AACxF,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,KAAK;AAElE,QAAM,cAAc,SAAS,MAAM;AAClC,QAAI,CAAC,aAAa,QAAS;AAI3B,UAAM,WAAW,gBAAgB,eAAe,gBAAgB;AAShE,UAAM,YAAY,aAAa,aAAa,QAAQ,QAAQ;AAC5D,UAAM,gBAAgB,gBAAgB,aAAa,cAAc,QAAQ,IAAI;AAC7E,aAAS,aAAa,YAA4B;AACjD,YAAM,QAAe,CAAC;AACtB,iBAAW,SAAS,YAAY;AAC/B,YAAI,MAAM,UAAU,SAAS,0BAA0B,GAAG;AACzD,gBAAM,KAAK;AAAA,YACV,MAAM;AAAA,YACN,OAAO,aAAa,MAAM,QAAQ;AAAA,YAClC,SAAS;AAAA,UACV,CAAC;AAAA,QACF,WAAW,CAAC,MAAM,aAAa,mCAAmC,GAAG;AACpE,gBAAM,KAAK,EAAE,MAAM,QAAQ,SAAS,MAAqB,CAAC;AAAA,QAC3D;AAAA,MACD;AAEA,aAAO;AAAA,IACR;AAGA,UAAM,eAAe,wBAAwB,aAAa,SAAS,qBAAqB;AACxF,UAAM,OAAO,aAAa,QAAQ;AAClC,UAAM,cAAc,KAAK;AAAA,MACxB,SAAS,MAAM,CAAC,WAAW,SAAS,GAAG,CAAC,UAAU,QAAQ,GAAG,IAAI;AAAA,IAClE;AAKA,QAAI,gBAAgB;AAEpB,QAAI,wBAAuC;AAE3C,QAAI,yCAAyC;AAE7C,UAAM,kBAAuC,CAAC;AAC9C,aAAS,WACRA,YACAC,gBAMC;AACD,UAAIA,eAAe,QAAOD,WAAU,WAAWC,eAAc,MAAM;AAEnE,UAAI,mBAAmB;AACvB,UAAIC,wBAAuB;AAE3B,eAAS,IAAI,GAAG,IAAIF,WAAU,QAAQ,KAAK;AAC1C,cAAM,WAAWA,WAAU,CAAC;AAC5B,cAAM,eAAeC,iBAAgB,CAAC;AAEtC,YAAI,SAAS,SAAS,QAAQ;AAC7B,gBAAM,2BACL,SAAS,QAAQ,aAAa,YAAY,MAAM;AAIjD,cAAI;AACJ,cAAI,wBAAwB;AAC3B,+BAAmB,gBAAgB,eAAe;AAAA,UACnD,OAAO;AAGN,+BAAmB,iBAAiB;AAAA,UACrC;AACA,gBAAM,uBAAuB,iBAAiB;AAE9C,+BAAqB;AACrB,UAAAC,0BAAyB;AAEzB;AAAA,YACC,SAAS;AAAA,YACT;AAAA,YACA,mBAAmB,SAAS;AAAA,UAC7B;AACA,cAAI,cAAc;AACjB,mBAAO,aAAa,SAAS,MAAM;AACnC;AAAA,cACC,aAAa;AAAA,cACb;AAAA,cACA,uBAAuB,SAAS;AAAA,YACjC;AAAA,UACD;AACA,cAAI,wBAAwB,SAAS,QAAQ,aAAa,cAAc,MAAM,QAAQ;AACrF,oCAAwB,SAAS,QAAQ,aAAa,YAAY;AAAA,UACnE;AACA,cAAI,oBAAoB,SAAS,QAAQ,YAAY,UAAU;AAC9D,4BAAgB,KAAK,SAAS,OAA4B;AAAA,UAC3D;AACA,cAAI,CAAC,wBAAwB,0BAA0B;AACtD,qDAAyC;AAAA,UAC1C;AACA;AAAA,QACD,OAAO;AAGN,cAAI,QAAQ;AACZ,cAAI,cAAc;AACjB,mBAAO,aAAa,SAAS,OAAO;AACpC,4BAAgB;AAChB,qBAAS,WAAW,SAAS,OAAO,cAAc,KAAK;AAAA,UACxD,OAAO;AACN,qBAAS,WAAW,SAAS,OAAO,IAAI;AAAA,UACzC;AAEA,+BAAqB,OAAO;AAC5B,UAAAA,0BAAyB,OAAO;AAEhC;AAAA,YACC,SAAS;AAAA,YACT;AAAA,YACA,OAAO,mBAAmB,SAAS;AAAA,UACpC;AACA,cAAI,eAAe;AAClB;AAAA,cACC,cAAc;AAAA,cACd;AAAA,cACA,OAAO,uBAAuB,SAAS;AAAA,YACxC;AAAA,UACD;AAAA,QACD;AAAA,MACD;AACA,aAAO,EAAE,kBAAkB,sBAAAA,sBAAqB;AAAA,IACjD;AAEA,UAAM,EAAE,qBAAqB,IAAI,WAAW,WAAW,aAAa;AACpE,0BAAsB,oBAAoB;AAC1C,QAAI,uBAAuB;AAC1B,gCAA0B,qBAAqB;AAAA,IAChD,WAAW,wCAAwC;AAClD,gCAA0B,IAAI;AAAA,IAC/B;AAEA,aAAS,UAAU;AAAA,EACpB,CAAC;AAED,kBAAgB,MAAM;AACrB,gBAAY;AAAA,EACb,CAAC;AAED,kBAAgB,MAAM;AACrB,QAAI,CAAC,aAAa,QAAS;AAE3B,UAAM,mBAAmB,IAAI,iBAAiB,WAAW;AACzD,qBAAiB,QAAQ,aAAa,SAAS;AAAA,MAC9C,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,eAAe;AAAA,IAChB,CAAC;AAED,UAAM,eAAe,wBAAwB,aAAa,SAAS,qBAAqB;AACxF,UAAM,iBAAiB,IAAI,eAAe,WAAW;AACrD,mBAAe,QAAQ,YAAY;AAEnC,WAAO,MAAM;AACZ,uBAAiB,WAAW;AAC5B,qBAAe,WAAW;AAAA,IAC3B;AAAA,EACD,GAAG,CAAC,aAAa,qBAAqB,CAAC;AAEvC,YAAU,MAAM;AACf,QAAI,CAAC,OAAO,QAAQ,+BAAgC;AAEpD,aAAS,cAAc,OAAsB;AAC5C,UACC,qBAAqB,MAAM,KAC3B;AAAA,QAA+B;AAAA;AAAA,MAAwB,GACtD;AACD;AAAA,MACD;AAGA,UAAI,MAAM,WAAW,MAAM,WAAW,MAAM,UAAU,MAAM,SAAU;AACtE,YAAM,QAAQ,uBAAuB,MAAM,GAAG;AAC9C,UAAI,OAAO,UAAU,UAAU;AAC9B,uBAAe,KAAK;AACpB,iBAAS,QAAQ,KAAK,GAAG,MAAM;AAAA,MAChC;AAAA,IACD;AAEA,aAAS,iBAAiB,WAAW,aAAa;AAClD,WAAO,MAAM;AACZ,eAAS,oBAAoB,WAAW,aAAa;AAAA,IACtD;AAAA,EACD,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAY;AAElB,QAAM,SAAS,gBAAgB,eAAe,cAAc;AAC5D,SACC,gCACC;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAW,WAAW,4BAA4B;AAAA,QACjD,oCAAoC,aAAa,oBAAoB;AAAA,MACtE,CAAC;AAAA,MACD,OAAO,IAAI,kBAAkB;AAAA,MAE7B;AAAA,4BAAC,UAAO,IAAI,GAAG,EAAE,SAAS,KAAK,cAC9B,8BAAC,+BAA4B,MAAK,WAAU,UAAS,WACnD,UACF,GACD;AAAA,QACC,sBACA,oBAAC,oBAAoB,UAApB,EAA6B,OAAO,MACpC,+BAAC,mBAAgB,IAAI,WAAW,MAAM,QAAQ,cAAc,WAC3D;AAAA,8BAAC,0BACA;AAAA,YAAC;AAAA;AAAA,cACA,OAAO,IAAI,iBAAiB;AAAA,cAC5B,MAAK;AAAA,cACL,WAAU;AAAA,cACV,eAAY;AAAA,cAEZ;AAAA,gBAAC;AAAA;AAAA,kBACA,MAAM,gBAAgB,eAAe,eAAe;AAAA;AAAA,cACrD;AAAA;AAAA,UACD,GACD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACA,MAAM,gBAAgB,eAAe,QAAQ;AAAA,cAC7C,OAAO,gBAAgB,eAAe,WAAW;AAAA,cAEjD;AAAA,gBAAC;AAAA;AAAA,kBACA,aAAY;AAAA,kBACZ,WAAU;AAAA,kBACV,KAAK;AAAA,kBACL,eAAY;AAAA,kBACZ,OAAO,IAAI,iBAAiB;AAAA,kBAC5B,IAAI,GAAG,EAAE;AAAA,kBACT,SAAS,MAAM;AACd,4BAAQ,eAAe,WAAW,OAAO,SAAS;AAClD,8BAAU,KAAK;AAAA,kBAChB;AAAA,kBAEA,8BAAC,+BAA4B,MAAK,oBAAmB,UAAS,WAC5D,UACF;AAAA;AAAA,cACD;AAAA;AAAA,UACD;AAAA,WACD,GACD;AAAA;AAAA;AAAA,EAEF,GACD;AAEF;AAEO,MAAM,uBAAuB,CACnC,MACA,cACA,aACI;AACJ,SAAO,KAAK,MAAM,MACf,iBAAiB,SAAS,aAAa,KAAK,MAAM,MAClD,iBAAiB,KAAK;AAC1B;AAEA,SAAS,wBAAwB,iBAA8B,WAAgC;AAC9F,MAAI,UAA8B;AAClC,SAAO,SAAS;AACf,QAAI,QAAQ,UAAU,SAAS,SAAS,GAAG;AAC1C,aAAO;AAAA,IACR;AACA,cAAU,QAAQ;AAAA,EACnB;AACA,QAAM,IAAI,MAAM,2CAA2C,SAAS;AACrE;AAEA,SAAS,aAAa,SAAsB,MAAc,OAAe;AACxE,MAAI,QAAQ,aAAa,IAAI,MAAM,MAAO;AAC1C,UAAQ,aAAa,MAAM,KAAK;AACjC;",
6
6
  "names": ["mainItems", "overflowItems", "didShowAnyInOverflow"]
7
7
  }
@@ -2,8 +2,10 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { useEditor, useValue } from "@tldraw/editor";
3
3
  import classNames from "classnames";
4
4
  import { PORTRAIT_BREAKPOINT } from "../../constants.mjs";
5
+ import { useActions } from "../../context/actions.mjs";
5
6
  import { useBreakpoint } from "../../context/breakpoints.mjs";
6
7
  import { useTranslation } from "../../hooks/useTranslation/useTranslation.mjs";
8
+ import { kbdStr } from "../../kbd-utils.mjs";
7
9
  import { TldrawUiButton } from "../primitives/Button/TldrawUiButton.mjs";
8
10
  import { TldrawUiButtonIcon } from "../primitives/Button/TldrawUiButtonIcon.mjs";
9
11
  import { TldrawUiTooltip } from "../primitives/TldrawUiTooltip.mjs";
@@ -11,16 +13,18 @@ function ToggleToolLockedButton({ activeToolId }) {
11
13
  const editor = useEditor();
12
14
  const breakpoint = useBreakpoint();
13
15
  const msg = useTranslation();
16
+ const actions = useActions();
14
17
  const isToolLocked = useValue("is tool locked", () => editor.getInstanceState().isToolLocked, [
15
18
  editor
16
19
  ]);
17
20
  const tool = useValue("current tool", () => editor.getCurrentTool(), [editor]);
18
21
  if (!activeToolId || !tool.isLockable) return null;
19
- return /* @__PURE__ */ jsx(TldrawUiTooltip, { content: msg("action.toggle-tool-lock"), children: /* @__PURE__ */ jsx(
22
+ const toggleLockAction = actions["toggle-tool-lock"];
23
+ const tooltipContent = toggleLockAction?.kbd ? `${msg("action.toggle-tool-lock")} ${kbdStr(toggleLockAction.kbd)}` : msg("action.toggle-tool-lock");
24
+ return /* @__PURE__ */ jsx(TldrawUiTooltip, { content: tooltipContent, children: /* @__PURE__ */ jsx(
20
25
  TldrawUiButton,
21
26
  {
22
27
  type: "normal",
23
- title: msg("action.toggle-tool-lock"),
24
28
  "data-testid": "tool-lock",
25
29
  className: classNames("tlui-main-toolbar__lock-button", {
26
30
  "tlui-main-toolbar__lock-button__mobile": breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx"],
4
- "sourcesContent": ["import { useEditor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from '../primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'\n\n/** @public */\nexport interface ToggleToolLockedButtonProps {\n\tactiveToolId?: string\n}\n\n/** @public @react */\nexport function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonProps) {\n\tconst editor = useEditor()\n\tconst breakpoint = useBreakpoint()\n\tconst msg = useTranslation()\n\n\tconst isToolLocked = useValue('is tool locked', () => editor.getInstanceState().isToolLocked, [\n\t\teditor,\n\t])\n\tconst tool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tif (!activeToolId || !tool.isLockable) return null\n\n\treturn (\n\t\t<TldrawUiTooltip content={msg('action.toggle-tool-lock')}>\n\t\t\t<TldrawUiButton\n\t\t\t\ttype=\"normal\"\n\t\t\t\ttitle={msg('action.toggle-tool-lock')}\n\t\t\t\tdata-testid=\"tool-lock\"\n\t\t\t\tclassName={classNames('tlui-main-toolbar__lock-button', {\n\t\t\t\t\t'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t\t})}\n\t\t\t\tonClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}\n\t\t\t>\n\t\t\t\t<TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />\n\t\t\t</TldrawUiButton>\n\t\t</TldrawUiTooltip>\n\t)\n}\n"],
5
- "mappings": "AAsCI;AAtCJ,SAAS,WAAW,gBAAgB;AACpC,OAAO,gBAAgB;AACvB,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAQzB,SAAS,uBAAuB,EAAE,aAAa,GAAgC;AACrF,QAAM,SAAS,UAAU;AACzB,QAAM,aAAa,cAAc;AACjC,QAAM,MAAM,eAAe;AAE3B,QAAM,eAAe,SAAS,kBAAkB,MAAM,OAAO,iBAAiB,EAAE,cAAc;AAAA,IAC7F;AAAA,EACD,CAAC;AACD,QAAM,OAAO,SAAS,gBAAgB,MAAM,OAAO,eAAe,GAAG,CAAC,MAAM,CAAC;AAE7E,MAAI,CAAC,gBAAgB,CAAC,KAAK,WAAY,QAAO;AAE9C,SACC,oBAAC,mBAAgB,SAAS,IAAI,yBAAyB,GACtD;AAAA,IAAC;AAAA;AAAA,MACA,MAAK;AAAA,MACL,OAAO,IAAI,yBAAyB;AAAA,MACpC,eAAY;AAAA,MACZ,WAAW,WAAW,kCAAkC;AAAA,QACvD,0CAA0C,aAAa,oBAAoB;AAAA,MAC5E,CAAC;AAAA,MACD,SAAS,MAAM,OAAO,oBAAoB,EAAE,cAAc,CAAC,aAAa,CAAC;AAAA,MAEzE,8BAAC,sBAAmB,MAAM,eAAe,SAAS,UAAU,OAAK,MAAC;AAAA;AAAA,EACnE,GACD;AAEF;",
4
+ "sourcesContent": ["import { useEditor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useActions } from '../../context/actions'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { kbdStr } from '../../kbd-utils'\nimport { TldrawUiButton } from '../primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'\n\n/** @public */\nexport interface ToggleToolLockedButtonProps {\n\tactiveToolId?: string\n}\n\n/** @public @react */\nexport function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonProps) {\n\tconst editor = useEditor()\n\tconst breakpoint = useBreakpoint()\n\tconst msg = useTranslation()\n\tconst actions = useActions()\n\n\tconst isToolLocked = useValue('is tool locked', () => editor.getInstanceState().isToolLocked, [\n\t\teditor,\n\t])\n\tconst tool = useValue('current tool', () => editor.getCurrentTool(), [editor])\n\n\tif (!activeToolId || !tool.isLockable) return null\n\n\tconst toggleLockAction = actions['toggle-tool-lock']\n\tconst tooltipContent = toggleLockAction?.kbd\n\t\t? `${msg('action.toggle-tool-lock')} ${kbdStr(toggleLockAction.kbd)}`\n\t\t: msg('action.toggle-tool-lock')\n\n\treturn (\n\t\t<TldrawUiTooltip content={tooltipContent}>\n\t\t\t<TldrawUiButton\n\t\t\t\ttype=\"normal\"\n\t\t\t\tdata-testid=\"tool-lock\"\n\t\t\t\tclassName={classNames('tlui-main-toolbar__lock-button', {\n\t\t\t\t\t'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t\t})}\n\t\t\t\tonClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}\n\t\t\t>\n\t\t\t\t<TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />\n\t\t\t</TldrawUiButton>\n\t\t</TldrawUiTooltip>\n\t)\n}\n"],
5
+ "mappings": "AA6CI;AA7CJ,SAAS,WAAW,gBAAgB;AACpC,OAAO,gBAAgB;AACvB,SAAS,2BAA2B;AACpC,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAQzB,SAAS,uBAAuB,EAAE,aAAa,GAAgC;AACrF,QAAM,SAAS,UAAU;AACzB,QAAM,aAAa,cAAc;AACjC,QAAM,MAAM,eAAe;AAC3B,QAAM,UAAU,WAAW;AAE3B,QAAM,eAAe,SAAS,kBAAkB,MAAM,OAAO,iBAAiB,EAAE,cAAc;AAAA,IAC7F;AAAA,EACD,CAAC;AACD,QAAM,OAAO,SAAS,gBAAgB,MAAM,OAAO,eAAe,GAAG,CAAC,MAAM,CAAC;AAE7E,MAAI,CAAC,gBAAgB,CAAC,KAAK,WAAY,QAAO;AAE9C,QAAM,mBAAmB,QAAQ,kBAAkB;AACnD,QAAM,iBAAiB,kBAAkB,MACtC,GAAG,IAAI,yBAAyB,CAAC,IAAI,OAAO,iBAAiB,GAAG,CAAC,KACjE,IAAI,yBAAyB;AAEhC,SACC,oBAAC,mBAAgB,SAAS,gBACzB;AAAA,IAAC;AAAA;AAAA,MACA,MAAK;AAAA,MACL,eAAY;AAAA,MACZ,WAAW,WAAW,kCAAkC;AAAA,QACvD,0CAA0C,aAAa,oBAAoB;AAAA,MAC5E,CAAC;AAAA,MACD,SAAS,MAAM,OAAO,oBAAoB,EAAE,cAAc,CAAC,aAAa,CAAC;AAAA,MAEzE,8BAAC,sBAAmB,MAAM,eAAe,SAAS,UAAU,OAAK,MAAC;AAAA;AAAA,EACnE,GACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import {
3
3
  assert,
4
4
  Box,
5
5
  clamp,
6
- markEventAsHandled,
7
6
  react,
8
7
  useAtom,
9
8
  useEditor,
@@ -114,7 +113,7 @@ const TldrawUiContextualToolbar = ({
114
113
  "data-visible": false,
115
114
  "data-testid": "contextual-toolbar",
116
115
  className: classNames("tlui-contextual-toolbar", className),
117
- onPointerDown: markEventAsHandled,
116
+ onPointerDown: editor.markEventAsHandled,
118
117
  children: /* @__PURE__ */ jsx(
119
118
  TldrawUiToolbar,
120
119
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx"],
4
- "sourcesContent": ["import {\n\tassert,\n\tBox,\n\tclamp,\n\tEditor,\n\tmarkEventAsHandled,\n\treact,\n\tuseAtom,\n\tuseEditor,\n\tusePassThroughMouseOverEvents,\n\tusePassThroughWheelEvents,\n\tuseValue,\n\tVec,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { RefObject, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { TldrawUiToolbar } from './TldrawUiToolbar'\n\nconst MOVE_TIMEOUT = 150\nconst HIDE_VISIBILITY_TIMEOUT = 16\nconst SHOW_VISIBILITY_TIMEOUT = 16\nconst MIN_DISTANCE_TO_REPOSITION_SQUARED = 16 ** 2\nconst TOOLBAR_GAP = 8\nconst SCREEN_MARGIN = 16\nconst HIDE_TOOLBAR_WHEN_CAMERA_IS_MOVING = false\nconst LEFT_ALIGN_TOOLBAR = false\n\n/** @public */\nexport interface TLUiContextualToolbarProps {\n\tchildren?: React.ReactNode\n\tclassName?: string\n\tisMousingDown?: boolean\n\tgetSelectionBounds(): Box | undefined\n\tchangeOnlyWhenYChanges?: boolean\n\tlabel: string\n}\n\n/**\n * A generic floating toolbar that can be used for things\n * like rich text editing, image toolbars, etc.\n *\n * @public @react\n */\nexport const TldrawUiContextualToolbar = ({\n\tchildren,\n\tclassName,\n\tisMousingDown,\n\tgetSelectionBounds,\n\tchangeOnlyWhenYChanges = false,\n\tlabel,\n}: TLUiContextualToolbarProps) => {\n\tconst editor = useEditor()\n\tconst toolbarRef = useRef<HTMLDivElement>(null)\n\n\tusePassThroughWheelEvents(toolbarRef as RefObject<HTMLDivElement>)\n\tusePassThroughMouseOverEvents(toolbarRef as RefObject<HTMLDivElement>)\n\n\tconst { isVisible, isInteractive, hide, show, position, move } =\n\t\tuseToolbarVisibilityStateMachine(changeOnlyWhenYChanges)\n\n\t// annoying react stuff: we don't want the toolbar position function to depend on the react state so we'll double with a ref\n\tconst rCouldShowToolbar = useRef(false)\n\tconst [hasValidToolbarPosition, setHasValidToolbarPosition] = useState(false)\n\n\tconst contentSizeUpdateCounter = useAtom('content size update counter', 0)\n\n\tuseEffect(() => {\n\t\tassert(toolbarRef.current)\n\t\tconst observer = new ResizeObserver(() => {\n\t\t\tcontentSizeUpdateCounter.update((n) => n + 1)\n\t\t})\n\t\tobserver.observe(toolbarRef.current)\n\t\treturn () => observer.disconnect()\n\t}, [contentSizeUpdateCounter])\n\n\tuseEffect(() => {\n\t\tlet lastContentSizeUpdateCounter = contentSizeUpdateCounter.get()\n\t\treturn react('toolbar position', function updateToolbarPositionAndDisplay() {\n\t\t\tconst toolbarElm = toolbarRef.current\n\t\t\tif (!toolbarElm) return\n\n\t\t\tconst nextContentSizeUpdateCounter = contentSizeUpdateCounter.get()\n\n\t\t\t// capture / force this to update when...\n\t\t\teditor.getCamera() // the camera moves\n\t\t\tcontentSizeUpdateCounter.get() // the toolbar size changes\n\t\t\t// undefined here means that we can't show the toolbar due to an incompatible position\n\t\t\tconst position = getToolbarScreenPosition(editor, toolbarElm, getSelectionBounds)\n\n\t\t\t// todo: when the toolbar is hidden due to the selection being off screen, it should be hidden immediately\n\t\t\t// rather than waiting for the position to settle. This is different than when the position changes due to\n\t\t\t// a change in the user's selection.\n\t\t\tif (!position) {\n\t\t\t\tif (rCouldShowToolbar.current) {\n\t\t\t\t\t// If we don't have a position, then we're not showing the toolbar\n\t\t\t\t\trCouldShowToolbar.current = false\n\t\t\t\t\tsetHasValidToolbarPosition(false)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If the camera state is moving, we want to immediately update the position\n\t\t\t\t// todo: consider hiding the toolbar while the camera is moving\n\t\t\t\tconst cameraState = editor.getCameraState()\n\t\t\t\tif (cameraState === 'moving') {\n\t\t\t\t\t// ...if we wanted this to avoid prematurely updating any positions, we'd need\n\t\t\t\t\t// to have the last updated position in page space, so that we could convert\n\t\t\t\t\t// it to screen space and update it here\n\t\t\t\t\tconst elm = toolbarRef.current\n\t\t\t\t\telm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)\n\t\t\t\t} else {\n\t\t\t\t\tconst moveImmediately = lastContentSizeUpdateCounter !== nextContentSizeUpdateCounter\n\t\t\t\t\t// Schedule a move to its next location\n\t\t\t\t\tmove(position.x, position.y, moveImmediately)\n\t\t\t\t}\n\n\t\t\t\t// Finally, if the toolbar was previously hidden, show it again\n\t\t\t\tif (!rCouldShowToolbar.current) {\n\t\t\t\t\trCouldShowToolbar.current = true\n\t\t\t\t\tsetHasValidToolbarPosition(true)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlastContentSizeUpdateCounter = nextContentSizeUpdateCounter\n\t\t})\n\t}, [editor, getSelectionBounds, contentSizeUpdateCounter, move])\n\n\tconst cameraState = useValue('camera state', () => editor.getCameraState(), [editor])\n\n\t// Send the hide or show events based on whether the user is clicking\n\t// and whether the toolbar's position is valid\n\tuseEffect(() => {\n\t\tif (cameraState === 'moving' && HIDE_TOOLBAR_WHEN_CAMERA_IS_MOVING) {\n\t\t\thide(true)\n\t\t\treturn\n\t\t}\n\n\t\tif (isMousingDown || !hasValidToolbarPosition) {\n\t\t\thide()\n\t\t\treturn\n\t\t}\n\n\t\tshow()\n\t}, [hasValidToolbarPosition, cameraState, isMousingDown, show, hide])\n\n\t// When the visibility changes, update the toolbar's visibility\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.dataset.visible = `${isVisible}`\n\t}, [isVisible, position])\n\n\t// When the position changes, update the toolbar's position on screen\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)\n\t}, [position])\n\n\t// When the interactivity changes, update the toolbar's interactivity\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.dataset.interactive = `${isInteractive}`\n\t}, [isInteractive])\n\n\treturn (\n\t\t<div\n\t\t\tref={toolbarRef}\n\t\t\tdata-interactive={false}\n\t\t\tdata-visible={false}\n\t\t\tdata-testid=\"contextual-toolbar\"\n\t\t\tclassName={classNames('tlui-contextual-toolbar', className)}\n\t\t\tonPointerDown={markEventAsHandled}\n\t\t>\n\t\t\t<TldrawUiToolbar\n\t\t\t\torientation=\"horizontal\"\n\t\t\t\tclassName=\"tlui-menu\"\n\t\t\t\tlabel={label}\n\t\t\t\ttooltipSide=\"top\"\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</TldrawUiToolbar>\n\t\t</div>\n\t)\n}\n\n// For convenience, let's work just with boxes here\n/** @internal */\nexport function rectToBox(rect: DOMRect): Box {\n\treturn new Box(rect.x, rect.y, rect.width, rect.height)\n}\n\nexport function getToolbarScreenPosition(\n\teditor: Editor,\n\ttoolbarElm: HTMLElement,\n\tgetSelectionBounds: () => Box | undefined\n) {\n\tconst selectionBounds = getSelectionBounds()?.clone()\n\tif (!selectionBounds) return\n\n\t// Offset the selection bounds by the viewport screen bounds (if the editor is scrolled or inset, etc)\n\tconst vsb = editor.getViewportScreenBounds()\n\tselectionBounds.x -= vsb.x\n\tselectionBounds.y -= vsb.y\n\n\t// If the selection bounds are too far off of the screen, don't show the toolbar\n\tif (\n\t\tselectionBounds.midY < SCREEN_MARGIN ||\n\t\tselectionBounds.midY > vsb.h - SCREEN_MARGIN ||\n\t\tselectionBounds.midX < SCREEN_MARGIN ||\n\t\tselectionBounds.midX > vsb.w - SCREEN_MARGIN\n\t) {\n\t\treturn\n\t}\n\n\t// Get the toolbar's screen rect as a box. Do this after we verify that there is at least one selection.\n\tconst toolbarBounds = rectToBox(toolbarElm.getBoundingClientRect())\n\n\t// Chance these are NaN? Rare case.\n\tif (!toolbarBounds.width || !toolbarBounds.height) return\n\n\t// Thrashy, only do this if we're showing the toolbar\n\t// ! this might not be needed, the container never scrolls\n\tconst { scrollLeft, scrollTop } = editor.getContainer()\n\n\t// We want to position the toolbar so that it is centered over the selection\n\t// except in the cases where it would extend off the edge of the screen.\n\n\t// Start by placing the top left corner of the toolbar so that the\n\t// toolbar would be centered above the section bounds, bumped up by the\n\n\tlet x = LEFT_ALIGN_TOOLBAR ? selectionBounds.x : selectionBounds.midX - toolbarBounds.w / 2\n\tlet y = selectionBounds.y - toolbarBounds.h - TOOLBAR_GAP\n\n\t// Clamp the position on screen.\n\tx = clamp(x, SCREEN_MARGIN, vsb.w - toolbarBounds.w - SCREEN_MARGIN)\n\ty = clamp(y, SCREEN_MARGIN, vsb.h - toolbarBounds.h - SCREEN_MARGIN)\n\n\t// Offset the position by the container's scroll position\n\tx += scrollLeft\n\ty += scrollTop\n\n\t// Round the position to the nearest pixel\n\tx = Math.round(x)\n\ty = Math.round(y)\n\n\treturn { x, y }\n}\n\nfunction sufficientlyDistant(curr: Vec, next: Vec, changeOnlyWhenYChanges: boolean) {\n\tif (changeOnlyWhenYChanges) {\n\t\treturn Vec.Sub(next, curr).y ** 2 >= MIN_DISTANCE_TO_REPOSITION_SQUARED\n\t}\n\treturn Vec.Len2(Vec.Sub(next, curr)) >= MIN_DISTANCE_TO_REPOSITION_SQUARED\n}\n\nexport function useToolbarVisibilityStateMachine(changeOnlyWhenYChanges: boolean) {\n\tconst editor = useEditor()\n\n\tconst rState = useRef<\n\t\t{ name: 'hidden' } | { name: 'showing' } | { name: 'shown' } | { name: 'hiding' }\n\t>({ name: 'hidden' })\n\n\t// The toolbar should only be interactive when in the 'shown' state\n\tconst [isInteractive, setIsInteractive] = useState(false)\n\n\t// The toolbar is visible in the 'shown' and 'hiding' states\n\tconst [isVisible, setIsVisible] = useState(false)\n\n\t// The position is updated when entering the 'shown' state or when moving while in the 'shown' state\n\tconst [position, setPosition] = useState({ x: -1000, y: -1000 })\n\n\t// The toolbar's current position\n\tconst rCurrPosition = useRef(new Vec(-1000, -1000))\n\n\t// The toolbar's proposed next position\n\tconst rNextPosition = useRef(new Vec(-1000, -1000))\n\n\t// A timeout needs to be completed before the toolbar is shown or hidden\n\tconst rStableVisibilityTimeout = useRef<any>(-1)\n\n\t// A timeout needs to be completed before the toolbar's position changes moved\n\tconst rStablePositionTimeout = useRef<any>(-1)\n\n\t/**\n\t * Send the 'move' event whenever something happens that would cause the toolbar's position to change.\n\t * Any update here will cause\n\t * If the state is 'shown', it will start a new timeout that will update the toolbar's position after it completes.\n\t */\n\tconst move = useCallback(\n\t\t(x: number, y: number, immediate = false) => {\n\t\t\t// Update the next proposed position\n\t\t\trNextPosition.current.x = x\n\t\t\trNextPosition.current.y = y\n\n\t\t\t// If the toolbar is not yet visible, don't do anything\n\t\t\tif (rState.current.name === 'hidden' || rState.current.name === 'showing') return\n\n\t\t\t// If showing or hiding, cancel the position timeout and start a new one.\n\t\t\t// When the timeout ends, if we're in the 'shown' state and the position has changed sufficiently\n\t\t\t// from the last visible position, update the position.\n\t\t\tclearTimeout(rStablePositionTimeout.current)\n\n\t\t\tconst flushMove = () => {\n\t\t\t\tif (\n\t\t\t\t\trState.current.name === 'shown' &&\n\t\t\t\t\tsufficientlyDistant(rNextPosition.current, rCurrPosition.current, changeOnlyWhenYChanges)\n\t\t\t\t) {\n\t\t\t\t\tconst { x, y } = rNextPosition.current\n\t\t\t\t\trCurrPosition.current = new Vec(x, y)\n\t\t\t\t\tif (immediate) {\n\t\t\t\t\t\tflushSync(() => setPosition({ x, y }))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetPosition({ x, y })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (immediate) {\n\t\t\t\tflushMove()\n\t\t\t} else {\n\t\t\t\trStablePositionTimeout.current = editor.timers.setTimeout(flushMove, MOVE_TIMEOUT)\n\t\t\t}\n\t\t},\n\t\t[editor, changeOnlyWhenYChanges]\n\t)\n\n\t/**\n\t * Send the hide event whenever a change occurs that would cause the toolbar to become invisible.\n\t * If the state is 'shown', it will enter 'hiding' and then 'hidden' after a timeout completes.\n\t * If the state is 'showing', it will cancel the visibility timeout and enter 'hidden' immediately.\n\t */\n\tconst hide = useCallback(\n\t\t(immediate = false) => {\n\t\t\tswitch (rState.current.name) {\n\t\t\t\tcase 'showing': {\n\t\t\t\t\tclearTimeout(rStableVisibilityTimeout.current)\n\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'shown': {\n\t\t\t\t\trState.current = { name: 'hiding' }\n\t\t\t\t\tsetIsInteractive(false) // when leaving shown, turn back on interactions\n\n\t\t\t\t\tif (immediate) {\n\t\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\t\tsetIsVisible(false)\n\t\t\t\t\t} else {\n\t\t\t\t\t\trStableVisibilityTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\t\t\tsetIsVisible(false)\n\t\t\t\t\t\t}, HIDE_VISIBILITY_TIMEOUT)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t/**\n\t * Send the show event whenever a change occurs that would cause the toolbar to become visible.\n\t * If the state is 'hidden', it will enter 'showing' and then 'shown' after a timeout completes.\n\t * If the state is 'hiding', it will cancel the visibility timeout and enter 'shown' immediately.\n\t */\n\tconst show = useCallback(() => {\n\t\tswitch (rState.current.name) {\n\t\t\tcase 'hidden': {\n\t\t\t\trState.current = { name: 'showing' }\n\t\t\t\trStableVisibilityTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t// position\n\t\t\t\t\tconst { x, y } = rNextPosition.current\n\t\t\t\t\trCurrPosition.current = new Vec(x, y)\n\t\t\t\t\tsetPosition({ x, y })\n\n\t\t\t\t\trState.current = { name: 'shown' }\n\t\t\t\t\tsetIsVisible(true)\n\t\t\t\t\tsetIsInteractive(true)\n\t\t\t\t}, SHOW_VISIBILITY_TIMEOUT)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'hiding': {\n\t\t\t\t// Go back to shown immediately\n\t\t\t\tclearTimeout(rStableVisibilityTimeout.current)\n\t\t\t\trState.current = { name: 'shown' }\n\t\t\t\tsetIsInteractive(true) // when entering shown, turn back on interactions\n\t\t\t\tmove(rNextPosition.current.x, rNextPosition.current.y)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t}, [editor, move])\n\n\treturn { isVisible, isInteractive, show, hide, move, position }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tassert,\n\tBox,\n\tclamp,\n\tEditor,\n\treact,\n\tuseAtom,\n\tuseEditor,\n\tusePassThroughMouseOverEvents,\n\tusePassThroughWheelEvents,\n\tuseValue,\n\tVec,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { RefObject, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { flushSync } from 'react-dom'\nimport { TldrawUiToolbar } from './TldrawUiToolbar'\n\nconst MOVE_TIMEOUT = 150\nconst HIDE_VISIBILITY_TIMEOUT = 16\nconst SHOW_VISIBILITY_TIMEOUT = 16\nconst MIN_DISTANCE_TO_REPOSITION_SQUARED = 16 ** 2\nconst TOOLBAR_GAP = 8\nconst SCREEN_MARGIN = 16\nconst HIDE_TOOLBAR_WHEN_CAMERA_IS_MOVING = false\nconst LEFT_ALIGN_TOOLBAR = false\n\n/** @public */\nexport interface TLUiContextualToolbarProps {\n\tchildren?: React.ReactNode\n\tclassName?: string\n\tisMousingDown?: boolean\n\tgetSelectionBounds(): Box | undefined\n\tchangeOnlyWhenYChanges?: boolean\n\tlabel: string\n}\n\n/**\n * A generic floating toolbar that can be used for things\n * like rich text editing, image toolbars, etc.\n *\n * @public @react\n */\nexport const TldrawUiContextualToolbar = ({\n\tchildren,\n\tclassName,\n\tisMousingDown,\n\tgetSelectionBounds,\n\tchangeOnlyWhenYChanges = false,\n\tlabel,\n}: TLUiContextualToolbarProps) => {\n\tconst editor = useEditor()\n\tconst toolbarRef = useRef<HTMLDivElement>(null)\n\n\tusePassThroughWheelEvents(toolbarRef as RefObject<HTMLDivElement>)\n\tusePassThroughMouseOverEvents(toolbarRef as RefObject<HTMLDivElement>)\n\n\tconst { isVisible, isInteractive, hide, show, position, move } =\n\t\tuseToolbarVisibilityStateMachine(changeOnlyWhenYChanges)\n\n\t// annoying react stuff: we don't want the toolbar position function to depend on the react state so we'll double with a ref\n\tconst rCouldShowToolbar = useRef(false)\n\tconst [hasValidToolbarPosition, setHasValidToolbarPosition] = useState(false)\n\n\tconst contentSizeUpdateCounter = useAtom('content size update counter', 0)\n\n\tuseEffect(() => {\n\t\tassert(toolbarRef.current)\n\t\tconst observer = new ResizeObserver(() => {\n\t\t\tcontentSizeUpdateCounter.update((n) => n + 1)\n\t\t})\n\t\tobserver.observe(toolbarRef.current)\n\t\treturn () => observer.disconnect()\n\t}, [contentSizeUpdateCounter])\n\n\tuseEffect(() => {\n\t\tlet lastContentSizeUpdateCounter = contentSizeUpdateCounter.get()\n\t\treturn react('toolbar position', function updateToolbarPositionAndDisplay() {\n\t\t\tconst toolbarElm = toolbarRef.current\n\t\t\tif (!toolbarElm) return\n\n\t\t\tconst nextContentSizeUpdateCounter = contentSizeUpdateCounter.get()\n\n\t\t\t// capture / force this to update when...\n\t\t\teditor.getCamera() // the camera moves\n\t\t\tcontentSizeUpdateCounter.get() // the toolbar size changes\n\t\t\t// undefined here means that we can't show the toolbar due to an incompatible position\n\t\t\tconst position = getToolbarScreenPosition(editor, toolbarElm, getSelectionBounds)\n\n\t\t\t// todo: when the toolbar is hidden due to the selection being off screen, it should be hidden immediately\n\t\t\t// rather than waiting for the position to settle. This is different than when the position changes due to\n\t\t\t// a change in the user's selection.\n\t\t\tif (!position) {\n\t\t\t\tif (rCouldShowToolbar.current) {\n\t\t\t\t\t// If we don't have a position, then we're not showing the toolbar\n\t\t\t\t\trCouldShowToolbar.current = false\n\t\t\t\t\tsetHasValidToolbarPosition(false)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If the camera state is moving, we want to immediately update the position\n\t\t\t\t// todo: consider hiding the toolbar while the camera is moving\n\t\t\t\tconst cameraState = editor.getCameraState()\n\t\t\t\tif (cameraState === 'moving') {\n\t\t\t\t\t// ...if we wanted this to avoid prematurely updating any positions, we'd need\n\t\t\t\t\t// to have the last updated position in page space, so that we could convert\n\t\t\t\t\t// it to screen space and update it here\n\t\t\t\t\tconst elm = toolbarRef.current\n\t\t\t\t\telm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)\n\t\t\t\t} else {\n\t\t\t\t\tconst moveImmediately = lastContentSizeUpdateCounter !== nextContentSizeUpdateCounter\n\t\t\t\t\t// Schedule a move to its next location\n\t\t\t\t\tmove(position.x, position.y, moveImmediately)\n\t\t\t\t}\n\n\t\t\t\t// Finally, if the toolbar was previously hidden, show it again\n\t\t\t\tif (!rCouldShowToolbar.current) {\n\t\t\t\t\trCouldShowToolbar.current = true\n\t\t\t\t\tsetHasValidToolbarPosition(true)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlastContentSizeUpdateCounter = nextContentSizeUpdateCounter\n\t\t})\n\t}, [editor, getSelectionBounds, contentSizeUpdateCounter, move])\n\n\tconst cameraState = useValue('camera state', () => editor.getCameraState(), [editor])\n\n\t// Send the hide or show events based on whether the user is clicking\n\t// and whether the toolbar's position is valid\n\tuseEffect(() => {\n\t\tif (cameraState === 'moving' && HIDE_TOOLBAR_WHEN_CAMERA_IS_MOVING) {\n\t\t\thide(true)\n\t\t\treturn\n\t\t}\n\n\t\tif (isMousingDown || !hasValidToolbarPosition) {\n\t\t\thide()\n\t\t\treturn\n\t\t}\n\n\t\tshow()\n\t}, [hasValidToolbarPosition, cameraState, isMousingDown, show, hide])\n\n\t// When the visibility changes, update the toolbar's visibility\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.dataset.visible = `${isVisible}`\n\t}, [isVisible, position])\n\n\t// When the position changes, update the toolbar's position on screen\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)\n\t}, [position])\n\n\t// When the interactivity changes, update the toolbar's interactivity\n\tuseLayoutEffect(() => {\n\t\tconst elm = toolbarRef.current\n\t\tif (!elm) return\n\t\telm.dataset.interactive = `${isInteractive}`\n\t}, [isInteractive])\n\n\treturn (\n\t\t<div\n\t\t\tref={toolbarRef}\n\t\t\tdata-interactive={false}\n\t\t\tdata-visible={false}\n\t\t\tdata-testid=\"contextual-toolbar\"\n\t\t\tclassName={classNames('tlui-contextual-toolbar', className)}\n\t\t\tonPointerDown={editor.markEventAsHandled}\n\t\t>\n\t\t\t<TldrawUiToolbar\n\t\t\t\torientation=\"horizontal\"\n\t\t\t\tclassName=\"tlui-menu\"\n\t\t\t\tlabel={label}\n\t\t\t\ttooltipSide=\"top\"\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</TldrawUiToolbar>\n\t\t</div>\n\t)\n}\n\n// For convenience, let's work just with boxes here\n/** @internal */\nexport function rectToBox(rect: DOMRect): Box {\n\treturn new Box(rect.x, rect.y, rect.width, rect.height)\n}\n\nexport function getToolbarScreenPosition(\n\teditor: Editor,\n\ttoolbarElm: HTMLElement,\n\tgetSelectionBounds: () => Box | undefined\n) {\n\tconst selectionBounds = getSelectionBounds()?.clone()\n\tif (!selectionBounds) return\n\n\t// Offset the selection bounds by the viewport screen bounds (if the editor is scrolled or inset, etc)\n\tconst vsb = editor.getViewportScreenBounds()\n\tselectionBounds.x -= vsb.x\n\tselectionBounds.y -= vsb.y\n\n\t// If the selection bounds are too far off of the screen, don't show the toolbar\n\tif (\n\t\tselectionBounds.midY < SCREEN_MARGIN ||\n\t\tselectionBounds.midY > vsb.h - SCREEN_MARGIN ||\n\t\tselectionBounds.midX < SCREEN_MARGIN ||\n\t\tselectionBounds.midX > vsb.w - SCREEN_MARGIN\n\t) {\n\t\treturn\n\t}\n\n\t// Get the toolbar's screen rect as a box. Do this after we verify that there is at least one selection.\n\tconst toolbarBounds = rectToBox(toolbarElm.getBoundingClientRect())\n\n\t// Chance these are NaN? Rare case.\n\tif (!toolbarBounds.width || !toolbarBounds.height) return\n\n\t// Thrashy, only do this if we're showing the toolbar\n\t// ! this might not be needed, the container never scrolls\n\tconst { scrollLeft, scrollTop } = editor.getContainer()\n\n\t// We want to position the toolbar so that it is centered over the selection\n\t// except in the cases where it would extend off the edge of the screen.\n\n\t// Start by placing the top left corner of the toolbar so that the\n\t// toolbar would be centered above the section bounds, bumped up by the\n\n\tlet x = LEFT_ALIGN_TOOLBAR ? selectionBounds.x : selectionBounds.midX - toolbarBounds.w / 2\n\tlet y = selectionBounds.y - toolbarBounds.h - TOOLBAR_GAP\n\n\t// Clamp the position on screen.\n\tx = clamp(x, SCREEN_MARGIN, vsb.w - toolbarBounds.w - SCREEN_MARGIN)\n\ty = clamp(y, SCREEN_MARGIN, vsb.h - toolbarBounds.h - SCREEN_MARGIN)\n\n\t// Offset the position by the container's scroll position\n\tx += scrollLeft\n\ty += scrollTop\n\n\t// Round the position to the nearest pixel\n\tx = Math.round(x)\n\ty = Math.round(y)\n\n\treturn { x, y }\n}\n\nfunction sufficientlyDistant(curr: Vec, next: Vec, changeOnlyWhenYChanges: boolean) {\n\tif (changeOnlyWhenYChanges) {\n\t\treturn Vec.Sub(next, curr).y ** 2 >= MIN_DISTANCE_TO_REPOSITION_SQUARED\n\t}\n\treturn Vec.Len2(Vec.Sub(next, curr)) >= MIN_DISTANCE_TO_REPOSITION_SQUARED\n}\n\nexport function useToolbarVisibilityStateMachine(changeOnlyWhenYChanges: boolean) {\n\tconst editor = useEditor()\n\n\tconst rState = useRef<\n\t\t{ name: 'hidden' } | { name: 'showing' } | { name: 'shown' } | { name: 'hiding' }\n\t>({ name: 'hidden' })\n\n\t// The toolbar should only be interactive when in the 'shown' state\n\tconst [isInteractive, setIsInteractive] = useState(false)\n\n\t// The toolbar is visible in the 'shown' and 'hiding' states\n\tconst [isVisible, setIsVisible] = useState(false)\n\n\t// The position is updated when entering the 'shown' state or when moving while in the 'shown' state\n\tconst [position, setPosition] = useState({ x: -1000, y: -1000 })\n\n\t// The toolbar's current position\n\tconst rCurrPosition = useRef(new Vec(-1000, -1000))\n\n\t// The toolbar's proposed next position\n\tconst rNextPosition = useRef(new Vec(-1000, -1000))\n\n\t// A timeout needs to be completed before the toolbar is shown or hidden\n\tconst rStableVisibilityTimeout = useRef<any>(-1)\n\n\t// A timeout needs to be completed before the toolbar's position changes moved\n\tconst rStablePositionTimeout = useRef<any>(-1)\n\n\t/**\n\t * Send the 'move' event whenever something happens that would cause the toolbar's position to change.\n\t * Any update here will cause\n\t * If the state is 'shown', it will start a new timeout that will update the toolbar's position after it completes.\n\t */\n\tconst move = useCallback(\n\t\t(x: number, y: number, immediate = false) => {\n\t\t\t// Update the next proposed position\n\t\t\trNextPosition.current.x = x\n\t\t\trNextPosition.current.y = y\n\n\t\t\t// If the toolbar is not yet visible, don't do anything\n\t\t\tif (rState.current.name === 'hidden' || rState.current.name === 'showing') return\n\n\t\t\t// If showing or hiding, cancel the position timeout and start a new one.\n\t\t\t// When the timeout ends, if we're in the 'shown' state and the position has changed sufficiently\n\t\t\t// from the last visible position, update the position.\n\t\t\tclearTimeout(rStablePositionTimeout.current)\n\n\t\t\tconst flushMove = () => {\n\t\t\t\tif (\n\t\t\t\t\trState.current.name === 'shown' &&\n\t\t\t\t\tsufficientlyDistant(rNextPosition.current, rCurrPosition.current, changeOnlyWhenYChanges)\n\t\t\t\t) {\n\t\t\t\t\tconst { x, y } = rNextPosition.current\n\t\t\t\t\trCurrPosition.current = new Vec(x, y)\n\t\t\t\t\tif (immediate) {\n\t\t\t\t\t\tflushSync(() => setPosition({ x, y }))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetPosition({ x, y })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (immediate) {\n\t\t\t\tflushMove()\n\t\t\t} else {\n\t\t\t\trStablePositionTimeout.current = editor.timers.setTimeout(flushMove, MOVE_TIMEOUT)\n\t\t\t}\n\t\t},\n\t\t[editor, changeOnlyWhenYChanges]\n\t)\n\n\t/**\n\t * Send the hide event whenever a change occurs that would cause the toolbar to become invisible.\n\t * If the state is 'shown', it will enter 'hiding' and then 'hidden' after a timeout completes.\n\t * If the state is 'showing', it will cancel the visibility timeout and enter 'hidden' immediately.\n\t */\n\tconst hide = useCallback(\n\t\t(immediate = false) => {\n\t\t\tswitch (rState.current.name) {\n\t\t\t\tcase 'showing': {\n\t\t\t\t\tclearTimeout(rStableVisibilityTimeout.current)\n\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'shown': {\n\t\t\t\t\trState.current = { name: 'hiding' }\n\t\t\t\t\tsetIsInteractive(false) // when leaving shown, turn back on interactions\n\n\t\t\t\t\tif (immediate) {\n\t\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\t\tsetIsVisible(false)\n\t\t\t\t\t} else {\n\t\t\t\t\t\trStableVisibilityTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\trState.current = { name: 'hidden' }\n\t\t\t\t\t\t\tsetIsVisible(false)\n\t\t\t\t\t\t}, HIDE_VISIBILITY_TIMEOUT)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\t/**\n\t * Send the show event whenever a change occurs that would cause the toolbar to become visible.\n\t * If the state is 'hidden', it will enter 'showing' and then 'shown' after a timeout completes.\n\t * If the state is 'hiding', it will cancel the visibility timeout and enter 'shown' immediately.\n\t */\n\tconst show = useCallback(() => {\n\t\tswitch (rState.current.name) {\n\t\t\tcase 'hidden': {\n\t\t\t\trState.current = { name: 'showing' }\n\t\t\t\trStableVisibilityTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t// position\n\t\t\t\t\tconst { x, y } = rNextPosition.current\n\t\t\t\t\trCurrPosition.current = new Vec(x, y)\n\t\t\t\t\tsetPosition({ x, y })\n\n\t\t\t\t\trState.current = { name: 'shown' }\n\t\t\t\t\tsetIsVisible(true)\n\t\t\t\t\tsetIsInteractive(true)\n\t\t\t\t}, SHOW_VISIBILITY_TIMEOUT)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'hiding': {\n\t\t\t\t// Go back to shown immediately\n\t\t\t\tclearTimeout(rStableVisibilityTimeout.current)\n\t\t\t\trState.current = { name: 'shown' }\n\t\t\t\tsetIsInteractive(true) // when entering shown, turn back on interactions\n\t\t\t\tmove(rNextPosition.current.x, rNextPosition.current.y)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t}, [editor, move])\n\n\treturn { isVisible, isInteractive, show, hide, move, position }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["position", "cameraState", "x", "y"]
7
7
  }
@@ -213,8 +213,8 @@ const TldrawUiTooltip = forwardRef(
213
213
  } else {
214
214
  delayDurationToUse = delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS);
215
215
  }
216
- if (!hasProvider) {
217
- return /* @__PURE__ */ jsxs(_Tooltip.Root, { delayDuration: delayDurationToUse, disableHoverableContent: true, children: [
216
+ if (!hasProvider || showUiLabels) {
217
+ return /* @__PURE__ */ jsxs(_Tooltip.Root, { delayDuration: delayDurationToUse, disableHoverableContent: !showUiLabels, children: [
218
218
  /* @__PURE__ */ jsx(_Tooltip.Trigger, { asChild: true, ref, children }),
219
219
  /* @__PURE__ */ jsxs(
220
220
  _Tooltip.Content,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiTooltip.tsx"],
4
- "sourcesContent": ["import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'\nimport { Tooltip as _Tooltip } from 'radix-ui'\nimport React, {\n\tcreateContext,\n\tforwardRef,\n\tReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { useTldrawUiOrientation } from './layout'\n\nconst DEFAULT_TOOLTIP_DELAY_MS = 700\n\n/** @public */\nexport interface TldrawUiTooltipProps {\n\tchildren: React.ReactNode\n\tcontent?: string | React.ReactNode\n\tside?: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset?: number\n\tdisabled?: boolean\n\tshowOnMobile?: boolean\n\tdelayDuration?: number\n}\n\ninterface CurrentTooltip {\n\tid: string\n\tcontent: ReactNode\n\tside: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset: number\n\tshowOnMobile: boolean\n\ttargetElement: HTMLElement\n\tdelayDuration: number\n}\n\n// Singleton tooltip manager\nclass TooltipManager {\n\tprivate static instance: TooltipManager | null = null\n\tprivate currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)\n\tprivate destroyTimeoutId: number | null = null\n\n\tstatic getInstance(): TooltipManager {\n\t\tif (!TooltipManager.instance) {\n\t\t\tTooltipManager.instance = new TooltipManager()\n\t\t}\n\t\treturn TooltipManager.instance\n\t}\n\n\tshowTooltip(\n\t\ttooltipId: string,\n\t\tcontent: string | React.ReactNode,\n\t\ttargetElement: HTMLElement,\n\t\tside: 'top' | 'right' | 'bottom' | 'left',\n\t\tsideOffset: number,\n\t\tshowOnMobile: boolean,\n\t\tdelayDuration: number\n\t) {\n\t\t// Clear any existing destroy timeout\n\t\tif (this.destroyTimeoutId) {\n\t\t\tclearTimeout(this.destroyTimeoutId)\n\t\t\tthis.destroyTimeoutId = null\n\t\t}\n\n\t\t// Update current tooltip\n\t\tthis.currentTooltip.set({\n\t\t\tid: tooltipId,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset,\n\t\t\tshowOnMobile,\n\t\t\ttargetElement,\n\t\t\tdelayDuration,\n\t\t})\n\t}\n\n\tupdateCurrentTooltip(tooltipId: string, update: (tooltip: CurrentTooltip) => CurrentTooltip) {\n\t\tthis.currentTooltip.update((tooltip) => {\n\t\t\tif (tooltip?.id === tooltipId) {\n\t\t\t\treturn update(tooltip)\n\t\t\t}\n\t\t\treturn tooltip\n\t\t})\n\t}\n\n\thideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {\n\t\tconst hide = () => {\n\t\t\t// Only hide if this is the current tooltip\n\t\t\tif (this.currentTooltip.get()?.id === tooltipId) {\n\t\t\t\tthis.currentTooltip.set(null)\n\t\t\t\tthis.destroyTimeoutId = null\n\t\t\t}\n\t\t}\n\n\t\tif (editor && !instant) {\n\t\t\t// Start destroy timeout (1 second)\n\t\t\tthis.destroyTimeoutId = editor.timers.setTimeout(hide, 300)\n\t\t} else {\n\t\t\thide()\n\t\t}\n\t}\n\n\thideAllTooltips() {\n\t\tthis.currentTooltip.set(null)\n\t\tthis.destroyTimeoutId = null\n\t}\n\n\tgetCurrentTooltipData() {\n\t\tconst currentTooltip = this.currentTooltip.get()\n\t\tif (!currentTooltip) return null\n\t\tif (!this.supportsHover() && !currentTooltip.showOnMobile) return null\n\t\treturn currentTooltip\n\t}\n\n\tprivate supportsHoverAtom: Atom<boolean> | null = null\n\tsupportsHover() {\n\t\tif (!this.supportsHoverAtom) {\n\t\t\tconst mediaQuery = window.matchMedia('(hover: hover)')\n\t\t\tconst supportsHover = atom('has hover', mediaQuery.matches)\n\t\t\tthis.supportsHoverAtom = supportsHover\n\t\t\tmediaQuery.addEventListener('change', (e) => {\n\t\t\t\tsupportsHover.set(e.matches)\n\t\t\t})\n\t\t}\n\t\treturn this.supportsHoverAtom.get()\n\t}\n}\n\nexport const tooltipManager = TooltipManager.getInstance()\n\n// Context for the tooltip singleton\nconst TooltipSingletonContext = createContext<boolean>(false)\n\n/** @public */\nexport interface TldrawUiTooltipProviderProps {\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderProps) {\n\treturn (\n\t\t<_Tooltip.Provider skipDelayDuration={700}>\n\t\t\t<TooltipSingletonContext.Provider value={true}>\n\t\t\t\t{children}\n\t\t\t\t<TooltipSingleton />\n\t\t\t</TooltipSingletonContext.Provider>\n\t\t</_Tooltip.Provider>\n\t)\n}\n\n// The singleton tooltip component that renders once\nfunction TooltipSingleton() {\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst triggerRef = useRef<HTMLDivElement>(null)\n\tconst isFirstShowRef = useRef(true)\n\tconst editor = useMaybeEditor()\n\n\tconst currentTooltip = useValue(\n\t\t'current tooltip',\n\t\t() => tooltipManager.getCurrentTooltipData(),\n\t\t[]\n\t)\n\n\tconst cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])\n\n\t// Hide tooltip when camera is moving (panning/zooming)\n\tuseEffect(() => {\n\t\tif (cameraState === 'moving' && isOpen && currentTooltip) {\n\t\t\ttooltipManager.hideTooltip(editor, currentTooltip.id, true)\n\t\t}\n\t}, [cameraState, isOpen, currentTooltip, editor])\n\n\tuseEffect(() => {\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (event.key === 'Escape' && currentTooltip && isOpen) {\n\t\t\t\ttooltipManager.hideTooltip(editor, currentTooltip.id)\n\t\t\t\tevent.stopPropagation()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown, { capture: true })\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeyDown, { capture: true })\n\t\t}\n\t}, [editor, currentTooltip, isOpen])\n\n\t// Update open state and trigger position\n\tuseEffect(() => {\n\t\tlet timer: ReturnType<typeof setTimeout> | null = null\n\t\tif (currentTooltip && triggerRef.current) {\n\t\t\t// Position the invisible trigger element over the active element\n\t\t\tconst activeRect = currentTooltip.targetElement.getBoundingClientRect()\n\t\t\tconst trigger = triggerRef.current\n\n\t\t\ttrigger.style.position = 'fixed'\n\t\t\ttrigger.style.left = `${activeRect.left}px`\n\t\t\ttrigger.style.top = `${activeRect.top}px`\n\t\t\ttrigger.style.width = `${activeRect.width}px`\n\t\t\ttrigger.style.height = `${activeRect.height}px`\n\t\t\ttrigger.style.pointerEvents = 'none'\n\t\t\ttrigger.style.zIndex = '9999'\n\n\t\t\t// Handle delay for first show\n\t\t\tif (isFirstShowRef.current) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tsetIsOpen(true)\n\t\t\t\t\tisFirstShowRef.current = false\n\t\t\t\t}, currentTooltip.delayDuration)\n\t\t\t} else {\n\t\t\t\t// Subsequent tooltips show immediately\n\t\t\t\tsetIsOpen(true)\n\t\t\t}\n\t\t} else {\n\t\t\t// Hide tooltip immediately\n\t\t\tsetIsOpen(false)\n\t\t\t// Reset first show state after tooltip is hidden\n\t\t\tisFirstShowRef.current = true\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (timer !== null) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t}\n\t\t}\n\t}, [currentTooltip])\n\n\tif (!currentTooltip) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<_Tooltip.Root open={isOpen} delayDuration={0}>\n\t\t\t<_Tooltip.Trigger asChild>\n\t\t\t\t<div ref={triggerRef} />\n\t\t\t</_Tooltip.Trigger>\n\t\t\t<_Tooltip.Content\n\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\tside={currentTooltip.side}\n\t\t\t\tsideOffset={currentTooltip.sideOffset}\n\t\t\t\tavoidCollisions\n\t\t\t\tcollisionPadding={8}\n\t\t\t\tdir=\"ltr\"\n\t\t\t>\n\t\t\t\t{currentTooltip.content}\n\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t</_Tooltip.Content>\n\t\t</_Tooltip.Root>\n\t)\n}\n\n/** @public @react */\nexport const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(\n\t(\n\t\t{\n\t\t\tchildren,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset = 5,\n\t\t\tdisabled = false,\n\t\t\tshowOnMobile = false,\n\t\t\tdelayDuration,\n\t\t},\n\t\tref\n\t) => {\n\t\tconst editor = useMaybeEditor()\n\t\tconst tooltipId = useRef<string>(uniqueId())\n\t\tconst hasProvider = useContext(TooltipSingletonContext)\n\t\tconst showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])\n\n\t\tconst orientationCtx = useTldrawUiOrientation()\n\t\tconst sideToUse = side ?? orientationCtx.tooltipSide\n\n\t\tuseEffect(() => {\n\t\t\tconst currentTooltipId = tooltipId.current\n\t\t\treturn () => {\n\t\t\t\tif (hasProvider) {\n\t\t\t\t\ttooltipManager.hideTooltip(editor, currentTooltipId, true)\n\t\t\t\t}\n\t\t\t}\n\t\t}, [editor, hasProvider])\n\n\t\tuseLayoutEffect(() => {\n\t\t\tif (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {\n\t\t\t\ttooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({\n\t\t\t\t\t...tooltip,\n\t\t\t\t\tcontent,\n\t\t\t\t\tside: sideToUse,\n\t\t\t\t\tsideOffset,\n\t\t\t\t\tshowOnMobile,\n\t\t\t\t}))\n\t\t\t}\n\t\t}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])\n\n\t\t// Don't show tooltip if disabled, no content, or UI labels are disabled\n\t\tif (disabled || !content) {\n\t\t\treturn <>{children}</>\n\t\t}\n\n\t\tlet delayDurationToUse\n\t\tif (showUiLabels) {\n\t\t\tdelayDurationToUse = 0\n\t\t} else {\n\t\t\tdelayDurationToUse =\n\t\t\t\tdelayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)\n\t\t}\n\n\t\t// Fallback to old behavior if no provider\n\t\tif (!hasProvider) {\n\t\t\treturn (\n\t\t\t\t<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>\n\t\t\t\t\t<_Tooltip.Trigger asChild ref={ref}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</_Tooltip.Trigger>\n\t\t\t\t\t<_Tooltip.Content\n\t\t\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\t\t\tside={sideToUse}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tavoidCollisions\n\t\t\t\t\t\tcollisionPadding={8}\n\t\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t\t\t</_Tooltip.Content>\n\t\t\t\t</_Tooltip.Root>\n\t\t\t)\n\t\t}\n\n\t\tconst child = React.Children.only(children)\n\t\tassert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')\n\n\t\tconst handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseEnter?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseLeave?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst handleFocus = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onFocus?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleBlur = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onBlur?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst childrenWithHandlers = React.cloneElement(children as React.ReactElement, {\n\t\t\tonMouseEnter: handleMouseEnter,\n\t\t\tonMouseLeave: handleMouseLeave,\n\t\t\tonFocus: handleFocus,\n\t\t\tonBlur: handleBlur,\n\t\t})\n\n\t\treturn childrenWithHandlers\n\t}\n)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'\nimport { Tooltip as _Tooltip } from 'radix-ui'\nimport React, {\n\tcreateContext,\n\tforwardRef,\n\tReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { useTldrawUiOrientation } from './layout'\n\nconst DEFAULT_TOOLTIP_DELAY_MS = 700\n\n/** @public */\nexport interface TldrawUiTooltipProps {\n\tchildren: React.ReactNode\n\tcontent?: string | React.ReactNode\n\tside?: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset?: number\n\tdisabled?: boolean\n\tshowOnMobile?: boolean\n\tdelayDuration?: number\n}\n\ninterface CurrentTooltip {\n\tid: string\n\tcontent: ReactNode\n\tside: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset: number\n\tshowOnMobile: boolean\n\ttargetElement: HTMLElement\n\tdelayDuration: number\n}\n\n// Singleton tooltip manager\nclass TooltipManager {\n\tprivate static instance: TooltipManager | null = null\n\tprivate currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)\n\tprivate destroyTimeoutId: number | null = null\n\n\tstatic getInstance(): TooltipManager {\n\t\tif (!TooltipManager.instance) {\n\t\t\tTooltipManager.instance = new TooltipManager()\n\t\t}\n\t\treturn TooltipManager.instance\n\t}\n\n\tshowTooltip(\n\t\ttooltipId: string,\n\t\tcontent: string | React.ReactNode,\n\t\ttargetElement: HTMLElement,\n\t\tside: 'top' | 'right' | 'bottom' | 'left',\n\t\tsideOffset: number,\n\t\tshowOnMobile: boolean,\n\t\tdelayDuration: number\n\t) {\n\t\t// Clear any existing destroy timeout\n\t\tif (this.destroyTimeoutId) {\n\t\t\tclearTimeout(this.destroyTimeoutId)\n\t\t\tthis.destroyTimeoutId = null\n\t\t}\n\n\t\t// Update current tooltip\n\t\tthis.currentTooltip.set({\n\t\t\tid: tooltipId,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset,\n\t\t\tshowOnMobile,\n\t\t\ttargetElement,\n\t\t\tdelayDuration,\n\t\t})\n\t}\n\n\tupdateCurrentTooltip(tooltipId: string, update: (tooltip: CurrentTooltip) => CurrentTooltip) {\n\t\tthis.currentTooltip.update((tooltip) => {\n\t\t\tif (tooltip?.id === tooltipId) {\n\t\t\t\treturn update(tooltip)\n\t\t\t}\n\t\t\treturn tooltip\n\t\t})\n\t}\n\n\thideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {\n\t\tconst hide = () => {\n\t\t\t// Only hide if this is the current tooltip\n\t\t\tif (this.currentTooltip.get()?.id === tooltipId) {\n\t\t\t\tthis.currentTooltip.set(null)\n\t\t\t\tthis.destroyTimeoutId = null\n\t\t\t}\n\t\t}\n\n\t\tif (editor && !instant) {\n\t\t\t// Start destroy timeout (1 second)\n\t\t\tthis.destroyTimeoutId = editor.timers.setTimeout(hide, 300)\n\t\t} else {\n\t\t\thide()\n\t\t}\n\t}\n\n\thideAllTooltips() {\n\t\tthis.currentTooltip.set(null)\n\t\tthis.destroyTimeoutId = null\n\t}\n\n\tgetCurrentTooltipData() {\n\t\tconst currentTooltip = this.currentTooltip.get()\n\t\tif (!currentTooltip) return null\n\t\tif (!this.supportsHover() && !currentTooltip.showOnMobile) return null\n\t\treturn currentTooltip\n\t}\n\n\tprivate supportsHoverAtom: Atom<boolean> | null = null\n\tsupportsHover() {\n\t\tif (!this.supportsHoverAtom) {\n\t\t\tconst mediaQuery = window.matchMedia('(hover: hover)')\n\t\t\tconst supportsHover = atom('has hover', mediaQuery.matches)\n\t\t\tthis.supportsHoverAtom = supportsHover\n\t\t\tmediaQuery.addEventListener('change', (e) => {\n\t\t\t\tsupportsHover.set(e.matches)\n\t\t\t})\n\t\t}\n\t\treturn this.supportsHoverAtom.get()\n\t}\n}\n\nexport const tooltipManager = TooltipManager.getInstance()\n\n// Context for the tooltip singleton\nconst TooltipSingletonContext = createContext<boolean>(false)\n\n/** @public */\nexport interface TldrawUiTooltipProviderProps {\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderProps) {\n\treturn (\n\t\t<_Tooltip.Provider skipDelayDuration={700}>\n\t\t\t<TooltipSingletonContext.Provider value={true}>\n\t\t\t\t{children}\n\t\t\t\t<TooltipSingleton />\n\t\t\t</TooltipSingletonContext.Provider>\n\t\t</_Tooltip.Provider>\n\t)\n}\n\n// The singleton tooltip component that renders once\nfunction TooltipSingleton() {\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst triggerRef = useRef<HTMLDivElement>(null)\n\tconst isFirstShowRef = useRef(true)\n\tconst editor = useMaybeEditor()\n\n\tconst currentTooltip = useValue(\n\t\t'current tooltip',\n\t\t() => tooltipManager.getCurrentTooltipData(),\n\t\t[]\n\t)\n\n\tconst cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])\n\n\t// Hide tooltip when camera is moving (panning/zooming)\n\tuseEffect(() => {\n\t\tif (cameraState === 'moving' && isOpen && currentTooltip) {\n\t\t\ttooltipManager.hideTooltip(editor, currentTooltip.id, true)\n\t\t}\n\t}, [cameraState, isOpen, currentTooltip, editor])\n\n\tuseEffect(() => {\n\t\tfunction handleKeyDown(event: KeyboardEvent) {\n\t\t\tif (event.key === 'Escape' && currentTooltip && isOpen) {\n\t\t\t\ttooltipManager.hideTooltip(editor, currentTooltip.id)\n\t\t\t\tevent.stopPropagation()\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown, { capture: true })\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', handleKeyDown, { capture: true })\n\t\t}\n\t}, [editor, currentTooltip, isOpen])\n\n\t// Update open state and trigger position\n\tuseEffect(() => {\n\t\tlet timer: ReturnType<typeof setTimeout> | null = null\n\t\tif (currentTooltip && triggerRef.current) {\n\t\t\t// Position the invisible trigger element over the active element\n\t\t\tconst activeRect = currentTooltip.targetElement.getBoundingClientRect()\n\t\t\tconst trigger = triggerRef.current\n\n\t\t\ttrigger.style.position = 'fixed'\n\t\t\ttrigger.style.left = `${activeRect.left}px`\n\t\t\ttrigger.style.top = `${activeRect.top}px`\n\t\t\ttrigger.style.width = `${activeRect.width}px`\n\t\t\ttrigger.style.height = `${activeRect.height}px`\n\t\t\ttrigger.style.pointerEvents = 'none'\n\t\t\ttrigger.style.zIndex = '9999'\n\n\t\t\t// Handle delay for first show\n\t\t\tif (isFirstShowRef.current) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tsetIsOpen(true)\n\t\t\t\t\tisFirstShowRef.current = false\n\t\t\t\t}, currentTooltip.delayDuration)\n\t\t\t} else {\n\t\t\t\t// Subsequent tooltips show immediately\n\t\t\t\tsetIsOpen(true)\n\t\t\t}\n\t\t} else {\n\t\t\t// Hide tooltip immediately\n\t\t\tsetIsOpen(false)\n\t\t\t// Reset first show state after tooltip is hidden\n\t\t\tisFirstShowRef.current = true\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (timer !== null) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t}\n\t\t}\n\t}, [currentTooltip])\n\n\tif (!currentTooltip) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<_Tooltip.Root open={isOpen} delayDuration={0}>\n\t\t\t<_Tooltip.Trigger asChild>\n\t\t\t\t<div ref={triggerRef} />\n\t\t\t</_Tooltip.Trigger>\n\t\t\t<_Tooltip.Content\n\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\tside={currentTooltip.side}\n\t\t\t\tsideOffset={currentTooltip.sideOffset}\n\t\t\t\tavoidCollisions\n\t\t\t\tcollisionPadding={8}\n\t\t\t\tdir=\"ltr\"\n\t\t\t>\n\t\t\t\t{currentTooltip.content}\n\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t</_Tooltip.Content>\n\t\t</_Tooltip.Root>\n\t)\n}\n\n/** @public @react */\nexport const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(\n\t(\n\t\t{\n\t\t\tchildren,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset = 5,\n\t\t\tdisabled = false,\n\t\t\tshowOnMobile = false,\n\t\t\tdelayDuration,\n\t\t},\n\t\tref\n\t) => {\n\t\tconst editor = useMaybeEditor()\n\t\tconst tooltipId = useRef<string>(uniqueId())\n\t\tconst hasProvider = useContext(TooltipSingletonContext)\n\t\tconst showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])\n\n\t\tconst orientationCtx = useTldrawUiOrientation()\n\t\tconst sideToUse = side ?? orientationCtx.tooltipSide\n\n\t\tuseEffect(() => {\n\t\t\tconst currentTooltipId = tooltipId.current\n\t\t\treturn () => {\n\t\t\t\tif (hasProvider) {\n\t\t\t\t\ttooltipManager.hideTooltip(editor, currentTooltipId, true)\n\t\t\t\t}\n\t\t\t}\n\t\t}, [editor, hasProvider])\n\n\t\tuseLayoutEffect(() => {\n\t\t\tif (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {\n\t\t\t\ttooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({\n\t\t\t\t\t...tooltip,\n\t\t\t\t\tcontent,\n\t\t\t\t\tside: sideToUse,\n\t\t\t\t\tsideOffset,\n\t\t\t\t\tshowOnMobile,\n\t\t\t\t}))\n\t\t\t}\n\t\t}, [content, sideToUse, sideOffset, showOnMobile, hasProvider])\n\n\t\t// Don't show tooltip if disabled, no content, or UI labels are disabled\n\t\tif (disabled || !content) {\n\t\t\treturn <>{children}</>\n\t\t}\n\n\t\tlet delayDurationToUse\n\t\tif (showUiLabels) {\n\t\t\tdelayDurationToUse = 0\n\t\t} else {\n\t\t\tdelayDurationToUse =\n\t\t\t\tdelayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)\n\t\t}\n\n\t\t// Fallback to old behavior if no provider\n\t\tif (!hasProvider || showUiLabels) {\n\t\t\treturn (\n\t\t\t\t<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent={!showUiLabels}>\n\t\t\t\t\t<_Tooltip.Trigger asChild ref={ref}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</_Tooltip.Trigger>\n\t\t\t\t\t<_Tooltip.Content\n\t\t\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\t\t\tside={sideToUse}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tavoidCollisions\n\t\t\t\t\t\tcollisionPadding={8}\n\t\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t\t\t</_Tooltip.Content>\n\t\t\t\t</_Tooltip.Root>\n\t\t\t)\n\t\t}\n\n\t\tconst child = React.Children.only(children)\n\t\tassert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')\n\n\t\tconst handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseEnter?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseLeave?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst handleFocus = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onFocus?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleBlur = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onBlur?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst childrenWithHandlers = React.cloneElement(children as React.ReactElement, {\n\t\t\tonMouseEnter: handleMouseEnter,\n\t\t\tonMouseLeave: handleMouseLeave,\n\t\t\tonFocus: handleFocus,\n\t\t\tonBlur: handleBlur,\n\t\t})\n\n\t\treturn childrenWithHandlers\n\t}\n)\n"],
5
+ "mappings": "AA+IG,SA0JO,UAxJN,KAFD;AA/IH,SAAS,QAAc,MAAc,UAAU,gBAAgB,gBAAgB;AAC/E,SAAS,WAAW,gBAAgB;AACpC,OAAO;AAAA,EACN;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,8BAA8B;AAEvC,MAAM,2BAA2B;AAwBjC,MAAM,eAAe;AAAA,EACpB,OAAe,WAAkC;AAAA,EACzC,iBAAiB,KAA4B,mBAAmB,IAAI;AAAA,EACpE,mBAAkC;AAAA,EAE1C,OAAO,cAA8B;AACpC,QAAI,CAAC,eAAe,UAAU;AAC7B,qBAAe,WAAW,IAAI,eAAe;AAAA,IAC9C;AACA,WAAO,eAAe;AAAA,EACvB;AAAA,EAEA,YACC,WACA,SACA,eACA,MACA,YACA,cACA,eACC;AAED,QAAI,KAAK,kBAAkB;AAC1B,mBAAa,KAAK,gBAAgB;AAClC,WAAK,mBAAmB;AAAA,IACzB;AAGA,SAAK,eAAe,IAAI;AAAA,MACvB,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,qBAAqB,WAAmB,QAAqD;AAC5F,SAAK,eAAe,OAAO,CAAC,YAAY;AACvC,UAAI,SAAS,OAAO,WAAW;AAC9B,eAAO,OAAO,OAAO;AAAA,MACtB;AACA,aAAO;AAAA,IACR,CAAC;AAAA,EACF;AAAA,EAEA,YAAY,QAAuB,WAAmB,UAAmB,OAAO;AAC/E,UAAM,OAAO,MAAM;AAElB,UAAI,KAAK,eAAe,IAAI,GAAG,OAAO,WAAW;AAChD,aAAK,eAAe,IAAI,IAAI;AAC5B,aAAK,mBAAmB;AAAA,MACzB;AAAA,IACD;AAEA,QAAI,UAAU,CAAC,SAAS;AAEvB,WAAK,mBAAmB,OAAO,OAAO,WAAW,MAAM,GAAG;AAAA,IAC3D,OAAO;AACN,WAAK;AAAA,IACN;AAAA,EACD;AAAA,EAEA,kBAAkB;AACjB,SAAK,eAAe,IAAI,IAAI;AAC5B,SAAK,mBAAmB;AAAA,EACzB;AAAA,EAEA,wBAAwB;AACvB,UAAM,iBAAiB,KAAK,eAAe,IAAI;AAC/C,QAAI,CAAC,eAAgB,QAAO;AAC5B,QAAI,CAAC,KAAK,cAAc,KAAK,CAAC,eAAe,aAAc,QAAO;AAClE,WAAO;AAAA,EACR;AAAA,EAEQ,oBAA0C;AAAA,EAClD,gBAAgB;AACf,QAAI,CAAC,KAAK,mBAAmB;AAC5B,YAAM,aAAa,OAAO,WAAW,gBAAgB;AACrD,YAAM,gBAAgB,KAAK,aAAa,WAAW,OAAO;AAC1D,WAAK,oBAAoB;AACzB,iBAAW,iBAAiB,UAAU,CAAC,MAAM;AAC5C,sBAAc,IAAI,EAAE,OAAO;AAAA,MAC5B,CAAC;AAAA,IACF;AACA,WAAO,KAAK,kBAAkB,IAAI;AAAA,EACnC;AACD;AAEO,MAAM,iBAAiB,eAAe,YAAY;AAGzD,MAAM,0BAA0B,cAAuB,KAAK;AAQrD,SAAS,wBAAwB,EAAE,SAAS,GAAiC;AACnF,SACC,oBAAC,SAAS,UAAT,EAAkB,mBAAmB,KACrC,+BAAC,wBAAwB,UAAxB,EAAiC,OAAO,MACvC;AAAA;AAAA,IACD,oBAAC,oBAAiB;AAAA,KACnB,GACD;AAEF;AAGA,SAAS,mBAAmB;AAC3B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,aAAa,OAAuB,IAAI;AAC9C,QAAM,iBAAiB,OAAO,IAAI;AAClC,QAAM,SAAS,eAAe;AAE9B,QAAM,iBAAiB;AAAA,IACtB;AAAA,IACA,MAAM,eAAe,sBAAsB;AAAA,IAC3C,CAAC;AAAA,EACF;AAEA,QAAM,cAAc,SAAS,gBAAgB,MAAM,QAAQ,eAAe,GAAG,CAAC,MAAM,CAAC;AAGrF,YAAU,MAAM;AACf,QAAI,gBAAgB,YAAY,UAAU,gBAAgB;AACzD,qBAAe,YAAY,QAAQ,eAAe,IAAI,IAAI;AAAA,IAC3D;AAAA,EACD,GAAG,CAAC,aAAa,QAAQ,gBAAgB,MAAM,CAAC;AAEhD,YAAU,MAAM;AACf,aAAS,cAAc,OAAsB;AAC5C,UAAI,MAAM,QAAQ,YAAY,kBAAkB,QAAQ;AACvD,uBAAe,YAAY,QAAQ,eAAe,EAAE;AACpD,cAAM,gBAAgB;AAAA,MACvB;AAAA,IACD;AAEA,aAAS,iBAAiB,WAAW,eAAe,EAAE,SAAS,KAAK,CAAC;AACrE,WAAO,MAAM;AACZ,eAAS,oBAAoB,WAAW,eAAe,EAAE,SAAS,KAAK,CAAC;AAAA,IACzE;AAAA,EACD,GAAG,CAAC,QAAQ,gBAAgB,MAAM,CAAC;AAGnC,YAAU,MAAM;AACf,QAAI,QAA8C;AAClD,QAAI,kBAAkB,WAAW,SAAS;AAEzC,YAAM,aAAa,eAAe,cAAc,sBAAsB;AACtE,YAAM,UAAU,WAAW;AAE3B,cAAQ,MAAM,WAAW;AACzB,cAAQ,MAAM,OAAO,GAAG,WAAW,IAAI;AACvC,cAAQ,MAAM,MAAM,GAAG,WAAW,GAAG;AACrC,cAAQ,MAAM,QAAQ,GAAG,WAAW,KAAK;AACzC,cAAQ,MAAM,SAAS,GAAG,WAAW,MAAM;AAC3C,cAAQ,MAAM,gBAAgB;AAC9B,cAAQ,MAAM,SAAS;AAGvB,UAAI,eAAe,SAAS;AAE3B,gBAAQ,WAAW,MAAM;AACxB,oBAAU,IAAI;AACd,yBAAe,UAAU;AAAA,QAC1B,GAAG,eAAe,aAAa;AAAA,MAChC,OAAO;AAEN,kBAAU,IAAI;AAAA,MACf;AAAA,IACD,OAAO;AAEN,gBAAU,KAAK;AAEf,qBAAe,UAAU;AAAA,IAC1B;AAEA,WAAO,MAAM;AACZ,UAAI,UAAU,MAAM;AACnB,qBAAa,KAAK;AAAA,MACnB;AAAA,IACD;AAAA,EACD,GAAG,CAAC,cAAc,CAAC;AAEnB,MAAI,CAAC,gBAAgB;AACpB,WAAO;AAAA,EACR;AAEA,SACC,qBAAC,SAAS,MAAT,EAAc,MAAM,QAAQ,eAAe,GAC3C;AAAA,wBAAC,SAAS,SAAT,EAAiB,SAAO,MACxB,8BAAC,SAAI,KAAK,YAAY,GACvB;AAAA,IACA;AAAA,MAAC,SAAS;AAAA,MAAT;AAAA,QACA,WAAU;AAAA,QACV,MAAM,eAAe;AAAA,QACrB,YAAY,eAAe;AAAA,QAC3B,iBAAe;AAAA,QACf,kBAAkB;AAAA,QAClB,KAAI;AAAA,QAEH;AAAA,yBAAe;AAAA,UAChB,oBAAC,SAAS,OAAT,EAAe,WAAU,uBAAsB;AAAA;AAAA;AAAA,IACjD;AAAA,KACD;AAEF;AAGO,MAAM,kBAAkB;AAAA,EAC9B,CACC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,WAAW;AAAA,IACX,eAAe;AAAA,IACf;AAAA,EACD,GACA,QACI;AACJ,UAAM,SAAS,eAAe;AAC9B,UAAM,YAAY,OAAe,SAAS,CAAC;AAC3C,UAAM,cAAc,WAAW,uBAAuB;AACtD,UAAM,eAAe,SAAS,gBAAgB,MAAM,QAAQ,KAAK,gBAAgB,GAAG,CAAC,MAAM,CAAC;AAE5F,UAAM,iBAAiB,uBAAuB;AAC9C,UAAM,YAAY,QAAQ,eAAe;AAEzC,cAAU,MAAM;AACf,YAAM,mBAAmB,UAAU;AACnC,aAAO,MAAM;AACZ,YAAI,aAAa;AAChB,yBAAe,YAAY,QAAQ,kBAAkB,IAAI;AAAA,QAC1D;AAAA,MACD;AAAA,IACD,GAAG,CAAC,QAAQ,WAAW,CAAC;AAExB,oBAAgB,MAAM;AACrB,UAAI,eAAe,eAAe,sBAAsB,GAAG,OAAO,UAAU,SAAS;AACpF,uBAAe,qBAAqB,UAAU,SAAS,CAAC,aAAa;AAAA,UACpE,GAAG;AAAA,UACH;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACD,EAAE;AAAA,MACH;AAAA,IACD,GAAG,CAAC,SAAS,WAAW,YAAY,cAAc,WAAW,CAAC;AAG9D,QAAI,YAAY,CAAC,SAAS;AACzB,aAAO,gCAAG,UAAS;AAAA,IACpB;AAEA,QAAI;AACJ,QAAI,cAAc;AACjB,2BAAqB;AAAA,IACtB,OAAO;AACN,2BACC,kBAAkB,QAAQ,QAAQ,kBAAkB;AAAA,IACtD;AAGA,QAAI,CAAC,eAAe,cAAc;AACjC,aACC,qBAAC,SAAS,MAAT,EAAc,eAAe,oBAAoB,yBAAyB,CAAC,cAC3E;AAAA,4BAAC,SAAS,SAAT,EAAiB,SAAO,MAAC,KACxB,UACF;AAAA,QACA;AAAA,UAAC,SAAS;AAAA,UAAT;AAAA,YACA,WAAU;AAAA,YACV,MAAM;AAAA,YACN;AAAA,YACA,iBAAe;AAAA,YACf,kBAAkB;AAAA,YAClB,KAAI;AAAA,YAEH;AAAA;AAAA,cACD,oBAAC,SAAS,OAAT,EAAe,WAAU,uBAAsB;AAAA;AAAA;AAAA,QACjD;AAAA,SACD;AAAA,IAEF;AAEA,UAAM,QAAQ,MAAM,SAAS,KAAK,QAAQ;AAC1C,WAAO,MAAM,eAAe,KAAK,GAAG,mDAAmD;AAEvF,UAAM,mBAAmB,CAAC,UAAyC;AAClE,YAAM,MAAM,eAAe,KAAK;AAChC,qBAAe;AAAA,QACd,UAAU;AAAA,QACV;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,mBAAmB,CAAC,UAAyC;AAClE,YAAM,MAAM,eAAe,KAAK;AAChC,qBAAe,YAAY,QAAQ,UAAU,OAAO;AAAA,IACrD;AAEA,UAAM,cAAc,CAAC,UAAyC;AAC7D,YAAM,MAAM,UAAU,KAAK;AAC3B,qBAAe;AAAA,QACd,UAAU;AAAA,QACV;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,aAAa,CAAC,UAAyC;AAC5D,YAAM,MAAM,SAAS,KAAK;AAC1B,qBAAe,YAAY,QAAQ,UAAU,OAAO;AAAA,IACrD;AAEA,UAAM,uBAAuB,MAAM,aAAa,UAAgC;AAAA,MAC/E,cAAc;AAAA,MACd,cAAc;AAAA,MACd,SAAS;AAAA,MACT,QAAQ;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACR;AACD;",
6
6
  "names": []
7
7
  }
@@ -228,7 +228,7 @@ function useDraggableEvents(onDragStart, onSelect) {
228
228
  type: "pointer",
229
229
  target: "canvas",
230
230
  name: "pointer_down",
231
- ...getPointerInfo(e),
231
+ ...getPointerInfo(editor, e),
232
232
  point: screenSpaceStart
233
233
  });
234
234
  editor.selectNone();
@@ -236,7 +236,7 @@ function useDraggableEvents(onDragStart, onSelect) {
236
236
  type: "pointer",
237
237
  target: "canvas",
238
238
  name: "pointer_move",
239
- ...getPointerInfo(e),
239
+ ...getPointerInfo(editor, e),
240
240
  point: screenSpaceStart
241
241
  });
242
242
  tooltipManager.hideAllTooltips();
@@ -252,7 +252,7 @@ function useDraggableEvents(onDragStart, onSelect) {
252
252
  type: "pointer",
253
253
  target: "canvas",
254
254
  name: "pointer_up",
255
- ...getPointerInfo(e)
255
+ ...getPointerInfo(editor, e)
256
256
  });
257
257
  }
258
258
  function handleClick() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx"],
4
- "sourcesContent": ["import {\n\texhaustiveSwitchError,\n\tgetPointerInfo,\n\tpreventDefault,\n\tTLPointerEventInfo,\n\tuseEditor,\n\tVec,\n\tVecModel,\n} from '@tldraw/editor'\nimport { ContextMenu as _ContextMenu } from 'radix-ui'\nimport { useMemo, useState } from 'react'\nimport { unwrapLabel } from '../../../context/actions'\nimport { TLUiEventSource } from '../../../context/events'\nimport { useReadonly } from '../../../hooks/useReadonly'\nimport { TLUiToolItem } from '../../../hooks/useTools'\nimport { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../../hooks/useTranslation/useTranslation'\nimport { kbdStr } from '../../../kbd-utils'\nimport { Spinner } from '../../Spinner'\nimport { TldrawUiButton } from '../Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from '../Button/TldrawUiButtonIcon'\nimport { TldrawUiButtonLabel } from '../Button/TldrawUiButtonLabel'\nimport { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'\nimport { TLUiIconJsx } from '../TldrawUiIcon'\nimport { TldrawUiKbd } from '../TldrawUiKbd'\nimport { TldrawUiToolbarButton } from '../TldrawUiToolbar'\nimport { tooltipManager } from '../TldrawUiTooltip'\nimport { useTldrawUiMenuContext } from './TldrawUiMenuContext'\n\n/** @public */\nexport interface TLUiMenuItemProps<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\t/**\n\t * The icon to display on the item. Icons are only shown in certain menu types.\n\t */\n\ticon?: IconType | TLUiIconJsx\n\t/**\n\t * An icon to display to the left of the menu item.\n\t */\n\ticonLeft?: IconType | TLUiIconJsx\n\t/**\n\t * The keyboard shortcut to display on the item.\n\t */\n\tkbd?: string\n\t/**\n\t * The label to display on the item. If it's a string, it will be translated. If it's an object, the keys will be used as the language keys and the values will be translated.\n\t */\n\tlabel?: TranslationKey | { [key: string]: TranslationKey }\n\t/**\n\t * If the editor is in readonly mode and the item is not marked as readonlyok, it will not be rendered.\n\t */\n\treadonlyOk?: boolean\n\t/**\n\t * The function to call when the item is clicked.\n\t */\n\tonSelect(source: TLUiEventSource): Promise<void> | void\n\t/**\n\t * Whether this item should be disabled.\n\t */\n\tdisabled?: boolean\n\t/**\n\t * Prevent the menu from closing when the item is clicked\n\t */\n\tnoClose?: boolean\n\t/**\n\t * Whether to show a spinner on the item.\n\t */\n\tspinner?: boolean\n\t/**\n\t * Whether the item is selected.\n\t */\n\tisSelected?: boolean\n\t/**\n\t * The function to call when the item is dragged. If this is provided, the item will be draggable.\n\t */\n\tonDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void\n}\n\n/** @public @react */\nexport function TldrawUiMenuItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n>({\n\tdisabled = false,\n\tspinner = false,\n\treadonlyOk = false,\n\tid,\n\tkbd,\n\tlabel,\n\ticon,\n\ticonLeft,\n\tonSelect,\n\tnoClose,\n\tisSelected,\n\tonDragStart,\n}: TLUiMenuItemProps<TranslationKey, IconType>) {\n\tconst { type: menuType, sourceId } = useTldrawUiMenuContext()\n\n\tconst msg = useTranslation()\n\n\tconst [disableClicks, setDisableClicks] = useState(false)\n\n\tconst isReadonlyMode = useReadonly()\n\tif (isReadonlyMode && !readonlyOk) return null\n\n\tconst labelToUse = unwrapLabel(label, menuType)\n\tconst kbdToUse = kbd ? kbdStr(kbd) : undefined\n\n\tconst labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined\n\tconst titleStr = labelStr && kbdToUse ? `${labelStr} ${kbdToUse}` : labelStr\n\n\tswitch (menuType) {\n\t\tcase 'menu': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiDropdownMenuItem>\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"menu\"\n\t\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (noClose) {\n\t\t\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (disableClicks) {\n\t\t\t\t\t\t\t\tsetDisableClicks(false)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tonSelect(sourceId)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{iconLeft && <TldrawUiButtonIcon icon={iconLeft} small />}\n\t\t\t\t\t\t<TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>\n\t\t\t\t\t\t{kbd && <TldrawUiKbd>{kbd}</TldrawUiKbd>}\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t)\n\t\t}\n\t\tcase 'context-menu': {\n\t\t\t// Hide disabled context menu items\n\t\t\tif (disabled) return null\n\n\t\t\treturn (\n\t\t\t\t<_ContextMenu.Item\n\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\tdraggable={false}\n\t\t\t\t\tclassName=\"tlui-button tlui-button__menu\"\n\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\tonSelect={(e) => {\n\t\t\t\t\t\tif (noClose) preventDefault(e)\n\t\t\t\t\t\tif (disableClicks) {\n\t\t\t\t\t\t\tsetDisableClicks(false)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tonSelect(sourceId)\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"tlui-button__label\" draggable={false}>\n\t\t\t\t\t\t{labelStr}\n\t\t\t\t\t</span>\n\t\t\t\t\t{iconLeft && <TldrawUiButtonIcon icon={iconLeft} small />}\n\t\t\t\t\t{kbd && <TldrawUiKbd>{kbd}</TldrawUiKbd>}\n\t\t\t\t\t{spinner && <Spinner />}\n\t\t\t\t</_ContextMenu.Item>\n\t\t\t)\n\t\t}\n\t\tcase 'small-icons':\n\t\tcase 'icons': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect(sourceId)}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} small />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tcase 'keyboard-shortcuts': {\n\t\t\tif (!kbd) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Menu item '${label}' isn't shown in the keyboard shortcuts dialog because it doesn't have a keyboard shortcut.`\n\t\t\t\t)\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair\" data-testid={`${sourceId}.${id}`}>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair__key\">{labelStr}</div>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair__value\">\n\t\t\t\t\t\t<TldrawUiKbd visibleOnMobileLayout>{kbd}</TldrawUiKbd>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'helper-buttons': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiButton type=\"low\" onClick={() => onSelect(sourceId)}>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t\t<TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>\n\t\t\t\t</TldrawUiButton>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar': {\n\t\t\tif (onDragStart) {\n\t\t\t\treturn (\n\t\t\t\t\t<DraggableToolbarButton\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\ticon={icon}\n\t\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\t\tonDragStart={onDragStart}\n\t\t\t\t\t\tlabelStr={labelStr}\n\t\t\t\t\t\ttitleStr={titleStr}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\taria-label={labelStr}\n\t\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\t\tdata-testid={`tools.${id}`}\n\t\t\t\t\tdata-value={id}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect('toolbar')}\n\t\t\t\t\tonTouchStart={(e) => {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\tonSelect('toolbar')\n\t\t\t\t\t}}\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\ttype=\"tool\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar-overflow': {\n\t\t\tif (onDragStart) {\n\t\t\t\treturn (\n\t\t\t\t\t<DraggableToolbarButton\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\ticon={icon}\n\t\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\t\tonDragStart={onDragStart}\n\t\t\t\t\t\tlabelStr={labelStr}\n\t\t\t\t\t\ttitleStr={titleStr}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\toverflow\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\taria-label={labelStr}\n\t\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\t\tisActive={isSelected}\n\t\t\t\t\tdata-testid={`tools.more.${id}`}\n\t\t\t\t\tdata-value={id}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect('toolbar')}\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tdefault: {\n\t\t\tthrow exhaustiveSwitchError(menuType)\n\t\t}\n\t}\n}\n\nfunction useDraggableEvents(\n\tonDragStart: TLUiToolItem['onDragStart'],\n\tonSelect: TLUiToolItem['onSelect']\n) {\n\tconst editor = useEditor()\n\tconst events = useMemo(() => {\n\t\tlet state = { name: 'idle' } as\n\t\t\t| {\n\t\t\t\t\tname: 'idle'\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'pointing'\n\t\t\t\t\tscreenSpaceStart: VecModel\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'dragging'\n\t\t\t\t\tscreenSpaceStart: VecModel\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'dragged'\n\t\t\t }\n\n\t\tfunction handlePointerDown(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tstate = {\n\t\t\t\tname: 'pointing',\n\t\t\t\tscreenSpaceStart: { x: e.clientX, y: e.clientY },\n\t\t\t}\n\n\t\t\te.currentTarget.setPointerCapture(e.pointerId)\n\t\t}\n\n\t\tfunction handlePointerMove(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\n\t\t\tif (state.name === 'pointing') {\n\t\t\t\tconst distanceSq = Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY })\n\t\t\t\tif (\n\t\t\t\t\tdistanceSq >\n\t\t\t\t\t(editor.getInstanceState().isCoarsePointer\n\t\t\t\t\t\t? editor.options.uiCoarseDragDistanceSquared\n\t\t\t\t\t\t: editor.options.uiDragDistanceSquared)\n\t\t\t\t) {\n\t\t\t\t\tconst screenSpaceStart = state.screenSpaceStart\n\t\t\t\t\tstate = {\n\t\t\t\t\t\tname: 'dragging',\n\t\t\t\t\t\tscreenSpaceStart,\n\t\t\t\t\t}\n\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setCurrentTool('select')\n\n\t\t\t\t\t\t// Set origin point\n\t\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t\t\t...getPointerInfo(e),\n\t\t\t\t\t\t\tpoint: screenSpaceStart,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t// Pointer down potentially selects shapes, so we need to deselect them.\n\t\t\t\t\t\teditor.selectNone()\n\n\t\t\t\t\t\t// start drag\n\t\t\t\t\t\tonDragStart?.('toolbar', {\n\t\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t\t\t...getPointerInfo(e),\n\t\t\t\t\t\t\tpoint: screenSpaceStart,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\ttooltipManager.hideAllTooltips()\n\t\t\t\t\t\teditor.getContainer().focus()\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction handlePointerUp(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\n\t\t\te.currentTarget.releasePointerCapture(e.pointerId)\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_up',\n\t\t\t\t...getPointerInfo(e),\n\t\t\t})\n\t\t}\n\n\t\tfunction handleClick() {\n\t\t\tif (state.name === 'dragging' || state.name === 'dragged') {\n\t\t\t\tstate = { name: 'idle' }\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tstate = { name: 'idle' }\n\t\t\tonSelect?.('toolbar')\n\t\t}\n\n\t\treturn {\n\t\t\tonPointerDown: handlePointerDown,\n\t\t\tonPointerMove: handlePointerMove,\n\t\t\tonPointerUp: handlePointerUp,\n\t\t\tonClick: handleClick,\n\t\t}\n\t}, [onDragStart, editor, onSelect])\n\n\treturn events\n}\n\nfunction DraggableToolbarButton({\n\tid,\n\tlabelStr,\n\ttitleStr,\n\tdisabled,\n\tisSelected,\n\ticon,\n\tonSelect,\n\tonDragStart,\n\toverflow,\n}: {\n\tid: string\n\tdisabled: boolean\n\tlabelStr?: string\n\ttitleStr?: string\n\tisSelected?: boolean\n\ticon: TLUiMenuItemProps['icon']\n\tonSelect: TLUiMenuItemProps['onSelect']\n\tonDragStart: TLUiMenuItemProps['onDragStart']\n\toverflow?: boolean\n}) {\n\tconst events = useDraggableEvents(onDragStart, onSelect)\n\n\tif (overflow) {\n\t\treturn (\n\t\t\t<TldrawUiToolbarButton\n\t\t\t\taria-label={labelStr}\n\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\tisActive={isSelected}\n\t\t\t\tclassName=\"tlui-button-grid__button\"\n\t\t\t\tdata-testid={`tools.more.${id}`}\n\t\t\t\tdata-value={id}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttitle={titleStr}\n\t\t\t\ttype=\"icon\"\n\t\t\t\t{...events}\n\t\t\t>\n\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t</TldrawUiToolbarButton>\n\t\t)\n\t}\n\n\treturn (\n\t\t<TldrawUiToolbarButton\n\t\t\taria-label={labelStr}\n\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\tdata-testid={`tools.${id}`}\n\t\t\tdata-value={id}\n\t\t\tdisabled={disabled}\n\t\t\tonTouchStart={(e) => {\n\t\t\t\tpreventDefault(e)\n\t\t\t\tonSelect('toolbar')\n\t\t\t}}\n\t\t\ttitle={titleStr}\n\t\t\ttype=\"tool\"\n\t\t\t{...events}\n\t\t>\n\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t</TldrawUiToolbarButton>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\texhaustiveSwitchError,\n\tgetPointerInfo,\n\tpreventDefault,\n\tTLPointerEventInfo,\n\tuseEditor,\n\tVec,\n\tVecModel,\n} from '@tldraw/editor'\nimport { ContextMenu as _ContextMenu } from 'radix-ui'\nimport { useMemo, useState } from 'react'\nimport { unwrapLabel } from '../../../context/actions'\nimport { TLUiEventSource } from '../../../context/events'\nimport { useReadonly } from '../../../hooks/useReadonly'\nimport { TLUiToolItem } from '../../../hooks/useTools'\nimport { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../../hooks/useTranslation/useTranslation'\nimport { kbdStr } from '../../../kbd-utils'\nimport { Spinner } from '../../Spinner'\nimport { TldrawUiButton } from '../Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from '../Button/TldrawUiButtonIcon'\nimport { TldrawUiButtonLabel } from '../Button/TldrawUiButtonLabel'\nimport { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'\nimport { TLUiIconJsx } from '../TldrawUiIcon'\nimport { TldrawUiKbd } from '../TldrawUiKbd'\nimport { TldrawUiToolbarButton } from '../TldrawUiToolbar'\nimport { tooltipManager } from '../TldrawUiTooltip'\nimport { useTldrawUiMenuContext } from './TldrawUiMenuContext'\n\n/** @public */\nexport interface TLUiMenuItemProps<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\t/**\n\t * The icon to display on the item. Icons are only shown in certain menu types.\n\t */\n\ticon?: IconType | TLUiIconJsx\n\t/**\n\t * An icon to display to the left of the menu item.\n\t */\n\ticonLeft?: IconType | TLUiIconJsx\n\t/**\n\t * The keyboard shortcut to display on the item.\n\t */\n\tkbd?: string\n\t/**\n\t * The label to display on the item. If it's a string, it will be translated. If it's an object, the keys will be used as the language keys and the values will be translated.\n\t */\n\tlabel?: TranslationKey | { [key: string]: TranslationKey }\n\t/**\n\t * If the editor is in readonly mode and the item is not marked as readonlyok, it will not be rendered.\n\t */\n\treadonlyOk?: boolean\n\t/**\n\t * The function to call when the item is clicked.\n\t */\n\tonSelect(source: TLUiEventSource): Promise<void> | void\n\t/**\n\t * Whether this item should be disabled.\n\t */\n\tdisabled?: boolean\n\t/**\n\t * Prevent the menu from closing when the item is clicked\n\t */\n\tnoClose?: boolean\n\t/**\n\t * Whether to show a spinner on the item.\n\t */\n\tspinner?: boolean\n\t/**\n\t * Whether the item is selected.\n\t */\n\tisSelected?: boolean\n\t/**\n\t * The function to call when the item is dragged. If this is provided, the item will be draggable.\n\t */\n\tonDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void\n}\n\n/** @public @react */\nexport function TldrawUiMenuItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n>({\n\tdisabled = false,\n\tspinner = false,\n\treadonlyOk = false,\n\tid,\n\tkbd,\n\tlabel,\n\ticon,\n\ticonLeft,\n\tonSelect,\n\tnoClose,\n\tisSelected,\n\tonDragStart,\n}: TLUiMenuItemProps<TranslationKey, IconType>) {\n\tconst { type: menuType, sourceId } = useTldrawUiMenuContext()\n\n\tconst msg = useTranslation()\n\n\tconst [disableClicks, setDisableClicks] = useState(false)\n\n\tconst isReadonlyMode = useReadonly()\n\tif (isReadonlyMode && !readonlyOk) return null\n\n\tconst labelToUse = unwrapLabel(label, menuType)\n\tconst kbdToUse = kbd ? kbdStr(kbd) : undefined\n\n\tconst labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined\n\tconst titleStr = labelStr && kbdToUse ? `${labelStr} ${kbdToUse}` : labelStr\n\n\tswitch (menuType) {\n\t\tcase 'menu': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiDropdownMenuItem>\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"menu\"\n\t\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (noClose) {\n\t\t\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (disableClicks) {\n\t\t\t\t\t\t\t\tsetDisableClicks(false)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tonSelect(sourceId)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{iconLeft && <TldrawUiButtonIcon icon={iconLeft} small />}\n\t\t\t\t\t\t<TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>\n\t\t\t\t\t\t{kbd && <TldrawUiKbd>{kbd}</TldrawUiKbd>}\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</TldrawUiDropdownMenuItem>\n\t\t\t)\n\t\t}\n\t\tcase 'context-menu': {\n\t\t\t// Hide disabled context menu items\n\t\t\tif (disabled) return null\n\n\t\t\treturn (\n\t\t\t\t<_ContextMenu.Item\n\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\tdraggable={false}\n\t\t\t\t\tclassName=\"tlui-button tlui-button__menu\"\n\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\tonSelect={(e) => {\n\t\t\t\t\t\tif (noClose) preventDefault(e)\n\t\t\t\t\t\tif (disableClicks) {\n\t\t\t\t\t\t\tsetDisableClicks(false)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tonSelect(sourceId)\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"tlui-button__label\" draggable={false}>\n\t\t\t\t\t\t{labelStr}\n\t\t\t\t\t</span>\n\t\t\t\t\t{iconLeft && <TldrawUiButtonIcon icon={iconLeft} small />}\n\t\t\t\t\t{kbd && <TldrawUiKbd>{kbd}</TldrawUiKbd>}\n\t\t\t\t\t{spinner && <Spinner />}\n\t\t\t\t</_ContextMenu.Item>\n\t\t\t)\n\t\t}\n\t\tcase 'small-icons':\n\t\tcase 'icons': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\tdata-testid={`${sourceId}.${id}`}\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect(sourceId)}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} small />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tcase 'keyboard-shortcuts': {\n\t\t\tif (!kbd) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Menu item '${label}' isn't shown in the keyboard shortcuts dialog because it doesn't have a keyboard shortcut.`\n\t\t\t\t)\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair\" data-testid={`${sourceId}.${id}`}>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair__key\">{labelStr}</div>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__key-pair__value\">\n\t\t\t\t\t\t<TldrawUiKbd visibleOnMobileLayout>{kbd}</TldrawUiKbd>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'helper-buttons': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiButton type=\"low\" onClick={() => onSelect(sourceId)}>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t\t<TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>\n\t\t\t\t</TldrawUiButton>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar': {\n\t\t\tif (onDragStart) {\n\t\t\t\treturn (\n\t\t\t\t\t<DraggableToolbarButton\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\ticon={icon}\n\t\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\t\tonDragStart={onDragStart}\n\t\t\t\t\t\tlabelStr={labelStr}\n\t\t\t\t\t\ttitleStr={titleStr}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\taria-label={labelStr}\n\t\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\t\tdata-testid={`tools.${id}`}\n\t\t\t\t\tdata-value={id}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect('toolbar')}\n\t\t\t\t\tonTouchStart={(e) => {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t\tonSelect('toolbar')\n\t\t\t\t\t}}\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\ttype=\"tool\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar-overflow': {\n\t\t\tif (onDragStart) {\n\t\t\t\treturn (\n\t\t\t\t\t<DraggableToolbarButton\n\t\t\t\t\t\tid={id}\n\t\t\t\t\t\ticon={icon}\n\t\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\t\tonDragStart={onDragStart}\n\t\t\t\t\t\tlabelStr={labelStr}\n\t\t\t\t\t\ttitleStr={titleStr}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\toverflow\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\taria-label={labelStr}\n\t\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\t\tisActive={isSelected}\n\t\t\t\t\tdata-testid={`tools.more.${id}`}\n\t\t\t\t\tdata-value={id}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonClick={() => onSelect('toolbar')}\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t)\n\t\t}\n\t\tdefault: {\n\t\t\tthrow exhaustiveSwitchError(menuType)\n\t\t}\n\t}\n}\n\nfunction useDraggableEvents(\n\tonDragStart: TLUiToolItem['onDragStart'],\n\tonSelect: TLUiToolItem['onSelect']\n) {\n\tconst editor = useEditor()\n\tconst events = useMemo(() => {\n\t\tlet state = { name: 'idle' } as\n\t\t\t| {\n\t\t\t\t\tname: 'idle'\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'pointing'\n\t\t\t\t\tscreenSpaceStart: VecModel\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'dragging'\n\t\t\t\t\tscreenSpaceStart: VecModel\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\tname: 'dragged'\n\t\t\t }\n\n\t\tfunction handlePointerDown(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tstate = {\n\t\t\t\tname: 'pointing',\n\t\t\t\tscreenSpaceStart: { x: e.clientX, y: e.clientY },\n\t\t\t}\n\n\t\t\te.currentTarget.setPointerCapture(e.pointerId)\n\t\t}\n\n\t\tfunction handlePointerMove(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\n\t\t\tif (state.name === 'pointing') {\n\t\t\t\tconst distanceSq = Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY })\n\t\t\t\tif (\n\t\t\t\t\tdistanceSq >\n\t\t\t\t\t(editor.getInstanceState().isCoarsePointer\n\t\t\t\t\t\t? editor.options.uiCoarseDragDistanceSquared\n\t\t\t\t\t\t: editor.options.uiDragDistanceSquared)\n\t\t\t\t) {\n\t\t\t\t\tconst screenSpaceStart = state.screenSpaceStart\n\t\t\t\t\tstate = {\n\t\t\t\t\t\tname: 'dragging',\n\t\t\t\t\t\tscreenSpaceStart,\n\t\t\t\t\t}\n\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setCurrentTool('select')\n\n\t\t\t\t\t\t// Set origin point\n\t\t\t\t\t\teditor.dispatch({\n\t\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\t\tname: 'pointer_down',\n\t\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t\t\tpoint: screenSpaceStart,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\t// Pointer down potentially selects shapes, so we need to deselect them.\n\t\t\t\t\t\teditor.selectNone()\n\n\t\t\t\t\t\t// start drag\n\t\t\t\t\t\tonDragStart?.('toolbar', {\n\t\t\t\t\t\t\ttype: 'pointer',\n\t\t\t\t\t\t\ttarget: 'canvas',\n\t\t\t\t\t\t\tname: 'pointer_move',\n\t\t\t\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\t\t\t\tpoint: screenSpaceStart,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\ttooltipManager.hideAllTooltips()\n\t\t\t\t\t\teditor.getContainer().focus()\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction handlePointerUp(e: React.PointerEvent<HTMLButtonElement>) {\n\t\t\tif ((e as any).isSpecialRedispatchedEvent) return\n\n\t\t\te.currentTarget.releasePointerCapture(e.pointerId)\n\n\t\t\teditor.dispatch({\n\t\t\t\ttype: 'pointer',\n\t\t\t\ttarget: 'canvas',\n\t\t\t\tname: 'pointer_up',\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t})\n\t\t}\n\n\t\tfunction handleClick() {\n\t\t\tif (state.name === 'dragging' || state.name === 'dragged') {\n\t\t\t\tstate = { name: 'idle' }\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tstate = { name: 'idle' }\n\t\t\tonSelect?.('toolbar')\n\t\t}\n\n\t\treturn {\n\t\t\tonPointerDown: handlePointerDown,\n\t\t\tonPointerMove: handlePointerMove,\n\t\t\tonPointerUp: handlePointerUp,\n\t\t\tonClick: handleClick,\n\t\t}\n\t}, [onDragStart, editor, onSelect])\n\n\treturn events\n}\n\nfunction DraggableToolbarButton({\n\tid,\n\tlabelStr,\n\ttitleStr,\n\tdisabled,\n\tisSelected,\n\ticon,\n\tonSelect,\n\tonDragStart,\n\toverflow,\n}: {\n\tid: string\n\tdisabled: boolean\n\tlabelStr?: string\n\ttitleStr?: string\n\tisSelected?: boolean\n\ticon: TLUiMenuItemProps['icon']\n\tonSelect: TLUiMenuItemProps['onSelect']\n\tonDragStart: TLUiMenuItemProps['onDragStart']\n\toverflow?: boolean\n}) {\n\tconst events = useDraggableEvents(onDragStart, onSelect)\n\n\tif (overflow) {\n\t\treturn (\n\t\t\t<TldrawUiToolbarButton\n\t\t\t\taria-label={labelStr}\n\t\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\t\tisActive={isSelected}\n\t\t\t\tclassName=\"tlui-button-grid__button\"\n\t\t\t\tdata-testid={`tools.more.${id}`}\n\t\t\t\tdata-value={id}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttitle={titleStr}\n\t\t\t\ttype=\"icon\"\n\t\t\t\t{...events}\n\t\t\t>\n\t\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t\t</TldrawUiToolbarButton>\n\t\t)\n\t}\n\n\treturn (\n\t\t<TldrawUiToolbarButton\n\t\t\taria-label={labelStr}\n\t\t\taria-pressed={isSelected ? 'true' : 'false'}\n\t\t\tdata-testid={`tools.${id}`}\n\t\t\tdata-value={id}\n\t\t\tdisabled={disabled}\n\t\t\tonTouchStart={(e) => {\n\t\t\t\tpreventDefault(e)\n\t\t\t\tonSelect('toolbar')\n\t\t\t}}\n\t\t\ttitle={titleStr}\n\t\t\ttype=\"tool\"\n\t\t\t{...events}\n\t\t>\n\t\t\t<TldrawUiButtonIcon icon={icon!} />\n\t\t</TldrawUiToolbarButton>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import {
3
3
  assert,
4
4
  compact,
5
5
  isDefined,
6
- markEventAsHandled,
7
6
  preventDefault,
8
7
  uniq,
9
8
  useEditor,
@@ -492,7 +491,7 @@ function useNativeClipboardEvents() {
492
491
  };
493
492
  const paste = (e) => {
494
493
  if (disablingMiddleClickPaste) {
495
- markEventAsHandled(e);
494
+ editor.markEventAsHandled(e);
496
495
  return;
497
496
  }
498
497
  if (editor.getEditingShapeId() !== null || areShortcutsDisabled(editor)) return;