Fixes and improvements
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tp/tp-tag-input",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "",
|
||||
"main": "tp-tag-input.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -47,11 +47,13 @@ class TpTagInputPopup extends DomQuery(EventHelpers(LitElement)) {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { selection } = this;
|
||||
|
||||
return html`
|
||||
<div class="wrap">
|
||||
<div id="list" @click=${this.onItemClick}>
|
||||
${this.filteredItems.map(item => html`
|
||||
<div class="item" .value=${item.value} ?selected=${item.value === this.value}>${item.label}</div>
|
||||
<div id="list" @click=${this._onItemClick}>
|
||||
${this.filteredItems.map((item, idx) => html`
|
||||
<div class="item" .item=${item} ?selected=${item.value === this.value || idx === selection}>${item.label}</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,12 +105,12 @@ class TpTagInputPopup extends DomQuery(EventHelpers(LitElement)) {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.listen(this.$.list, 'down', '_onItemTap');
|
||||
this.listen(this.$.list, 'mousedown', '_onItemClick');
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.unlisten(this.$.list, 'down', '_onItemTap');
|
||||
this.unlisten(this.$.list, 'mousedown', '_onItemClick');
|
||||
}
|
||||
|
||||
show() {
|
||||
@@ -132,11 +134,13 @@ class TpTagInputPopup extends DomQuery(EventHelpers(LitElement)) {
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
onItemClick(e) {
|
||||
_onItemClick(e) {
|
||||
const item = closest(e.composedPath()[0], '.item', true);
|
||||
if (!item) return;
|
||||
this.value = item.value;
|
||||
this.value = item.item;
|
||||
this.dispatchEvent(new CustomEvent('selection-changed', { detail: this.value, bubbles: true, composed: true }));
|
||||
this.hide();
|
||||
this.target.focus();
|
||||
}
|
||||
|
||||
_filterItemsByTerm() {
|
||||
@@ -176,7 +180,8 @@ class TpTagInputPopup extends DomQuery(EventHelpers(LitElement)) {
|
||||
case 13: // Enter
|
||||
const item = this.$.list.querySelector('.item[selected]');
|
||||
if (item) {
|
||||
this.value = this.$.itemRepeater.itemForElement(item);
|
||||
this.value = item.item;
|
||||
this.dispatchEvent(new CustomEvent('selection-changed', { detail: this.value, bubbles: true, composed: true }));
|
||||
}
|
||||
this.hide();
|
||||
e.preventDefault();
|
||||
@@ -190,16 +195,6 @@ class TpTagInputPopup extends DomQuery(EventHelpers(LitElement)) {
|
||||
}
|
||||
}
|
||||
|
||||
_onItemTap(e) {
|
||||
const item = e.composedPath()[0];
|
||||
|
||||
if (item.classList.contains('item')) {
|
||||
this.value = this.$.itemRepeater.itemForElement(item);
|
||||
this.hide();
|
||||
this.target.focus();
|
||||
}
|
||||
}
|
||||
|
||||
_scrollIntoView(element, container) {
|
||||
if (!element) {
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,8 @@ import { EventHelpers } from '@tp/helpers/event-helpers.js';
|
||||
import { DomQuery } from '@tp/helpers/dom-query.js';
|
||||
import { reach } from '@tp/helpers/reach.js';
|
||||
import { debounce } from '@tp/helpers/debounce.js';
|
||||
import { clone } from '@tp/helpers/clone.js';
|
||||
import { closest } from '@tp/helpers/closest.js';
|
||||
|
||||
const mixins = [
|
||||
FormElement,
|
||||
@@ -52,13 +54,15 @@ class TpTagInput extends BaseElement {
|
||||
tp-input {
|
||||
min-height: 15px;
|
||||
outline: none;
|
||||
margin: 5px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
tp-input::part(wrap) {
|
||||
border: none;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:host(.has-items) tp-input {
|
||||
@@ -94,20 +98,20 @@ class TpTagInput extends BaseElement {
|
||||
|
||||
render() {
|
||||
const value = this.value || [];
|
||||
|
||||
|
||||
return html`
|
||||
<div class="wrap" part="wrap">
|
||||
<div class="wrap" part="wrap" @click=${this._onClick}>
|
||||
${value.map(item => html`
|
||||
<div class="item">
|
||||
<tp-icon .icon=${TpTagInput.icon}></tp-icon>
|
||||
<div class="item" .item=${item}>
|
||||
<tp-icon class="remove-icon" .icon=${TpTagInput.icon}></tp-icon>
|
||||
${item.label}
|
||||
</div>
|
||||
`)}
|
||||
<tp-input id="input" .validator=${this.validator} @input=${e => this._inputChanged(e)} required>
|
||||
<input type="text" id="innerInput" .pattern=${this.pattern}>
|
||||
<tp-input id="input" .validator=${this.validator} @keydown=${e => this._inputChanged(e)} required>
|
||||
<input type="text" id="innerInput" .pattern=${this.pattern} autocomplete="off">
|
||||
</tp-input>
|
||||
</div>
|
||||
<tp-tag-input-popup id="autoCpl" .items=${this.items} @selection-changed=${e => this._itemSelected(e.detail.item)}></tp-tag-input-popup>
|
||||
<tp-tag-input-popup id="autoCpl" .items=${this.items} @selection-changed=${e => this._itemSelected(e.detail)}></tp-tag-input-popup>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -173,10 +177,17 @@ class TpTagInput extends BaseElement {
|
||||
return true;
|
||||
}
|
||||
|
||||
_inputChanged(e) {
|
||||
this._input = e.target.value;
|
||||
_onClick(e) {
|
||||
if (closest(e.composedPath()[0], '.remove-icon', true)) {
|
||||
const item = closest(e.composedPath()[0], '.item', true);
|
||||
if (!item) return;
|
||||
this.value = this.value.filter(i => i.value !== item.item.value);
|
||||
}
|
||||
}
|
||||
|
||||
_inputChanged(e) {
|
||||
this._input = this.$.input.value;
|
||||
|
||||
console.log('input changed');
|
||||
if (this.api && this._input.length > 2) {
|
||||
this._callFilterApiDebounced();
|
||||
return;
|
||||
@@ -217,14 +228,13 @@ class TpTagInput extends BaseElement {
|
||||
_itemSelected(item) {
|
||||
if (item !== null) {
|
||||
if (this.allowDuplicates || !this._isAlreadySelected(item.label)) {
|
||||
// Need to clone the item so polymer won't get confused if the user removes duplicated entries.
|
||||
if (Array.isArray(this.value)) {
|
||||
this.push('value', this._clone(item));
|
||||
if (!Array.isArray(this.value)) {
|
||||
this.value = [ clone(item) ];
|
||||
} else {
|
||||
this.set('value', [ this._clone(item) ]);
|
||||
this.value = [...this.value, clone(item)];
|
||||
}
|
||||
}
|
||||
this._input = '';
|
||||
this._clearInput();
|
||||
this.$.autoCpl.selection = null;
|
||||
this.$.autoCpl.value = null;
|
||||
}
|
||||
@@ -232,7 +242,7 @@ class TpTagInput extends BaseElement {
|
||||
|
||||
_inputBlur() {
|
||||
if (!this._tryToAddItem()) {
|
||||
this._input = '';
|
||||
this._clearInput();
|
||||
this.$.autoCpl.selection = null;
|
||||
this.$.autoCpl.value = null;
|
||||
this.$.autoCpl.hide();
|
||||
@@ -260,7 +270,7 @@ class TpTagInput extends BaseElement {
|
||||
|
||||
if (this._keyboardEventMatchesKeys(e, 'backspace')) {
|
||||
if (this._input === '' && this.value) {
|
||||
this.pop('value');
|
||||
this.value = this.value.slice(0, -1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +324,7 @@ class TpTagInput extends BaseElement {
|
||||
const keyList = keys.split(' ');
|
||||
|
||||
for (const key of keyList) {
|
||||
if (key === e.key) {
|
||||
if (key.toLowerCase() === e.key.toLowerCase()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -374,7 +384,10 @@ class TpTagInput extends BaseElement {
|
||||
this.$.input.focus();
|
||||
}
|
||||
|
||||
|
||||
_clearInput() {
|
||||
this._input = '';
|
||||
this.$.input.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('tp-tag-input', TpTagInput);
|
||||
|
||||
Reference in New Issue
Block a user