-
Notifications
You must be signed in to change notification settings - Fork 4
/
ContextMenu.svelte
70 lines (60 loc) · 1.29 KB
/
ContextMenu.svelte
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
<svelte:options accessors={true} immutable={true} />
<script lang="ts">
import { fade } from 'svelte/transition';
export let hideAfterClick: boolean = true;
export function hide(): void {
shown = false;
x = 0;
y = 0;
}
export function show(e: MouseEvent): void {
e.preventDefault();
shown = true;
x = e.clientX;
y = e.clientY;
}
let div: HTMLDivElement;
let shown = false;
let x: number;
let y: number;
$: if (div) {
const rect = div.getBoundingClientRect();
x = Math.min(window.innerWidth - rect.width, x);
if (y > window.innerHeight - rect.height) {
y -= rect.height;
}
}
function onClick() {
if (hideAfterClick) {
hide();
}
}
</script>
<svelte:body on:click={hide} />
{#if shown}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
bind:this={div}
class="context-menu"
style:left={`${x}px`}
style:top={`${y}px`}
transition:fade={{ duration: 50 }}
on:click|stopPropagation={onClick}
>
<slot />
</div>
{/if}
<style>
.context-menu {
background: #fff;
border: 1px solid var(--st-gray-30);
border-radius: 4px;
display: block;
min-height: 64px;
min-width: 150px;
outline: 0;
padding: 4px;
position: absolute;
z-index: 100;
}
</style>