UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

103 lines 4.43 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { useState, useEffect, useCallback, useRef } from 'react'; const isBrowser = typeof window !== 'undefined'; const notificationApi = isBrowser ? window.Notification : undefined; /** * Hook to manage web notifications. * * @param defaultOptions Default options for the notification (title is required). * @returns State and functions to request permission and show notifications. */ export function useNotification(defaultOptions) { const isSupported = !!notificationApi; const [permission, setPermission] = useState(isSupported ? notificationApi.permission : 'default'); const [error, setError] = useState(null); const optionsRef = useRef(defaultOptions); // Keep optionsRef updated useEffect(() => { optionsRef.current = defaultOptions; }, [defaultOptions]); const requestPermission = useCallback(async () => { if (!isSupported) { setError(new Error('Notifications not supported by this browser.')); return 'denied'; } try { const status = await notificationApi.requestPermission(); setPermission(status); setError(null); return status; } catch (err) { console.error('Error requesting notification permission:', err); const currentError = err instanceof Error ? err : new Error('Failed to request permission'); setError(currentError); setPermission('denied'); // Assume denied on error return 'denied'; } }, [isSupported]); const showNotification = useCallback((overrideOptions) => { if (!isSupported) { console.warn('Notifications not supported.'); setError(new Error('Notifications not supported by this browser.')); return null; } if (permission !== 'granted') { console.warn('Notification permission not granted.'); // Optionally, you could trigger requestPermission here, or just log // setError(new Error('Permission not granted')); // Maybe too noisy return null; } const finalOptions = Object.assign(Object.assign({}, optionsRef.current), overrideOptions); const { title, onClick, onClose, onError: optionsOnError, onShow } = finalOptions, restOptions = __rest(finalOptions, ["title", "onClick", "onClose", "onError", "onShow"]); if (!title) { console.error('Notification title is required.'); setError(new Error('Notification title is required.')); return null; } try { const notification = new Notification(title, restOptions); notification.onclick = onClick || null; notification.onclose = onClose || null; notification.onerror = optionsOnError || null; notification.onshow = onShow || null; setError(null); return notification; } catch (err) { console.error('Error creating notification:', err); const currentError = err instanceof Error ? err : new Error('Failed to show notification'); setError(currentError); return null; } }, [isSupported, permission]); // Optional: Listen for permission changes from browser settings (might not work everywhere) // useEffect(() => { // if (!isSupported) return; // const handler = () => setPermission(notificationApi.permission); // // navigator.permissions?.query({ name: 'notifications' }).then(permissionStatus => { // // permissionStatus.onchange = handler; // // }); // // return () => { /* remove listener */ }; // }, [isSupported]); return { permission, requestPermission, showNotification, error, isSupported, }; } //# sourceMappingURL=useNotification.js.map