Skip to content

Commit fb848c2

Browse files
committed
Initial commit
0 parents  commit fb848c2

26 files changed

+16350
-0
lines changed

.eslintrc.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module.exports = {
2+
root: true,
3+
4+
env: {
5+
node: true
6+
},
7+
8+
'extends': [
9+
'plugin:vue/vue3-essential',
10+
'eslint:recommended',
11+
'@vue/typescript/recommended'
12+
],
13+
14+
parserOptions: {
15+
ecmaVersion: 2020
16+
},
17+
18+
rules: {
19+
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
20+
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
21+
},
22+
23+
overrides: [
24+
{
25+
files: [
26+
'**/__tests__/*.{j,t}s?(x)',
27+
'**/tests/unit/**/*.spec.{j,t}s?(x)'
28+
],
29+
env: {
30+
mocha: true
31+
}
32+
}
33+
]
34+
}

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

.npmignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 梦欤
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
vue3-context-menu
3+
---
4+
A context menu for Vue3
5+

babel.config.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
presets: [
3+
'@vue/cli-plugin-babel/preset'
4+
],
5+
plugins: ['@vue/babel-plugin-jsx']
6+
}

examples/App.vue

+293
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
<template>
2+
<div class="test">
3+
4+
<div class="box" @contextmenu="onContextMenu($event)">
5+
Right click to show contextmenu. (Use <code>$contextmenu</code>)
6+
</div>
7+
8+
<div class="box" @click="onButtonClick($event)">
9+
Click to show contextmenu. (Use component)
10+
</div>
11+
12+
<context-menu
13+
v-model:show="show"
14+
:options="options" />
15+
16+
<div class="box2" @contextmenu="onContextMenu2($event)">
17+
Useage:
18+
<ol>
19+
<li>
20+
Import vue3-context-menu in main.js:
21+
<pre>
22+
<code class="language-javascript">
23+
import ContextMenu from 'vue3-context-menu'
24+
25+
createApp(App)
26+
.use(ContextMenu)
27+
</code>
28+
</pre>
29+
</li>
30+
<li>
31+
Add events to the elements that you want show contextmenu:
32+
<pre>
33+
<code class="language-javascript">
34+
&lt;div class="box" @contextmenu="onContextMenu($event)"&gt;
35+
</code>
36+
</pre>
37+
38+
Then show your menu:
39+
<pre>
40+
<code class="language-javascript">
41+
onContextMenu(e : MouseEvent) {
42+
//prevent the browser's default menu
43+
e.preventDefault();
44+
//shou our menu
45+
this.$contextmenu({
46+
x: e.x,
47+
y: e.y,
48+
items: [
49+
{
50+
label: "A menu item",
51+
onClick: () => {
52+
alert("You click a menu item");
53+
}
54+
},
55+
{
56+
label: "A submenu",
57+
children: [
58+
{ label: "Item1" },
59+
{ label: "Item2" },
60+
{ label: "Item3" },
61+
]
62+
},
63+
]
64+
});
65+
}
66+
</code>
67+
</pre>
68+
</li>
69+
</ol>
70+
</div>
71+
72+
</div>
73+
</template>
74+
75+
<script lang="ts">
76+
import { defineComponent } from 'vue'
77+
import { MenuOptions } from '../src/ContextMenuDefine'
78+
79+
export default defineComponent({
80+
data() {
81+
return {
82+
show: false,
83+
options: {
84+
items: [
85+
{
86+
label: "Back",
87+
onClick: () => {
88+
console.log("You click Back");
89+
}
90+
},
91+
{ label: "Forward", disabled: true },
92+
{
93+
label: "Reload",
94+
divided: true,
95+
icon: "icon-reload-1",
96+
onClick: () => {
97+
alert("You click Reload");
98+
}
99+
},
100+
{
101+
label: "Save as...",
102+
icon: "icon-save",
103+
onClick: () => {
104+
alert("You click Save as");
105+
}
106+
},
107+
{
108+
label: "Print...",
109+
icon: "icon-print",
110+
onClick: () => {
111+
alert("You click Print");
112+
}
113+
},
114+
{
115+
label: "A submenu",
116+
divided: true,
117+
children: [
118+
{
119+
label: "Reload2",
120+
divided: true,
121+
icon: "icon-reload-",
122+
onClick: () => {
123+
alert("You click Reload2");
124+
}
125+
},
126+
{
127+
label: "Very long submenu",
128+
children: [
129+
{ label: "Test1" },
130+
{ label: "Test2" },
131+
{ label: "Test3" },
132+
{ label: "Test4" },
133+
{ label: "Test5" },
134+
{ label: "Test6" },
135+
{ label: "Test7" },
136+
{ label: "Test8" },
137+
{ label: "Test9" },
138+
{ label: "Test10" },
139+
{ label: "Test11" },
140+
{ label: "Test12" },
141+
{ label: "Test13" },
142+
{ label: "Test14" },
143+
{ label: "Test15" },
144+
{ label: "Test16" },
145+
{ label: "Test17" },
146+
{ label: "Test18" },
147+
{ label: "Test19" },
148+
{ label: "Test20" },
149+
{ label: "Test21" },
150+
{ label: "Test22" },
151+
{ label: "Test23" },
152+
{ label: "Test24" },
153+
{ label: "Test25" },
154+
{ label: "Test26" },
155+
]
156+
},
157+
{
158+
label: "A submenu",
159+
children: [
160+
{ label: "Item1" },
161+
{ label: "Item2" },
162+
{ label: "Item3" },
163+
]
164+
},
165+
{
166+
label: "A submenu2",
167+
divided: true,
168+
children: [
169+
{ label: "Item1" },
170+
{ label: "Item2" },
171+
{ label: "Item3" },
172+
{
173+
label: "A submenu",
174+
children: [
175+
{ label: "Item1" },
176+
{ label: "Item2" },
177+
{ label: "Item3" },
178+
]
179+
},
180+
]
181+
},
182+
{ label: "Settings", icon: "icon-settings-1" },
183+
{ label: "View source", icon: "icon-terminal" },
184+
{ label: "Inspect" }
185+
]
186+
},
187+
{ label: "View source", icon: "icon-terminal" },
188+
{ label: "Inspect" }
189+
],
190+
iconFontClass: 'iconfont',
191+
customClass: "class-a",
192+
zIndex: 3,
193+
minWidth: 230,
194+
x: 500,
195+
y: 200
196+
} as MenuOptions,
197+
optionsCopy: {
198+
items: [
199+
{
200+
label: "Copy",
201+
onClick: () => {
202+
document.execCommand('copy');
203+
}
204+
},
205+
{ label: "Paste", disabled: true },
206+
{
207+
label: "Print",
208+
icon: 'icon-print',
209+
onClick: () => {
210+
document.execCommand('print');
211+
}
212+
},
213+
],
214+
iconFontClass: 'iconfont',
215+
customClass: "class-a",
216+
minWidth: 230,
217+
x: 0,
218+
y: 0
219+
}
220+
}
221+
},
222+
mounted() {
223+
(window as any).hljs.highlightAll();
224+
},
225+
methods: {
226+
onButtonClick(e : MouseEvent) {
227+
this.show = true;
228+
this.options.x = e.x;
229+
this.options.y = e.y;
230+
},
231+
onContextMenu(e : MouseEvent) {
232+
e.preventDefault();
233+
this.options.x = e.x;
234+
this.options.y = e.y;
235+
this.$contextmenu(this.options);
236+
},
237+
onContextMenu2(e : MouseEvent) {
238+
e.preventDefault();
239+
if(document.getSelection().toString().length > 0) {
240+
this.optionsCopy.x = e.x;
241+
this.optionsCopy.y = e.y;
242+
this.$contextmenu(this.optionsCopy);
243+
}
244+
},
245+
246+
}
247+
})
248+
</script>
249+
250+
<style>
251+
252+
253+
html, body, #app {
254+
position: relative;
255+
width: 100%;
256+
height: 100%;
257+
overflow: hidden;
258+
margin: 0;
259+
}
260+
.test {
261+
position: relative;
262+
width: 100%;
263+
height: 100%;
264+
overflow: hidden;
265+
overflow-y: scroll;
266+
}
267+
268+
.box {
269+
width: 80%;
270+
padding: 20px 60px;
271+
margin: 0 auto;
272+
margin-top: 10px;
273+
border-radius: 10px;
274+
background-color: #eeeeee;
275+
cursor: pointer;
276+
}
277+
.box:active {
278+
background-color: #dadada;
279+
}
280+
.box2 {
281+
width: 80%;
282+
padding: 20px 60px;
283+
margin: 0 auto;
284+
margin-top: 10px;
285+
border-radius: 10px;
286+
background-color: #777777;
287+
color: #fff;
288+
}
289+
code {
290+
border-radius: 10px;
291+
}
292+
293+
</style>

0 commit comments

Comments
 (0)