11<template >
2- <transition name =" va-toast-fade" >
2+ <Transition name =" va-toast-fade" @after-leave = " onHidden " >
33 <div
44 v-show =" visible"
55 ref =" rootElement"
3838 />
3939 </div >
4040 </div >
41- </transition >
41+ </Transition >
4242</template >
4343
4444<script lang="ts">
@@ -47,6 +47,7 @@ import { PropType, ref, computed, onMounted, shallowRef, defineComponent, Comput
4747import { useComponentPresetProp , useColors , useTimer , useTextColor , useTranslation , useTranslationProp , useNumericProp } from ' ../../composables'
4848
4949import { ToastPosition } from ' ./types'
50+ import { useToastService } from ' ./hooks/useToastService'
5051
5152import { StringWithAutocomplete } from ' ../../utils/types/prop-type'
5253 </script >
@@ -78,15 +79,15 @@ const props = defineProps({
7879 icon: { type: String , default: ' close' },
7980 customClass: { type: String , default: ' ' },
8081 duration: { type: [Number , String ], default: 5000 },
81- color: { type: String , default: ' ' },
82+ color: { type: String , default: ' primary ' },
8283 closeable: { type: Boolean , default: true },
8384 onClose: { type: Function },
8485 onClick: { type: Function },
8586 multiLine: { type: Boolean , default: false },
8687 position: {
8788 type: String as PropType <ToastPosition >,
8889 default: ' top-right' ,
89- validator : (value : string ) => [' top-right' , ' top-left' , ' bottom-right' , ' bottom-left' ].includes (value ),
90+ validator : (value : string ) => [' top-right' , ' top-center ' , ' top- left' , ' bottom-right' , ' bottom-center ' , ' bottom-left' ].includes (value ),
9091 },
9192 render: { type: Function },
9293 ariaCloseLabel: useTranslationProp (' $t:close' ),
@@ -107,20 +108,30 @@ const durationComputed = useNumericProp('duration') as ComputedRef<number>
107108
108109const visible = ref (false )
109110
111+ const {
112+ yOffset,
113+ updateYOffset,
114+ } = useToastService (props )
115+
116+ const positionObject = computed (() => ({
117+ vertical: props .position .includes (' top' ) ? ' top' : ' bottom' ,
118+ horizontal: props .position .includes (' center' ) ? ' center' : props .position .includes (' right' ) ? ' right' : ' left' ,
119+ }))
120+
110121const getPositionStyle = () => {
111- const vertical = props . position . includes ( ' top ' ) ? ' top ' : ' bottom '
112- const horizontal = props . position . includes ( ' center ' ) ? ' center ' : props . position . includes ( ' right ' ) ? ' right ' : ' left '
122+ const vertical = positionObject . value . vertical
123+ const horizontal = positionObject . value . horizontal
113124
114125 if (horizontal === ' center' ) {
115126 return {
116- [vertical ]: ` ${offsetYComputed .value }px ` ,
127+ [vertical ]: ` ${offsetYComputed .value + yOffset . value }px ` ,
117128 left: ' 50%' ,
118- transform : ' translateX( -50%) ' ,
129+ ' --va-toast-x-shift ' : ' -50%' ,
119130 }
120131 }
121132
122133 return {
123- [vertical ]: ` ${offsetYComputed .value }px ` ,
134+ [vertical ]: ` ${offsetYComputed .value + yOffset . value }px ` ,
124135 [horizontal ]: ` ${offsetXComputed .value }px ` ,
125136 }
126137}
@@ -129,6 +140,7 @@ const toastClasses = computed(() => [
129140 props .customClass ,
130141 props .multiLine ? ' va-toast--multiline' : ' ' ,
131142 props .inline ? ' va-toast--inline' : ' ' ,
143+ [` va-toast--${props .position } ` ],
132144])
133145
134146const toastStyles = computed (() => ({
@@ -163,14 +175,16 @@ const onToastClick = () => {
163175
164176const onToastClose = () => {
165177 visible .value = false
178+ updateYOffset ()
179+ }
166180
167- rootElement .value ?.addEventListener (' transitionend' , destroyElement )
168-
181+ const onHidden = () => {
169182 if (typeof props .onClose === ' function' ) {
170183 props .onClose ()
171184 } else {
172185 emit (' on-close' )
173186 }
187+ destroyElement ()
174188}
175189
176190const timer = useTimer ()
@@ -193,6 +207,10 @@ onMounted(() => {
193207@import " variables" ;
194208
195209.va-toast {
210+ --va-toast-x-shift : 0px ;
211+ --va-toast-animation-x-shift : 0px ;
212+ --va-toast-animation-y-shift : 100% ;
213+
196214 position : fixed ;
197215 box-sizing : border-box ;
198216 width : var (--va-toast-width );
@@ -207,26 +225,30 @@ onMounted(() => {
207225 overflow : hidden ;
208226 z-index : var (--va-toast-z-index );
209227 font-family : var (--va-font-family );
228+ transform : translateX (var (--va-toast-x-shift ));
210229
211- & --inline {
212- position : static ;
230+ & --top-right ,
231+ & --bottom-right {
232+ --va-toast-animation-x-shift : 100% ;
213233 }
214234
215- & --multiline {
216- min-height : 70px ;
235+ & --top-left ,
236+ & --bottom-left {
237+ --va-toast-animation-x-shift : -100% ;
217238 }
218239
219- & --right {
220- right : 16px ;
240+ & --top-left ,
241+ & --top-center ,
242+ & --top-right {
243+ --va-toast-animation-y-shift : -100% ;
221244 }
222245
223- & --left {
224- left : 16 px ;
246+ & --inline {
247+ position : static ;
225248 }
226249
227- & __group {
228- margin-left : var (--va-toast-group-margin-left );
229- margin-right : var (--va-toast-group-margin-right );
250+ & --multiline {
251+ min-height : 70px ;
230252 }
231253
232254 & __title {
@@ -269,19 +291,14 @@ onMounted(() => {
269291 }
270292}
271293
272- .va-toast-fade-enter {
273- & .right {
274- right : 0 ;
275- transform : translateX (100% );
294+ .va-toast-fade {
295+ & -enter-from {
296+ transform : translateX (calc (var (--va-toast-animation-x-shift ) + var (--va-toast-x-shift )));
276297 }
277298
278- & .left {
279- left : 0 ;
280- transform : translateX ( -100 % ) ;
299+ & -leave-to {
300+ transform : translateY ( var ( --va-toast-animation-y-shift )) ;
301+ opacity : 0 ;
281302 }
282303}
283-
284- .va-toast-fade-leave-active {
285- opacity : 0 ;
286- }
287304 </style >
0 commit comments