@lemonadejs/contextmenu 1.1.3 → 1.4.0

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 CHANGED
@@ -1,4 +1,4 @@
1
- if (!lemonade && typeof (require) === 'function') {
1
+ if (! lemonade && typeof(require) === 'function') {
2
2
  var lemonade = require('lemonadejs');
3
3
  }
4
4
 
@@ -47,7 +47,7 @@ if (! Modal && typeof (require) === 'function') {
47
47
  } else if (self.type === 'inline') {
48
48
  return `<div></div>`;
49
49
  } else {
50
- return `<div class="lm-menu-item" data-cursor="{{self.cursor}}" data-icon="{{self.icon}}" data-submenu="{{self.submenu?true:''}}" onmouseup="self.parent.parent.mouseUp(self, e)" onmouseenter="self.parent.parent.mouseEnter(self)" onmouseleave="self.parent.parent.mouseLeave(self)">
50
+ return `<div class="lm-menu-item" data-disabled="{{self.disabled}}" data-cursor="{{self.cursor}}" data-icon="{{self.icon}}" data-submenu="${!!self.submenu}" onmouseup="self.parent.mouseUp" onmouseenter="self.parent.mouseEnter" onmouseleave="self.parent.mouseLeave">
51
51
  <a>{{self.title}}</a> <div>{{self.shortcut}}</div>
52
52
  </div>`;
53
53
  }
@@ -61,10 +61,13 @@ if (! Modal && typeof (require) === 'function') {
61
61
  // Save the position of this modal
62
62
  let index = self.parent.modals.length;
63
63
 
64
+ // Blank options
65
+ self.options = [];
66
+
64
67
  // Close handler
65
68
  self.onclose = function() {
66
69
  // Reset any cursor
67
- resetCursor.call(self.modal);
70
+ resetCursor.call(self);
68
71
  // Parent
69
72
  if (typeof(self.parent.onclose) === 'function') {
70
73
  self.parent.onclose(self.parent, self);
@@ -94,39 +97,37 @@ if (! Modal && typeof (require) === 'function') {
94
97
  self.open = function(s, cursor) {
95
98
  if (s.submenu) {
96
99
  // Get the modal in the container of modals
97
- let item = self.parent.modals[index+1];
98
- if (! item) {
100
+ let current = self.parent.modals[index+1];
101
+ // Do not exist yet, create it.
102
+ if (! current) {
99
103
  // Modal need to be created
100
- item = self.parent.create();
104
+ current = self.parent.create();
101
105
  }
102
106
  // Get the parent from this one
103
- let parent = self.parent.modals[index].modal;
104
- // Get the self of the modal
105
- let modal = item.modal;
107
+ let parent = self.parent.modals[index];
106
108
  // Update modal content
107
- if (modal.options !== s.submenu) {
109
+ if (current.options !== s.submenu) {
108
110
  // Close modals with higher level
109
- modal.options = s.submenu;
111
+ current.options = s.submenu;
110
112
  // Close other modals
111
113
  self.parent.close(index+1);
112
114
  }
113
- // Open modal
114
- modal.closed = false;
115
115
  // Update selected modal
116
116
  self.parent.modalIndex = index+1;
117
- // Define the position
118
- modal.top = parent.top + s.el.offsetTop + 2;
119
- modal.left = parent.left + 248;
117
+ // Update modal
118
+ current.modal.closed = false;
119
+ current.modal.top = parent.modal.top + s.el.offsetTop + 2;
120
+ current.modal.left = parent.modal.left + 248;
120
121
 
121
122
  // Activate the cursor
122
123
  if (cursor === true) {
123
124
  // Place cursor in the first position
124
- modal.options[0].cursor = true;
125
+ current.options[0].cursor = true;
125
126
  // Position cursor
126
- modal.cursor = 0;
127
+ current.cursor = 0;
127
128
  }
128
129
 
129
- onopen(modal, s.submenu)
130
+ onopen(current, s.submenu)
130
131
  } else {
131
132
  // Close modals with higher level
132
133
  self.parent.close(index+1);
@@ -134,7 +135,7 @@ if (! Modal && typeof (require) === 'function') {
134
135
  }
135
136
 
136
137
  // Mouse open
137
- self.mouseUp = function(s, e) {
138
+ self.mouseUp = function(e, s) {
138
139
  if (typeof(s.onclick) === 'function') {
139
140
  s.onclick.call(s, e, s.el);
140
141
  }
@@ -143,7 +144,7 @@ if (! Modal && typeof (require) === 'function') {
143
144
  }
144
145
  }
145
146
 
146
- self.mouseEnter = function(s) {
147
+ self.mouseEnter = function(e, s) {
147
148
  if (delayTimer) {
148
149
  clearTimeout(delayTimer);
149
150
  }
@@ -152,17 +153,17 @@ if (! Modal && typeof (require) === 'function') {
152
153
  }, 200);
153
154
  }
154
155
 
155
- self.mouseLeave = function() {
156
+ self.mouseLeave = function(e, s) {
156
157
  if (delayTimer) {
157
158
  clearTimeout(delayTimer);
158
159
  }
159
160
  }
160
161
 
161
- let template = `<Modal position="absolute" :overflow="true" :closed="true" :ref="self.modal" :responsive="false" :auto-adjust="true" :focus="false" :layers="false" :onopen="self.onopen" :onclose="self.onclose">
162
+ let template = `<lm-modal position="absolute" :overflow="true" :closed="true" :ref="self.modal" :responsive="false" :auto-adjust="true" :focus="false" :layers="false" :onopen="self.onopen" :onclose="self.onclose">
162
163
  <div class="lm-menu-submenu">
163
164
  <Item :loop="self.options" />
164
165
  </div>
165
- </Modal>`;
166
+ </lm-modal>`;
166
167
 
167
168
  return lemonade.element(template, self, { Item: Item });
168
169
  }
@@ -196,6 +197,7 @@ if (! Modal && typeof (require) === 'function') {
196
197
  } else {
197
198
  this.options[this.cursor].cursor = false;
198
199
  }
200
+
199
201
  // Add the cursor
200
202
  this.options[cursor].cursor = true;
201
203
  // Cursor
@@ -223,40 +225,11 @@ if (! Modal && typeof (require) === 'function') {
223
225
  }
224
226
  }
225
227
 
226
- const actionCursor = function(e) {
227
- // Contextmenu modal
228
- let item = this.options[this.cursor];
229
- // Cursor is found so reset it
230
- if (typeof(item) !== 'undefined') {
231
- // Execute action
232
- if (typeof(item.onclick) === 'function') {
233
- item.onclick.call(item, e, item.el);
234
- }
235
- // Open sub menu in case exists
236
- if (item.submenu) {
237
- this.parent.open(item);
238
- return true;
239
- }
240
- }
241
- }
242
-
243
228
  /**
244
- * Open a sub option of the contextmenu by a user action
245
- * @returns {boolean}
229
+ * Go through all items of a menu
230
+ * @param s
231
+ * @param options
246
232
  */
247
- const openSubmenu = function() {
248
- // Get the selected cursor
249
- let item = this.options[this.cursor];
250
- // Open submenu
251
- if (typeof(item) !== 'undefined') {
252
- // Open submenu in case that exists
253
- if (item.submenu) {
254
- this.parent.open(item, true);
255
- return true;
256
- }
257
- }
258
- }
259
-
260
233
  const onopen = function(s, options) {
261
234
  // Onopen
262
235
  for (let i = 0; i < options.length; i++) {
@@ -280,7 +253,7 @@ if (! Modal && typeof (require) === 'function') {
280
253
  };
281
254
  // Render the modal inside the main container
282
255
  lemonade.render(Create, self.el, s);
283
- // Add the reference of the modal in a container
256
+ // Add the reference of the modal in a container#
284
257
  self.modals.push(s);
285
258
  // Return self
286
259
  return s;
@@ -288,38 +261,41 @@ if (! Modal && typeof (require) === 'function') {
288
261
 
289
262
  self.open = function(options, x, y, e) {
290
263
  // Get the main modal
291
- let modal = self.modals[0].modal;
264
+ let menu = self.modals[0];
292
265
  // Reset cursor
293
- resetCursor.call(modal);
266
+ resetCursor.call(menu);
294
267
 
295
268
  // Current state
296
269
  if (! e || e.type === 'contextmenu') {
297
- modal.closed = false;
270
+ menu.modal.closed = false;
298
271
  } else if (e.type === 'click') {
299
- modal.closed = ! modal.closed;
272
+ menu.modal.closed = ! menu.modal.closed;
300
273
  }
301
274
  // If the modal is open and the content is different from what is shown
302
- if (modal.closed === false) {
275
+ if (menu.modal.closed === false) {
303
276
  // Close modals with higher level
304
277
  self.close(1);
305
278
  // Update the data
306
- if (modal.options !== options) {
279
+ if (menu.options !== options) {
307
280
  // Refresh content
308
- modal.options = options;
281
+ menu.options = options;
309
282
  }
310
283
  // Define new position
311
- modal.top = y;
312
- modal.left = x;
284
+ menu.modal.top = y;
285
+ menu.modal.left = x;
286
+
313
287
  onopen(self, options);
314
288
  }
315
289
  }
316
290
 
317
291
  self.close = function(level) {
318
292
  // Close all modals from the level specified
319
- self.modals.forEach(function(value, k) {
293
+ self.modals.forEach(function(menu, k) {
320
294
  if (k >= level) {
295
+ // Reset cursor
296
+ resetCursor.call(menu);
321
297
  // Close the modal
322
- value.modal.closed = true;
298
+ menu.modal.closed = true;
323
299
  }
324
300
  });
325
301
  // Keep the index of the modal that is opened
@@ -331,34 +307,80 @@ if (! Modal && typeof (require) === 'function') {
331
307
  self.root = self.el.parentNode;
332
308
  }
333
309
 
310
+ self.root.setAttribute('tabindex', -1);
311
+
312
+ // Create first menu
313
+ self.create();
314
+
315
+ // Normal click
316
+ self.root.addEventListener("click", function(e) {
317
+ if (e.target === self.root) {
318
+ self.close(0);
319
+ }
320
+ });
321
+
334
322
  // Keyboard event
335
323
  self.root.addEventListener("keydown", function(e) {
336
- // Modal object
337
- let m = self.modals[self.modalIndex].modal;
338
- // Something happens
339
- let ret = false;
340
- // Control
341
- if (e.key === 'ArrowLeft') {
342
- if (self.modalIndex > 0) {
343
- // Close modal
344
- m.parent.close();
345
- // Action happened
346
- ret = true;
324
+ // Menu object
325
+ let menu = self.modals[self.modalIndex];
326
+ // Modal must be opened
327
+ if (! menu.modal.closed) {
328
+ // Something happens
329
+ let ret = false;
330
+ // Control
331
+ if (e.key === 'ArrowLeft') {
332
+ if (self.modalIndex > 0) {
333
+ // Close modal
334
+ menu.close();
335
+ // Action happened
336
+ ret = true;
337
+ }
338
+ } else if (e.key === 'ArrowRight') {
339
+ // Get the selected cursor
340
+ let item = menu.options[menu.cursor];
341
+ // Open submenu
342
+ if (typeof (item) !== 'undefined') {
343
+ // Open submenu in case that exists
344
+ if (item.submenu && !item.disabled) {
345
+ // Open modal
346
+ menu.open(item, true);
347
+ // Action happened
348
+ ret = true;
349
+ }
350
+ }
351
+ } else if (e.key === 'ArrowUp') {
352
+ ret = setCursor.call(menu, 0);
353
+ } else if (e.key === 'ArrowDown') {
354
+ ret = setCursor.call(menu, 1);
355
+ } else if (e.key === 'Enter') {
356
+ // Contextmenu modal
357
+ let item = menu.options[menu.cursor];
358
+ // Cursor is found so reset it
359
+ if (typeof (item) !== 'undefined') {
360
+ // Execute action
361
+ if (typeof (item.onclick) === 'function') {
362
+ item.onclick.call(item, e, item.el);
363
+ }
364
+ // Open sub menu in case exists
365
+ if (item.submenu) {
366
+ // Open menu
367
+ menu.open(item, true);
368
+ // Action happened
369
+ ret = true;
370
+ } else {
371
+ // Close all menu
372
+ self.close(0);
373
+ // Action happened
374
+ ret = true;
375
+ }
376
+ }
347
377
  }
348
- } else if (e.key === 'ArrowRight') {
349
- ret = openSubmenu.call(m);
350
- } else if (e.key === 'ArrowUp') {
351
- ret = setCursor.call(m, 0);
352
- } else if (e.key === 'ArrowDown') {
353
- ret = setCursor.call(m, 1);
354
- } else if (e.key === 'Enter') {
355
- ret = actionCursor.call(m, e);
356
- }
357
378
 
358
- // Something important happen so block any progression
359
- if (ret === true) {
360
- e.preventDefault();
361
- e.stopImmediatePropagation();
379
+ // Something important happen so block any progression
380
+ if (ret === true) {
381
+ e.preventDefault();
382
+ e.stopImmediatePropagation();
383
+ }
362
384
  }
363
385
  });
364
386
 
@@ -378,11 +400,6 @@ if (! Modal && typeof (require) === 'function') {
378
400
  e.preventDefault();
379
401
  e.stopImmediatePropagation();
380
402
  });
381
-
382
- self.root.setAttribute('tabindex', -1);
383
-
384
- // Create first menu
385
- self.create();
386
403
  }
387
404
 
388
405
  return `<div class="lm-menu"></div>`;
@@ -390,6 +407,8 @@ if (! Modal && typeof (require) === 'function') {
390
407
 
391
408
  lemonade.setComponents({ Contextmenu: Contextmenu });
392
409
 
410
+ lemonade.createWebComponent('contextmenu', Contextmenu);
411
+
393
412
  return function (root, options) {
394
413
  if (typeof (root) === 'object') {
395
414
  lemonade.render(Contextmenu, root, options)
package/dist/react.d.ts CHANGED
@@ -6,10 +6,13 @@
6
6
  import Component from './index';
7
7
 
8
8
  interface Contextmenu {
9
+ ref?: MutableRefObject<undefined>;
9
10
  (): any
10
11
  [key: string]: any
11
12
  }
12
13
 
13
- declare function Contextmenu<Contextmenu>(props: Component.Options): any;
14
+ type Props = IntrinsicAttributes & Component.Options & Contextmenu;
15
+
16
+ declare function Contextmenu<Contextmenu>(props: Props): any;
14
17
 
15
18
  export default Contextmenu;
package/dist/style.css CHANGED
@@ -11,6 +11,7 @@
11
11
  min-height: initial;
12
12
  padding-top: 4px;
13
13
  padding-bottom: 4px;
14
+ z-index: 16;
14
15
  }
15
16
 
16
17
  .lm-menu-submenu {
@@ -46,8 +47,9 @@
46
47
  content: '\25B6'
47
48
  }
48
49
 
49
- .lm-menu-submenu > div.lm-menu-item.disabled {
50
- color: #ccc;
50
+ .lm-menu-submenu > div.lm-menu-item[data-disabled="true"] {
51
+ opacity: 0.5;
52
+ pointer-events: none;
51
53
  }
52
54
 
53
55
  .lm-menu-submenu > div.lm-menu-item:hover,
package/package.json CHANGED
@@ -14,10 +14,10 @@
14
14
  "build": "webpack --config webpack.config.js"
15
15
  },
16
16
  "dependencies": {
17
- "@lemonadejs/modal": "^2.8.1",
18
- "lemonadejs": "^4.2.2"
17
+ "lemonadejs": "^4.3.3",
18
+ "@lemonadejs/modal": "^3.3.0"
19
19
  },
20
20
  "main": "dist/index.js",
21
21
  "types": "dist/index.d.ts",
22
- "version": "1.1.3"
22
+ "version": "1.4.0"
23
23
  }