UNPKG

ng-devui

Version:

DevUI components based on Angular

803 lines (796 loc) 50 kB
import { __decorate, __metadata } from 'tslib'; import * as i5 from '@angular/cdk/overlay'; import { CdkConnectedOverlay, CdkOverlayOrigin, OverlayModule } from '@angular/cdk/overlay'; import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Component, Input, Output, ViewChild, forwardRef, Directive, HostBinding, HostListener, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import * as i3 from 'ng-devui/i18n'; import * as i2$1 from 'ng-devui/position'; import { PositioningModule } from 'ng-devui/position'; import * as i4 from 'ng-devui/utils'; import { fadeInOut, removeClassFromOrigin, AppendToBodyDirectionsConfig, addClassToOrigin, WithConfig, LazyLoadModule, HighlightModule } from 'ng-devui/utils'; import { Subject, of, fromEvent } from 'rxjs'; import { takeUntil, map, filter, debounceTime, tap, switchMap } from 'rxjs/operators'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i5$1 from 'ng-devui/loading'; import { LoadingModule } from 'ng-devui/loading'; class AutoCompleteConfig { constructor() { this.autoComplete = { delay: 300, minLength: 1, itemTemplate: null, noResultItemTemplate: null, formatter: (item) => (item ? item.label || item.toString() : ''), valueParser: (item) => (item ? item.label || item.toString() : ''), }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteConfig, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteConfig, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class AutoCompletePopupComponent { constructor(autoCompleteConfig, elementRef) { this.autoCompleteConfig = autoCompleteConfig; this.elementRef = elementRef; this.maxHeight = 300; this.disabled = false; this.customViewDirection = 'bottom'; this.isSearching = false; this.appendToBody = false; this.cdkOverlayOffsetY = 0; this.showAnimation = true; this.hoverItem = new EventEmitter(); this.activeIndex = 0; this.hoverIndex = 0; this.labelMinHeight = 20; // position.top小于20px时候,表示光标在第一行 this.showLoading = false; this.popPosition = 'bottom'; this.onChange = (_) => null; this.onTouched = () => null; this.formatter = this.autoCompleteConfig.autoComplete.formatter; } writeValue(obj) { this.value = obj; } setDisabledState(isDisabled) { this.disabled = isDisabled; } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } onSelect(event, item) { if (this.disabledKey && item && item[this.disabledKey]) { event.preventDefault(); event.stopPropagation(); return; } if (this.overview === 'single') { // 单选场景和单行场景不需要冒泡 event.preventDefault(); event.stopPropagation(); } this.value = item; this.onTouched(); this.onChange({ type: 'select', value: this.value }); } selectCurrentItem(event) { this.activeIndex = this.hoverIndex; this.onSelect(event, this.source[this.hoverIndex]); } onActiveIndexChange(index) { this.activeIndex = index; } reset() { this.activeIndex = 0; this.hoverIndex = 0; } scrollToActive(index) { const that = this; setTimeout(() => { const scrollIndex = index === undefined ? this.activeIndex : index; const selectIndex = scrollIndex; const scrollPane = that.dropdownUl.nativeElement.children[selectIndex]; if (scrollPane.scrollIntoViewIfNeeded) { scrollPane.scrollIntoViewIfNeeded(false); } else { const containerInfo = that.dropdownUl.nativeElement.getBoundingClientRect(); const elementInfo = scrollPane.getBoundingClientRect(); if (elementInfo.bottom > containerInfo.bottom || elementInfo.top < containerInfo.top) { scrollPane.scrollIntoView(false); } } }); } next() { if (this.isOpen && this.source && this.source.length) { if (this.hoverIndex === this.source.length - 1) { this.hoverIndex = 0; this.scrollToActive(this.hoverIndex); return; } this.hoverIndex = this.hoverIndex + 1; this.scrollToActive(this.hoverIndex); } } prev() { if (this.isOpen && this.source && this.source.length) { if (this.hoverIndex === 0) { this.hoverIndex = this.source.length - 1; this.scrollToActive(this.hoverIndex); return; } this.hoverIndex = this.hoverIndex - 1; this.scrollToActive(this.hoverIndex); } } trackByFn(index, item) { return index; } animationEnd($event) { if (!this.isOpen && this.selectMenuElement) { const targetElement = this.selectMenuElement.nativeElement; setTimeout(() => { targetElement.style.display = 'none'; }); } } loadMoreEvent($event) { this.showLoading = true; this.onChange({ type: 'loadMore', value: this }); } loadFinish($event) { this.showLoading = false; } onPositionChange(position) { this.popPosition = position.connectionPair.originY; } onMouseOver(event, item) { this.hoverItem.emit(item); } hidePopup() { } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompletePopupComponent, deps: [{ token: AutoCompleteConfig }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AutoCompletePopupComponent, selector: "d-auto-complete-popup", inputs: { width: "width", cssClass: "cssClass", maxHeight: "maxHeight", disabled: "disabled", disabledKey: "disabledKey", source: "source", position: "position", isOpen: "isOpen", term: "term", popTipsText: "popTipsText", overview: "overview", itemTemplate: "itemTemplate", noResultItemTemplate: "noResultItemTemplate", customViewTemplate: "customViewTemplate", customViewDirection: "customViewDirection", searchingTemplate: "searchingTemplate", isSearching: "isSearching", formatter: "formatter", dropdown: "dropdown", selectWidth: "selectWidth", enableLazyLoad: "enableLazyLoad", appendToBody: "appendToBody", cdkOverlayOffsetY: "cdkOverlayOffsetY", origin: "origin", showAnimation: "showAnimation" }, outputs: { hoverItem: "hoverItem" }, viewQueries: [{ propertyName: "selectMenuElement", first: true, predicate: ["selectMenuElement"], descendants: true }, { propertyName: "dropdownUl", first: true, predicate: ["dropdownUl"], descendants: true }, { propertyName: "connectedOverlay", first: true, predicate: CdkConnectedOverlay, descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"appendToBody\">\n <ng-template\n cdk-connected-overlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayWidth]=\"width\"\n [cdkConnectedOverlayOpen]=\"isOpen && !disabled\"\n [cdkConnectedOverlayOffsetY]=\"cdkOverlayOffsetY\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n (positionChange)=\"onPositionChange($event)\"\n (detach)=\"isOpen && hidePopup()\"\n >\n <ng-template [ngTemplateOutlet]=\"popTpl\"> </ng-template>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"!appendToBody\">\n <ng-template [ngTemplateOutlet]=\"popTpl\"> </ng-template>\n</ng-container>\n\n<ng-template #popTpl>\n <div\n class=\"devui-dropdown-menu\"\n [ngClass]=\"{\n 'devui-dropdown-menu-cdk': appendToBody,\n 'devui-custom-right': customViewTemplate && customViewDirection === 'right',\n 'devui-custom-left': customViewTemplate && customViewDirection === 'left',\n 'devui-custom-top': customViewTemplate && customViewDirection === 'top'\n }\"\n [style.display]=\"isOpen && (source?.length || noResultItemTemplate) && !disabled ? 'inline-block' : 'none'\"\n [style.top]=\"overview === 'multiline' ? (position?.top < labelMinHeight ? '50%' : '100%') : '100%'\"\n [style.left]=\"overview === 'multiline' ? position?.left + 'px' : '0'\"\n [@fadeInOut]=\"isOpen && !disabled ? (appendToBody ? popPosition : 'bottom') : 'void'\"\n (@fadeInOut.done)=\"animationEnd($event)\"\n [@.disabled]=\"!showAnimation\"\n #selectMenuElement\n dLoading\n [showLoading]=\"showLoading\"\n [backdrop]=\"true\"\n >\n <ul\n class=\"devui-list-unstyled devui-scrollbar scroll-height devui-dropdown-menu-wrap devui-auto-complete-list\"\n [style.maxHeight]=\"maxHeight + 'px'\"\n dLazyLoad\n [enableLazyLoad]=\"enableLazyLoad\"\n (loadMore)=\"loadMoreEvent($event)\"\n #dropdownUl\n >\n <ng-container *ngIf=\"!isSearching || !searchingTemplate\">\n <li *ngIf=\"popTipsText && popTipsText.length > 0\" class=\"devui-popup-tips\">\n {{ popTipsText }}\n </li>\n <li\n *ngFor=\"let item of source; let $index = index; trackBy: trackByFn\"\n class=\"devui-dropdown-item\"\n [title]=\"formatter(item)\"\n [ngClass]=\"{\n selected: $index == activeIndex,\n 'devui-dropdown-bg': $index == hoverIndex,\n disabled: disabledKey && item[disabledKey]\n }\"\n (click)=\"onSelect($event, item)\"\n (mouseover)=\"onMouseOver($event, item)\"\n >\n <ng-template\n [ngTemplateOutlet]=\"itemTemplate || defaultItemTemplate\"\n [ngTemplateOutletContext]=\"{\n formatter: formatter,\n term: term,\n source: source,\n item: item,\n $index: $index\n }\"\n >\n </ng-template>\n </li>\n <div class=\"devui-no-data-tip\" *ngIf=\"!source?.length && noResultItemTemplate\">\n <ng-template [ngTemplateOutlet]=\"noResultItemTemplate\" [ngTemplateOutletContext]=\"{ term: term, source: source }\"> </ng-template>\n </div>\n </ng-container>\n <div class=\"devui-no-data-tip\" *ngIf=\"isSearching && searchingTemplate\">\n <ng-template [ngTemplateOutlet]=\"searchingTemplate\" [ngTemplateOutletContext]=\"{ term: term }\"> </ng-template>\n </div>\n </ul>\n <ng-container *ngIf=\"customViewTemplate\">\n <div class=\"devui-select-custom-area\">\n <ng-template [ngTemplateOutlet]=\"customViewTemplate\" [ngTemplateOutletContext]=\"{ $implicit: this }\"></ng-template>\n </div>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultItemTemplate let-item=\"item\" let-term=\"term\">\n <d-highlight [value]=\"formatter(item)\" [term]=\"term\"></d-highlight>\n</ng-template>\n", styles: [".devui-dropdown-menu{width:100%;display:block}.devui-dropdown-menu.devui-custom-right,.devui-dropdown-menu.devui-custom-left,.devui-dropdown-menu.devui-custom-top{min-width:400px;display:flex!important}.devui-dropdown-menu.devui-custom-right>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-left>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-top>.devui-dropdown-menu-wrap{display:inline-block}.devui-dropdown-menu.devui-custom-right>.devui-dropdown-menu-wrap>.devui-no-data-tip,.devui-dropdown-menu.devui-custom-left>.devui-dropdown-menu-wrap>.devui-no-data-tip,.devui-dropdown-menu.devui-custom-top>.devui-dropdown-menu-wrap>.devui-no-data-tip{padding:12px}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area{display:inline-block;overflow:auto}.devui-dropdown-menu.devui-custom-right:not(.devui-custom-top)>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-left:not(.devui-custom-top)>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-top:not(.devui-custom-top)>.devui-dropdown-menu-wrap{width:calc(50% - 1px)}.devui-dropdown-menu.devui-custom-right:not(.devui-custom-top)>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-left:not(.devui-custom-top)>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-top:not(.devui-custom-top)>.devui-select-custom-area{width:50%}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area:before,.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area:before,.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area:before{display:none}.devui-dropdown-menu.devui-custom-top{flex-direction:column-reverse}.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area{border-right:1px solid var(--devui-dividing-line, #f0f0f0);order:-1}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area{border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area{border-bottom:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-select-custom-area:before{display:block;content:\"\";width:calc(100% - 20px);margin:0 10px;height:1px;border-top:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-dropdown-menu-cdk{position:static}ul.devui-list-unstyled{margin:0}.devui-popup-tips{color:var(--devui-text-weak, #333333);padding:4px 12px}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.LazyLoadDirective, selector: "[dLazyLoad]", inputs: ["enableLazyLoad", "contentMode", "target", "imgLoadSrc", "direction"], outputs: ["loadMore"] }, { kind: "directive", type: i5$1.LoadingDirective, selector: "[dLoading]", inputs: ["backdrop", "message", "positionType", "showLoading", "view", "zIndex", "loading", "loadingStyle", "loadingTemplateRef"], exportAs: ["dLoading"] }, { kind: "component", type: i4.HighlightComponent, selector: "d-highlight", inputs: ["value", "term", "highlightClass"] }], animations: [fadeInOut] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompletePopupComponent, decorators: [{ type: Component, args: [{ selector: 'd-auto-complete-popup', animations: [fadeInOut], preserveWhitespaces: false, template: "<ng-container *ngIf=\"appendToBody\">\n <ng-template\n cdk-connected-overlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayWidth]=\"width\"\n [cdkConnectedOverlayOpen]=\"isOpen && !disabled\"\n [cdkConnectedOverlayOffsetY]=\"cdkOverlayOffsetY\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n (positionChange)=\"onPositionChange($event)\"\n (detach)=\"isOpen && hidePopup()\"\n >\n <ng-template [ngTemplateOutlet]=\"popTpl\"> </ng-template>\n </ng-template>\n</ng-container>\n\n<ng-container *ngIf=\"!appendToBody\">\n <ng-template [ngTemplateOutlet]=\"popTpl\"> </ng-template>\n</ng-container>\n\n<ng-template #popTpl>\n <div\n class=\"devui-dropdown-menu\"\n [ngClass]=\"{\n 'devui-dropdown-menu-cdk': appendToBody,\n 'devui-custom-right': customViewTemplate && customViewDirection === 'right',\n 'devui-custom-left': customViewTemplate && customViewDirection === 'left',\n 'devui-custom-top': customViewTemplate && customViewDirection === 'top'\n }\"\n [style.display]=\"isOpen && (source?.length || noResultItemTemplate) && !disabled ? 'inline-block' : 'none'\"\n [style.top]=\"overview === 'multiline' ? (position?.top < labelMinHeight ? '50%' : '100%') : '100%'\"\n [style.left]=\"overview === 'multiline' ? position?.left + 'px' : '0'\"\n [@fadeInOut]=\"isOpen && !disabled ? (appendToBody ? popPosition : 'bottom') : 'void'\"\n (@fadeInOut.done)=\"animationEnd($event)\"\n [@.disabled]=\"!showAnimation\"\n #selectMenuElement\n dLoading\n [showLoading]=\"showLoading\"\n [backdrop]=\"true\"\n >\n <ul\n class=\"devui-list-unstyled devui-scrollbar scroll-height devui-dropdown-menu-wrap devui-auto-complete-list\"\n [style.maxHeight]=\"maxHeight + 'px'\"\n dLazyLoad\n [enableLazyLoad]=\"enableLazyLoad\"\n (loadMore)=\"loadMoreEvent($event)\"\n #dropdownUl\n >\n <ng-container *ngIf=\"!isSearching || !searchingTemplate\">\n <li *ngIf=\"popTipsText && popTipsText.length > 0\" class=\"devui-popup-tips\">\n {{ popTipsText }}\n </li>\n <li\n *ngFor=\"let item of source; let $index = index; trackBy: trackByFn\"\n class=\"devui-dropdown-item\"\n [title]=\"formatter(item)\"\n [ngClass]=\"{\n selected: $index == activeIndex,\n 'devui-dropdown-bg': $index == hoverIndex,\n disabled: disabledKey && item[disabledKey]\n }\"\n (click)=\"onSelect($event, item)\"\n (mouseover)=\"onMouseOver($event, item)\"\n >\n <ng-template\n [ngTemplateOutlet]=\"itemTemplate || defaultItemTemplate\"\n [ngTemplateOutletContext]=\"{\n formatter: formatter,\n term: term,\n source: source,\n item: item,\n $index: $index\n }\"\n >\n </ng-template>\n </li>\n <div class=\"devui-no-data-tip\" *ngIf=\"!source?.length && noResultItemTemplate\">\n <ng-template [ngTemplateOutlet]=\"noResultItemTemplate\" [ngTemplateOutletContext]=\"{ term: term, source: source }\"> </ng-template>\n </div>\n </ng-container>\n <div class=\"devui-no-data-tip\" *ngIf=\"isSearching && searchingTemplate\">\n <ng-template [ngTemplateOutlet]=\"searchingTemplate\" [ngTemplateOutletContext]=\"{ term: term }\"> </ng-template>\n </div>\n </ul>\n <ng-container *ngIf=\"customViewTemplate\">\n <div class=\"devui-select-custom-area\">\n <ng-template [ngTemplateOutlet]=\"customViewTemplate\" [ngTemplateOutletContext]=\"{ $implicit: this }\"></ng-template>\n </div>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #defaultItemTemplate let-item=\"item\" let-term=\"term\">\n <d-highlight [value]=\"formatter(item)\" [term]=\"term\"></d-highlight>\n</ng-template>\n", styles: [".devui-dropdown-menu{width:100%;display:block}.devui-dropdown-menu.devui-custom-right,.devui-dropdown-menu.devui-custom-left,.devui-dropdown-menu.devui-custom-top{min-width:400px;display:flex!important}.devui-dropdown-menu.devui-custom-right>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-left>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-top>.devui-dropdown-menu-wrap{display:inline-block}.devui-dropdown-menu.devui-custom-right>.devui-dropdown-menu-wrap>.devui-no-data-tip,.devui-dropdown-menu.devui-custom-left>.devui-dropdown-menu-wrap>.devui-no-data-tip,.devui-dropdown-menu.devui-custom-top>.devui-dropdown-menu-wrap>.devui-no-data-tip{padding:12px}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area{display:inline-block;overflow:auto}.devui-dropdown-menu.devui-custom-right:not(.devui-custom-top)>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-left:not(.devui-custom-top)>.devui-dropdown-menu-wrap,.devui-dropdown-menu.devui-custom-top:not(.devui-custom-top)>.devui-dropdown-menu-wrap{width:calc(50% - 1px)}.devui-dropdown-menu.devui-custom-right:not(.devui-custom-top)>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-left:not(.devui-custom-top)>.devui-select-custom-area,.devui-dropdown-menu.devui-custom-top:not(.devui-custom-top)>.devui-select-custom-area{width:50%}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area:before,.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area:before,.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area:before{display:none}.devui-dropdown-menu.devui-custom-top{flex-direction:column-reverse}.devui-dropdown-menu.devui-custom-left>.devui-select-custom-area{border-right:1px solid var(--devui-dividing-line, #f0f0f0);order:-1}.devui-dropdown-menu.devui-custom-right>.devui-select-custom-area{border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-dropdown-menu.devui-custom-top>.devui-select-custom-area{border-bottom:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-select-custom-area:before{display:block;content:\"\";width:calc(100% - 20px);margin:0 10px;height:1px;border-top:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-dropdown-menu-cdk{position:static}ul.devui-list-unstyled{margin:0}.devui-popup-tips{color:var(--devui-text-weak, #333333);padding:4px 12px}\n"] }] }], ctorParameters: () => [{ type: AutoCompleteConfig }, { type: i0.ElementRef }], propDecorators: { width: [{ type: Input }], cssClass: [{ type: Input }], maxHeight: [{ type: Input }], disabled: [{ type: Input }], disabledKey: [{ type: Input }], source: [{ type: Input }], position: [{ type: Input }], isOpen: [{ type: Input }], term: [{ type: Input }], popTipsText: [{ type: Input }], overview: [{ type: Input }], itemTemplate: [{ type: Input }], noResultItemTemplate: [{ type: Input }], customViewTemplate: [{ type: Input }], customViewDirection: [{ type: Input }], searchingTemplate: [{ type: Input }], isSearching: [{ type: Input }], formatter: [{ type: Input }], dropdown: [{ type: Input }], selectWidth: [{ type: Input }], enableLazyLoad: [{ type: Input }], appendToBody: [{ type: Input }], cdkOverlayOffsetY: [{ type: Input }], origin: [{ type: Input }], showAnimation: [{ type: Input }], hoverItem: [{ type: Output }], selectMenuElement: [{ type: ViewChild, args: ['selectMenuElement'] }], dropdownUl: [{ type: ViewChild, args: ['dropdownUl'] }], connectedOverlay: [{ type: ViewChild, args: [CdkConnectedOverlay] }] } }); class AutoCompleteDirective { get hasGlowStyle() { return this.showGlowStyle; } set isSearching(isSearching) { if (this.popupRef && this.searchingTemplate) { const pop = this.popupRef.instance; pop.isSearching = isSearching; pop.searchingTemplate = this.searchingTemplate; if (isSearching) { pop.isOpen = true; } } } constructor(autoCompleteConfig, elementRef, viewContainerRef, componentFactoryResolver, renderer, injector, positionService, changeDetectorRef, i18n, devConfigService, scrollStrategyOption) { this.autoCompleteConfig = autoCompleteConfig; this.elementRef = elementRef; this.viewContainerRef = viewContainerRef; this.componentFactoryResolver = componentFactoryResolver; this.renderer = renderer; this.injector = injector; this.positionService = positionService; this.changeDetectorRef = changeDetectorRef; this.i18n = i18n; this.devConfigService = devConfigService; this.scrollStrategyOption = scrollStrategyOption; this.autocomplete = 'off'; this.autocapitalize = 'off'; this.autocorrect = 'off'; this.delay = 300; this.showGlowStyle = true; this.appendToBody = false; this.appendToBodyDirections = ['rightDown', 'leftDown', 'rightUp', 'leftUp']; this.cdkOverlayOffsetY = 0; // 内部使用不开放 this.sceneType = ''; this.tipsText = ''; // 提示文字 this.maxHeight = 300; this.showAnimation = true; /** * 【可选】启用数据懒加载,默认不启用 */ this.enableLazyLoad = false; this.retainInputValue = false; this.allowEmptyValueSearch = false; // 在value为空时,是否允许进行搜索 this.customViewDirection = 'bottom'; this.loadMore = new EventEmitter(); this.selectValue = new EventEmitter(); this.transInputFocusEmit = new EventEmitter(); // input状态传给父组件函数 /** * @deprecated */ this.changeDropDownStatus = new EventEmitter(); this.toggleChange = new EventEmitter(); this.hoverItem = new EventEmitter(); this.KEYBOARD_EVENT_NOT_REFRESH = ['escape', 'enter', 'arrowup', 'arrowdown', /* ie 10 edge */ 'esc', 'up', 'down']; this.popTipsText = ''; this.focus = false; this.SELECT_TYPES = ['select', 'select-extend']; this.destroy$ = new Subject(); this.onChange = (_) => null; this.onTouched = () => null; this.hidePopup = () => { if (this.popupRef) { this.popupRef.instance.isOpen = false; removeClassFromOrigin(this.elementRef); this.changeDropDownStatus.emit(false); this.toggleChange.emit(false); } }; this.scrollStrategy = this.scrollStrategyOption.reposition(); } ngOnInit() { this.init(); this.setI18nText(); this.valueChanges = this.registerInputEvent(this.elementRef); // 调用时机:input keyup this.subscription = this.valueChanges.subscribe((source) => this.onSourceChange(source)); // 动态的创建了popup组件, const factory = this.componentFactoryResolver.resolveComponentFactory(AutoCompletePopupComponent); this.popupRef = this.viewContainerRef.createComponent(factory, this.viewContainerRef.length, this.injector); this.popupRef.instance.hoverItem.subscribe((item) => this.hoverItem.emit(item)); this.fillPopup(this.source); if (!this.searchFn) { this.searchFn = (term) => { return of(this.source.filter((item) => this.formatter(item).toLowerCase().indexOf(term.toLowerCase()) !== -1)); }; } // 调用时机:选中回车或者鼠标单击下拉选项 this.popupRef.instance.registerOnChange((item) => { if (item.type === 'loadMore') { this.loadMore.emit(item.value); return; } this.writeValue(item.value); this.onChange(item.value); this.hidePopup(); this.selectValue.emit(item.value); if (this.overview && this.overview !== 'single') { setTimeout(() => { // 这里稍微延迟一下,等待光标的位置发生变化,好重新获取光标的位置 this.restLatestSource(); }, 0); } }); this.setPositions(); } ngOnChanges(changes) { const { appendToBodyDirections, appendToBodyScrollStrategy, source } = changes; const globalScrollStrategy = this.devConfigService.getConfigForApi('appendToBodyScrollStrategy'); if (source && this.popupRef) { this.fillPopup(this.source); } if (appendToBodyDirections) { this.setPositions(); } if (this.appendToBodyScrollStrategy && (appendToBodyScrollStrategy || globalScrollStrategy)) { const func = this.scrollStrategyOption[this.appendToBodyScrollStrategy]; this.scrollStrategy = func(); if (this.popupRef) { this.popupRef.instance.scrollStrategy = this.scrollStrategy; } } } init() { this.minLength = this.minLength ?? this.autoCompleteConfig.autoComplete.minLength; this.itemTemplate = this.itemTemplate || this.autoCompleteConfig.autoComplete.itemTemplate; this.noResultItemTemplate = this.noResultItemTemplate || this.autoCompleteConfig.autoComplete.noResultItemTemplate; this.formatter = this.formatter || this.autoCompleteConfig.autoComplete.formatter; this.valueParser = this.valueParser || this.autoCompleteConfig.autoComplete.valueParser; } setPositions() { if (this.popupRef) { this.popupRef.instance.overlayPositions = this.appendToBodyDirections && this.appendToBodyDirections.length > 0 ? this.appendToBodyDirections .map((position) => { if (typeof position === 'string') { return AppendToBodyDirectionsConfig[position]; } else { return position; } }) .filter((position) => position !== undefined) : undefined; } } setI18nText() { this.i18nText = this.i18n.getI18nText().autoComplete; this.i18n .langChange() .pipe(takeUntil(this.destroy$)) .subscribe((data) => { this.i18nText = data.autoComplete; }); } restLatestSource() { if (this.latestSource && this.latestSource.length > 0) { this.writeValue(''); this.clearInputValue(); this.showLatestSource(); } } // 调用时机:input keyup onSourceChange(source) { if (!this.elementRef.nativeElement.value) { if (!this.SELECT_TYPES.includes(this.sceneType) && !this.allowEmptyValueSearch) { // 下拉场景不展示最近输入 this.showLatestSource(); } else { this.showSource(source, true, true); } } else { this.showSource(source, true, true); } } showLatestSource() { let tempSource = []; if (this.latestSource && this.latestSource.length > 0) { this.searchFn('').subscribe((source) => { const t = this.latestSource; tempSource = t.filter((data) => { if (!data.label) { return source.find((item) => item === data); } else { return source.find((item) => item.label === data.label); } }); const pop = this.popupRef.instance; pop.reset(); this.popTipsText = this.i18nText.latestInput; this.fillPopup(tempSource); this.openPopup(); this.changeDetectorRef.markForCheck(); this.updatePosition(); }); } if (tempSource.length <= 0) { this.hidePopup(); } } showSource(source, setOpen, isReset) { if ((source && source.length) || this.noResultItemTemplate) { const pop = this.popupRef.instance; if (isReset) { pop.reset(); } this.popTipsText = this.tipsText || ''; this.fillPopup(source, this.value); if (setOpen) { this.openPopup(isReset ? 0 : -1); } this.changeDetectorRef.markForCheck(); this.updatePosition(); } else { this.hidePopup(); } } updatePosition() { if (this.appendToBody) { setTimeout(() => { if (this.popupRef.instance.connectedOverlay && this.popupRef.instance.connectedOverlay.overlayRef) { this.popupRef.instance.connectedOverlay.overlayRef.updatePosition(); } }); } } openPopup(activeIndex) { const index = activeIndex >= 0 ? activeIndex : this.popupRef.instance.activeIndex; this.popupRef.instance.activeIndex = index; this.popupRef.instance.hoverIndex = index; this.popupRef.instance.disabled = this.disabled; if (!this.popupRef.instance.isOpen) { this.popupRef.instance.isOpen = true; addClassToOrigin(this.elementRef); this.changeDropDownStatus.emit(true); this.toggleChange.emit(true); } } writeValue(obj) { this.value = this.valueParser(obj) || ''; if (!this.retainInputValue) { this.writeInputValue(this.value); } } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', isDisabled); if (this.popupRef) { this.popupRef.instance.setDisabledState(isDisabled); } } ngOnDestroy() { this.unSubscription(); this.destroy$.next(); this.destroy$.complete(); } onFocus($event) { this.focus = true; this.transInputFocusEmit.emit({ focus: true, popupRef: this.popupRef, }); if (this.sceneType === 'select') { this.searchValue(this.value ?? '', false); } } onBlur($event) { this.focus = false; this.onTouched(); } onEscKeyup($event) { this.hidePopup(); } onEnterKeyDown($event) { if (!this.popupRef.instance.source?.length || !this.popupRef.instance.isOpen) { return; } if (this.popupRef) { this.popupRef.instance.selectCurrentItem($event); } } onArrowUpKeyDown($event) { if (this.popupRef) { $event.preventDefault(); $event.stopPropagation(); this.popupRef.instance.prev(); } } onArrowDownKeyDown($event) { if (this.popupRef) { $event.preventDefault(); $event.stopPropagation(); this.popupRef.instance.next(); } } onDocumentClick($event) { if (this.focus) { this.transInputFocusEmit.emit({ focus: this.focus, popupRef: this.popupRef, }); } // TODO: sceneType为'select'时,自定义了太多处理,十分不优雅,需要合一化 const hostElement = this.elementRef.nativeElement; const isInside = hostElement.contains($event.target); const isSelect = this.SELECT_TYPES.includes(this.sceneType); const value = this.elementRef.nativeElement.value; if (this.popupRef && this.popupRef.instance.isOpen) { if ((!isInside && isSelect) || !isSelect) { this.hidePopup(); } if (!isInside) { this.transInputFocusEmit.emit({ focus: false, popupRef: this.popupRef, }); } } else if (isInside && !isSelect) { if (!value && !this.allowEmptyValueSearch) { this.showLatestSource(); } else { this.searchValue(value, true); } } } searchValue(value, isOpen) { this.searchFn(value).subscribe((source) => { const searchStr = this.formatter(value) ?? ''; if (searchStr) { const activeIndex = source.map((item) => this.formatter(item).toLowerCase()).indexOf(searchStr.toLowerCase()); this.popupRef.instance.activeIndex = activeIndex > -1 ? activeIndex : 0; } this.showSource(source, isOpen, false); }); } fillPopup(source, term) { this.position = this.positionService.position(this.elementRef.nativeElement); const pop = this.popupRef.instance; pop.source = source; pop.maxHeight = this.maxHeight; pop.term = term; pop.disabledKey = this.disabledKey; pop.enableLazyLoad = this.enableLazyLoad; pop.disabled = this.disabled; pop.scrollStrategy = this.scrollStrategy; pop.hidePopup = this.hidePopup; if (this.appendToBody) { pop.appendToBody = true; pop.origin = new CdkOverlayOrigin(this.elementRef); pop.width = this.dAutoCompleteWidth ? this.dAutoCompleteWidth : this.elementRef.nativeElement.offsetWidth; pop.cdkOverlayOffsetY = this.cdkOverlayOffsetY; } else { pop.appendToBody = false; } [ 'formatter', 'itemTemplate', 'noResultItemTemplate', 'cssClass', 'dropdown', 'popTipsText', 'position', 'overview', 'showAnimation', 'customViewTemplate', 'customViewDirection', ].forEach((key) => { if (this[key] !== undefined) { pop[key] = this[key]; } }); } writeInputValue(value) { this.renderer.setProperty(this.elementRef.nativeElement, 'value', value); } clearInputValue() { this.renderer.setProperty(this.elementRef.nativeElement, 'value', ''); } unSubscription() { if (this.subscription) { this.subscription.unsubscribe(); this.subscription = null; } } onTermChange(term) { this.value = term; if (this.popupRef) { this.popupRef.instance.term = term; } this.onChange(term); } registerInputEvent(elementRef) { return fromEvent(elementRef.nativeElement, 'input').pipe(map((e) => e.target.value), filter((term) => !this.disabled && this.searchFn && term.length >= 0), debounceTime(this.delay), tap((term) => this.onTermChange(term)), switchMap((term) => this.searchFn(term, this))); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteDirective, deps: [{ token: AutoCompleteConfig }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: i0.Renderer2 }, { token: i0.Injector }, { token: i2$1.PositionService }, { token: i0.ChangeDetectorRef }, { token: i3.I18nService }, { token: i4.DevConfigService }, { token: i5.ScrollStrategyOptions }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: AutoCompleteDirective, selector: "[dAutoComplete]", inputs: { disabled: "disabled", cssClass: "cssClass", delay: "delay", showGlowStyle: "showGlowStyle", minLength: "minLength", itemTemplate: "itemTemplate", noResultItemTemplate: "noResultItemTemplate", searchingTemplate: "searchingTemplate", isSearching: "isSearching", appendToBody: "appendToBody", appendToBodyDirections: "appendToBodyDirections", appendToBodyScrollStrategy: "appendToBodyScrollStrategy", cdkOverlayOffsetY: "cdkOverlayOffsetY", dAutoCompleteWidth: "dAutoCompleteWidth", formatter: "formatter", sceneType: "sceneType", tipsText: "tipsText", overview: "overview", latestSource: "latestSource", source: "source", valueParser: "valueParser", searchFn: "searchFn", dropdown: "dropdown", maxHeight: "maxHeight", disabledKey: "disabledKey", showAnimation: "showAnimation", enableLazyLoad: "enableLazyLoad", retainInputValue: "retainInputValue", allowEmptyValueSearch: "allowEmptyValueSearch", customViewTemplate: "customViewTemplate", customViewDirection: "customViewDirection" }, outputs: { loadMore: "loadMore", selectValue: "selectValue", transInputFocusEmit: "transInputFocusEmit", changeDropDownStatus: "changeDropDownStatus", toggleChange: "toggleChange", hoverItem: "hoverItem" }, host: { listeners: { "focus": "onFocus($event)", "blur": "onBlur($event)", "keydown.esc": "onEscKeyup($event)", "keydown.Enter": "onEnterKeyDown($event)", "keydown.ArrowUp": "onArrowUpKeyDown($event)", "keydown.ArrowDown": "onArrowDownKeyDown($event)", "document:click": "onDocumentClick($event)" }, properties: { "attr.autocomplete": "this.autocomplete", "attr.autocapitalize": "this.autocapitalize", "attr.autocorrect": "this.autocorrect", "class.devui-glow-style": "this.hasGlowStyle" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AutoCompleteDirective), multi: true, }, ], exportAs: ["autoComplete"], usesOnChanges: true, ngImport: i0 }); } } __decorate([ WithConfig(), __metadata("design:type", Object) ], AutoCompleteDirective.prototype, "showGlowStyle", void 0); __decorate([ WithConfig(), __metadata("design:type", String) ], AutoCompleteDirective.prototype, "appendToBodyScrollStrategy", void 0); __decorate([ WithConfig(), __metadata("design:type", Object) ], AutoCompleteDirective.prototype, "showAnimation", void 0); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteDirective, decorators: [{ type: Directive, args: [{ selector: '[dAutoComplete]', exportAs: 'autoComplete', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AutoCompleteDirective), multi: true, }, ], }] }], ctorParameters: () => [{ type: AutoCompleteConfig }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: i0.Renderer2 }, { type: i0.Injector }, { type: i2$1.PositionService }, { type: i0.ChangeDetectorRef }, { type: i3.I18nService }, { type: i4.DevConfigService }, { type: i5.ScrollStrategyOptions }], propDecorators: { autocomplete: [{ type: HostBinding, args: ['attr.autocomplete'] }], autocapitalize: [{ type: HostBinding, args: ['attr.autocapitalize'] }], autocorrect: [{ type: HostBinding, args: ['attr.autocorrect'] }], disabled: [{ type: Input }], cssClass: [{ type: Input }], delay: [{ type: Input }], showGlowStyle: [{ type: Input }], hasGlowStyle: [{ type: HostBinding, args: ['class.devui-glow-style'] }], minLength: [{ type: Input }], itemTemplate: [{ type: Input }], noResultItemTemplate: [{ type: Input }], searchingTemplate: [{ type: Input }], isSearching: [{ type: Input }], appendToBody: [{ type: Input }], appendToBodyDirections: [{ type: Input }], appendToBodyScrollStrategy: [{ type: Input }], cdkOverlayOffsetY: [{ type: Input }], dAutoCompleteWidth: [{ type: Input }], formatter: [{ type: Input }], sceneType: [{ type: Input }], tipsText: [{ type: Input }], overview: [{ type: Input }], latestSource: [{ type: Input }], source: [{ type: Input }], valueParser: [{ type: Input }], searchFn: [{ type: Input }], dropdown: [{ type: Input }], maxHeight: [{ type: Input }], disabledKey: [{ type: Input }], showAnimation: [{ type: Input }], enableLazyLoad: [{ type: Input }], retainInputValue: [{ type: Input }], allowEmptyValueSearch: [{ type: Input }], customViewTemplate: [{ type: Input }], customViewDirection: [{ type: Input }], loadMore: [{ type: Output }], selectValue: [{ type: Output }], transInputFocusEmit: [{ type: Output }], changeDropDownStatus: [{ type: Output }], toggleChange: [{ type: Output }], hoverItem: [{ type: Output }], onFocus: [{ type: HostListener, args: ['focus', ['$event']] }], onBlur: [{ type: HostListener, args: ['blur', ['$event']] }], onEscKeyup: [{ type: HostListener, args: ['keydown.esc', ['$event']] }], onEnterKeyDown: [{ type: HostListener, args: ['keydown.Enter', ['$event']] }], onArrowUpKeyDown: [{ type: HostListener, args: ['keydown.ArrowUp', ['$event']] }], onArrowDownKeyDown: [{ type: HostListener, args: ['keydown.ArrowDown', ['$event']] }], onDocumentClick: [{ type: HostListener, args: ['document:click', ['$event']] }] } }); class AutoCompleteModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteModule, declarations: [AutoCompleteDirective, AutoCompletePopupComponent], imports: [CommonModule, FormsModule, OverlayModule, LazyLoadModule, LoadingModule, PositioningModule, HighlightModule], exports: [AutoCompleteDirective, AutoCompletePopupComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteModule, providers: [AutoCompleteConfig], imports: [CommonModule, FormsModule, OverlayModule, LazyLoadModule, LoadingModule, PositioningModule, HighlightModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutoCompleteModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, FormsModule, OverlayModule, LazyLoadModule, LoadingModule, PositioningModule, HighlightModule], exports: [AutoCompleteDirective, AutoCompletePopupComponent], declarations: [AutoCompleteDirective, AutoCompletePopupComponent], providers: [AutoCompleteConfig], }] }] }); /** * Generated bundle index. Do not edit. */ export { AutoCompleteConfig, AutoCompleteDirective, AutoCompleteModule, AutoCompletePopupComponent }; //# sourceMappingURL=ng-devui-auto-complete.mjs.map