import { useContainer, useEditor, useValue } from '@tldraw/editor' import { DropdownMenu as _DropdownMenu } from 'radix-ui' import { ReactNode, memo, useCallback } from 'react' import { PORTRAIT_BREAKPOINT } from '../../constants' import { useBreakpoint } from '../../context/breakpoints' import { useMenuIsOpen } from '../../hooks/useMenuIsOpen' import { useDirection, useTranslation } from '../../hooks/useTranslation/useTranslation' import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext' import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar' import { DefaultZoomMenuContent } from './DefaultZoomMenuContent' /** @public */ export interface TLUiZoomMenuProps { children?: ReactNode } /** @public @react */ export const DefaultZoomMenu = memo(function DefaultZoomMenu({ children }: TLUiZoomMenuProps) { const container = useContainer() const [isOpen, onOpenChange] = useMenuIsOpen('zoom menu') const dir = useDirection() // Get the zoom menu content, either the default component or the user's // override. If there's no menu content, then the user has set it to null, // so skip rendering the menu. const content = children ?? return ( <_DropdownMenu.Root dir={dir} open={isOpen} onOpenChange={onOpenChange} modal={false}> <_DropdownMenu.Portal container={container}> <_DropdownMenu.Content className="tlui-menu" side="top" align="start" alignOffset={0} sideOffset={8} collisionPadding={4} > {content} ) }) const ZoomTriggerButton = () => { const editor = useEditor() const breakpoint = useBreakpoint() const zoom = useValue('zoom', () => editor.getZoomLevel(), [editor]) const msg = useTranslation() const dir = useDirection() const handleDoubleClick = useCallback(() => { editor.resetZoom(editor.getViewportScreenCenter(), { animation: { duration: editor.options.animationMediumMs }, }) }, [editor]) const value = `${Math.floor(zoom * 100)}%` return ( <_DropdownMenu.Trigger dir={dir}> {breakpoint < PORTRAIT_BREAKPOINT.MOBILE ? null : ( {value} )} ) }