@lemonadejs/contextmenu 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +110 -20
- package/dist/style.css +30 -15
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ if (!lemonade && typeof (require) === 'function') {
|
|
|
2
2
|
var lemonade = require('lemonadejs');
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
if (!Modal && typeof (require) === 'function') {
|
|
5
|
+
if (! Modal && typeof (require) === 'function') {
|
|
6
6
|
var Modal = require('@lemonadejs/modal');
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -12,9 +12,6 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
12
12
|
global.Contextmenu = factory();
|
|
13
13
|
}(this, (function () {
|
|
14
14
|
|
|
15
|
-
// Level
|
|
16
|
-
let index = 0;
|
|
17
|
-
|
|
18
15
|
// Get the coordinates of the action
|
|
19
16
|
const getCoords = function(e) {
|
|
20
17
|
let x;
|
|
@@ -32,11 +29,14 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
32
29
|
}
|
|
33
30
|
|
|
34
31
|
const Item = function() {
|
|
32
|
+
let self = this;
|
|
35
33
|
if (this.type === 'line') {
|
|
36
34
|
return `<hr />`;
|
|
35
|
+
} else if (this.type === 'inline') {
|
|
36
|
+
return '<div>' + this.component() + '</div>';
|
|
37
37
|
} else {
|
|
38
|
-
return `<div data-icon="{{self.icon}}" data-submenu="{{!!self.submenu}}" onmouseover="self.parent.parent.open(
|
|
39
|
-
<a>{{self.title}}</a> <
|
|
38
|
+
return `<div class="lm-menu-item" data-cursor="{{self.cursor}}" data-icon="{{self.icon}}" data-submenu="{{!!self.submenu}}" onmouseover="self.parent.parent.open(self)">
|
|
39
|
+
<a>{{self.title}}</a> <div>{{self.shortcut}}</div>
|
|
40
40
|
</div>`;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -44,38 +44,58 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
44
44
|
const Create = function() {
|
|
45
45
|
let self = this;
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
// Save the position of this modal
|
|
48
|
+
let index = self.parent.modals.length;
|
|
49
|
+
|
|
50
|
+
// Close handler
|
|
51
|
+
self.onclose = function() {
|
|
52
|
+
// if (typeof(value.modal.cursor) !== 'undefined') {
|
|
53
|
+
// value.modal.options[value.modal.cursor].cursor = false;
|
|
54
|
+
// delete value.modal.cursor;
|
|
55
|
+
// }
|
|
56
|
+
|
|
57
|
+
console.log(self.cursor,self.options);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Open handler
|
|
61
|
+
self.open = function(s) {
|
|
48
62
|
if (s.submenu) {
|
|
49
63
|
// Get the modal in the container of modals
|
|
50
|
-
let item = self.parent.modals[
|
|
64
|
+
let item = self.parent.modals[index+1];
|
|
51
65
|
if (! item) {
|
|
52
66
|
// Modal need to be created
|
|
53
67
|
item = self.parent.create();
|
|
54
68
|
}
|
|
55
69
|
// Get the parent from this one
|
|
56
|
-
let parent = self.parent.modals[
|
|
70
|
+
let parent = self.parent.modals[index].modal;
|
|
57
71
|
// Get the self of the modal
|
|
58
72
|
let modal = item.modal;
|
|
59
73
|
|
|
60
74
|
if (modal.options !== s.submenu) {
|
|
61
75
|
// Close modals with higher level
|
|
62
76
|
modal.options = s.submenu;
|
|
77
|
+
// Remove cursor
|
|
78
|
+
if (modal.cursor) {
|
|
79
|
+
delete modal.cursor;
|
|
80
|
+
}
|
|
63
81
|
// Close other modals
|
|
64
|
-
self.parent.close(
|
|
82
|
+
self.parent.close(index+1);
|
|
65
83
|
}
|
|
66
84
|
|
|
67
85
|
// Open modal
|
|
68
86
|
modal.closed = false;
|
|
87
|
+
// Update selected modal
|
|
88
|
+
self.parent.modalIndex = index+1;
|
|
69
89
|
// Define the position
|
|
70
|
-
modal.top = parent.top +
|
|
90
|
+
modal.top = parent.top + s.el.offsetTop + 2;
|
|
71
91
|
modal.left = parent.left + 248;
|
|
72
92
|
} else {
|
|
73
93
|
// Close modals with higher level
|
|
74
|
-
self.parent.close(
|
|
94
|
+
self.parent.close(index+1);
|
|
75
95
|
}
|
|
76
96
|
}
|
|
77
97
|
|
|
78
|
-
let template = `<Modal :closed="true" :ref="self.modal">
|
|
98
|
+
let template = `<Modal :closed="true" :ref="self.modal" :responsive="false" :autoadjust="true" :onclose="self.onclose">
|
|
79
99
|
<div class="lm-menu-submenu">
|
|
80
100
|
<Item :loop="self.options" />
|
|
81
101
|
</div>
|
|
@@ -84,16 +104,66 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
84
104
|
return lemonade.element(template, self, { Item: Item });
|
|
85
105
|
}
|
|
86
106
|
|
|
107
|
+
const setCursor = function(direction) {
|
|
108
|
+
let cursor = null;
|
|
109
|
+
|
|
110
|
+
if (typeof(this.cursor) !== 'undefined') {
|
|
111
|
+
if (! direction) {
|
|
112
|
+
// Up
|
|
113
|
+
cursor = this.cursor - 1;
|
|
114
|
+
if (cursor < 0) {
|
|
115
|
+
cursor = this.options.length - 1;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
// Down
|
|
119
|
+
cursor = this.cursor + 1;
|
|
120
|
+
if (cursor >= this.options.length) {
|
|
121
|
+
cursor = 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Remove the cursor
|
|
127
|
+
if (cursor === null) {
|
|
128
|
+
if (direction) {
|
|
129
|
+
cursor = 0;
|
|
130
|
+
} else {
|
|
131
|
+
cursor = this.options.length - 1;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
this.options[this.cursor].cursor = false;
|
|
135
|
+
}
|
|
136
|
+
// Add the cursor
|
|
137
|
+
this.options[cursor].cursor = true;
|
|
138
|
+
// Cursor
|
|
139
|
+
this.cursor = cursor;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const openSubmenu = function() {
|
|
143
|
+
if (typeof(this.options[this.cursor]) !== 'undefined') {
|
|
144
|
+
// Get the selected cursor
|
|
145
|
+
let item = this.options[this.cursor];
|
|
146
|
+
// Open submenu in case that exists
|
|
147
|
+
if (item.submenu) {
|
|
148
|
+
this.parent.open(item);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const closeSubmenu = function() {
|
|
154
|
+
this.parent.parent.close(this.parent.parent.modalIndex);
|
|
155
|
+
}
|
|
156
|
+
|
|
87
157
|
const Contextmenu = function() {
|
|
88
158
|
let self = this;
|
|
89
159
|
|
|
90
160
|
// Container for all modals
|
|
91
161
|
self.modals = [];
|
|
162
|
+
self.modalIndex = 0;
|
|
92
163
|
|
|
93
164
|
self.create = function() {
|
|
94
165
|
// Create a new self for each modal
|
|
95
166
|
let s = {
|
|
96
|
-
index: index++,
|
|
97
167
|
parent: self,
|
|
98
168
|
};
|
|
99
169
|
// Render the modal inside the main container
|
|
@@ -108,12 +178,12 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
108
178
|
// Get the main modal
|
|
109
179
|
let modal = self.modals[0].modal;
|
|
110
180
|
// Click on the top level menu toggle the state of the menu
|
|
111
|
-
if (e.type
|
|
181
|
+
if (e.type === 'click') {
|
|
112
182
|
modal.closed = ! modal.closed;
|
|
113
|
-
} else if (e.type
|
|
183
|
+
} else if (e.type === 'contextmenu') {
|
|
114
184
|
modal.closed = false;
|
|
115
185
|
}
|
|
116
|
-
|
|
186
|
+
|
|
117
187
|
// If the modal is open and the content is different from what is shown
|
|
118
188
|
if (modal.closed === false) {
|
|
119
189
|
// Close modals with higher level
|
|
@@ -127,22 +197,42 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
127
197
|
}
|
|
128
198
|
}
|
|
129
199
|
}
|
|
130
|
-
|
|
200
|
+
|
|
131
201
|
self.close = function(level) {
|
|
132
202
|
self.modals.forEach(function(value, k) {
|
|
133
203
|
if (k >= level) {
|
|
204
|
+
// Close the modal
|
|
134
205
|
value.modal.closed = true;
|
|
135
206
|
}
|
|
136
|
-
})
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
self.modalIndex = level ? level-1 : 0;
|
|
137
210
|
}
|
|
138
211
|
|
|
139
212
|
self.onload = function() {
|
|
140
213
|
if (! self.root) {
|
|
141
214
|
self.root = self.el.parentNode;
|
|
142
215
|
}
|
|
216
|
+
// Keyboard event
|
|
217
|
+
self.root.addEventListener("keydown", function(e) {
|
|
218
|
+
// Modal object
|
|
219
|
+
let m = self.modals[self.modalIndex].modal;
|
|
220
|
+
if (e.key === 'ArrowLeft') {
|
|
221
|
+
closeSubmenu.call(m);
|
|
222
|
+
} else if (e.key === 'ArrowRight') {
|
|
223
|
+
openSubmenu.call(m);
|
|
224
|
+
} else if (e.key === 'ArrowUp') {
|
|
225
|
+
setCursor.call(m, 0);
|
|
226
|
+
} else if (e.key === 'ArrowDown') {
|
|
227
|
+
setCursor.call(m, 1);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
143
231
|
// Create event for focus out
|
|
144
232
|
self.root.addEventListener("focusout", (e) => {
|
|
145
|
-
self.
|
|
233
|
+
if (! self.el.contains(e.relatedTarget)) {
|
|
234
|
+
self.close(0);
|
|
235
|
+
}
|
|
146
236
|
});
|
|
147
237
|
// Parent
|
|
148
238
|
self.root.addEventListener("contextmenu", function(e) {
|
package/dist/style.css
CHANGED
|
@@ -4,12 +4,29 @@
|
|
|
4
4
|
border: 1px solid transparent;
|
|
5
5
|
border-radius: 4px;
|
|
6
6
|
box-shadow: 0 2px 6px 2px rgba(60,64,67,.15);
|
|
7
|
-
max-height:
|
|
7
|
+
max-height: 300px;
|
|
8
8
|
overflow-y: auto;
|
|
9
9
|
|
|
10
10
|
width: initial;
|
|
11
11
|
height: initial;
|
|
12
|
+
min-width: 250px;
|
|
12
13
|
min-height: initial;
|
|
14
|
+
padding-bottom: 6px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.lm-menu .lm-modal::-webkit-scrollbar {
|
|
18
|
+
width: 12px;
|
|
19
|
+
height: 12px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.lm-menu .lm-modal::-webkit-scrollbar-track {
|
|
23
|
+
border: 1px solid #fff;
|
|
24
|
+
background: #eee;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.lm-menu .lm-modal::-webkit-scrollbar-thumb {
|
|
28
|
+
border: 1px solid #fff;
|
|
29
|
+
background: #888;
|
|
13
30
|
}
|
|
14
31
|
|
|
15
32
|
.lm-menu-submenu {
|
|
@@ -17,10 +34,10 @@
|
|
|
17
34
|
padding-bottom: 1px;
|
|
18
35
|
}
|
|
19
36
|
|
|
20
|
-
.lm-menu-submenu > div {
|
|
37
|
+
.lm-menu-submenu > div.lm-menu-item {
|
|
21
38
|
box-sizing: border-box;
|
|
22
39
|
display: flex;
|
|
23
|
-
padding: 0
|
|
40
|
+
padding: 0 8px 0 32px;
|
|
24
41
|
width: 250px;
|
|
25
42
|
font-size: 11px;
|
|
26
43
|
font-family:sans-serif;
|
|
@@ -28,26 +45,27 @@
|
|
|
28
45
|
align-items: center;
|
|
29
46
|
}
|
|
30
47
|
|
|
31
|
-
.lm-menu-submenu > div a {
|
|
48
|
+
.lm-menu-submenu > div.lm-menu-item a {
|
|
32
49
|
text-decoration: none;
|
|
33
50
|
flex: 1;
|
|
34
51
|
cursor: pointer;
|
|
35
52
|
line-height: 28px;
|
|
36
53
|
}
|
|
37
54
|
|
|
38
|
-
.lm-menu-submenu > div
|
|
39
|
-
margin-right:
|
|
55
|
+
.lm-menu-submenu > div.lm-menu-item div {
|
|
56
|
+
margin-right: 5px;
|
|
40
57
|
}
|
|
41
58
|
|
|
42
|
-
.lm-menu-submenu > div[data-submenu="true"]::after {
|
|
59
|
+
.lm-menu-submenu > div.lm-menu-item[data-submenu="true"]::after {
|
|
43
60
|
content: '\25B6'
|
|
44
61
|
}
|
|
45
62
|
|
|
46
|
-
.lm-menu-submenu > div.disabled {
|
|
63
|
+
.lm-menu-submenu > div.lm-menu-item.disabled {
|
|
47
64
|
color: #ccc;
|
|
48
65
|
}
|
|
49
66
|
|
|
50
|
-
.lm-menu-submenu > div:hover
|
|
67
|
+
.lm-menu-submenu > div.lm-menu-item:hover,
|
|
68
|
+
.lm-menu-submenu > div.lm-menu-item[data-cursor="true"] {
|
|
51
69
|
background: #ebebeb;
|
|
52
70
|
}
|
|
53
71
|
|
|
@@ -58,15 +76,12 @@
|
|
|
58
76
|
margin-bottom:5px;
|
|
59
77
|
}
|
|
60
78
|
|
|
61
|
-
.lm-menu-submenu > div::before {
|
|
79
|
+
.lm-menu-submenu > div.lm-menu-item::before {
|
|
62
80
|
content: attr(data-icon);
|
|
63
81
|
font-family: 'Material Icons';
|
|
64
|
-
font-size:
|
|
82
|
+
font-size: 16px;
|
|
65
83
|
position: absolute;
|
|
66
84
|
left: 9px;
|
|
67
85
|
line-height: 24px;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
.lm-menu-submenu.symbols > div::before {
|
|
71
|
-
font-family: 'Material Symbols Outlined';
|
|
86
|
+
transform: rotate(0.03deg);
|
|
72
87
|
}
|
package/package.json
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"build": "webpack --config webpack.config.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lemonadejs/modal": "^2.1
|
|
18
|
-
"lemonadejs": "^3.
|
|
17
|
+
"@lemonadejs/modal": "^2.3.1",
|
|
18
|
+
"lemonadejs": "^3.4.0"
|
|
19
19
|
},
|
|
20
20
|
"main": "dist/index.js",
|
|
21
|
-
"version": "1.0.
|
|
21
|
+
"version": "1.0.4"
|
|
22
22
|
}
|