|  | @@ -0,0 +1,129 @@
 | 
	
		
			
				|  |  | +import { useApp } from '@tldraw/react'
 | 
	
		
			
				|  |  | +import { MOD_KEY} from '@tldraw/core'
 | 
	
		
			
				|  |  | +import { observer } from 'mobx-react-lite'
 | 
	
		
			
				|  |  | +import * as React from 'react'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import * as ReactContextMenu from '@radix-ui/react-context-menu'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const preventDefault = (e: Event) => e.stopPropagation()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +interface ContextMenuProps {
 | 
	
		
			
				|  |  | +  children: React.ReactNode
 | 
	
		
			
				|  |  | +  collisionRef: React.RefObject<HTMLDivElement>
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const ContextMenu = observer(function ContextMenu({ children, collisionRef }: ContextMenuProps) {
 | 
	
		
			
				|  |  | +  const app = useApp()
 | 
	
		
			
				|  |  | +  const rContent = React.useRef<HTMLDivElement>(null)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return (
 | 
	
		
			
				|  |  | +    <ReactContextMenu.Root onOpenChange={state => {if (!state) app.transition('select')}}>
 | 
	
		
			
				|  |  | +      <ReactContextMenu.Trigger>{children}</ReactContextMenu.Trigger>
 | 
	
		
			
				|  |  | +      <ReactContextMenu.Content className="tl-context-menu"
 | 
	
		
			
				|  |  | +      ref={rContent}
 | 
	
		
			
				|  |  | +      onEscapeKeyDown={preventDefault}
 | 
	
		
			
				|  |  | +      collisionBoundary={collisionRef.current}
 | 
	
		
			
				|  |  | +      asChild
 | 
	
		
			
				|  |  | +      tabIndex={-1}
 | 
	
		
			
				|  |  | +      >
 | 
	
		
			
				|  |  | +        <div>
 | 
	
		
			
				|  |  | +          {app.selectedShapes?.size > 0 && (
 | 
	
		
			
				|  |  | +            <>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                onClick={() => app.copy()}>
 | 
	
		
			
				|  |  | +                  Copy
 | 
	
		
			
				|  |  | +                  <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                    <span className="keyboard-shortcut"><code>{MOD_KEY}</code> <code>C</code></span>
 | 
	
		
			
				|  |  | +                  </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +            </>
 | 
	
		
			
				|  |  | +          )}
 | 
	
		
			
				|  |  | +          <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +            className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +            onClick={() => app.paste()}>
 | 
	
		
			
				|  |  | +              Paste
 | 
	
		
			
				|  |  | +              <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                <span className="keyboard-shortcut"><code>{MOD_KEY}</code> <code>V</code></span>
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +          </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +          <ReactContextMenu.Separator className="menu-separator"/>
 | 
	
		
			
				|  |  | +          <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +            className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +            onClick={() => app.api.selectAll()}>
 | 
	
		
			
				|  |  | +              Select All
 | 
	
		
			
				|  |  | +            <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +              <span className="keyboard-shortcut"><code>{MOD_KEY}</code> <code>A</code></span>
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +          </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +          {app.selectedShapes?.size > 1 && (
 | 
	
		
			
				|  |  | +            <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +              className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +              onClick={() => app.api.deselectAll()}>
 | 
	
		
			
				|  |  | +                Deselect All
 | 
	
		
			
				|  |  | +            </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +          )}
 | 
	
		
			
				|  |  | +          {app.selectedShapes?.size > 0 && (
 | 
	
		
			
				|  |  | +            <>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                onClick={() => app.api.deleteShapes()}>
 | 
	
		
			
				|  |  | +                Delete
 | 
	
		
			
				|  |  | +                <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                  <span className="keyboard-shortcut"><code>Del</code></span>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +              {app.selectedShapes?.size > 1 && (
 | 
	
		
			
				|  |  | +                <>
 | 
	
		
			
				|  |  | +                  <ReactContextMenu.Separator className="menu-separator"/>
 | 
	
		
			
				|  |  | +                  <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                    className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                    onClick={() => app.flipHorizontal()}>
 | 
	
		
			
				|  |  | +                      Flip Horizontally
 | 
	
		
			
				|  |  | +                  </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +                  <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                    className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                    onClick={() => app.flipVertical()}>
 | 
	
		
			
				|  |  | +                      Flip Vertically
 | 
	
		
			
				|  |  | +                  </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +                </>
 | 
	
		
			
				|  |  | +              )}
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Separator className="menu-separator"/>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                onClick={() => app.bringToFront()}>
 | 
	
		
			
				|  |  | +                  Move to Front
 | 
	
		
			
				|  |  | +                <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                  <span className="keyboard-shortcut"><code>⇧</code> <code>]</code></span>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button">
 | 
	
		
			
				|  |  | +                  Move forwards
 | 
	
		
			
				|  |  | +                <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                  <span className="keyboard-shortcut"><code>]</code></span>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                onClick={() => app.sendToBack()}>
 | 
	
		
			
				|  |  | +                  Move to back
 | 
	
		
			
				|  |  | +                <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                  <span className="keyboard-shortcut"><code>⇧</code> <code>[</code></span>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +              <ReactContextMenu.Item
 | 
	
		
			
				|  |  | +                className="tl-context-menu-button"
 | 
	
		
			
				|  |  | +                onClick={() => app.sendBackward()}>
 | 
	
		
			
				|  |  | +                  Move backwards
 | 
	
		
			
				|  |  | +                <div className="tl-context-menu-right-slot">
 | 
	
		
			
				|  |  | +                  <span className="keyboard-shortcut"><code>[</code></span>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </ReactContextMenu.Item>
 | 
	
		
			
				|  |  | +            </>
 | 
	
		
			
				|  |  | +          )}
 | 
	
		
			
				|  |  | +        </div>
 | 
	
		
			
				|  |  | +      </ReactContextMenu.Content>
 | 
	
		
			
				|  |  | +    </ReactContextMenu.Root>
 | 
	
		
			
				|  |  | +  )
 | 
	
		
			
				|  |  | +})
 |