UNPKG

ng-zorro-antd-mobile

Version:

An enterprise-class mobile UI components based on Ant Design and Angular

632 lines (623 loc) 29.4 kB
import * as i0 from '@angular/core'; import { EventEmitter, Injectable, ViewContainerRef, Component, ViewEncapsulation, ViewChild, HostListener, Injector, forwardRef, Directive, Input, Output, NgModule } from '@angular/core'; import * as i3 from '@angular/common'; import { CommonModule } from '@angular/common'; import { getEventTarget, getVelocity, PopupService } from 'ng-zorro-antd-mobile/core'; import * as i2 from 'ng-zorro-antd-mobile/locale-provider'; import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { OverlayModule } from '@angular/cdk/overlay'; class PickerOptions { constructor() { this.data = []; this.value = []; this.cols = 3; this.mask = true; this.title = ''; this.okText = '确定'; this.dismissText = '取消'; this.disabled = false; this.cascade = true; this.appendToBody = false; this.onDismiss = new EventEmitter(); this.onPickerChange = new EventEmitter(); this.indicatorStyle = {}; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerOptions }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerOptions, decorators: [{ type: Injectable }] }); class PickerRef { } class PickerComponent extends PickerRef { panstart(event) { if (!event.target.classList.contains('am-picker-col-mask') || this.options.disabled) { return; } this.isMouseDown = true; event.preventDefault(); this.dom = getEventTarget(event).target.parentElement.children[2]; this.len = this.dom.children.length; this.maxY = -(this.len - 1); if (this.dom.style.transform === 'translateY(0px)') { this.currentY = 0; this.maxY = -(this.len - 1); } else if (this.selectedTarget.length > 0) { this.selectedTarget.forEach(item => { if (item.targetId === event.target.id) { this.currentY = item.currentY; } }); } this.startY = getEventTarget(event).clientY; } panmove(event) { if (!event.target.classList.contains('am-picker-col-mask') || !this.isMouseDown || this.options.disabled) { return; } event.preventDefault(); const ev = getEventTarget(event); this.differY = ev.clientY - this.startY; this.Velocity.record(this.differY); this.dom.style.transition = 'transform 0s'; this.dom.style.transform = `translateY(${this.currentY * this.lineHeight + this.differY}px)`; } panend(event) { if (!event.target.classList.contains('am-picker-col-mask') || !this.isMouseDown || this.options.disabled) { return; } this.isMouseDown = false; event.preventDefault(); const ev = getEventTarget(event); this.differY = ev.clientY - this.startY; let time = 0.3; const velocityTemp = this.Velocity.getVelocity(this.differY) * 4; if (getVelocity) { this.differY = velocityTemp * 40 + this.differY; time = Math.abs(velocityTemp) * 0.1; } this.dom.style.transition = 'transform ' + (time < 0.3 ? 0.3 : time) + 's'; if (this.differY <= -this.lineHeight / 2) { this.currentY += Math.floor(this.differY / this.lineHeight + 0.5); if (this.currentY <= this.maxY) { this.currentY = this.maxY; } } else if (this.differY >= this.lineHeight / 2) { this.currentY += Math.floor(this.differY / this.lineHeight + 0.5); if (this.currentY >= 0) { this.currentY = 0; } } if (this.selectedTarget.length > 0) { let hasKey = false; this.selectedTarget.forEach(item => { if (item.targetId === event.target.id) { hasKey = true; item.targetId = event.target.id; item.currentY = this.currentY; } else if (parseInt(item.targetId, 0) > parseInt(event.target.id, 0) && this.options.cascade) { item.currentY = 0; } }); if (!hasKey) { this.selectedTarget.push({ targetId: event.target.id, currentY: this.currentY }); } } else { this.selectedTarget.push({ targetId: event.target.id, currentY: this.currentY }); } this.dom.style.transform = `translateY(${this.currentY * this.lineHeight}px)`; this.index = Math.floor(Math.abs(this.currentY / 1)); this.setCurrentSelected(parseInt(event.target.id, 0), this.index); if (this.options.value !== this.combineReslut()) { this.options.onPickerChange.emit(this.combineReslut()); this.onChange(this.combineReslut()); } } constructor(elementRef, options, _localeProviderService) { super(); this.elementRef = elementRef; this.options = options; this._localeProviderService = _localeProviderService; this.transitionName = 'am-slide-up-enter am-slide-up-enter-active'; this.maskTransitionName = 'am-fade-enter am-fade-enter-active'; this.startY = 0; this.differY = 0; this.currentY = 0; this.len = 0; this.dom = null; this.index = 0; this.maxY = 0; this.lineHeight = 34; this.dataForRender = []; this.selectedTarget = []; this.isMouseDown = false; this.Velocity = getVelocity(); this._unsubscribe$ = new Subject(); this.onChange = (_) => { }; } init() { if (this.dataForRender.length === 0 && this.generateArrayData(this.options.data).length > 0) { this.dataForRender.push(this.generateArrayData(this.options.data)); } if (this.options.value.length > 0) { this.getInitValueIndex(this.dataForRender); } else { this.checkArrayDeep(this.options.data[0]); for (let index = 0; index < this.dataForRender.length; index++) { this.selectedTarget.push({ targetId: `${index}`, currentY: 0 }); } } } getInitValueIndex(dataTemp) { const self = this; self.selectedTarget = []; self.options.value.forEach((element, i) => { dataTemp.forEach((item, j) => { item.forEach((item1, k) => { if ((element === item1.label || element === item1.value || element === item1) && i === j) { self.checkArrayDeep(self.dataForRender[i][k], false); self.selectedTarget.push({ targetId: `${i}`, currentY: -k }); } }); }); }); } reloadPicker() { if (!this._picker || this._picker === undefined) { return; } this.currentPicker = this._picker.element.nativeElement; if (this.currentPicker && this.currentPicker.children.length > 0) { const self = this; setTimeout(() => { self.selectedTarget.forEach((item, i) => { self.currentPicker.children[i].children[2].style.transition = 'transform .3s'; const index = parseInt(item.currentY, 0); self.currentPicker.children[i].children[2].style.transform = `translateY(${index * self.lineHeight}px)`; }); }, 0); } } generateArrayData(targetArr) { const tempArr = []; if (targetArr instanceof Array) { targetArr.forEach((item, i) => { if (item instanceof Array) { const keys = Object.keys(item); const element = {}; keys.forEach(key => { element[key] = targetArr[i][key] || targetArr[i]; }); tempArr.push(element); } else { tempArr.push(item); } }); return tempArr; } return []; } checkArrayDeep(parent, init = true) { if (parent instanceof Object && parent.children && parent.children.length > 0) { if (this.generateArrayData(parent.children).length > 0 && this.dataForRender.length < this.options.cols) { let hasValue = false; this.dataForRender.filter((item, index) => { if (JSON.stringify(item) === JSON.stringify(parent.children)) { hasValue = true; } }); if (!hasValue) { this.dataForRender.push(this.generateArrayData(parent.children)); } if (init) { this.checkArrayDeep(parent.children[0]); } } } } ok() { if (this.options.updateNgModel) { this.options.updateNgModel(this.combineReslut()); } if (this.options.confirm) { this.options.confirm(this.combineReslut()); } this.setTransitionName(); } combineReslut() { const result = []; const self = this; self.selectedTarget.forEach(item => { if (self.dataForRender.length > 0 && self.dataForRender.length >= parseInt(item.targetId, 0) + 1) { const curItem = self.dataForRender[parseInt(item.targetId, 0)][-item.currentY]; if (curItem !== undefined) { result.push(curItem); } } }); return result; } cancel() { this.setTransitionName(); this.options.onDismiss.emit(); if (this.options.cancel) { this.options.cancel(); } } setTransitionName() { this.transitionName = 'am-slide-up-leave am-slide-up-leave-active'; this.maskTransitionName = 'am-fade-leave am-fade-leave-active'; setTimeout(() => { this.options.hidePicker(); }, 200); } setCurrentSelected(target, index) { if (!this.options.cascade) { return; } const a = this.dataForRender.slice(0, target + 1); this.dataForRender = a; this.checkArrayDeep(this.dataForRender[target][index]); if (this.selectedTarget.length > 0 && this.selectedTarget.length < this.dataForRender.length) { for (let i = 0; i < this.dataForRender.length; i++) { if (i > target) { if (i < this.selectedTarget.length) { this.selectedTarget[i] = { targetId: `${i}`, currentY: 0 }; } else { this.selectedTarget.push({ targetId: `${i}`, currentY: 0 }); } } } } setTimeout(() => { this.dataForRender.forEach((item, i) => { if (target !== `${i}` && i > target) { this._picker.element.nativeElement.children[i].children[2].style.transition = 'transform .3s'; this._picker.element.nativeElement.children[i].children[2].style.transform = 'translateY(0px)'; } }); }, 0); } getInstance() { return this; } getElement() { return this.elementRef && this.elementRef.nativeElement; } close() { if (this.options.hidePicker) { this.options.hidePicker(); } } destroy() { this.close(); } ngOnInit() { this.init(); this._localeProviderService.localeChange.pipe(takeUntil(this._unsubscribe$)).subscribe(_ => { const locale = this._localeProviderService.getLocaleSubObj('Picker'); this.options.okText = this.options.okText === '确定' ? locale.okText : this.options.okText; this.options.dismissText = this.options.dismissText === '取消' ? locale.dismissText : this.options.dismissText; }); } ngAfterViewInit() { this.reloadPicker(); } ngOnDestroy() { this._unsubscribe$.next(); this._unsubscribe$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerComponent, deps: [{ token: i0.ElementRef }, { token: PickerOptions }, { token: i2.LocaleProviderService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.8", type: PickerComponent, selector: "Picker", host: { listeners: { "mousedown": "panstart($event)", "touchstart": "panstart($event)", "mousemove": "panmove($event)", "touchmove": "panmove($event)", "mouseup": "panend($event)", "mouseleave": "panend($event)", "touchend": "panend($event)" } }, viewQueries: [{ propertyName: "_picker", first: true, predicate: ["picker"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: "<div *ngIf=\"options.mask\" class=\"am-picker-popup-mask {{ maskTransitionName }}\" (click)=\"cancel()\"></div>\n<div class=\"am-picker-popup am-picker-popup-wrap {{ transitionName }}\" style=\" min-height: 280px\">\n <div class=\"am-picker-popup-content\">\n <div class=\"am-picker-popup-body\">\n <div>\n <div class=\"am-picker-popup-header\">\n <div class=\"am-picker-popup-item am-picker-popup-header-left\" (click)=\"cancel()\">\n {{ options.dismissText }}\n </div>\n <div class=\"am-picker-popup-item am-picker-popup-title\">{{ options.title }}</div>\n <div class=\"am-picker-popup-item am-picker-popup-header-right\" (click)=\"ok()\">{{ options.okText }}</div>\n </div>\n <div class=\"am-picker\" style=\"flex-direction: row; align-items: center;\" #picker>\n <div *ngFor=\"let item of dataForRender; let i = index\" class=\"am-picker-col\">\n <div class=\"am-picker-col-indicator \" style=\"top: 102px;\" [ngStyle]=\"options.indicatorStyle\"></div>\n <div class=\"am-picker-col-mask\" style=\"background-size: 100% 102px;\" id=\"{{ i }}\"></div>\n <div class=\"am-picker-col-content\">\n <div *ngFor=\"let val of item; let i = index\" class=\"am-picker-col-item\" id=\"{{ i }}\">\n {{ val.label ? val.label : val }}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerComponent, decorators: [{ type: Component, args: [{ selector: 'Picker', encapsulation: ViewEncapsulation.None, template: "<div *ngIf=\"options.mask\" class=\"am-picker-popup-mask {{ maskTransitionName }}\" (click)=\"cancel()\"></div>\n<div class=\"am-picker-popup am-picker-popup-wrap {{ transitionName }}\" style=\" min-height: 280px\">\n <div class=\"am-picker-popup-content\">\n <div class=\"am-picker-popup-body\">\n <div>\n <div class=\"am-picker-popup-header\">\n <div class=\"am-picker-popup-item am-picker-popup-header-left\" (click)=\"cancel()\">\n {{ options.dismissText }}\n </div>\n <div class=\"am-picker-popup-item am-picker-popup-title\">{{ options.title }}</div>\n <div class=\"am-picker-popup-item am-picker-popup-header-right\" (click)=\"ok()\">{{ options.okText }}</div>\n </div>\n <div class=\"am-picker\" style=\"flex-direction: row; align-items: center;\" #picker>\n <div *ngFor=\"let item of dataForRender; let i = index\" class=\"am-picker-col\">\n <div class=\"am-picker-col-indicator \" style=\"top: 102px;\" [ngStyle]=\"options.indicatorStyle\"></div>\n <div class=\"am-picker-col-mask\" style=\"background-size: 100% 102px;\" id=\"{{ i }}\"></div>\n <div class=\"am-picker-col-content\">\n <div *ngFor=\"let val of item; let i = index\" class=\"am-picker-col-item\" id=\"{{ i }}\">\n {{ val.label ? val.label : val }}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: PickerOptions }, { type: i2.LocaleProviderService }], propDecorators: { _picker: [{ type: ViewChild, args: ['picker', { read: ViewContainerRef, static: true }] }], panstart: [{ type: HostListener, args: ['mousedown', ['$event']] }, { type: HostListener, args: ['touchstart', ['$event']] }], panmove: [{ type: HostListener, args: ['mousemove', ['$event']] }, { type: HostListener, args: ['touchmove', ['$event']] }], panend: [{ type: HostListener, args: ['mouseup', ['$event']] }, { type: HostListener, args: ['mouseleave', ['$event']] }, { type: HostListener, args: ['touchend', ['$event']] }] } }); class PickerDirective { togglePicker() { if (!this.picker) { this.showPicker(); } else { this.hidePicker(); } } constructor(_viewContainerRef, _elm, _defaultOptions, _cfr, _renderer, _zone) { this._viewContainerRef = _viewContainerRef; this._elm = _elm; this._defaultOptions = _defaultOptions; this._cfr = _cfr; this._renderer = _renderer; this._zone = _zone; this._eventListeners = []; this.onVisibleChange = new EventEmitter(true); this.onPickerChange = new EventEmitter(); this.onDismiss = new EventEmitter(); this.onChange = () => null; this.onTouched = () => null; } ngOnInit() { this.onVisibleChange.emit(false); } ngOnChanges(value) { if (value.cols && this.picker) { this.picker.instance.options.cols = value.cols.currentValue; } if (value.data && this.picker) { if (!this.isPickerDataEqual(this.picker.instance.options.data, value.data.currentValue)) { this.picker.instance.options.data = value.data.currentValue; this.showPicker(); } } } ngOnDestroy() { this.hidePicker(); } onDocumentClick(event) { if (this.picker && !this._elm.nativeElement.contains(event.target) && !this.picker.location.nativeElement.contains(event.target)) { this.hidePicker(); } } showPicker() { if (this.picker) { this._zone.run(() => { this.picker.instance.init(); }); } else if (!this.picker && !this.disabled) { setTimeout(() => { this._eventListeners = [ this._renderer.listen('document', 'click', (event) => this.onDocumentClick(event)), this._renderer.listen('document', 'touchend', (event) => this.onDocumentClick(event)) ]; }); const options = new PickerOptions(); Object.assign(options, this._defaultOptions, { hidePicker: (event) => { this.hidePicker(); }, updateNgModel: (value) => { this.value = value; this.onChange(value); } }); const optionalParams = [ 'data', 'value', 'cols', 'mask', 'title', 'okText', 'dismissText', 'disabled', 'cascade', 'appendToBody', 'indicatorStyle', 'onPickerChange', 'onVisibleChange', 'onDismiss' ]; optionalParams.forEach(param => { if (typeof this[param] !== 'undefined') { options[param] = this[param]; } }); const componentFactory = this._cfr.resolveComponentFactory(PickerComponent); const childInjector = Injector.create([ { provide: PickerOptions, useValue: options } ]); this.picker = this._viewContainerRef.createComponent(componentFactory, this._viewContainerRef.length, childInjector); if (options.appendToBody) { this.appendToBodyElement = document.body.appendChild(this.picker.location.nativeElement); } this.onVisibleChange.emit(true); } } hidePicker() { if (this.appendToBodyElement) { document.body.removeChild(this.appendToBodyElement); this.appendToBodyElement = null; } if (this.picker) { this.picker.destroy(); delete this.picker; this.onVisibleChange.emit(false); this._eventListeners.forEach(fn => fn()); this._eventListeners = []; } } writeValue(value) { this.value = Array.isArray(value) ? value : []; if (this.picker) { this.picker.instance.options.value = this.value; this.showPicker(); this.picker.instance.reloadPicker(); } } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; } isPickerDataEqual(data1, data2) { if (!data1 && !data2) { return true; } if (!Array.isArray(data1) || !Array.isArray(data2) || data1.length !== data2.length) { return false; } for (let i = 0; i < data1.length; i++) { const item1 = data1[i]; const item2 = data2[i]; if ((item1 && !item2) || (!item1 && item2)) { return false; } if (item1.value !== item2.value) { return false; } if (item1.label !== item2.label) { return false; } if (item1.children && item2.children) { return this.isPickerDataEqual(item1.children, item2.children); } } return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.ElementRef }, { token: PickerOptions }, { token: i0.ComponentFactoryResolver }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.8", type: PickerDirective, selector: "[Picker], [nzm-picker]", inputs: { data: "data", cols: "cols", mask: "mask", title: "title", visible: "visible", okText: "okText", dismissText: "dismissText", disabled: "disabled", cascade: "cascade", appendToBody: "appendToBody", indicatorStyle: "indicatorStyle" }, outputs: { onVisibleChange: "onVisibleChange", onPickerChange: "onPickerChange", onDismiss: "onDismiss" }, host: { listeners: { "click": "togglePicker()" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PickerDirective), multi: true } ], usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerDirective, decorators: [{ type: Directive, args: [{ selector: '[Picker], [nzm-picker]', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => PickerDirective), multi: true } ] }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.ElementRef }, { type: PickerOptions }, { type: i0.ComponentFactoryResolver }, { type: i0.Renderer2 }, { type: i0.NgZone }], propDecorators: { data: [{ type: Input }], cols: [{ type: Input }], mask: [{ type: Input }], title: [{ type: Input }], visible: [{ type: Input }], okText: [{ type: Input }], dismissText: [{ type: Input }], disabled: [{ type: Input }], cascade: [{ type: Input }], appendToBody: [{ type: Input }], indicatorStyle: [{ type: Input }], onVisibleChange: [{ type: Output }], onPickerChange: [{ type: Output }], onDismiss: [{ type: Output }], togglePicker: [{ type: HostListener, args: ['click'] }] } }); class PickerService extends PopupService { constructor() { super(...arguments); this.comRef = null; this.defaultOptions = new PickerOptions(); } showPicker(config = this.defaultOptions, confirmCallback, cancelCallback) { const options = new PickerOptions(); Object.assign(options, config, { hidePicker: (event) => { this.hidePicker(); }, confirm: (event) => { if (confirmCallback) { confirmCallback(event); } }, cancel: () => { if (cancelCallback) { cancelCallback(); } } }); const childInjector = Injector.create([ { provide: PickerOptions, useValue: options } ]); this.comRef = this.showPopup(PickerComponent, childInjector); return this.comRef && this.comRef.instance; } hidePicker() { this.hidePopup(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerService, decorators: [{ type: Injectable }] }); class PickerModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.8", ngImport: i0, type: PickerModule, declarations: [PickerComponent, PickerDirective], imports: [CommonModule, OverlayModule], exports: [PickerComponent, PickerDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerModule, providers: [PickerOptions, PopupService, PickerService], imports: [CommonModule, OverlayModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.8", ngImport: i0, type: PickerModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, OverlayModule], exports: [PickerComponent, PickerDirective], declarations: [PickerComponent, PickerDirective], providers: [PickerOptions, PopupService, PickerService] }] }] }); /** * Generated bundle index. Do not edit. */ export { PickerService as Picker, PickerComponent, PickerDirective, PickerModule, PickerOptions, PickerRef, PickerService }; //# sourceMappingURL=ng-zorro-antd-mobile-picker.mjs.map