@codingfactory/notify-kit-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,547 @@
1
+ import { N as NotifyKitClient, a as NotifyKitMeResponse, L as ListNotificationsParams, b as NotifyKitListResponse, c as NotifyKitUnreadCountResponse, P as PaginationParams, d as NotifyKitNotification, e as NotifyKitPreferences, f as NotifyKitPreferencesUpdate, g as NotifyKitClientConfig, C as ConnectionState, h as NotificationCategory, i as NotificationLevel } from './useNotifyKitModals-BZ_NiTKw.js';
2
+ export { j as ChannelPreferences, I as InvalidSnoozeDurationError, k as NOTIFICATION_CATEGORIES, l as NOTIFICATION_LEVELS, m as NOTIFY_KIT_MODALS_KEY, n as NOTIFY_KIT_STORE_KEY, o as NotifyKitApiError, p as NotifyKitErrorResponse, q as NotifyKitGroupedEntry, r as NotifyKitGroupedListResponse, s as NotifyKitModalSpec, t as NotifyKitModalState, u as NotifyKitModalsClientLike, v as NotifyKitModalsResponse, w as NotifyKitStoreState, x as PaginationMeta, U as UseNotifyKitModalsOptions, y as UseNotifyKitModalsReturn, z as UseNotifyKitStoreReturn, A as createNotifyKitClient, B as isChannelPreferences, D as isMeResponse, E as isModalEnabled, F as isModalSpec, G as isNotifyKitNotification, H as isPaginationMeta, J as isUnreadCountResponse, K as isValidCategory, M as isValidLevel, O as provideNotifyKitModals, Q as provideNotifyKitStore, R as resetNotifyKitStore, S as useNotifyKitModals, T as useNotifyKitStore } from './useNotifyKitModals-BZ_NiTKw.js';
3
+ import { InjectionKey, ComputedRef, Ref } from 'vue';
4
+
5
+ /**
6
+ * Notify Kit API endpoint constants.
7
+ *
8
+ * These are provided for reference and debugging purposes.
9
+ * The NotifyKitClient class handles URL construction internally.
10
+ */
11
+ declare const ENDPOINTS: {
12
+ /** GET - Returns broadcast channel for authenticated user */
13
+ readonly ME: "/me";
14
+ /** GET - List notifications (supports filters and pagination) */
15
+ readonly NOTIFICATIONS: "/notifications";
16
+ /** GET - Get count of unread notifications */
17
+ readonly UNREAD_COUNT: "/notifications/unread-count";
18
+ /** PATCH - Mark a specific notification as read */
19
+ readonly MARK_READ: (id: string) => string;
20
+ /** POST - Mark all notifications as read */
21
+ readonly MARK_ALL_READ: "/notifications/read-all";
22
+ /** DELETE - Delete a specific notification */
23
+ readonly DELETE_NOTIFICATION: (id: string) => string;
24
+ /** PATCH - Mark all notifications in a group as read (Phase 2) */
25
+ readonly MARK_GROUP_READ: (groupKey: string) => string;
26
+ /** GET - Get all notifications in a group (Phase 2) */
27
+ readonly GROUP_NOTIFICATIONS: (groupKey: string) => string;
28
+ /** GET - List outstanding modal notifications */
29
+ readonly MODALS: "/modals";
30
+ /** POST - Acknowledge a modal notification */
31
+ readonly ACK_MODAL: (id: string) => string;
32
+ /** POST - Snooze a modal notification */
33
+ readonly SNOOZE_MODAL: (id: string) => string;
34
+ /** GET - Get user's notification preferences */
35
+ readonly PREFERENCES: "/preferences";
36
+ };
37
+
38
+ /**
39
+ * useNotifyKitClient composable
40
+ *
41
+ * Provides access to the NotifyKit HTTP client within Vue components.
42
+ * Supports both direct configuration and provide/inject pattern.
43
+ */
44
+
45
+ /**
46
+ * Injection key for the NotifyKit client.
47
+ */
48
+ declare const NOTIFY_KIT_CLIENT_KEY: InjectionKey<NotifyKitClient>;
49
+ /**
50
+ * Return type of useNotifyKitClient composable.
51
+ */
52
+ interface UseNotifyKitClientReturn {
53
+ /** The underlying NotifyKitClient instance */
54
+ readonly client: NotifyKitClient;
55
+ getMe: () => Promise<NotifyKitMeResponse>;
56
+ listNotifications: (params?: ListNotificationsParams) => Promise<NotifyKitListResponse>;
57
+ getUnreadCount: () => Promise<NotifyKitUnreadCountResponse>;
58
+ markRead: (id: string) => Promise<void>;
59
+ markAllRead: () => Promise<void>;
60
+ deleteNotification: (id: string) => Promise<void>;
61
+ markGroupRead: (groupKey: string) => Promise<void>;
62
+ getGroupNotifications: (groupKey: string, params?: PaginationParams) => Promise<NotifyKitListResponse>;
63
+ listModals: () => Promise<readonly NotifyKitNotification[]>;
64
+ ackModal: (id: string) => Promise<void>;
65
+ snoozeModal: (id: string, minutes: number) => Promise<void>;
66
+ getPreferences: () => Promise<NotifyKitPreferences>;
67
+ updatePreferences: (preferences: NotifyKitPreferencesUpdate) => Promise<void>;
68
+ }
69
+ /**
70
+ * Provides a NotifyKitClient for injection into descendant components.
71
+ *
72
+ * Call this in your app's setup or a parent component to make the client
73
+ * available to all child components via useNotifyKitClient().
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // In App.vue setup
78
+ * provideNotifyKitClient({
79
+ * baseUrl: '/api/notify-kit',
80
+ * getAuthHeaders: () => ({ Authorization: `Bearer ${token}` })
81
+ * })
82
+ *
83
+ * // In any child component
84
+ * const { listNotifications, markRead } = useNotifyKitClient()
85
+ * ```
86
+ */
87
+ declare function provideNotifyKitClient(config: NotifyKitClientConfig): NotifyKitClient;
88
+ /**
89
+ * Access the NotifyKit client within a Vue component.
90
+ *
91
+ * If a config is provided, creates a new client instance.
92
+ * Otherwise, uses the client provided via provideNotifyKitClient().
93
+ *
94
+ * @throws Error if no client is available (neither config nor injection)
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Use injected client
99
+ * const { client, getMe, listNotifications } = useNotifyKitClient()
100
+ *
101
+ * // Or provide config directly
102
+ * const { client } = useNotifyKitClient({
103
+ * baseUrl: 'https://api.example.com/notify-kit'
104
+ * })
105
+ * ```
106
+ */
107
+ declare function useNotifyKitClient(config?: NotifyKitClientConfig): UseNotifyKitClientReturn;
108
+
109
+ /**
110
+ * useNotifyKitRealtime composable
111
+ *
112
+ * Provides real-time notification handling via Laravel Echo.
113
+ * Manages WebSocket connection, subscribes to user's broadcast channel,
114
+ * and updates the store when notifications are received.
115
+ */
116
+
117
+ /**
118
+ * Minimal Echo interface - just what we need for notifications.
119
+ * This allows consumers to pass their own Echo instance.
120
+ */
121
+ interface EchoLike {
122
+ private: (channel: string) => EchoChannelLike;
123
+ leave: (channel: string) => void;
124
+ }
125
+ /**
126
+ * Minimal Echo channel interface.
127
+ */
128
+ interface EchoChannelLike {
129
+ notification: (callback: (notification: NotifyKitNotification) => void) => EchoChannelLike;
130
+ stopListening: (event: string) => EchoChannelLike;
131
+ }
132
+ /**
133
+ * Minimal NotifyKit client interface - just the methods we need.
134
+ */
135
+ interface NotifyKitClientLike {
136
+ getMe: () => Promise<{
137
+ broadcast_channel: string;
138
+ }>;
139
+ }
140
+ /**
141
+ * Configuration options for useNotifyKitRealtime.
142
+ */
143
+ interface UseNotifyKitRealtimeOptions {
144
+ /**
145
+ * Laravel Echo instance or a function that returns one.
146
+ * Function form is useful for lazy initialization or SSR safety.
147
+ */
148
+ echo: EchoLike | (() => EchoLike);
149
+ /**
150
+ * NotifyKit client instance for fetching broadcast channel.
151
+ */
152
+ client: NotifyKitClientLike;
153
+ /**
154
+ * Whether to auto-connect when the composable is created.
155
+ * Default: true
156
+ */
157
+ autoConnect?: boolean;
158
+ /**
159
+ * Callback called when a notification is received.
160
+ * Called after store is updated.
161
+ */
162
+ onNotification?: (notification: NotifyKitNotification) => void;
163
+ /**
164
+ * Callback called when connection state changes.
165
+ */
166
+ onConnectionChange?: (state: ConnectionState) => void;
167
+ }
168
+ /**
169
+ * Return type of useNotifyKitRealtime composable.
170
+ */
171
+ interface UseNotifyKitRealtimeReturn {
172
+ /** Whether currently connected */
173
+ readonly isConnected: ComputedRef<boolean>;
174
+ /** Current connection state */
175
+ readonly connectionState: Ref<ConnectionState>;
176
+ /** Connect to real-time notifications */
177
+ connect: () => Promise<void>;
178
+ /** Disconnect from real-time notifications */
179
+ disconnect: () => void;
180
+ /** Disconnect and reconnect */
181
+ reconnect: () => Promise<void>;
182
+ }
183
+ /**
184
+ * Composable for real-time notification handling via Laravel Echo.
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * import Echo from 'laravel-echo'
189
+ * import { useNotifyKitRealtime } from '@coding-factory/notify-kit-client'
190
+ *
191
+ * const echo = new Echo({ ... })
192
+ * const client = useNotifyKitClient()
193
+ *
194
+ * const {
195
+ * isConnected,
196
+ * connectionState,
197
+ * connect,
198
+ * disconnect
199
+ * } = useNotifyKitRealtime({
200
+ * echo,
201
+ * client: client.client,
202
+ * onNotification: (notification) => {
203
+ * console.log('New notification:', notification.title)
204
+ * }
205
+ * })
206
+ * ```
207
+ */
208
+ declare function useNotifyKitRealtime(options: UseNotifyKitRealtimeOptions): UseNotifyKitRealtimeReturn;
209
+
210
+ /**
211
+ * useNotifyKitFallback composable
212
+ *
213
+ * Provides fallback polling when WebSocket connection fails.
214
+ * Automatically starts polling when disconnected and stops when reconnected.
215
+ */
216
+
217
+ /**
218
+ * Configuration options for fallback polling.
219
+ */
220
+ interface FallbackConfig {
221
+ /**
222
+ * Time in milliseconds before starting fallback polling after disconnect.
223
+ * Default: 5000 (5 seconds)
224
+ */
225
+ disconnectThresholdMs: number;
226
+ /**
227
+ * Polling interval for unread count in milliseconds.
228
+ * Default: 30000 (30 seconds)
229
+ */
230
+ unreadCountIntervalMs: number;
231
+ /**
232
+ * Polling interval for modals in milliseconds.
233
+ * Default: 120000 (2 minutes)
234
+ */
235
+ modalsIntervalMs: number;
236
+ /**
237
+ * Grace period in milliseconds after reconnection before stopping polling.
238
+ * Default: 2000 (2 seconds)
239
+ */
240
+ reconnectGracePeriodMs: number;
241
+ }
242
+ /**
243
+ * Options for useNotifyKitFallback composable.
244
+ */
245
+ interface UseNotifyKitFallbackOptions {
246
+ /**
247
+ * NotifyKit client instance for API calls.
248
+ */
249
+ client: NotifyKitClient;
250
+ /**
251
+ * Connection state ref to watch for disconnect/reconnect.
252
+ */
253
+ connectionState: Ref<ConnectionState>;
254
+ /**
255
+ * Partial fallback configuration (merged with defaults).
256
+ */
257
+ config?: Partial<FallbackConfig>;
258
+ /**
259
+ * Callback when new modals are fetched during fallback.
260
+ */
261
+ onModalsReceived?: (modals: readonly NotifyKitNotification[]) => void;
262
+ /**
263
+ * Callback when unread count is fetched during fallback.
264
+ */
265
+ onUnreadCountReceived?: (count: number) => void;
266
+ }
267
+ /**
268
+ * Return type of useNotifyKitFallback composable.
269
+ */
270
+ interface UseNotifyKitFallbackReturn {
271
+ /** Whether fallback polling is currently active */
272
+ readonly isPolling: Ref<boolean>;
273
+ /** Timestamp of the last poll */
274
+ readonly lastPollAt: Ref<number | null>;
275
+ /** Start fallback polling manually */
276
+ startPolling: () => void;
277
+ /** Stop fallback polling manually */
278
+ stopPolling: () => void;
279
+ /** Poll unread count immediately */
280
+ pollUnreadCount: () => Promise<void>;
281
+ /** Poll modals immediately */
282
+ pollModals: () => Promise<void>;
283
+ }
284
+ /**
285
+ * Composable for fallback polling when WebSocket connection fails.
286
+ *
287
+ * Automatically monitors connection state and starts/stops polling
288
+ * based on WebSocket connectivity.
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * const { connectionState } = useNotifyKitRealtime({ ... })
293
+ * const client = useNotifyKitClient()
294
+ *
295
+ * const {
296
+ * isPolling,
297
+ * lastPollAt,
298
+ * startPolling,
299
+ * stopPolling
300
+ * } = useNotifyKitFallback({
301
+ * client: client.client,
302
+ * connectionState,
303
+ * config: {
304
+ * unreadCountIntervalMs: 15000, // Poll more frequently
305
+ * }
306
+ * })
307
+ * ```
308
+ */
309
+ declare function useNotifyKitFallback(options: UseNotifyKitFallbackOptions): UseNotifyKitFallbackReturn;
310
+
311
+ /**
312
+ * Toast Policy Helpers
313
+ *
314
+ * Provides utilities for apps to decide which notifications should
315
+ * display as toasts vs only appear in the notification inbox, and
316
+ * which should play sound alerts.
317
+ */
318
+
319
+ /**
320
+ * Interface for toast policy implementations.
321
+ * Apps can implement this directly for full customization.
322
+ */
323
+ interface ToastPolicy {
324
+ /**
325
+ * Determines if a notification should display as a toast.
326
+ * @param notification The notification to evaluate
327
+ * @returns true if the notification should toast
328
+ */
329
+ shouldToast(notification: NotifyKitNotification): boolean;
330
+ /**
331
+ * Determines if a notification should play a sound alert.
332
+ * @param notification The notification to evaluate
333
+ * @returns true if the notification should play sound
334
+ */
335
+ shouldPlaySound(notification: NotifyKitNotification): boolean;
336
+ }
337
+ /**
338
+ * Configuration options for creating a custom toast policy.
339
+ */
340
+ interface ToastPolicyConfig {
341
+ /**
342
+ * Per-category toast settings.
343
+ * true = toast, false = don't toast
344
+ * Categories not specified use defaults.
345
+ */
346
+ toastCategories?: Partial<Record<NotificationCategory, boolean>>;
347
+ /**
348
+ * Notification levels that should play sound.
349
+ * Defaults to ['danger'].
350
+ */
351
+ soundLevels?: NotificationLevel[];
352
+ /**
353
+ * Categories that should always play sound regardless of level.
354
+ * Defaults to ['security'].
355
+ */
356
+ soundCategories?: NotificationCategory[];
357
+ /**
358
+ * Custom shouldToast function.
359
+ * If provided, takes precedence over toastCategories.
360
+ */
361
+ shouldToast?: (notification: NotifyKitNotification) => boolean;
362
+ /**
363
+ * Custom shouldPlaySound function.
364
+ * If provided, takes precedence over soundLevels and soundCategories.
365
+ */
366
+ shouldPlaySound?: (notification: NotifyKitNotification) => boolean;
367
+ }
368
+ /**
369
+ * The default toast policy.
370
+ *
371
+ * Rules:
372
+ * - Critical modals (requires_ack): no toast (modal is the UX)
373
+ * - Security: always toast
374
+ * - Social: no toast by default (high frequency)
375
+ * - All others: toast
376
+ *
377
+ * Sound rules:
378
+ * - Danger level: play sound
379
+ * - Security category: play sound
380
+ * - All others: no sound
381
+ */
382
+ declare const defaultToastPolicy: ToastPolicy;
383
+ /**
384
+ * Creates a custom toast policy with the specified overrides.
385
+ *
386
+ * @param config Configuration options for the policy
387
+ * @returns A ToastPolicy instance
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * // Enable toasts for social, disable for marketing
392
+ * const policy = createToastPolicy({
393
+ * toastCategories: {
394
+ * social: true,
395
+ * marketing: false,
396
+ * },
397
+ * });
398
+ *
399
+ * // Custom sound for warnings
400
+ * const policy = createToastPolicy({
401
+ * soundLevels: ['warning', 'danger'],
402
+ * });
403
+ *
404
+ * // Fully custom logic
405
+ * const policy = createToastPolicy({
406
+ * shouldToast: (n) => n.level === 'danger',
407
+ * shouldPlaySound: (n) => n.category === 'security',
408
+ * });
409
+ * ```
410
+ */
411
+ declare function createToastPolicy(config: ToastPolicyConfig): ToastPolicy;
412
+
413
+ /**
414
+ * Modal helper functions for implementing accessible notification modals.
415
+ * These helpers ensure WCAG 2.1 AA compliance.
416
+ */
417
+
418
+ /**
419
+ * Action type from notification payload.
420
+ */
421
+ interface NotifyKitAction {
422
+ readonly type: 'link' | 'api' | 'ack' | 'snooze';
423
+ readonly label: string;
424
+ readonly primary?: boolean;
425
+ readonly url?: string;
426
+ readonly method?: string;
427
+ readonly endpoint?: string;
428
+ readonly body?: Record<string, unknown>;
429
+ readonly confirm?: string;
430
+ }
431
+ /**
432
+ * Get appropriate ARIA attributes for a modal element.
433
+ *
434
+ * @param notification - The notification being displayed in the modal
435
+ * @param ids - Element IDs for title and body elements
436
+ * @returns Object of ARIA attributes to spread on the modal element
437
+ *
438
+ * @example
439
+ * ```vue
440
+ * <div v-bind="getModalAriaAttributes(notification, { titleId: 'modal-title', bodyId: 'modal-body' })">
441
+ * <h2 id="modal-title">{{ notification.title }}</h2>
442
+ * <p id="modal-body">{{ notification.body }}</p>
443
+ * </div>
444
+ * ```
445
+ */
446
+ declare function getModalAriaAttributes(notification: NotifyKitNotification, ids: {
447
+ titleId: string;
448
+ bodyId: string;
449
+ }): Record<string, string>;
450
+ /**
451
+ * Get an escape key handler based on the modal's escape behavior configuration.
452
+ *
453
+ * @param notification - The notification being displayed
454
+ * @param callbacks - Callback functions for close and snooze actions
455
+ * @returns A keydown event handler, or null if escape is disabled
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * const handleKeydown = getEscapeKeyHandler(notification, {
460
+ * onClose: () => closeModal(),
461
+ * onSnooze: (minutes) => snoozeModal(minutes),
462
+ * });
463
+ *
464
+ * if (handleKeydown) {
465
+ * document.addEventListener('keydown', handleKeydown);
466
+ * }
467
+ * ```
468
+ */
469
+ declare function getEscapeKeyHandler(notification: NotifyKitNotification, callbacks: {
470
+ onClose: () => void;
471
+ onSnooze: (minutes: number) => void;
472
+ }): ((event: KeyboardEvent) => void) | null;
473
+ /**
474
+ * Focus trap interface returned by createFocusTrap.
475
+ */
476
+ interface FocusTrap {
477
+ /** Activate the focus trap - call when modal opens */
478
+ activate: () => void;
479
+ /** Deactivate the focus trap - call when modal closes */
480
+ deactivate: () => void;
481
+ }
482
+ /**
483
+ * Create a focus trap for a modal element.
484
+ * Traps tab/shift+tab navigation inside the modal.
485
+ *
486
+ * @param modalElement - The modal DOM element to trap focus within
487
+ * @returns Object with activate/deactivate methods
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * const trap = createFocusTrap(modalRef.value);
492
+ *
493
+ * onMounted(() => trap.activate());
494
+ * onUnmounted(() => trap.deactivate());
495
+ * ```
496
+ */
497
+ declare function createFocusTrap(modalElement: HTMLElement): FocusTrap;
498
+ /**
499
+ * Get data attributes for an action button.
500
+ *
501
+ * @param action - The action configuration
502
+ * @param index - Index of the action in the actions array
503
+ * @returns Object of attributes to spread on the button element
504
+ *
505
+ * @example
506
+ * ```vue
507
+ * <button
508
+ * v-for="(action, index) in actions"
509
+ * v-bind="getActionButtonAttributes(action, index)"
510
+ * @click="handleAction(action)"
511
+ * >
512
+ * {{ action.label }}
513
+ * </button>
514
+ * ```
515
+ */
516
+ declare function getActionButtonAttributes(action: NotifyKitAction, index: number): Record<string, string | boolean>;
517
+ /**
518
+ * Determine if a notification is critical (requires acknowledgment).
519
+ *
520
+ * @param notification - The notification to check
521
+ * @returns True if the notification is critical
522
+ */
523
+ declare function isCriticalModal(notification: NotifyKitNotification): boolean;
524
+ /**
525
+ * Determine if backdrop click should close the modal.
526
+ *
527
+ * @param notification - The notification being displayed
528
+ * @returns True if clicking the backdrop should close the modal
529
+ */
530
+ declare function shouldCloseOnBackdropClick(notification: NotifyKitNotification): boolean;
531
+ /**
532
+ * Get the minimum snooze duration for a notification.
533
+ *
534
+ * @param notification - The notification to check
535
+ * @returns Minimum snooze duration in minutes, or null if snoozing is not available
536
+ */
537
+ declare function getMinSnoozeDuration(notification: NotifyKitNotification): number | null;
538
+
539
+ /**
540
+ * @coding-factory/notify-kit-client
541
+ *
542
+ * Headless Vue 3/Nuxt client for Notify Kit notifications.
543
+ * Provides TypeScript types, HTTP client, composables, and Nuxt integration.
544
+ */
545
+ declare const VERSION = "0.1.0";
546
+
547
+ export { ConnectionState, ENDPOINTS, type EchoChannelLike, type EchoLike, type FallbackConfig, type FocusTrap, ListNotificationsParams, NOTIFY_KIT_CLIENT_KEY, NotificationCategory, NotificationLevel, type NotifyKitAction, NotifyKitClient, NotifyKitClientConfig, type NotifyKitClientLike, NotifyKitListResponse, NotifyKitMeResponse, NotifyKitNotification, NotifyKitPreferences, NotifyKitPreferencesUpdate, NotifyKitUnreadCountResponse, PaginationParams, type ToastPolicy, type ToastPolicyConfig, type UseNotifyKitClientReturn, type UseNotifyKitFallbackOptions, type UseNotifyKitFallbackReturn, type UseNotifyKitRealtimeOptions, type UseNotifyKitRealtimeReturn, VERSION, createFocusTrap, createToastPolicy, defaultToastPolicy, getActionButtonAttributes, getEscapeKeyHandler, getMinSnoozeDuration, getModalAriaAttributes, isCriticalModal, provideNotifyKitClient, shouldCloseOnBackdropClick, useNotifyKitClient, useNotifyKitFallback, useNotifyKitRealtime };