@supunlakmal/hooks
Version:
A collection of reusable React hooks
103 lines • 4.43 kB
JavaScript
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