commit
fa02cff8aa
|
@ -1,106 +1,106 @@
|
|||
import { ComputedRef, Ref } from 'vue';
|
||||
|
||||
export interface UseButton {
|
||||
/**
|
||||
* 附加按钮的Class
|
||||
*/
|
||||
buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 点击附加按钮事件响应函数
|
||||
*/
|
||||
onClickButton: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标移入附加按钮事件响应函数
|
||||
*/
|
||||
onMouseEnterButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标移出附加按钮事件响应函数
|
||||
*/
|
||||
onMouseLeaveButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标滑过附加按钮事件响应函数
|
||||
*/
|
||||
onMouseOverButton: () => void;
|
||||
/**
|
||||
* 附加按钮的Class
|
||||
*/
|
||||
buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 点击附加按钮事件响应函数
|
||||
*/
|
||||
onClickButton: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标移入附加按钮事件响应函数
|
||||
*/
|
||||
onMouseEnterButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标移出附加按钮事件响应函数
|
||||
*/
|
||||
onMouseLeaveButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标滑过附加按钮事件响应函数
|
||||
*/
|
||||
onMouseOverButton: () => void;
|
||||
}
|
||||
|
||||
export interface UseClear {
|
||||
/**
|
||||
* 启用清空按钮
|
||||
*/
|
||||
enableClearButton: ComputedRef<boolean>;
|
||||
/**
|
||||
* 显示清空按钮
|
||||
*/
|
||||
showClearButton: Ref<boolean>;
|
||||
/**
|
||||
* 清空输入框值事件响应函数
|
||||
*/
|
||||
onClearValue: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标进入输入框事件响应函数
|
||||
*/
|
||||
onMouseEnterTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标移出输入框事件响应函数
|
||||
*/
|
||||
onMouseLeaveTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 启用清空按钮
|
||||
*/
|
||||
enableClearButton: ComputedRef<boolean>;
|
||||
/**
|
||||
* 显示清空按钮
|
||||
*/
|
||||
showClearButton: Ref<boolean>;
|
||||
/**
|
||||
* 清空输入框值事件响应函数
|
||||
*/
|
||||
onClearValue: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标进入输入框事件响应函数
|
||||
*/
|
||||
onMouseEnterTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标移出输入框事件响应函数
|
||||
*/
|
||||
onMouseLeaveTextBox: ($event: MouseEvent) => void;
|
||||
}
|
||||
|
||||
export interface UseTextBox {
|
||||
/**
|
||||
* 输入框是否获得焦点
|
||||
*/
|
||||
hasFocusedTextBox: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框是否处于只读状态
|
||||
*/
|
||||
isTextBoxReadonly: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框Class
|
||||
*/
|
||||
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 输入框提示语
|
||||
*/
|
||||
textBoxPlaceholder: ComputedRef<string>;
|
||||
/**
|
||||
* 输入框提示标签
|
||||
*/
|
||||
textBoxTitle: ComputedRef<string>;
|
||||
/**
|
||||
* 更新输入框的值并触发change事件
|
||||
*/
|
||||
changeTextBoxValue: (newValue: string, showEmitChangeEmit: boolean) => void;
|
||||
/**
|
||||
* 输入框失去焦点事件响应函数
|
||||
*/
|
||||
onBlurTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onClickTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框获得焦点事件响应函数
|
||||
*/
|
||||
onFocusTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件
|
||||
*/
|
||||
onInput: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onMouseDownTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 键盘在输入框按下事件
|
||||
*/
|
||||
onKeyDownTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 键盘在输入框抬起事件
|
||||
*/
|
||||
onKeyUpTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件响应函数
|
||||
*/
|
||||
onTextBoxValueChange: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框是否获得焦点
|
||||
*/
|
||||
hasFocusedTextBox: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框是否处于只读状态
|
||||
*/
|
||||
isTextBoxReadonly: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框Class
|
||||
*/
|
||||
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 输入框提示语
|
||||
*/
|
||||
textBoxPlaceholder: ComputedRef<string>;
|
||||
/**
|
||||
* 输入框提示标签
|
||||
*/
|
||||
textBoxTitle: ComputedRef<string>;
|
||||
/**
|
||||
* 更新输入框的值并触发change事件
|
||||
*/
|
||||
changeTextBoxValue: (newValue: string, showEmitChangeEmit: boolean) => void;
|
||||
/**
|
||||
* 输入框失去焦点事件响应函数
|
||||
*/
|
||||
onBlurTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onClickTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框获得焦点事件响应函数
|
||||
*/
|
||||
onFocusTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件
|
||||
*/
|
||||
onInput: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onMouseDownTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 键盘在输入框按下事件
|
||||
*/
|
||||
onKeyDownTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 键盘在输入框抬起事件
|
||||
*/
|
||||
onKeyUpTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件响应函数
|
||||
*/
|
||||
onTextBoxValueChange: ($event: Event) => void;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ import { computed, defineComponent, ref, SetupContext, watch } from 'vue';
|
|||
import { NotifyButton, NotifyData } from '../notify.props';
|
||||
import { ToastProps, toastProps } from './toast.props';
|
||||
|
||||
import './toast.css';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Toast',
|
||||
props: toastProps,
|
||||
|
@ -41,6 +43,8 @@ export default defineComponent({
|
|||
|
||||
const shouldShowTitle = computed(() => toast.value.title && toast.value.msg);
|
||||
|
||||
const shouldShowMessageOnly = computed(() => !toast.value.title && toast.value.msg);
|
||||
|
||||
const shouldShowCloseButton = computed(() => {
|
||||
return true;
|
||||
});
|
||||
|
@ -108,6 +112,15 @@ export default defineComponent({
|
|||
{shouldShowButtonsInTitle.value && renderNotifyButtons()}
|
||||
</>
|
||||
)}
|
||||
{shouldShowMessageOnly.value &&
|
||||
(toast.value.buttons ? (
|
||||
<div class="toast-title-btns-wrapper d-flex">
|
||||
<h5 class="toast-title modal-tips-title only-toast-msg" v-html={toast.value.msg}></h5>
|
||||
<div class="after-toast-title text-right ml-auto">{renderNotifyButtons()}</div>
|
||||
</div>
|
||||
) : (
|
||||
<h5 class="toast-title modal-tips-title only-toast-msg" v-html={toast.value.msg}></h5>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
.toast-title-beforeshow {
|
||||
opacity: 0;
|
||||
}
|
||||
@-webkit-keyframes farrisMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes farrisMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes farrisMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes farrisMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.toast.fadeIn {
|
||||
-webkit-animation: farrisMoveUpIn 0.2s linear;
|
||||
animation: farrisMoveUpIn 0.2s linear;
|
||||
}
|
||||
.toast.fadeOut {
|
||||
-webkit-animation: farrisMoveUpOut 0.2s linear;
|
||||
animation: farrisMoveUpOut 0.2s linear;
|
||||
}
|
|
@ -1,222 +0,0 @@
|
|||
import { Component, Input, ViewChildren, QueryList, AfterContentChecked, OnInit, Output, EventEmitter, NgZone, HostListener } from '@angular/core';
|
||||
import { NotifyConfig, NotifyData } from './notifiy.options';
|
||||
import { isFunction } from 'lodash-es';
|
||||
import { NotifyComponent } from './notify.component';
|
||||
|
||||
@Component({
|
||||
selector: 'farris-notify-container',
|
||||
template: `
|
||||
<div [id]="id" class="farris-notify" [ngClass]="[position]" [ngStyle]="style">
|
||||
<farris-notify *ngFor="let toast of toasts" [toast]="toast" [animateCls]="animateCls" (close)="closeToast(toast)" (btnClick)="btnClickHander($event,toast)"></farris-notify>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class NotifyContainerComponent implements OnInit, AfterContentChecked {
|
||||
|
||||
static POSITIONS: Array<String> = ['bottom-right', 'bottom-left',
|
||||
'top-right', 'top-left', 'top-center', 'bottom-center', 'center-center'];
|
||||
|
||||
static ANIMATES: Array<string> = ['bounceInRight', 'bounceInLeft',
|
||||
'bounceInRight', 'bounceInLeft', 'bounceInDown', 'bounceInUp', 'bounceIn'];
|
||||
|
||||
private _position = '';
|
||||
style = {
|
||||
'left': '',
|
||||
'right': '',
|
||||
'top': '',
|
||||
'bottom': ''
|
||||
};
|
||||
notifyDistance = {
|
||||
'left': 12,
|
||||
'right': 12,
|
||||
'top': 136,
|
||||
'bottom': 12
|
||||
};
|
||||
|
||||
animateCls = 'fadeIn';
|
||||
|
||||
config: NotifyConfig;
|
||||
|
||||
id = '';
|
||||
|
||||
@ViewChildren(NotifyComponent) notifyCmpList: QueryList<NotifyComponent>;
|
||||
|
||||
|
||||
@Output() empty = new EventEmitter();
|
||||
|
||||
@Input() set position(value: string) {
|
||||
if (value) {
|
||||
let notFound = true;
|
||||
for (let i = 0; i < NotifyContainerComponent.POSITIONS.length; i++) {
|
||||
if (NotifyContainerComponent.POSITIONS[i] === value) {
|
||||
notFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notFound) {
|
||||
value = this.config.position;
|
||||
}
|
||||
} else {
|
||||
value = this.config.position;
|
||||
}
|
||||
|
||||
// console.log(this.config);
|
||||
|
||||
|
||||
// if (value === 'center-center') {
|
||||
// this.animateCls = 'bounceIn';
|
||||
// } else {
|
||||
const i = NotifyContainerComponent.POSITIONS.indexOf(value);
|
||||
//this.animateCls = NotifyContainerComponent.ANIMATES[i];
|
||||
this.animateCls = 'fadeIn';
|
||||
//}
|
||||
|
||||
this._position = 'toasty-position-' + value;
|
||||
|
||||
if (this.config.left) {
|
||||
this.notifyDistance.left = this.config.left;
|
||||
}
|
||||
if (this.config.right) {
|
||||
this.notifyDistance.right = this.config.right;
|
||||
}
|
||||
if (this.config.top) {
|
||||
this.notifyDistance.top = this.config.top;
|
||||
}
|
||||
if (this.config.bottom) {
|
||||
this.notifyDistance.bottom = this.config.bottom;
|
||||
}
|
||||
this.initstyle();
|
||||
if (value === 'top-left') {
|
||||
this.style.left = `${this.notifyDistance.left}px`;
|
||||
this.style.top = `${this.notifyDistance.top}px`;
|
||||
}
|
||||
else if (value === 'top-center') {
|
||||
this.style.top = `${this.notifyDistance.top}px`;
|
||||
}
|
||||
else if (value === 'top-right') {
|
||||
this.style.right = `${this.notifyDistance.right}px`;
|
||||
this.style.top = `${this.notifyDistance.top}px`;
|
||||
}
|
||||
else if (value === 'bottom-left') {
|
||||
this.style.left = `${this.notifyDistance.left}px`;
|
||||
this.style.bottom = `${this.notifyDistance.bottom}px`;
|
||||
}
|
||||
else if (value === 'bottom-center') {
|
||||
this.style.bottom = `${this.notifyDistance.bottom}px`;
|
||||
}
|
||||
else if (value === 'bottom-right') {
|
||||
this.style.right = `${this.notifyDistance.right}px`;
|
||||
this.style.bottom = `${this.notifyDistance.bottom}px`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get position() {
|
||||
if (this._position) {
|
||||
return this._position;
|
||||
} else {
|
||||
return 'toasty-position-top-center';
|
||||
}
|
||||
}
|
||||
|
||||
initstyle() {
|
||||
this.style = {
|
||||
'left': '',
|
||||
'right': '',
|
||||
'top': '',
|
||||
'bottom': ''
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
toasts: Array<NotifyData> = [];
|
||||
|
||||
constructor(private ngZone: NgZone) { }
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
onContainerClick($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
ngAfterContentChecked() {
|
||||
if (this.notifyCmpList && this.notifyCmpList.length) {
|
||||
this.notifyCmpList.forEach(cmp => {
|
||||
cmp.close.subscribe(() => {
|
||||
this.clear(cmp.toast.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
closeToast(toast: NotifyData) {
|
||||
this.clear(toast.id);
|
||||
}
|
||||
|
||||
add(notify: NotifyData) {
|
||||
if (this.toasts.length >= this.config.limit) {
|
||||
this.toasts.shift();
|
||||
}
|
||||
|
||||
this.toasts.push(notify);
|
||||
|
||||
if (notify.timeout) {
|
||||
this._setTimeout(notify);
|
||||
}
|
||||
}
|
||||
|
||||
clear(id: number | string) {
|
||||
if (id) {
|
||||
this.toasts.forEach((value: any, key: number) => {
|
||||
if (value.id === id) {
|
||||
if (value.onRemove && isFunction(value.onRemove)) {
|
||||
value.onRemove.call(this, value);
|
||||
}
|
||||
|
||||
this.toasts.splice(key, 1);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.toasts.length === 0) {
|
||||
this.empty.emit();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error('Please provide id of Toast to close');
|
||||
}
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
this.toasts.forEach((value: any, key: number) => {
|
||||
if (value.onRemove && isFunction(value.onRemove)) {
|
||||
value.onRemove.call(this, value);
|
||||
}
|
||||
});
|
||||
this.toasts = [];
|
||||
this.empty.emit();
|
||||
}
|
||||
|
||||
private findNotifyComponent(id: number | string) {
|
||||
return this.notifyCmpList.find(item => item.toast.id === id);
|
||||
}
|
||||
|
||||
private _setTimeout(notify: NotifyData) {
|
||||
// this.ngZone.runOutsideAngular(() => {
|
||||
window.setTimeout(() => {
|
||||
// this.clear(notify.id);
|
||||
const cmp = this.findNotifyComponent(notify.id);
|
||||
if (cmp) {
|
||||
cmp.state = true;
|
||||
cmp.inCls[cmp.animateCls] = false;
|
||||
}
|
||||
}, notify.timeout);
|
||||
// });
|
||||
}
|
||||
btnClickHander(ev, notify: NotifyData) {
|
||||
const cmp = this.findNotifyComponent(notify.id);
|
||||
ev.callback(ev['ev'], cmp);
|
||||
}
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
OnChanges,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
SimpleChanges,
|
||||
NgZone,
|
||||
TemplateRef
|
||||
} from '@angular/core';
|
||||
import { NotifyData,NotifyButton } from './notifiy.options';
|
||||
|
||||
@Component({
|
||||
selector: 'farris-notify',
|
||||
template: `
|
||||
<div #notifyDiv class="toast" [ngClass]="inCls">
|
||||
<button *ngIf="toast.showClose" class="toast-close f-btn-icon f-bare" (click)="closeToast($event)">
|
||||
<span class="f-icon modal_close"></span>
|
||||
</button>
|
||||
<section class="modal-tips" *ngIf="toast.title || toast.msg">
|
||||
<div class="float-left modal-tips-iconwrap">
|
||||
<span class="f-icon" [ngClass]=" getPurType()"></span>
|
||||
</div>
|
||||
<div class="modal-tips-content">
|
||||
<ng-container *ngIf="toast.title&&toast.msg">
|
||||
<h5 class="toast-title modal-tips-title" [innerHTML]="toast.title | safe: 'html'"></h5>
|
||||
<p class="toast-msg" [innerHtml]="toast.msg | safe:'html'"></p>
|
||||
<div class="after-toast-msg text-right" *ngIf="toast.buttons">
|
||||
<ng-container [ngTemplateOutlet]="useButtonsTemplate() ? toast.buttons : defaultButtonRef"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!toast.title&&toast.msg">
|
||||
<ng-container *ngIf="toast.buttons" >
|
||||
<div class="toast-title-btns-wrapper d-flex" >
|
||||
<h5 class="toast-title modal-tips-title only-toast-msg" [innerHtml]="toast.msg | safe:'html'"></h5>
|
||||
<div class="after-toast-title text-right ml-auto">
|
||||
<ng-container [ngTemplateOutlet]="useButtonsTemplate() ? toast.buttons : defaultButtonRef"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!toast.buttons" >
|
||||
<h5 class="toast-title modal-tips-title only-toast-msg" [innerHtml]="toast.msg | safe:'html'"></h5>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<ng-template #defaultButtonRef>
|
||||
<span class="'f-preten-link '+btn.cls?btn.cls:''" *ngFor="let btn of toast.buttons; last as isLast"
|
||||
(click)="clickHandler($event,btn) ">
|
||||
{{ btn.text }}
|
||||
</span>
|
||||
</ng-template>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.toast-title-beforeshow{
|
||||
opacity:0;
|
||||
}
|
||||
@-webkit-keyframes farrisMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
@keyframes farrisMoveUpIn {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes farrisMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
@keyframes farrisMoveUpOut {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
transform-origin: 0 0;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
.toast.fadeIn {
|
||||
-webkit-animation: farrisMoveUpIn 0.2s linear;
|
||||
animation: farrisMoveUpIn 0.2s linear;
|
||||
}
|
||||
.toast.fadeOut {
|
||||
-webkit-animation: farrisMoveUpOut 0.2s linear;
|
||||
animation: farrisMoveUpOut 0.2s linear;
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
export class NotifyComponent implements OnInit, OnChanges {
|
||||
@Input() toast: NotifyData;
|
||||
@Output() close = new EventEmitter();
|
||||
@Output() btnClick = new EventEmitter();
|
||||
@ViewChild('notifyDiv') notifyDiv: ElementRef;
|
||||
|
||||
_state = false;
|
||||
@Input() animateCls: string;
|
||||
outCls = '';
|
||||
inCls = {};
|
||||
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
set state(value) {
|
||||
this._state = value;
|
||||
if (value) {
|
||||
this.inCls[this.animateCls] = false;
|
||||
this.inCls['animated'] = value;
|
||||
this.inCls[this.outCls] = value;
|
||||
// this.ngZone.runOutsideAngular(() => {
|
||||
setTimeout(() => {
|
||||
this.close.next(this.toast);
|
||||
}, 200);
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private ngZone: NgZone) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (this.toast.buttons) {
|
||||
this.ngZone.runOutsideAngular(() => {
|
||||
setTimeout(() => {
|
||||
let closeEl = this.notifyDiv.nativeElement.querySelector('.toast-close');
|
||||
let contentEl =this.notifyDiv.nativeElement.querySelector('.toast-title-btns-wrapper');
|
||||
if(closeEl['clientHeight']+10<contentEl['clientHeight']){
|
||||
contentEl.classList.remove('d-flex');
|
||||
}
|
||||
contentEl.classList.remove('toast-title-beforeshow');
|
||||
}, 200);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
this.getAnimateCls(changes.animateCls.currentValue);
|
||||
}
|
||||
|
||||
getAnimateCls(cls?: any) {
|
||||
cls = cls || 'bounceInRight';
|
||||
// this.outCls = 'bounceOut' + cls.substr(8);
|
||||
// switch (cls.substr(8)) {
|
||||
// case 'Up':
|
||||
// this.outCls = 'bounceOutDown';
|
||||
// break;
|
||||
// case 'Down':
|
||||
// this.outCls = 'bounceOutUp';
|
||||
// break;
|
||||
// }
|
||||
|
||||
this.outCls = 'fadeOut';
|
||||
|
||||
// outCls += tmp;
|
||||
|
||||
this.inCls = {
|
||||
[this.toast.type]: true,
|
||||
[this.toast.theme]: true,
|
||||
'animated': false,
|
||||
[cls]: true,
|
||||
[this.outCls]: this.state
|
||||
};
|
||||
}
|
||||
|
||||
closeToast(event: any) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.state = true;
|
||||
}
|
||||
getPurType(): string {
|
||||
if (this.toast && this.toast.type) {
|
||||
return 'f-icon-' + this.toast.type.replace('toasty-type-', '');
|
||||
}
|
||||
return 'f-icon-default';
|
||||
}
|
||||
useButtonsTemplate() {
|
||||
return this.toast.buttons instanceof TemplateRef;
|
||||
}
|
||||
//点击事件抛出
|
||||
clickHandler(ev, btn:NotifyButton) {
|
||||
if (btn.handle) {
|
||||
this.btnClick.emit({ ev: ev, callback: btn.handle });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +1,83 @@
|
|||
import { isFunction } from 'lodash';
|
||||
import { computed, defineComponent, ref, SetupContext } from 'vue';
|
||||
import { NotifyContainerComponent } from './notify-container.component';
|
||||
import { NotifyData, NotifyProps, notifyProps } from './notify.props';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Notify',
|
||||
props: notifyProps,
|
||||
emits: [],
|
||||
emits: ['empty'],
|
||||
setup(props: NotifyProps, context: SetupContext) {
|
||||
const notifyClass = computed(() => ({
|
||||
'farris-notify': true,
|
||||
}));
|
||||
|
||||
const defaultNotifyDistance = {
|
||||
left: 12,
|
||||
right: 12,
|
||||
top: 136,
|
||||
bottom: 12,
|
||||
};
|
||||
|
||||
const toasts = ref(props.toasts || []);
|
||||
|
||||
const notifyStyle = computed(() => ({
|
||||
left: '',
|
||||
right: '',
|
||||
top: '',
|
||||
bottom: '',
|
||||
left: props.position.indexOf('left') > -1 ? `${props.left ? props.left : defaultNotifyDistance.left}px` : '',
|
||||
right: props.position.indexOf('right') > -1 ? `${props.right ? props.right : defaultNotifyDistance.right}px` : '',
|
||||
top: props.position.indexOf('top') > -1 ? `${props.top ? props.top : defaultNotifyDistance.top}px` : '',
|
||||
bottom: props.position.indexOf('bottom') > -1 ? `${props.bottom ? props.bottom : defaultNotifyDistance.bottom}px` : '',
|
||||
}));
|
||||
|
||||
const toasts = computed(() => {
|
||||
return props.toasts ? props.toasts : [];
|
||||
});
|
||||
function closeToast(toast: NotifyData) {}
|
||||
|
||||
function addToast(toast: NotifyData) {
|
||||
if (toasts.value.length >= props.limit) {
|
||||
toasts.value.shift();
|
||||
}
|
||||
toasts.value.push(toast);
|
||||
// if (props.timeout) {
|
||||
// this._setTimeout(notify);
|
||||
// }
|
||||
}
|
||||
|
||||
function invokeToastOnRemoveCallback(toast: NotifyData) {
|
||||
if (toast && toast.onRemove && isFunction(toast.onRemove)) {
|
||||
toast.onRemove.call(this, toast);
|
||||
}
|
||||
}
|
||||
|
||||
function clear(id: number | string) {
|
||||
const targetToastIndex = toasts.value.findIndex((toast: NotifyData) => toast.id === id);
|
||||
if (targetToastIndex > -1) {
|
||||
const targetToast = toasts.value[targetToastIndex];
|
||||
invokeToastOnRemoveCallback(targetToast);
|
||||
toasts.value.splice(targetToastIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function clearAll() {
|
||||
toasts.value.forEach((toast: NotifyData) => invokeToastOnRemoveCallback(toast));
|
||||
toasts.value.length = 0;
|
||||
context.emit('empty');
|
||||
}
|
||||
|
||||
context.expose({ addToast, clear, clearAll, closeToast });
|
||||
|
||||
function onClose($event: Event, toast: NotifyData) {
|
||||
closeToast(toast);
|
||||
}
|
||||
function onClick($event: Event) {}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div id={props.id} class={notifyClass.value} style={notifyStyle.value}>
|
||||
{toasts.value.map((toastData: NotifyData) => {
|
||||
return <f-toast v-model={toastData} animate={props.animate} onClose={} onClick={}></f-toast>;
|
||||
return (
|
||||
<f-toast
|
||||
v-model={toastData}
|
||||
animate={props.animate}
|
||||
onClose={($event: Event) => onClose($event, toastData)}
|
||||
onClick={onClick}></f-toast>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { NotifyData } from './notify.props';
|
||||
import { ExtractPropTypes, PropType } from 'vue';
|
||||
|
||||
export type NotifyPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'top-center' | 'bottom-center' | 'center-center';
|
||||
|
@ -13,6 +12,8 @@ export type ToastyAnimate =
|
|||
| 'bounceIn'
|
||||
| 'fadeIn';
|
||||
|
||||
export type NotifyTheme = 'default' | 'material' | 'bootstrap';
|
||||
|
||||
export interface NotifyButton {
|
||||
customClass?: string;
|
||||
text: string;
|
||||
|
@ -37,9 +38,18 @@ export interface NotifyData {
|
|||
// export interface NotifyData extends NotifyOptions {}
|
||||
|
||||
export const notifyProps = {
|
||||
limit: { type: Number, default: 5 },
|
||||
showCloseButton: { type: Boolean, default: true },
|
||||
position: { type: String as PropType<NotifyPosition>, default: 'top-center' },
|
||||
timeout: { type: Number, default: 3000 },
|
||||
theme: { type: String as PropType<NotifyTheme>, default: 'bootstrap' },
|
||||
left: { type: Number },
|
||||
right: { type: Number },
|
||||
top: { type: Number },
|
||||
bottom: { type: Number },
|
||||
id: { type: String },
|
||||
animate: { type: String as PropType<ToastyAnimate>, default: 'fadeIn' },
|
||||
position: { type: String as PropType<NotifyPosition>, default: 'toasty-position-top-center' },
|
||||
toasts: { type: Array<NotifyData> },
|
||||
options: { type: Object as PropType<NotifyData> },
|
||||
};
|
||||
export type NotifyProps = ExtractPropTypes<typeof notifyProps>;
|
||||
|
|
|
@ -18,7 +18,7 @@ export default defineComponent({
|
|||
<>
|
||||
<div class="popover-arrow arrow"></div>
|
||||
{shouldShowTitle.value && <h3 class="popover-title popover-header">{props.title}</h3>}
|
||||
<div class={popoverContainerClass.value}></div>
|
||||
<div class={popoverContainerClass.value}>{context.slots.default && context.slots?.default()}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { ExtractPropTypes } from 'vue';
|
||||
import { ExtractPropTypes, PropType } from 'vue';
|
||||
|
||||
export type PopoverPosition = 'top' | 'bottom' | 'left' | 'right' | 'auto';
|
||||
|
||||
export const popoverProps = {
|
||||
title: { type: String },
|
||||
position: { type: String as PropType<PopoverPosition>, default: 'top' },
|
||||
};
|
||||
|
||||
export type PopoverProps = ExtractPropTypes<typeof popoverProps>;
|
||||
|
|
Loading…
Reference in New Issue