New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@vaadin/vaadin-menu-bar

Package Overview
Dependencies
Maintainers
16
Versions
255
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/vaadin-menu-bar - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0-alpha1

src/interfaces.d.ts

85

package.json
{
"name": "@vaadin/vaadin-menu-bar",
"version": "2.0.0-alpha1",
"description": "vaadin-menu-bar",
"main": "vaadin-menu-bar.js",
"module": "vaadin-menu-bar.js",
"repository": "vaadin/vaadin-menu-bar",
"keywords": [

@@ -10,7 +15,2 @@ "Vaadin",

],
"repository": "vaadin/vaadin-menu-bar",
"homepage": "https://vaadin.com/components",
"name": "@vaadin/vaadin-menu-bar",
"version": "1.2.1",
"main": "vaadin-menu-bar.js",
"author": "Vaadin Ltd",

@@ -21,40 +21,77 @@ "license": "Apache-2.0",

},
"homepage": "https://vaadin.com/components",
"files": [
"vaadin-*.d.ts",
"vaadin-*.js",
"@types",
"src",
"theme"
],
"resolutions": {
"@webcomponents/webcomponentsjs": "2.2.0",
"es-abstract": "1.17.6",
"@types/doctrine": "0.0.3",
"inherits": "2.0.3",
"samsam": "1.1.3",
"supports-color": "3.1.2",
"type-detect": "1.0.0"
"scripts": {
"analyze": "polymer analyze vaadin-* > analysis.json",
"check-version": "magi check-version",
"debug": "web-test-runner test/*.test.js --watch",
"dist": "rimraf dist && npm run analyze && rollup -c rollup.config.js && cp analysis.json dist",
"lint": "npm run lint:js && npm run lint:css && npm run lint:types",
"lint:css": "stylelint src/*.js theme/**/*-styles.js",
"lint:js": "eslint src theme test",
"lint:types": "tsc",
"prestart": "npm run analyze",
"preversion": "magi update-version",
"screenshots": "hermione test/visual/test.js --update-refs",
"serve:dist": "web-dev-server --app-index dist/index.html --open",
"start": "web-dev-server --node-resolve --open",
"test": "web-test-runner test/*.test.js --coverage",
"test:sauce": "TEST_ENV=sauce npm test",
"test:visual": "hermione test/visual/test.js"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint --fix",
"prettier --write"
]
},
"dependencies": {
"@polymer/polymer": "^3.0.0",
"@polymer/iron-resizable-behavior": "^3.0.0",
"@vaadin/vaadin-themable-mixin": "^1.6.1",
"@vaadin/vaadin-themable-mixin": "^1.6.2",
"@vaadin/vaadin-element-mixin": "^2.4.1",
"@vaadin/vaadin-button": "^2.4.0",
"@vaadin/vaadin-context-menu": "^4.5.0",
"@vaadin/vaadin-lumo-styles": "^1.6.0",
"@vaadin/vaadin-context-menu": "^5.0.0-alpha1",
"@vaadin/vaadin-lumo-styles": "^1.6.1",
"@vaadin/vaadin-material-styles": "^1.3.2"
},
"scripts": {
"generate-typings": "gen-typescript-declarations --outDir . --verify"
},
"devDependencies": {
"@esm-bundle/chai": "^4.1.5",
"@open-wc/rollup-plugin-html": "^1.2.5",
"@open-wc/testing-helpers": "^1.8.12",
"@polymer/iron-component-page": "^4.0.0",
"@polymer/iron-test-helpers": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.0.0",
"wct-browser-legacy": "^1.0.1",
"@vaadin/vaadin-checkbox": "^2.4.0",
"@vaadin/vaadin-icons": "^4.3.1",
"@vaadin/vaadin-demo-helpers": "^3.1.0"
"@web/dev-server": "~0.0.27",
"@web/test-runner": "^0.10.0",
"@web/test-runner-saucelabs": "^0.2.0",
"eslint": "^7.15.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4",
"hermione": "^3.9.0",
"hermione-esm": "^0.4.0",
"hermione-sauce": "^0.1.0",
"husky": "^4.3.0",
"lint-staged": "^10.5.1",
"magi-cli": "^0.29.0",
"prettier": "^2.2.0",
"rimraf": "^3.0.2",
"rollup": "^2.34.1",
"rollup-plugin-terser": "^7.0.2",
"sinon": "^9.2.1",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-vaadin": "^0.2.7",
"typescript": "^4.1.2"
}
}

@@ -1,12 +0,1 @@

