{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "use-notifications",
  "title": "UseNotifications",
  "description": "Manages browser notifications.",
  "files": [
    {
      "path": "registry/hooks/use-notifications.tsx",
      "content": "'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\ntype NotificationPermission = 'default' | 'granted' | 'denied';\n\ntype NotificationOptions<TData = void> = {\n  body?: string;\n  icon?: string;\n  image?: string;\n  badge?: string;\n  tag?: string;\n  data?: TData;\n  requireInteraction?: boolean;\n  silent?: boolean;\n  sound?: string;\n  vibrate?: number | number[];\n  dir?: 'auto' | 'ltr' | 'rtl';\n  lang?: string;\n  renotify?: boolean;\n  sticky?: boolean;\n  timestamp?: number;\n  actions?: Array<{\n    action: string;\n    title: string;\n    icon?: string;\n  }>;\n};\n\ntype UseNotificationsReturn<TData = void> = {\n  permission: NotificationPermission;\n  requestPermission: () => Promise<NotificationPermission>;\n  showNotification: (\n    title: string,\n    options?: NotificationOptions<TData>,\n  ) => void;\n  isSupported: boolean;\n  isSecureContext: boolean;\n  supportsActions: boolean;\n  supportsBadge: boolean;\n  supportsImage: boolean;\n  supportsVibrate: boolean;\n  supportsSound: boolean;\n};\n\n// Cache to store the result of the support check\nconst supportCache = new Map<string, boolean>();\n\ntype NotificationFeature = 'actions' | 'badge' | 'image' | 'vibrate' | 'sound';\n\nfunction checkFeatureSupport(feature: NotificationFeature): boolean {\n  if (supportCache.has(feature)) {\n    return supportCache.get(feature)!;\n  }\n\n  const isSupported = feature in Notification.prototype;\n  supportCache.set(feature, isSupported);\n  return isSupported;\n}\n\nexport function useNotifications<\n  TData = void,\n>(): UseNotificationsReturn<TData> {\n  const [permission, setPermission] =\n    useState<NotificationPermission>('default');\n  const [isSupported, setIsSupported] = useState(false);\n  const [isSecureContext, setIsSecureContext] = useState(false);\n  const [supportsActions, setSupportsActions] = useState(false);\n  const [supportsBadge, setSupportsBadge] = useState(false);\n  const [supportsImage, setSupportsImage] = useState(false);\n  const [supportsVibrate, setSupportsVibrate] = useState(false);\n  const [supportsSound, setSupportsSound] = useState(false);\n\n  // Using useRef to avoid recreating objects on each render\n  const notificationRef = useRef<Notification | null>(null);\n\n  useEffect(() => {\n    const checkSupport = () => {\n      const hasNotification = 'Notification' in window;\n      const isSecure = window.isSecureContext;\n\n      setIsSupported(hasNotification);\n      setIsSecureContext(isSecure);\n\n      if (hasNotification) {\n        setPermission(Notification.permission);\n        setSupportsActions(checkFeatureSupport('actions'));\n        setSupportsBadge(checkFeatureSupport('badge'));\n        setSupportsImage(checkFeatureSupport('image'));\n        setSupportsVibrate(checkFeatureSupport('vibrate'));\n        setSupportsSound(checkFeatureSupport('sound'));\n      }\n    };\n\n    checkSupport();\n  }, []);\n\n  const requestPermission = useCallback(async () => {\n    if (!isSupported) {\n      throw new Error('Notifications are not supported in this browser');\n    }\n\n    if (!isSecureContext) {\n      throw new Error('Notifications require a secure context (HTTPS)');\n    }\n\n    try {\n      const result = await Notification.requestPermission();\n      setPermission(result);\n      return result;\n    } catch (error) {\n      console.error('Error requesting notification permission:', error);\n      throw error;\n    }\n  }, [isSupported, isSecureContext]);\n\n  const showNotification = useCallback(\n    (title: string, options?: NotificationOptions<TData>) => {\n      if (!isSupported) {\n        // Fallback for browsers that do not support notifications\n        console.warn(\n          'Notifications not supported. Consider using a fallback UI notification.',\n        );\n        return;\n      }\n\n      if (!isSecureContext) {\n        console.warn(\n          'Notifications require HTTPS. Consider using a fallback UI notification.',\n        );\n        return;\n      }\n\n      if (permission !== 'granted') {\n        console.warn(\n          'Notification permission not granted. Consider using a fallback UI notification.',\n        );\n        return;\n      }\n\n      try {\n        // Clear previous notification if it exists\n        if (notificationRef.current) {\n          notificationRef.current.close();\n        }\n\n        // Create new notification\n        notificationRef.current = new Notification(title, {\n          ...options,\n          // Remove unsupported options\n          ...(!supportsActions && { actions: undefined }),\n          ...(!supportsBadge && { badge: undefined }),\n          ...(!supportsImage && { image: undefined }),\n          ...(!supportsVibrate && { vibrate: undefined }),\n          ...(!supportsSound && { sound: undefined }),\n        });\n\n        // Clear reference when the notification is closed\n        notificationRef.current.onclose = () => {\n          notificationRef.current = null;\n        };\n      } catch (error) {\n        console.error('Error showing notification:', error);\n        // Fallback for UI notification in case of error\n        console.warn(\n          'Failed to show system notification. Consider using a fallback UI notification.',\n        );\n      }\n    },\n    [\n      isSupported,\n      isSecureContext,\n      permission,\n      supportsActions,\n      supportsBadge,\n      supportsImage,\n      supportsVibrate,\n      supportsSound,\n    ],\n  );\n\n  return {\n    permission,\n    requestPermission,\n    showNotification,\n    isSupported,\n    isSecureContext,\n    supportsActions,\n    supportsBadge,\n    supportsImage,\n    supportsVibrate,\n    supportsSound,\n  };\n}\n",
      "type": "registry:hook",
      "target": "hooks/guarahooks/use-notifications.tsx"
    }
  ],
  "categories": [
    "ui-and-dom"
  ],
  "type": "registry:hook"
}