ng-devui
Version:
DevUI components based on Angular
1 lines • 90 kB
Source Map (JSON)
{"version":3,"file":"ng-devui-toggle-menu.mjs","sources":["../../devui/toggle-menu/toggle-menu-list.component.ts","../../devui/toggle-menu/toggle-menu-list.component.html","../../devui/toggle-menu/toggle-menu-container.component.ts","../../devui/toggle-menu/toggle-menu-container.component.html","../../devui/toggle-menu/toggle-menu-input.component.ts","../../devui/toggle-menu/toggle-menu-input.component.html","../../devui/toggle-menu/toggle-menu-label.component.ts","../../devui/toggle-menu/toggle-menu-label.component.html","../../devui/toggle-menu/toggle-menu-list-item.component.ts","../../devui/toggle-menu/toggle-menu-list-item.component.html","../../devui/toggle-menu/toggle-menu-operation.component.ts","../../devui/toggle-menu/toggle-menu-operation.component.html","../../devui/toggle-menu/toggle-menu-placeholder.component.ts","../../devui/toggle-menu/toggle-menu-search.component.ts","../../devui/toggle-menu/toggle-menu-search.component.html","../../devui/toggle-menu/toggle-menu.module.ts","../../devui/toggle-menu/ng-devui-toggle-menu.ts"],"sourcesContent":["import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';\r\nimport {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n OnChanges,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n SimpleChanges,\r\n TemplateRef,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport { I18nInterface, I18nService } from 'ng-devui/i18n';\r\nimport { fadeInOut } from 'ng-devui/utils';\r\nimport { Subscription } from 'rxjs';\r\nimport { ToggleMenuListItem } from './toggle-menu.type';\r\n\r\n@Component({\r\n selector: 'd-toggle-menu-list',\r\n templateUrl: './toggle-menu-list.component.html',\r\n styleUrls: [`./toggle-menu-list.component.scss`],\r\n animations: [fadeInOut],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n preserveWhitespaces: false,\r\n})\r\nexport class ToggleMenuListComponent implements OnInit, OnChanges, OnDestroy {\r\n /**\r\n * 【必选】下拉选项资源,支持Array<string>, Array<{key: value}>\r\n */\r\n @Input() options: Array<ToggleMenuListItem> = [];\r\n /**\r\n * 【当传入资源(options)类型为Array<{key: value},必选】针对传入资源options的每项对应字段做禁用操作的key\r\n */\r\n @Input() optionDisabledKey = '';\r\n /**\r\n * 【当传入资源(options)类型为Array<{key: value},必选】针对传入资源options的每项对应字段禁止变更的key\r\n */\r\n @Input() optionImmutableKey = '';\r\n /**\r\n * 【当传入资源(options)类型为Array<{key: value},可选】如使用分组需设置\r\n */\r\n @Input() optionGroupKey = '';\r\n /**\r\n * 【可选】下拉选框尺寸\r\n */\r\n @Input() size: '' | 'sm' | 'lg';\r\n @Input() keyword: string;\r\n /**\r\n * 【可选】是否在搜索过滤状态中\r\n */\r\n @Input() isFiltering = false;\r\n /**\r\n * 【可选】启用数据懒加载,默认不启用\r\n */\r\n @Input() enableLazyLoad = false;\r\n /**\r\n * 【可选】是否虚拟滚动\r\n */\r\n @Input() virtualScroll = false;\r\n\r\n /**\r\n * 【必选】下拉列表单项模板\r\n */\r\n @Input() listItemTemplate: TemplateRef<any>;\r\n /**\r\n * 【可选】自定义 loading 模板\r\n */\r\n @Input() loadingTemplateRef: TemplateRef<any>;\r\n /**\r\n * 【可选】配置无数据展示\r\n */\r\n @Input() noResultItemTemplate: TemplateRef<any>;\r\n /**\r\n * 【可选】支持自定义区域显示内容\r\n */\r\n @Input() customViewTemplate: TemplateRef<any>;\r\n /**\r\n * customViewTemplate的方向,支持下方和右方\r\n */\r\n @Input() customViewDirection: 'top' | 'bottom' | 'right' | 'left' = 'bottom';\r\n /**\r\n * 【可选】模板高度\r\n */\r\n @Input() templateItemSize: number; // 模板itemSize,appendToBody为true\r\n /**\r\n * 【可选】下拉菜单高度,建议使用px作为高度单位\r\n */\r\n @Input() set scrollHeight(value) {\r\n this._scrollHeight = `${parseInt(value, 10)}px`;\r\n }\r\n\r\n get scrollHeight() {\r\n return this._scrollHeight;\r\n }\r\n\r\n @Input() selectIndex = -1;\r\n /**\r\n * 【可选】是否允许单选状态下无选中值时高亮某项\r\n */\r\n @Input() hasSelectIndex: boolean;\r\n /**\r\n * 【可选】是否支持多选\r\n */\r\n @Input() multiple: boolean;\r\n @Input() multiItems = [];\r\n @Input() value: ToggleMenuListItem | Array<ToggleMenuListItem>;\r\n /**\r\n * 【可选】是否支持全选\r\n */\r\n @Input() isSelectAll = false;\r\n /**\r\n * 【可选】配置多选的时候是否维持原数组排序还是用户选择的顺序排序,默认是用户顺序\r\n */\r\n @Input() keepMultipleOrder: 'origin' | 'user-select' = 'user-select';\r\n @Input() eventHandle: any;\r\n @Input() closeScope: 'all' | 'blank' | 'none' = 'all';\r\n /**\r\n * select下拉toggle事件,值为true或false\r\n */\r\n @Output() toggleChange = new EventEmitter<any>();\r\n @Output() valueChange = new EventEmitter<any>();\r\n @Output() loadMore = new EventEmitter<any>();\r\n @ViewChild('dropdownUl') dropdownUl: ElementRef;\r\n @ViewChild(CdkVirtualScrollViewport) virtualScrollViewport: CdkVirtualScrollViewport;\r\n\r\n get realVirtualScrollItemSize() {\r\n const itemSize = (this.templateItemSize || this.virtualScrollItemSize[this.size || 'normal']) + this.virtualScrollItemSize.space;\r\n const num = Math.round(this.scrollHeightNum / itemSize) || 10;\r\n this.minBuffer = num * 1.5 * itemSize;\r\n this.maxBuffer = num * 2.5 * itemSize;\r\n return itemSize;\r\n }\r\n\r\n _scrollHeight = '300px';\r\n i18nCommonText: I18nInterface['common'];\r\n i18nSubscription: Subscription;\r\n availableOptions = [];\r\n activeIndex = -1;\r\n allChecked = false;\r\n halfChecked = false;\r\n showLoading = false;\r\n scrollHeightNum: number;\r\n minBuffer: number;\r\n maxBuffer: number;\r\n virtualScrollViewportSizeMightChange = false;\r\n virtualScrollItemSize: any = {\r\n sm: 30,\r\n normal: 36,\r\n lg: 50,\r\n space: 4,\r\n };\r\n // 容器边距,虚拟滚动设置高度需考虑上下边距\r\n CONTAINER_MARGINS = 12;\r\n\r\n constructor(private changeDetectorRef: ChangeDetectorRef, private i18n: I18nService) {}\r\n\r\n ngOnInit() {\r\n this.setI18nText();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n const { options, value, eventHandle } = changes;\r\n if (options) {\r\n this.availableOptions = this.options;\r\n this.setAvailableOptions();\r\n // 显示数据变更,需要判断全选半选状态\r\n if (this.isSelectAll) {\r\n const selectedItemForFilterOptions = [];\r\n this.multiItems.forEach((item) => {\r\n this.availableOptions.forEach((option) => {\r\n if (item.id === option.id) {\r\n selectedItemForFilterOptions.push(item);\r\n }\r\n });\r\n });\r\n this.setChecked(selectedItemForFilterOptions);\r\n }\r\n if (\r\n !this.hasSelectIndex &&\r\n !this.multiple &&\r\n (!this.value || (this.availableOptions && !this.availableOptions.find((option) => option.option === this.value)))\r\n ) {\r\n this.selectIndex = this.isFiltering && this.availableOptions && this.availableOptions.length > 0 ? 0 : -1;\r\n }\r\n if (this.virtualScroll && this.virtualScrollViewport) {\r\n this.virtualScrollViewportSizeMightChange = true;\r\n this.virtualScrollViewport.checkViewportSize();\r\n }\r\n this.changeDetectorRef.markForCheck();\r\n }\r\n if (value) {\r\n this.setAvailableOptions();\r\n }\r\n if (eventHandle?.currentValue) {\r\n const evt = eventHandle.currentValue;\r\n const { event, type } = evt;\r\n switch (type) {\r\n case 'keydown.esc':\r\n this.onEscKeyup(event);\r\n break;\r\n case 'keydown.ArrowUp':\r\n this.handleKeyUpEvent(event);\r\n break;\r\n case 'keydown.ArrowDown':\r\n this.handleKeyDownEvent(event);\r\n break;\r\n case 'keydown.enter':\r\n this.handleKeyEnterEvent(event);\r\n break;\r\n default:\r\n }\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n if (this.i18nSubscription) {\r\n this.i18nSubscription.unsubscribe();\r\n }\r\n }\r\n\r\n setI18nText() {\r\n this.i18nCommonText = this.i18n.getI18nText().common;\r\n this.i18nSubscription = this.i18n.langChange().subscribe((data) => {\r\n this.i18nCommonText = data.common;\r\n });\r\n }\r\n\r\n setAvailableOptions() {\r\n if (!Array.isArray(this.availableOptions)) {\r\n return;\r\n }\r\n const result = this.multiple ? this.value : [this.value];\r\n const _value = this.value ? result : [];\r\n this.availableOptions = this.availableOptions.map((item, index) =>\r\n item.id >= 0 && item.option\r\n ? {\r\n isChecked: _value.findIndex((i) => JSON.stringify(i) === JSON.stringify(item.option)) > -1,\r\n id: item.id,\r\n option: item.option,\r\n }\r\n : { isChecked: _value.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) > -1, id: index, option: item }\r\n );\r\n }\r\n\r\n setChecked(selectedItem) {\r\n if (!selectedItem) {\r\n return;\r\n }\r\n if (!this.isSelectAll) {\r\n return;\r\n }\r\n this.halfChecked = false;\r\n if (selectedItem.length === this.availableOptions.length) {\r\n this.allChecked = true;\r\n } else if (selectedItem.length === 0) {\r\n this.allChecked = false;\r\n } else {\r\n this.halfChecked = true;\r\n }\r\n }\r\n\r\n selectAll() {\r\n const mutableOption = this.optionImmutableKey\r\n ? this.availableOptions.filter((item) => !item.option[this.optionImmutableKey])\r\n : this.availableOptions;\r\n const selectedImmutableOption = this.optionImmutableKey ? this.multiItems.filter((item) => item.option[this.optionImmutableKey]) : [];\r\n\r\n if (mutableOption && mutableOption.length > this.multiItems.length - selectedImmutableOption.length) {\r\n mutableOption.forEach((item) => {\r\n const indexOfOption = this.multiItems.findIndex((i) => JSON.stringify(i.option) === JSON.stringify(item.option));\r\n if (indexOfOption === -1) {\r\n this.multiItems.push({ id: item.id, option: item.option });\r\n }\r\n });\r\n } else {\r\n this.multiItems = [...selectedImmutableOption];\r\n }\r\n this.value = this.multiItems.map((item) => item.option);\r\n this.valueChange.emit({ value: this.value, multiItems: this.multiItems });\r\n this.setChecked(this.value);\r\n }\r\n\r\n trackByFn(index, item) {\r\n return index;\r\n }\r\n\r\n onEscKeyup(event?: Event) {\r\n if (event) {\r\n event.stopPropagation();\r\n }\r\n this.toggleChange.emit(false);\r\n }\r\n\r\n handleKeyUpEvent(event?: Event) {\r\n if (event) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n this.selectIndex = this.selectIndex === 0 || this.selectIndex === -1 ? this.availableOptions.length - 1 : this.selectIndex - 1;\r\n this.scrollToActive();\r\n }\r\n\r\n handleKeyDownEvent(event?: Event) {\r\n if (event) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n this.selectIndex = this.selectIndex === this.availableOptions.length - 1 ? 0 : this.selectIndex + 1;\r\n this.scrollToActive();\r\n }\r\n\r\n handleKeyEnterEvent(event?: Event) {\r\n if (event) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n const item = this.availableOptions[this.selectIndex];\r\n if (item) {\r\n this.choose({ option: item.option, index: item.id, event: null });\r\n } else if (this.closeScope === 'all') {\r\n this.toggleChange.emit(false);\r\n }\r\n }\r\n\r\n scrollToActive(): void {\r\n const that = this;\r\n setTimeout(() => {\r\n try {\r\n const selectIndex = that.selectIndex + (that.isSelectAll ? 1 : 0); // 多了个全选会导致问题,index需要加1\r\n const scrollPane: any = that.dropdownUl.nativeElement.children[selectIndex];\r\n if (scrollPane.scrollIntoViewIfNeeded) {\r\n scrollPane.scrollIntoViewIfNeeded(false);\r\n } else {\r\n const containerInfo = that.dropdownUl.nativeElement.getBoundingClientRect();\r\n const elementInfo = scrollPane.getBoundingClientRect();\r\n if (elementInfo.bottom > containerInfo.bottom || elementInfo.top < containerInfo.top) {\r\n scrollPane.scrollIntoView(false);\r\n }\r\n }\r\n } catch (e) {}\r\n });\r\n }\r\n\r\n resetIndex(resetSelectIndex = true) {\r\n this.selectIndex = resetSelectIndex ? -1 : 0;\r\n this.activeIndex = -1;\r\n this.changeDetectorRef.markForCheck();\r\n }\r\n\r\n choose = ({ option, index, event }) => {\r\n if (event) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n if (typeof option === 'object' && Object.keys(option).length === 0) {\r\n this.toggleChange.emit(false);\r\n return;\r\n }\r\n if (this.optionDisabledKey && option[this.optionDisabledKey]) {\r\n return;\r\n }\r\n if (this.optionImmutableKey && option[this.optionImmutableKey]) {\r\n return;\r\n }\r\n if (this.optionGroupKey && option[this.optionGroupKey]) {\r\n return;\r\n }\r\n if (this.multiple) {\r\n const indexOfOption = this.multiItems.findIndex((item) => JSON.stringify(item.option) === JSON.stringify(option));\r\n if (indexOfOption === -1) {\r\n this.multiItems.push({ id: index, option });\r\n } else {\r\n this.multiItems.splice(indexOfOption, 1);\r\n }\r\n if (this.keepMultipleOrder === 'origin') {\r\n this.multiItems.sort((a, b) => a.id - b.id);\r\n }\r\n this.value = this.multiItems.map((item) => item.option);\r\n } else {\r\n this.value = option;\r\n this.activeIndex = index;\r\n this.selectIndex = index;\r\n if (this.closeScope === 'all') {\r\n this.toggleChange.emit(false);\r\n }\r\n if (this.virtualScrollViewportSizeMightChange) {\r\n // 解决虚拟滚动更新options长度展开前无法获取正确高度影响\r\n setTimeout(() => {\r\n if (this.virtualScrollViewportSizeMightChange && this.virtualScrollViewport) {\r\n this.virtualScrollViewportSizeMightChange = false;\r\n this.virtualScrollViewport.checkViewportSize();\r\n }\r\n }, 0);\r\n }\r\n }\r\n this.valueChange.emit({ value: this.value, multiItems: this.multiItems, option, event, index });\r\n this.setAvailableOptions();\r\n this.setChecked(this.value);\r\n };\r\n\r\n showSelectAll() {\r\n return this.isSelectAll && this.multiple && this.availableOptions.length > 0;\r\n }\r\n\r\n getVirtualScrollHeight(len, size) {\r\n if (len > 0) {\r\n let height =\r\n (this.templateItemSize || this.virtualScrollItemSize[size || 'normal']) * len + this.virtualScrollItemSize.space * (len - 1);\r\n if (this.isSelectAll && this.multiple) {\r\n height += this.virtualScrollItemSize[size ? size : 'normal'] + this.virtualScrollItemSize.space;\r\n }\r\n const scrollHeight = parseInt(this.scrollHeight, 10);\r\n this.scrollHeightNum = height > scrollHeight ? scrollHeight : height;\r\n return `${this.scrollHeightNum + this.CONTAINER_MARGINS * 2}px`;\r\n }\r\n }\r\n\r\n loadMoreEvent(event) {\r\n this.showLoading = true;\r\n this.loadMore.emit({ instance: this, event });\r\n }\r\n\r\n loadStart() {\r\n this.showLoading = true;\r\n this.changeDetectorRef.detectChanges();\r\n }\r\n\r\n loadFinish() {\r\n this.showLoading = false;\r\n this.changeDetectorRef.detectChanges();\r\n }\r\n}\r\n","<ul\n class=\"devui-dropdown-menu-wrap {{ size ? 'devui-dropdown-menu-' + size : '' }}\"\n dLoading\n positionType=\"relative\"\n [showLoading]=\"showLoading\"\n [message]=\"i18nCommonText?.loading\"\n [loadingTemplateRef]=\"loadingTemplateRef\"\n [backdrop]=\"true\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n>\n <ng-content></ng-content>\n <ul\n #dropdownUl\n *ngIf=\"!virtualScroll || enableLazyLoad; else scrollViewTpl\"\n class=\"devui-select-list-unstyled devui-scrollbar\"\n [ngStyle]=\"{ 'max-height': scrollHeight, width: '100%' }\"\n dLazyLoad\n [enableLazyLoad]=\"enableLazyLoad\"\n (loadMore)=\"loadMoreEvent($event)\"\n >\n <ng-template [ngTemplateOutlet]=\"selectAllTpl\"></ng-template>\n <ng-container *ngFor=\"let item of availableOptions; let index = index; trackBy: trackByFn\">\n <!--list-item 单个选项模板-->\n <ng-template\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{\n item: item,\n index: index,\n selectIndex: selectIndex,\n activeIndex: activeIndex,\n choose: choose\n }\"\n ></ng-template>\n </ng-container>\n <div *ngIf=\"availableOptions?.length === 0\" class=\"devui-no-data-tip\">\n <ng-container *ngIf=\"noResultItemTemplate; else noResultDefaultTpl\">\n <ng-template [ngTemplateOutlet]=\"noResultItemTemplate\" [ngTemplateOutletContext]=\"{ options: options }\"></ng-template>\n </ng-container>\n </div>\n </ul>\n</ul>\n<ng-container *ngIf=\"customViewTemplate\">\n <div class=\"devui-select-custom-area\">\n <ng-template [ngTemplateOutlet]=\"customViewTemplate\" [ngTemplateOutletContext]=\"{ $implicit: this, choose: choose }\"></ng-template>\n </div>\n</ng-container>\n\n<!--虚拟滚动模板-->\n<ng-template #scrollViewTpl>\n <cdk-virtual-scroll-viewport\n [ngStyle]=\"{\n height: getVirtualScrollHeight(availableOptions.length, size),\n width: '100%',\n 'max-height': scrollHeight\n }\"\n [itemSize]=\"realVirtualScrollItemSize\"\n [minBufferPx]=\"minBuffer\"\n [maxBufferPx]=\"maxBuffer\"\n class=\"viewport-wrapper devui-select-list-unstyled devui-scrollbar\"\n #dropdownUl\n >\n <ng-template [ngTemplateOutlet]=\"selectAllTpl\"></ng-template>\n <ng-container *cdkVirtualFor=\"let item of availableOptions; let index = index; trackBy: trackByFn\">\n <ng-template\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{\n item: item,\n index: index,\n selectIndex: selectIndex,\n activeIndex: activeIndex,\n choose: choose\n }\"\n ></ng-template>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n</ng-template>\n\n<!--全选模板-->\n<ng-template #selectAllTpl>\n <li class=\"devui-dropdown-item\" *ngIf=\"showSelectAll()\" (click)=\"selectAll()\">\n <span>\n <d-checkbox [label]=\"i18nCommonText.checkAll\" [isShowTitle]=\"false\" [halfchecked]=\"halfChecked\" [(ngModel)]=\"allChecked\"></d-checkbox>\n </span>\n </li>\n</ng-template>\n\n<!--无内容模板-->\n<ng-template #noResultDefaultTpl>{{ isFiltering ? i18nCommonText?.noRecordsFound : i18nCommonText?.noData }}</ng-template>\n","import {\r\n CdkConnectedOverlay,\r\n CdkOverlayOrigin,\r\n ConnectedOverlayPositionChange,\r\n ConnectedPosition,\r\n ScrollStrategy,\r\n ScrollStrategyOptions,\r\n VerticalConnectionPos,\r\n} from '@angular/cdk/overlay';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport {\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ContentChild,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Inject,\r\n Input,\r\n NgZone,\r\n OnChanges,\r\n OnInit,\r\n Output,\r\n Renderer2,\r\n SimpleChanges,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport {\r\n AppendToBodyDirection,\r\n AppendToBodyDirectionsConfig,\r\n AppendToBodyScrollStrategyType,\r\n DevConfigService,\r\n WithConfig,\r\n addClassToOrigin,\r\n fadeInOut,\r\n formWithDropDown,\r\n removeClassFromOrigin,\r\n} from 'ng-devui/utils';\r\nimport { WindowRef } from 'ng-devui/window-ref';\r\nimport { ToggleMenuListComponent } from './toggle-menu-list.component';\r\n\r\n@Component({\r\n selector: 'd-toggle-menu-container',\r\n templateUrl: './toggle-menu-container.component.html',\r\n styleUrls: [`./toggle-menu-container.component.scss`],\r\n animations: [fadeInOut],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n preserveWhitespaces: false,\r\n})\r\nexport class ToggleMenuContainerComponent implements OnInit, OnChanges {\r\n @Input() set isOpen(value) {\r\n if (this._isOpen === value) {\r\n // 如果toggle-container自身触发开关,父级组件的isOpen随toggleChange改变,会通过input再次返回导致重复触发,通过值是否变化屏蔽该次触发\r\n return;\r\n }\r\n this._isOpen = value;\r\n this.toggleChange.emit(value);\r\n this.setDocumentClickListener();\r\n if (this.selectWrapper) {\r\n this.dropDownWidth = this.width ? this.width : this.selectWrapper.nativeElement.offsetWidth;\r\n }\r\n if (value) {\r\n addClassToOrigin(this.selectWrapper);\r\n setTimeout(() => {\r\n this.startAnimation = true;\r\n this.changeDetectorRef.detectChanges();\r\n });\r\n } else {\r\n removeClassFromOrigin(this.selectWrapper);\r\n }\r\n }\r\n\r\n get isOpen() {\r\n return this._isOpen;\r\n }\r\n /**\r\n * 【可选】是否appendToBody\r\n */\r\n @Input() appendToBody = false;\r\n @Input() appendToBodyDirections: Array<AppendToBodyDirection | ConnectedPosition> = ['rightDown', 'leftDown', 'rightUp', 'leftUp'];\r\n @Input() @WithConfig() appendToBodyScrollStrategy: AppendToBodyScrollStrategyType;\r\n /**\r\n * 【可选】cdk模式origin width\r\n */\r\n @Input() width: number;\r\n @Input() size: '' | 'sm' | 'lg';\r\n /**\r\n * auto-complete 参数\r\n */\r\n @Input() overview: string;\r\n @Input() position: any;\r\n /**\r\n * 【可选】是否禁用下拉框\r\n */\r\n @Input() disabled = false;\r\n /**\r\n * 【可选】暂停使用下拉功能,不添加禁用效果\r\n */\r\n @Input() paused = false;\r\n /**\r\n * 【可选】是否展示动效\r\n */\r\n @Input() @WithConfig() showAnimation = true;\r\n /**\r\n * 【可选】是否支持聚焦自动展开下拉\r\n */\r\n @Input() toggleOnFocus = false;\r\n @Input() closeScope: 'all' | 'blank' | 'none' = 'all';\r\n @Input() direction: 'up' | 'down' | 'auto' = 'down';\r\n @Input() selectWrapper: ElementRef;\r\n\r\n /**\r\n * select下拉toggle事件,值为true或false\r\n */\r\n @Output() toggleChange = new EventEmitter<any>();\r\n @Output() passEvent = new EventEmitter<any>();\r\n @ViewChild('selectBox', { static: true }) selectBoxElement: ElementRef;\r\n @ViewChild('selectMenu', { static: true }) selectMenuElement: ElementRef;\r\n @ViewChild(CdkConnectedOverlay) connectedOverlay: CdkConnectedOverlay;\r\n @ContentChild(ToggleMenuListComponent) listInstance: ToggleMenuListComponent;\r\n\r\n _isOpen = false;\r\n isInit = true;\r\n isMouseEvent = false;\r\n startAnimation = false;\r\n labelMinHeight = 20; // position.top小于20px时候,表示光标在第一行\r\n popDirection: 'top' | 'bottom' = 'bottom';\r\n menuPosition: VerticalConnectionPos = 'bottom';\r\n scrollStrategy: ScrollStrategy;\r\n cdkConnectedOverlayOrigin: CdkOverlayOrigin;\r\n overlayPositions: Array<ConnectedPosition>;\r\n dropDownWidth: number;\r\n document: Document;\r\n\r\n constructor(\r\n @Inject(DOCUMENT) private doc: any,\r\n public element: ElementRef,\r\n private windowRef: WindowRef,\r\n private ngZone: NgZone,\r\n private renderer: Renderer2,\r\n private changeDetectorRef: ChangeDetectorRef,\r\n private devConfigService: DevConfigService,\r\n private scrollStrategyOption: ScrollStrategyOptions\r\n ) {\r\n this.document = this.doc;\r\n this.scrollStrategy = this.scrollStrategyOption.reposition();\r\n }\r\n\r\n ngOnInit() {\r\n this.isInit = false;\r\n this.setPositions();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n const { appendToBodyDirections, appendToBodyScrollStrategy } = changes;\r\n const globalScrollStrategy = this.devConfigService.getConfigForApi('appendToBodyScrollStrategy');\r\n if (appendToBodyDirections) {\r\n this.setPositions();\r\n }\r\n if (this.appendToBodyScrollStrategy && (appendToBodyScrollStrategy || globalScrollStrategy)) {\r\n const func = this.scrollStrategyOption[this.appendToBodyScrollStrategy];\r\n this.scrollStrategy = func();\r\n }\r\n }\r\n\r\n animationEnd() {\r\n if (!this.isOpen && this.selectMenuElement && this.showAnimation) {\r\n const targetElement = this.selectMenuElement.nativeElement;\r\n this.startAnimation = false;\r\n setTimeout(() => {\r\n // 动画会覆盖导致display还是block, 所以要等动画覆盖完\r\n this.renderer.setStyle(targetElement, 'display', 'none');\r\n });\r\n }\r\n }\r\n\r\n setPositions() {\r\n if (this.appendToBodyDirections && this.appendToBodyDirections.length > 0) {\r\n this.overlayPositions = this.appendToBodyDirections\r\n .map((position) => {\r\n if (typeof position === 'string') {\r\n return AppendToBodyDirectionsConfig[position];\r\n } else {\r\n return position;\r\n }\r\n })\r\n .filter((position) => position !== undefined);\r\n } else {\r\n this.overlayPositions = undefined;\r\n }\r\n }\r\n\r\n updatePosition() {\r\n if (this.appendToBody) {\r\n setTimeout(() => {\r\n if (this.connectedOverlay && this.connectedOverlay.overlayRef) {\r\n this.connectedOverlay.overlayRef.updatePosition();\r\n }\r\n });\r\n }\r\n }\r\n\r\n setPassEvent(event, type) {\r\n if (this.isOpen || this.paused) {\r\n this.passEvent.emit({ event, type });\r\n }\r\n }\r\n\r\n onPositionChange(position: ConnectedOverlayPositionChange) {\r\n this.menuPosition = position.connectionPair.originY;\r\n }\r\n\r\n setDocumentClickListener() {\r\n this.ngZone.runOutsideAngular(() => {\r\n if (this.isOpen) {\r\n this.document.addEventListener('click', this.onDocumentClick);\r\n } else {\r\n this.document.removeEventListener('click', this.onDocumentClick);\r\n }\r\n });\r\n }\r\n\r\n onDocumentClick = (event: Event) => {\r\n if (this.listInstance && this.isOpen && this.selectBoxElement && !this.selectBoxElement.nativeElement.contains(event.target)) {\r\n this.isOpen = false;\r\n this.listInstance.selectIndex = this.listInstance.activeIndex ? this.listInstance.activeIndex : -1;\r\n this.changeDetectorRef.detectChanges();\r\n }\r\n };\r\n\r\n // mousedown mouseup解决focus与click冲突问题\r\n @HostListener('mousedown', ['$event'])\r\n public setMouseEventTrue(event) {\r\n this.isMouseEvent = true;\r\n }\r\n @HostListener('mouseup', ['$event'])\r\n public setMouseEventFalse(event) {\r\n this.isMouseEvent = false;\r\n }\r\n\r\n autoToggle(event) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (this.toggleOnFocus && !this.disabled && !this.paused && !this.isOpen && !this.isMouseEvent) {\r\n this.toggle();\r\n }\r\n }\r\n\r\n toggle(event?: Event) {\r\n if (this.disabled || this.paused) {\r\n this.isOpen = false;\r\n return;\r\n }\r\n if (!this.isOpen) {\r\n if (!this.appendToBody) {\r\n let direction = '';\r\n switch (this.direction) {\r\n case 'auto':\r\n direction = this.isBottomRectEnough() ? 'bottom' : 'top';\r\n break;\r\n case 'down':\r\n direction = 'bottom';\r\n break;\r\n case 'up':\r\n direction = 'top';\r\n break;\r\n default:\r\n direction = 'bottom';\r\n }\r\n this.popDirection = <any>direction;\r\n } else {\r\n this.updateCdkConnectedOverlayOrigin();\r\n }\r\n } else {\r\n if (!this.showAnimation) {\r\n this.startAnimation = false;\r\n }\r\n if (this.closeScope === 'none' || (this.closeScope === 'blank' && this.element.nativeElement.contains(event.target))) {\r\n return;\r\n }\r\n }\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n isBottomRectEnough() {\r\n const selectMenuElement = this.selectWrapper.nativeElement;\r\n const selectInputElement = this.selectBoxElement;\r\n const displayStyle = selectMenuElement.style.display || (<any>window).getComputedStyle(selectMenuElement).display;\r\n let tempStyle;\r\n if (displayStyle === 'none') {\r\n // 必要, 否则首次展开必有问题, 如果animationEnd之后设置为none也会有问题\r\n tempStyle = {\r\n visibility: selectMenuElement.style.visibility,\r\n display: selectMenuElement.style.display,\r\n transform: selectMenuElement.style.transform,\r\n };\r\n this.renderer.setStyle(selectMenuElement, 'visibility', 'hidden');\r\n this.renderer.setStyle(selectMenuElement, 'display', 'block');\r\n this.renderer.setStyle(selectMenuElement, 'transform', 'translate(0, -9999)');\r\n }\r\n const elementHeight = selectMenuElement.offsetHeight;\r\n const bottomDistance = this.windowRef.innerHeight - selectInputElement.nativeElement.getBoundingClientRect().bottom;\r\n const isBottomEnough = bottomDistance >= elementHeight;\r\n if (displayStyle === 'none') {\r\n this.renderer.setStyle(selectMenuElement, 'visibility', tempStyle.visibility);\r\n this.renderer.setStyle(selectMenuElement, 'display', tempStyle.display);\r\n this.renderer.setStyle(selectMenuElement, 'transform', tempStyle.transform);\r\n }\r\n return isBottomEnough;\r\n }\r\n\r\n updateCdkConnectedOverlayOrigin() {\r\n if (this.selectWrapper?.nativeElement) {\r\n this.cdkConnectedOverlayOrigin = new CdkOverlayOrigin(formWithDropDown(this.selectWrapper) || this.selectWrapper.nativeElement);\r\n }\r\n }\r\n}\r\n","<div\r\n #selectBox\r\n class=\"devui-toggle-menu-container devui-toggle-menu{{ size ? '-' + size : '' }} {{ disabled ? 'disabled' : '' }}\"\r\n [tabindex]=\"0\"\r\n (click)=\"toggle($event)\"\r\n (focus)=\"autoToggle($event); setPassEvent($event, 'focus')\"\r\n (blur)=\"setPassEvent($event, 'blur')\"\r\n (keydown.esc)=\"setPassEvent($event, 'keydown.esc')\"\r\n (keydown.ArrowUp)=\"setPassEvent($event, 'keydown.ArrowUp')\"\r\n (keydown.ArrowDown)=\"setPassEvent($event, 'keydown.ArrowDown')\"\r\n (keydown.enter)=\"setPassEvent($event, 'keydown.enter')\"\r\n (keydown)=\"setPassEvent($event, 'keydown')\"\r\n>\r\n <ng-content></ng-content>\r\n <ng-container *ngIf=\"appendToBody; else selectDropdownTpl\">\r\n <ng-template\r\n cdk-connected-overlay\r\n [cdkConnectedOverlayOrigin]=\"cdkConnectedOverlayOrigin\"\r\n [cdkConnectedOverlayWidth]=\"dropDownWidth\"\r\n [cdkConnectedOverlayOpen]=\"isOpen\"\r\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\r\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\r\n (positionChange)=\"onPositionChange($event)\"\r\n (backdropClick)=\"isOpen = false\"\r\n (detach)=\"isOpen && (isOpen = false)\"\r\n >\r\n <ng-template [ngTemplateOutlet]=\"selectDropdownTpl\"></ng-template>\r\n </ng-template>\r\n </ng-container>\r\n <ng-template #selectDropdownTpl>\r\n <div\r\n #selectMenu\r\n class=\"devui-dropdown-menu\"\r\n [ngClass]=\"{\r\n 'devui-dropdown-menu-cdk': appendToBody,\r\n 'devui-custom-right': listInstance?.customViewDirection === 'right',\r\n 'devui-custom-left': listInstance?.customViewDirection === 'left',\r\n 'devui-custom-top': listInstance?.customViewDirection === 'top',\r\n 'devui-dropdown-menu-multiple': listInstance?.multiple\r\n }\"\r\n [@fadeInOut]=\"isOpen && startAnimation ? (appendToBody ? menuPosition : popDirection) : 'void'\"\r\n (@fadeInOut.done)=\"animationEnd()\"\r\n [@.disabled]=\"!showAnimation\"\r\n >\r\n <ng-content select=\"d-toggle-menu-list\"></ng-content>\r\n </div>\r\n </ng-template>\r\n</div>\r\n","import { ChangeDetectionStrategy, Component, HostBinding, Input, TemplateRef } from '@angular/core';\n\n@Component({\n selector: 'd-toggle-menu-input',\n templateUrl: './toggle-menu-input.component.html',\n styleUrls: [`./toggle-menu-input.component.scss`],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ToggleMenuInputComponent {\n @Input() value: any;\n @Input() inputValue: any;\n @Input() inputWidth: string;\n @Input() disabled = false;\n @Input() readonly = false;\n @Input() filterKey: string;\n @Input() isDisabledCustomTemplate = false;\n @Input() customTemplate: TemplateRef<any>;\n @HostBinding('style.width')\n get width() {\n return this.inputWidth || 'inherit';\n }\n}\n","<ng-container *ngIf=\"!isDisabledCustomTemplate; else defaultInputTemplate\">\n <div class=\"devui-toggle-menu-input-template-container\">\n <ng-template\n [ngTemplateOutlet]=\"customTemplate\"\n [ngTemplateOutletContext]=\"{\n option: value,\n filterKey: filterKey,\n position: 'result',\n inputValue: inputValue\n }\"\n ></ng-template>\n </div>\n</ng-container>\n\n<ng-template #defaultInputTemplate>\n <input\n type=\"text\"\n class=\"devui-form-control devui-select-input devui-input\"\n autocomplete=\"off\"\n [disabled]=\"disabled\"\n [minLength]=\"0\"\n [tabindex]=\"-1\"\n [readonly]=\"readonly\"\n [value]=\"inputValue || ''\"\n />\n</ng-template>\n","import { Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core';\nimport { ToggleMenuListItem } from './toggle-menu.type';\n\n@Component({\n selector: 'd-toggle-menu-label',\n templateUrl: './toggle-menu-label.component.html',\n styleUrls: [`./toggle-menu-label.component.scss`],\n})\nexport class ToggleMenuLabelComponent {\n @Input() mode: 'normal' | 'scroll-y' | 'multiple-line' | string;\n @Input() multiItems: Array<ToggleMenuListItem> = [];\n @Input() disabled = false;\n @Input() maxWidth: string;\n @Input() maxHeight: string;\n @Input() optionDisabledKey = '';\n @Input() customViewTemplate: TemplateRef<any>;\n @Input() valueParser: (item: any) => any;\n @Output() removeChange = new EventEmitter<any>();\n\n trackByOptionPointer(index, item) {\n return item.option;\n }\n\n removeItem(item, event, index) {\n this.removeChange.emit({ ...item, event, index });\n }\n}\n","<ul class=\"devui-select-tag-list devui-scrollbar {{ mode }}\" [style.maxHeight]=\"maxHeight\" *ngIf=\"multiItems.length > 0\">\n <li\n class=\"devui-select-tag-item\"\n *ngFor=\"let item of multiItems; let index = index; trackBy: trackByOptionPointer\"\n [style.maxWidth]=\"maxWidth\"\n [ngClass]=\"{\n disabled: disabled || (optionDisabledKey && item.option[optionDisabledKey])\n }\"\n >\n <d-tag\n [deletable]=\"!(disabled || (optionDisabledKey && item.option[optionDisabledKey]))\"\n [maxWidth]=\"'100%'\"\n [tag]=\"valueParser(item.option)\"\n [customViewTemplate]=\"customViewTemplate\"\n (tagDelete)=\"removeItem(item, $event?.event, index)\"\n ></d-tag>\n </li>\n</ul>\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core';\nimport { ToggleMenuListItem } from './toggle-menu.type';\n\n@Component({\n selector: 'd-toggle-menu-list-item',\n templateUrl: './toggle-menu-list-item.component.html',\n styleUrls: ['./toggle-menu-list-item.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ToggleMenuListItemComponent {\n @Input() item: ToggleMenuListItem;\n @Input() index: number;\n @Input() selectIndex: number;\n @Input() activeIndex: number;\n /**\n * 【可选】决定下拉框每项文字如何显示,默认显示filterKey字段或者本身的值\n */\n // @deprecated\n @Input() formatter: (item: any) => string;\n /**\n * 【当传入资源(options)类型为Array<{key: value},必选】针对传入资源options的每项对应字段做过滤操作\n */\n @Input() filterKey: string;\n /**\n * 【当传入资源(options)类型为Array<{key: value},必选】针对传入资源options的每项对应字段做禁用操作的key\n */\n @Input() optionDisabledKey = '';\n /**\n * 【当传入资源(options)类型为Array<{key: value},可选】如使用分组需设置\n */\n @Input() optionGroupKey = '';\n /**\n * 【可选】是否允许高亮选项\n */\n @Input() highlightToggle = true;\n /**\n * 【可选】下拉高亮css\n */\n @Input() highlightItemClass = 'active';\n /**\n * 【可选】是否支持多选\n */\n @Input() multiple: boolean;\n /**\n * 【可选】是否需要关键字高亮显示\n */\n @Input() isShowKeyword: boolean;\n /**\n * 【可选】auto-complete 中需要高亮显示的关键字\n */\n @Input() keyword: string;\n @Input() customTemplate: TemplateRef<any>;\n\n // @deprecated\n @Input() color: string;\n @Output() chooseItem = new EventEmitter<any>();\n\n constructor() {\n this.formatter = (item) => (item ? item[this.filterKey] || item.label || item.toString() : '');\n }\n\n choose(option, index, event?: Event) {\n this.chooseItem.emit({ option, index, event });\n }\n}\n","<li\n title=\"{{ formatter(item.option) }}\"\n class=\"devui-dropdown-item devui-toggle-menu{{ multiple ? '-multiple-' : '-' }}item {{\n highlightToggle && item.isChecked ? highlightItemClass : ''\n }}\"\n [class.selected]=\"selectIndex === index && item.id !== activeIndex\"\n [class.disabled]=\"optionDisabledKey && item.option[optionDisabledKey]\"\n [class.group]=\"optionGroupKey && item.option[optionGroupKey]\"\n (click)=\"choose(item.option, item.id, $event)\"\n>\n <ng-content select=\"[itemPrefix]\"></ng-content>\n <ng-template\n [ngTemplateOutlet]=\"customTemplate || (multiple ? checkBoxItem : isShowKeyword ? defaultHighlight : defaultItem)\"\n [ngTemplateOutletContext]=\"\n isShowKeyword\n ? {\n item: item.option,\n formatter: formatter,\n keyword: keyword,\n $index: index\n }\n : multiple\n ? {\n option: item.option,\n checked: item.isChecked,\n filterKey: filterKey,\n position: 'list',\n template: checkBoxItem,\n $index: index\n }\n : {\n option: item.option,\n filterKey: filterKey,\n position: 'list',\n template: defaultItem,\n $index: index\n }\n \"\n >\n </ng-template>\n <ng-content select=\"[itemSuffix]\"></ng-content>\n</li>\n\n<ng-template #defaultItem let-option=\"option\">\n {{ formatter(option) }}\n</ng-template>\n\n<ng-template #defaultHighlight let-item=\"item\" let-keyword=\"keyword\">\n <d-highlight [value]=\"formatter(item)\" [term]=\"keyword\"></d-highlight>\n</ng-template>\n\n<ng-template #checkBoxItem let-option=\"option\" let-checked=\"checked\">\n <d-checkbox\n [color]=\"color\"\n [cssClass]=\"'devui-select-checkbox'\"\n [disabled]=\"option[optionDisabledKey]\"\n [label]=\"formatter(option)\"\n [ngModel]=\"checked\"\n >\n </d-checkbox>\n</ng-template>\n","import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\nimport { DevConfigService, WithConfig } from 'ng-devui/utils';\n\n@Component({\n selector: 'd-toggle-menu-operation',\n templateUrl: './toggle-menu-operation.component.html',\n styleUrls: [`./toggle-menu-operation.component.scss`],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ToggleMenuOperationComponent {\n @Input() controlConfig: {\n clear?: boolean;\n chevron?: boolean;\n };\n @Input() @WithConfig() showAnimation = true;\n @Input() chevronStatus = false;\n @Output() operationChangeEvent = new EventEmitter<any>();\n\n constructor(private devConfigService: DevConfigService) {}\n\n operationFn(event, operate) {\n this.operationChangeEvent.emit({ event, operate });\n }\n}\n","<div class=\"devui-toggle-menu-operation-container\">\n <span\n *ngIf=\"controlConfig?.clear\"\n class=\"devui-select-clear-icon\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"operationFn($event, 'clear')\"\n >\n <svg\n width=\"16px\"\n height=\"16px\"\n viewBox=\"0 0 16 16\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 Z M5.87867966,5.17157288 C5.68341751,4.97631073 5.36683502,4.97631073 5.17157288,5.17157288 C4.99800652,5.34513923 4.97872137,5.61456363 5.11371742,5.80943177 L5.17157288,5.87867966 L7.29218611,7.99929289 L5.17157288,10.1213203 C4.97631073,10.3165825 4.97631073,10.633165 5.17157288,10.8284271 C5.34513923,11.0019935 5.61456363,11.0212786 5.80943177,10.8862826 L5.87867966,10.8284271 L7.99929289,8.70639967 L10.1213203,10.8284271 C10.3165825,11.0236893 10.633165,11.0236893 10.8284271,10.8284271 C11.0019935,10.6548608 11.0212786,10.3854364 10.8862826,10.1905682 L10.8284271,10.1213203 L8.70710678,8 L10.8284271,5.87867966 C11.0236893,5.68341751 11.0236893,5.36683502 10.8284271,5.17157288 C10.6548608,4.99800652 10.3854364,4.97872137 10.1905682,5.11371742 L10.1213203,5.17157288 L8,7.29289322 L5.87867966,5.17157288 Z\"\n fill-rule=\"nonzero\"\n ></path>\n </g>\n </svg>\n </span>\n <span\n *ngIf=\"controlConfig?.chevron\"\n class=\"devui-toggle-menu-chevron-icon\"\n [ngClass]=\"{ 'devui-toggle-menu-chevron-icon-animation': showAnimation, 'devui-toggle-menu-chevron-icon-open': chevronStatus }\"\n >\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 16 16\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n >\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M12.1464466,6.85355339 L8.35355339,10.6464466 C8.15829124,10.8417088 7.84170876,10.8417088 7.64644661,10.6464466 L3.85355339,6.85355339 C3.65829124,6.65829124 3.65829124,6.34170876 3.85355339,6.14644661 C3.94732158,6.05267842 4.07449854,6 4.20710678,6 L11.7928932,6 C12.0690356,6 12.2928932,6.22385763 12.2928932,6.5 C12.2928932,6.63260824 12.2402148,6.7597852 12.1464466,6.85355339 Z\"\n fill-rule=\"nonzero\"\n ></path>\n </g>\n </svg>\n </span>\n</div>\n","import { Component, Input, TemplateRef } from '@angular/core';\n\n@Component({\n selector: 'd-toggle-menu-placeholder',\n template: `\n <ng-container *ngIf=\"isTemplate; else defaultTemplate\"></ng-container>\n <ng-template #defaultTemplate\n ><span class=\"devui-placeholder\">{{ placeholder }}</span></ng-template\n >\n `,\n styleUrls: [`./toggle-menu-placeholder.component.scss`],\n})\nexport class ToggleMenuPlaceholderComponent {\n @Input() placeholder: TemplateRef<any> | string;\n get isTemplate() {\n return this.placeholder && typeof this.placeholder !== 'string';\n }\n}\n","import {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostBinding,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n} from '@angular/core';\r\nimport { Observable, Subscription, fromEvent, of } from 'rxjs';\r\nimport { debounceTime, filter, map } from 'rxjs/operators';\r\n\r\n@Component({\r\n selector: 'd-toggle-menu-search',\r\n templateUrl: './toggle-menu-search.component.html',\r\n styleUrls: [`./toggle-menu-search.component.scss`],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n preserveWhitespaces: false,\r\n})\r\nexport class ToggleMenuSearchComponent implements OnInit, AfterViewInit, OnDestroy {\r\n @Input() searchPlaceholder: string;\r\n @Input() isShowSearchIcon = true;\r\n @Input() inputValue: string;\r\n @Input() inputWidth: string;\r\n @Input() filterKey: string;\r\n @Input() maxLength: number;\r\n @Input() disabled = false;\r\n @Input() spellcheck = false;\r\n @Input() options = [];\r\n @Input() delay = 300;\r\n /**\r\n * 【可选】决定下拉框没项文字如何显示,默认显示filterKey字段或者本身的值\r\n */\r\n // @deprecated\r\n @Input() formatter: (item: any) => string;\r\n /**\r\n * 【可选】搜索函数,当需要自定义下拉选择过滤规则时可以使用\r\n * 请保证返回值有id和option字段,id是确保尤其多选的时候能正确索引对应选项\r\n * 简单实现参考:\r\n * search = (term) => {\r\n * return of(\r\n * [Lily, May, Jorsh, Shiwa, Nanth]\r\n * .map((option, index) => ({id: index, option: option}))\r\n * .filter(item => item.option.name.toLowerCase().indexOf(term.toLowerCase()) !== -1)\r\n * );\r\n * }\r\n */\r\n @Input() searchFn: (term: string) => Observable<Array<{ id: string | number; option: any }>>;\r\n @Output() searchInputValueChange = new EventEmitter<any>();\r\n @HostBinding('style.width')\r\n get width() {\r\n return this.inputWidth || 'inherit';\r\n }\r\n\r\n filterSubscription: Subscription;\r\n\r\n constructor(public el: ElementRef) {\r\n this.formatter = (item) => {\r\n const str = String(item) ? item.toString() : '';\r\n return typeof item === 'object' ? item[this.filterKey] || '' : str;\r\n };\r\n }\r\n\r\n ngOnInit() {\r\n if (!this.searchFn) {\r\n this.searchFn = (term: any) => {\r\n return of(\r\n (this.options ? this.options : [])\r\n .map((option, index) => ({ id: index, option }))\r\n .filter((item) => this.formatter(item.option).toLowerCase().indexOf(term.toLowerCase()) !== -1)\r\n );\r\n };\r\n }\r\n }\r\n\r\n ngAfterViewInit() {\r\n this.el.nativeElement.focus();\r\n if (!this.filterSubscription) {\r\n // 避免重复订阅\r\n this.filterSubscription = fromEvent(this.el.nativeElement, 'input')\r\n .pipe(\r\n map((e: any) => e.target.value),\r\n filter((term) => !this.disabled && this.searchFn && term.length >= 0),\r\n debounceTime(this.delay)\r\n )\r\n .subscribe((term) => this.searchInputValueChange.emit(term));\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.filterSubscription) {\r\n this.filterSubscription.unsubscribe();\r\n }\r\n }\r\n}\r\n","<div class=\"devui-toggle-menu-search\">\r\n <input\r\n name=\"search\"\r\n type=\"text\"\r\n autocomplete=\"off\"\r\n class=\"devui-form-control devui-select-search devui-select-input\"\r\n [value]=\"inputValue || ''\"\r\n [disabled]=\"disabled\"\r\n [spellcheck]=\"spellcheck\"\r\n [maxLength]=\"maxLength\"\r\n [placeholder]=\"searchPlaceholder\"\r\n (trim)=\"(false)\"\r\n />\r\n <span class=\"devui-toggle-menu-search-icon\">\r\n <svg\r\n *ngIf=\"isShowSearchIcon\"\r\n width=\"14px\"\r\n height=\"14px\"\r\n viewBox=\"0 0 14 14\"\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n class=\"svg-icon-search\"\r\n style=\"vertical-align: middle; margin-top: -4px\"\r\n >\r\n <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\r\n <g transform=\"translate(-1.000000, -1.000000)\">\r\n <path\r\n d=\"M7.30811922,1 C10.7919973,1 13.6162384,3.82424117 13.6162384,7.30811922 C13.6162384,8.72507634 13.149053,10.0329164 12.3603151,11.0860065 L14.7360564,13.4616238 C15.0879812,13.8135487 15.0879812,14.3841316 14.7360564,14.7360564 C14.3841316,15.0879812 13.8135487,15.0879812 13.4616238,14.7360564 L11.0860065,12.3603151 C10.0329164,13.149053 8.72507634,13.6162384 7.30811922,13.6162384 C3.82424117,13.6162384 1,10.7919973 1,7.30811922 C1,3.82424117 3.82424117,1 7.30811922,1 Z M7.31,2.51 C4.6590332,2.51 2.51,4.6590332 2.51,7.31 C2.51,9.9609668 4.6590332,12.11 7.31,12.11 C9.9609668,12.11 12.11,9.9609668 12.11,7.31 C12.11,4.6590332 9.9609668,2.51 7.31,2.51 Z\"\r\n fill-rule=\"nonzero\"\r\n ></path>\r\n </g>\r\n </g>\r\n </svg>\r\n </span>\r\n <ng-content></ng-content>\r\n</div>\r\n","import { OverlayModule } from '@angular/cdk/overlay';\nimport { ScrollingModule } from '@angular/cdk/scrolling';\nimport { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { CheckBoxModule } from 'ng-devui/checkbox';\nimport { LoadingModule } from 'ng-devui/loading';\nimport { TagsModule } from 'ng-devui/tags';\nimport { HighlightModule, LazyLoadModule } from 'ng-devui/utils';\nimport { WindowRefModule } from 'ng-devui/window-ref';\nimport { ToggleMenuContainerComponent } from './toggle-menu-container.component';\nimport { ToggleMenuInputComponent } from './toggle-menu-input.component';\nimport { ToggleMenuLabelComponent } from './toggle-menu-label.component';\nimport { ToggleMenuListItemComponent } from './toggle-menu-list-item.component';\nimport { ToggleMenuListComponent } from './toggle-menu-list.component';\nimport { ToggleMenuOperationComponent } from './toggle-menu-operation.component';\nimport { ToggleMenuPlaceholderComponent } from './toggle-menu-placeholder.component';\nimport { ToggleMenuSearchComponent } from './toggle-menu-search.component';\n\n@NgModule({\n imports: [\n CommonModule,\n FormsModule,\n CheckBoxModule,\n HighlightModule,\n LazyLoadModule,\n LoadingModule,\n OverlayModule,\n ScrollingModule,\n WindowRefModule,\n TagsModule,\n ],\n declarations: [\n ToggleMenuContainerComponent,\n ToggleMenuOperationComponent,\n ToggleMenuInputComponent,\n ToggleMenuLabelComponent,\n ToggleMenuListItemComponent,\n ToggleMenuListComponent,\n ToggleMenuPlaceholderComponent,\n ToggleMenuSearchComponent,\n ],\n exports: [\n ToggleMenuContainerComponent,\n ToggleMenuOperationComponent,\n ToggleMenuInputComponent,\n ToggleMenuLabelComponent,\n ToggleMenuListItemComponent,\n ToggleMenuListComponent,\n ToggleMenuPlaceholderComponent,\n ToggleMenuSearchComponent,\n ],\n})\nexport class ToggleMenuModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i2","i5","i1","i3","i4"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;MA6Ba,uBAAuB,CAAA;AA2DlC;;AAEG;IACH,IAAa,YAAY,CAAC,KAAK,EAAA;QAC7B,IAAI,CAAC,aAAa,GAAG,CAAG,EAAA,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA,EAAA,CAAI,CAAC;KACjD;AAED,IAAA,IAAI,YAAY,GAAA;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;KAC3B;AAgCD,IAAA,IAAI,yBAAyB,GAAA;QAC3B,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC;AACjI,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC9D,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC;AACtC,QAAA,OAAO,QAAQ,CAAC;KACjB;IAuBD,WAAoB,CAAA,iBAAoC,