@vaadin/vaadin-menu-bar
Advanced tools
Comparing version 1.2.1 to 2.0.0-alpha1
{ | ||
"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 @@ | ||
[](https://www.npmjs.com/package/@vaadin/vaadin-menu-bar) | ||
[](https://github.com/vaadin/vaadin-menu-bar/releases) | ||
[](https://www.webcomponents.org/element/vaadin/vaadin-menu-bar) | ||
[](https://travis-ci.org/vaadin/vaadin-menu-bar) | ||
[](https://coveralls.io/github/vaadin/vaadin-menu-bar?branch=master) | ||
[](https://gitter.im/vaadin/web-components?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) | ||
[](https://vaadin.com/directory/component/vaadinvaadin-menu-bar) | ||
[](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> | ||
``` | ||
--> | ||
[](https://www.npmjs.com/package/@vaadin/vaadin-menu-bar) | ||
[](https://travis-ci.org/vaadin/vaadin-menu-bar) | ||
[](https://www.webcomponents.org/element/vaadin/vaadin-menu-bar) | ||
[](https://vaadin.com/directory/component/vaadinvaadin-menu-bar) | ||
[](https://vaadin.com/directory/component/vaadinvaadin-menu-bar) | ||
[](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'; |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
58362
27
1224
1
103
+ Added@vaadin/vaadin-context-menu@5.0.0(transitive)
+ Added@vaadin/vaadin-item@3.0.0(transitive)
+ Added@vaadin/vaadin-list-box@2.0.0(transitive)
- Removed@vaadin/vaadin-context-menu@4.6.1(transitive)
- Removed@vaadin/vaadin-item@2.3.0(transitive)
- Removed@vaadin/vaadin-list-box@1.4.0(transitive)