123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- <template>
- <transition
- enter-active-class="fadeIn"
- leave-active-class="fadeOut"
- @after-leave="$emit('closed')"
- >
- <div
- v-if="visible"
- class="ptc-toast"
- :class="{ 'ptc-toast--loading': icon === 'loading' }"
- >
- <i v-if="icon !== 'none'" class="ptc-toast__icon"></i>
- <span class="ptc-toast__message">{{ message }}</span>
- </div>
- </transition>
- </template>
- <script setup lang="ts">
- import { getCurrentInstance, ref, watch } from 'vue'
- const props = withDefaults(
- defineProps<{
- visible: boolean
- message: string
- duration?: number
- icon?: 'loading' | 'none'
- }>(),
- {
- duration: 2000,
- icon: 'none',
- }
- )
- const emit = defineEmits<{
- (e: 'closed'): void
- (e: 'update:visible', val: boolean): void
- }>()
- let tid: NodeJS.Timeout
- const close = () => emit('update:visible', false)
- const reset = () => {
- clearTimeout(tid)
- if (props.duration) {
- tid = setTimeout(close, props.duration)
- }
- }
- watch(
- () => props.visible,
- val => val && reset()
- )
- watch(() => props.message, reset)
- </script>
- <style lang="scss">
- .ptc-toast {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- box-sizing: content-box;
- // hack for avoid max-width when use left & fixed
- min-width: 192px;
- max-width: 60%;
- width: fit-content;
- padding: 22px 38px;
- color: #fff;
- font-size: 28px;
- line-height: 40px;
- // allow newline charactor
- white-space: pre-wrap;
- text-align: center;
- word-wrap: break-word;
- background-color: rgba(0, 0, 0, 0.7);
- border-radius: 12px;
- z-index: 9999;
- &--loading {
- padding: 56px 24px 40px;
- }
- &__icon {
- margin-bottom: 32px;
- width: 64px;
- height: 64px;
- background-size: contain;
- .ptc-toast--loading & {
- background-image: url(@img/loading.svg);
- animation: rotate 1s linear infinite;
- }
- }
- }
- </style>
|