@vaadin/context-menu 24.0.0-beta1 → 24.0.0-beta2
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/package.json +10 -10
- package/src/vaadin-context-menu.d.ts +5 -0
- package/src/vaadin-context-menu.js +10 -2
- package/src/vaadin-contextmenu-items-mixin.js +216 -143
- package/web-types.json +3 -3
- package/web-types.lit.json +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/context-menu",
|
|
3
|
-
"version": "24.0.0-
|
|
3
|
+
"version": "24.0.0-beta2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
41
41
|
"@polymer/polymer": "^3.0.0",
|
|
42
|
-
"@vaadin/component-base": "24.0.0-
|
|
43
|
-
"@vaadin/item": "24.0.0-
|
|
44
|
-
"@vaadin/list-box": "24.0.0-
|
|
45
|
-
"@vaadin/lit-renderer": "24.0.0-
|
|
46
|
-
"@vaadin/overlay": "24.0.0-
|
|
47
|
-
"@vaadin/vaadin-lumo-styles": "24.0.0-
|
|
48
|
-
"@vaadin/vaadin-material-styles": "24.0.0-
|
|
49
|
-
"@vaadin/vaadin-themable-mixin": "24.0.0-
|
|
42
|
+
"@vaadin/component-base": "24.0.0-beta2",
|
|
43
|
+
"@vaadin/item": "24.0.0-beta2",
|
|
44
|
+
"@vaadin/list-box": "24.0.0-beta2",
|
|
45
|
+
"@vaadin/lit-renderer": "24.0.0-beta2",
|
|
46
|
+
"@vaadin/overlay": "24.0.0-beta2",
|
|
47
|
+
"@vaadin/vaadin-lumo-styles": "24.0.0-beta2",
|
|
48
|
+
"@vaadin/vaadin-material-styles": "24.0.0-beta2",
|
|
49
|
+
"@vaadin/vaadin-themable-mixin": "24.0.0-beta2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@esm-bundle/chai": "^4.3.4",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"web-types.json",
|
|
59
59
|
"web-types.lit.json"
|
|
60
60
|
],
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "00086f1f6d487f042f189c9b9ecd7ba736960888"
|
|
62
62
|
}
|
|
@@ -267,6 +267,11 @@ declare class ContextMenu extends OverlayClassMixin(ElementMixin(ThemePropertyMi
|
|
|
267
267
|
*/
|
|
268
268
|
renderer: ContextMenuRenderer | null | undefined;
|
|
269
269
|
|
|
270
|
+
/**
|
|
271
|
+
* When true, the menu overlay is modeless.
|
|
272
|
+
*/
|
|
273
|
+
protected _modeless: boolean;
|
|
274
|
+
|
|
270
275
|
/**
|
|
271
276
|
* Requests an update for the content of the menu overlay.
|
|
272
277
|
* While performing the update, it invokes the renderer passed in the `renderer` property.
|
|
@@ -225,12 +225,12 @@ class ContextMenu extends OverlayClassMixin(
|
|
|
225
225
|
id="overlay"
|
|
226
226
|
on-opened-changed="_onOverlayOpened"
|
|
227
227
|
on-vaadin-overlay-open="_onVaadinOverlayOpen"
|
|
228
|
+
modeless="[[_modeless]]"
|
|
228
229
|
with-backdrop="[[_phone]]"
|
|
229
230
|
phone$="[[_phone]]"
|
|
230
231
|
model="[[_context]]"
|
|
231
232
|
theme$="[[_theme]]"
|
|
232
|
-
>
|
|
233
|
-
</vaadin-context-menu-overlay>
|
|
233
|
+
></vaadin-context-menu-overlay>
|
|
234
234
|
`;
|
|
235
235
|
}
|
|
236
236
|
|
|
@@ -309,6 +309,14 @@ class ContextMenu extends OverlayClassMixin(
|
|
|
309
309
|
type: Function,
|
|
310
310
|
},
|
|
311
311
|
|
|
312
|
+
/**
|
|
313
|
+
* When true, the menu overlay is modeless.
|
|
314
|
+
* @protected
|
|
315
|
+
*/
|
|
316
|
+
_modeless: {
|
|
317
|
+
type: Boolean,
|
|
318
|
+
},
|
|
319
|
+
|
|
312
320
|
/** @private */
|
|
313
321
|
_context: Object,
|
|
314
322
|
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import './vaadin-context-menu-item.js';
|
|
7
7
|
import './vaadin-context-menu-list-box.js';
|
|
8
8
|
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
|
|
9
|
-
import { Item } from '@vaadin/item/src/vaadin-item.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @polymerMixin
|
|
@@ -159,55 +158,216 @@ export const ItemsMixin = (superClass) =>
|
|
|
159
158
|
}
|
|
160
159
|
|
|
161
160
|
/**
|
|
162
|
-
* @param {!
|
|
163
|
-
* @
|
|
164
|
-
* @
|
|
165
|
-
* @protected
|
|
161
|
+
* @param {!ContextMenuItem} item
|
|
162
|
+
* @return {HTMLElement}
|
|
163
|
+
* @private
|
|
166
164
|
*/
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
__createComponent(item) {
|
|
166
|
+
let component;
|
|
169
167
|
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
if (item.component instanceof HTMLElement) {
|
|
169
|
+
component = item.component;
|
|
170
|
+
} else {
|
|
171
|
+
component = document.createElement(item.component || `${this._tagNamePrefix}-item`);
|
|
172
|
+
}
|
|
172
173
|
|
|
173
|
-
|
|
174
|
+
// Support menu-bar / context-menu item
|
|
175
|
+
if (component._hasVaadinItemMixin) {
|
|
176
|
+
component.setAttribute('role', 'menuitem');
|
|
177
|
+
}
|
|
174
178
|
|
|
175
|
-
|
|
179
|
+
if (component.localName === 'hr') {
|
|
180
|
+
component.setAttribute('role', 'separator');
|
|
181
|
+
} else {
|
|
182
|
+
// Accept not `menuitem` elements e.g. `<button>`
|
|
183
|
+
component.setAttribute('aria-haspopup', 'false');
|
|
184
|
+
}
|
|
176
185
|
|
|
177
|
-
|
|
186
|
+
this._setMenuItemTheme(component, item, this._theme);
|
|
178
187
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
component._item = item;
|
|
189
|
+
|
|
190
|
+
if (item.text) {
|
|
191
|
+
component.textContent = item.text;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.__toggleMenuComponentAttribute(component, 'menu-item-checked', item.checked);
|
|
195
|
+
this.__toggleMenuComponentAttribute(component, 'disabled', item.disabled);
|
|
196
|
+
|
|
197
|
+
if (item.children && item.children.length) {
|
|
198
|
+
this.__updateExpanded(component, false);
|
|
199
|
+
component.setAttribute('aria-haspopup', 'true');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return component;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** @private */
|
|
206
|
+
__initListBox() {
|
|
207
|
+
const listBox = document.createElement(`${this._tagNamePrefix}-list-box`);
|
|
208
|
+
|
|
209
|
+
if (this._theme) {
|
|
210
|
+
listBox.setAttribute('theme', this._theme);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
listBox.addEventListener('selected-changed', (event) => {
|
|
214
|
+
const { value } = event.detail;
|
|
215
|
+
if (typeof value === 'number') {
|
|
216
|
+
const item = listBox.items[value]._item;
|
|
217
|
+
if (!item.children) {
|
|
218
|
+
this.dispatchEvent(new CustomEvent('item-selected', { detail: { value: item } }));
|
|
219
|
+
}
|
|
220
|
+
listBox.selected = null;
|
|
185
221
|
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return listBox;
|
|
225
|
+
}
|
|
186
226
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
227
|
+
/** @private */
|
|
228
|
+
__initOverlay() {
|
|
229
|
+
const overlay = this.$.overlay;
|
|
230
|
+
|
|
231
|
+
overlay.$.backdrop.addEventListener('click', () => {
|
|
232
|
+
this.close();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Open a submenu on click event when a touch device is used.
|
|
236
|
+
// On desktop, a submenu opens on hover.
|
|
237
|
+
overlay.addEventListener(isTouch ? 'click' : 'mouseover', (event) => {
|
|
238
|
+
this.__showSubMenu(event);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
overlay.addEventListener('keydown', (event) => {
|
|
242
|
+
const { key } = event;
|
|
243
|
+
const isRTL = this.__isRTL;
|
|
244
|
+
|
|
245
|
+
const isArrowRight = key === 'ArrowRight';
|
|
246
|
+
const isArrowLeft = key === 'ArrowLeft';
|
|
247
|
+
|
|
248
|
+
if ((!isRTL && isArrowRight) || (isRTL && isArrowLeft) || key === 'Enter' || key === ' ') {
|
|
249
|
+
// Open a sub-menu
|
|
250
|
+
this.__showSubMenu(event);
|
|
251
|
+
} else if ((!isRTL && isArrowLeft) || (isRTL && isArrowRight)) {
|
|
252
|
+
// Close the menu
|
|
253
|
+
this.close();
|
|
254
|
+
this.listenOn.focus();
|
|
255
|
+
} else if (key === 'Escape' || key === 'Tab') {
|
|
256
|
+
// Close all menus
|
|
257
|
+
this.dispatchEvent(new CustomEvent('close-all-menus'));
|
|
191
258
|
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** @private */
|
|
263
|
+
__initSubMenu() {
|
|
264
|
+
const subMenu = document.createElement(this.constructor.is);
|
|
192
265
|
|
|
193
|
-
|
|
266
|
+
subMenu._modeless = true;
|
|
267
|
+
subMenu.openOn = 'opensubmenu';
|
|
194
268
|
|
|
195
|
-
|
|
269
|
+
// Sub-menu doesn't have a target to wrap,
|
|
270
|
+
// so there is no need to keep it visible.
|
|
271
|
+
subMenu.setAttribute('hidden', '');
|
|
196
272
|
|
|
197
|
-
|
|
198
|
-
|
|
273
|
+
// Close sub-menu when the parent menu closes.
|
|
274
|
+
this.addEventListener('opened-changed', (event) => {
|
|
275
|
+
if (!event.detail.value) {
|
|
276
|
+
this._subMenu.close();
|
|
199
277
|
}
|
|
278
|
+
});
|
|
200
279
|
|
|
201
|
-
|
|
202
|
-
|
|
280
|
+
// Forward event to the parent menu element.
|
|
281
|
+
subMenu.addEventListener('close-all-menus', () => {
|
|
282
|
+
this.dispatchEvent(new CustomEvent('close-all-menus'));
|
|
283
|
+
});
|
|
203
284
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
285
|
+
// Forward event to the parent menu element.
|
|
286
|
+
subMenu.addEventListener('item-selected', (event) => {
|
|
287
|
+
const { detail } = event;
|
|
288
|
+
this.dispatchEvent(new CustomEvent('item-selected', { detail }));
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Listen to the forwarded event from sub-menu.
|
|
292
|
+
this.addEventListener('close-all-menus', () => {
|
|
293
|
+
this.close();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Listen to the forwarded event from sub-menu.
|
|
297
|
+
this.addEventListener('item-selected', () => {
|
|
298
|
+
this.close();
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// Mark parent item as collapsed when closing.
|
|
302
|
+
subMenu.addEventListener('opened-changed', (event) => {
|
|
303
|
+
if (!event.detail.value) {
|
|
304
|
+
const expandedItem = this._listBox.querySelector('[expanded]');
|
|
305
|
+
if (expandedItem) {
|
|
306
|
+
this.__updateExpanded(expandedItem, false);
|
|
307
|
+
}
|
|
209
308
|
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
return subMenu;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** @private */
|
|
315
|
+
__showSubMenu(event, item = event.composedPath().find((node) => node.localName === `${this._tagNamePrefix}-item`)) {
|
|
316
|
+
// Delay enabling the mouseover listener to avoid it from triggering on parent menu open
|
|
317
|
+
if (!this.__openListenerActive) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Don't open sub-menus while the menu is still opening
|
|
322
|
+
if (this.$.overlay.hasAttribute('opening')) {
|
|
323
|
+
requestAnimationFrame(() => {
|
|
324
|
+
this.__showSubMenu(event, item);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
210
329
|
|
|
330
|
+
const subMenu = this._subMenu;
|
|
331
|
+
|
|
332
|
+
if (item) {
|
|
333
|
+
const { children } = item._item;
|
|
334
|
+
|
|
335
|
+
if (subMenu.items !== children) {
|
|
336
|
+
subMenu.close();
|
|
337
|
+
}
|
|
338
|
+
if (!this.opened) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (children && children.length) {
|
|
343
|
+
this.__updateExpanded(item, true);
|
|
344
|
+
|
|
345
|
+
// Forward parent overlay class
|
|
346
|
+
const { overlayClass } = this;
|
|
347
|
+
this.__openSubMenu(subMenu, item, overlayClass);
|
|
348
|
+
} else {
|
|
349
|
+
subMenu.listenOn.focus();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* @param {!HTMLElement} root
|
|
356
|
+
* @param {!ContextMenu} menu
|
|
357
|
+
* @param {!ContextMenuRendererContext} context
|
|
358
|
+
* @protected
|
|
359
|
+
*/
|
|
360
|
+
__itemsRenderer(root, menu, { detail }) {
|
|
361
|
+
this.__initMenu(root, menu);
|
|
362
|
+
|
|
363
|
+
const subMenu = root.querySelector(this.constructor.is);
|
|
364
|
+
subMenu.closeOn = menu.closeOn;
|
|
365
|
+
|
|
366
|
+
const listBox = root.querySelector(`${this._tagNamePrefix}-list-box`);
|
|
367
|
+
listBox.innerHTML = '';
|
|
368
|
+
|
|
369
|
+
[...(detail.children || menu.items)].forEach((item) => {
|
|
370
|
+
const component = this.__createComponent(item);
|
|
211
371
|
listBox.appendChild(component);
|
|
212
372
|
});
|
|
213
373
|
}
|
|
@@ -223,11 +383,7 @@ export const ItemsMixin = (superClass) =>
|
|
|
223
383
|
theme = Array.isArray(item.theme) ? item.theme.join(' ') : item.theme;
|
|
224
384
|
}
|
|
225
385
|
|
|
226
|
-
|
|
227
|
-
component.setAttribute('theme', theme);
|
|
228
|
-
} else {
|
|
229
|
-
component.removeAttribute('theme');
|
|
230
|
-
}
|
|
386
|
+
this.__updateTheme(component, theme);
|
|
231
387
|
}
|
|
232
388
|
|
|
233
389
|
/** @private */
|
|
@@ -243,122 +399,39 @@ export const ItemsMixin = (superClass) =>
|
|
|
243
399
|
|
|
244
400
|
/** @private */
|
|
245
401
|
__initMenu(root, menu) {
|
|
402
|
+
// NOTE: in this method, `menu` and `this` reference the same element,
|
|
403
|
+
// so we can use either of those. Original implementation used `menu`.
|
|
246
404
|
if (!root.firstElementChild) {
|
|
247
|
-
|
|
248
|
-
root.appendChild(listBox);
|
|
405
|
+
this.__initOverlay();
|
|
249
406
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
requestAnimationFrame(() => listBox.setAttribute('role', 'menu'));
|
|
407
|
+
const listBox = this.__initListBox();
|
|
408
|
+
this._listBox = listBox;
|
|
409
|
+
root.appendChild(listBox);
|
|
254
410
|
|
|
255
|
-
const subMenu =
|
|
256
|
-
|
|
411
|
+
const subMenu = this.__initSubMenu();
|
|
412
|
+
this._subMenu = subMenu;
|
|
257
413
|
root.appendChild(subMenu);
|
|
258
|
-
subMenu.$.overlay.modeless = true;
|
|
259
|
-
subMenu.openOn = 'opensubmenu';
|
|
260
|
-
|
|
261
|
-
menu.addEventListener('opened-changed', (e) => !e.detail.value && subMenu.close());
|
|
262
|
-
subMenu.addEventListener('opened-changed', (e) => {
|
|
263
|
-
if (!e.detail.value) {
|
|
264
|
-
const expandedItem = listBox.querySelector('[expanded]');
|
|
265
|
-
if (expandedItem) {
|
|
266
|
-
expandedItem.setAttribute('aria-expanded', 'false');
|
|
267
|
-
expandedItem.removeAttribute('expanded');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
listBox.addEventListener('selected-changed', (e) => {
|
|
273
|
-
if (typeof e.detail.value === 'number') {
|
|
274
|
-
const item = e.target.items[e.detail.value]._item;
|
|
275
|
-
if (!item.children) {
|
|
276
|
-
const detail = { value: item };
|
|
277
|
-
menu.dispatchEvent(new CustomEvent('item-selected', { detail }));
|
|
278
|
-
}
|
|
279
|
-
listBox.selected = null;
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
subMenu.addEventListener('item-selected', (e) => {
|
|
284
|
-
menu.dispatchEvent(new CustomEvent('item-selected', { detail: e.detail }));
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
subMenu.addEventListener('close-all-menus', () => {
|
|
288
|
-
menu.dispatchEvent(new CustomEvent('close-all-menus'));
|
|
289
|
-
});
|
|
290
|
-
menu.addEventListener('close-all-menus', menu.close);
|
|
291
|
-
menu.addEventListener('item-selected', menu.close);
|
|
292
|
-
menu.$.overlay.$.backdrop.addEventListener('click', () => menu.close());
|
|
293
|
-
|
|
294
|
-
menu.$.overlay.addEventListener('keydown', (e) => {
|
|
295
|
-
const isRTL = this.__isRTL;
|
|
296
|
-
if ((!isRTL && e.keyCode === 37) || (isRTL && e.keyCode === 39)) {
|
|
297
|
-
menu.close();
|
|
298
|
-
menu.listenOn.focus();
|
|
299
|
-
} else if (e.key === 'Escape' || e.key === 'Tab') {
|
|
300
|
-
menu.dispatchEvent(new CustomEvent('close-all-menus'));
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
414
|
|
|
304
415
|
requestAnimationFrame(() => {
|
|
305
416
|
this.__openListenerActive = true;
|
|
306
417
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// Delay enabling the mouseover listener to avoid it from triggering on parent menu open
|
|
312
|
-
if (!this.__openListenerActive) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Don't open sub-menus while the menu is still opening
|
|
317
|
-
if (menu.$.overlay.hasAttribute('opening')) {
|
|
318
|
-
requestAnimationFrame(() => openSubMenu(e, itemElement));
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (itemElement) {
|
|
323
|
-
if (subMenu.items !== itemElement._item.children) {
|
|
324
|
-
subMenu.close();
|
|
325
|
-
}
|
|
326
|
-
if (!menu.opened) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
if (itemElement._item.children && itemElement._item.children.length) {
|
|
330
|
-
itemElement.setAttribute('aria-expanded', 'true');
|
|
331
|
-
itemElement.setAttribute('expanded', '');
|
|
332
|
-
|
|
333
|
-
// Forward parent overlay class
|
|
334
|
-
const { overlayClass } = menu;
|
|
335
|
-
this.__openSubMenu(subMenu, itemElement, overlayClass);
|
|
336
|
-
} else {
|
|
337
|
-
subMenu.listenOn.focus();
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
// Open a submenu on click event when a touch device is used.
|
|
343
|
-
// On desktop, a submenu opens on hover.
|
|
344
|
-
menu.$.overlay.addEventListener(isTouch ? 'click' : 'mouseover', openSubMenu);
|
|
418
|
+
} else {
|
|
419
|
+
this.__updateTheme(this._listBox, this._theme);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
345
422
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
423
|
+
/** @private */
|
|
424
|
+
__updateExpanded(component, expanded) {
|
|
425
|
+
component.setAttribute('aria-expanded', expanded.toString());
|
|
426
|
+
component.toggleAttribute('expanded', expanded);
|
|
427
|
+
}
|
|
350
428
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
429
|
+
/** @private */
|
|
430
|
+
__updateTheme(component, theme) {
|
|
431
|
+
if (theme) {
|
|
432
|
+
component.setAttribute('theme', theme);
|
|
355
433
|
} else {
|
|
356
|
-
|
|
357
|
-
if (this._theme) {
|
|
358
|
-
listBox.setAttribute('theme', this._theme);
|
|
359
|
-
} else {
|
|
360
|
-
listBox.removeAttribute('theme');
|
|
361
|
-
}
|
|
434
|
+
component.removeAttribute('theme');
|
|
362
435
|
}
|
|
363
436
|
}
|
|
364
437
|
};
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/context-menu",
|
|
4
|
-
"version": "24.0.0-
|
|
4
|
+
"version": "24.0.0-beta2",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-context-menu",
|
|
11
|
-
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\n\n```javascript\ncontextMenu.items = [\n {text: 'Menu Item 1', theme: 'primary', children:\n [\n {text: 'Menu Item 1-1', checked: true},\n {text: 'Menu Item 1-2'}\n ]\n },\n {component: 'hr'},\n {text: 'Menu Item 2', children:\n [\n {text: 'Menu Item 2-1'},\n {text: 'Menu Item 2-2', disabled: true}\n ]\n },\n {text: 'Menu Item 3', disabled: true}\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n###
|
|
11
|
+
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', children:\n [\n { text: 'Menu Item 1-1', checked: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\n`<vaadin-context-menu>` uses `<vaadin-context-menu-overlay>` internal\nthemable component as the actual visible context menu overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-overlay)\ndocumentation for `<vaadin-context-menu-overlay>` stylable parts.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API, in addition `<vaadin-context-menu-overlay>`, the following\ninternal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-list-box).\n\nNote: the `theme` attribute value set on `<vaadin-context-menu>` is\npropagated to the internal components listed above.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "overlay-class",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"name": "items",
|
|
80
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n {text: 'Menu Item 1', theme: 'primary', children:\n [\n {text: 'Menu Item 1-1', checked: true},\n {text: 'Menu Item 1-2'}\n ]\n },\n {component: 'hr'},\n {text: 'Menu Item 2', children:\n [\n {text: 'Menu Item 2-1'},\n {text: 'Menu Item 2-2', disabled: true}\n ]\n },\n {text: 'Menu Item 3', disabled: true}\n];\n```",
|
|
80
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', children:\n [\n { text: 'Menu Item 1-1', checked: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true }\n];\n```",
|
|
81
81
|
"value": {
|
|
82
82
|
"type": [
|
|
83
83
|
"Array.<ContextMenuItem>",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/context-menu",
|
|
4
|
-
"version": "24.0.0-
|
|
4
|
+
"version": "24.0.0-beta2",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"elements": [
|
|
17
17
|
{
|
|
18
18
|
"name": "vaadin-context-menu",
|
|
19
|
-
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\n\n```javascript\ncontextMenu.items = [\n {text: 'Menu Item 1', theme: 'primary', children:\n [\n {text: 'Menu Item 1-1', checked: true},\n {text: 'Menu Item 1-2'}\n ]\n },\n {component: 'hr'},\n {text: 'Menu Item 2', children:\n [\n {text: 'Menu Item 2-1'},\n {text: 'Menu Item 2-2', disabled: true}\n ]\n },\n {text: 'Menu Item 3', disabled: true}\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n###
|
|
19
|
+
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', children:\n [\n { text: 'Menu Item 1-1', checked: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\n`<vaadin-context-menu>` uses `<vaadin-context-menu-overlay>` internal\nthemable component as the actual visible context menu overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-overlay)\ndocumentation for `<vaadin-context-menu-overlay>` stylable parts.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API, in addition `<vaadin-context-menu-overlay>`, the following\ninternal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-beta2/#/elements/vaadin-list-box).\n\nNote: the `theme` attribute value set on `<vaadin-context-menu>` is\npropagated to the internal components listed above.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": ".items",
|
|
31
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n {text: 'Menu Item 1', theme: 'primary', children:\n [\n {text: 'Menu Item 1-1', checked: true},\n {text: 'Menu Item 1-2'}\n ]\n },\n {component: 'hr'},\n {text: 'Menu Item 2', children:\n [\n {text: 'Menu Item 2-1'},\n {text: 'Menu Item 2-2', disabled: true}\n ]\n },\n {text: 'Menu Item 3', disabled: true}\n];\n```",
|
|
31
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', children:\n [\n { text: 'Menu Item 1-1', checked: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true }\n];\n```",
|
|
32
32
|
"value": {
|
|
33
33
|
"kind": "expression"
|
|
34
34
|
}
|