File size: 1,832 Bytes
fc414a2
 
32849cc
 
759cc6f
71ff5df
fc414a2
71ff5df
fc414a2
 
71ff5df
fc414a2
71ff5df
 
fc414a2
 
71ff5df
 
 
 
fc414a2
71ff5df
fc414a2
71ff5df
 
fc414a2
71ff5df
fc414a2
32849cc
71ff5df
32849cc
 
 
71ff5df
 
32849cc
 
71ff5df
 
 
 
 
 
 
 
 
 
 
32849cc
 
71ff5df
 
32849cc
 
fc414a2
32849cc
71ff5df
 
 
32849cc
fc414a2
71ff5df
fc414a2
 
71ff5df
fc414a2
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
'use client'

import { useState } from 'react'
import type React from 'react'

import { isTextNode } from '@/hooks/useCurrentPage'
import type { PointerToDocumentFn } from '@/hooks/usePointerToDocument'
import type { Page } from '@/lib/api/schemas'

type BlockContextMenuOptions = {
  page: Page | null
  pointerToDocument: PointerToDocumentFn
  onSelect: (nodeId: string | null) => void
  onRemove: (nodeId: string) => void
}

/**
 * Right-click on a text node pops the context menu. `onSelect(null)` / clear
 * on empty-space right-click. `onRemove(id)` triggered by menu's delete item.
 */
export function useBlockContextMenu({
  page,
  pointerToDocument,
  onSelect,
  onRemove,
}: BlockContextMenuOptions) {
  const [contextMenuNodeId, setContextMenuNodeId] = useState<string | null>(null)

  const handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {
    if (!page) return
    const point = pointerToDocument(event)
    if (!point) {
      event.preventDefault()
      setContextMenuNodeId(null)
      onSelect(null)
      return
    }
    const hitId = Object.entries(page.nodes).find(([, n]) => {
      if (!isTextNode(n)) return false
      const t = n.transform
      if (!t) return false
      return (
        point.x >= t.x && point.x <= t.x + t.width && point.y >= t.y && point.y <= t.y + t.height
      )
    })?.[0]
    if (hitId) {
      onSelect(hitId)
      setContextMenuNodeId(hitId)
    } else {
      event.preventDefault()
      setContextMenuNodeId(null)
      onSelect(null)
    }
  }

  const handleDeleteBlock = () => {
    if (!contextMenuNodeId) return
    onRemove(contextMenuNodeId)
    setContextMenuNodeId(null)
  }

  const clearContextMenu = () => setContextMenuNodeId(null)

  return {
    contextMenuNodeId,
    handleContextMenu,
    handleDeleteBlock,
    clearContextMenu,
  }
}