Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* @license
* Copyright (c) 2016 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
/**
* @polymerMixin
*/
export const ItemsMixin = (superClass) =>
class ItemsMixin extends superClass {
static get properties() {
return {
/**
* @typedef ContextMenuItem
* @type {object}
* @property {string} text - Text to be set as the menu item component's textContent
* @property {union: string | object} component - The component to represent the item.
* Either a tagName or an element instance. Defaults to "vaadin-context-menu-item".
* @property {boolean} disabled - If true, the item is disabled and cannot be selected
* @property {boolean} checked - If true, the item shows a checkmark next to it
* @property {boolean} keepOpen - If true, the menu will not be closed on item selection
* @property {string} className - A space-delimited list of CSS class names to be set on the menu item component.
* @property {union: string | string[]} theme - If set, sets the given theme(s) as an attribute to the menu item component, overriding any theme set on the context menu.
* @property {MenuItem[]} children - Array of child menu items
*/
/**
* Defines a (hierarchical) menu structure for the component.
* If a menu item has a non-empty `children` set, a sub-menu with the child items is opened
* next to the parent menu on mouseover, tap or a right arrow keypress.
*
* The items API can't be used together with a renderer!
*
* #### Example
*
* ```javascript
* contextMenu.items = [
* { text: 'Menu Item 1', theme: 'primary', className: 'first', children:
* [
* { text: 'Menu Item 1-1', checked: true, keepOpen: true },
* { text: 'Menu Item 1-2' }
* ]
* },
* { component: 'hr' },
* { text: 'Menu Item 2', children:
* [
* { text: 'Menu Item 2-1' },
* { text: 'Menu Item 2-2', disabled: true }
* ]
* },
* { text: 'Menu Item 3', disabled: true, className: 'last' }
* ];
* ```
*
* @type {!Array | undefined}
*/
items: {
type: Array,
sync: true,
},
};
}
constructor() {
super();
// Overlay's outside click listener doesn't work with modeless
// overlays (submenus) so we need additional logic for it
this.__itemsOutsideClickListener = (e) => {
if (!e.composedPath().some((el) => el.localName === `${this._tagNamePrefix}-overlay`)) {
this.dispatchEvent(new CustomEvent('items-outside-click'));
}
};
this.addEventListener('items-outside-click', () => {
this.items && this.close();
});
}
/**
* Tag name prefix used by overlay, list-box and items.
* @protected
* @return {string}
*/
get _tagNamePrefix() {
return 'vaadin-context-menu';
}
/** @protected */
connectedCallback() {
super.connectedCallback();
// Firefox leaks click to document on contextmenu even if prevented
// https://bugzilla.mozilla.org/show_bug.cgi?id=990614
document.documentElement.addEventListener('click', this.__itemsOutsideClickListener);
}
/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
document.documentElement.removeEventListener('click', this.__itemsOutsideClickListener);
}
/** @protected */
__forwardFocus() {
const overlay = this._overlayElement;
const child = overlay.getFirstChild();
// If parent item is not focused, do not focus submenu
if (overlay.parentOverlay) {
const parent = overlay.parentOverlay.querySelector('[expanded]');
if (parent && parent.hasAttribute('focused') && child) {
child.focus();
} else {
overlay.$.overlay.focus();
}
} else if (child) {
child.focus();
}
}
/** @private */
__openSubMenu(subMenu, itemElement, overlayClass) {
subMenu.items = itemElement._item.children;
subMenu.listenOn = itemElement;
subMenu.overlayClass = overlayClass;
const parent = this._overlayElement;
const subMenuOverlay = subMenu._overlayElement;
subMenuOverlay.positionTarget = itemElement;
subMenuOverlay.noHorizontalOverlap = true;
// Store the reference parent overlay
subMenuOverlay._setParentOverlay(parent);
// Set theme attribute from parent element
if (parent.hasAttribute('theme')) {
subMenu.setAttribute('theme', parent.getAttribute('theme'));
} else {
subMenu.removeAttribute('theme');
}
const content = subMenuOverlay.$.content;
content.style.minWidth = '';
itemElement.dispatchEvent(
new CustomEvent('opensubmenu', {
detail: {
children: itemElement._item.children,
},
}),
);
}
/**
* @param {!ContextMenuItem} item
* @return {HTMLElement}
* @private
*/
__createComponent(item) {
let component;
if (item.component instanceof HTMLElement) {
component = item.component;
} else {
component = document.createElement(item.component || `${this._tagNamePrefix}-item`);
}
// Support menu-bar / context-menu item
if (component._hasVaadinItemMixin) {
component.setAttribute('role', 'menuitem');
component.tabIndex = -1;
}
if (component.localName === 'hr') {
component.setAttribute('role', 'separator');
} else {
// Accept not `menuitem` elements e.g. `