UNPKG

@logo-elements/tag-input

Version:

Input control for a collection of tags

222 lines (191 loc) 6.32 kB
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 !important; } .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 !important; } .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);