feature/tauri-v2
svelte 112 lines 3.18 KB
Raw
1 <script lang="ts">
2 import { onMount } from "svelte";
3 import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
4 const appWindow = getCurrentWebviewWindow()
5
6 export let items = [];
7 export let target: HTMLElement = null;
8
9 export let menuOpen = false;
10
11 let cursorPos = { x: 0, y: 0 }
12 let menuPos = { h: 0, w: 0 }
13 let windowSize = { h: 0, w: 0 } // keep track of window borders
14
15 onMount(() => {
16 return () => {
17 if (target !== null) {
18 target.removeEventListener("contextmenu", openContextMenu)
19 }
20 }
21 })
22
23 async function openContextMenu(e) {
24 const appWindowSize = await appWindow.innerSize();
25 let windowWidth = appWindowSize.width;
26 let windowHeight = appWindowSize.height;
27
28 menuOpen = true;
29 windowSize = {w: windowWidth, h: windowHeight};
30 cursorPos = {x: e.clientX, y: e.clientY};
31
32 // Adjust context menu position based on where it is on the window
33 // If it overlaps with the window border then move it to the right/left/top/bottom accordingly
34 if (windowSize.h - cursorPos.y < menuPos.h) {
35 cursorPos.y = cursorPos.y - menuPos.h
36 }
37 if (windowSize.w - cursorPos.x < menuPos.w) {
38 cursorPos.x = cursorPos.x - menuPos.w
39 }
40 }
41
42 function getContextMenuDimension(node){
43 // This function will get context menu dimension
44 // when navigation is shown
45 let height = node.offsetHeight;
46 let width = node.offsetWidth;
47 menuPos = {
48 w: width,
49 h: height
50 }
51 }
52
53 $: if (target !== null) {
54 target.addEventListener("contextmenu", openContextMenu)
55 }
56 </script>
57
58 <svelte:window on:contextmenu|preventDefault on:click={(e) => {
59 menuOpen = false;
60 }} on:mouseup={(e) => {
61 if (e.button === 2) {
62 menuOpen = false;
63 }
64 }}></svelte:window>
65
66 {#if menuOpen}
67 <div use:getContextMenuDimension class="context-menu" style="top:{cursorPos.y}px; left:{cursorPos.x}px">
68 {#each items as item}
69 <!-- svelte-ignore a11y-click-events-have-key-events -->
70 <div class="context-menu-option" title="" class:disabled={item.disabled} on:click={() => {
71 if (!item.disabled) {
72 item.action();
73 }
74 }}>
75 <span class="option-name">{item.name}</span>
76 {#if item.shortcut}
77 <span class="option-shortcut">{item.shortcut}</span>
78 {/if}
79 </div>
80 {/each}
81 </div>
82 {/if}
83
84 <style lang="scss">
85 .context-menu {
86 min-width: 10rem;
87 max-width: 18rem;
88 padding: 0.25rem;
89 z-index: 9999;
90 position: absolute;
91 border-radius: 3px;
92 }
93 .context-menu-option {
94 display: flex;
95 align-items: center;
96 justify-content: space-between;
97 height: 17px;
98 padding: 6px 0;
99 width: 100%;
100 font-size: 0.875rem;
101 cursor: pointer;
102 }
103 .option-name, .option-shortcut {
104 padding: 0 10px;
105 }
106 .option-shortcut {
107 margin-left: 10px;
108 }
109 .disabled {
110 cursor: not-allowed;
111 }
112 </style>