zaphyra's git: domsonic

subsonic web-client

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 import { ref, reactive } from 'vue'
import { useEventListener } from '@vueuse/core'

export const ContextMenu = ({ enabled = true }: { enabled?: boolean }) => {
  const
    el = ref<Element | null>(null),
    visible = ref<boolean>(false),
    position = ref({ top: 0, left: 0 })

  useEventListener(document, 'contextmenu', (event) => {
    if (
      enabled &&
      el.value &&
      event.target &&
      (event.target === el.value || el.value.contains(event.target as Element))
    ) {
      event.preventDefault()
      position.value = { top: event.offsetY, left: event.offsetX }
      visible.value = true
    } else {
      visible.value = false
    }
  })

  useEventListener(document, 'click', () => {
    visible.value = false
  })

  useEventListener(document, 'keyup', (event) => {
    if (event.key === 'Escape')
      visible.value = false
  })

  vineStyle.scoped(`
    .dropdown-menu {
      min-width: 3rem !important;
      z-index: 3000 !important;
    }
    .dropdown-menu .dropdown-item {
      z-index: 9000 !important;
    }
  `)

  const style = reactive({
    left: `${position.value.left}px`,
    top: `${position.value.top}px`,
  })

  return vine`
    <div ref="el">
      <slot />
      <ul
        v-if="enabled && visible"
        class="dropdown-menu position-absolute show"
        :style="style"
      >
        <slot name="context-menu" />
      </ul>
    </div>
  `
}