UNPKG

ngx-tags

Version:
823 lines (811 loc) 27.7 kB
import { BrowserModule } from '@angular/platform-browser'; import { __extends } from 'tslib'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { Subject } from 'rxjs'; import { filter, map, takeUntil } from 'rxjs/operators'; import { Component, ViewEncapsulation, Input, EventEmitter, Output, forwardRef, HostListener, ViewChild, ElementRef, Directive, NgModule } from '@angular/core'; /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var noop = (/** * @return {?} */ function () { }); var NgxTagsValueAccessor = /** @class */ (function () { function NgxTagsValueAccessor() { this.onTouchedCallback = noop; this.onChangeCallback = noop; this._value = []; } Object.defineProperty(NgxTagsValueAccessor.prototype, "value", { get: /** * @return {?} */ function () { return this._value; }, // set accessor including call the onchange callback set: // set accessor including call the onchange callback /** * @param {?} v * @return {?} */ function (v) { if (v !== this._value) { this._value = v; this.onChangeCallback(v); } }, enumerable: true, configurable: true }); /** * @param {?} value * @return {?} */ NgxTagsValueAccessor.prototype.writeValue = /** * @param {?} value * @return {?} */ function (value) { if (value !== this._value) { this._value = value; } }; // From ControlValueAccessor interface // From ControlValueAccessor interface /** * @param {?} fn * @return {?} */ NgxTagsValueAccessor.prototype.registerOnChange = // From ControlValueAccessor interface /** * @param {?} fn * @return {?} */ function (fn) { this.onChangeCallback = fn; }; // From ControlValueAccessor interface // From ControlValueAccessor interface /** * @param {?} fn * @return {?} */ NgxTagsValueAccessor.prototype.registerOnTouched = // From ControlValueAccessor interface /** * @param {?} fn * @return {?} */ function (fn) { this.onTouchedCallback = fn; }; /** * @param {?} isDisabled * @return {?} */ NgxTagsValueAccessor.prototype.setDisabledState = /** * @param {?} isDisabled * @return {?} */ function (isDisabled) { this.disabled = isDisabled; }; return NgxTagsValueAccessor; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* tslint:disable:component-selector */ var NgTagComponent = /** @class */ (function (_super) { __extends(NgTagComponent, _super); function NgTagComponent() { var _this = _super.call(this) || this; _this.isMenuOpen = false; _this.inputTag = ''; _this.placeholder = 'add a tag'; _this.actionTypes = { 'add': 'add', 'delete': 'delete', 'update': 'update', }; _this.tagLabel = 'tagLabel'; _this.tagValue = 'tagValue'; _this.clearOnBlur = true; _this.allowDupes = false; _this.onlyFromDropdown = false; _this.tagEditable = false; _this.change = new EventEmitter(); return _this; } Object.defineProperty(NgTagComponent.prototype, "tags", { get: /** * @return {?} */ function () { return this._value; }, enumerable: true, configurable: true }); /** * @return {?} */ NgTagComponent.prototype.whenClickedOut = /** * @return {?} */ function () { this.isMenuOpen = false; }; /** * @param {?} e * @return {?} */ NgTagComponent.prototype.enter = /** * @param {?} e * @return {?} */ function (e) { if (this.onlyFromDropdown) { e.stopProgation(); return false; } if (this.inputTag.trim()) { this.addToModal(this.inputTag); this.clearInput(); } }; /** * @param {?} $event * @return {?} */ NgTagComponent.prototype.save = /** * @param {?} $event * @return {?} */ function ($event) { this._value[$event.index][this.tagLabel] = $event.item.trim(); this.emitChange(this.actionTypes.update, this._value[$event.index]); }; /** * @return {?} */ NgTagComponent.prototype.blur = /** * @return {?} */ function () { if (this.clearOnBlur) { this.clearInput(); } }; /** * @return {?} */ NgTagComponent.prototype.clearInput = /** * @return {?} */ function () { this.inputTag = ''; }; /** * @param {?} indx * @return {?} */ NgTagComponent.prototype.del = /** * @param {?} indx * @return {?} */ function (indx) { if (this.canDeleteTags) { this._value.splice(indx, 1); this.emitChange(this.actionTypes.delete, this._value); } }; /** * @return {?} */ NgTagComponent.prototype.backspace = /** * @return {?} */ function () { if (!this.removeLastOnBackspace && !this.inputTag.trim()) { this._value.pop(); } }; /** * @return {?} */ NgTagComponent.prototype.input = /** * @return {?} */ function () { /** @type {?} */ var _inputTag = this.inputTag.trim(); if (_inputTag) { this._options = this.filterByInput(this.options); this.isMenuOpen = true; } }; /** * @private * @param {?} items * @return {?} */ NgTagComponent.prototype.filterByInput = /** * @private * @param {?} items * @return {?} */ function (items) { var _this = this; return items.filter((/** * @param {?} item * @return {?} */ function (item) { /** @type {?} */ var val = (typeof item !== 'string' && _this.tagLabel) ? item[_this.tagLabel] : item; if (val.toLowerCase().includes(_this.inputTag.trim().toLowerCase())) { return true; } return false; })); }; /** * @param {?} item * @return {?} */ NgTagComponent.prototype.select = /** * @param {?} item * @return {?} */ function (item) { this.addToModal(item.value); this.clearInput(); this.whenClickedOut(); }; /** * @private * @param {?} item * @return {?} */ NgTagComponent.prototype.addToModal = /** * @private * @param {?} item * @return {?} */ function (item) { if (this.hasReachedMaxTags()) { return; } /** @type {?} */ var itemToAdd = this.createTag(item); if (!this.allowDupes) { if (this.isDuplicate(itemToAdd)) { this._value.push(itemToAdd); this.emitChange(this.actionTypes.add, itemToAdd); } } else { this._value.push(itemToAdd); this.emitChange(this.actionTypes.add, itemToAdd); } }; /** * @private * @param {?} tag * @return {?} */ NgTagComponent.prototype.createTag = /** * @private * @param {?} tag * @return {?} */ function (tag) { var _a; if (typeof tag !== 'string') { return tag; } else { return _a = {}, _a[this.tagValue] = tag, _a[this.tagLabel] = tag, _a; } }; /** * @return {?} */ NgTagComponent.prototype.hasReachedMaxTags = /** * @return {?} */ function () { return this.maxTags ? (this.maxTags === this._value.length) : false; }; /** * @param {?} item * @return {?} */ NgTagComponent.prototype.isDuplicate = /** * @param {?} item * @return {?} */ function (item) { return this._value.indexOf(item) === -1 ? true : false; }; /** * @private * @param {?} type * @param {?} value * @return {?} */ NgTagComponent.prototype.emitChange = /** * @private * @param {?} type * @param {?} value * @return {?} */ function (type, value) { this.change.emit({ type: type, value: value }); }; NgTagComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-tags', template: "<section class=\"ngx-tags\">\n <section class=\"tag-container\" [closeMenu]=\"isMenuOpen\" (whenClickedOut)=\"whenClickedOut()\" [ngClass]=\"{'ngx-tags-disabled':disabled}\" >\n <span class=\"tag\" *ngFor=\"let tag of tags;let $index = index\" [ngClass]=\"{'tag-readonly': tag.readonly}\">\n <ng-container [ngTemplateOutletContext]=\"{ item: tag, index: $index,tagLabel:tagLabel,tagEditable:tagEditable }\"\n [ngTemplateOutlet]=\"tagTemplate ? tagTemplate:defaultTagItemTemplate\">\n </ng-container>\n <a href=\"#\" class=\"close\" [hidden]=\"!canDeleteTags\" (click)=\"del($index)\"></a>\n </span>\n <span class=\"tag-input\" >\n <input type=\"text\" *ngIf=\"canAddTags\" [(ngModel)]=\"inputTag\" (blur)=\"blur()\"\n [placeholder]=\"placeholder\" (keydown.enter)=\"enter($event)\" (keydown.backspace)=\"backspace()\"\n (input)=\"input()\">\n </span>\n </section>\n <ngx-tags-dropdown [items]=\"_options\" [dropdownItemTemplate]=\"dropdownItemTemplate\" [tagLabel]=\"tagLabel\" [inputTag]=\"inputTag\" (select)=\"select($event) \" [hidden]=\"!isMenuOpen\"></ngx-tags-dropdown>\n</section>\n\n<ng-template #defaultTagItemTemplate let-item=\"item\" let-tagLabel=\"tagLabel\" let-input=\"input\" let-tagEditable=\"tagEditable\" let-index=\"index\">\n <ngx-tag [item]=\"item\" [tagEditable]=\"tagEditable\" [tagLabel]=\"tagLabel\" [index]=\"index\" (change)=\"save($event)\"></ngx-tag>\n</ng-template>", providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ function () { return NgTagComponent; })), multi: true }], encapsulation: ViewEncapsulation.None, styles: [".ngx-tags{position:relative;display:block;width:100%}.ngx-tags .ngx-tags-disabled{opacity:.7;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.ngx-tags .tag-container{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;box-sizing:border-box}.ngx-tags .tag-container .tag,.ngx-tags .tag-container .tag-input{background:#9dc1ff;padding:.25rem;border-radius:.25rem;margin-right:.25rem;display:inline-flex;align-items:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.ngx-tags .tag-container .tag-input{background:#fff}.ngx-tags .tag-container .tag-input input{border:none;outline:0;min-width:140px;max-width:100%;height:100%;margin-left:4px;box-sizing:border-box;display:inline-block}.ngx-tags .tag-container .tag-readonly{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;opacity:.7}.ngx-tags .tag-container .close{position:relative;display:inline-block;width:10px;height:10px;opacity:.8}.ngx-tags .tag-container .close:hover{opacity:1}.ngx-tags .tag-container .close:after,.ngx-tags .tag-container .close:before{position:absolute;left:3px;content:' ';height:11px;width:2px;background-color:#333}.ngx-tags .tag-container .close:before{transform:rotate(45deg)}.ngx-tags .tag-container .close:after{transform:rotate(-45deg)}.item:hover,.keynav-active{background:#e1e4e8}.dropdown{margin:0;padding:0;border:1px solid #e1e4e8;box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12);border-radius:2px;max-height:200px;overflow-y:auto;position:absolute;background:#fff;display:block;width:100%;z-index:1}.item{padding:4px 2px;display:block}"] }] } ]; /** @nocollapse */ NgTagComponent.ctorParameters = function () { return []; }; NgTagComponent.propDecorators = { tagTemplate: [{ type: Input }], dropdownItemTemplate: [{ type: Input }], options: [{ type: Input }], maxTags: [{ type: Input }], tagLabel: [{ type: Input }], tagValue: [{ type: Input }], removeLastOnBackspace: [{ type: Input }], canDeleteTags: [{ type: Input }], canAddTags: [{ type: Input }], clearOnBlur: [{ type: Input }], allowDupes: [{ type: Input }], onlyFromDropdown: [{ type: Input }], tagEditable: [{ type: Input }], change: [{ type: Output }] }; return NgTagComponent; }(NgxTagsValueAccessor)); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var keyCodeConstant = { UP: 'ArrowUp', DOWN: 'ArrowDown', LEFT: 'ArrowLeft', RIGHT: 'ArrowRight', ESC: 'Escape', ENTER: 'Enter', }; /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* tslint:disable:component-selector */ var DropdownComponent = /** @class */ (function () { function DropdownComponent() { this._focusIndex = -1; this.navKey$ = new Subject(); this.destroy$ = new Subject(); this.select = new EventEmitter(); } /** * @param {?} event * @return {?} */ DropdownComponent.prototype.onKeydownHandler = /** * @param {?} event * @return {?} */ function (event) { this.navKey$.next(event); }; /** * @return {?} */ DropdownComponent.prototype.ngOnInit = /** * @return {?} */ function () { this.navDropdown(); this.selectOnEnter(); }; /** * @param {?} change * @return {?} */ DropdownComponent.prototype.ngOnChanges = /** * @param {?} change * @return {?} */ function (change) { if (change.items) { this._focusIndex = 0; } }; /** * @return {?} */ DropdownComponent.prototype.selectOnEnter = /** * @return {?} */ function () { var _this = this; this.navKey$ .pipe(map((/** * @param {?} e * @return {?} */ function (e) { return e.key; })), filter((/** * @param {?} key * @return {?} */ function (key) { return _this.items && _this.items.length; })), filter((/** * @param {?} key * @return {?} */ function (key) { return key === keyCodeConstant.ENTER; })), takeUntil(this.destroy$)) .subscribe((/** * @param {?} key * @return {?} */ function (key) { _this.emitSelectedItem(_this.items[_this._focusIndex], _this._focusIndex); })); }; /** * @return {?} */ DropdownComponent.prototype.navDropdown = /** * @return {?} */ function () { var _this = this; this.navKey$ .pipe(map((/** * @param {?} e * @return {?} */ function (e) { return e.key; })), filter((/** * @param {?} key * @return {?} */ function (key) { return _this.items && _this.items.length; })), filter((/** * @param {?} key * @return {?} */ function (key) { return key === keyCodeConstant.DOWN || key === keyCodeConstant.UP; })), takeUntil(this.destroy$)) .subscribe((/** * @param {?} key * @return {?} */ function (key) { if (_this.items.length) { /** @type {?} */ var tempFocusIndex = 0; if (key === keyCodeConstant.DOWN) { tempFocusIndex = _this._focusIndex + 1; tempFocusIndex = (tempFocusIndex === _this.items.length) ? 0 : tempFocusIndex; } else if (key === keyCodeConstant.UP) { tempFocusIndex = _this._focusIndex - 1; tempFocusIndex = (tempFocusIndex === -1) ? _this.items.length - 1 : tempFocusIndex; } _this._focusIndex = tempFocusIndex; } })); }; /** * @param {?} item * @param {?} index * @return {?} */ DropdownComponent.prototype.emitSelectedItem = /** * @param {?} item * @param {?} index * @return {?} */ function (item, index) { this.select.emit({ key: index, value: item }); }; /** * @return {?} */ DropdownComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.destroy$.next(true); this.destroy$.unsubscribe(); }; DropdownComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-tags-dropdown', template: "<article class=\"dropdown\" #dropdown tabindex=\"0\">\n\t<a class=\"item\" *ngFor=\"let item of items;let $index =index\" (click)=\"emitSelectedItem(item,$index)\" [ngClass]=\"{'keynav-active':$index == _focusIndex}\" [InView]=\"$index == _focusIndex\" >\n <ng-container \n [ngTemplateOutletContext]=\"{ \n item: item, \n label: tagLabel, \n input: inputTag, \n index: index }\"\n [ngTemplateOutlet]=\"dropdownItemTemplate ? dropdownItemTemplate : defaultDropdownItemTemplate\">\n </ng-container>\n </a>\n</article>\n<ng-template \n #defaultDropdownItemTemplate\n let-item=\"item\"\n let-label=\"label\"\n let-input=\"input\"\n let-index=\"index\">\n <span > {{item[label]}}</span>\n</ng-template>\n", encapsulation: ViewEncapsulation.None }] } ]; /** @nocollapse */ DropdownComponent.ctorParameters = function () { return []; }; DropdownComponent.propDecorators = { items: [{ type: Input }], tagLabel: [{ type: Input }], inputTag: [{ type: Input }], dropdownItemTemplate: [{ type: Input }], select: [{ type: Output }], onKeydownHandler: [{ type: HostListener, args: ['document:keydown', ['$event'],] }] }; return DropdownComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* tslint:disable:component-selector */ var TagComponent = /** @class */ (function () { function TagComponent() { this.change = new EventEmitter(); } Object.defineProperty(TagComponent.prototype, "isEditable", { get: /** * @return {?} */ function () { return this.tagContent.nativeElement.contentEditable; }, set: /** * @param {?} flag * @return {?} */ function (flag) { this.tagContent.nativeElement.contentEditable = flag; }, enumerable: true, configurable: true }); /** * @param {?} e * @return {?} */ TagComponent.prototype.dbclick = /** * @param {?} e * @return {?} */ function (e) { if (this.tagEditable) { this.isEditable = true; } }; /** * @param {?} event * @return {?} */ TagComponent.prototype.keydownHandler = /** * @param {?} event * @return {?} */ function (event) { if (this.isEditable && event.key === keyCodeConstant.ESC) { this.toggleEditMode(); } }; /** * @return {?} */ TagComponent.prototype.toggleEditMode = /** * @return {?} */ function () { this.isEditable = !this.isEditable; }; /** * @param {?} e * @return {?} */ TagComponent.prototype.save = /** * @param {?} e * @return {?} */ function (e) { e.preventDefault(); /** @type {?} */ var tagText = this.tagContent.nativeElement.innerHTML.trim(); if (tagText) { this.change.emit({ item: tagText, index: this.index }); } this.toggleEditMode(); }; /** * @return {?} */ TagComponent.prototype.blur = /** * @return {?} */ function () { this.isEditable = false; }; TagComponent.decorators = [ { type: Component, args: [{ selector: 'ngx-tag', template: "<span (keydown.enter)=\"save($event)\" contenteditable=\"false\" (blur)=\"blur()\" #tagContent>\n {{(tagLabel) ? item[tagLabel] : item }}\n</span>\n\n\n" }] } ]; /** @nocollapse */ TagComponent.ctorParameters = function () { return []; }; TagComponent.propDecorators = { item: [{ type: Input }], tagLabel: [{ type: Input }], index: [{ type: Input }], tagEditable: [{ type: Input }], change: [{ type: Output }], tagContent: [{ type: ViewChild, args: ['tagContent',] }], dbclick: [{ type: HostListener, args: ['dblclick', ['$event'],] }], keydownHandler: [{ type: HostListener, args: ['keydown', ['$event'],] }] }; return TagComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* tslint:disable:directive-selector */ var CloseMenuDirective = /** @class */ (function () { function CloseMenuDirective($elem) { this.$elem = $elem; this.whenClickedOut = new EventEmitter(); } /** * @param {?} e * @return {?} */ CloseMenuDirective.prototype.onMouseUp = /** * @param {?} e * @return {?} */ function (e) { if (this.closeMenu) { this.isOutside(e); } }; /** * @param {?} e * @return {?} */ CloseMenuDirective.prototype.isOutside = /** * @param {?} e * @return {?} */ function (e) { if (!this.$elem.nativeElement.contains(event.target) && this.$elem.nativeElement.style.display !== 'none') { this.whenClickedOut.emit(); } }; CloseMenuDirective.decorators = [ { type: Directive, args: [{ selector: '[closeMenu]' },] } ]; /** @nocollapse */ CloseMenuDirective.ctorParameters = function () { return [ { type: ElementRef } ]; }; CloseMenuDirective.propDecorators = { whenClickedOut: [{ type: Output }], closeMenu: [{ type: Input }], onMouseUp: [{ type: HostListener, args: ['document:mouseup', ['$event'],] }] }; return CloseMenuDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* tslint:disable:directive-selector */ var InViewDirective = /** @class */ (function () { function InViewDirective(el) { this.el = el; this.dropdown = this.el.nativeElement.closest('.dropdown'); } /** * @param {?} values * @return {?} */ InViewDirective.prototype.ngOnChanges = /** * @param {?} values * @return {?} */ function (values) { if (values.InView.currentValue) { this.setInView(); } }; /** * @return {?} */ InViewDirective.prototype.setInView = /** * @return {?} */ function () { /** @type {?} */ var dropdown = this.el.nativeElement.closest('.dropdown'); /** @type {?} */ var currentPos = this.el.nativeElement.offsetTop; /** @type {?} */ var dropdownScrollPos = dropdown.scrollTop; /** @type {?} */ var dropdownHeight = dropdown.offsetHeight; /** @type {?} */ var elHeight = this.el.nativeElement.offsetHeight; if ((currentPos + elHeight) > (dropdownScrollPos + dropdownHeight)) { dropdown.scrollTop = currentPos; } else if (dropdownScrollPos > currentPos) { dropdown.scrollTop = currentPos; } }; InViewDirective.decorators = [ { type: Directive, args: [{ selector: '[InView]' },] } ]; /** @nocollapse */ InViewDirective.ctorParameters = function () { return [ { type: ElementRef } ]; }; InViewDirective.propDecorators = { InView: [{ type: Input }] }; return InViewDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var NgxTagsModule = /** @class */ (function () { function NgxTagsModule() { } NgxTagsModule.decorators = [ { type: NgModule, args: [{ imports: [BrowserModule, FormsModule], declarations: [NgTagComponent, DropdownComponent, TagComponent, CloseMenuDirective, InViewDirective], exports: [NgTagComponent] },] } ]; return NgxTagsModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { NgxTagsModule, DropdownComponent as ɵc, TagComponent as ɵd, CloseMenuDirective as ɵe, InViewDirective as ɵf, NgTagComponent as ɵa, NgxTagsValueAccessor as ɵb }; //# sourceMappingURL=ngx-tags.js.map