64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
import {defineStore} from "pinia";
|
|
import {ref} from "vue";
|
|
|
|
export type ToastType = 'success' | 'error' | 'info';
|
|
|
|
export interface ToastOptions {
|
|
message: string;
|
|
title?: string;
|
|
type?: ToastType;
|
|
duration?: number;
|
|
}
|
|
|
|
export interface Toast {
|
|
id: number;
|
|
message: string;
|
|
title?: string;
|
|
type: ToastType;
|
|
}
|
|
|
|
const DEFAULT_DURATION = 5000;
|
|
|
|
export const useToastStore = defineStore('toast', () => {
|
|
const toasts = ref<Toast[]>([]);
|
|
let nextId = 0;
|
|
|
|
const dismiss = (id: number) => {
|
|
toasts.value = toasts.value.filter(toast => toast.id !== id);
|
|
};
|
|
|
|
const push = (opts: ToastOptions | string): number => {
|
|
const options = typeof opts === "string" ? {message: opts} : opts;
|
|
const id = nextId++;
|
|
toasts.value.push({
|
|
id,
|
|
message: options.message,
|
|
title: options.title,
|
|
type: options.type ?? 'info',
|
|
});
|
|
const duration = options.duration ?? DEFAULT_DURATION;
|
|
if (duration > 0) {
|
|
setTimeout(() => dismiss(id), duration);
|
|
}
|
|
return id;
|
|
};
|
|
|
|
return {toasts, push, dismiss};
|
|
});
|
|
|
|
interface ToastHelper {
|
|
(opts: ToastOptions | string): number;
|
|
success: (message: string) => number;
|
|
error: (message: string) => number;
|
|
info: (message: string) => number;
|
|
}
|
|
|
|
export const toast: ToastHelper = Object.assign(
|
|
(opts: ToastOptions | string): number => useToastStore().push(opts),
|
|
{
|
|
success: (message: string): number => useToastStore().push({message, type: 'success'}),
|
|
error: (message: string): number => useToastStore().push({message, type: 'error'}),
|
|
info: (message: string): number => useToastStore().push({message, type: 'info'}),
|
|
},
|
|
);
|