initial
This commit is contained in:
113
layers/ui/components/notification/notification.vue
Normal file
113
layers/ui/components/notification/notification.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<Transition
|
||||
:name="cn.b()"
|
||||
@before-leave="$emit('close')"
|
||||
@after-leave="$emit('destroy')"
|
||||
>
|
||||
<UiAlert
|
||||
v-show="visible"
|
||||
:id="id"
|
||||
:class="[cn.b(), verticalSide, horizontalSide]"
|
||||
:title="title"
|
||||
:type="type"
|
||||
@mouseenter="clearTimer"
|
||||
@mouseleave="startTimer"
|
||||
>
|
||||
<slot />
|
||||
</UiAlert>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import useClassname from '../../composables/use-classname'
|
||||
import UiAlert from '../alert/index.vue'
|
||||
import type { NotificationPlacement, NotificationType } from './types'
|
||||
|
||||
export interface Props {
|
||||
duration?: number
|
||||
id?: string | number
|
||||
offset?: number
|
||||
placement?: NotificationPlacement
|
||||
type?: NotificationType
|
||||
title?: string
|
||||
zIndex?: number
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'UiNotification',
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
type: 'neutral',
|
||||
duration: 5000,
|
||||
offset: 0,
|
||||
placement: 'top-right',
|
||||
zIndex: 0,
|
||||
})
|
||||
|
||||
defineEmits(['close', 'destroy'])
|
||||
|
||||
const cn = useClassname('ui-notification')
|
||||
|
||||
const timerId = ref()
|
||||
const visible = ref(false)
|
||||
|
||||
const verticalSide = computed(() => props.placement.split('-')[0])
|
||||
const horizontalSide = computed(() => props.placement.split('-')[1])
|
||||
|
||||
function close() {
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
if (props.duration > 0) {
|
||||
timerId.value = setTimeout(() => {
|
||||
if (visible.value)
|
||||
close()
|
||||
}, props.duration)
|
||||
}
|
||||
}
|
||||
|
||||
function clearTimer() {
|
||||
if (timerId.value)
|
||||
clearTimeout(timerId.value)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
startTimer()
|
||||
visible.value = true
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
visible,
|
||||
close,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-notification {
|
||||
position: fixed;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: opacity, transform, left, right, top, bottom;
|
||||
z-index: calc(8000 + v-bind('zIndex'));
|
||||
width: 400px;
|
||||
transform-origin: right top;
|
||||
|
||||
&.top {
|
||||
top: v-bind('`${offset}px`');
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
bottom: v-bind('`${offset}px`');
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 56px;
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 56px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user