notifications.svelte.ts 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. type NotificationType = 'success' | 'error' | 'info' | 'loading';
  2. type Notification = {
  3. id: string;
  4. type: NotificationType;
  5. message: string;
  6. href?: string;
  7. durationMs?: number;
  8. };
  9. class NotificationsStore {
  10. items = $state<Notification[]>([]);
  11. push(n: Omit<Notification, 'id'>): string {
  12. const item: Notification = { ...n, id: crypto.randomUUID() };
  13. this.items = [...this.items, item];
  14. const duration = n.durationMs ?? 4000;
  15. if (duration > 0) setTimeout(() => this.dismiss(item.id), duration);
  16. return item.id;
  17. }
  18. /** Replace fields on an existing notification by id. If type changes away from
  19. * 'loading', schedules auto-dismiss using the updated durationMs (default 4000). */
  20. update(id: string, partial: Partial<Omit<Notification, 'id'>>) {
  21. this.items = this.items.map((n) => (n.id === id ? { ...n, ...partial } : n));
  22. if (partial.type && partial.type !== 'loading') {
  23. const item = this.items.find((n) => n.id === id);
  24. if (item) {
  25. const duration = item.durationMs ?? 4000;
  26. if (duration > 0) setTimeout(() => this.dismiss(id), duration);
  27. }
  28. }
  29. }
  30. dismiss(id: string) {
  31. this.items = this.items.filter((n) => n.id !== id);
  32. }
  33. }
  34. const notificationsStore = new NotificationsStore();
  35. export type { Notification, NotificationType };
  36. export { notificationsStore };