diff --git a/npm/ng-packs/packages/theme-shared/src/lib/animations/bounce.animations.ts b/npm/ng-packs/packages/theme-shared/src/lib/animations/bounce.animations.ts
index ccdc62c491..c539725a0a 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/animations/bounce.animations.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/animations/bounce.animations.ts
@@ -1,4 +1,4 @@
-import { animation, animate, style, trigger, transition, state, useAnimation, keyframes } from '@angular/animations';
+import { animate, animation, keyframes, style } from '@angular/animations';
export const bounceIn = animation(
[
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/animations/fade.animations.ts b/npm/ng-packs/packages/theme-shared/src/lib/animations/fade.animations.ts
index 60be602291..7eb513522d 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/animations/fade.animations.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/animations/fade.animations.ts
@@ -13,3 +13,67 @@ export const fadeOut = animation(
],
{ params: { time: '350ms', easing: 'ease' } }
);
+
+export const fadeInDown = animation(
+ [
+ style({ opacity: '0', display: '{{ display }}', transform: '{{ transform }} translateY(-20px)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '1', transform: '{{ transform }} translateY(0)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeInUp = animation(
+ [
+ style({ opacity: '0', display: '{{ display }}', transform: '{{ transform }} translateY(20px)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '1', transform: '{{ transform }} translateY(0)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeInLeft = animation(
+ [
+ style({ opacity: '0', display: '{{ display }}', transform: '{{ transform }} translateX(20px)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '1', transform: '{{ transform }} translateX(0)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeInRight = animation(
+ [
+ style({ opacity: '0', display: '{{ display }}', transform: '{{ transform }} translateX(-20px)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '1', transform: '{{ transform }} translateX(0)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeOutDown = animation(
+ [
+ style({ opacity: '1', display: '{{ display }}', transform: '{{ transform }} translateY(0)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '0', transform: '{{ transform }} translateY(20px)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeOutUp = animation(
+ [
+ style({ opacity: '1', display: '{{ display }}', transform: '{{ transform }} translateY(0)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '0', transform: '{{ transform }} translateY(-20px)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeOutLeft = animation(
+ [
+ style({ opacity: '1', display: '{{ display }}', transform: '{{ transform }} translateX(0)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '0', transform: '{{ transform }} translateX(20px)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
+
+export const fadeOutRight = animation(
+ [
+ style({ opacity: '1', display: '{{ display }}', transform: '{{ transform }} translateX(0)' }),
+ animate('{{ time }} {{ easing }}', style({ opacity: '0', transform: '{{ transform }} translateX(-20px)' }))
+ ],
+ { params: { time: '350ms', easing: 'ease', display: 'block', transform: 'translate(-50%, -50%)' } }
+);
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/README.md b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/README.md
deleted file mode 100644
index cf51e03845..0000000000
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-
Abp Modal
-
-Example Usage:
-
-```html
-
-
- Modal Title
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.animations.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.animations.ts
new file mode 100644
index 0000000000..c686bec552
--- /dev/null
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.animations.ts
@@ -0,0 +1,14 @@
+import { trigger, state, style, transition, useAnimation } from '@angular/animations';
+import { fadeInDown, fadeOut, fadeIn } from '../../animations';
+
+export const backdropAnimation = trigger('backdrop', [
+ state('void', style({ opacity: '0' })),
+ state('*', style({ opacity: '1' })),
+ transition('void => *', useAnimation(fadeIn)),
+ transition('* => void', useAnimation(fadeOut))
+]);
+
+export const dialogAnimation = trigger('dialog', [
+ transition('void => *', useAnimation(fadeInDown)),
+ transition('* => void', useAnimation(fadeOut))
+]);
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html
index 75c48d2d15..c6eb6bf839 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.html
@@ -1,31 +1,15 @@
-
-
-
+
+
+
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
index 5e6ebff228..014b8cc58c 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
@@ -11,19 +11,19 @@ import {
ViewChild,
ViewChildren
} from '@angular/core';
-import { fromEvent, Subject, timer } from 'rxjs';
-import { filter, take, takeUntil, debounceTime } from 'rxjs/operators';
+import { fromEvent, Subject } from 'rxjs';
+import { debounceTime, filter, takeUntil } from 'rxjs/operators';
import { Toaster } from '../../models/toaster';
-import { ConfirmationService } from '../../services/confirmation.service';
+import { ConfirmationService } from '../../services';
import { ButtonComponent } from '../button/button.component';
+import { backdropAnimation, dialogAnimation } from './modal.animations';
export type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
-const ANIMATION_TIMEOUT = 200;
-
@Component({
selector: 'abp-modal',
- templateUrl: './modal.component.html'
+ templateUrl: './modal.component.html',
+ animations: [backdropAnimation, dialogAnimation]
})
export class ModalComponent implements OnDestroy {
@Input()
@@ -32,27 +32,14 @@ export class ModalComponent implements OnDestroy {
}
set visible(value: boolean) {
if (typeof value !== 'boolean') return;
-
- if (!this.modalContent) {
- if (value) {
- setTimeout(() => {
- this.showModal = value;
- this.visible = value;
- }, 0);
- }
- return;
- }
-
+ this._visible = value;
if (value) {
- this.setVisible(value);
this.listen();
+ this.renderer.addClass(document.body, 'modal-open');
+ this.appear.emit();
} else {
- this.closable = false;
- this.renderer.addClass(this.modalContent.nativeElement, 'fade-out-top');
- setTimeout(() => {
- this.setVisible(value);
- this.destroy$.next();
- }, ANIMATION_TIMEOUT - 10);
+ this.renderer.removeClass(document.body, 'modal-open');
+ this.disappear.emit();
}
}
@@ -74,13 +61,8 @@ export class ModalComponent implements OnDestroy {
@Input() size: ModalSize = 'lg';
- @Input() height: number;
-
- @Input() minHeight: number;
-
- @Output() readonly visibleChange = new EventEmitter
();
-
- @Output() readonly init = new EventEmitter();
+ @ContentChild(ButtonComponent, { static: false, read: ButtonComponent })
+ abpSubmit: ButtonComponent;
@ContentChild('abpHeader', { static: false }) abpHeader: TemplateRef;
@@ -91,13 +73,14 @@ export class ModalComponent implements OnDestroy {
@ContentChild('abpClose', { static: false, read: ElementRef })
abpClose: ElementRef;
- @ContentChild(ButtonComponent, { static: false, read: ButtonComponent })
- abpSubmit: ButtonComponent;
-
@ViewChild('abpModalContent', { static: false }) modalContent: ElementRef;
@ViewChildren('abp-button') abpButtons;
+ @Output() readonly visibleChange = new EventEmitter();
+
+ @Output() readonly init = new EventEmitter();
+
@Output() readonly appear = new EventEmitter();
@Output() readonly disappear = new EventEmitter();
@@ -106,11 +89,7 @@ export class ModalComponent implements OnDestroy {
_busy = false;
- showModal = false;
-
- isOpenConfirmation = false;
-
- closable = false;
+ isConfirmationOpen = false;
destroy$ = new Subject();
@@ -120,22 +99,27 @@ export class ModalComponent implements OnDestroy {
this.destroy$.next();
}
- setVisible(value: boolean) {
- this._visible = value;
- this.visibleChange.emit(value);
- this.showModal = value;
+ close() {
+ if (this.busy) return;
- if (value) {
- timer(ANIMATION_TIMEOUT + 100)
- .pipe(take(1))
- .subscribe(_ => (this.closable = true));
+ const nodes = getFlatNodes(
+ (this.modalContent.nativeElement.querySelector('#abp-modal-body') as HTMLElement).childNodes
+ );
- this.renderer.addClass(document.body, 'modal-open');
- this.appear.emit();
+ if (hasNgDirty(nodes)) {
+ if (this.isConfirmationOpen) return;
+
+ this.isConfirmationOpen = true;
+ this.confirmationService
+ .warn('AbpAccount::AreYouSureYouWantToCancelEditingWarningMessage', 'AbpAccount::AreYouSure')
+ .subscribe((status: Toaster.Status) => {
+ this.isConfirmationOpen = false;
+ if (status === Toaster.Status.confirm) {
+ this.visible = false;
+ }
+ });
} else {
- this.closable = false;
- this.renderer.removeClass(document.body, 'modal-open');
- this.disappear.emit();
+ this.visible = false;
}
}
@@ -144,7 +128,7 @@ export class ModalComponent implements OnDestroy {
.pipe(
takeUntil(this.destroy$),
debounceTime(150),
- filter((key: KeyboardEvent) => key && key.code === 'Escape' && this.closable)
+ filter((key: KeyboardEvent) => key && key.code === 'Escape')
)
.subscribe(_ => {
this.close();
@@ -155,40 +139,13 @@ export class ModalComponent implements OnDestroy {
fromEvent(this.abpClose.nativeElement, 'click')
.pipe(
takeUntil(this.destroy$),
- filter(() => !!(this.closable && this.modalContent))
+ filter(() => !!this.modalContent)
)
.subscribe(() => this.close());
}, 0);
this.init.emit();
}
-
- close() {
- if (!this.closable || this.busy) return;
-
- const nodes = getFlatNodes(
- (this.modalContent.nativeElement.querySelector('#abp-modal-body') as HTMLElement).childNodes
- );
-
- if (hasNgDirty(nodes)) {
- if (this.isOpenConfirmation) return;
-
- this.isOpenConfirmation = true;
- this.confirmationService
- .warn('AbpAccount::AreYouSureYouWantToCancelEditingWarningMessage', 'AbpAccount::AreYouSure')
- .subscribe((status: Toaster.Status) => {
- timer(ANIMATION_TIMEOUT).subscribe(() => {
- this.isOpenConfirmation = false;
- });
-
- if (status === Toaster.Status.confirm) {
- this.visible = false;
- }
- });
- } else {
- this.visible = false;
- }
- }
}
function getFlatNodes(nodes: NodeList): HTMLElement[] {