UNPKG

ng-devui

Version:

DevUI components based on Angular

435 lines (429 loc) 26.6 kB
import * as i2 from '@angular/cdk/scrolling'; import { ScrollingModule } from '@angular/cdk/scrolling'; import * as i1 from '@angular/common'; import { DOCUMENT, CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { Directive, Component, Inject, Input, ViewChild, HostListener, Injectable, NgModule } from '@angular/core'; import * as i1$1 from 'ng-devui/overlay-container'; import { OverlayContainerModule } from 'ng-devui/overlay-container'; import { PortalModule } from 'ng-devui/portal'; import * as i3 from 'ng-devui/splitter'; import { ResizeDirective, SplitterModule } from 'ng-devui/splitter'; import { backdropFadeInOut, flyInOut } from 'ng-devui/utils'; import { trim, parseInt, isNumber, assign, isUndefined } from 'lodash-es'; import { Subject, fromEvent } from 'rxjs'; import { takeUntil, map, distinctUntilChanged, debounceTime, tap, filter, switchMap } from 'rxjs/operators'; class DrawerContentDirective { constructor(viewContainerRef) { this.viewContainerRef = viewContainerRef; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerContentDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DrawerContentDirective, selector: "[dDrawerContentHost]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerContentDirective, decorators: [{ type: Directive, args: [{ selector: '[dDrawerContentHost]', }] }], ctorParameters: () => [{ type: i0.ViewContainerRef }] }); class DrawerComponent { constructor(elementRef, renderer, doc, cdr) { this.elementRef = elementRef; this.renderer = renderer; this.doc = doc; this.cdr = cdr; this.animateState = 'void'; this.width = '300px'; this.isCover = true; /** * @deprecated */ this.fullScreen = false; this.showAnimation = true; this.clickDoms = []; this.position = 'right'; this.bodyScrollable = true; // drawer打开body是否可滚动 this.resizable = false; this.animationDone = new Subject(); this.stopPropagation = ({ originalEvent: event }) => { event.stopPropagation(); if (event.cancelable) { event.preventDefault(); } }; this.moveStream = (resize) => (mouseDown) => resize.dragEvent.pipe(takeUntil(resize.releaseEvent), map(({ pageX, pageY }) => ({ originalX: mouseDown.pageX, originalY: mouseDown.pageY, pageX, pageY, }))); this.document = this.doc; } ngOnInit() { this.setWidth(this.width); this._isCover = this.isCover === undefined ? true : this.isCover; // some browsers(ie11 & edge) fire the animation done event twice this.animationDoneSub = this.animationDone .pipe(distinctUntilChanged((x, y) => { return x.fromState === y.fromState && x.toState === y.toState; })) .subscribe((event) => { this.onAnimationEnd(event); }); } setWidth(width) { if (typeof window === 'undefined') { return; } if (width.indexOf('%') >= 0) { const widthStr = trim(width, '%'); const widthNum = parseInt(widthStr, 10); this._width = isNumber(widthNum) ? (widthNum * window.innerWidth) / 100 + 'px' : '0px'; if (!this.windowResizeSub) { this.windowResizeSub = fromEvent(window, 'resize') .pipe(debounceTime(100)) .subscribe(() => { if (!this.isFullScreen) { this.setWidth(this.width); } }); } } else { this._width = width; } this._right = parseInt(this._width) > window.innerWidth ? -(parseInt(this._width) - (window.innerWidth - 100)) + 'px' : '0px'; this.oldWidth = this._width; } ngOnDestroy() { if (this.animationDoneSub) { this.animationDoneSub.unsubscribe(); } if (this.resizeSub) { this.resizeSub.unsubscribe(); } if (this.windowResizeSub) { this.windowResizeSub.unsubscribe(); } } keydownHandler(event) { event.stopPropagation(); if (this.escKeyCloseable && !this.isHaveDialogOrUpload()) { this.hide(); } } onAnimationEnd(event) { if (this.animateState === 'void') { this.onHidden(); } if (this.animateState === 'in' && this.afterOpened) { this.afterOpened(); } } // Will overwrite by drawer service onHidden() { } show() { if (this.document.documentElement.scrollHeight > this.document.documentElement.clientHeight) { this.documentOverFlow = true; this.scrollTop = this.document.documentElement.scrollTop || this.document.body.scrollTop; this.scrollLeft = this.document.documentElement.scrollLeft || this.document.body.scrollLeft; this.renderer.addClass(this.document.body, 'devui-body-scrollblock'); this.renderer.setStyle(this.document.body, 'top', `-${this.scrollTop}px`); this.renderer.setStyle(this.document.body, 'left', `-${this.scrollLeft}px`); } if (!this.bodyScrollable && this.documentOverFlow) { this.renderer.addClass(this.document.body, 'devui-body-overflow-hidden'); } this.animateState = 'in'; const activeElement = this.document.activeElement; if (activeElement && typeof activeElement.blur === 'function') { activeElement.blur(); } setTimeout(() => { this.handleResizeWidth(); }, 0); this.isCover = this.isCover === undefined ? true : this.isCover; if (!this.backdropCloseable || this.isCover) { return; } const documentClick = fromEvent(document, 'click'); setTimeout(() => { this.subscription = documentClick.subscribe((event) => { if (this.clickDoms && this.clickDoms.length > 0) { this.clickDoms.forEach((dom) => { if (dom !== null && dom.contains(event.target)) { this.hide(); return; } }); } else { const target = event.target; // 一定要document.contains(event.target),因为event.target可能已经不在document里了,这个时候就不能进hide了 if (this.animateState === 'in' && !this.elementRef.nativeElement.contains(target) && this.document.body.contains(target) && !this.isHaveDialogOrUpload()) { this.hide(); } } }); }); } hide() { this.canHideModel().then((canHide) => { if (!canHide) { return; } this.hideOperation(); }); } hideDirectly() { this.hideOperation(); } hideOperation() { if (this.documentOverFlow) { this.renderer.removeStyle(this.document.body, 'top'); this.renderer.removeStyle(this.document.body, 'left'); this.renderer.removeClass(this.document.body, 'devui-body-scrollblock'); this.renderer.removeClass(this.document.body, 'devui-body-overflow-hidden'); this.document.documentElement.scrollTop = this.scrollTop; this.document.body.scrollTop = this.scrollTop; this.document.documentElement.scrollLeft = this.scrollLeft; this.document.body.scrollLeft = this.scrollLeft; } this.animateState = 'void'; if (this.subscription) { this.subscription.unsubscribe(); this.subscription = undefined; } } // Will overwrite by drawer service destroy() { } isHaveDialogOrUpload() { const dialog = this.document.getElementsByClassName('modal-dialog'); const upload = this.document.getElementById('d-upload-temp'); return (dialog && dialog.length > 0) || upload; } canHideModel() { let hiddenResult = Promise.resolve(true); if (this.beforeHidden) { const result = this.beforeHidden(); if (typeof result !== 'undefined') { if (result.then) { hiddenResult = result; } else if (result.subscribe) { hiddenResult = result.toPromise(); } else { hiddenResult = Promise.resolve(result); } } } return hiddenResult; } _setFullScreen(fullScreen) { if (typeof window === 'undefined') { return; } const drawerContainerEle = this.drawerContainer.nativeElement; if (this._width === this.oldWidth) { if (fullScreen === true || fullScreen === undefined) { this.isFullScreen = true; this._width = this._isCover ? '100%' : window.innerWidth + 'px'; this.renderer.setStyle(drawerContainerEle, 'transition', this.showAnimation ? `width .3s cubic-bezier(0.5, 0.05, 0.5, 0.95)` : 'none'); if (!this._isCover) { const resizeEv = fromEvent(window, 'resize'); const result = resizeEv.pipe(debounceTime(100)); this.resizeSub = result.subscribe((ev) => { this._width = window.innerWidth + 'px'; }); } } } else { if (!fullScreen) { this.isFullScreen = false; this._width = this.oldWidth; if (this.resizeSub) { this.resizeSub.unsubscribe(); } } } } toggleFullScreen() { this._setFullScreen(); } setFullScreen(fullScreen) { this._setFullScreen(fullScreen); } handleResizeWidth() { if (this.resizable) { this.resizeCmp.pressEvent .pipe(tap(this.stopPropagation), filter(() => { this._curWidth = this._width; return this.resizable; }), switchMap(this.moveStream(this.resizeCmp))) .subscribe(({ pageX, originalX }) => { this.showAnimation = false; let tmpWidth; if (this.position === 'left') { tmpWidth = parseInt(this._curWidth, 10) + pageX - originalX + 'px'; } else { tmpWidth = parseInt(this._curWidth, 10) + originalX - pageX + 'px'; } this.setWidth(tmpWidth); this.cdr.detectChanges(); }); this.resizeCmp.releaseEvent.subscribe(() => { this.showAnimation = true; }); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DOCUMENT }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DrawerComponent, selector: "d-drawer", inputs: { id: "id", width: "width", zIndex: "zIndex", isCover: "isCover", fullScreen: "fullScreen", showAnimation: "showAnimation", backdropCloseable: "backdropCloseable", escKeyCloseable: "escKeyCloseable", beforeHidden: "beforeHidden", clickDoms: "clickDoms", afterOpened: "afterOpened", position: "position", bodyScrollable: "bodyScrollable", resizable: "resizable" }, host: { listeners: { "document:keydown.escape": "keydownHandler($event)" } }, viewQueries: [{ propertyName: "drawerContentHost", first: true, predicate: DrawerContentDirective, descendants: true, static: true }, { propertyName: "drawerContainer", first: true, predicate: ["drawerContainer"], descendants: true, static: true }, { propertyName: "resizeCmp", first: true, predicate: ["resizeBar"], descendants: true, read: ResizeDirective }], ngImport: i0, template: "<div\n class=\"drawer\"\n [attr.id]=\"id\"\n [ngStyle]=\"{ 'z-index': zIndex }\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n>\n <div\n class=\"overlay-wrapper\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n >\n <div\n class=\"overlay-backdrop\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [@backdropAnimation]=\"animateState\"\n [@.disabled]=\"!showAnimation\"\n (click)=\"backdropCloseable && hide()\"\n ></div>\n <div\n #drawerContainer\n class=\"drawer-nav\"\n [ngStyle]=\"{ width: _width }\"\n [@flyInOut]=\"position + '-' + animateState\"\n (@flyInOut.done)=\"animationDone.next($event)\"\n [@.disabled]=\"!showAnimation\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? _right : null\"\n >\n <div class=\"drawer-content\" cdkScrollable>\n <ng-template dDrawerContentHost></ng-template>\n </div>\n <div *ngIf=\"contentTemplate\" class=\"drawer-content\" cdkScrollable>\n <ng-template [ngTemplateOutlet]=\"contentTemplate\"></ng-template>\n </div>\n <div\n #resizeBar\n dResize\n class=\"devui-drawer-resize-bar\"\n [ngClass]=\"{\n 'devui-drawer-can-hover': resizable,\n 'devui-drawer-resize-bar-left': position === 'left',\n 'devui-drawer-resize-bar-right': position === 'right'\n }\"\n ></div>\n </div>\n </div>\n</div>\n", styles: [".drawer{position:fixed;top:0;bottom:0;z-index:var(--devui-z-index-drawer, 1040)}.overlay-wrapper{display:flex;justify-content:center;align-items:center;position:absolute;top:0;bottom:0}.display-width{left:0;right:0}.overlay-backdrop{position:absolute;top:0;bottom:0!important;background:var(--devui-feedback-overlay-backdrop, rgba(0, 0, 0, .3))}.drawer-nav,.drawer-content{position:absolute;top:0;bottom:0;border-radius:var(--devui-border-radius, 2px)}.drawer-nav{background:var(--devui-base-bg, #ffffff)}.drawer-content{left:0;right:0;box-shadow:var(--devui-shadow-length-fullscreen-overlay, 0 16px 48px 0) var(--devui-shadow, rgba(0, 0, 0, .16));overflow:auto}.drawer-content::-webkit-scrollbar-thumb{background-color:transparent}.drawer-content:hover::-webkit-scrollbar-thumb{background-color:var(--devui-line, #dbdbdb)}.drawer-content:hover::-webkit-scrollbar-thumb:hover{background-color:var(--devui-placeholder, #808080)}.devui-drawer-resize-bar{position:absolute;top:0;height:100%;width:4px;z-index:10;border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-drawer-resize-bar.devui-drawer-resize-bar-left{right:-1px}.devui-drawer-resize-bar.devui-drawer-resize-bar-right{left:-1px}.devui-drawer-resize-bar.devui-drawer-can-hover:hover{border-left-color:var(--devui-brand-hover, #3979f9);border-left-width:2px;cursor:col-resize}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: i3.ResizeDirective, selector: "[dResize]", inputs: ["enableResize"], outputs: ["pressEvent", "dragEvent", "releaseEvent"] }, { kind: "directive", type: DrawerContentDirective, selector: "[dDrawerContentHost]" }], animations: [backdropFadeInOut, flyInOut] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerComponent, decorators: [{ type: Component, args: [{ selector: 'd-drawer', animations: [backdropFadeInOut, flyInOut], preserveWhitespaces: false, template: "<div\n class=\"drawer\"\n [attr.id]=\"id\"\n [ngStyle]=\"{ 'z-index': zIndex }\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n>\n <div\n class=\"overlay-wrapper\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? 0 : null\"\n >\n <div\n class=\"overlay-backdrop\"\n [ngClass]=\"{ 'display-width': _isCover && animateState === 'in' }\"\n [@backdropAnimation]=\"animateState\"\n [@.disabled]=\"!showAnimation\"\n (click)=\"backdropCloseable && hide()\"\n ></div>\n <div\n #drawerContainer\n class=\"drawer-nav\"\n [ngStyle]=\"{ width: _width }\"\n [@flyInOut]=\"position + '-' + animateState\"\n (@flyInOut.done)=\"animationDone.next($event)\"\n [@.disabled]=\"!showAnimation\"\n [style.left]=\"position === 'left' ? 0 : null\"\n [style.right]=\"position === 'right' ? _right : null\"\n >\n <div class=\"drawer-content\" cdkScrollable>\n <ng-template dDrawerContentHost></ng-template>\n </div>\n <div *ngIf=\"contentTemplate\" class=\"drawer-content\" cdkScrollable>\n <ng-template [ngTemplateOutlet]=\"contentTemplate\"></ng-template>\n </div>\n <div\n #resizeBar\n dResize\n class=\"devui-drawer-resize-bar\"\n [ngClass]=\"{\n 'devui-drawer-can-hover': resizable,\n 'devui-drawer-resize-bar-left': position === 'left',\n 'devui-drawer-resize-bar-right': position === 'right'\n }\"\n ></div>\n </div>\n </div>\n</div>\n", styles: [".drawer{position:fixed;top:0;bottom:0;z-index:var(--devui-z-index-drawer, 1040)}.overlay-wrapper{display:flex;justify-content:center;align-items:center;position:absolute;top:0;bottom:0}.display-width{left:0;right:0}.overlay-backdrop{position:absolute;top:0;bottom:0!important;background:var(--devui-feedback-overlay-backdrop, rgba(0, 0, 0, .3))}.drawer-nav,.drawer-content{position:absolute;top:0;bottom:0;border-radius:var(--devui-border-radius, 2px)}.drawer-nav{background:var(--devui-base-bg, #ffffff)}.drawer-content{left:0;right:0;box-shadow:var(--devui-shadow-length-fullscreen-overlay, 0 16px 48px 0) var(--devui-shadow, rgba(0, 0, 0, .16));overflow:auto}.drawer-content::-webkit-scrollbar-thumb{background-color:transparent}.drawer-content:hover::-webkit-scrollbar-thumb{background-color:var(--devui-line, #dbdbdb)}.drawer-content:hover::-webkit-scrollbar-thumb:hover{background-color:var(--devui-placeholder, #808080)}.devui-drawer-resize-bar{position:absolute;top:0;height:100%;width:4px;z-index:10;border-left:1px solid var(--devui-dividing-line, #f0f0f0)}.devui-drawer-resize-bar.devui-drawer-resize-bar-left{right:-1px}.devui-drawer-resize-bar.devui-drawer-resize-bar-right{left:-1px}.devui-drawer-resize-bar.devui-drawer-can-hover:hover{border-left-color:var(--devui-brand-hover, #3979f9);border-left-width:2px;cursor:col-resize}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: i0.ChangeDetectorRef }], propDecorators: { id: [{ type: Input }], width: [{ type: Input }], zIndex: [{ type: Input }], isCover: [{ type: Input }], fullScreen: [{ type: Input }], showAnimation: [{ type: Input }], drawerContentHost: [{ type: ViewChild, args: [DrawerContentDirective, { static: true }] }], backdropCloseable: [{ type: Input }], escKeyCloseable: [{ type: Input }], beforeHidden: [{ type: Input }], clickDoms: [{ type: Input }], afterOpened: [{ type: Input }], position: [{ type: Input }], bodyScrollable: [{ type: Input }], resizable: [{ type: Input }], drawerContainer: [{ type: ViewChild, args: ['drawerContainer', { static: true }] }], resizeCmp: [{ type: ViewChild, args: ['resizeBar', { read: ResizeDirective }] }], keydownHandler: [{ type: HostListener, args: ['document:keydown.escape', ['$event']] }] } }); class DrawerService { constructor(overlayContainerRef, componentFactoryResolver) { this.overlayContainerRef = overlayContainerRef; this.componentFactoryResolver = componentFactoryResolver; } open({ drawerContentComponent, injector, componentFactoryResolver, id, zIndex, width, fullScreen, // @deprecated data, isCover, clickDoms, onClose, afterOpened, backdropCloseable, escKeyCloseable, beforeHidden, destroyOnHide = true, position = 'right', bodyScrollable = true, showAnimation = true, contentTemplate, resizable = false }) { const componentFactoryResolver_ = componentFactoryResolver || this.componentFactoryResolver; const drawerRef = this.overlayContainerRef.createComponent(componentFactoryResolver_.resolveComponentFactory(DrawerComponent), injector); assign(drawerRef.instance, { id, width, zIndex, isCover, clickDoms, fullScreen, beforeHidden, afterOpened, escKeyCloseable, position, backdropCloseable: isUndefined(backdropCloseable) ? true : backdropCloseable, bodyScrollable, showAnimation, contentTemplate, resizable }); let drawerContentRef; if (drawerContentComponent) { drawerContentRef = drawerRef.instance.drawerContentHost.viewContainerRef.createComponent(componentFactoryResolver_.resolveComponentFactory(drawerContentComponent), 0, injector); assign(drawerContentRef.instance, data); } drawerRef.instance.onHidden = () => { if (onClose) { onClose(); } if (destroyOnHide) { setTimeout(() => { drawerRef.hostView.destroy(); }); } }; drawerRef.instance.destroy = () => { if (!destroyOnHide && drawerRef.instance.animateState === 'void') { drawerRef.hostView.destroy(); } }; drawerRef.instance.show(); return { drawerInstance: drawerRef.instance, drawerContentInstance: drawerContentRef ? drawerContentRef.instance : null }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerService, deps: [{ token: i1$1.OverlayContainerRef }, { token: i0.ComponentFactoryResolver }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1$1.OverlayContainerRef }, { type: i0.ComponentFactoryResolver }] }); class DrawerModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: DrawerModule, declarations: [DrawerComponent, DrawerContentDirective], imports: [CommonModule, ScrollingModule, SplitterModule, PortalModule, OverlayContainerModule], exports: [DrawerComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerModule, providers: [DrawerService], imports: [CommonModule, ScrollingModule, SplitterModule, PortalModule, OverlayContainerModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DrawerModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, ScrollingModule, SplitterModule, PortalModule, OverlayContainerModule ], exports: [DrawerComponent], declarations: [ DrawerComponent, DrawerContentDirective ], providers: [DrawerService], }] }] }); /** * Generated bundle index. Do not edit. */ export { DrawerComponent, DrawerContentDirective, DrawerModule, DrawerService }; //# sourceMappingURL=ng-devui-drawer.mjs.map