@logo-elements/tag-input
Version:
Input control for a collection of tags
222 lines (191 loc) • 6.32 kB
JavaScript
import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';
import '@polymer/polymer/lib/elements/dom-repeat.js';
import '@vaadin/text-field/vaadin-text-field.js';
import '@vaadin/icon/vaadin-icon.js';
import '@vaadin/button/vaadin-button.js';
import '@logo-elements/leds/leds.js';
import '@logo-elements/leds/leds-iconset.js';
/**
* `paper-tags-input`
* Material Design input control for a collection of tags
*
* @customElement
* @polymer
* @demo demo/index.html
*/
class LogoElementsTagInput extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
}
:host[hidden] {
display: none ;
}
.tags-list {
display: flex;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
max-width: 100%;
}
.tag-item {
margin: 4px 2px;
white-space: nowrap;
display: inline-flex;
align-items: center;
justify-content: space-between;
flex-wrap: nowrap;
padding: 4px 8px;
color: var(--lumo-contrast-90pct);
font-size: 12px;
line-height: 16px;
border-radius: var(--lumo-border-radius);
background-color: var(--lumo-primary-contrast-color);
}
.tags-list.activated div:last-of-type {
border: 2px solid var(--lumo-primary-color-50pct);
}
input {
min-width: 15%;
max-width: calc(100% - 44px);
height: 32px ;
}
.tag-item vaadin-icon {
margin-left: 4px;
cursor: pointer;
width: var(--lumo-icon-size-s);
height: var(--lumo-icon-size-s);
}
vaadin-text-field {
width: 100%;
}
.tag-input-container-wrapper {
flex-wrap: wrap;
}
</style>
<vaadin-text-field label="[[label]]" on-keyup="_onInputKeydown" on-blur="_onBlur">
<div class="tags-list" slot="prefix">
<template is="dom-repeat" items="[[tags]]">
<div class="tag-item">
[[item]]
<vaadin-icon icon="leds:cross" theme="small" on-click="_onTagRemoveClicked"></vaadin-icon>
</div>
</template>
</div>
<template is="dom-if" if="{{tags.length > 0}}" restamp>
<vaadin-button slot="suffix" theme="small tertiary icon" on-click="_onClearAllClicked">
<vaadin-icon icon="leds:trash"></vaadin-icon>
</vaadin-button>
</template>
</vaadin-text-field>
`;
}
static get is() {
return 'logo-elements-tag-input';
}
static get properties() {
return {
label: {
type: String,
value: 'Tags'
},
tags: {
type: Array,
notify: true,
value: function () {
return [];
}
}
};
}
addTag(tag) {
if (this.tags === null) {
this.tags = [];
}
var trimmedTag = tag.replace(/^\s+/, '').replace(/\s+$/, '');
if (trimmedTag !== '') {
var tagIndex = this.tags.indexOf(trimmedTag);
if (tagIndex === -1) {
this.push('tags', trimmedTag);
this._setContainerWrapper();
}
}
}
removeTag(tag) {
if (this.tags === null) {
return;
}
var tagIndex = this.tags.indexOf(tag);
if (tagIndex > -1) {
this.splice('tags', tagIndex, 1);
this._setContainerWrapper();
}
}
_setContainerWrapper() {
const tagListBase = this.shadowRoot.querySelector('.tags-list');
const tagInputElement = this.shadowRoot.querySelector('vaadin-text-field').shadowRoot;
const tagInputContainer = tagInputElement.querySelector('vaadin-input-container');
let percent = 0;
let styleStatus;
setTimeout(() => {
percent = Math.round((tagListBase.clientWidth * 100) / this.clientWidth);
styleStatus = tagInputContainer.hasAttribute('style');
if (percent > 75) {
if (!styleStatus) {
tagInputContainer.setAttribute('style', 'flex-wrap:wrap');
}
} else if (percent < 75) {
if (styleStatus) {
tagInputContainer.removeAttribute('style');
}
}
}, 50);
}
_onClearAllClicked() {
this.tags = [];
this._setContainerWrapper();
}
_onTagRemoveClicked(e) {
this.removeTag(e.model.item);
}
_onInputKeydown(e) {
if (e.keyCode === 13) {
this.addTag(e.target.value.toLowerCase());
e.target.value = '';
} else if (e.keyCode === 186 || e.keyCode === 188) {
this.addTag(e.target.value.slice(0, -1).toLowerCase());
e.target.value = '';
} else if (e.keyCode === 8) {
if (e.target.value.length < 1) {
if (this._checkSelected()) {
this.shadowRoot.querySelector('.tags-list').className = 'tags-list';
this.tags = this.tags.slice(0, -1);
this._setContainerWrapper();
} else {
this.shadowRoot.querySelector('.tags-list').className = 'tags-list activated';
}
}
}
}
_checkSelected() {
const tagListBase = this.shadowRoot.querySelector('.tags-list');
return tagListBase.className.includes('activated');
}
_onBlur(e) {
const tagInputElement = this.shadowRoot.querySelector('vaadin-text-field');
const tagInput = tagInputElement.querySelector('input');
if (tagInput.value.length) {
this.addTag(tagInput.value);
tagInput.value = '';
}
}
_isTags() {
return this.tags.length > 0;
}
ready() {
super.ready();
}
}
window.customElements.define(LogoElementsTagInput.is, LogoElementsTagInput);