feat: alert system + useToast works
This commit is contained in:
@@ -1,9 +1,49 @@
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
|
||||
.slide-left-enter-active,
|
||||
.slide-left-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.list-enter-from,
|
||||
.list-leave-to {
|
||||
.slide-left-enter-from,
|
||||
.slide-left-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
.slide-right-enter-active,
|
||||
.slide-right-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.slide-right-enter-from,
|
||||
.slide-right-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
|
||||
.slide-top-enter-active,
|
||||
.slide-top-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.slide-top-enter-from,
|
||||
.slide-top-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
.slide-bottom-enter-active,
|
||||
.slide-bottom-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.slide-bottom-enter-from,
|
||||
.slide-bottom-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, h, provide, ref, resolveComponent, TransitionGroup } from 'vue'
|
||||
import { defineComponent, h, provide, ref, TransitionGroup } from 'vue'
|
||||
import { FLOWBITE_TOAST_INJECTION_KEY } from '@/components/Toast/components/ToastProvider/injection/config'
|
||||
import type { ToastItem, ToastItemWithId } from '@/components/Toast/components/ToastProvider/types'
|
||||
import type {
|
||||
ToastItem,
|
||||
ToastItemWithId,
|
||||
ToastTransition,
|
||||
UseToastInjection,
|
||||
} from '@/components/Toast/components/ToastProvider/types'
|
||||
import { Toast } from '@/index'
|
||||
import { useTimeoutFn } from '@vueuse/core'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Toast: Toast as any,
|
||||
},
|
||||
props: {
|
||||
transition: {
|
||||
type: String as PropType<ToastTransition>,
|
||||
default: 'slide-left',
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const toasts = ref<ToastItemWithId[]>([])
|
||||
|
||||
@@ -17,29 +29,33 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const addToast = (toast: ToastItem) => {
|
||||
const id = ((new Date()).getTime() * Math.random()).toString()
|
||||
const id = parseInt(((new Date()).getTime() * Math.random()).toString()).toString()
|
||||
toasts.value.push({
|
||||
id,
|
||||
...toast,
|
||||
})
|
||||
if (toast.time > 0)
|
||||
runRemoveTimeout(id, toast.time)
|
||||
return id
|
||||
}
|
||||
|
||||
const popToast = () => {
|
||||
if (toasts.value.length === 0) return ''
|
||||
const lastId = toasts.value[toasts.value.length - 1].id
|
||||
toasts.value.pop()
|
||||
return lastId
|
||||
}
|
||||
|
||||
const removeToast = (id: string) => {
|
||||
const index = toasts.value.findIndex(_ => _.id === id)
|
||||
toasts.value.splice(index, 1)
|
||||
if(index >= 0) toasts.value.splice(index, 1)
|
||||
return index >= 0
|
||||
}
|
||||
|
||||
const popToast = () => {
|
||||
if (toasts.value.length === 0) return
|
||||
toasts.value.pop()
|
||||
}
|
||||
|
||||
provide(FLOWBITE_TOAST_INJECTION_KEY, {
|
||||
provide<UseToastInjection>(FLOWBITE_TOAST_INJECTION_KEY, {
|
||||
add: addToast,
|
||||
remove: removeToast,
|
||||
pop: popToast,
|
||||
remove: removeToast,
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -49,6 +65,7 @@ export default defineComponent({
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
$props,
|
||||
$slots,
|
||||
toasts,
|
||||
removeToast,
|
||||
@@ -57,7 +74,7 @@ export default defineComponent({
|
||||
return h('div', {}, [
|
||||
$slots.default ? $slots.default() : null, // rendering default slot
|
||||
h(TransitionGroup, {
|
||||
name: 'list',
|
||||
name: $props.transition,
|
||||
tag: 'div',
|
||||
class: 'xl:w-1/6 md:w-1/4 sm:w-1/4 fixed top-3 right-3 flex flex-col gap-2 z-50',
|
||||
},
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
export function useToast() {
|
||||
return ''
|
||||
import { inject } from 'vue'
|
||||
import type { ToastItem, UseToastInjection } from '@/components/Toast/components/ToastProvider/types'
|
||||
import { FLOWBITE_TOAST_INJECTION_KEY } from '@/components/Toast/components/ToastProvider/injection/config'
|
||||
|
||||
export function useToast(): UseToastInjection {
|
||||
const injection = inject<UseToastInjection | null>(FLOWBITE_TOAST_INJECTION_KEY, null)
|
||||
if(injection === null) console.warn('Cannot use useToast outside <toast-provider> component. Please wrap your component with <toast-provider>')
|
||||
|
||||
const add = (toast: ToastItem): string => {
|
||||
if(!injection) return ''
|
||||
return injection?.add(toast)
|
||||
}
|
||||
|
||||
const remove = (id: string): boolean => {
|
||||
if(!injection) return false
|
||||
return injection?.remove(id)
|
||||
}
|
||||
|
||||
const pop = (): string => {
|
||||
if(!injection) return ''
|
||||
return injection?.pop()
|
||||
}
|
||||
|
||||
return {
|
||||
add,
|
||||
remove,
|
||||
pop,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,10 @@ export type ToastItemWithId = ToastItem & {
|
||||
id: string
|
||||
}
|
||||
|
||||
export type ToastInjection = {
|
||||
export type ToastTransition = 'slide-left' | 'slide-right' | 'fade' | 'slide-top' | 'slide-bottom'
|
||||
|
||||
export type UseToastInjection = {
|
||||
add: (toast: ToastItem) => string
|
||||
remove: (id: string) => boolean // true if removed, false if not found
|
||||
pop: () => string // empty '' string if no toast to pop
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user