<template>
	<view class="custom-popup" :class="{'custom-popup--show': showPopup}">
		<!-- 遮罩层 -->
		<view
			class="custom-popup__mask"
			:style="{
				backgroundColor: maskBackgroundColor,
				zIndex: zIndex
			}"
			:class="{'custom-popup__mask--show': showPopup && mask}"
			@tap="maskClick"
			@touchmove.stop.prevent="clear"
		></view>
		<!-- 弹出层 -->
		<view
			class="custom-popup__container"
			:class="[
				`custom-popup__container--${mode}`,
				showPopup && `custom-popup__container--${mode}--active`,
			]"
			:style="{
				zIndex: zIndex + 1,
				backgroundColor: bgColor
			}"
			@touchmove.stop.prevent="clear"
		>
			<!-- 顶部安全区适配 -->
			<view class="custom-popup__safe-area-inset-top" v-if="safeAreaInsetTop"></view>
			<!-- 主体内容 -->
			<view
				class="custom-popup__content"
				:class="{'custom-popup__content--round': round}"
				:style="{
					width: width ? width : 'auto',
					borderRadius: mode === 'center' ? borderRadius : 0
				}"
			>
				<slot></slot>
			</view>
			<!-- 底部安全区适配 -->
			<view class="custom-popup__safe-area-inset-bottom" v-if="safeAreaInsetBottom"></view>
		</view>
	</view>
</template>

<script>
export default {
	name: 'CustomPopup',
	model: {
		prop: 'value',
		event: 'input'
	},
	props: {
		// 是否显示弹窗 (v-model绑定)
		value: {
			type: Boolean,
			default: false
		},
		// 弹出方式
		// top: 顶部弹出
		// bottom: 底部弹出
		// center: 中部弹出
		// left: 左侧弹出
		// right: 右侧弹出
		mode: {
			type: String,
			default: 'bottom'
		},
		// 是否显示遮罩
		mask: {
			type: Boolean,
			default: true
		},
		// 点击遮罩是否关闭弹窗
		maskClosable: {
			type: Boolean,
			default: true
		},
		// 弹窗背景色
		bgColor: {
			type: String,
			default: '#ffffff'
		},
		// 弹窗圆角
		borderRadius: {
			type: [String, Number],
			default: '20rpx'
		},
		// 弹窗宽度，mode=center时生效
		width: {
			type: String,
			default: '650rpx'
		},
		// 是否显示圆角
		round: {
			type: Boolean,
			default: false
		},
		// z-index层级
		zIndex: {
			type: [String, Number],
			default: 10070
		},
		// 遮罩的背景色
		maskBackgroundColor: {
			type: String,
			default: 'rgba(0, 0, 0, 0.5)'
		},
		// 是否适配底部安全区
		safeAreaInsetBottom: {
			type: Boolean,
			default: true
		},
		// 是否适配顶部安全区
		safeAreaInsetTop: {
			type: Boolean,
			default: false
		}
	},
	data() {
		return {
			showPopup: false
		}
	},
	watch: {
		value(val) {
			this.showPopup = val;
		}
	},
	created() {
		this.showPopup = this.value;
	},
	methods: {
		// 点击遮罩
		maskClick() {
			if (this.maskClosable) {
				this.closePopup();
			}
		},
		// 关闭弹窗
		closePopup() {
			this.showPopup = false;
			this.$emit('input', false);
			this.$emit('close');
		},
		// 防止滚动穿透
		clear(e) {
			e.stopPropagation();
			e.preventDefault();
		}
	}
}
</script>

<style lang="scss">
.custom-popup {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	visibility: hidden;
	
	&__mask {
		position: fixed;
		top: 0;
		left: 0;
        bottom: 0;
		width: 100%;
		height: 100%;
		opacity: 0;
		transition: opacity 0.3s;
		
		&--show {
			opacity: 1;
		}
	}
	
	&__container {
		position: fixed;
		transition: all 0.3s ease-in-out;
		
		&--center {
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%) scale(0.9);
			opacity: 0;
			
			&--active {
				transform: translate(-50%, -50%) scale(1);
				opacity: 1;
			}
		}
		
		&--bottom {
			bottom: 0;
			left: 0;
			width: 100%;
			transform: translateY(100%);
			
			&--active {
				transform: translateY(0);
			}
		}
		
		&--top {
			top: 0;
			left: 0;
			width: 100%;
			transform: translateY(-100%);
			
			&--active {
				transform: translateY(0);
			}
		}
		
		&--left {
			top: 0;
			left: 0;
			height: 100%;
			transform: translateX(-100%);
			
			&--active {
				transform: translateX(0);
			}
		}
		
		&--right {
			top: 0;
			right: 0;
			height: 100%;
			transform: translateX(100%);
			
			&--active {
				transform: translateX(0);
			}
		}
	}
	
	&__content {
		position: relative;
		
		&--round {
			border-radius: 20rpx;
			
			&::after {
				content: "";
				position: absolute;
				top: 0;
				left: 0;
				width: 200%;
				height: 200%;
				transform: scale(0.5);
				transform-origin: 0 0;
				border-radius: 40rpx;
				pointer-events: none;
			}
		}
	}
	
	&__safe-area-inset-top {
		width: 100%;
		height: var(--status-bar-height);
	}
	
	&__safe-area-inset-bottom {
		width: 100%;
		height: env(safe-area-inset-bottom);
	}
	
	&--show {
		visibility: visible;
		z-index: 9999;
	}
}
</style>
