Notification services and Svelte bindings for Classic Theme apps
npm install @classic-homes/notificationsFramework-agnostic notifications core with Svelte bindings for the Classic Theme design system.
- Persistent notifications from API with pagination
- Mark as read/unread functionality
- Batch operations (mark all read, delete all)
- Svelte reactive stores for notification state
- Derived stores for unread count and loading state
- TypeScript-first with full type safety
- Integrates with @classic-homes/auth for API authentication
``bash`
npm install @classic-homes/notifications
This package requires @classic-homes/auth to be initialized first, as it uses the shared HTTP client and authentication headers.
`typescript
import { initAuth } from '@classic-homes/auth';
initAuth({
baseUrl: 'https://api.example.com',
// ... other config
});
`
`typescript
import { notificationStore } from '@classic-homes/notifications/svelte';
// Fetch initial notifications
await notificationStore.fetch();
// With pagination
await notificationStore.fetch({ page: 1, limit: 20 });
// Filter by type or read status
await notificationStore.fetch({ type: 'info', unreadOnly: true });
`
`svelte
{#if $isLoadingNotifications}
{:else}
You have {$unreadCount} unread notifications
{#each $notifications as notification}
{notification.message}
API Reference
$3
`typescript
import {
// API
notificationsApi, // Service
notificationService,
NotificationService,
// Utilities
getNotificationIconName,
getNotificationIconColor,
getPriorityBadgeVariant,
getTypeBadgeVariant,
getPriorityLabel,
getTypeLabel,
formatRelativeTime,
formatFullTimestamp,
formatNotificationTime,
getPrioritySortValue,
// Types
type Notification,
type NotificationType,
type NotificationPriority,
type NotificationPreference,
type NotificationChannel,
type NotificationFrequency,
type NotificationFilter,
type NotificationCounts,
type BadgeVariant,
} from '@classic-homes/notifications';
`$3
`typescript
import {
// Main store
notificationStore, // Derived stores
notifications, // Notification[]
unreadCount, // number
isLoadingNotifications, // boolean
// Types
type Notification,
type NotificationType,
type NotificationPriority,
} from '@classic-homes/notifications/svelte';
`Notification Store Methods
$3
`typescript
// Fetch notifications with optional filters
await notificationStore.fetch({
page?: number,
limit?: number,
type?: NotificationType,
unreadOnly?: boolean,
});// Refresh current page
await notificationStore.refresh();
// Load more (next page)
await notificationStore.loadMore();
`$3
`typescript
// Mark single notification as read
await notificationStore.markRead(notificationId);// Mark multiple notifications as read
await notificationStore.markManyRead([id1, id2, id3]);
// Mark all notifications as read
await notificationStore.markAllRead();
`$3
`typescript
// Dismiss single notification
await notificationStore.dismiss(notificationId);// Delete all notifications
await notificationStore.deleteAll();
`$3
`typescript
// Clear error state
notificationStore.clearError();// Reset store to initial state
notificationStore.reset();
`Notification Types
`typescript
type NotificationType = 'security' | 'system' | 'feature' | 'update' | 'alert' | 'info';
type NotificationPriority = 'urgent' | 'high' | 'normal' | 'low';interface Notification {
id: string;
userId: string;
type: NotificationType;
category: string;
title: string;
message: string;
icon?: string;
color?: string;
priority: NotificationPriority;
read: boolean;
dismissed: boolean;
actionUrl?: string;
actionLabel?: string;
metadata?: Record;
createdAt: string;
readAt?: string;
dismissedAt?: string;
}
`Channels and Preferences
The package supports notification channels (email, sms, push, in_app) and user preferences for fine-grained control.
$3
`typescript
import { notificationService } from '@classic-homes/notifications/core';const { channels } = await notificationService.getChannels();
// channels: [{ id, name, displayName, enabled, priority }]
`$3
`typescript
import { notificationService } from '@classic-homes/notifications/core';// Get user preferences
const { preferences } = await notificationService.getPreferences();
// Update a preference
await notificationService.updatePreference({
channelId: 'email',
notificationType: 'security',
enabled: true,
frequency: 'immediate',
minPriority: 'normal',
});
// Batch update preferences
await notificationService.batchUpdatePreferences([
{ eventType: 'security', channels: ['email', 'push'], enabled: true },
{ eventType: 'feature', channels: ['in_app'], enabled: true },
]);
`$3
`typescript
type ChannelType = 'email' | 'sms' | 'push' | 'in_app';
type NotificationFrequency = 'immediate' | 'digest_hourly' | 'digest_daily' | 'digest_weekly';interface NotificationPreference {
id: string;
userId: string;
channelId: string;
notificationType: NotificationType;
notificationCategory?: string;
enabled: boolean;
frequency: NotificationFrequency;
quietHoursStart?: string;
quietHoursEnd?: string;
quietHoursTimezone?: string;
minPriority: NotificationPriority;
tags?: string[];
createdAt: string;
updatedAt?: string;
}
`Utility Functions
Display helpers for consistent notification rendering:
`typescript
import {
getNotificationIconName,
getNotificationIconColor,
getPriorityBadgeVariant,
getTypeBadgeVariant,
getPriorityLabel,
getTypeLabel,
formatRelativeTime,
formatNotificationTime,
} from '@classic-homes/notifications/core';// Get icon for notification type
getNotificationIconName('security'); // 'shield'
getNotificationIconColor('security'); // 'text-red-500'
// Get badge variants
getPriorityBadgeVariant('urgent'); // 'destructive'
getTypeBadgeVariant('update'); // 'success'
// Get display labels
getPriorityLabel('high'); // 'High'
getTypeLabel('feature'); // 'Feature'
// Format timestamps
formatRelativeTime('2024-01-22T10:00:00Z'); // '2h ago'
formatNotificationTime('2024-01-15T10:00:00Z'); // 'Jan 15'
`Using with Toast Notifications
For client-side only toast notifications (not persisted), use
toastStore from @classic-homes/theme-svelte:`svelte
`Store State
`typescript
interface NotificationState {
notifications: Notification[];
unreadCount: number;
isLoading: boolean;
error: string | null;
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
`Example: Notification Bell
`svelte
{#each $notifications as notification}
{notification.title}
{#if !notification.read}
{/if}
{/each} {#if $unreadCount > 0}
{/if}
`Direct API Access
For direct API access without the Svelte store:
`typescript
import { notificationsApi } from '@classic-homes/notifications/core';// List notifications
const response = await notificationsApi.list({ page: 1, limit: 20 });
// Get single notification
const notification = await notificationsApi.get('notification-id');
// Mark as read
await notificationsApi.markRead('notification-id');
await notificationsApi.markManyRead(['id1', 'id2']);
await notificationsApi.markAllRead();
// Delete notifications
await notificationsApi.dismiss('notification-id');
await notificationsApi.bulkDelete(['id1', 'id2']);
await notificationsApi.deleteAll();
// Channels and preferences
const channels = await notificationsApi.getChannels();
const preferences = await notificationsApi.getPreferences();
await notificationsApi.updatePreference(preferenceData);
await notificationsApi.deletePreference('subscription-id');
// Test notifications (dev/admin only)
await notificationsApi.generateTestNotifications({ type: 'info' });
``MIT