[![npm version](https://badgen.net/npm/v/@vaadin/vaadin-menu-bar)](https://www.npmjs.com/package/@vaadin/vaadin-menu-bar)
[![Bower version](https://badgen.net/github/release/vaadin/vaadin-menu-bar)](https://github.com/vaadin/vaadin-menu-bar/releases)
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/vaadin/vaadin-menu-bar)
[![Build Status](https://travis-ci.org/vaadin/vaadin-menu-bar.svg?branch=master)](https://travis-ci.org/vaadin/vaadin-menu-bar)
[![Coverage Status](https://coveralls.io/repos/github/vaadin/vaadin-menu-bar/badge.svg?branch=master)](https://coveralls.io/github/vaadin/vaadin-menu-bar?branch=master)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/vaadin/web-components?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Published on Vaadin Directory](https://img.shields.io/badge/Vaadin%20Directory-published-00b4f0.svg)](https://vaadin.com/directory/component/vaadinvaadin-menu-bar)
[![Stars on vaadin.com/directory](https://img.shields.io/vaadin-directory/star/vaadin-menu-bar-directory-urlidentifier.svg)](https://vaadin.com/directory/component/vaadinvaadin-menu-bar)
# <vaadin-menu-bar>

@@ -18,20 +7,13 @@

[<vaadin-menu-bar>](https://vaadin.com/components/vaadin-menu-bar) is a Web Component providing application menu functionality, part of the [Vaadin components](https://vaadin.com/components).
<!--
```
<custom-element-demo>
<template>
<script src="../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="vaadin-menu-bar.html">
<next-code-block></next-code-block>
</template>
</custom-element-demo>
```
-->
[![npm version](https://badgen.net/npm/v/@vaadin/vaadin-menu-bar)](https://www.npmjs.com/package/@vaadin/vaadin-menu-bar)
[![Build Status](https://travis-ci.org/vaadin/vaadin-menu-bar.svg?branch=master)](https://travis-ci.org/vaadin/vaadin-menu-bar)
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/vaadin/vaadin-menu-bar)
[![Published on Vaadin Directory](https://img.shields.io/badge/Vaadin%20Directory-published-00b4f0.svg)](https://vaadin.com/directory/component/vaadinvaadin-menu-bar)
[![Stars on vaadin.com/directory](https://img.shields.io/vaadin-directory/star/vaadin-menu-bar-directory-urlidentifier.svg)](https://vaadin.com/directory/component/vaadinvaadin-menu-bar)
[![Discord](https://img.shields.io/discord/732335336448852018?label=discord)](https://discord.gg/PHmkCKC)
```html
<vaadin-menu-bar>
...
</vaadin-menu-bar>
<vaadin-menu-bar></vaadin-menu-bar>
```

@@ -41,31 +23,7 @@

## Installation
The Vaadin components are distributed as Bower and npm packages.
Please note that the version range is the same, as the API has not changed.
You should not mix Bower and npm versions in the same application, though.
Unlike the official Polymer Elements, the converted Polymer 3 compatible Vaadin components
are only published on npm, not pushed to GitHub repositories.
### Polymer 2 and HTML Imports compatible version
Install `vaadin-menu-bar`:
```sh
bower i vaadin/vaadin-menu-bar --save
```
Once installed, import it in your application:
```html
<link rel="import" href="bower_components/vaadin-menu-bar/vaadin-menu-bar.html">
```
### Polymer 3 and ES Modules compatible version
Install `vaadin-menu-bar`:
```sh
npm i @vaadin/vaadin-menu-bar --save

@@ -90,29 +48,28 @@ ```

`theme/lumo/vaadin-menu-bar.html`
`theme/lumo/vaadin-menu-bar.js`
- The component with the Material theme:
`theme/material/vaadin-menu-bar.html`
`theme/material/vaadin-menu-bar.js`
- Alias for `theme/lumo/vaadin-menu-bar.html`:
- Alias for `theme/lumo/vaadin-menu-bar.js`:
`vaadin-menu-bar.html`
`vaadin-menu-bar.js`
## Running demos and tests in browser
## Running API docs and tests in a browser
1. Fork the `vaadin-menu-bar` repository and clone it locally.
1. Make sure you have [node.js](https://nodejs.org/) 12.x installed.
1. Make sure you have [npm](https://www.npmjs.com/) installed.
1. When in the `vaadin-menu-bar` directory, run `npm install` and then `bower install` to install dependencies.
1. When in the `vaadin-menu-bar` directory, run `npm install` to install dependencies.
1. Make sure you have [polymer-cli](https://www.npmjs.com/package/polymer-cli) installed globally: `npm i -g polymer-cli`.
1. Run `npm start`, browser will automatically open the component API documentation.
1. You can also open demo or in-browser tests by adding **demo** or **test** to the URL, for example:
1. You can also open visual tests, for example:
- http://127.0.0.1:8080/components/vaadin-menu-bar/demo
- http://127.0.0.1:8080/components/vaadin-menu-bar/test
- http://127.0.0.1:3000/test/visual/default.html

@@ -122,5 +79,9 @@

1. When in the `vaadin-menu-bar` directory, run `polymer test`
1. When in the `vaadin-menu-bar` directory, run `npm test`
## Debugging tests in the browser
1. Run `npm run debug`, then choose manual mode (M) and open the link in browser.
## Following the coding style

@@ -127,0 +88,0 @@

/**
@license
Copyright (c) 2019 Vaadin Ltd.
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import '@polymer/polymer/lib/elements/dom-module.js';
* @license
* Copyright (c) 2020 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { ButtonElement } from '@vaadin/vaadin-button/src/vaadin-button.js';
const $_documentContainer = document.createElement('template');
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
$_documentContainer.innerHTML = `<dom-module id="vaadin-menu-bar-button-styles" theme-for="vaadin-menu-bar-button">
<template>
<style>
[part="label"] ::slotted(vaadin-context-menu-item) {
position: relative;
z-index: 1;
}
</style>
</template>
</dom-module>`;
registerStyles(
'vaadin-menu-bar-button',
css`
[part='label'] ::slotted(vaadin-context-menu-item) {
position: relative;
z-index: 1;
}
`,
{ moduleId: 'vaadin-menu-bar-button-styles' }
);
document.head.appendChild($_documentContainer.content);
/**

@@ -24,0 +21,0 @@ * @extends PolymerElement

@@ -1,39 +0,15 @@

/**
* DO NOT EDIT
*
* This file was automatically generated by
* https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations
*
* To modify these typings, edit the source file(s):
* src/vaadin-menu-bar-buttons-mixin.js
*/
// tslint:disable:variable-name Describing an API that's defined elsewhere.
// tslint:disable:no-any describes the API as best we are able today
import {animationFrame} from '@polymer/polymer/lib/utils/async.js';
import {Debouncer} from '@polymer/polymer/lib/utils/debounce.js';
import {IronResizableBehavior} from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
export {ButtonsMixin};
declare function ButtonsMixin<T extends new (...args: any[]) => {}>(base: T): T & ButtonsMixinConstructor;
interface ButtonsMixinConstructor {
new(...args: any[]): ButtonsMixin;
new (...args: any[]): ButtonsMixin;
}
export {ButtonsMixinConstructor};
interface ButtonsMixin {
readonly _buttons: HTMLElement[];
readonly _container: HTMLElement;
readonly _overflow: HTMLElement;
_hasOverflow: boolean;
ready(): void;

@@ -46,1 +22,3 @@ /**

}
export { ButtonsMixin, ButtonsMixinConstructor };
/**
@license
Copyright (c) 2019 Vaadin Ltd.
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
* @license
* Copyright (c) 2020 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { animationFrame } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';

@@ -15,225 +14,223 @@ import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';

*/
export const ButtonsMixin = superClass => class extends mixinBehaviors(IronResizableBehavior, superClass) {
export const ButtonsMixin = (superClass) =>
class extends mixinBehaviors(IronResizableBehavior, superClass) {
static get properties() {
return {
/**
* @type {boolean}
* @protected
*/
_hasOverflow: {
type: Boolean,
value: false
}
};
}
static get properties() {
return {
/**
* @type {boolean}
* @protected
*/
_hasOverflow: {
type: Boolean,
value: false
}
};
}
static get observers() {
return ['_menuItemsChanged(items, items.splices)'];
}
static get observers() {
return [
'_menuItemsChanged(items, items.splices)'
];
}
/** @protected */
ready() {
super.ready();
/** @protected */
ready() {
super.ready();
this.setAttribute('role', 'menubar');
this.setAttribute('role', 'menubar');
this.addEventListener('iron-resize', () => this.__onResize());
this.addEventListener('iron-resize', e => this.__onResize());
this._overflow.setAttribute('role', 'menuitem');
this._overflow.setAttribute('aria-haspopup', 'true');
this._overflow.setAttribute('aria-expanded', 'false');
}
this._overflow.setAttribute('role', 'menuitem');
this._overflow.setAttribute('aria-haspopup', 'true');
this._overflow.setAttribute('aria-expanded', 'false');
}
/**
* @return {!Array<!HTMLElement>}
* @protected
*/
get _buttons() {
return Array.from(this.shadowRoot.querySelectorAll('[part$="button"]'));
}
/**
* @return {!Array<!HTMLElement>}
* @protected
*/
get _buttons() {
return Array.from(this.shadowRoot.querySelectorAll('[part$="button"]'));
}
/**
* @return {!HTMLElement}
* @protected
*/
get _container() {
return this.shadowRoot.querySelector('[part="container"]');
}
/**
* @return {!HTMLElement}
* @protected
*/
get _container() {
return this.shadowRoot.querySelector('[part="container"]');
}
/**
* @return {!HTMLElement}
* @protected
*/
get _overflow() {
return this.shadowRoot.querySelector('[part="overflow-button"]');
}
/**
* @return {!HTMLElement}
* @protected
*/
get _overflow() {
return this.shadowRoot.querySelector('[part="overflow-button"]');
}
/** @private */
_menuItemsChanged(items, splices) {
if (items !== this._oldItems) {
this._oldItems = items;
this.__renderButtons(items);
/** @private */
_menuItemsChanged(items) {
if (items !== this._oldItems) {
this._oldItems = items;
this.__renderButtons(items);
}
}
}
/** @private */
__detectOverflow() {
const container = this._container;
const buttons = this._buttons.slice(0);
const overflow = buttons.pop();
const containerWidth = container.offsetWidth;
const isRTL = this.getAttribute('dir') === 'rtl';
/** @private */
__detectOverflow() {
const container = this._container;
const buttons = this._buttons.slice(0);
const overflow = buttons.pop();
const containerWidth = container.offsetWidth;
const isRTL = this.getAttribute('dir') === 'rtl';
if (container.offsetWidth < container.scrollWidth) {
this._hasOverflow = true;
if (container.offsetWidth < container.scrollWidth) {
this._hasOverflow = true;
let i;
for (i = buttons.length; i > 0; i--) {
const btn = buttons[i - 1];
const btnStyle = getComputedStyle(btn);
if (btnStyle.visibility === 'hidden') {
continue;
}
let i;
for (i = buttons.length; i > 0; i--) {
const btn = buttons[i - 1];
const btnStyle = getComputedStyle(btn);
if (btnStyle.visibility === 'hidden') {
continue;
}
const btnWidth = btn.offsetWidth;
if (
(!isRTL && (btn.offsetLeft + btnWidth) < (containerWidth - overflow.offsetWidth)) ||
(isRTL && btn.offsetLeft >= overflow.offsetWidth)
) {
break;
const btnWidth = btn.offsetWidth;
if (
(!isRTL && btn.offsetLeft + btnWidth < containerWidth - overflow.offsetWidth) ||
(isRTL && btn.offsetLeft >= overflow.offsetWidth)
) {
break;
}
btn.disabled = true;
btn.style.visibility = 'hidden';
btn.style.position = 'absolute';
// save width for buttons with component
btn.style.width = btnStyle.width;
}
overflow.item = {
children: buttons.filter((b, idx) => idx >= i).map((b) => b.item)
};
} else if (this._hasOverflow) {
if (this._subMenu.opened) {
this._subMenu.close();
}
btn.disabled = true;
btn.style.visibility = 'hidden';
btn.style.position = 'absolute';
// save width for buttons with component
btn.style.width = btnStyle.width;
}
overflow.item = {
children: buttons.filter((b, idx) => idx >= i).map(b => b.item)
};
} else if (this._hasOverflow) {
if (this._subMenu.opened) {
this._subMenu.close();
}
for (let i = 0; i < buttons.length; i++) {
const btn = buttons[i];
const btnWidth = btn.getBoundingClientRect().width;
for (let i = 0; i < buttons.length; i++) {
const btn = buttons[i];
const btnWidth = btn.getBoundingClientRect().width;
if (getComputedStyle(btn).visibility !== 'hidden') {
continue;
}
if (getComputedStyle(btn).visibility !== 'hidden') {
continue;
}
if (
(!isRTL && overflow.offsetLeft + overflow.offsetWidth + btnWidth < containerWidth) ||
(isRTL && btnWidth < overflow.offsetLeft)
) {
btn.disabled = btn.item.disabled;
btn.style.visibility = '';
btn.style.position = '';
btn.style.width = '';
if (
(!isRTL && (overflow.offsetLeft + overflow.offsetWidth + btnWidth) < containerWidth) ||
(isRTL && (btnWidth < overflow.offsetLeft))
) {
btn.disabled = btn.item.disabled;
btn.style.visibility = '';
btn.style.position = '';
btn.style.width = '';
// teleport item component back from "overflow" sub-menu
const item = btn.item && btn.item.component;
if (item instanceof HTMLElement && item.classList.contains('vaadin-menu-item')) {
btn.appendChild(item);
item.classList.remove('vaadin-menu-item');
}
// teleport item component back from "overflow" sub-menu
const item = btn.item && btn.item.component;
if (item instanceof HTMLElement && item.classList.contains('vaadin-menu-item')) {
btn.appendChild(item);
item.classList.remove('vaadin-menu-item');
}
overflow.item = {
children: buttons.filter((b, idx) => idx >= i + 1).map((b) => b.item)
};
overflow.item = {
children: buttons.filter((b, idx) => idx >= i + 1).map(b => b.item)
};
if (btn === buttons[buttons.length - 1]) {
this._hasOverflow = false;
overflow.item = {children: []};
if (btn === buttons[buttons.length - 1]) {
this._hasOverflow = false;
overflow.item = { children: [] };
}
} else {
break;
}
} else {
break;
}
}
}
}
/**
* Call this method after updating menu bar `items` dynamically, including changing
* any property on the item object corresponding to one of the menu bar buttons.
*/
render() {
if (!this.shadowRoot) {
return;
/**
* Call this method after updating menu bar `items` dynamically, including changing
* any property on the item object corresponding to one of the menu bar buttons.
*/
render() {
if (!this.shadowRoot) {
return;
}
this.__renderButtons(this.items);
}
this.__renderButtons(this.items);
}
/** @private */
__renderButtons(items = []) {
const container = this._container;
const overflow = this._overflow;
/** @private */
__renderButtons(items = []) {
const container = this._container;
const overflow = this._overflow;
while (container.children.length > 1) {
container.removeChild(container.firstElementChild);
}
while (container.children.length > 1) {
container.removeChild(container.firstElementChild);
}
items.forEach(item => {
const button = document.createElement('vaadin-menu-bar-button');
const itemCopy = Object.assign({}, item);
button.item = itemCopy;
items.forEach((item) => {
const button = document.createElement('vaadin-menu-bar-button');
const itemCopy = Object.assign({}, item);
button.item = itemCopy;
const itemComponent = item.component;
if (itemComponent) {
let component;
const isElement = itemComponent instanceof HTMLElement;
// use existing item component, if any
if (isElement && itemComponent.localName === 'vaadin-context-menu-item') {
component = itemComponent;
const itemComponent = item.component;
if (itemComponent) {
let component;
const isElement = itemComponent instanceof HTMLElement;
// use existing item component, if any
if (isElement && itemComponent.localName === 'vaadin-context-menu-item') {
component = itemComponent;
} else {
component = document.createElement('vaadin-context-menu-item');
component.appendChild(isElement ? itemComponent : document.createElement(itemComponent));
}
if (item.text) {
const node = component.firstChild || component;
node.textContent = item.text;
}
itemCopy.component = component;
// save item for overflow menu
component.item = itemCopy;
component.setAttribute('theme', 'menu-bar-item');
button.appendChild(component);
} else if (item.text) {
button.textContent = item.text;
}
if (item.disabled) {
button.disabled = true;
button.setAttribute('tabindex', '-1');
} else {
component = document.createElement('vaadin-context-menu-item');
component.appendChild(isElement ? itemComponent : document.createElement(itemComponent));
button.setAttribute('tabindex', '0');
}
if (item.text) {
const node = component.firstChild || component;
node.textContent = item.text;
if (button.item.children) {
button.setAttribute('aria-haspopup', 'true');
button.setAttribute('aria-expanded', 'false');
}
itemCopy.component = component;
// save item for overflow menu
component.item = itemCopy;
component.setAttribute('theme', 'menu-bar-item');
button.appendChild(component);
} else if (item.text) {
button.textContent = item.text;
}
if (item.disabled) {
button.disabled = true;
button.setAttribute('tabindex', '-1');
} else {
button.setAttribute('tabindex', '0');
}
if (button.item.children) {
button.setAttribute('aria-haspopup', 'true');
button.setAttribute('aria-expanded', 'false');
}
button.setAttribute('part', 'menu-bar-button');
if (this.theme && this.theme !== '') {
button.setAttribute('theme', this.theme);
}
container.insertBefore(button, overflow);
button.setAttribute('role', 'menuitem');
});
button.setAttribute('part', 'menu-bar-button');
if (this.theme && this.theme !== '') {
button.setAttribute('theme', this.theme);
}
container.insertBefore(button, overflow);
button.setAttribute('role', 'menuitem');
});
this.__detectOverflow();
}
this.__detectOverflow();
}
/** @private */
__onResize() {
this.__debounceOverflow = Debouncer.debounce(
this.__debounceOverflow,
animationFrame,
this.__detectOverflow.bind(this)
);
}
};
/** @private */
__onResize() {
this.__debounceOverflow = Debouncer.debounce(
this.__debounceOverflow,
animationFrame,
this.__detectOverflow.bind(this)
);
}
};

@@ -1,27 +0,8 @@

/**
* DO NOT EDIT
*
* This file was automatically generated by
* https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations
*
* To modify these typings, edit the source file(s):
* src/vaadin-menu-bar-interactions-mixin.js
*/
// tslint:disable:variable-name Describing an API that's defined elsewhere.
// tslint:disable:no-any describes the API as best we are able today
export {InteractionsMixin};
declare function InteractionsMixin<T extends new (...args: any[]) => {}>(base: T): T & InteractionsMixinConstructor;
interface InteractionsMixinConstructor {
new(...args: any[]): InteractionsMixin;
new (...args: any[]): InteractionsMixin;
}
export {InteractionsMixinConstructor};
interface InteractionsMixin {
/**

@@ -31,6 +12,3 @@ * If true, the submenu will open on hover (mouseover) instead of click.

*/
openOnHover: boolean|null|undefined;
ready(): void;
connectedCallback(): void;
disconnectedCallback(): void;
openOnHover: boolean | null | undefined;

@@ -42,6 +20,12 @@ /**

notifyResize(): void;
_onFocusin(event: FocusEvent): void;
_onKeydown(event: KeyboardEvent): void;
_onMouseOver(e: MouseEvent): void;
_close(restoreFocus: boolean): void;
}
export { InteractionsMixin, InteractionsMixinConstructor };
/**
@license
Copyright (c) 2019 Vaadin Ltd.
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
* @license
* Copyright (c) 2020 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
/**
* @polymerMixin
*/
export const InteractionsMixin = superClass => class InteractionsMixin extends superClass {
export const InteractionsMixin = (superClass) =>
class InteractionsMixin extends superClass {
static get properties() {
return {
/**
* If true, the submenu will open on hover (mouseover) instead of click.
* @attr {boolean} open-on-hover
*/
openOnHover: {
type: Boolean
}
};
}
static get properties() {
return {
/**
* If true, the submenu will open on hover (mouseover) instead of click.
* @attr {boolean} open-on-hover
*/
openOnHover: {
type: Boolean
}
};
}
constructor() {
super();
this.__boundOnContextMenuKeydown = this.__onContextMenuKeydown.bind(this);
}
constructor() {
super();
this.__boundOnContextMenuKeydown = this.__onContextMenuKeydown.bind(this);
}
static get observers() {
return ['_itemsChanged(items, items.splices)', '_themeChanged(theme)'];
}
static get observers() {
return [
'_itemsChanged(items, items.splices)',
'_themeChanged(theme)'
];
}
/** @protected */
ready() {
super.ready();
/** @protected */
ready() {
super.ready();
this.addEventListener('keydown', (e) => this._onKeydown(e));
this.addEventListener('focusin', (e) => this._onFocusin(e));
this.addEventListener('keydown', e => this._onKeydown(e));
this.addEventListener('focusin', e => this._onFocusin(e));
this._subMenu.addEventListener('item-selected', this.__onItemSelected.bind(this));
this._subMenu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
this._subMenu.addEventListener('item-selected', this.__onItemSelected.bind(this));
this._subMenu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
const overlay = this._subMenu.$.overlay;
overlay.addEventListener('keydown', this.__boundOnContextMenuKeydown);
overlay.addEventListener('vaadin-overlay-open', this.__alignOverlayPosition.bind(this));
const overlay = this._subMenu.$.overlay;
overlay.addEventListener('keydown', this.__boundOnContextMenuKeydown);
overlay.addEventListener('vaadin-overlay-open', this.__alignOverlayPosition.bind(this));
const container = this._container;
container.addEventListener('click', this.__onButtonClick.bind(this));
container.addEventListener('mouseover', (e) => this._onMouseOver(e));
}
const container = this._container;
container.addEventListener('click', this.__onButtonClick.bind(this));
container.addEventListener('mouseover', e => this._onMouseOver(e));
}
/** @protected */
connectedCallback() {
super.connectedCallback();
document.addEventListener('click', this.__boundOutsideClickListener, true);
}
/** @protected */
connectedCallback() {
super.connectedCallback();
document.addEventListener('click', this.__boundOutsideClickListener, true);
}
/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener('click', this.__boundOutsideClickListener, true);
}
/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
document.removeEventListener('click', this.__boundOutsideClickListener, true);
}
/**
* Can be called to manually notify a resizable and its descendant
* resizables of a resize change.
*/
notifyResize() {
// NOTE: we have this method here to include it to TypeScript definitions.
// gen-typescript-declarations does not generate types for `mixinBehaviors`
super.notifyResize();
}
/**
* Can be called to manually notify a resizable and its descendant
* resizables of a resize change.
*/
notifyResize() {
// NOTE: we have this method here to include it to TypeScript definitions.
// gen-typescript-declarations does not generate types for `mixinBehaviors`
super.notifyResize();
}
/** @private */
get __isRTL() {
return this.getAttribute('dir') === 'rtl';
}
/** @private */
get __isRTL() {
return this.getAttribute('dir') === 'rtl';
}
/** @private */
_themeChanged(theme) {
if (theme) {
this._buttons.forEach((button) => button.setAttribute('theme', theme));
this._subMenu.setAttribute('theme', theme);
} else {
this._buttons.forEach((button) => button.removeAttribute('theme'));
this._subMenu.removeAttribute('theme');
}
}
/** @private */
_themeChanged(theme) {
if (theme) {
this._buttons.forEach(button => button.setAttribute('theme', theme));
this._subMenu.setAttribute('theme', theme);
} else {
this._buttons.forEach(button => button.removeAttribute('theme'));
this._subMenu.removeAttribute('theme');
/** @private */
_focusButton(button) {
button.focus();
button.setAttribute('focus-ring', '');
this._buttons.forEach((btn) => {
btn.setAttribute('tabindex', btn === button ? '0' : '-1');
});
}
}
/** @private */
_focusButton(button) {
button.focus();
button.setAttribute('focus-ring', '');
this._buttons.forEach(btn => {
btn.setAttribute('tabindex', btn === button ? '0' : '-1');
});
}
/** @private */
_getButtonFromEvent(e) {
return Array.from(e.composedPath()).filter((el) => el.localName === 'vaadin-menu-bar-button')[0];
}
/** @private */
_getButtonFromEvent(e) {
return Array.from(e.composedPath()).filter(el => el.localName === 'vaadin-menu-bar-button')[0];
}
/**
* @param {!FocusEvent} event
* @protected
*/
_onFocusin(event) {
const target = this.shadowRoot.querySelector('[part$="button"][tabindex="0"]');
if (target) {
this._buttons.forEach(btn => {
btn.setAttribute('tabindex', btn === target ? '0' : '-1');
});
/**
* @param {!FocusEvent} event
* @protected
*/
_onFocusin() {
const target = this.shadowRoot.querySelector('[part$="button"][tabindex="0"]');
if (target) {
this._buttons.forEach((btn) => {
btn.setAttribute('tabindex', btn === target ? '0' : '-1');
});
}
}
}
/**
* @param {!KeyboardEvent} event
* @protected
*/
_onKeydown(event) {
const button = this._getButtonFromEvent(event);
if (button) {
if (event.keyCode === 40) {
// ArrowDown, prevent page scroll
event.preventDefault();
if (button === this._expandedButton) {
// Menu opened previously, focus first item
this._focusFirstItem();
/**
* @param {!KeyboardEvent} event
* @protected
*/
_onKeydown(event) {
const button = this._getButtonFromEvent(event);
if (button) {
if (event.keyCode === 40) {
// ArrowDown, prevent page scroll
event.preventDefault();
if (button === this._expandedButton) {
// Menu opened previously, focus first item
this._focusFirstItem();
} else {
this.__openSubMenu(button, event);
}
} else if (event.keyCode === 38) {
// ArrowUp, prevent page scroll
event.preventDefault();
if (button === this._expandedButton) {
// Menu opened previously, focus last item
this._focusLastItem();
} else {
this.__openSubMenu(button, event, { focusLast: true });
}
} else if (event.keyCode === 27 && button === this._expandedButton) {
this._close(true);
} else {
this.__openSubMenu(button, event);
this._navigateByKey(event);
}
} else if (event.keyCode === 38) {
// ArrowUp, prevent page scroll
event.preventDefault();
if (button === this._expandedButton) {
// Menu opened previously, focus last item
this._focusLastItem();
} else {
this.__openSubMenu(button, event, {focusLast: true});
}
} else if (event.keyCode === 27 && button === this._expandedButton) {
this._close(true);
} else {
this._navigateByKey(event);
}
}
}
/** @private */
_navigateByKey(event) {
// IE names for arrows do not include the Arrow prefix
const key = event.key.replace(/^Arrow/, '');
const buttons = this._buttons;
const currentBtn = this.shadowRoot.activeElement || this._expandedButton;
const currentIdx = buttons.indexOf(currentBtn);
let idx;
let increment;
const dirIncrement = this.__isRTL ? -1 : 1;
/** @private */
_navigateByKey(event) {
// IE names for arrows do not include the Arrow prefix
const key = event.key.replace(/^Arrow/, '');
const buttons = this._buttons;
const currentBtn = this.shadowRoot.activeElement || this._expandedButton;
const currentIdx = buttons.indexOf(currentBtn);
let idx;
let increment;
const dirIncrement = this.__isRTL ? -1 : 1;
switch (key) {
case 'Left':
increment = -dirIncrement;
idx = currentIdx - dirIncrement;
break;
case 'Right':
increment = dirIncrement;
idx = currentIdx + dirIncrement;
break;
case 'Home':
increment = 1;
idx = 0;
break;
case 'End':
increment = -1;
idx = buttons.length - 1;
break;
default:
switch (key) {
case 'Left':
increment = -dirIncrement;
idx = currentIdx - dirIncrement;
break;
case 'Right':
increment = dirIncrement;
idx = currentIdx + dirIncrement;
break;
case 'Home':
increment = 1;
idx = 0;
break;
case 'End':
increment = -1;
idx = buttons.length - 1;
break;
default:
// do nothing.
}
}
idx = this._getAvailableIndex(idx, increment, buttons);
if (idx >= 0) {
event.preventDefault();
const btn = buttons[idx];
const wasExpanded = currentBtn === this._expandedButton;
if (wasExpanded) {
this._close();
idx = this._getAvailableIndex(idx, increment, buttons);
if (idx >= 0) {
event.preventDefault();
const btn = buttons[idx];
const wasExpanded = currentBtn === this._expandedButton;
if (wasExpanded) {
this._close();
}
this._focusButton(btn);
if (wasExpanded && btn.item && btn.item.children) {
this.__openSubMenu(btn, event, { keepFocus: true });
}
}
this._focusButton(btn);
if (wasExpanded && btn.item && btn.item.children) {
this.__openSubMenu(btn, event, {keepFocus: true});
}
}
}
/** @private */
_getAvailableIndex(index, increment, buttons) {
const totalItems = buttons.length;
let idx = index;
for (let i = 0; typeof idx === 'number' && i < totalItems; i++, idx += increment || 1) {
if (idx < 0) {
idx = totalItems - 1;
} else if (idx >= totalItems) {
idx = 0;
}
/** @private */
_getAvailableIndex(index, increment, buttons) {
const totalItems = buttons.length;
let idx = index;
for (let i = 0; typeof idx === 'number' && i < totalItems; i++, idx += increment || 1) {
if (idx < 0) {
idx = totalItems - 1;
} else if (idx >= totalItems) {
idx = 0;
}
const btn = buttons[idx];
if (!btn.disabled && !btn.hasAttribute('hidden')) {
return idx;
const btn = buttons[idx];
if (!btn.disabled && !btn.hasAttribute('hidden')) {
return idx;
}
}
return -1;
}
return -1;
}
/** @private */
get _subMenu() {
return this.shadowRoot.querySelector('vaadin-menu-bar-submenu');
}
/** @private */
get _subMenu() {
return this.shadowRoot.querySelector('vaadin-menu-bar-submenu');
}
/** @private */
__alignOverlayPosition(e) {
/* istanbul ignore if */
if (!this._expandedButton) {
// When `openOnHover` is true, quickly moving cursor can close submenu,
// so by the time when event listener gets executed button is null.
// See https://github.com/vaadin/vaadin-menu-bar/issues/85
return;
}
const overlay = e.target;
const {width, height, left} = this._expandedButton.getBoundingClientRect();
if (overlay.hasAttribute('bottom-aligned')) {
overlay.style.bottom = parseInt(getComputedStyle(overlay).bottom) + height + 'px';
}
const endAligned = overlay.hasAttribute('end-aligned');
if (endAligned) {
if (this.__isRTL) {
overlay.style.left = left + 'px';
} else {
overlay.style.right = parseInt(getComputedStyle(overlay).right) - width + 'px';
/** @private */
__alignOverlayPosition(e) {
/* istanbul ignore if */
if (!this._expandedButton) {
// When `openOnHover` is true, quickly moving cursor can close submenu,
// so by the time when event listener gets executed button is null.
// See https://github.com/vaadin/vaadin-menu-bar/issues/85
return;
}
const overlay = e.target;
const { width, height, left } = this._expandedButton.getBoundingClientRect();
if (overlay.hasAttribute('bottom-aligned')) {
overlay.style.bottom = parseInt(getComputedStyle(overlay).bottom) + height + 'px';
}
const endAligned = overlay.hasAttribute('end-aligned');
if (endAligned) {
if (this.__isRTL) {
overlay.style.left = left + 'px';
} else {
overlay.style.right = parseInt(getComputedStyle(overlay).right) - width + 'px';
}
}
}
}
/** @private */
_itemsChanged(items, splices) {
const subMenu = this._subMenu;
if (subMenu && subMenu.opened) {
subMenu.close();
/** @private */
_itemsChanged() {
const subMenu = this._subMenu;
if (subMenu && subMenu.opened) {
subMenu.close();
}
}
}
/**
* @param {!MouseEvent} e
* @protected
*/
_onMouseOver(e) {
const button = this._getButtonFromEvent(e);
if (button && button !== this._expandedButton) {
const isOpened = this._subMenu.opened;
if (button.item.children && (this.openOnHover || isOpened)) {
this.__openSubMenu(button, e);
} else if (isOpened) {
this._close();
/**
* @param {!MouseEvent} e
* @protected
*/
_onMouseOver(e) {
const button = this._getButtonFromEvent(e);
if (button && button !== this._expandedButton) {
const isOpened = this._subMenu.opened;
if (button.item.children && (this.openOnHover || isOpened)) {
this.__openSubMenu(button, e);
} else if (isOpened) {
this._close();
}
}
}
}
/** @private */
__onContextMenuKeydown(e) {
const item = Array.from(e.composedPath()).filter(el => el._item)[0];
if (item) {
const list = item.parentNode;
if (e.keyCode === 38 && item === list.items[0]) {
this._close(true);
}
// ArrowLeft, or ArrowRight on non-parent submenu item
if (e.keyCode === 37 || (e.keyCode === 39 && !item._item.children)) {
// Prevent ArrowLeft from being handled in context-menu
e.stopImmediatePropagation();
this._navigateByKey(e);
const button = this.shadowRoot.activeElement;
if (button && button.item && button.item.children) {
this.__openSubMenu(button, e, {keepFocus: true});
/** @private */
__onContextMenuKeydown(e) {
const item = Array.from(e.composedPath()).filter((el) => el._item)[0];
if (item) {
const list = item.parentNode;
if (e.keyCode === 38 && item === list.items[0]) {
this._close(true);
}
// ArrowLeft, or ArrowRight on non-parent submenu item
if (e.keyCode === 37 || (e.keyCode === 39 && !item._item.children)) {
// Prevent ArrowLeft from being handled in context-menu
e.stopImmediatePropagation();
this._navigateByKey(e);
const button = this.shadowRoot.activeElement;
if (button && button.item && button.item.children) {
this.__openSubMenu(button, e, { keepFocus: true });
}
}
}
}
}
/** @private */
__fireItemSelected(value) {
this.dispatchEvent(new CustomEvent('item-selected', {detail: {value}}));
}
/** @private */
__fireItemSelected(value) {
this.dispatchEvent(new CustomEvent('item-selected', { detail: { value } }));
}
/** @private */
__onButtonClick(e) {
e.stopPropagation();
const button = this._getButtonFromEvent(e);
if (button) {
this.__openSubMenu(button, e);
/** @private */
__onButtonClick(e) {
e.stopPropagation();
const button = this._getButtonFromEvent(e);
if (button) {
this.__openSubMenu(button, e);
}
}
}
/** @private */
__openSubMenu(button, event, options = {}) {
const subMenu = this._subMenu;
const item = button.item;
/** @private */
__openSubMenu(button, event, options = {}) {
const subMenu = this._subMenu;
const item = button.item;
if (subMenu.opened) {
this._close();
if (subMenu.listenOn === button) {
if (subMenu.opened) {
this._close();
if (subMenu.listenOn === button) {
return;
}
}
const items = item && item.children;
if (!items || items.length === 0) {
this.__fireItemSelected(item);
return;
}
}
const items = item && item.children;
if (!items || items.length === 0) {
this.__fireItemSelected(item);
return;
}
subMenu.items = items;
subMenu.listenOn = button;
this._expandedButton = button;
subMenu.items = items;
subMenu.listenOn = button;
this._expandedButton = button;
const rect = button.getBoundingClientRect();
const rect = button.getBoundingClientRect();
requestAnimationFrame(() => {
button.dispatchEvent(
new CustomEvent('opensubmenu', {
detail: {
x: this.__isRTL ? rect.right : rect.left,
y: rect.bottom,
children: items
}
})
);
requestAnimationFrame(() => {
button.dispatchEvent(new CustomEvent('opensubmenu', {detail: {
x: this.__isRTL ? rect.right : rect.left,
y: rect.bottom,
children: items
}}));
button.setAttribute('expanded', '');
button.setAttribute('aria-expanded', 'true');
});
button.setAttribute('expanded', '');
button.setAttribute('aria-expanded', 'true');
});
if (options.focusLast) {
this.__onceOpened(() => this._focusLastItem());
}
if (options.focusLast) {
this.__onceOpened(() => this._focusLastItem());
if (options.keepFocus) {
this.__onceOpened(() => {
this._focusButton(this._expandedButton);
});
}
// do not focus item when open not from keyboard
if (event.type !== 'keydown') {
this.__onceOpened(() => {
subMenu.$.overlay.$.overlay.focus();
});
}
}
if (options.keepFocus) {
this.__onceOpened(() => {
this._focusButton(this._expandedButton);
});
/** @private */
_focusFirstItem() {
const list = this._subMenu.$.overlay.firstElementChild;
list.focus();
}
// do not focus item when open not from keyboard
if (event.type !== 'keydown') {
this.__onceOpened(() => {
subMenu.$.overlay.$.overlay.focus();
});
/** @private */
_focusLastItem() {
const list = this._subMenu.$.overlay.firstElementChild;
const item = list.items[list.items.length - 1];
item && item.focus();
}
}
/** @private */
_focusFirstItem() {
const list = this._subMenu.$.overlay.firstElementChild;
list.focus();
}
/** @private */
__onceOpened(cb) {
this.style.pointerEvents = 'auto';
const overlay = this._subMenu.$.overlay;
const listener = () => {
cb();
overlay.removeEventListener('vaadin-overlay-open', listener);
};
overlay.addEventListener('vaadin-overlay-open', listener);
}
/** @private */
_focusLastItem() {
const list = this._subMenu.$.overlay.firstElementChild;
const item = list.items[list.items.length - 1];
item && item.focus();
}
/** @private */
__onItemSelected(e) {
e.stopPropagation();
this._close();
this.__fireItemSelected(e.detail.value);
}
/** @private */
__onceOpened(cb) {
this.style.pointerEvents = 'auto';
const overlay = this._subMenu.$.overlay;
const listener = () => {
cb();
overlay.removeEventListener('vaadin-overlay-open', listener);
};
overlay.addEventListener('vaadin-overlay-open', listener);
}
/** @private */
__onEscapeClose() {
this.__deactivateButton(true);
}
/** @private */
__onItemSelected(e) {
e.stopPropagation();
this._close();
this.__fireItemSelected(e.detail.value);
}
/** @private */
__onEscapeClose(e) {
this.__deactivateButton(true);
}
/** @private */
__deactivateButton(restoreFocus) {
const button = this._expandedButton;
if (button && button.hasAttribute('expanded')) {
button.removeAttribute('expanded');
button.setAttribute('aria-expanded', 'false');
if (restoreFocus) {
this._focusButton(button);
/** @private */
__deactivateButton(restoreFocus) {
const button = this._expandedButton;
if (button && button.hasAttribute('expanded')) {
button.removeAttribute('expanded');
button.setAttribute('aria-expanded', 'false');
if (restoreFocus) {
this._focusButton(button);
}
this._expandedButton = null;
}
this._expandedButton = null;
}
}
/**
* @param {boolean} restoreFocus
* @protected
*/
_close(restoreFocus) {
this.style.pointerEvents = '';
this.__deactivateButton(restoreFocus);
this._subMenu.opened && this._subMenu.close();
}
};
/**
* @param {boolean} restoreFocus
* @protected
*/
_close(restoreFocus) {
this.style.pointerEvents = '';
this.__deactivateButton(restoreFocus);
this._subMenu.opened && this._subMenu.close();
}
};
/**
@license
Copyright (c) 2019 Vaadin Ltd.
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
* @license
* Copyright (c) 2020 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { ContextMenuElement } from '@vaadin/vaadin-context-menu/src/vaadin-context-menu.js';

@@ -29,3 +29,2 @@

/**

@@ -32,0 +31,0 @@ * Overriding the public method to reset expanded button state.

@@ -1,26 +0,11 @@

/**
* DO NOT EDIT
*
* This file was automatically generated by
* https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations
*
* To modify these typings, edit the source file(s):
* src/vaadin-menu-bar.js
*/
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js';
// tslint:disable:variable-name Describing an API that's defined elsewhere.
import { ButtonsMixin } from './vaadin-menu-bar-buttons-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import { InteractionsMixin } from './vaadin-menu-bar-interactions-mixin.js';
import {ThemableMixin} from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { MenuBarEventMap, MenuBarItem } from './interfaces';
import {ElementMixin} from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js';
import {ButtonsMixin} from './vaadin-menu-bar-buttons-mixin.js';
import {InteractionsMixin} from './vaadin-menu-bar-interactions-mixin.js';
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
/**

@@ -54,10 +39,6 @@ * `<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering

* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
*
* @fires {CustomEvent} item-selected - Fired when a submenu item or menu bar button without children is clicked.
*/
declare class MenuBarElement extends
ButtonsMixin(
InteractionsMixin(
ElementMixin(
ThemableMixin(
PolymerElement)))) {
declare class MenuBarElement extends ButtonsMixin(InteractionsMixin(ElementMixin(ThemableMixin(HTMLElement)))) {
/**

@@ -92,13 +73,22 @@ * Defines a hierarchical structure, where root level items represent menu bar buttons,

items: MenuBarItem[];
addEventListener<K extends keyof MenuBarEventMap>(
type: K,
listener: (this: MenuBarElement, ev: MenuBarEventMap[K]) => void,
options?: boolean | AddEventListenerOptions
): void;
removeEventListener<K extends keyof MenuBarEventMap>(
type: K,
listener: (this: MenuBarElement, ev: MenuBarEventMap[K]) => void,
options?: boolean | EventListenerOptions
): void;
}
declare global {
interface HTMLElementTagNameMap {
"vaadin-menu-bar": MenuBarElement;
'vaadin-menu-bar': MenuBarElement;
}
}
export {MenuBarElement};
import {MenuBarItem} from '../@types/interfaces';
export { MenuBarElement };
/**
@license
Copyright (c) 2019 Vaadin Ltd.
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
* @license
* Copyright (c) 2020 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js';
import './vaadin-menu-bar-button.js';
import { ButtonsMixin } from './vaadin-menu-bar-buttons-mixin.js';
import { InteractionsMixin } from './vaadin-menu-bar-interactions-mixin.js';
import './vaadin-menu-bar-submenu.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import './vaadin-menu-bar-button.js';

@@ -45,3 +43,5 @@ /**

*
* @extends PolymerElement
* @fires {CustomEvent<boolean>} item-selected - Fired when a submenu item or menu bar button without children is clicked.
*
* @extends HTMLElement
* @mixes ButtonsMixin

@@ -51,51 +51,46 @@ * @mixes InteractionsMixin

* @mixes ThemableMixin
* @demo demo/index.html
*/
class MenuBarElement extends
ButtonsMixin(
InteractionsMixin(
ElementMixin(
ThemableMixin(PolymerElement)))) {
class MenuBarElement extends ButtonsMixin(InteractionsMixin(ElementMixin(ThemableMixin(PolymerElement)))) {
static get template() {
return html`
<style>
:host {
display: block;
}
<style>
:host {
display: block;
}
:host([hidden]) {
display: none !important;
}
:host([hidden]) {
display: none !important;
}
[part="container"] {
position: relative;
display: flex;
width: 100%;
flex-wrap: nowrap;
overflow: hidden;
}
[part='container'] {
position: relative;
display: flex;
width: 100%;
flex-wrap: nowrap;
overflow: hidden;
}
[part\$="button"] {
flex-shrink: 0;
}
[part$='button'] {
flex-shrink: 0;
}
[part="overflow-button"] {
margin-right: 0;
}
[part='overflow-button'] {
margin-right: 0;
}
.dots::before {
display: block;
content: "\\00B7\\00B7\\00B7";
font-size: inherit;
line-height: inherit;
}
</style>
.dots::before {
display: block;
content: '\\00B7\\00B7\\00B7';
font-size: inherit;
line-height: inherit;
}
</style>
<div part="container">
<vaadin-menu-bar-button part="overflow-button" hidden\$="[[!_hasOverflow]]">
<div class="dots"></div>
</vaadin-menu-bar-button>
</div>
<vaadin-menu-bar-submenu is-root=""></vaadin-menu-bar-submenu>
`;
<div part="container">
<vaadin-menu-bar-button part="overflow-button" hidden$="[[!_hasOverflow]]">
<div class="dots"></div>
</vaadin-menu-bar-button>
</div>
<vaadin-menu-bar-submenu is-root=""></vaadin-menu-bar-submenu>
`;
}

@@ -108,3 +103,3 @@

static get version() {
return '1.2.1';
return '2.0.0-alpha1';
}

@@ -111,0 +106,0 @@

@@ -0,121 +1,119 @@

import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-button/theme/lumo/vaadin-button-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
const $_documentContainer = html`<dom-module id="lumo-menu-bar-button" theme-for="vaadin-menu-bar-button">
<template>
<style include="lumo-button">
:host {
margin: calc(var(--lumo-space-xs) / 2);
margin-left: 0;
border-radius: 0;
}
registerStyles(
'vaadin-menu-bar-button',
css`
:host {
margin: calc(var(--lumo-space-xs) / 2);
margin-left: 0;
border-radius: 0;
}
[part="label"] {
width: 100%;
}
[part='label'] {
width: 100%;
}
/* NOTE(web-padawan): avoid using shorthand padding property for IE11 */
[part="label"] ::slotted(vaadin-context-menu-item) {
justify-content: center;
height: var(--lumo-button-size);
margin: 0 calc((var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2) * -1);
padding-left: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2);
padding-right: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2);
}
/* NOTE(web-padawan): avoid using shorthand padding property for IE11 */
[part='label'] ::slotted(vaadin-context-menu-item) {
justify-content: center;
height: var(--lumo-button-size);
margin: 0 calc((var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2) * -1);
padding-left: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2);
padding-right: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius) / 2);
}
:host([theme~="small"]) [part="label"] ::slotted(vaadin-context-menu-item) {
min-height: var(--lumo-size-s);
margin: 0 calc((var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2) * -1);
padding-left: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2);
padding-right: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2);
}
:host([theme~='small']) [part='label'] ::slotted(vaadin-context-menu-item) {
min-height: var(--lumo-size-s);
margin: 0 calc((var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2) * -1);
padding-left: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2);
padding-right: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius) / 2);
}
:host([theme~="tertiary"]) [part="label"] ::slotted(vaadin-context-menu-item) {
margin: 0 calc((var(--lumo-button-size) / 6) * -1);
padding-left: calc(var(--lumo-button-size) / 6);
padding-right: calc(var(--lumo-button-size) / 6);
}
:host([theme~='tertiary']) [part='label'] ::slotted(vaadin-context-menu-item) {
margin: 0 calc((var(--lumo-button-size) / 6) * -1);
padding-left: calc(var(--lumo-button-size) / 6);
padding-right: calc(var(--lumo-button-size) / 6);
}
:host([theme~="tertiary-inline"]) {
margin-top: calc(var(--lumo-space-xs) / 2);
margin-bottom: calc(var(--lumo-space-xs) / 2);
margin-right: calc(var(--lumo-space-xs) / 2);
}
:host([theme~='tertiary-inline']) {
margin-top: calc(var(--lumo-space-xs) / 2);
margin-bottom: calc(var(--lumo-space-xs) / 2);
margin-right: calc(var(--lumo-space-xs) / 2);
}
:host([theme~="tertiary-inline"]) [part="label"] ::slotted(vaadin-context-menu-item) {
margin: 0;
padding: 0;
}
:host([theme~='tertiary-inline']) [part='label'] ::slotted(vaadin-context-menu-item) {
margin: 0;
padding: 0;
}
:host([expanded]) {
background-color: var(--lumo-primary-color-10pct);
}
:host([expanded]) {
background-color: var(--lumo-primary-color-10pct);
}
:host([expanded][theme~="primary"]) {
background-color: var(--lumo-primary-color-50pct);
}
:host([expanded][theme~='primary']) {
background-color: var(--lumo-primary-color-50pct);
}
:host([disabled][theme~="primary"]) {
color: var(--lumo-disabled-text-color);
background-color: var(--lumo-contrast-5pct);
}
:host([disabled][theme~='primary']) {
color: var(--lumo-disabled-text-color);
background-color: var(--lumo-contrast-5pct);
}
:host([expanded][theme~="tertiary"]),
:host([expanded][theme~="tertiary-inline"]) {
background-color: var(--lumo-primary-color-10pct) !important;
}
:host([expanded][theme~='tertiary']),
:host([expanded][theme~='tertiary-inline']) {
background-color: var(--lumo-primary-color-10pct) !important;
}
:host(:first-of-type) {
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
:host(:first-of-type) {
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
/* Needed to retain the focus-ring with border-radius */
margin-left: calc(var(--lumo-space-xs) / 2);
}
/* Needed to retain the focus-ring with border-radius */
margin-left: calc(var(--lumo-space-xs) / 2);
}
:host(:nth-last-of-type(2)),
:host([part="overflow-button"]) {
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
}
:host(:nth-last-of-type(2)),
:host([part='overflow-button']) {
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
}
:host([theme~="tertiary"]),
:host([theme~="tertiary-inline"]) {
border-radius: var(--lumo-border-radius-m);
}
:host([theme~='tertiary']),
:host([theme~='tertiary-inline']) {
border-radius: var(--lumo-border-radius-m);
}
:host([part="overflow-button"]) {
min-width: var(--lumo-button-size);
padding-left: calc(var(--lumo-button-size) / 4);
padding-right: calc(var(--lumo-button-size) / 4);
}
:host([part='overflow-button']) {
min-width: var(--lumo-button-size);
padding-left: calc(var(--lumo-button-size) / 4);
padding-right: calc(var(--lumo-button-size) / 4);
}
:host([part="overflow-button"]) ::slotted(*) {
font-size: var(--lumo-font-size-xl);
}
:host([part='overflow-button']) ::slotted(*) {
font-size: var(--lumo-font-size-xl);
}
:host([part="overflow-button"]) [part="prefix"],
:host([part="overflow-button"]) [part="suffix"] {
margin-left: 0;
margin-right: 0;
}
:host([part='overflow-button']) [part='prefix'],
:host([part='overflow-button']) [part='suffix'] {
margin-left: 0;
margin-right: 0;
}
/* RTL styles */
:host([dir="rtl"]) {
margin-left: calc(var(--lumo-space-xs) / 2);
margin-right: 0;
border-radius: 0;
}
/* RTL styles */
:host([dir='rtl']) {
margin-left: calc(var(--lumo-space-xs) / 2);
margin-right: 0;
border-radius: 0;
}
:host([dir="rtl"]:first-of-type) {
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
margin-right: calc(var(--lumo-space-xs) / 2);
}
:host([dir='rtl']:first-of-type) {
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
margin-right: calc(var(--lumo-space-xs) / 2);
}
:host([dir="rtl"]:nth-last-of-type(2)),
:host([dir="rtl"][part="overflow-button"]) {
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
:host([dir='rtl']:nth-last-of-type(2)),
:host([dir='rtl'][part='overflow-button']) {
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
}
`,
{ include: ['lumo-button'], moduleId: 'lumo-menu-bar-button' }
);

@@ -0,29 +1,27 @@

import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-lumo-styles/sizing.js';
import '@vaadin/vaadin-lumo-styles/spacing.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
const $_documentContainer = html`<dom-module id="lumo-menu-bar-item" theme-for="vaadin-context-menu-item">
<template>
<style>
:host([theme="menu-bar-item"]) [part="content"] {
display: flex;
/* tweak to inherit centering from menu bar button */
align-items: inherit;
justify-content: inherit;
}
registerStyles(
'vaadin-context-menu-item',
css`
:host([theme='menu-bar-item']) [part='content'] {
display: flex;
/* tweak to inherit centering from menu bar button */
align-items: inherit;
justify-content: inherit;
}
:host([theme="menu-bar-item"]) [part="content"] ::slotted(iron-icon) {
display: inline-block;
width: var(--lumo-icon-size-m);
height: var(--lumo-icon-size-m);
}
:host([theme='menu-bar-item']) [part='content'] ::slotted(iron-icon) {
display: inline-block;
width: var(--lumo-icon-size-m);
height: var(--lumo-icon-size-m);
}
:host([theme="menu-bar-item"]) [part="content"] ::slotted(iron-icon[icon^="vaadin:"]) {
padding: var(--lumo-space-xs);
box-sizing: border-box !important;
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
:host([theme='menu-bar-item']) [part='content'] ::slotted(iron-icon[icon^='vaadin:']) {
padding: var(--lumo-space-xs);
box-sizing: border-box !important;
}
`,
{ moduleId: 'lumo-menu-bar-item' }
);

@@ -1,13 +0,11 @@

import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
const $_documentContainer = html`<dom-module id="lumo-menu-bar-overlay" theme-for="vaadin-context-menu-overlay">
<template>
<style>
:host(:first-of-type) {
padding-top: var(--lumo-space-xs);
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
registerStyles(
'vaadin-context-menu-overlay',
css`
:host(:first-of-type) {
padding-top: var(--lumo-space-xs);
}
`,
{ moduleId: 'lumo-menu-bar-overlay' }
);

@@ -0,112 +1,110 @@

import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-button/theme/material/vaadin-button-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
const $_documentContainer = html`<dom-module id="material-menu-bar-button" theme-for="vaadin-menu-bar-button">
<template>
<style include="material-button">
[part="label"] {
width: 100%;
}
registerStyles(
'vaadin-menu-bar-button',
css`
[part='label'] {
width: 100%;
}
[part="label"] ::slotted(vaadin-context-menu-item) {
line-height: 20px;
margin: -8px;
padding: 8px;
justify-content: center;
}
[part='label'] ::slotted(vaadin-context-menu-item) {
line-height: 20px;
margin: -8px;
padding: 8px;
justify-content: center;
}
:host([theme="outlined"]),
:host([theme="contained"]) {
border-radius: 0;
}
:host([theme='outlined']),
:host([theme='contained']) {
border-radius: 0;
}
:host([theme~="contained"]) ::slotted(vaadin-context-menu-item),
:host([theme~="outlined"]) ::slotted(vaadin-context-menu-item) {
margin: -8px -16px;
padding: 8px 16px;
}
:host([theme~='contained']) ::slotted(vaadin-context-menu-item),
:host([theme~='outlined']) ::slotted(vaadin-context-menu-item) {
margin: -8px -16px;
padding: 8px 16px;
}
:host([expanded])::before {
opacity: 0.08;
transition: opacity 0.4s;
}
:host([expanded])::before {
opacity: 0.08;
transition: opacity 0.4s;
}
:host([expanded])::after {
transform: translate(-50%, -50%) scale(0.0000001); /* animation works weirdly with scale(0) */
opacity: 0.1;
transition: 0s;
}
:host([expanded])::after {
transform: translate(-50%, -50%) scale(0.0000001); /* animation works weirdly with scale(0) */
opacity: 0.1;
transition: 0s;
}
:host([theme="contained"][expanded]) {
box-shadow: var(--material-shadow-elevation-8dp);
}
:host([theme='contained'][expanded]) {
box-shadow: var(--material-shadow-elevation-8dp);
}
:host(:hover:not([expanded]))::after {
transform: translate(-50%, -50%) scale(1);
opacity: 0;
}
:host(:hover:not([expanded]))::after {
transform: translate(-50%, -50%) scale(1);
opacity: 0;
}
:host([theme="contained"]:not([dir="rtl"])) {
margin-right: 1px;
}
:host([theme='contained']:not([dir='rtl'])) {
margin-right: 1px;
}
:host(:first-of-type) {
border-radius: 0.25em 0 0 0.25em;
}
:host(:first-of-type) {
border-radius: 0.25em 0 0 0.25em;
}
:host(:nth-last-of-type(2)),
:host([part~="overflow-button"]) {
border-radius: 0 0.25em 0.25em 0;
}
:host(:nth-last-of-type(2)),
:host([part~='overflow-button']) {
border-radius: 0 0.25em 0.25em 0;
}
:host([part="overflow-button"]) {
padding-right: 8px;
padding-left: 8px;
min-width: 36px;
}
:host([part='overflow-button']) {
padding-right: 8px;
padding-left: 8px;
min-width: 36px;
}
:host([part="overflow-button"]) ::slotted(*) {
font-size: 24px;
}
:host([part='overflow-button']) ::slotted(*) {
font-size: 24px;
}
:host([theme="outlined"]:not([dir="rtl"])) {
margin-right: -1px;
}
:host([theme='outlined']:not([dir='rtl'])) {
margin-right: -1px;
}
:host([theme="outlined"]:not([dir="rtl"]):nth-last-of-type(2)),
:host([theme="outlined"]:not([dir="rtl"])[part~="overflow-button"]) {
margin-right: 0;
}
:host([theme='outlined']:not([dir='rtl']):nth-last-of-type(2)),
:host([theme='outlined']:not([dir='rtl'])[part~='overflow-button']) {
margin-right: 0;
}
:host([theme="text"]),
:host(:not([theme])) {
border-radius: 4px;
}
:host([theme='text']),
:host(:not([theme])) {
border-radius: 4px;
}
/* RTL styles */
:host([dir="rtl"]:first-of-type) {
border-radius: 0 0.25em 0.25em 0;
}
/* RTL styles */
:host([dir='rtl']:first-of-type) {
border-radius: 0 0.25em 0.25em 0;
}
:host([dir="rtl"]:nth-last-of-type(2)),
:host([dir="rtl"][part="overflow-button"]) {
border-radius: 0.25em 0 0 0.25em;
}
:host([dir='rtl']:nth-last-of-type(2)),
:host([dir='rtl'][part='overflow-button']) {
border-radius: 0.25em 0 0 0.25em;
}
:host([dir="rtl"][theme="contained"]) {
margin-left: 1px;
}
:host([dir='rtl'][theme='contained']) {
margin-left: 1px;
}
:host([dir="rtl"][theme="outlined"]) {
margin-left: -1px;
}
:host([dir='rtl'][theme='outlined']) {
margin-left: -1px;
}
:host([theme="outlined"][dir="rtl"]:nth-last-of-type(2)),
:host([theme="outlined"][dir="rtl"][part~="overflow-button"]) {
margin-left: 0;
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
:host([theme='outlined'][dir='rtl']:nth-last-of-type(2)),
:host([theme='outlined'][dir='rtl'][part~='overflow-button']) {
margin-left: 0;
}
`,
{ include: ['material-button'], moduleId: 'material-menu-bar-button' }
);

@@ -0,25 +1,23 @@

import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-material-styles/typography.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
const $_documentContainer = html`<dom-module id="material-menu-bar-item" theme-for="vaadin-context-menu-item">
<template>
<style>
:host([theme="menu-bar-item"]) [part="content"] {
display: flex;
/* tweak to inherit centering from menu bar button */
align-items: inherit;
justify-content: inherit;
font-size: var(--material-button-font-size);
}
registerStyles(
'vaadin-context-menu-item',
css`
:host([theme='menu-bar-item']) [part='content'] {
display: flex;
/* tweak to inherit centering from menu bar button */
align-items: inherit;
justify-content: inherit;
font-size: var(--material-button-font-size);
}
:host([theme="menu-bar-item"]) [part="content"] ::slotted(iron-icon[icon^="vaadin:"]) {
display: inline-block;
width: 18px;
height: 18px;
box-sizing: border-box !important;
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
:host([theme='menu-bar-item']) [part='content'] ::slotted(iron-icon[icon^='vaadin:']) {
display: inline-block;
width: 18px;
height: 18px;
box-sizing: border-box !important;
}
`,
{ moduleId: 'material-menu-bar-item' }
);

@@ -1,13 +0,11 @@

import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
const $_documentContainer = html`<dom-module id="material-menu-bar-overlay" theme-for="vaadin-context-menu-overlay">
<template>
<style>
:host(:first-of-type) {
padding-top: 5px;
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
registerStyles(
'vaadin-context-menu-overlay',
css`
:host(:first-of-type) {
padding-top: 5px;
}
`,
{ moduleId: 'material-menu-bar-overlay' }
);

@@ -1,14 +0,12 @@

import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
const $_documentContainer = html`<dom-module id="material-menu-bar" theme-for="vaadin-menu-bar">
<template>
<style>
[part="container"] {
/* To retain the box-shadow */
padding-bottom: 5px;
}
</style>
</template>
</dom-module>`;
document.head.appendChild($_documentContainer.content);
registerStyles(
'vaadin-menu-bar',
css`
[part='container'] {
/* To retain the box-shadow */
padding-bottom: 5px;
}
`,
{ moduleId: 'material-menu-bar' }
);

@@ -1,15 +0,2 @@

/**
* DO NOT EDIT
*
* This file was automatically generated by
* https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations
*
* To modify these typings, edit the source file(s):
* vaadin-menu-bar.js
*/
// tslint:disable:variable-name Describing an API that's defined elsewhere.
export * from './src/vaadin-menu-bar.js';
export * from './@types/interfaces';
export * from './src/interfaces';
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc