@vaadin/vaadin-text-field
Advanced tools
Comparing version 2.8.2 to 3.0.0-alpha1
{ | ||
"name": "@vaadin/vaadin-text-field", | ||
"version": "3.0.0-alpha1", | ||
"description": "vaadin-text-field", | ||
"main": "vaadin-text-field.js", | ||
"module": "vaadin-text-field.js", | ||
"repository": "vaadin/vaadin-text-field", | ||
"keywords": [ | ||
@@ -10,7 +15,2 @@ "Vaadin", | ||
], | ||
"repository": "vaadin/vaadin-text-field", | ||
"homepage": "https://vaadin.com/components", | ||
"name": "@vaadin/vaadin-text-field", | ||
"version": "2.8.2", | ||
"main": "vaadin-text-field.js", | ||
"author": "Vaadin Ltd", | ||
@@ -21,37 +21,75 @@ "license": "Apache-2.0", | ||
}, | ||
"homepage": "https://vaadin.com/components", | ||
"files": [ | ||
"vaadin-*.d.ts", | ||
"vaadin-*.js", | ||
"@types", | ||
"src", | ||
"theme" | ||
], | ||
"resolutions": { | ||
"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", | ||
"debug": "web-test-runner test/*.test.js --watch", | ||
"dist": "rimraf dist && npm run analyze && rollup -c rollup.config.js && cp analysis.json dist", | ||
"check-version": "magi check-version", | ||
"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", | ||
"@vaadin/vaadin-themable-mixin": "^1.6.1", | ||
"@vaadin/vaadin-themable-mixin": "^1.6.2", | ||
"@vaadin/vaadin-control-state-mixin": "^2.2.1", | ||
"@vaadin/vaadin-lumo-styles": "^1.6.0", | ||
"@vaadin/vaadin-lumo-styles": "^1.6.1", | ||
"@vaadin/vaadin-material-styles": "^1.3.2", | ||
"@vaadin/vaadin-element-mixin": "^2.4.1" | ||
}, | ||
"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-form": "^3.0.0", | ||
"@polymer/iron-test-helpers": "^3.0.0", | ||
"@webcomponents/webcomponentsjs": "^2.0.0", | ||
"wct-browser-legacy": "^1.0.1", | ||
"@vaadin/vaadin-demo-helpers": "^3.0.0", | ||
"@vaadin/vaadin-button": "^2.1.0" | ||
"@rollup/plugin-node-resolve": "^11.0.0", | ||
"@web/dev-server": "0.0.24", | ||
"@web/test-runner": "^0.9.13", | ||
"@web/test-runner-saucelabs": "^0.1.3", | ||
"eslint": "^7.13.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.28.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" | ||
} | ||
} |
111
README.md
@@ -18,18 +18,2 @@ [](https://badge.fury.io/js/%40vaadin%2Fvaadin-text-field) | ||
<!-- | ||
``` | ||
<custom-element-demo> | ||
<template> | ||
<script src="../webcomponentsjs/webcomponents-lite.js"></script> | ||
<link rel="import" href="vaadin-text-field.html"> | ||
<link rel="import" href="vaadin-password-field.html"> | ||
<link rel="import" href="vaadin-text-area.html"> | ||
<link rel="import" href="vaadin-email-field.html"> | ||
<link rel="import" href="vaadin-number-field.html"> | ||
<link rel="import" href="vaadin-integer-field.html"> | ||
<next-code-block></next-code-block> | ||
</template> | ||
</custom-element-demo> | ||
``` | ||
--> | ||
```html | ||
@@ -48,32 +32,5 @@ <vaadin-text-field label="Username"></vaadin-text-field> | ||
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-text-field`: | ||
```sh | ||
bower i vaadin/vaadin-text-field --save | ||
``` | ||
Once installed, import the components you need in your application: | ||
```html | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-text-field.html"> | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-text-area.html"> | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-password-field.html"> | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-email-field.html"> | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-number-field.html"> | ||
<link rel="import" href="bower_components/vaadin-text-field/vaadin-integer-field.html"> | ||
``` | ||
### Polymer 3 and ES Modules Compatible Version | ||
Install `vaadin-text-field`: | ||
```sh | ||
npm i @vaadin/vaadin-text-field --save | ||
@@ -103,47 +60,48 @@ ``` | ||
`theme/lumo/vaadin-text-field.html` | ||
`theme/lumo/vaadin-text-area.html` | ||
`theme/lumo/vaadin-password-field.html` | ||
`theme/lumo/vaadin-email-field.html` | ||
`theme/lumo/vaadin-number-field.html` | ||
`theme/lumo/vaadin-integer-field.html` | ||
`theme/lumo/vaadin-text-field.js` | ||
`theme/lumo/vaadin-text-area.js` | ||
`theme/lumo/vaadin-password-field.js` | ||
`theme/lumo/vaadin-email-field.js` | ||
`theme/lumo/vaadin-number-field.js` | ||
`theme/lumo/vaadin-integer-field.js` | ||
- The components with the Material theme: | ||
`theme/material/vaadin-text-field.html` | ||
`theme/material/vaadin-text-area.html` | ||
`theme/material/vaadin-password-field.html` | ||
`theme/material/vaadin-email-field.html` | ||
`theme/material/vaadin-number-field.html` | ||
`theme/material/vaadin-integer-field.html` | ||
`theme/material/vaadin-text-field.js` | ||
`theme/material/vaadin-text-area.js` | ||
`theme/material/vaadin-password-field.js` | ||
`theme/material/vaadin-email-field.js` | ||
`theme/material/vaadin-number-field.js` | ||
`theme/material/vaadin-integer-field.js` | ||
- Aliases for `theme/lumo/vaadin-text-field.html` | ||
`theme/lumo/vaadin-text-area.html` | ||
`theme/lumo/vaadin-password-field.html` | ||
`theme/lumo/vaadin-email-field.html` | ||
`theme/lumo/vaadin-number-field.html` | ||
`theme/lumo/vaadin-integer-field.html`: | ||
- Aliases for `theme/lumo/vaadin-text-field.js` | ||
`theme/lumo/vaadin-text-area.js` | ||
`theme/lumo/vaadin-password-field.js` | ||
`theme/lumo/vaadin-email-field.js` | ||
`theme/lumo/vaadin-number-field.js` | ||
`theme/lumo/vaadin-integer-field.js`: | ||
`vaadin-text-field.html` | ||
`vaadin-text-area.html` | ||
`vaadin-password-field.html` | ||
`vaadin-email-field.html` | ||
`vaadin-number-field` | ||
`vaadin-integer-field` | ||
`vaadin-text-field.js` | ||
`vaadin-text-area.js` | ||
`vaadin-password-field.js` | ||
`vaadin-email-field.js` | ||
`vaadin-number-field.js` | ||
`vaadin-integer-field.js` | ||
## Running demos and tests in a browser | ||
## Running API docs and tests in a browser | ||
1. Fork the `vaadin-text-field` repository and clone it locally. | ||
1. Make sure you have [npm](https://www.npmjs.com/) and [Bower](https://bower.io) installed. | ||
1. Make sure you have [node.js](https://nodejs.org/) 12.x installed. | ||
1. When in the `vaadin-text-field` directory, run `npm install` and then `bower install` to install dependencies. | ||
1. Make sure you have [npm](https://www.npmjs.com/) installed. | ||
1. When in the `vaadin-text-field` directory, run `npm install` to install dependencies. | ||
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:3000/components/vaadin-text-field/demo | ||
- http://127.0.0.1:3000/components/vaadin-text-field/test | ||
- http://127.0.0.1:3000/test/visual/vaadin-text-field/text-field-1.html | ||
@@ -153,8 +111,11 @@ | ||
1. When in the `vaadin-text-field` directory, run `polymer test` | ||
1. When in the `vaadin-text-field` 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 | ||
We are using [ESLint](http://eslint.org/) for linting JavaScript code. You can check if your code is following our standards by running `npm run lint`, which will automatically lint all `.js` files as well as JavaScript snippets inside `.html` files. | ||
We are using [ESLint](http://eslint.org/) for linting JavaScript code. You can check if your code is following our standards by running `npm run lint`, which will automatically lint all `.js` files. | ||
@@ -161,0 +122,0 @@ |
@@ -1,20 +0,3 @@ | ||
/** | ||
* 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-email-field.js | ||
*/ | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import {TextFieldElement} from './vaadin-text-field.js'; | ||
import {DomModule} from '@polymer/polymer/lib/elements/dom-module.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -33,5 +16,7 @@ * `<vaadin-email-field>` is a Web Component for email field control in forms. | ||
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki) | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class EmailFieldElement extends TextFieldElement { | ||
ready(): void; | ||
_createConstraintsObserver(): void; | ||
@@ -41,8 +26,7 @@ } | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-email-field": EmailFieldElement; | ||
'vaadin-email-field': EmailFieldElement; | ||
} | ||
} | ||
export {EmailFieldElement}; | ||
export { EmailFieldElement }; |
/** | ||
@license | ||
Copyright (c) 2018 Vaadin Ltd. | ||
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import '@polymer/polymer/polymer-element.js'; | ||
import '@polymer/polymer/lib/elements/custom-style.js'; | ||
* @license | ||
* Copyright (c) 2020 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js'; | ||
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="vaadin-email-field-template"> | ||
<template> | ||
<style> | ||
:host([dir="rtl"]) [part="input-field"] { | ||
direction: ltr; | ||
} | ||
registerStyles( | ||
'vaadin-email-field', | ||
css` | ||
:host([dir='rtl']) [part='input-field'] { | ||
direction: ltr; | ||
} | ||
:host([dir="rtl"]) [part="value"]::placeholder { | ||
direction: rtl; | ||
text-align: left; | ||
} | ||
:host([dir='rtl']) [part='value']::placeholder { | ||
direction: rtl; | ||
text-align: left; | ||
} | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input)::placeholder { | ||
direction: rtl; | ||
text-align: left; | ||
} | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder { | ||
direction: rtl; | ||
text-align: left; | ||
} | ||
`, | ||
{ moduleId: 'vaadin-email-field-styles' } | ||
); | ||
:host([dir="rtl"]) [part="value"]:-ms-input-placeholder, | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input):-ms-input-placeholder { | ||
direction: rtl; | ||
text-align: left; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
let memoizedTemplate; | ||
/** | ||
@@ -57,4 +43,6 @@ * `<vaadin-email-field>` is a Web Component for email field control in forms. | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends TextFieldElement | ||
* @demo demo/index.html | ||
*/ | ||
@@ -67,21 +55,5 @@ class EmailFieldElement extends TextFieldElement { | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
static get template() { | ||
if (!memoizedTemplate) { | ||
// Clone the superclass template | ||
memoizedTemplate = super.template.cloneNode(true); | ||
// Retrieve this element's dom-module template | ||
const thisTemplate = DomModule.import(this.is + '-template', 'template'); | ||
const styles = thisTemplate.content.querySelector('style'); | ||
// Add the and styles to the text-field template | ||
memoizedTemplate.content.appendChild(styles); | ||
} | ||
return memoizedTemplate; | ||
} | ||
/** @protected */ | ||
@@ -88,0 +60,0 @@ ready() { |
@@ -1,18 +0,3 @@ | ||
/** | ||
* 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-integer-field.js | ||
*/ | ||
import { NumberFieldElement } from './vaadin-number-field.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import {NumberFieldElement} from './vaadin-number-field.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -25,16 +10,18 @@ * `<vaadin-integer-field>` is a Web Component for integer field control in forms. | ||
* ``` | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class IntegerFieldElement extends NumberFieldElement { | ||
ready(): void; | ||
_valueChanged(newVal: unknown|null, oldVal: unknown|null): void; | ||
_stepChanged(newVal: number, oldVal: number|undefined): void; | ||
_valueChanged(newVal: unknown | null, oldVal: unknown | null): void; | ||
_stepChanged(newVal: number, oldVal: number | undefined): void; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-integer-field": IntegerFieldElement; | ||
'vaadin-integer-field': IntegerFieldElement; | ||
} | ||
} | ||
export {IntegerFieldElement}; | ||
export { IntegerFieldElement }; |
/** | ||
@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/polymer-element.js'; | ||
import '@polymer/polymer/lib/elements/custom-style.js'; | ||
* @license | ||
* Copyright (c) 2020 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { NumberFieldElement } from './vaadin-number-field.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="vaadin-integer-field-template"> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
/** | ||
@@ -26,4 +15,7 @@ * `<vaadin-integer-field>` is a Web Component for integer field control in forms. | ||
* ``` | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends NumberFieldElement | ||
* @demo demo/index.html | ||
*/ | ||
@@ -36,3 +28,3 @@ class IntegerFieldElement extends NumberFieldElement { | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
@@ -70,4 +62,3 @@ | ||
if (newVal !== '' && !this.__isInteger(newVal)) { | ||
console.warn(`Trying to set non-integer value "${newVal}" to <vaadin-integer-field>.` | ||
+ ` Clearing the value.`); | ||
console.warn(`Trying to set non-integer value "${newVal}" to <vaadin-integer-field>.` + ` Clearing the value.`); | ||
this.value = ''; | ||
@@ -86,5 +77,7 @@ return; | ||
if (!this.__hasOnlyDigits(newVal)) { | ||
console.warn(`Trying to set invalid step size "${newVal}",` | ||
+ ` which is not a positive integer, to <vaadin-integer-field>.` | ||
+ ` Resetting the default value 1.`); | ||
console.warn( | ||
`Trying to set invalid step size "${newVal}",` + | ||
` which is not a positive integer, to <vaadin-integer-field>.` + | ||
` Resetting the default value 1.` | ||
); | ||
this.step = 1; | ||
@@ -91,0 +84,0 @@ return; |
@@ -1,20 +0,3 @@ | ||
/** | ||
* 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-number-field.js | ||
*/ | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import {TextFieldElement} from './vaadin-text-field.js'; | ||
import {DomModule} from '@polymer/polymer/lib/elements/dom-module.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -27,5 +10,7 @@ * `<vaadin-number-field>` is a Web Component for number field control in forms. | ||
* ``` | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class NumberFieldElement extends TextFieldElement { | ||
/** | ||
@@ -40,3 +25,3 @@ * Set to true to display value increase/decrease controls. | ||
*/ | ||
min: number|null|undefined; | ||
min: number | null | undefined; | ||
@@ -46,3 +31,3 @@ /** | ||
*/ | ||
max: number|null|undefined; | ||
max: number | null | undefined; | ||
@@ -53,17 +38,20 @@ /** | ||
step: number; | ||
ready(): void; | ||
_createConstraintsObserver(): void; | ||
_valueChanged(newVal: unknown|null, oldVal: unknown|null): void; | ||
_valueChanged(newVal: unknown | null, oldVal: unknown | null): void; | ||
checkValidity(): boolean; | ||
_onKeyDown(e: KeyboardEvent): void; | ||
_stepChanged(newVal: number, oldVal: number|undefined): void; | ||
_stepChanged(newVal: number, oldVal: number | undefined): void; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-number-field": NumberFieldElement; | ||
'vaadin-number-field': NumberFieldElement; | ||
} | ||
} | ||
export {NumberFieldElement}; | ||
export { NumberFieldElement }; |
/** | ||
@license | ||
Copyright (c) 2017 Vaadin Ltd. | ||
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import '@polymer/polymer/polymer-element.js'; | ||
import '@polymer/polymer/lib/elements/custom-style.js'; | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
* @license | ||
* Copyright (c) 2020 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
@@ -16,16 +13,16 @@ const $_documentContainer = html`<dom-module id="vaadin-number-field-template"> | ||
<style> | ||
:host([readonly]) [part\$="button"] { | ||
:host([readonly]) [part$='button'] { | ||
pointer-events: none; | ||
} | ||
[part="decrease-button"]::before { | ||
content: "−"; | ||
[part='decrease-button']::before { | ||
content: '−'; | ||
} | ||
[part="increase-button"]::before { | ||
content: "+"; | ||
[part='increase-button']::before { | ||
content: '+'; | ||
} | ||
[part="decrease-button"], | ||
[part="increase-button"] { | ||
[part='decrease-button'], | ||
[part='increase-button'] { | ||
-webkit-user-select: none; | ||
@@ -38,4 +35,4 @@ -moz-user-select: none; | ||
/* Hide the native arrow icons */ | ||
[part="value"]::-webkit-outer-spin-button, | ||
[part="value"]::-webkit-inner-spin-button { | ||
[part='value']::-webkit-outer-spin-button, | ||
[part='value']::-webkit-inner-spin-button { | ||
-webkit-appearance: none; | ||
@@ -45,3 +42,3 @@ margin: 0; | ||
[part="value"] { | ||
[part='value'] { | ||
/* Older Firefox versions (v47.0) requires !important */ | ||
@@ -51,41 +48,39 @@ -moz-appearance: textfield !important; | ||
:host([dir="rtl"]) [part="input-field"] { | ||
:host([dir='rtl']) [part='input-field'] { | ||
direction: ltr; | ||
} | ||
:host([dir="rtl"]) [part="value"]::placeholder { | ||
:host([dir='rtl']) [part='value']::placeholder { | ||
direction: rtl; | ||
} | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input)::placeholder { | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder { | ||
direction: rtl; | ||
} | ||
:host([dir="rtl"]) [part="value"]:-ms-input-placeholder, | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input):-ms-input-placeholder { | ||
direction: rtl; | ||
} | ||
:host([dir="rtl"]:not([has-controls])) [part="value"]::placeholder { | ||
:host([dir='rtl']:not([has-controls])) [part='value']::placeholder { | ||
text-align: left; | ||
} | ||
:host([dir="rtl"]:not([has-controls])) [part="input-field"] ::slotted(input)::placeholder { | ||
:host([dir='rtl']:not([has-controls])) [part='input-field'] ::slotted(input)::placeholder { | ||
text-align: left; | ||
} | ||
:host([dir="rtl"]:not([has-controls])) [part="value"]:-ms-input-placeholder, | ||
:host([dir="rtl"]:not([has-controls])) [part="input-field"] ::slotted(input):-ms-input-placeholder { | ||
text-align: left; | ||
} | ||
</style> | ||
<div disabled\$="[[!_allowed(-1, value, min, max, step)]]" part="decrease-button" on-click="_decreaseValue" on-touchend="_decreaseButtonTouchend" hidden\$="[[!hasControls]]"> | ||
</div> | ||
<div | ||
disabled$="[[!_allowed(-1, value, min, max, step)]]" | ||
part="decrease-button" | ||
on-click="_decreaseValue" | ||
on-touchend="_decreaseButtonTouchend" | ||
hidden$="[[!hasControls]]" | ||
></div> | ||
<div disabled\$="[[!_allowed(1, value, min, max, step)]]" part="increase-button" on-click="_increaseValue" on-touchend="_increaseButtonTouchend" hidden\$="[[!hasControls]]"> | ||
</div> | ||
<div | ||
disabled$="[[!_allowed(1, value, min, max, step)]]" | ||
part="increase-button" | ||
on-click="_increaseValue" | ||
on-touchend="_increaseButtonTouchend" | ||
hidden$="[[!hasControls]]" | ||
></div> | ||
</template> | ||
</dom-module>`; | ||
@@ -103,4 +98,7 @@ | ||
* ``` | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends TextFieldElement | ||
* @demo demo/index.html | ||
*/ | ||
@@ -113,3 +111,3 @@ class NumberFieldElement extends TextFieldElement { | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
@@ -157,3 +155,2 @@ | ||
} | ||
}; | ||
@@ -213,3 +210,3 @@ } | ||
/** @private */ | ||
_constraintsChanged(required, minlength, maxlength, pattern, min, max, step) { | ||
_constraintsChanged(required, minlength, maxlength, pattern, min, max) { | ||
if (!this.invalid) { | ||
@@ -219,3 +216,3 @@ return; | ||
const isNumUnset = n => (!n && n !== 0); | ||
const isNumUnset = (n) => !n && n !== 0; | ||
@@ -248,9 +245,6 @@ if (!isNumUnset(min) || !isNumUnset(max)) { | ||
if (!this.value) { | ||
if (this.min == 0 && incr < 0 || | ||
this.max == 0 && incr > 0 || | ||
this.max == 0 && this.min == 0) { | ||
if ((this.min == 0 && incr < 0) || (this.max == 0 && incr > 0) || (this.max == 0 && this.min == 0)) { | ||
incr = 0; | ||
value = 0; | ||
} else if ((this.max == null || this.max >= 0) && | ||
(this.min == null || this.min <= 0)) { | ||
} else if ((this.max == null || this.max >= 0) && (this.min == null || this.min <= 0)) { | ||
value = 0; | ||
@@ -293,3 +287,3 @@ } else if (this.min > 0) { | ||
this.value = this.inputElement.value = String(parseFloat(value)); | ||
this.dispatchEvent(new CustomEvent('change', {bubbles: true})); | ||
this.dispatchEvent(new CustomEvent('change', { bubbles: true })); | ||
} | ||
@@ -303,5 +297,3 @@ | ||
// To avoid problems with decimal math, multiplying to operate with integers. | ||
const multiplier = Math.max(this._getMultiplier(currentValue), | ||
this._getMultiplier(step), | ||
this._getMultiplier(min)); | ||
const multiplier = Math.max(this._getMultiplier(currentValue), this._getMultiplier(step), this._getMultiplier(min)); | ||
@@ -360,3 +352,3 @@ step *= multiplier; | ||
*/ | ||
_stepChanged(newVal, oldVal) { | ||
_stepChanged(newVal) { | ||
// Avoid using initial value in validation | ||
@@ -363,0 +355,0 @@ this.__validateByStep = this.__stepChangedCalled || this.getAttribute('step') !== null; |
@@ -1,20 +0,3 @@ | ||
/** | ||
* 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-password-field.js | ||
*/ | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import {TextFieldElement} from './vaadin-text-field.js'; | ||
import {DomModule} from '@polymer/polymer/lib/elements/dom-module.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -45,5 +28,7 @@ * `<vaadin-password-field>` is a Web Component for password field control in forms. | ||
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki) | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class PasswordFieldElement extends TextFieldElement { | ||
/** | ||
@@ -60,3 +45,3 @@ * Set to true to hide the eye icon which toggles the password visibility. | ||
readonly passwordVisible: boolean; | ||
ready(): void; | ||
_onChange(e: Event): void; | ||
@@ -66,8 +51,7 @@ } | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-password-field": PasswordFieldElement; | ||
'vaadin-password-field': PasswordFieldElement; | ||
} | ||
} | ||
export {PasswordFieldElement}; | ||
export { PasswordFieldElement }; |
/** | ||
@license | ||
Copyright (c) 2017 Vaadin Ltd. | ||
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import '@polymer/polymer/polymer-element.js'; | ||
import '@polymer/polymer/lib/elements/custom-style.js'; | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
* @license | ||
* Copyright (c) 2020 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
import { TextFieldElement } from './vaadin-text-field.js'; | ||
const $_documentContainer = html`<custom-style> | ||
<style> | ||
const $_documentContainer = html` <style> | ||
@font-face { | ||
font-family: 'vaadin-password-field-icons'; | ||
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAYMAAsAAAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIFgGNtYXAAAAFoAAAAVAAAAFQXVtKIZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAAAfwAAAH8yBLEP2hlYWQAAAPAAAAANgAAADYN+RfTaGhlYQAAA/gAAAAkAAAAJAfCA8dobXR4AAAEHAAAABgAAAAYDgAAAGxvY2EAAAQ0AAAADgAAAA4BJgCSbWF4cAAABEQAAAAgAAAAIAAMAFpuYW1lAAAEZAAAAYYAAAGGmUoJ+3Bvc3QAAAXsAAAAIAAAACAAAwAAAAMDVQGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QEDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkB//3//wAAAAAAIOkA//3//wAB/+MXBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAAAHoEAALGABQAJABFAAABIg4CMTAeAjMyPgIxMC4CIwc+ATEwBhUUFjEHMCY1NDYTIi4CJz4BNw4BFRQeAjMyPgI1NCYnHgEXDgMjAgChyHAnN3rAiYjFfjsncMihrRg7IA1GExmnY5ZqQg8PWGAFCChGXTU1XUYoCAVgWA8RRW2ZZALGZnpmUmJSUGBQaHxoYA8FRSIhJQ0rIiYz/lQvQkYVInswEygYNV1GKChGXTUYKBMrgCIVRkIvAAAABQAA/8AEAAPAABoAJgA6AEcAVwAAAQceARcOAyMiJicHHgEzMj4CMTAuAicHNCYnATIWMzI+AhMBLgEjIg4CMTAeAhcHFTMBNQEuASc+ATcOARUUFhc3BzAmNTQ2MT4BMTAGFQYWAzo0UlMPEUVtmWQiNR0zJ1QsiMV+OxEsTTw6AgT+zA8dDjVdRijT/ucnXjWhyHAnGTNQN9MtA9P9AE1ZFA9YYAUILSY6QBMZGDsgBAsCczMrcyIWQ0AtCAQzDgtQYFAzS1ckeQ4bCv7TBihGXQH7/uYKEGZ6Zic5RBzNLQPTLf0tIVoYInswEygYNWMihgwrISc5DwVHJiIlAAEAAAAAAADkyo21Xw889QALBAAAAAAA1W1pqwAAAADVbWmrAAD/wAQAA8AAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAABAAAAQAAAAAAAAAAAAAAAAAAAAYEAAAAAAAAAAAAAAACAAAABAAAAAQAAAAAAAAAAAoAFAAeAH4A/gAAAAEAAAAGAFgABQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAHAAAAAQAAAAAAAgAHAGAAAQAAAAAAAwAHADYAAQAAAAAABAAHAHUAAQAAAAAABQALABUAAQAAAAAABgAHAEsAAQAAAAAACgAaAIoAAwABBAkAAQAOAAcAAwABBAkAAgAOAGcAAwABBAkAAwAOAD0AAwABBAkABAAOAHwAAwABBAkABQAWACAAAwABBAkABgAOAFIAAwABBAkACgA0AKRpY29tb29uAGkAYwBvAG0AbwBvAG5WZXJzaW9uIDEuMABWAGUAcgBzAGkAbwBuACAAMQAuADBpY29tb29uAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG5SZWd1bGFyAFIAZQBnAHUAbABhAHJpY29tb29uAGkAYwBvAG0AbwBvAG5Gb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('woff'); | ||
src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAYMAAsAAAAABcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIFgGNtYXAAAAFoAAAAVAAAAFQXVtKIZ2FzcAAAAbwAAAAIAAAACAAAABBnbHlmAAABxAAAAfwAAAH8yBLEP2hlYWQAAAPAAAAANgAAADYN+RfTaGhlYQAAA/gAAAAkAAAAJAfCA8dobXR4AAAEHAAAABgAAAAYDgAAAGxvY2EAAAQ0AAAADgAAAA4BJgCSbWF4cAAABEQAAAAgAAAAIAAMAFpuYW1lAAAEZAAAAYYAAAGGmUoJ+3Bvc3QAAAXsAAAAIAAAACAAAwAAAAMDVQGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA6QEDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADgAAAAKAAgAAgACAAEAIOkB//3//wAAAAAAIOkA//3//wAB/+MXBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAAAHoEAALGABQAJABFAAABIg4CMTAeAjMyPgIxMC4CIwc+ATEwBhUUFjEHMCY1NDYTIi4CJz4BNw4BFRQeAjMyPgI1NCYnHgEXDgMjAgChyHAnN3rAiYjFfjsncMihrRg7IA1GExmnY5ZqQg8PWGAFCChGXTU1XUYoCAVgWA8RRW2ZZALGZnpmUmJSUGBQaHxoYA8FRSIhJQ0rIiYz/lQvQkYVInswEygYNV1GKChGXTUYKBMrgCIVRkIvAAAABQAA/8AEAAPAABoAJgA6AEcAVwAAAQceARcOAyMiJicHHgEzMj4CMTAuAicHNCYnATIWMzI+AhMBLgEjIg4CMTAeAhcHFTMBNQEuASc+ATcOARUUFhc3BzAmNTQ2MT4BMTAGFQYWAzo0UlMPEUVtmWQiNR0zJ1QsiMV+OxEsTTw6AgT+zA8dDjVdRijT/ucnXjWhyHAnGTNQN9MtA9P9AE1ZFA9YYAUILSY6QBMZGDsgBAsCczMrcyIWQ0AtCAQzDgtQYFAzS1ckeQ4bCv7TBihGXQH7/uYKEGZ6Zic5RBzNLQPTLf0tIVoYInswEygYNWMihgwrISc5DwVHJiIlAAEAAAAAAADkyo21Xw889QALBAAAAAAA1W1pqwAAAADVbWmrAAD/wAQAA8AAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAABAAAAQAAAAAAAAAAAAAAAAAAAAYEAAAAAAAAAAAAAAACAAAABAAAAAQAAAAAAAAAAAoAFAAeAH4A/gAAAAEAAAAGAFgABQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAHAAAAAQAAAAAAAgAHAGAAAQAAAAAAAwAHADYAAQAAAAAABAAHAHUAAQAAAAAABQALABUAAQAAAAAABgAHAEsAAQAAAAAACgAaAIoAAwABBAkAAQAOAAcAAwABBAkAAgAOAGcAAwABBAkAAwAOAD0AAwABBAkABAAOAHwAAwABBAkABQAWACAAAwABBAkABgAOAFIAAwABBAkACgA0AKRpY29tb29uAGkAYwBvAG0AbwBvAG5WZXJzaW9uIDEuMABWAGUAcgBzAGkAbwBuACAAMQAuADBpY29tb29uAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG5SZWd1bGFyAFIAZQBnAHUAbABhAHJpY29tb29uAGkAYwBvAG0AbwBvAG5Gb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) | ||
format('woff'); | ||
font-weight: normal; | ||
@@ -22,21 +19,20 @@ font-style: normal; | ||
</style> | ||
</custom-style><dom-module id="vaadin-password-field-template"> | ||
<template> | ||
<style> | ||
/* Hide the native eye icon for IE/Edge */ | ||
::-ms-reveal { | ||
display: none; | ||
} | ||
<dom-module id="vaadin-password-field-template"> | ||
<template> | ||
<style> | ||
[part='reveal-button'][hidden] { | ||
display: none !important; | ||
} | ||
</style> | ||
[part="reveal-button"][hidden] { | ||
display: none !important; | ||
} | ||
</style> | ||
<div | ||
part="reveal-button" | ||
on-mousedown="_revealButtonMouseDown" | ||
on-touchend="_togglePasswordVisibilityTouchend" | ||
on-click="_togglePasswordVisibility" | ||
hidden$="[[revealButtonHidden]]" | ||
></div> | ||
</template> | ||
</dom-module>`; | ||
<div part="reveal-button" on-mousedown="_revealButtonMouseDown" on-touchend="_togglePasswordVisibilityTouchend" on-click="_togglePasswordVisibility" hidden\$="[[revealButtonHidden]]"> | ||
</div> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
@@ -71,4 +67,6 @@ let memoizedTemplate; | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends TextFieldElement | ||
* @demo demo/index.html | ||
*/ | ||
@@ -81,3 +79,3 @@ class PasswordFieldElement extends TextFieldElement { | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
@@ -84,0 +82,0 @@ |
@@ -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-text-area.js | ||
*/ | ||
import { TextFieldMixin } from './vaadin-text-field-mixin.js'; | ||
import { ControlStateMixin } from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import {PolymerElement} from '@polymer/polymer/polymer-element.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import {TextFieldMixin} from './vaadin-text-field-mixin.js'; | ||
import { TextFieldEventMap } from './interfaces'; | ||
import {ControlStateMixin} from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
import {ThemableMixin} from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import {ElementMixin} from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -74,20 +59,30 @@ * `<vaadin-text-area>` is a Web Component for text area control in forms. | ||
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki) | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class TextAreaElement extends | ||
TextFieldMixin( | ||
ControlStateMixin( | ||
ElementMixin( | ||
ThemableMixin( | ||
PolymerElement)))) { | ||
declare class TextAreaElement extends TextFieldMixin(ControlStateMixin(ElementMixin(ThemableMixin(HTMLElement)))) { | ||
readonly _slottedTagName: string; | ||
ready(): void; | ||
_valueChanged(newVal: unknown | null, oldVal: unknown | null): void; | ||
addEventListener<K extends keyof TextFieldEventMap>( | ||
type: K, | ||
listener: (this: TextAreaElement, ev: TextFieldEventMap[K]) => void, | ||
options?: boolean | AddEventListenerOptions | ||
): void; | ||
removeEventListener<K extends keyof TextFieldEventMap>( | ||
type: K, | ||
listener: (this: TextAreaElement, ev: TextFieldEventMap[K]) => void, | ||
options?: boolean | EventListenerOptions | ||
): void; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-text-area": TextAreaElement; | ||
'vaadin-text-area': TextAreaElement; | ||
} | ||
} | ||
export {TextAreaElement}; | ||
export { TextAreaElement }; |
/** | ||
@license | ||
Copyright (c) 2017 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 { TextFieldMixin } from './vaadin-text-field-mixin.js'; | ||
@@ -12,3 +11,3 @@ import { ControlStateMixin } from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -63,3 +62,6 @@ * `<vaadin-text-area>` is a Web Component for text area control in forms. | ||
* | ||
* @extends PolymerElement | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends HTMLElement | ||
* @mixes TextFieldMixin | ||
@@ -69,75 +71,70 @@ * @mixes ControlStateMixin | ||
* @mixes ThemableMixin | ||
* @demo demo/index.html | ||
*/ | ||
class TextAreaElement extends | ||
ElementMixin( | ||
TextFieldMixin( | ||
ControlStateMixin( | ||
ThemableMixin(PolymerElement)))) { | ||
class TextAreaElement extends ElementMixin(TextFieldMixin(ControlStateMixin(ThemableMixin(PolymerElement)))) { | ||
static get template() { | ||
return html` | ||
<style include="vaadin-text-field-shared-styles"> | ||
.vaadin-text-area-container { | ||
flex: auto; | ||
max-height: inherit; /* MSIE 11 */ | ||
min-height: inherit; /* MSIE 11 */ | ||
} | ||
<style include="vaadin-text-field-shared-styles"> | ||
.vaadin-text-area-container { | ||
flex: auto; | ||
} | ||
/* The label, helper text and the error message should neither grow nor shrink. */ | ||
[part="label"], | ||
[part="helper-text"], | ||
[part="error-message"] { | ||
flex: none; | ||
} | ||
/* The label, helper text and the error message should neither grow nor shrink. */ | ||
[part='label'], | ||
[part='helper-text'], | ||
[part='error-message'] { | ||
flex: none; | ||
} | ||
[part="input-field"] { | ||
overflow: auto; | ||
-webkit-overflow-scrolling: touch; | ||
} | ||
[part='input-field'] { | ||
overflow: auto; | ||
-webkit-overflow-scrolling: touch; | ||
} | ||
[part="value"] { | ||
resize: none; | ||
} | ||
[part='value'] { | ||
resize: none; | ||
} | ||
[part="value"], | ||
[part="input-field"] ::slotted(*) { | ||
align-self: flex-start; | ||
} | ||
[part='value'], | ||
[part='input-field'] ::slotted(*) { | ||
align-self: flex-start; | ||
} | ||
@keyframes vaadin-text-area-appear { | ||
to { | ||
opacity: 1; | ||
@keyframes vaadin-text-area-appear { | ||
to { | ||
opacity: 1; | ||
} | ||
} | ||
} | ||
:host { | ||
animation: 1ms vaadin-text-area-appear; | ||
} | ||
</style> | ||
:host { | ||
animation: 1ms vaadin-text-area-appear; | ||
} | ||
</style> | ||
<div class="vaadin-text-area-container"> | ||
<div class="vaadin-text-area-container"> | ||
<label part="label" on-click="focus" id="[[_labelId]]">[[label]]</label> | ||
<label part="label" on-click="focus" id="[[_labelId]]">[[label]]</label> | ||
<div part="input-field" id="[[_inputId]]"> | ||
<slot name="prefix"></slot> | ||
<div part="input-field" id="[[_inputId]]"> | ||
<slot name="textarea"> | ||
<textarea part="value"></textarea> | ||
</slot> | ||
<slot name="prefix"></slot> | ||
<div part="clear-button" id="clearButton" role="button" aria-label$="[[i18n.clear]]"></div> | ||
<slot name="suffix"></slot> | ||
</div> | ||
<slot name="textarea"> | ||
<textarea part="value"></textarea> | ||
</slot> | ||
<div part="helper-text" on-click="focus" id="[[_helperTextId]]"> | ||
<slot name="helper">[[helperText]]</slot> | ||
</div> | ||
<div part="clear-button" id="clearButton" role="button" aria-label\$="[[i18n.clear]]"></div> | ||
<slot name="suffix"></slot> | ||
<div | ||
part="error-message" | ||
id="[[_errorId]]" | ||
aria-live="assertive" | ||
aria-hidden$="[[_getErrorMessageAriaHidden(invalid, errorMessage, _errorId)]]" | ||
>[[errorMessage]]</div | ||
> | ||
</div> | ||
<div part="helper-text" on-click="focus" id="[[_helperTextId]]"> | ||
<slot name="helper">[[helperText]]</slot> | ||
</div> | ||
<div part="error-message" id="[[_errorId]]" aria-live="assertive" aria-hidden\$="[[_getErrorMessageAriaHidden(invalid, errorMessage, _errorId)]]">[[errorMessage]]</div> | ||
</div> | ||
`; | ||
`; | ||
} | ||
@@ -150,11 +147,5 @@ | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
static get observers() { | ||
return [ | ||
'_textAreaValueChanged(value)' | ||
]; | ||
} | ||
/** @protected */ | ||
@@ -182,4 +173,10 @@ ready() { | ||
/** @private */ | ||
_textAreaValueChanged(value) { | ||
/** | ||
* @param {unknown} newVal | ||
* @param {unknown} oldVal | ||
* @protected | ||
*/ | ||
_valueChanged(newVal, oldVal) { | ||
super._valueChanged(newVal, oldVal); | ||
this._updateHeight(); | ||
@@ -186,0 +183,0 @@ } |
@@ -1,34 +0,14 @@ | ||
/** | ||
* 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-text-field-mixin.js | ||
*/ | ||
import { TextFieldAutoCorrect, TextFieldAutoCapitalize } from './interfaces'; | ||
// 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 {timeOut, animationFrame} from '@polymer/polymer/lib/utils/async.js'; | ||
import {Debouncer} from '@polymer/polymer/lib/utils/debounce.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
export {TextFieldMixin}; | ||
declare function TextFieldMixin<T extends new (...args: any[]) => {}>(base: T): T & TextFieldMixinConstructor; | ||
interface TextFieldMixinConstructor { | ||
new(...args: any[]): TextFieldMixin; | ||
new (...args: any[]): TextFieldMixin; | ||
} | ||
export {TextFieldMixinConstructor}; | ||
interface TextFieldMixin { | ||
readonly focusElement: HTMLElement | null | undefined; | ||
interface TextFieldMixin { | ||
readonly focusElement: HTMLElement|null|undefined; | ||
readonly inputElement: HTMLElement|null|undefined; | ||
readonly inputElement: HTMLElement | null | undefined; | ||
readonly _slottedTagName: string; | ||
@@ -41,3 +21,3 @@ | ||
*/ | ||
autocomplete: string|null|undefined; | ||
autocomplete: string | null | undefined; | ||
@@ -51,3 +31,3 @@ /** | ||
*/ | ||
autocorrect: TextFieldAutoCorrect|undefined; | ||
autocorrect: TextFieldAutoCorrect | undefined; | ||
@@ -63,3 +43,3 @@ /** | ||
*/ | ||
autocapitalize: TextFieldAutoCapitalize|undefined; | ||
autocapitalize: TextFieldAutoCapitalize | undefined; | ||
@@ -94,3 +74,3 @@ /** | ||
*/ | ||
i18n: {clear: string}; | ||
i18n: { clear: string }; | ||
@@ -106,3 +86,3 @@ /** | ||
*/ | ||
helperText: string|null; | ||
helperText: string | null; | ||
@@ -112,3 +92,3 @@ /** | ||
*/ | ||
maxlength: number|null|undefined; | ||
maxlength: number | null | undefined; | ||
@@ -118,3 +98,3 @@ /** | ||
*/ | ||
minlength: number|null|undefined; | ||
minlength: number | null | undefined; | ||
@@ -124,3 +104,3 @@ /** | ||
*/ | ||
name: string|null|undefined; | ||
name: string | null | undefined; | ||
@@ -130,3 +110,3 @@ /** | ||
*/ | ||
placeholder: string|null|undefined; | ||
placeholder: string | null | undefined; | ||
@@ -136,3 +116,3 @@ /** | ||
*/ | ||
readonly: boolean|null|undefined; | ||
readonly: boolean | null | undefined; | ||
@@ -142,3 +122,3 @@ /** | ||
*/ | ||
required: boolean|null|undefined; | ||
required: boolean | null | undefined; | ||
@@ -157,8 +137,2 @@ /** | ||
/** | ||
* Specifies that the text field has value. | ||
* @attr {boolean} has-value | ||
*/ | ||
hasValue: boolean|null|undefined; | ||
/** | ||
* When set to true, user is prevented from typing a value that | ||
@@ -168,3 +142,3 @@ * conflicts with the given `pattern`. | ||
*/ | ||
preventInvalidInput: boolean|null|undefined; | ||
preventInvalidInput: boolean | null | undefined; | ||
@@ -181,8 +155,17 @@ /** | ||
*/ | ||
_enabledCharPattern: string|null|undefined; | ||
_enabledCharPattern: string | null | undefined; | ||
_createConstraintsObserver(): void; | ||
_onChange(e: Event): void; | ||
_valueChanged(newVal: unknown|null, oldVal: unknown|null): void; | ||
_constraintsChanged(required: boolean|undefined, minlength: number|undefined, maxlength: string|undefined, pattern: any): void; | ||
_valueChanged(newVal: unknown | null, oldVal: unknown | null): void; | ||
_constraintsChanged( | ||
required: boolean | undefined, | ||
minlength: number | undefined, | ||
maxlength: string | undefined, | ||
pattern: any | ||
): void; | ||
/** | ||
@@ -192,7 +175,5 @@ * Returns true if the current input value satisfies all constraints (if any) | ||
checkValidity(): boolean; | ||
ready(): void; | ||
/** | ||
* Returns true if `value` is valid. | ||
* `<iron-form>` uses this to check the validity for all its elements. | ||
* | ||
@@ -202,9 +183,8 @@ * @returns True if the value is valid. | ||
validate(): boolean; | ||
clear(): void; | ||
_onKeyDown(e: KeyboardEvent): void; | ||
attributeChangedCallback(prop: string, oldVal: string, newVal: string): void; | ||
} | ||
import {TextFieldAutoCorrect} from '../@types/interfaces'; | ||
import {TextFieldAutoCapitalize} from '../@types/interfaces'; | ||
export { TextFieldMixin, TextFieldMixinConstructor }; |
/** | ||
@license | ||
Copyright (c) 2017 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 { Debouncer } from '@polymer/polymer/lib/utils/debounce.js'; | ||
import { timeOut, animationFrame } from '@polymer/polymer/lib/utils/async.js'; | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
registerStyles( | ||
'', | ||
css` | ||
:host { | ||
display: inline-flex; | ||
outline: none; | ||
} | ||
const $_documentContainer = html`<dom-module id="vaadin-text-field-shared-styles"> | ||
<template> | ||
<style> | ||
:host { | ||
display: inline-flex; | ||
outline: none; | ||
} | ||
:host::before { | ||
content: '\\2003'; | ||
width: 0; | ||
display: inline-block; | ||
/* Size and position this element on the same vertical position as the input-field element | ||
to make vertical align for the host element work as expected */ | ||
} | ||
:host::before { | ||
content: "\\2003"; | ||
width: 0; | ||
display: inline-block; | ||
/* Size and position this element on the same vertical position as the input-field element | ||
to make vertical align for the host element work as expected */ | ||
} | ||
:host([hidden]) { | ||
display: none !important; | ||
} | ||
:host([hidden]) { | ||
display: none !important; | ||
} | ||
.vaadin-text-field-container, | ||
.vaadin-text-area-container { | ||
display: flex; | ||
flex-direction: column; | ||
min-width: 100%; | ||
max-width: 100%; | ||
width: var(--vaadin-text-field-default-width, 12em); | ||
} | ||
.vaadin-text-field-container, | ||
.vaadin-text-area-container { | ||
display: flex; | ||
flex-direction: column; | ||
min-width: 100%; | ||
max-width: 100%; | ||
width: var(--vaadin-text-field-default-width, 12em); | ||
} | ||
[part='label']:empty { | ||
display: none; | ||
} | ||
[part="label"]:empty { | ||
display: none; | ||
} | ||
[part='input-field'] { | ||
display: flex; | ||
align-items: center; | ||
flex: auto; | ||
} | ||
[part="input-field"] { | ||
display: flex; | ||
align-items: center; | ||
flex: auto; | ||
} | ||
.vaadin-text-field-container [part='input-field'] { | ||
flex-grow: 0; | ||
} | ||
.vaadin-text-field-container [part="input-field"] { | ||
flex-grow: 0; | ||
} | ||
/* Reset the native input styles */ | ||
[part='value'], | ||
[part='input-field'] ::slotted(input), | ||
[part='input-field'] ::slotted(textarea) { | ||
-webkit-appearance: none; | ||
-moz-appearance: none; | ||
outline: none; | ||
margin: 0; | ||
padding: 0; | ||
border: 0; | ||
border-radius: 0; | ||
min-width: 0; | ||
font: inherit; | ||
font-size: 1em; | ||
line-height: normal; | ||
color: inherit; | ||
background-color: transparent; | ||
/* Disable default invalid style in Firefox */ | ||
box-shadow: none; | ||
} | ||
/* Reset the native input styles */ | ||
[part="value"], | ||
[part="input-field"] ::slotted(input), | ||
[part="input-field"] ::slotted(textarea) { | ||
-webkit-appearance: none; | ||
-moz-appearance: none; | ||
outline: none; | ||
margin: 0; | ||
padding: 0; | ||
border: 0; | ||
border-radius: 0; | ||
min-width: 0; | ||
font: inherit; | ||
font-size: 1em; | ||
line-height: normal; | ||
color: inherit; | ||
background-color: transparent; | ||
/* Disable default invalid style in Firefox */ | ||
box-shadow: none; | ||
} | ||
[part='input-field'] ::slotted(*) { | ||
flex: none; | ||
} | ||
[part="input-field"] ::slotted(*) { | ||
flex: none; | ||
} | ||
[part='value'], | ||
[part='input-field'] ::slotted(input), | ||
[part='input-field'] ::slotted(textarea), | ||
[part='input-field'] ::slotted([part='value']) { | ||
flex: auto; | ||
white-space: nowrap; | ||
overflow: hidden; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
[part="value"], | ||
[part="input-field"] ::slotted(input), | ||
[part="input-field"] ::slotted(textarea), | ||
/* Slotted by vaadin-select-text-field */ | ||
[part="input-field"] ::slotted([part="value"]) { | ||
flex: auto; | ||
white-space: nowrap; | ||
overflow: hidden; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
[part='input-field'] ::slotted(textarea) { | ||
resize: none; | ||
} | ||
[part="input-field"] ::slotted(textarea) { | ||
resize: none; | ||
} | ||
[part='clear-button'] { | ||
display: none; | ||
cursor: default; | ||
} | ||
[part="value"]::-ms-clear, | ||
[part="input-field"] ::slotted(input)::-ms-clear { | ||
display: none; | ||
} | ||
[part='clear-button']::before { | ||
content: '✕'; | ||
} | ||
[part="clear-button"] { | ||
cursor: default; | ||
} | ||
:host([clear-button-visible][has-value]:not([disabled]):not([readonly])) [part='clear-button'] { | ||
display: block; | ||
} | ||
`, | ||
{ moduleId: 'vaadin-text-field-shared-styles' } | ||
); | ||
[part="clear-button"]::before { | ||
content: "✕"; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
const HOST_PROPS = { | ||
default: ['list', 'autofocus', 'pattern', 'autocapitalize', 'autocorrect', 'maxlength', | ||
'minlength', 'name', 'placeholder', 'autocomplete', 'title', 'disabled', 'readonly', 'required'], | ||
default: [ | ||
'autofocus', | ||
'pattern', | ||
'autocapitalize', | ||
'autocorrect', | ||
'maxlength', | ||
'minlength', | ||
'name', | ||
'placeholder', | ||
'autocomplete', | ||
'title', | ||
'disabled', | ||
'readonly', | ||
'required' | ||
], | ||
accessible: ['invalid'] | ||
@@ -124,836 +133,743 @@ }; | ||
/** | ||
* @polymerMixin | ||
*/ | ||
export const TextFieldMixin = subclass => class VaadinTextFieldMixin extends subclass { | ||
static get properties() { | ||
return { | ||
/** | ||
* Whether the value of the control can be automatically completed by the browser. | ||
* List of available options at: | ||
* https://developer.mozilla.org/en/docs/Web/HTML/Element/input#attr-autocomplete | ||
*/ | ||
autocomplete: { | ||
type: String | ||
}, | ||
export const TextFieldMixin = (subclass) => | ||
class VaadinTextFieldMixin extends subclass { | ||
static get properties() { | ||
return { | ||
/** | ||
* Whether the value of the control can be automatically completed by the browser. | ||
* List of available options at: | ||
* https://developer.mozilla.org/en/docs/Web/HTML/Element/input#attr-autocomplete | ||
*/ | ||
autocomplete: { | ||
type: String | ||
}, | ||
/** | ||
* This is a property supported by Safari that is used to control whether | ||
* autocorrection should be enabled when the user is entering/editing the text. | ||
* Possible values are: | ||
* on: Enable autocorrection. | ||
* off: Disable autocorrection. | ||
* @type {!TextFieldAutoCorrect | undefined} | ||
*/ | ||
autocorrect: { | ||
type: String | ||
}, | ||
/** | ||
* This is a property supported by Safari that is used to control whether | ||
* autocorrection should be enabled when the user is entering/editing the text. | ||
* Possible values are: | ||
* on: Enable autocorrection. | ||
* off: Disable autocorrection. | ||
* @type {!TextFieldAutoCorrect | undefined} | ||
*/ | ||
autocorrect: { | ||
type: String | ||
}, | ||
/** | ||
* This is a property supported by Safari and Chrome that is used to control whether | ||
* autocapitalization should be enabled when the user is entering/editing the text. | ||
* Possible values are: | ||
* characters: Characters capitalization. | ||
* words: Words capitalization. | ||
* sentences: Sentences capitalization. | ||
* none: No capitalization. | ||
* @type {!TextFieldAutoCapitalize | undefined} | ||
*/ | ||
autocapitalize: { | ||
type: String | ||
}, | ||
/** | ||
* This is a property supported by Safari and Chrome that is used to control whether | ||
* autocapitalization should be enabled when the user is entering/editing the text. | ||
* Possible values are: | ||
* characters: Characters capitalization. | ||
* words: Words capitalization. | ||
* sentences: Sentences capitalization. | ||
* none: No capitalization. | ||
* @type {!TextFieldAutoCapitalize | undefined} | ||
*/ | ||
autocapitalize: { | ||
type: String | ||
}, | ||
/** | ||
* Specify that the value should be automatically selected when the field gains focus. | ||
* @type {boolean} | ||
*/ | ||
autoselect: { | ||
type: Boolean, | ||
value: false | ||
}, | ||
/** | ||
* Specify that the value should be automatically selected when the field gains focus. | ||
* @type {boolean} | ||
*/ | ||
autoselect: { | ||
type: Boolean, | ||
value: false | ||
}, | ||
/** | ||
* Set to true to display the clear icon which clears the input. | ||
* @attr {boolean} clear-button-visible | ||
* @type {boolean} | ||
*/ | ||
clearButtonVisible: { | ||
type: Boolean, | ||
value: false | ||
}, | ||
/** | ||
* Set to true to display the clear icon which clears the input. | ||
* @attr {boolean} clear-button-visible | ||
* @type {boolean} | ||
*/ | ||
clearButtonVisible: { | ||
type: Boolean, | ||
value: false, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* Error to show when the input value is invalid. | ||
* @attr {string} error-message | ||
* @type {string} | ||
*/ | ||
errorMessage: { | ||
type: String, | ||
value: '', | ||
observer: '_errorMessageChanged' | ||
}, | ||
/** | ||
* Error to show when the input value is invalid. | ||
* @attr {string} error-message | ||
* @type {string} | ||
*/ | ||
errorMessage: { | ||
type: String, | ||
value: '', | ||
observer: '_errorMessageChanged' | ||
}, | ||
/** | ||
* Object with translated strings used for localization. Has | ||
* the following structure and default values: | ||
* | ||
* ``` | ||
* { | ||
* // Translation of the clear icon button accessible label | ||
* clear: 'Clear' | ||
* } | ||
* ``` | ||
* @type {{clear: string}} | ||
*/ | ||
i18n: { | ||
type: Object, | ||
value: () => { | ||
return { | ||
clear: 'Clear' | ||
}; | ||
} | ||
}, | ||
/** | ||
* Object with translated strings used for localization. Has | ||
* the following structure and default values: | ||
* | ||
* ``` | ||
* { | ||
* // Translation of the clear icon button accessible label | ||
* clear: 'Clear' | ||
* } | ||
* ``` | ||
* @type {{clear: string}} | ||
*/ | ||
i18n: { | ||
type: Object, | ||
value: () => { | ||
return { | ||
clear: 'Clear' | ||
}; | ||
} | ||
}, | ||
/** | ||
* String used for the label element. | ||
* @type {string} | ||
*/ | ||
label: { | ||
type: String, | ||
value: '', | ||
observer: '_labelChanged' | ||
}, | ||
/** | ||
* String used for the label element. | ||
* @type {string} | ||
*/ | ||
label: { | ||
type: String, | ||
value: '', | ||
observer: '_labelChanged' | ||
}, | ||
/** | ||
* String used for the helper text. | ||
* @attr {string} helper-text | ||
* @type {string | null} | ||
*/ | ||
helperText: { | ||
type: String, | ||
value: '', | ||
observer: '_helperTextChanged' | ||
}, | ||
/** | ||
* String used for the helper text. | ||
* @attr {string} helper-text | ||
* @type {string | null} | ||
*/ | ||
helperText: { | ||
type: String, | ||
value: '', | ||
observer: '_helperTextChanged' | ||
}, | ||
/** | ||
* Maximum number of characters (in Unicode code points) that the user can enter. | ||
*/ | ||
maxlength: { | ||
type: Number | ||
}, | ||
/** | ||
* Maximum number of characters (in Unicode code points) that the user can enter. | ||
*/ | ||
maxlength: { | ||
type: Number | ||
}, | ||
/** | ||
* Minimum number of characters (in Unicode code points) that the user can enter. | ||
*/ | ||
minlength: { | ||
type: Number | ||
}, | ||
/** | ||
* Minimum number of characters (in Unicode code points) that the user can enter. | ||
*/ | ||
minlength: { | ||
type: Number | ||
}, | ||
/** | ||
* The name of the control, which is submitted with the form data. | ||
*/ | ||
name: { | ||
type: String | ||
}, | ||
/** | ||
* The name of the control, which is submitted with the form data. | ||
*/ | ||
name: { | ||
type: String | ||
}, | ||
/** | ||
* A hint to the user of what can be entered in the control. | ||
*/ | ||
placeholder: { | ||
type: String | ||
}, | ||
/** | ||
* A hint to the user of what can be entered in the control. | ||
*/ | ||
placeholder: { | ||
type: String | ||
}, | ||
/** | ||
* This attribute indicates that the user cannot modify the value of the control. | ||
*/ | ||
readonly: { | ||
type: Boolean, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* This attribute indicates that the user cannot modify the value of the control. | ||
*/ | ||
readonly: { | ||
type: Boolean, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* Specifies that the user must fill in a value. | ||
*/ | ||
required: { | ||
type: Boolean, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* Specifies that the user must fill in a value. | ||
*/ | ||
required: { | ||
type: Boolean, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* The initial value of the control. | ||
* It can be used for two-way data binding. | ||
* @type {string} | ||
*/ | ||
value: { | ||
type: String, | ||
value: '', | ||
observer: '_valueChanged', | ||
notify: true | ||
}, | ||
/** | ||
* The initial value of the control. | ||
* It can be used for two-way data binding. | ||
* @type {string} | ||
*/ | ||
value: { | ||
type: String, | ||
value: '', | ||
observer: '_valueChanged', | ||
notify: true | ||
}, | ||
/** | ||
* This property is set to true when the control value is invalid. | ||
* @type {boolean} | ||
*/ | ||
invalid: { | ||
type: Boolean, | ||
reflectToAttribute: true, | ||
notify: true, | ||
value: false | ||
}, | ||
/** | ||
* This property is set to true when the control value is invalid. | ||
* @type {boolean} | ||
*/ | ||
invalid: { | ||
type: Boolean, | ||
reflectToAttribute: true, | ||
notify: true, | ||
value: false | ||
}, | ||
/** | ||
* When set to true, user is prevented from typing a value that | ||
* conflicts with the given `pattern`. | ||
* @attr {boolean} prevent-invalid-input | ||
*/ | ||
preventInvalidInput: { | ||
type: Boolean | ||
}, | ||
/** | ||
* Specifies that the text field has value. | ||
* @attr {boolean} has-value | ||
*/ | ||
hasValue: { | ||
type: Boolean, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* A pattern matched against individual characters the user inputs. | ||
* When set, the field will prevent: | ||
* - `keyDown` events if the entered key doesn't match `/^_enabledCharPattern$/` | ||
* - `paste` events if the pasted text doesn't match `/^_enabledCharPattern*$/` | ||
* - `drop` events if the dropped text doesn't match `/^_enabledCharPattern*$/` | ||
* | ||
* For example, to enable entering only numbers and minus signs, | ||
* `_enabledCharPattern = "[\\d-]"` | ||
* @protected | ||
*/ | ||
_enabledCharPattern: String, | ||
/** | ||
* When set to true, user is prevented from typing a value that | ||
* conflicts with the given `pattern`. | ||
* @attr {boolean} prevent-invalid-input | ||
*/ | ||
preventInvalidInput: { | ||
type: Boolean | ||
}, | ||
/** @private */ | ||
_labelId: String, | ||
/** | ||
* A pattern matched against individual characters the user inputs. | ||
* When set, the field will prevent: | ||
* - `keyDown` events if the entered key doesn't match `/^_enabledCharPattern$/` | ||
* - `paste` events if the pasted text doesn't match `/^_enabledCharPattern*$/` | ||
* - `drop` events if the dropped text doesn't match `/^_enabledCharPattern*$/` | ||
* | ||
* For example, to enable entering only numbers and minus signs, | ||
* `_enabledCharPattern = "[\\d-]"` | ||
* @protected | ||
*/ | ||
_enabledCharPattern: String, | ||
/** @private */ | ||
_helperTextId: String, | ||
/** @private */ | ||
_labelId: String, | ||
/** @private */ | ||
_errorId: String, | ||
/** @private */ | ||
_helperTextId: String, | ||
/** @private */ | ||
_inputId: String, | ||
/** @private */ | ||
_errorId: String, | ||
/** @private */ | ||
_hasSlottedHelper: Boolean | ||
}; | ||
} | ||
/** @private */ | ||
_inputId: String, | ||
static get observers() { | ||
return [ | ||
'_hostPropsChanged(' + HOST_PROPS.default.join(', ') + ')', | ||
'_hostAccessiblePropsChanged(' + HOST_PROPS.accessible.join(', ') + ')', | ||
'_getActiveErrorId(invalid, errorMessage, _errorId, helperText, _helperTextId, _hasSlottedHelper)', | ||
'_getActiveLabelId(label, _labelId, _inputId)', | ||
'__observeOffsetHeight(errorMessage, invalid, label, helperText)', | ||
'__enabledCharPatternChanged(_enabledCharPattern)' | ||
]; | ||
} | ||
/** @private */ | ||
_hasSlottedHelper: Boolean | ||
}; | ||
} | ||
/** | ||
* @return {HTMLElement | undefined} | ||
* @protected | ||
*/ | ||
get focusElement() { | ||
if (!this.shadowRoot) { | ||
return undefined; | ||
} | ||
const slotted = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
if (slotted) { | ||
return slotted; | ||
} | ||
return this.shadowRoot.querySelector('[part="value"]'); | ||
} | ||
static get observers() { | ||
return ['_stateChanged(disabled, readonly, clearButtonVisible, hasValue)', | ||
'_hostPropsChanged(' + HOST_PROPS.default.join(', ') + ')', | ||
'_hostAccessiblePropsChanged(' + HOST_PROPS.accessible.join(', ') + ')', | ||
'_getActiveErrorId(invalid, errorMessage, _errorId, helperText, _helperTextId, _hasSlottedHelper)', | ||
'_getActiveLabelId(label, _labelId, _inputId)', | ||
'__observeOffsetHeight(errorMessage, invalid, label, helperText)', | ||
'__enabledCharPatternChanged(_enabledCharPattern)' | ||
]; | ||
} | ||
/** | ||
* @return {HTMLElement | undefined}} | ||
* @protected | ||
*/ | ||
get inputElement() { | ||
return this.focusElement; | ||
} | ||
/** | ||
* @return {HTMLElement | undefined} | ||
* @protected | ||
*/ | ||
get focusElement() { | ||
if (!this.shadowRoot) { | ||
return; | ||
/** | ||
* @return {string} | ||
* @protected | ||
*/ | ||
get _slottedTagName() { | ||
return 'input'; | ||
} | ||
const slotted = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
if (slotted) { | ||
return slotted; | ||
/** @protected */ | ||
_createConstraintsObserver() { | ||
// This complex observer needs to be added dynamically here (instead of defining it above in the `get observers()`) | ||
// so that it runs after complex observers of inheriting classes. Otherwise e.g. `_stepOrMinChanged()` observer of | ||
// vaadin-number-field would run after this and the `min` and `step` properties would not yet be propagated to | ||
// the `inputElement` when this runs. | ||
this._createMethodObserver('_constraintsChanged(required, minlength, maxlength, pattern)'); | ||
} | ||
return this.shadowRoot.querySelector('[part="value"]'); | ||
} | ||
/** | ||
* @return {HTMLElement | undefined}} | ||
* @protected | ||
*/ | ||
get inputElement() { | ||
return this.focusElement; | ||
} | ||
/** @private */ | ||
_onInput(e) { | ||
if (this.preventInvalidInput) { | ||
const input = this.inputElement; | ||
if (input.value.length > 0 && !this.checkValidity()) { | ||
input.value = this.value || ''; | ||
// add input-prevented attribute for 200ms | ||
this.setAttribute('input-prevented', ''); | ||
this._inputDebouncer = Debouncer.debounce(this._inputDebouncer, timeOut.after(200), () => { | ||
this.removeAttribute('input-prevented'); | ||
}); | ||
return; | ||
} | ||
} | ||
/** | ||
* @return {string} | ||
* @protected | ||
*/ | ||
get _slottedTagName() { | ||
return 'input'; | ||
} | ||
if (!e.__fromClearButton) { | ||
this.__userInput = true; | ||
} | ||
/** @protected */ | ||
_createConstraintsObserver() { | ||
// This complex observer needs to be added dynamically here (instead of defining it above in the `get observers()`) | ||
// so that it runs after complex observers of inheriting classes. Otherwise e.g. `_stepOrMinChanged()` observer of | ||
// vaadin-number-field would run after this and the `min` and `step` properties would not yet be propagated to | ||
// the `inputElement` when this runs. | ||
this._createMethodObserver('_constraintsChanged(required, minlength, maxlength, pattern)'); | ||
} | ||
/** @private */ | ||
_onInput(e) { | ||
if (this.__preventInput) { | ||
e.stopImmediatePropagation(); | ||
this.__preventInput = false; | ||
return; | ||
this.value = e.target.value; | ||
this.__userInput = false; | ||
} | ||
if (this.preventInvalidInput) { | ||
const input = this.inputElement; | ||
if (input.value.length > 0 && !this.checkValidity()) { | ||
input.value = this.value || ''; | ||
// add input-prevented attribute for 200ms | ||
this.setAttribute('input-prevented', ''); | ||
this._inputDebouncer = Debouncer.debounce( | ||
this._inputDebouncer, | ||
timeOut.after(200), () => { | ||
this.removeAttribute('input-prevented'); | ||
}); | ||
/** | ||
* @param {!Event} e | ||
* @protected | ||
*/ | ||
_onChange(e) { | ||
if (this._valueClearing) { | ||
return; | ||
} | ||
} | ||
if (!e.__fromClearButton) { | ||
this.__userInput = true; | ||
// In the Shadow DOM, the `change` event is not leaked into the | ||
// ancestor tree, so we must do this manually. | ||
const changeEvent = new CustomEvent('change', { | ||
detail: { | ||
sourceEvent: e | ||
}, | ||
bubbles: e.bubbles, | ||
cancelable: e.cancelable | ||
}); | ||
this.dispatchEvent(changeEvent); | ||
} | ||
this.value = e.target.value; | ||
this.__userInput = false; | ||
} | ||
/** | ||
* @param {unknown} newVal | ||
* @param {unknown} oldVal | ||
* @protected | ||
*/ | ||
_valueChanged(newVal, oldVal) { | ||
// setting initial value to empty string, skip validation | ||
if (newVal === '' && oldVal === undefined) { | ||
return; | ||
} | ||
// NOTE(yuriy): Workaround needed for IE11 and Edge for proper displaying | ||
// of the clear button instead of setting display property for it depending on state. | ||
/** @private */ | ||
_stateChanged(disabled, readonly, clearButtonVisible, hasValue) { | ||
if (!disabled && | ||
!readonly && | ||
clearButtonVisible && | ||
hasValue | ||
) { | ||
this.$.clearButton.removeAttribute('hidden'); | ||
} else { | ||
this.$.clearButton.setAttribute('hidden', true); | ||
} | ||
} | ||
if (newVal !== '' && newVal != null) { | ||
this.setAttribute('has-value', ''); | ||
} else { | ||
this.removeAttribute('has-value'); | ||
} | ||
/** | ||
* @param {!Event} e | ||
* @protected | ||
*/ | ||
_onChange(e) { | ||
if (this._valueClearing) { | ||
return; | ||
if (this.__userInput) { | ||
return; | ||
} else if (newVal !== undefined) { | ||
this.inputElement.value = newVal; | ||
} else { | ||
this.value = this.inputElement.value = ''; | ||
} | ||
if (this.invalid) { | ||
this.validate(); | ||
} | ||
} | ||
// In the Shadow DOM, the `change` event is not leaked into the | ||
// ancestor tree, so we must do this manually. | ||
const changeEvent = new CustomEvent('change', { | ||
detail: { | ||
sourceEvent: e | ||
}, | ||
bubbles: e.bubbles, | ||
cancelable: e.cancelable, | ||
}); | ||
this.dispatchEvent(changeEvent); | ||
} | ||
/** | ||
* @param {unknown} newVal | ||
* @param {unknown} oldVal | ||
* @protected | ||
*/ | ||
_valueChanged(newVal, oldVal) { | ||
// setting initial value to empty string, skip validation | ||
if (newVal === '' && oldVal === undefined) { | ||
return; | ||
/** @private */ | ||
_labelChanged(label) { | ||
this._setOrToggleAttribute('has-label', !!label, this); | ||
} | ||
if (newVal !== '' && newVal != null) { | ||
this.hasValue = true; | ||
} else { | ||
this.hasValue = false; | ||
/** @private */ | ||
_helperTextChanged(helperText) { | ||
this._setOrToggleAttribute('has-helper', !!helperText, this); | ||
} | ||
if (this.__userInput) { | ||
return; | ||
} else if (newVal !== undefined) { | ||
this.inputElement.value = newVal; | ||
} else { | ||
this.value = this.inputElement.value = ''; | ||
/** @private */ | ||
_errorMessageChanged(errorMessage) { | ||
this._setOrToggleAttribute('has-error-message', !!errorMessage, this); | ||
} | ||
if (this.invalid) { | ||
this.validate(); | ||
/** @private */ | ||
_onHelperSlotChange() { | ||
const slottedNodes = this.shadowRoot.querySelector(`[name="helper"]`).assignedNodes({ flatten: true }); | ||
// Only has slotted helper if not a text node | ||
// Text nodes are added by the helperText prop and not the helper slot | ||
// The filter is added due to shady DOM triggering this callback on helperText prop change | ||
this._hasSlottedHelper = slottedNodes.filter((node) => node.nodeType !== 3).length; | ||
if (this._hasSlottedHelper) { | ||
this.setAttribute('has-helper', 'slotted'); | ||
} else if (this.helperText === '' || this.helperText === null) { | ||
this.removeAttribute('has-helper'); | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_labelChanged(label) { | ||
this._setOrToggleAttribute('has-label', !!label, this); | ||
} | ||
/** @private */ | ||
_onSlotChange() { | ||
const slotted = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
/** @private */ | ||
_helperTextChanged(helperText) { | ||
this._setOrToggleAttribute('has-helper', !!helperText, this); | ||
} | ||
if (this.value) { | ||
this.inputElement.value = this.value; | ||
this.validate(); | ||
} | ||
/** @private */ | ||
_errorMessageChanged(errorMessage) { | ||
this._setOrToggleAttribute('has-error-message', !!errorMessage, this); | ||
} | ||
if (slotted && !this._slottedInput) { | ||
this._validateSlottedValue(slotted); | ||
this._addInputListeners(slotted); | ||
this._slottedInput = slotted; | ||
} else if (!slotted && this._slottedInput) { | ||
this._removeInputListeners(this._slottedInput); | ||
this._slottedInput = undefined; | ||
} | ||
/** @private */ | ||
_onHelperSlotChange() { | ||
const slottedNodes = this.shadowRoot.querySelector(`[name="helper"]`).assignedNodes({flatten: true}); | ||
// Only has slotted helper if not a text node | ||
// Text nodes are added by the helperText prop and not the helper slot | ||
// The filter is added due to shady DOM triggering this callback on helperText prop change | ||
this._hasSlottedHelper = slottedNodes.filter(node => node.nodeType !== 3).length; | ||
Object.keys(PROP_TYPE) | ||
.map((key) => PROP_TYPE[key]) | ||
.forEach((type) => | ||
this._propagateHostAttributes( | ||
HOST_PROPS[type].map((attr) => this[attr]), | ||
type | ||
) | ||
); | ||
} | ||
if (this._hasSlottedHelper) { | ||
this.setAttribute('has-helper', 'slotted'); | ||
} else if (this.helperText === '' || this.helperText === null) { | ||
this.removeAttribute('has-helper'); | ||
/** @private */ | ||
_hostPropsChanged(...attributesValues) { | ||
this._propagateHostAttributes(attributesValues, PROP_TYPE.DEFAULT); | ||
} | ||
} | ||
/** @private */ | ||
_onSlotChange() { | ||
const slotted = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
if (this.value) { | ||
this.inputElement.value = this.value; | ||
this.validate(); | ||
/** @private */ | ||
_hostAccessiblePropsChanged(...attributesValues) { | ||
this._propagateHostAttributes(attributesValues, PROP_TYPE.ACCESSIBLE); | ||
} | ||
if (slotted && !this._slottedInput) { | ||
this._validateSlottedValue(slotted); | ||
this._addInputListeners(slotted); | ||
this._addIEListeners(slotted); | ||
this._slottedInput = slotted; | ||
} else if (!slotted && this._slottedInput) { | ||
this._removeInputListeners(this._slottedInput); | ||
this._removeIEListeners(this._slottedInput); | ||
this._slottedInput = undefined; | ||
/** @private */ | ||
_validateSlottedValue(slotted) { | ||
if (slotted.value !== this.value) { | ||
console.warn('Please define value on the vaadin-text-field component!'); | ||
slotted.value = ''; | ||
} | ||
} | ||
Object.keys(PROP_TYPE).map(key => PROP_TYPE[key]).forEach(type => | ||
this._propagateHostAttributes(HOST_PROPS[type].map(attr => this[attr]), type)); | ||
} | ||
/** @private */ | ||
_propagateHostAttributes(attributesValues, type) { | ||
const input = this.inputElement; | ||
const attributeNames = HOST_PROPS[type]; | ||
/** @private */ | ||
_hostPropsChanged(...attributesValues) { | ||
this._propagateHostAttributes(attributesValues, PROP_TYPE.DEFAULT); | ||
} | ||
/** @private */ | ||
_hostAccessiblePropsChanged(...attributesValues) { | ||
this._propagateHostAttributes(attributesValues, PROP_TYPE.ACCESSIBLE); | ||
} | ||
/** @private */ | ||
_validateSlottedValue(slotted) { | ||
if (slotted.value !== this.value) { | ||
console.warn('Please define value on the vaadin-text-field component!'); | ||
slotted.value = ''; | ||
if (type === PROP_TYPE.ACCESSIBLE) { | ||
attributeNames.forEach((attr, index) => { | ||
this._setOrToggleAttribute(attr, attributesValues[index], input); | ||
this._setOrToggleAttribute(`aria-${attr}`, attributesValues[index] ? 'true' : false, input); | ||
}); | ||
} else { | ||
attributeNames.forEach((attr, index) => { | ||
this._setOrToggleAttribute(attr, attributesValues[index], input); | ||
}); | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_propagateHostAttributes(attributesValues, type) { | ||
const input = this.inputElement; | ||
const attributeNames = HOST_PROPS[type]; | ||
/** @private */ | ||
_setOrToggleAttribute(name, value, node) { | ||
if (!name || !node) { | ||
return; | ||
} | ||
if (type === PROP_TYPE.ACCESSIBLE) { | ||
attributeNames.forEach((attr, index) => { | ||
this._setOrToggleAttribute(attr, attributesValues[index], input); | ||
this._setOrToggleAttribute(`aria-${attr}`, attributesValues[index] ? 'true' : false, input); | ||
}); | ||
} else { | ||
attributeNames.forEach((attr, index) => { | ||
this._setOrToggleAttribute(attr, attributesValues[index], input); | ||
}); | ||
if (value) { | ||
node.setAttribute(name, typeof value === 'boolean' ? '' : value); | ||
} else { | ||
node.removeAttribute(name); | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_setOrToggleAttribute(name, value, node) { | ||
if (!name || !node) { | ||
return; | ||
} | ||
/** | ||
* @param {boolean | undefined} required | ||
* @param {number | undefined} minlength | ||
* @param {number | undefined} maxlength | ||
* @param {string | undefined} maxlength | ||
* @protected | ||
*/ | ||
_constraintsChanged(required, minlength, maxlength, pattern) { | ||
if (!this.invalid) { | ||
return; | ||
} | ||
if (value) { | ||
node.setAttribute(name, (typeof value === 'boolean') ? '' : value); | ||
} else { | ||
node.removeAttribute(name); | ||
if (!required && !minlength && !maxlength && !pattern) { | ||
this.invalid = false; | ||
} else { | ||
this.validate(); | ||
} | ||
} | ||
} | ||
/** | ||
* @param {boolean | undefined} required | ||
* @param {number | undefined} minlength | ||
* @param {number | undefined} maxlength | ||
* @param {string | undefined} maxlength | ||
* @protected | ||
*/ | ||
_constraintsChanged(required, minlength, maxlength, pattern) { | ||
if (!this.invalid) { | ||
return; | ||
/** | ||
* Returns true if the current input value satisfies all constraints (if any) | ||
* @return {boolean} | ||
*/ | ||
checkValidity() { | ||
// Note (Yuriy): `__forceCheckValidity` is used in containing components (i.e. `vaadin-date-picker`) in order | ||
// to force the checkValidity instead of returning the previous invalid state. | ||
if (this.required || this.pattern || this.maxlength || this.minlength || this.__forceCheckValidity) { | ||
return this.inputElement.checkValidity(); | ||
} else { | ||
return !this.invalid; | ||
} | ||
} | ||
if (!required && !minlength && !maxlength && !pattern) { | ||
this.invalid = false; | ||
} else { | ||
this.validate(); | ||
/** @private */ | ||
_addInputListeners(node) { | ||
node.addEventListener('input', this._boundOnInput); | ||
node.addEventListener('change', this._boundOnChange); | ||
node.addEventListener('blur', this._boundOnBlur); | ||
node.addEventListener('focus', this._boundOnFocus); | ||
node.addEventListener('paste', this._boundOnPaste); | ||
node.addEventListener('drop', this._boundOnDrop); | ||
node.addEventListener('beforeinput', this._boundOnBeforeInput); | ||
} | ||
} | ||
/** | ||
* Returns true if the current input value satisfies all constraints (if any) | ||
* @return {boolean} | ||
*/ | ||
checkValidity() { | ||
// Note (Yuriy): `__forceCheckValidity` is used in containing components (i.e. `vaadin-date-picker`) in order | ||
// to force the checkValidity instead of returning the previous invalid state. | ||
if (this.required || this.pattern || this.maxlength || this.minlength || this.__forceCheckValidity) { | ||
return this.inputElement.checkValidity(); | ||
} else { | ||
return !this.invalid; | ||
/** @private */ | ||
_removeInputListeners(node) { | ||
node.removeEventListener('input', this._boundOnInput); | ||
node.removeEventListener('change', this._boundOnChange); | ||
node.removeEventListener('blur', this._boundOnBlur); | ||
node.removeEventListener('focus', this._boundOnFocus); | ||
node.removeEventListener('paste', this._boundOnPaste); | ||
node.removeEventListener('drop', this._boundOnDrop); | ||
node.removeEventListener('beforeinput', this._boundOnBeforeInput); | ||
} | ||
} | ||
/** @private */ | ||
_addInputListeners(node) { | ||
node.addEventListener('input', this._boundOnInput); | ||
node.addEventListener('change', this._boundOnChange); | ||
node.addEventListener('blur', this._boundOnBlur); | ||
node.addEventListener('focus', this._boundOnFocus); | ||
node.addEventListener('paste', this._boundOnPaste); | ||
node.addEventListener('drop', this._boundOnDrop); | ||
node.addEventListener('beforeinput', this._boundOnBeforeInput); | ||
} | ||
/** @protected */ | ||
ready() { | ||
super.ready(); | ||
/** @private */ | ||
_removeInputListeners(node) { | ||
node.removeEventListener('input', this._boundOnInput); | ||
node.removeEventListener('change', this._boundOnChange); | ||
node.removeEventListener('blur', this._boundOnBlur); | ||
node.removeEventListener('focus', this._boundOnFocus); | ||
node.removeEventListener('paste', this._boundOnPaste); | ||
node.removeEventListener('drop', this._boundOnDrop); | ||
node.removeEventListener('beforeinput', this._boundOnBeforeInput); | ||
} | ||
this._createConstraintsObserver(); | ||
/** @protected */ | ||
ready() { | ||
super.ready(); | ||
this._boundOnInput = this._onInput.bind(this); | ||
this._boundOnChange = this._onChange.bind(this); | ||
this._boundOnBlur = this._onBlur.bind(this); | ||
this._boundOnFocus = this._onFocus.bind(this); | ||
this._boundOnPaste = this._onPaste.bind(this); | ||
this._boundOnDrop = this._onDrop.bind(this); | ||
this._boundOnBeforeInput = this._onBeforeInput.bind(this); | ||
this._createConstraintsObserver(); | ||
const defaultInput = this.shadowRoot.querySelector('[part="value"]'); | ||
this._slottedInput = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
this._addInputListeners(defaultInput); | ||
if (this._slottedInput) { | ||
this._addInputListeners(this._slottedInput); | ||
} | ||
this._boundOnInput = this._onInput.bind(this); | ||
this._boundOnChange = this._onChange.bind(this); | ||
this._boundOnBlur = this._onBlur.bind(this); | ||
this._boundOnFocus = this._onFocus.bind(this); | ||
this._boundOnPaste = this._onPaste.bind(this); | ||
this._boundOnDrop = this._onDrop.bind(this); | ||
this._boundOnBeforeInput = this._onBeforeInput.bind(this); | ||
this.shadowRoot | ||
.querySelector('[name="input"], [name="textarea"]') | ||
.addEventListener('slotchange', this._onSlotChange.bind(this)); | ||
const defaultInput = this.shadowRoot.querySelector('[part="value"]'); | ||
this._slottedInput = this.querySelector(`${this._slottedTagName}[slot="${this._slottedTagName}"]`); | ||
this._addInputListeners(defaultInput); | ||
this._addIEListeners(defaultInput); | ||
if (this._slottedInput) { | ||
this._addIEListeners(this._slottedInput); | ||
this._addInputListeners(this._slottedInput); | ||
} | ||
this._onHelperSlotChange(); | ||
this.shadowRoot | ||
.querySelector('[name="helper"]') | ||
.addEventListener('slotchange', this._onHelperSlotChange.bind(this)); | ||
this.shadowRoot.querySelector('[name="input"], [name="textarea"]') | ||
.addEventListener('slotchange', this._onSlotChange.bind(this)); | ||
this.$.clearButton.addEventListener('mousedown', () => (this._valueClearing = true)); | ||
this.$.clearButton.addEventListener('mouseleave', () => (this._valueClearing = false)); | ||
this.$.clearButton.addEventListener('click', this._onClearButtonClick.bind(this)); | ||
this.addEventListener('keydown', this._onKeyDown.bind(this)); | ||
this._onHelperSlotChange(); | ||
this.shadowRoot.querySelector('[name="helper"]').addEventListener('slotchange', this._onHelperSlotChange.bind(this)); | ||
var uniqueId = (TextFieldMixin._uniqueId = 1 + TextFieldMixin._uniqueId || 0); | ||
this._errorId = `${this.constructor.is}-error-${uniqueId}`; | ||
this._labelId = `${this.constructor.is}-label-${uniqueId}`; | ||
this._helperTextId = `${this.constructor.is}-helper-${uniqueId}`; | ||
this._inputId = `${this.constructor.is}-input-${uniqueId}`; | ||
if (!(window.ShadyCSS && window.ShadyCSS.nativeCss)) { | ||
this.updateStyles(); | ||
} | ||
this.$.clearButton.addEventListener('mousedown', () => this._valueClearing = true); | ||
this.$.clearButton.addEventListener('mouseleave', () => this._valueClearing = false); | ||
this.$.clearButton.addEventListener('click', this._onClearButtonClick.bind(this)); | ||
this.addEventListener('keydown', this._onKeyDown.bind(this)); | ||
var uniqueId = TextFieldMixin._uniqueId = 1 + TextFieldMixin._uniqueId || 0; | ||
this._errorId = `${this.constructor.is}-error-${uniqueId}`; | ||
this._labelId = `${this.constructor.is}-label-${uniqueId}`; | ||
this._helperTextId = `${this.constructor.is}-helper-${uniqueId}`; | ||
this._inputId = `${this.constructor.is}-input-${uniqueId}`; | ||
// Lumo theme defines a max-height transition for the "error-message" | ||
// part on invalid state change. | ||
this.shadowRoot.querySelector('[part="error-message"]') | ||
.addEventListener('transitionend', () => { | ||
// Lumo theme defines a max-height transition for the "error-message" | ||
// part on invalid state change. | ||
this.shadowRoot.querySelector('[part="error-message"]').addEventListener('transitionend', () => { | ||
this.__observeOffsetHeight(); | ||
}); | ||
} | ||
} | ||
/** | ||
* Returns true if `value` is valid. | ||
* `<iron-form>` uses this to check the validity for all its elements. | ||
* | ||
* @return {boolean} True if the value is valid. | ||
*/ | ||
validate() { | ||
return !(this.invalid = !this.checkValidity()); | ||
} | ||
/** | ||
* Returns true if `value` is valid. | ||
* | ||
* @return {boolean} True if the value is valid. | ||
*/ | ||
validate() { | ||
return !(this.invalid = !this.checkValidity()); | ||
} | ||
clear() { | ||
this.value = ''; | ||
} | ||
/** @private */ | ||
_onBlur() { | ||
this.validate(); | ||
} | ||
/** @private */ | ||
_onFocus() { | ||
if (this.autoselect) { | ||
this.inputElement.select(); | ||
// iOS 9 workaround: https://stackoverflow.com/a/7436574 | ||
setTimeout(() => { | ||
try { | ||
this.inputElement.setSelectionRange(0, 9999); | ||
} catch (e) { | ||
// The workaround may cause errors on different input types. | ||
// Needs to be suppressed. See https://github.com/vaadin/flow/issues/6070 | ||
} | ||
}); | ||
clear() { | ||
this.value = ''; | ||
} | ||
} | ||
/** @private */ | ||
_onClearButtonClick(e) { | ||
e.preventDefault(); | ||
// NOTE(yuriy): This line won't affect focus on the host. Cannot be properly tested. | ||
this.inputElement.focus(); | ||
this.clear(); | ||
this._valueClearing = false; | ||
if (navigator.userAgent.match(/Trident/)) { | ||
// Disable IE input" event prevention here, we want the input event from | ||
// below to propagate normally. | ||
this.__preventInput = false; | ||
/** @private */ | ||
_onBlur() { | ||
this.validate(); | ||
} | ||
const inputEvent = new Event('input', {bubbles: true, composed: true}); | ||
inputEvent.__fromClearButton = true; | ||
const changeEvent = new Event('change', {bubbles: !this._slottedInput}); | ||
changeEvent.__fromClearButton = true; | ||
this.inputElement.dispatchEvent(inputEvent); | ||
this.inputElement.dispatchEvent(changeEvent); | ||
} | ||
/** | ||
* @param {!KeyboardEvent} e | ||
* @protected | ||
*/ | ||
_onKeyDown(e) { | ||
if (e.keyCode === 27 && this.clearButtonVisible) { | ||
const dispatchChange = !!this.value; | ||
this.clear(); | ||
dispatchChange && this.inputElement.dispatchEvent(new Event('change', {bubbles: !this._slottedInput})); | ||
/** @private */ | ||
_onFocus() { | ||
if (this.autoselect) { | ||
this.inputElement.select(); | ||
// iOS 9 workaround: https://stackoverflow.com/a/7436574 | ||
setTimeout(() => { | ||
try { | ||
this.inputElement.setSelectionRange(0, 9999); | ||
} catch (e) { | ||
// The workaround may cause errors on different input types. | ||
// Needs to be suppressed. See https://github.com/vaadin/flow/issues/6070 | ||
} | ||
}); | ||
} | ||
} | ||
if (this._enabledCharPattern && !this.__shouldAcceptKey(e)) { | ||
/** @private */ | ||
_onClearButtonClick(e) { | ||
e.preventDefault(); | ||
// NOTE(yuriy): This line won't affect focus on the host. Cannot be properly tested. | ||
this.inputElement.focus(); | ||
this.clear(); | ||
this._valueClearing = false; | ||
const inputEvent = new Event('input', { bubbles: true, composed: true }); | ||
inputEvent.__fromClearButton = true; | ||
const changeEvent = new Event('change', { bubbles: !this._slottedInput }); | ||
changeEvent.__fromClearButton = true; | ||
this.inputElement.dispatchEvent(inputEvent); | ||
this.inputElement.dispatchEvent(changeEvent); | ||
} | ||
} | ||
/** @private */ | ||
__shouldAcceptKey(event) { | ||
return (event.metaKey || event.ctrlKey) | ||
|| !event.key // allow typing anything if event.key is not supported | ||
|| event.key.length !== 1 // allow "Backspace", "ArrowLeft" etc. | ||
|| this.__enabledCharRegExp.test(event.key); | ||
} | ||
/** | ||
* @param {!KeyboardEvent} e | ||
* @protected | ||
*/ | ||
_onKeyDown(e) { | ||
if (e.keyCode === 27 && this.clearButtonVisible) { | ||
const dispatchChange = !!this.value; | ||
this.clear(); | ||
dispatchChange && this.inputElement.dispatchEvent(new Event('change', { bubbles: !this._slottedInput })); | ||
} | ||
/** @private */ | ||
_onPaste(e) { | ||
if (this._enabledCharPattern) { | ||
const pastedText = (e.clipboardData || window.clipboardData).getData('text'); | ||
if (!this.__enabledTextRegExp.test(pastedText)) { | ||
if (this._enabledCharPattern && !this.__shouldAcceptKey(e)) { | ||
e.preventDefault(); | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_onDrop(e) { | ||
if (this._enabledCharPattern) { | ||
const draggedText = e.dataTransfer.getData('text'); | ||
if (!this.__enabledTextRegExp.test(draggedText)) { | ||
e.preventDefault(); | ||
/** @private */ | ||
__shouldAcceptKey(event) { | ||
return ( | ||
event.metaKey || | ||
event.ctrlKey || | ||
!event.key || // allow typing anything if event.key is not supported | ||
event.key.length !== 1 || // allow "Backspace", "ArrowLeft" etc. | ||
this.__enabledCharRegExp.test(event.key) | ||
); | ||
} | ||
/** @private */ | ||
_onPaste(e) { | ||
if (this._enabledCharPattern) { | ||
const pastedText = (e.clipboardData || window.clipboardData).getData('text'); | ||
if (!this.__enabledTextRegExp.test(pastedText)) { | ||
e.preventDefault(); | ||
} | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_onBeforeInput(e) { | ||
// The `beforeinput` event covers all the cases for `_enabledCharPattern`: keyboard, pasting and dropping, | ||
// but it is still experimental technology so we can't rely on it. It's used here just as an additional check, | ||
// because it seems to be the only way to detect and prevent specific keys on mobile devices. See issue #429. | ||
if (this._enabledCharPattern && e.data && !this.__enabledTextRegExp.test(e.data)) { | ||
e.preventDefault(); | ||
/** @private */ | ||
_onDrop(e) { | ||
if (this._enabledCharPattern) { | ||
const draggedText = e.dataTransfer.getData('text'); | ||
if (!this.__enabledTextRegExp.test(draggedText)) { | ||
e.preventDefault(); | ||
} | ||
} | ||
} | ||
} | ||
/** @private */ | ||
__enabledCharPatternChanged(_enabledCharPattern) { | ||
this.__enabledCharRegExp = _enabledCharPattern && new RegExp('^' + _enabledCharPattern + '$'); | ||
this.__enabledTextRegExp = _enabledCharPattern && new RegExp('^' + _enabledCharPattern + '*$'); | ||
} | ||
/** @private */ | ||
_onBeforeInput(e) { | ||
// The `beforeinput` event covers all the cases for `_enabledCharPattern`: keyboard, pasting and dropping, | ||
// but it is still experimental technology so we can't rely on it. It's used here just as an additional check, | ||
// because it seems to be the only way to detect and prevent specific keys on mobile devices. See issue #429. | ||
if (this._enabledCharPattern && e.data && !this.__enabledTextRegExp.test(e.data)) { | ||
e.preventDefault(); | ||
} | ||
} | ||
/** @private */ | ||
_addIEListeners(node) { | ||
/* istanbul ignore if */ | ||
if (navigator.userAgent.match(/Trident/)) { | ||
// IE11 dispatches `input` event in following cases: | ||
// - focus or blur, when placeholder attribute is set | ||
// - placeholder attribute value changed | ||
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/101220/ | ||
this._shouldPreventInput = () => { | ||
this.__preventInput = true; | ||
requestAnimationFrame(() => { | ||
this.__preventInput = false; | ||
}); | ||
}; | ||
node.addEventListener('focusin', this._shouldPreventInput); | ||
node.addEventListener('focusout', this._shouldPreventInput); | ||
this._createPropertyObserver('placeholder', this._shouldPreventInput); | ||
/** @private */ | ||
__enabledCharPatternChanged(_enabledCharPattern) { | ||
this.__enabledCharRegExp = _enabledCharPattern && new RegExp('^' + _enabledCharPattern + '$'); | ||
this.__enabledTextRegExp = _enabledCharPattern && new RegExp('^' + _enabledCharPattern + '*$'); | ||
} | ||
} | ||
/** @private */ | ||
_removeIEListeners(node) { | ||
/* istanbul ignore if */ | ||
if (navigator.userAgent.match(/Trident/)) { | ||
node.removeEventListener('focusin', this._shouldPreventInput); | ||
node.removeEventListener('focusout', this._shouldPreventInput); | ||
/** @private */ | ||
_getActiveErrorId(invalid, errorMessage, errorId, helperText, helperTextId, hasSlottedHelper) { | ||
const ids = []; | ||
if (helperText || hasSlottedHelper) { | ||
ids.push(helperTextId); | ||
} | ||
if (errorMessage && invalid) { | ||
ids.push(errorId); | ||
} | ||
this._setOrToggleAttribute('aria-describedby', ids.join(' '), this.focusElement); | ||
} | ||
} | ||
/** @private */ | ||
_getActiveErrorId(invalid, errorMessage, errorId, helperText, helperTextId, hasSlottedHelper) { | ||
const ids = []; | ||
if (helperText || hasSlottedHelper) { | ||
ids.push(helperTextId); | ||
/** @private */ | ||
_getActiveLabelId(label, _labelId, _inputId) { | ||
let ids = _inputId; | ||
if (label) { | ||
ids = `${_labelId} ${_inputId}`; | ||
} | ||
this.focusElement.setAttribute('aria-labelledby', ids); | ||
} | ||
if (errorMessage && invalid) { | ||
ids.push(errorId); | ||
/** @private */ | ||
_getErrorMessageAriaHidden(invalid, errorMessage, errorId) { | ||
return (!(errorMessage && invalid ? errorId : undefined)).toString(); | ||
} | ||
this._setOrToggleAttribute('aria-describedby', ids.join(' '), this.focusElement); | ||
} | ||
/** @private */ | ||
_getActiveLabelId(label, _labelId, _inputId) { | ||
let ids = _inputId; | ||
if (label) { | ||
ids = `${_labelId} ${_inputId}`; | ||
/** @private */ | ||
_dispatchIronResizeEventIfNeeded(sizePropertyName, value) { | ||
const previousSizePropertyName = '__previous' + sizePropertyName; | ||
if (this[previousSizePropertyName] !== undefined && this[previousSizePropertyName] !== value) { | ||
this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true })); | ||
} | ||
this[previousSizePropertyName] = value; | ||
} | ||
this.focusElement.setAttribute('aria-labelledby', ids); | ||
} | ||
/** @private */ | ||
_getErrorMessageAriaHidden(invalid, errorMessage, errorId) { | ||
return (!(errorMessage && invalid ? errorId : undefined)).toString(); | ||
} | ||
/** @private */ | ||
_dispatchIronResizeEventIfNeeded(sizePropertyName, value) { | ||
const previousSizePropertyName = '__previous' + sizePropertyName; | ||
if (this[previousSizePropertyName] !== undefined | ||
&& this[previousSizePropertyName] !== value) { | ||
this.dispatchEvent( | ||
new CustomEvent('iron-resize', {bubbles: true}) | ||
/** @private */ | ||
__observeOffsetHeight() { | ||
this.__observeOffsetHeightDebouncer = Debouncer.debounce( | ||
this.__observeOffsetHeightDebouncer, | ||
animationFrame, | ||
() => { | ||
this._dispatchIronResizeEventIfNeeded('Height', this.offsetHeight); | ||
} | ||
); | ||
} | ||
this[previousSizePropertyName] = value; | ||
} | ||
/** @private */ | ||
__observeOffsetHeight() { | ||
this.__observeOffsetHeightDebouncer = Debouncer.debounce( | ||
this.__observeOffsetHeightDebouncer, | ||
animationFrame, () => { | ||
this._dispatchIronResizeEventIfNeeded('Height', this.offsetHeight); | ||
}); | ||
} | ||
/** | ||
* @param {string} prop | ||
* @param {string} oldVal | ||
* @param {string} newVal | ||
* @protected | ||
*/ | ||
attributeChangedCallback(prop, oldVal, newVal) { | ||
super.attributeChangedCallback(prop, oldVal, newVal); | ||
// Needed until Edge has CSS Custom Properties (present in Edge Preview) | ||
/* istanbul ignore if */ | ||
if (!(window.ShadyCSS && window.ShadyCSS.nativeCss) && | ||
/^(focused|focus-ring|invalid|disabled|placeholder|has-value)$/.test(prop)) { | ||
this.updateStyles(); | ||
// Workaround for https://github.com/Polymer/polymer/issues/5259 | ||
get __data() { | ||
return this.__dataValue || {}; | ||
} | ||
// Safari has an issue with repainting shadow root element styles when a host attribute changes. | ||
// Need this workaround (toggle any inline css property on and off) until the issue gets fixed. | ||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); | ||
/* istanbul ignore if */ | ||
if (isSafari && this.root) { | ||
const WEBKIT_PROPERTY = '-webkit-backface-visibility'; | ||
this.root.querySelectorAll('*').forEach(el => { | ||
el.style[WEBKIT_PROPERTY] = 'visible'; | ||
el.style[WEBKIT_PROPERTY] = ''; | ||
}); | ||
set __data(value) { | ||
this.__dataValue = value; | ||
} | ||
} | ||
// Workaround for https://github.com/Polymer/polymer/issues/5259 | ||
get __data() { | ||
return this.__dataValue || {}; | ||
} | ||
/** | ||
* Fired when the user commits a value change. | ||
* | ||
* @event change | ||
*/ | ||
set __data(value) { | ||
this.__dataValue = value; | ||
} | ||
/** | ||
* Fired when the value is changed by the user: on every typing keystroke, | ||
* and the value is cleared using the clear button. | ||
* | ||
* @event input | ||
*/ | ||
/** | ||
* Fired when the user commits a value change. | ||
* | ||
* @event change | ||
*/ | ||
/** | ||
* Fired when the value is changed by the user: on every typing keystroke, | ||
* and the value is cleared using the clear button. | ||
* | ||
* @event input | ||
*/ | ||
/** | ||
* Fired when the size of the element changes. | ||
* | ||
* @event iron-resize | ||
*/ | ||
}; | ||
/** | ||
* Fired when the size of the element changes. | ||
* | ||
* @event iron-resize | ||
*/ | ||
}; |
@@ -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-text-field.js | ||
*/ | ||
import { TextFieldMixin } from './vaadin-text-field-mixin.js'; | ||
import { ControlStateMixin } from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import {PolymerElement} from '@polymer/polymer/polymer-element.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import {TextFieldMixin} from './vaadin-text-field-mixin.js'; | ||
import { TextFieldEventMap } from './interfaces'; | ||
import {ControlStateMixin} from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
import {ThemableMixin} from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import {ElementMixin} from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import {html} from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -81,21 +66,12 @@ * `<vaadin-text-field>` is a Web Component for text field control in forms. | ||
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki) | ||
* | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
*/ | ||
declare class TextFieldElement extends | ||
TextFieldMixin( | ||
ControlStateMixin( | ||
ThemableMixin( | ||
ElementMixin( | ||
PolymerElement)))) { | ||
declare class TextFieldElement extends TextFieldMixin(ControlStateMixin(ThemableMixin(ElementMixin(HTMLElement)))) { | ||
/** | ||
* Identifies a list of pre-defined options to suggest to the user. | ||
* The value must be the id of a <datalist> element in the same document. | ||
*/ | ||
list: string|null|undefined; | ||
/** | ||
* A regular expression that the value is checked against. | ||
* The pattern must match the entire value, not just some subset. | ||
*/ | ||
pattern: string|null|undefined; | ||
pattern: string | null | undefined; | ||
@@ -106,11 +82,22 @@ /** | ||
title: string; | ||
addEventListener<K extends keyof TextFieldEventMap>( | ||
type: K, | ||
listener: (this: TextFieldElement, ev: TextFieldEventMap[K]) => void, | ||
options?: boolean | AddEventListenerOptions | ||
): void; | ||
removeEventListener<K extends keyof TextFieldEventMap>( | ||
type: K, | ||
listener: (this: TextFieldElement, ev: TextFieldEventMap[K]) => void, | ||
options?: boolean | EventListenerOptions | ||
): void; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
"vaadin-text-field": TextFieldElement; | ||
'vaadin-text-field': TextFieldElement; | ||
} | ||
} | ||
export {TextFieldElement}; | ||
export { TextFieldElement }; |
/** | ||
@license | ||
Copyright (c) 2017 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 { TextFieldMixin } from './vaadin-text-field-mixin.js'; | ||
@@ -12,3 +11,3 @@ import { ControlStateMixin } from '@vaadin/vaadin-control-state-mixin/vaadin-control-state-mixin.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
/** | ||
@@ -70,3 +69,6 @@ * `<vaadin-text-field>` is a Web Component for text field control in forms. | ||
* | ||
* @extends PolymerElement | ||
* @fires {CustomEvent<boolean>} invalid-changed | ||
* @fires {CustomEvent<string>} value-changed | ||
* | ||
* @extends HTMLElement | ||
* @mixes TextFieldMixin | ||
@@ -76,40 +78,35 @@ * @mixes ControlStateMixin | ||
* @mixes ElementMixin | ||
* @demo demo/index.html | ||
*/ | ||
class TextFieldElement extends | ||
ElementMixin( | ||
TextFieldMixin( | ||
ControlStateMixin( | ||
ThemableMixin(PolymerElement)))) { | ||
class TextFieldElement extends ElementMixin(TextFieldMixin(ControlStateMixin(ThemableMixin(PolymerElement)))) { | ||
static get template() { | ||
return html` | ||
<style include="vaadin-text-field-shared-styles"> | ||
/* polymer-cli linter breaks with empty line */ | ||
</style> | ||
<style include="vaadin-text-field-shared-styles"></style> | ||
<div class="vaadin-text-field-container"> | ||
<div class="vaadin-text-field-container"> | ||
<label part="label" on-click="focus" id="[[_labelId]]">[[label]]</label> | ||
<label part="label" on-click="focus" id="[[_labelId]]">[[label]]</label> | ||
<div part="input-field" id="[[_inputId]]"> | ||
<slot name="prefix"></slot> | ||
<div part="input-field" id="[[_inputId]]"> | ||
<slot name="input"> | ||
<input part="value" /> | ||
</slot> | ||
<slot name="prefix"></slot> | ||
<div part="clear-button" id="clearButton" role="button" aria-label$="[[i18n.clear]]"></div> | ||
<slot name="suffix"></slot> | ||
</div> | ||
<slot name="input"> | ||
<input part="value"> | ||
</slot> | ||
<div part="helper-text" on-click="focus" id="[[_helperTextId]]"> | ||
<slot name="helper">[[helperText]]</slot> | ||
</div> | ||
<div part="clear-button" id="clearButton" role="button" aria-label\$="[[i18n.clear]]"></div> | ||
<slot name="suffix"></slot> | ||
<div | ||
part="error-message" | ||
id="[[_errorId]]" | ||
aria-live="assertive" | ||
aria-hidden$="[[_getErrorMessageAriaHidden(invalid, errorMessage, _errorId)]]" | ||
>[[errorMessage]]</div | ||
> | ||
</div> | ||
<div part="helper-text" on-click="focus" id="[[_helperTextId]]"> | ||
<slot name="helper">[[helperText]]</slot> | ||
</div> | ||
<div part="error-message" id="[[_errorId]]" aria-live="assertive" aria-hidden\$="[[_getErrorMessageAriaHidden(invalid, errorMessage, _errorId)]]">[[errorMessage]]</div> | ||
</div> | ||
`; | ||
`; | ||
} | ||
@@ -122,3 +119,3 @@ | ||
static get version() { | ||
return '2.8.2'; | ||
return '3.0.0-alpha1'; | ||
} | ||
@@ -129,10 +126,2 @@ | ||
/** | ||
* Identifies a list of pre-defined options to suggest to the user. | ||
* The value must be the id of a <datalist> element in the same document. | ||
*/ | ||
list: { | ||
type: String | ||
}, | ||
/** | ||
* A regular expression that the value is checked against. | ||
@@ -139,0 +128,0 @@ * The pattern must match the entire value, not just some subset. |
@@ -1,20 +0,17 @@ | ||
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-email-field" theme-for="vaadin-email-field"> | ||
<template> | ||
<style> | ||
:not(*):placeholder-shown, /* to prevent broken styles on IE */ | ||
:host([dir="rtl"]) [part="value"]:placeholder-shown, | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input:placeholder-shown) { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
registerStyles( | ||
'vaadin-email-field', | ||
css` | ||
:host([dir='rtl']) [part='value']:placeholder-shown, | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input:placeholder-shown) { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([dir="rtl"]) [part="value"], | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
:host([dir='rtl']) [part='value'], | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
} | ||
`, | ||
{ moduleId: 'lumo-email-field' } | ||
); |
@@ -0,49 +1,43 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-lumo-styles/font-icons.js'; | ||
import '@vaadin/vaadin-lumo-styles/sizing.js'; | ||
import '@vaadin/vaadin-lumo-styles/mixins/field-button.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="lumo-number-field" theme-for="vaadin-number-field"> | ||
<template> | ||
<style include="lumo-field-button"> | ||
:host { | ||
width: 8em; | ||
} | ||
registerStyles( | ||
'vaadin-number-field', | ||
css` | ||
:host { | ||
width: 8em; | ||
} | ||
:host([has-controls]:not([theme~="align-right"])) [part="value"] { | ||
text-align: center; | ||
} | ||
:host([has-controls]:not([theme~='align-right'])) [part='value'] { | ||
text-align: center; | ||
} | ||
[part="decrease-button"][disabled], | ||
[part="increase-button"][disabled] { | ||
opacity: 0.2; | ||
} | ||
[part$='button'][disabled] { | ||
opacity: 0.2; | ||
} | ||
:host([has-controls]) [part="input-field"] { | ||
padding: 0; | ||
} | ||
:host([has-controls]) [part='input-field'] { | ||
padding: 0; | ||
} | ||
[part="decrease-button"], | ||
[part="increase-button"] { | ||
cursor: pointer; | ||
font-size: var(--lumo-icon-size-s); | ||
width: 1.6em; | ||
height: 1.6em; | ||
} | ||
[part\$='button'] { | ||
cursor: pointer; | ||
font-size: var(--lumo-icon-size-s); | ||
width: 1.6em; | ||
height: 1.6em; | ||
} | ||
[part="decrease-button"]::before, | ||
[part="increase-button"]::before { | ||
margin-top: 0.2em; | ||
} | ||
[part\$='button']::before { | ||
margin-top: 0.2em; | ||
} | ||
/* RTL specific styles */ | ||
:host([dir="rtl"]) [part="value"], | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
/* RTL specific styles */ | ||
:host([dir='rtl']) [part='value'], | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
} | ||
`, | ||
{ moduleId: 'lumo-number-field', include: ['lumo-field-button'] } | ||
); |
@@ -0,29 +1,22 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-lumo-styles/font-icons.js'; | ||
import '@vaadin/vaadin-lumo-styles/sizing.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="lumo-password-field" theme-for="vaadin-password-field"> | ||
<template> | ||
<style> | ||
[part="reveal-button"]::before { | ||
content: var(--lumo-icons-eye); | ||
} | ||
registerStyles( | ||
'vaadin-password-field', | ||
css` | ||
[part='reveal-button']::before { | ||
content: var(--lumo-icons-eye); | ||
} | ||
:host([password-visible]) [part="reveal-button"]::before { | ||
content: var(--lumo-icons-eye-disabled); | ||
} | ||
:host([password-visible]) [part='reveal-button']::before { | ||
content: var(--lumo-icons-eye-disabled); | ||
} | ||
/* Make it easy to hide the button across the whole app */ | ||
[part="reveal-button"] { | ||
display: var(--lumo-password-field-reveal-button-display, block); | ||
} | ||
/* FIXME: ShadyCSS workaround for slotted input in Edge */ | ||
[part="input-field"] ::slotted(input)::-ms-reveal { | ||
display: none; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
/* Make it easy to hide the button across the whole app */ | ||
[part='reveal-button'] { | ||
display: var(--lumo-password-field-reveal-button-display, block); | ||
} | ||
`, | ||
{ moduleId: 'lumo-password-field' } | ||
); |
@@ -1,65 +0,21 @@ | ||
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-placeholder-styles"> | ||
<template> | ||
<style> | ||
input[slot="input"]::-webkit-input-placeholder, | ||
textarea[slot="textarea"]::-webkit-input-placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 0.5; | ||
} | ||
registerStyles( | ||
'', | ||
css` | ||
input[slot='input']::placeholder, | ||
textarea[slot='textarea']::placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 0.5; | ||
} | ||
input[slot="input"]::-ms-input-placeholder, | ||
textarea[slot="textarea"]::-ms-input-placeholder { | ||
color: inherit; | ||
opacity: 0.5; | ||
} | ||
input[slot="input"]::-moz-placeholder, | ||
textarea[slot="textarea"]::-moz-placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 0.5; | ||
} | ||
input[slot="input"]::placeholder, | ||
textarea[slot="textarea"]::placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 0.5; | ||
} | ||
/* Read-only and disabled */ | ||
[readonly] > input[slot="input"]::-webkit-input-placeholder, | ||
[readonly] > textarea[slot="textarea"]::-webkit-input-placeholder, | ||
[disabled] > input[slot="input"]::-webkit-input-placeholder, | ||
[disabled] > textarea[slot="textarea"]::-webkit-input-placeholder { | ||
opacity: 0; | ||
} | ||
[readonly] > input[slot="input"]::-ms-input-placeholder, | ||
[readonly] > textarea[slot="textarea"]::-ms-input-placeholder, | ||
[disabled] > input[slot="input"]::-ms-input-placeholder, | ||
[disabled] > textarea[slot="textarea"]::-ms-input-placeholder { | ||
opacity: 0; | ||
} | ||
[readonly] > input[slot="input"]::-moz-placeholder, | ||
[readonly] > textarea[slot="textarea"]::-moz-placeholder, | ||
[disabled] > input[slot="input"]::-moz-placeholder, | ||
[disabled] > textarea[slot="textarea"]::-moz-placeholder { | ||
opacity: 0; | ||
} | ||
[readonly] > input[slot="input"]::placeholder, | ||
[readonly] > textarea[slot="textarea"]::placeholder, | ||
[disabled] > input[slot="input"]::placeholder, | ||
[disabled] > textarea[slot="textarea"]::placeholder { | ||
opacity: 0; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
[readonly] > input[slot='input']::placeholder, | ||
[readonly] > textarea[slot='textarea']::placeholder, | ||
[disabled] > input[slot='input']::placeholder, | ||
[disabled] > textarea[slot='textarea']::placeholder { | ||
opacity: 0; | ||
} | ||
`, | ||
{ moduleId: 'lumo-placeholder-styles' } | ||
); |
@@ -0,66 +1,65 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-lumo-styles/color.js'; | ||
import '@vaadin/vaadin-lumo-styles/sizing.js'; | ||
import '@vaadin/vaadin-lumo-styles/typography.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
import './vaadin-text-field-styles.js'; | ||
const $_documentContainer = html`<dom-module id="lumo-text-area" theme-for="vaadin-text-area"> | ||
<template> | ||
<style include="lumo-text-field"> | ||
[part="input-field"], | ||
[part="input-field"] ::slotted(textarea) { | ||
/* Equal to the implicit padding in vaadin-text-field */ | ||
padding-top: calc((var(--lumo-text-field-size) - 1em * var(--lumo-line-height-s)) / 2); | ||
padding-bottom: calc((var(--lumo-text-field-size) - 1em * var(--lumo-line-height-s)) / 2); | ||
height: auto; | ||
box-sizing: border-box; | ||
transition: background-color 0.1s; | ||
line-height: var(--lumo-line-height-s); | ||
} | ||
registerStyles( | ||
'vaadin-text-area', | ||
css` | ||
[part='input-field'], | ||
[part='input-field'] ::slotted(textarea) { | ||
/* Equal to the implicit padding in vaadin-text-field */ | ||
padding-top: calc((var(--lumo-text-field-size) - 1em * var(--lumo-line-height-s)) / 2); | ||
padding-bottom: calc((var(--lumo-text-field-size) - 1em * var(--lumo-line-height-s)) / 2); | ||
height: auto; | ||
box-sizing: border-box; | ||
transition: background-color 0.1s; | ||
line-height: var(--lumo-line-height-s); | ||
} | ||
:host(:not([readonly])) [part="input-field"]::after { | ||
display: none; | ||
} | ||
:host(:not([readonly])) [part='input-field']::after { | ||
display: none; | ||
} | ||
:host([readonly]) [part="input-field"] { | ||
border: 1px dashed var(--lumo-contrast-30pct); | ||
} | ||
:host([readonly]) [part='input-field'] { | ||
border: 1px dashed var(--lumo-contrast-30pct); | ||
} | ||
:host([readonly]) [part="input-field"]::after { | ||
border: none; | ||
} | ||
:host([readonly]) [part='input-field']::after { | ||
border: none; | ||
} | ||
:host(:hover:not([readonly]):not([focused])) [part="input-field"] { | ||
background-color: var(--lumo-contrast-20pct); | ||
} | ||
:host(:hover:not([readonly]):not([focused])) [part='input-field'] { | ||
background-color: var(--lumo-contrast-20pct); | ||
} | ||
@media (pointer: coarse) { | ||
:host(:hover:not([readonly]):not([focused])) [part="input-field"] { | ||
background-color: var(--lumo-contrast-10pct); | ||
} | ||
:host(:active:not([readonly]):not([focused])) [part="input-field"] { | ||
background-color: var(--lumo-contrast-20pct); | ||
} | ||
@media (pointer: coarse) { | ||
:host(:hover:not([readonly]):not([focused])) [part='input-field'] { | ||
background-color: var(--lumo-contrast-10pct); | ||
} | ||
[part="value"], | ||
[part="input-field"] ::slotted(textarea) { | ||
line-height: inherit; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
:host(:active:not([readonly]):not([focused])) [part='input-field'] { | ||
background-color: var(--lumo-contrast-20pct); | ||
} | ||
} | ||
/* Vertically align icon prefix/suffix with the first line of text */ | ||
[part="input-field"] ::slotted(iron-icon) { | ||
margin-top: calc((var(--lumo-icon-size-m) - 1em * var(--lumo-line-height-s)) / -2); | ||
} | ||
[part='value'], | ||
[part='input-field'] ::slotted(textarea) { | ||
line-height: inherit; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
[part="input-field"] [part="value"], | ||
[part="input-field"] ::slotted(textarea) { | ||
white-space: pre-wrap; /* override \`nowrap\` from <vaadin-text-field> */ | ||
align-self: stretch; /* override \`baseline\` from <vaadin-text-field> */ | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
/* Vertically align icon prefix/suffix with the first line of text */ | ||
[part='input-field'] ::slotted(iron-icon) { | ||
margin-top: calc((var(--lumo-icon-size-m) - 1em * var(--lumo-line-height-s)) / -2); | ||
} | ||
document.head.appendChild($_documentContainer.content); | ||
[part='input-field'] [part='value'], | ||
[part='input-field'] ::slotted(textarea) { | ||
white-space: pre-wrap; /* override "nowrap" from <vaadin-text-field> */ | ||
align-self: stretch; /* override "baseline" from <vaadin-text-field> */ | ||
} | ||
`, | ||
{ moduleId: 'lumo-text-area', include: ['lumo-text-field'] } | ||
); |
@@ -0,1 +1,2 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-lumo-styles/color.js'; | ||
@@ -9,393 +10,345 @@ import '@vaadin/vaadin-lumo-styles/sizing.js'; | ||
import '@vaadin/vaadin-lumo-styles/mixins/field-button.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="lumo-text-field" theme-for="vaadin-text-field"> | ||
<template> | ||
<style include="lumo-required-field lumo-field-button"> | ||
:host { | ||
--lumo-text-field-size: var(--lumo-size-m); | ||
color: var(--lumo-body-text-color); | ||
font-size: var(--lumo-font-size-m); | ||
font-family: var(--lumo-font-family); | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
-webkit-tap-highlight-color: transparent; | ||
padding: var(--lumo-space-xs) 0; | ||
} | ||
registerStyles( | ||
'vaadin-text-field', | ||
css` | ||
:host { | ||
--lumo-text-field-size: var(--lumo-size-m); | ||
color: var(--lumo-body-text-color); | ||
font-size: var(--lumo-font-size-m); | ||
font-family: var(--lumo-font-family); | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
-webkit-tap-highlight-color: transparent; | ||
padding: var(--lumo-space-xs) 0; | ||
} | ||
:host::before { | ||
height: var(--lumo-text-field-size); | ||
box-sizing: border-box; | ||
display: inline-flex; | ||
align-items: center; | ||
} | ||
:host::before { | ||
height: var(--lumo-text-field-size); | ||
box-sizing: border-box; | ||
display: inline-flex; | ||
align-items: center; | ||
} | ||
:host([focused]:not([readonly])) [part="label"] { | ||
color: var(--lumo-primary-text-color); | ||
} | ||
:host([focused]:not([readonly])) [part='label'] { | ||
color: var(--lumo-primary-text-color); | ||
} | ||
:host([has-helper]) [part="helper-text"]::before { | ||
content: ""; | ||
display: block; | ||
height: 0.4em; | ||
} | ||
:host([has-helper]) [part='helper-text']::before { | ||
content: ''; | ||
display: block; | ||
height: 0.4em; | ||
} | ||
[part="helper-text"], | ||
[part="helper-text"] ::slotted(*) { | ||
display: block; | ||
color: var(--lumo-secondary-text-color); | ||
font-size: var(--lumo-font-size-xs); | ||
line-height: var(--lumo-line-height-xs); | ||
margin-left: calc(var(--lumo-border-radius-m) / 4); | ||
transition: color 0.2s; | ||
} | ||
[part='helper-text'], | ||
[part='helper-text'] ::slotted(*) { | ||
display: block; | ||
color: var(--lumo-secondary-text-color); | ||
font-size: var(--lumo-font-size-xs); | ||
line-height: var(--lumo-line-height-xs); | ||
margin-left: calc(var(--lumo-border-radius-m) / 4); | ||
transition: color 0.2s; | ||
} | ||
[part="value"], | ||
[part="input-field"] ::slotted(input), | ||
[part="input-field"] ::slotted(textarea), | ||
/* Slotted by vaadin-select-text-field */ | ||
[part="input-field"] ::slotted([part="value"]) { | ||
cursor: inherit; | ||
min-height: var(--lumo-text-field-size); | ||
padding: 0 0.25em; | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
-webkit-mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
} | ||
[part='value'], | ||
[part='input-field'] ::slotted(input), | ||
[part='input-field'] ::slotted(textarea), | ||
[part='input-field'] ::slotted([part='value']) { | ||
cursor: inherit; | ||
min-height: var(--lumo-text-field-size); | ||
padding: 0 0.25em; | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em); | ||
-webkit-mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
} | ||
[part="value"]:focus, | ||
:host([focused]) [part="input-field"] ::slotted(input), | ||
:host([focused]) [part="input-field"] ::slotted(textarea) { | ||
-webkit-mask-image: none; | ||
mask-image: none; | ||
} | ||
[part='value']:focus, | ||
:host([focused]) [part='input-field'] ::slotted(input), | ||
:host([focused]) [part='input-field'] ::slotted(textarea) { | ||
-webkit-mask-image: none; | ||
mask-image: none; | ||
} | ||
/* | ||
TODO: CSS custom property in \`mask-image\` causes crash in Edge | ||
see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/15415089/ | ||
*/ | ||
@-moz-document url-prefix() { | ||
[part="value"], | ||
[part="input-field"] ::slotted(input), | ||
[part="input-field"] ::slotted(textarea), | ||
[part="input-field"] ::slotted([part="value"]) { | ||
mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
} | ||
} | ||
[part='value']::placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 0.5; | ||
} | ||
[part="value"]::-webkit-input-placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 0.5; | ||
} | ||
[part='input-field'] { | ||
border-radius: var(--lumo-border-radius); | ||
background-color: var(--lumo-contrast-10pct); | ||
padding: 0 calc(0.375em + var(--lumo-border-radius) / 4 - 1px); | ||
font-weight: 500; | ||
line-height: 1; | ||
position: relative; | ||
cursor: text; | ||
box-sizing: border-box; | ||
} | ||
[part="value"]:-ms-input-placeholder { | ||
color: inherit; | ||
opacity: 0.5; | ||
} | ||
/* Used for hover and activation effects */ | ||
[part='input-field']::after { | ||
content: ''; | ||
position: absolute; | ||
top: 0; | ||
right: 0; | ||
bottom: 0; | ||
left: 0; | ||
border-radius: inherit; | ||
pointer-events: none; | ||
background-color: var(--lumo-contrast-50pct); | ||
opacity: 0; | ||
transition: transform 0.15s, opacity 0.2s; | ||
transform-origin: 100% 0; | ||
} | ||
[part="value"]::-moz-placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 0.5; | ||
} | ||
/* Hover */ | ||
[part="value"]::placeholder { | ||
color: inherit; | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 0.5; | ||
} | ||
:host(:hover:not([readonly]):not([focused])) [part='label'], | ||
:host(:hover:not([readonly])) [part='helper-text'], | ||
:host(:hover:not([readonly])) [part='helper-text'] ::slotted(*) { | ||
color: var(--lumo-body-text-color); | ||
} | ||
[part="input-field"] { | ||
border-radius: var(--lumo-border-radius); | ||
background-color: var(--lumo-contrast-10pct); | ||
padding: 0 calc(0.375em + var(--lumo-border-radius) / 4 - 1px); | ||
font-weight: 500; | ||
line-height: 1; | ||
position: relative; | ||
cursor: text; | ||
box-sizing: border-box; | ||
:host(:hover:not([readonly]):not([focused])) [part='input-field']::after { | ||
opacity: 0.1; | ||
} | ||
/* Touch device adjustment */ | ||
@media (pointer: coarse) { | ||
:host(:hover:not([readonly]):not([focused])) [part='label'] { | ||
color: var(--lumo-secondary-text-color); | ||
} | ||
/* Used for hover and activation effects */ | ||
[part="input-field"]::after { | ||
content: ""; | ||
position: absolute; | ||
top: 0; | ||
right: 0; | ||
bottom: 0; | ||
left: 0; | ||
border-radius: inherit; | ||
pointer-events: none; | ||
background-color: var(--lumo-contrast-50pct); | ||
:host(:hover:not([readonly]):not([focused])) [part='input-field']::after { | ||
opacity: 0; | ||
transition: transform 0.15s, opacity 0.2s; | ||
transform-origin: 100% 0; | ||
} | ||
/* Hover */ | ||
:host(:hover:not([readonly]):not([focused])) [part="label"], | ||
:host(:hover:not([readonly])) [part="helper-text"], | ||
:host(:hover:not([readonly])) [part="helper-text"] ::slotted(*) { | ||
color: var(--lumo-body-text-color); | ||
:host(:active:not([readonly]):not([focused])) [part='input-field']::after { | ||
opacity: 0.2; | ||
} | ||
} | ||
:host(:hover:not([readonly]):not([focused])) [part="input-field"]::after { | ||
opacity: 0.1; | ||
} | ||
/* Trigger when not focusing using the keyboard */ | ||
:host([focused]:not([focus-ring]):not([readonly])) [part='input-field']::after { | ||
transform: scaleX(0); | ||
transition-duration: 0.15s, 1s; | ||
} | ||
/* Touch device adjustment */ | ||
@media (pointer: coarse) { | ||
:host(:hover:not([readonly]):not([focused])) [part="label"] { | ||
color: var(--lumo-secondary-text-color); | ||
} | ||
/* Focus-ring */ | ||
:host(:hover:not([readonly]):not([focused])) [part="input-field"]::after { | ||
opacity: 0; | ||
} | ||
:host([focus-ring]) [part='input-field'] { | ||
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct); | ||
} | ||
:host(:active:not([readonly]):not([focused])) [part="input-field"]::after { | ||
opacity: 0.2; | ||
} | ||
} | ||
/* Read-only and disabled */ | ||
:host([readonly]) [part='value']::placeholder, | ||
:host([disabled]) [part='value']::placeholder { | ||
opacity: 0; | ||
} | ||
/* Trigger when not focusing using the keyboard */ | ||
:host([focused]:not([focus-ring]):not([readonly])) [part="input-field"]::after { | ||
transform: scaleX(0); | ||
transition-duration: 0.15s, 1s; | ||
} | ||
/* Read-only */ | ||
/* Focus-ring */ | ||
:host([readonly]) [part='input-field'] { | ||
color: var(--lumo-secondary-text-color); | ||
background-color: transparent; | ||
cursor: default; | ||
} | ||
:host([focus-ring]) [part="input-field"] { | ||
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct); | ||
} | ||
:host([readonly]) [part='input-field']::after { | ||
background-color: transparent; | ||
opacity: 1; | ||
border: 1px dashed var(--lumo-contrast-30pct); | ||
} | ||
/* Read-only and disabled */ | ||
:host([readonly]) [part="value"]::-webkit-input-placeholder, | ||
:host([disabled]) [part="value"]::-webkit-input-placeholder { | ||
opacity: 0; | ||
} | ||
/* Disabled style */ | ||
:host([readonly]) [part="value"]:-ms-input-placeholder, | ||
:host([disabled]) [part="value"]:-ms-input-placeholder { | ||
opacity: 0; | ||
} | ||
:host([disabled]) { | ||
pointer-events: none; | ||
} | ||
:host([readonly]) [part="value"]::-moz-placeholder, | ||
:host([disabled]) [part="value"]::-moz-placeholder { | ||
opacity: 0; | ||
} | ||
:host([disabled]) [part='input-field'] { | ||
background-color: var(--lumo-contrast-5pct); | ||
} | ||
:host([readonly]) [part="value"]::placeholder, | ||
:host([disabled]) [part="value"]::placeholder { | ||
opacity: 0; | ||
} | ||
:host([disabled]) [part='label'], | ||
:host([disabled]) [part='helper-text'], | ||
:host([disabled]) [part='value'], | ||
:host([disabled]) [part='input-field'] ::slotted(*) { | ||
color: var(--lumo-disabled-text-color); | ||
-webkit-text-fill-color: var(--lumo-disabled-text-color); | ||
} | ||
/* Read-only */ | ||
/* Invalid style */ | ||
:host([readonly]) [part="input-field"] { | ||
color: var(--lumo-secondary-text-color); | ||
background-color: transparent; | ||
cursor: default; | ||
} | ||
:host([invalid]) [part='input-field'] { | ||
background-color: var(--lumo-error-color-10pct); | ||
} | ||
:host([readonly]) [part="input-field"]::after { | ||
background-color: transparent; | ||
opacity: 1; | ||
border: 1px dashed var(--lumo-contrast-30pct); | ||
} | ||
:host([invalid]) [part='input-field']::after { | ||
background-color: var(--lumo-error-color-50pct); | ||
} | ||
/* Disabled style */ | ||
:host([invalid][focus-ring]) [part='input-field'] { | ||
box-shadow: 0 0 0 2px var(--lumo-error-color-50pct); | ||
} | ||
:host([disabled]) { | ||
pointer-events: none; | ||
} | ||
:host([input-prevented]) [part='input-field'] { | ||
color: var(--lumo-error-text-color); | ||
} | ||
:host([disabled]) [part="input-field"] { | ||
background-color: var(--lumo-contrast-5pct); | ||
} | ||
/* Small theme */ | ||
:host([disabled]) [part="label"], | ||
:host([disabled]) [part="helper-text"], | ||
:host([disabled]) [part="value"], | ||
:host([disabled]) [part="input-field"] ::slotted(*) { | ||
color: var(--lumo-disabled-text-color); | ||
-webkit-text-fill-color: var(--lumo-disabled-text-color); | ||
} | ||
:host([theme~='small']) { | ||
font-size: var(--lumo-font-size-s); | ||
--lumo-text-field-size: var(--lumo-size-s); | ||
} | ||
/* Invalid style */ | ||
:host([theme~='small'][has-label]) [part='label'] { | ||
font-size: var(--lumo-font-size-xs); | ||
} | ||
:host([invalid]) [part="input-field"] { | ||
background-color: var(--lumo-error-color-10pct); | ||
} | ||
:host([theme~='small'][has-label]) [part='error-message'] { | ||
font-size: var(--lumo-font-size-xxs); | ||
} | ||
:host([invalid]) [part="input-field"]::after { | ||
background-color: var(--lumo-error-color-50pct); | ||
} | ||
/* Text align */ | ||
:host([invalid][focus-ring]) [part="input-field"] { | ||
box-shadow: 0 0 0 2px var(--lumo-error-color-50pct); | ||
} | ||
:host([theme~='align-left']) [part='value'] { | ||
text-align: left; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([input-prevented]) [part="input-field"] { | ||
color: var(--lumo-error-text-color); | ||
} | ||
:host([theme~='align-center']) [part='value'] { | ||
text-align: center; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
/* Small theme */ | ||
:host([theme~='align-right']) [part='value'] { | ||
text-align: right; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([theme~="small"]) { | ||
font-size: var(--lumo-font-size-s); | ||
--lumo-text-field-size: var(--lumo-size-s); | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~='align-right']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
:host([theme~="small"][has-label]) [part="label"] { | ||
font-size: var(--lumo-font-size-xs); | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~='align-left']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
/* helper-text position */ | ||
:host([theme~="small"][has-label]) [part="error-message"] { | ||
font-size: var(--lumo-font-size-xxs); | ||
} | ||
:host([has-helper][theme~='helper-above-field']) [part='helper-text']::before { | ||
display: none; | ||
} | ||
/* Text align */ | ||
:host([has-helper][theme~='helper-above-field']) [part='helper-text']::after { | ||
content: ''; | ||
display: block; | ||
height: 0.4em; | ||
} | ||
:host([theme~="align-left"]) [part="value"] { | ||
text-align: left; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([has-helper][theme~='helper-above-field']) [part='label'] { | ||
order: 0; | ||
padding-bottom: 0.4em; | ||
} | ||
:host([theme~="align-center"]) [part="value"] { | ||
text-align: center; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([has-helper][theme~='helper-above-field']) [part='helper-text'] { | ||
order: 1; | ||
} | ||
:host([theme~="align-right"]) [part="value"] { | ||
text-align: right; | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([has-helper][theme~='helper-above-field']) [part='input-field'] { | ||
order: 2; | ||
} | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~="align-right"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
:host([has-helper][theme~='helper-above-field']) [part='error-message'] { | ||
order: 3; | ||
} | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~="align-left"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
/* helper-text position */ | ||
/* Slotted content */ | ||
:host([has-helper][theme~="helper-above-field"]) [part="helper-text"]::before { | ||
display: none; | ||
} | ||
[part='input-field'] ::slotted(:not([part]):not(iron-icon):not(input):not(textarea)) { | ||
color: var(--lumo-secondary-text-color); | ||
font-weight: 400; | ||
} | ||
:host([has-helper][theme~="helper-above-field"]) [part="helper-text"]::after { | ||
content: ""; | ||
display: block; | ||
height: 0.4em; | ||
} | ||
/* Slotted icons */ | ||
:host([has-helper][theme~="helper-above-field"]) [part="label"] { | ||
order: 0; | ||
padding-bottom: 0.4em; | ||
} | ||
[part='input-field'] ::slotted(iron-icon) { | ||
color: var(--lumo-contrast-60pct); | ||
width: var(--lumo-icon-size-m); | ||
height: var(--lumo-icon-size-m); | ||
} | ||
:host([has-helper][theme~="helper-above-field"]) [part="helper-text"] { | ||
order: 1; | ||
} | ||
/* Vaadin icons are based on a 16x16 grid (unlike Lumo and Material icons with 24x24), so they look too big by default */ | ||
[part='input-field'] ::slotted(iron-icon[icon^='vaadin:']) { | ||
padding: 0.25em; | ||
box-sizing: border-box !important; | ||
} | ||
:host([has-helper][theme~="helper-above-field"]) [part="input-field"] { | ||
order: 2; | ||
} | ||
[part='clear-button']::before { | ||
content: var(--lumo-icons-cross); | ||
} | ||
:host([has-helper][theme~="helper-above-field"]) [part="error-message"] { | ||
order: 3; | ||
} | ||
/* RTL specific styles */ | ||
/* Slotted content */ | ||
:host([dir='rtl']) [part='input-field']::after { | ||
transform-origin: 0% 0; | ||
} | ||
[part="input-field"] ::slotted(:not([part]):not(iron-icon):not(input):not(textarea)) { | ||
color: var(--lumo-secondary-text-color); | ||
font-weight: 400; | ||
} | ||
:host([dir='rtl']) [part='value'], | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input), | ||
:host([dir='rtl']) [part='input-field'] ::slotted(textarea) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent, #000 1.25em); | ||
} | ||
/* Slotted icons */ | ||
:host([dir='rtl']) [part='value']:focus, | ||
:host([focused][dir='rtl']) [part='input-field'] ::slotted(input), | ||
:host([focused][dir='rtl']) [part='input-field'] ::slotted(textarea) { | ||
-webkit-mask-image: none; | ||
mask-image: none; | ||
} | ||
[part="input-field"] ::slotted(iron-icon) { | ||
color: var(--lumo-contrast-60pct); | ||
width: var(--lumo-icon-size-m); | ||
height: var(--lumo-icon-size-m); | ||
@-moz-document url-prefix() { | ||
:host([dir='rtl']) [part='value'], | ||
:host([dir='rtl']) [part='input-field'] ::slotted(input), | ||
:host([dir='rtl']) [part='input-field'] ::slotted(textarea), | ||
:host([dir='rtl']) [part='input-field'] ::slotted([part='value']) { | ||
mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
} | ||
} | ||
/* Vaadin icons are based on a 16x16 grid (unlike Lumo and Material icons with 24x24), so they look too big by default */ | ||
[part="input-field"] ::slotted(iron-icon[icon^="vaadin:"]) { | ||
padding: 0.25em; | ||
box-sizing: border-box !important; | ||
} | ||
:host([theme~='align-left'][dir='rtl']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
[part="clear-button"]::before { | ||
content: var(--lumo-icons-cross); | ||
} | ||
:host([theme~='align-center'][dir='rtl']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
/* RTL specific styles */ | ||
:host([theme~='align-right'][dir='rtl']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([dir="rtl"]) [part="input-field"]::after { | ||
transform-origin: 0% 0; | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~='align-right'][dir='rtl']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
:host([dir="rtl"]) [part="value"], | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input), | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(textarea) { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent, #000 1.25em); | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~='align-left'][dir='rtl']) [part='value'] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent 0.25em, #000 1.5em); | ||
} | ||
:host([dir="rtl"]) [part="value"]:focus, | ||
:host([focused][dir="rtl"]) [part="input-field"] ::slotted(input), | ||
:host([focused][dir="rtl"]) [part="input-field"] ::slotted(textarea) { | ||
-webkit-mask-image: none; | ||
mask-image: none; | ||
} | ||
@-moz-document url-prefix() { | ||
:host([dir="rtl"]) [part="value"], | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(input), | ||
:host([dir="rtl"]) [part="input-field"] ::slotted(textarea), | ||
:host([dir="rtl"]) [part="input-field"] ::slotted([part="value"]) { | ||
mask-image: var(--_lumo-text-field-overflow-mask-image); | ||
} | ||
} | ||
:host([theme~="align-left"][dir="rtl"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([theme~="align-center"][dir="rtl"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
:host([theme~="align-right"][dir="rtl"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: none; | ||
} | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~="align-right"][dir="rtl"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to right, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
@-moz-document url-prefix() { | ||
/* Firefox is smart enough to align overflowing text to right */ | ||
:host([theme~="align-left"][dir="rtl"]) [part="value"] { | ||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent 0.25em, #000 1.5em); | ||
} | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
} | ||
`, | ||
{ moduleId: 'lumo-text-field', include: ['lumo-required-field', 'lumo-field-button'] } | ||
); |
@@ -1,32 +0,27 @@ | ||
import './vaadin-text-field-styles.js'; | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-material-styles/font-icons.js'; | ||
import '@vaadin/vaadin-material-styles/mixins/field-button.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="material-number-field" theme-for="vaadin-number-field"> | ||
<template> | ||
<style include="material-field-button"> | ||
:host { | ||
width: 8em; | ||
} | ||
registerStyles( | ||
'vaadin-number-field', | ||
css` | ||
:host { | ||
width: 8em; | ||
} | ||
:host([has-controls]) [part="value"] { | ||
text-align: center; | ||
} | ||
:host([has-controls]) [part='value'] { | ||
text-align: center; | ||
} | ||
[part="decrease-button"][disabled], | ||
[part="increase-button"][disabled] { | ||
opacity: 0.2; | ||
} | ||
[part\$='button'][disabled] { | ||
opacity: 0.2; | ||
} | ||
[part="decrease-button"], | ||
[part="increase-button"] { | ||
cursor: pointer; | ||
font-size: var(--material-body-font-size); | ||
padding-bottom: 0.21em; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
[part\$='decrease-button'] { | ||
cursor: pointer; | ||
font-size: var(--material-body-font-size); | ||
padding-bottom: 0.21em; | ||
} | ||
`, | ||
{ moduleId: 'material-number-field', include: ['material-field-button'] } | ||
); |
@@ -1,33 +0,29 @@ | ||
import './vaadin-text-field-styles.js'; | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-material-styles/font-icons.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="material-password-field" theme-for="vaadin-password-field"> | ||
<template> | ||
<style> | ||
[part="reveal-button"]::before { | ||
content: var(--material-icons-eye); | ||
} | ||
registerStyles( | ||
'vaadin-password-field', | ||
css` | ||
[part='reveal-button']::before { | ||
content: var(--material-icons-eye); | ||
} | ||
:host([password-visible]) [part="reveal-button"]::before { | ||
content: var(--material-icons-eye-disabled); | ||
} | ||
:host([password-visible]) [part='reveal-button']::before { | ||
content: var(--material-icons-eye-disabled); | ||
} | ||
/* The reveal button works also in readonly mode */ | ||
/* The reveal button works also in readonly mode */ | ||
:host([readonly]) [part\$='button'] { | ||
color: var(--material-secondary-text-color); | ||
} | ||
:host([readonly]) [part\$="button"] { | ||
color: var(--material-secondary-text-color); | ||
} | ||
[part='reveal-button'] { | ||
cursor: pointer; | ||
} | ||
[part="reveal-button"] { | ||
cursor: pointer; | ||
} | ||
[part="reveal-button"]:hover { | ||
color: var(--material-text-color); | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
[part='reveal-button']:hover { | ||
color: var(--material-text-color); | ||
} | ||
`, | ||
{ moduleId: 'material-password-field' } | ||
); |
import './vaadin-password-field-styles.js'; | ||
import './vaadin-text-field.js'; | ||
import '../../src/vaadin-password-field.js'; |
@@ -0,60 +1,21 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-material-styles/color.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="material-placeholder-styles"> | ||
<template> | ||
<style> | ||
input[slot="input"]::-webkit-input-placeholder, | ||
textarea[slot="textarea"]::-webkit-input-placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 1; | ||
} | ||
registerStyles( | ||
'', | ||
css` | ||
input[slot='input']::placeholder, | ||
textarea[slot='textarea']::placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 1; | ||
} | ||
input[slot="input"]::-ms-input-placeholder, | ||
textarea[slot="textarea"]::-ms-input-placeholder { | ||
color: var(--material-disabled-text-color); | ||
} | ||
input[slot="input"]::-moz-placeholder, | ||
textarea[slot="textarea"]::-moz-placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 1; | ||
} | ||
input[slot="input"]::placeholder, | ||
textarea[slot="textarea"]::placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 1; | ||
} | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="input"]::-webkit-input-placeholder, | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="textarea"]::-webkit-input-placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="input"]::-moz-placeholder, | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="textarea"]::-moz-placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="input"]::placeholder, | ||
[has-label]:not([focused]):not([invalid]):not([theme="always-float-label"]) > input[slot="textarea"]::placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
/* IE11 doesn’t show the placeholder when the input is focused, so it’s basically useless for this theme */ | ||
[has-label] > input[slot="input"]:-ms-input-placeholder, | ||
[has-label] > input[slot="textarea"]:-ms-input-placeholder { | ||
opacity: 0; | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
[has-label]:not([focused]):not([invalid]):not([theme='always-float-label']) > input[slot='input']::placeholder, | ||
[has-label]:not([focused]):not([invalid]):not([theme='always-float-label']) > input[slot='textarea']::placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
`, | ||
{ moduleId: 'material-placeholder-styles' } | ||
); |
@@ -0,27 +1,24 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import './vaadin-text-field-styles.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="material-text-area" theme-for="vaadin-text-area"> | ||
<template> | ||
<style include="material-text-field"> | ||
[part="input-field"] { | ||
height: auto; | ||
box-sizing: border-box; | ||
} | ||
registerStyles( | ||
'vaadin-text-area', | ||
css` | ||
[part='input-field'] { | ||
height: auto; | ||
box-sizing: border-box; | ||
} | ||
/* NOTE(platosha): double attribute workarounds specifity for Firefox */ | ||
[part="value"][part="value"] { | ||
padding-top: 0; | ||
margin-top: 4px; | ||
} | ||
[part='input-field'] [part='value'] { | ||
padding-top: 0; | ||
margin-top: 4px; | ||
} | ||
[part="input-field"] [part="value"], | ||
[part="input-field"] ::slotted(textarea) { | ||
white-space: pre-wrap; /* override \`nowrap\` from <vaadin-text-field> */ | ||
align-self: stretch; /* override \`baseline\` from <vaadin-text-field> */ | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
[part='input-field'] [part='value'], | ||
[part='input-field'] ::slotted(textarea) { | ||
white-space: pre-wrap; /* override "nowrap" from <vaadin-text-field> */ | ||
align-self: stretch; /* override "baseline" from <vaadin-text-field> */ | ||
} | ||
`, | ||
{ moduleId: 'material-text-area', include: ['material-text-field'] } | ||
); |
@@ -0,1 +1,2 @@ | ||
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js'; | ||
import '@vaadin/vaadin-material-styles/color.js'; | ||
@@ -6,254 +7,215 @@ import '@vaadin/vaadin-material-styles/typography.js'; | ||
import '@vaadin/vaadin-material-styles/mixins/field-button.js'; | ||
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; | ||
const $_documentContainer = html`<dom-module id="material-text-field" theme-for="vaadin-text-field"> | ||
<template> | ||
<style include="material-required-field material-field-button"> | ||
:host { | ||
display: inline-flex; | ||
position: relative; | ||
padding-top: 8px; | ||
margin-bottom: 8px; | ||
outline: none; | ||
color: var(--material-body-text-color); | ||
font-size: var(--material-body-font-size); | ||
line-height: 24px; | ||
font-family: var(--material-font-family); | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} | ||
registerStyles( | ||
'vaadin-text-field', | ||
css` | ||
:host { | ||
display: inline-flex; | ||
position: relative; | ||
padding-top: 8px; | ||
margin-bottom: 8px; | ||
outline: none; | ||
color: var(--material-body-text-color); | ||
font-size: var(--material-body-font-size); | ||
line-height: 24px; | ||
font-family: var(--material-font-family); | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} | ||
:host::before { | ||
line-height: 32px; | ||
} | ||
:host::before { | ||
line-height: 32px; | ||
} | ||
/* Strange gymnastics to make fields vertically align nicely in most cases | ||
/* Strange gymnastics to make fields vertically align nicely in most cases | ||
(no label, with label, without prefix, with prefix, etc.) */ | ||
:host([has-label]) { | ||
padding-top: 24px; | ||
} | ||
:host([has-label]) { | ||
padding-top: 24px; | ||
} | ||
[part="label"]:empty { | ||
display: none; | ||
} | ||
[part='label']:empty { | ||
display: none; | ||
} | ||
[part="label"]:empty::before { | ||
content: " "; | ||
position: absolute; | ||
} | ||
[part='label']:empty::before { | ||
content: '\\00a0'; | ||
position: absolute; | ||
} | ||
[part="input-field"] { | ||
position: relative; | ||
top: -0.2px; /* NOTE(platosha): Adjusts for wrong flex baseline in Chrome & Safari */ | ||
height: 32px; | ||
padding-left: 0; | ||
padding-right: 0; | ||
background-color: transparent; | ||
margin: 0; | ||
} | ||
[part='input-field'] { | ||
position: relative; | ||
top: -0.2px; /* NOTE(platosha): Adjusts for wrong flex baseline in Chrome & Safari */ | ||
height: 32px; | ||
padding-left: 0; | ||
padding-right: 0; | ||
background-color: transparent; | ||
margin: 0; | ||
} | ||
[part="input-field"]::before, | ||
[part="input-field"]::after { | ||
content: ""; | ||
position: absolute; | ||
bottom: 0; | ||
left: 0; | ||
right: 0; | ||
height: 1px; | ||
transform-origin: 50% 0%; | ||
background-color: var(--_material-text-field-input-line-background-color, #000); | ||
opacity: var(--_material-text-field-input-line-opacity, 0.42); | ||
} | ||
[part='input-field']::before, | ||
[part='input-field']::after { | ||
content: ''; | ||
position: absolute; | ||
bottom: 0; | ||
left: 0; | ||
right: 0; | ||
height: 1px; | ||
transform-origin: 50% 0%; | ||
background-color: var(--_material-text-field-input-line-background-color, #000); | ||
opacity: var(--_material-text-field-input-line-opacity, 0.42); | ||
} | ||
[part="input-field"]::after { | ||
background-color: var(--material-primary-color); | ||
opacity: 0; | ||
height: 2px; | ||
bottom: 0; | ||
transform: scaleX(0); | ||
transition: opacity 0.175s; | ||
} | ||
[part='input-field']::after { | ||
background-color: var(--material-primary-color); | ||
opacity: 0; | ||
height: 2px; | ||
bottom: 0; | ||
transform: scaleX(0); | ||
transition: opacity 0.175s; | ||
} | ||
:host([disabled]) [part="label"], | ||
:host([disabled]) [part="value"], | ||
:host([disabled]) [part="input-field"] ::slotted(input), | ||
:host([disabled]) [part="input-field"] ::slotted(textarea), | ||
:host([disabled]) [part="input-field"] ::slotted([part="value"]) { | ||
color: var(--material-disabled-text-color); | ||
-webkit-text-fill-color: var(--material-disabled-text-color); | ||
} | ||
:host([disabled]) [part='label'], | ||
:host([disabled]) [part='value'], | ||
:host([disabled]) [part='input-field'] ::slotted(input), | ||
:host([disabled]) [part='input-field'] ::slotted(textarea), | ||
:host([disabled]) [part='input-field'] ::slotted([part='value']) { | ||
color: var(--material-disabled-text-color); | ||
-webkit-text-fill-color: var(--material-disabled-text-color); | ||
} | ||
[part="value"], | ||
:host([disabled]) [part="input-field"] ::slotted(input), | ||
:host([disabled]) [part="input-field"] ::slotted(textarea), | ||
/* Slotted by vaadin-select-text-field */ | ||
[part="input-field"] ::slotted([part="value"]) { | ||
outline: none; | ||
margin: 0; | ||
border: 0; | ||
border-radius: 0; | ||
padding: 8px 0; | ||
width: 100%; | ||
height: 100%; | ||
font-family: inherit; | ||
font-size: 1em; | ||
line-height: inherit; | ||
color: inherit; | ||
background-color: transparent; | ||
/* Disable default invalid style in Firefox */ | ||
box-shadow: none; | ||
} | ||
[part='value'], | ||
:host([disabled]) [part='input-field'] ::slotted(input), | ||
:host([disabled]) [part='input-field'] ::slotted(textarea), | ||
[part='input-field'] ::slotted([part='value']) { | ||
outline: none; | ||
margin: 0; | ||
border: 0; | ||
border-radius: 0; | ||
padding: 8px 0; | ||
width: 100%; | ||
height: 100%; | ||
font-family: inherit; | ||
font-size: 1em; | ||
line-height: inherit; | ||
color: inherit; | ||
background-color: transparent; | ||
/* Disable default invalid style in Firefox */ | ||
box-shadow: none; | ||
} | ||
/* TODO: the text opacity should be 42%, but the disabled style is 38%. | ||
/* TODO: the text opacity should be 42%, but the disabled style is 38%. | ||
Would need to introduce another property for it if we want to be 100% accurate. */ | ||
[part="value"]::-webkit-input-placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 1; | ||
} | ||
[part='value']::placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 1; | ||
} | ||
[part="value"]:-ms-input-placeholder { | ||
color: var(--material-disabled-text-color); | ||
} | ||
:host([has-label]:not([focused]):not([invalid]):not([theme='always-float-label'])) [part='value']::placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
[part="value"]::-moz-placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.05s; | ||
opacity: 1; | ||
} | ||
/* According to material theme guidelines, helper text should be hidden when error message is set and input is invalid */ | ||
:host([has-helper][invalid][has-error-message]) [part='helper-text'] { | ||
display: none; | ||
} | ||
[part="value"]::placeholder { | ||
color: var(--material-disabled-text-color); | ||
transition: opacity 0.175s 0.1s; | ||
opacity: 1; | ||
} | ||
[part='label'] { | ||
width: 133%; | ||
transition: transform 0.175s, color 0.175s, width 0.175s; | ||
transition-timing-function: ease, ease, step-end; | ||
} | ||
:host([has-label]:not([focused]):not([invalid]):not([theme="always-float-label"])) [part="value"]::-webkit-input-placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
:host([has-helper]) [part='helper-text']::before { | ||
content: ''; | ||
display: block; | ||
height: 6px; | ||
} | ||
:host([has-label]:not([focused]):not([invalid]):not([theme="always-float-label"])) [part="value"]::-moz-placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
[part='helper-text'], | ||
[part='helper-text'] ::slotted(*) { | ||
font-size: 0.75rem; | ||
line-height: 1; | ||
color: var(--material-secondary-text-color); | ||
} | ||
:host([has-label]:not([focused]):not([invalid]):not([theme="always-float-label"])) [part="value"]::placeholder { | ||
opacity: 0; | ||
transition-delay: 0; | ||
} | ||
:host(:hover:not([readonly]):not([invalid])) [part='input-field']::before { | ||
opacity: var(--_material-text-field-input-line-hover-opacity, 0.87); | ||
} | ||
/* IE11 doesn’t show the placeholder when the input is focused, so it’s basically useless for this theme */ | ||
:host([has-label]) [part="value"]:-ms-input-placeholder { | ||
opacity: 0; | ||
} | ||
:host([focused]:not([invalid])) [part='label'] { | ||
color: var(--material-primary-text-color); | ||
} | ||
/* According to material theme guidelines, helper text should be hidden when error message is set and input is invalid */ | ||
:host([has-helper][invalid][has-error-message]) [part="helper-text"] { | ||
display: none; | ||
} | ||
:host([focused]) [part='input-field']::after, | ||
:host([invalid]) [part='input-field']::after { | ||
opacity: 1; | ||
transform: none; | ||
transition: transform 0.175s, opacity 0.175s; | ||
} | ||
[part="label"] { | ||
width: 133%; | ||
transition: transform 0.175s, color 0.175s, width 0.175s; | ||
transition-timing-function: ease, ease, step-end; | ||
} | ||
:host([invalid]) [part='input-field']::after { | ||
background-color: var(--material-error-color); | ||
} | ||
:host([has-helper]) [part="helper-text"]::before { | ||
content: ""; | ||
display: block; | ||
height: 6px; | ||
} | ||
:host([input-prevented]) [part='input-field'] { | ||
color: var(--material-error-text-color); | ||
} | ||
[part="helper-text"], | ||
[part="helper-text"] ::slotted(*) { | ||
font-size: .75rem; | ||
line-height: 1; | ||
color: var(--material-secondary-text-color); | ||
} | ||
:host([disabled]) { | ||
pointer-events: none; | ||
} | ||
/* TODO: using unsupported selector to fix IE11 (even thought the label element is scaled down, | ||
the 133% width still takes the same space as an unscaled element */ | ||
::-ms-backdrop, | ||
.vaadin-text-field-container { | ||
overflow: hidden; | ||
} | ||
:host([disabled]) [part='input-field'] { | ||
color: var(--material-disabled-text-color); | ||
} | ||
/* Same fix for MS Edge ^^ */ | ||
@supports (-ms-ime-align:auto) { | ||
.vaadin-text-field-container { | ||
overflow: hidden; | ||
} | ||
} | ||
:host([disabled]) [part='input-field']::before { | ||
background-color: transparent; | ||
background-image: linear-gradient( | ||
90deg, | ||
var(--_material-text-field-input-line-background-color, #000) 0, | ||
var(--_material-text-field-input-line-background-color, #000) 2px, | ||
transparent 2px | ||
); | ||
background-size: 4px 1px; | ||
background-repeat: repeat-x; | ||
} | ||
:host(:hover:not([readonly]):not([invalid])) [part="input-field"]::before { | ||
opacity: var(--_material-text-field-input-line-hover-opacity, 0.87); | ||
} | ||
/* Only target the visible floating label */ | ||
:host([has-label]:not([has-value]):not([focused]):not([invalid]):not([theme~='always-float-label'])) | ||
[part='label'] { | ||
width: 100%; | ||
transform: scale(1) translateY(24px); | ||
transition-timing-function: ease, ease, step-start; | ||
pointer-events: none; | ||
left: auto; | ||
right: auto; | ||
transition-delay: 0.1s; | ||
} | ||
:host([focused]:not([invalid])) [part="label"] { | ||
color: var(--material-primary-text-color); | ||
} | ||
/* Slotted content */ | ||
:host([focused]) [part="input-field"]::after, | ||
:host([invalid]) [part="input-field"]::after { | ||
opacity: 1; | ||
transform: none; | ||
transition: transform 0.175s, opacity 0.175s; | ||
} | ||
[part='input-field'] ::slotted(*:not([part='value']):not([part\$='-button']):not(input):not(textarea)) { | ||
color: var(--material-secondary-text-color); | ||
} | ||
:host([invalid]) [part="input-field"]::after { | ||
background-color: var(--material-error-color); | ||
} | ||
[part='clear-button']::before { | ||
content: var(--material-icons-clear); | ||
} | ||
:host([input-prevented]) [part="input-field"] { | ||
color: var(--material-error-text-color); | ||
} | ||
/* RTL specific styles */ | ||
:host([disabled]) { | ||
pointer-events: none; | ||
} | ||
:host([disabled]) [part="input-field"] { | ||
color: var(--material-disabled-text-color); | ||
} | ||
:host([disabled]) [part="input-field"]::before { | ||
background-color: transparent; | ||
background-image: linear-gradient(90deg, var(--_material-text-field-input-line-background-color, #000) 0, var(--_material-text-field-input-line-background-color, #000) 2px, transparent 2px); | ||
background-size: 4px 1px; | ||
background-repeat: repeat-x; | ||
} | ||
/* Only target the visible floating label */ | ||
:host([has-label]:not([has-value]):not([focused]):not([invalid]):not([theme~="always-float-label"])) [part="label"] { | ||
width: 100%; | ||
/* IE11 doesn’t work with calc inside the translate function, so we need to have a fixed pixel value instead of 50% + 16px */ | ||
transform: scale(1) translateY(24px); | ||
transition-timing-function: ease, ease, step-start; | ||
pointer-events: none; | ||
left: auto; | ||
right: auto; | ||
transition-delay: 0.1s; | ||
} | ||
/* Slotted content */ | ||
[part="input-field"] ::slotted(*:not([part="value"]):not([part\$="-button"]):not(input):not(textarea)) { | ||
color: var(--material-secondary-text-color); | ||
} | ||
[part="clear-button"]::before { | ||
content: var(--material-icons-clear); | ||
} | ||
/* RTL specific styles */ | ||
:host([disabled][dir="rtl"]) [part="input-field"]::before { | ||
background-image: linear-gradient(-90deg, var(--_material-text-field-input-line-background-color, #000) 0, var(--_material-text-field-input-line-background-color, #000) 2px, transparent 2px); | ||
} | ||
</style> | ||
</template> | ||
</dom-module>`; | ||
document.head.appendChild($_documentContainer.content); | ||
:host([disabled][dir='rtl']) [part='input-field']::before { | ||
background-image: linear-gradient( | ||
-90deg, | ||
var(--_material-text-field-input-line-background-color, #000) 0, | ||
var(--_material-text-field-input-line-background-color, #000) 2px, | ||
transparent 2px | ||
); | ||
} | ||
`, | ||
{ moduleId: 'material-text-field', include: ['material-required-field', 'material-field-button'] } | ||
); |
@@ -1,14 +0,1 @@ | ||
/** | ||
* 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-email-field.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-email-field.js'; |
@@ -1,14 +0,1 @@ | ||
/** | ||
* 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-integer-field.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-integer-field.js'; |
@@ -1,14 +0,1 @@ | ||
/** | ||
* 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-number-field.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-number-field.js'; |
@@ -1,14 +0,1 @@ | ||
/** | ||
* 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-password-field.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-password-field.js'; |
@@ -1,14 +0,1 @@ | ||
/** | ||
* 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-text-area.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-text-area.js'; |
@@ -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-text-field.js | ||
*/ | ||
// tslint:disable:variable-name Describing an API that's defined elsewhere. | ||
export * from './src/vaadin-text-field.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
121082
27
2996
1
134