cookiebanner-finally
Version:
Headless cookie banner library for Next.js with shadcn philosophy
1 lines • 42.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/types/index.ts","../src/core/cookies.ts","../src/core/ConsentProvider.tsx","../src/hooks/useCookieBanner.ts","../src/hooks/useCookiePreferences.ts","../src/hooks/useConsentGate.ts","../src/scripts/ScriptManager.ts","../src/hooks/useScriptLoader.ts","../src/components/ConsentGate.tsx","../src/components/ScriptLoader.tsx"],"names":["ConsentCategory","DEFAULT_CONSENT_PREFERENCES","DEFAULT_CONSENT_GATE_MESSAGES","DEFAULT_COOKIE_NAME","DEFAULT_COOKIE_OPTIONS","CookieManager","cookieName","cookieOptions","cookieValue","parsed","error","preferences","updatedPreferences","category","Cookies","value","cookieManager","ConsentContext","createContext","ConsentProvider","children","cookieExpires","initialPreferences","autoShowBanner","manager","useState","setPreferences","isConsentGiven","setIsConsentGiven","showBanner","setShowBanner","isMounted","setIsMounted","useEffect","hasGivenConsent","currentPreferences","acceptAll","updated","denyAll","updatePreferences","newPreferences","closeOnUpdate","closeBanner","resetBanner","hasConsentFor","jsx","Fragment","useConsentContext","context","useContext","useCookieBanner","useCookiePreferences","isLoading","enabled","useConsentGate","isClient","setIsClient","ScriptManager","script","scripts","id","hasConsent","resolve","categoryScripts","callback","scriptElement","key","scriptManager","useScriptLoader","s","consent","ConsentGate","fallback","loading","showPromptOnClick","messages","showConsentPrompt","finalMessages","jsxs","ScriptLoader","onLoad","autoLoad","register","load","isLoaded","success","ScriptBatchLoader","registerBatch","results"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Cookie consent categories\n */\nexport enum ConsentCategory {\n Necessary = 'necessary',\n Preferences = 'preferences',\n Analytics = 'analytics',\n Marketing = 'marketing'\n}\n\n/**\n * Cookie consent preferences\n */\nexport interface ConsentPreferences {\n [ConsentCategory.Necessary]: boolean; // Always true\n [ConsentCategory.Preferences]: boolean;\n [ConsentCategory.Analytics]: boolean;\n [ConsentCategory.Marketing]: boolean;\n lastUpdated?: string;\n}\n\n/**\n * Default consent preferences\n */\nexport const DEFAULT_CONSENT_PREFERENCES: ConsentPreferences = {\n [ConsentCategory.Necessary]: true, // Necessary cookies are always allowed\n [ConsentCategory.Preferences]: false,\n [ConsentCategory.Analytics]: false,\n [ConsentCategory.Marketing]: false\n};\n\n/**\n * Custom messages for consent gate\n */\nexport interface ConsentGateMessages {\n /**\n * Message shown when content requires consent\n * Can include {category} placeholder for the consent category\n */\n consentRequired?: string;\n \n /**\n * Button text for managing preferences\n */\n managePreferences?: string;\n \n /**\n * Loading message\n */\n loading?: string;\n}\n\n/**\n * Default messages for consent gate\n */\nexport const DEFAULT_CONSENT_GATE_MESSAGES: ConsentGateMessages = {\n consentRequired: 'This content requires consent for {category} cookies.',\n managePreferences: 'Manage Cookie Preferences',\n loading: 'Loading...'\n};\n\n/**\n * Script definition\n */\nexport interface Script {\n id: string;\n category: ConsentCategory;\n src?: string;\n content?: string;\n attributes?: Record<string, string>;\n}\n","import Cookies from 'js-cookie';\nimport { ConsentCategory, ConsentPreferences, DEFAULT_CONSENT_PREFERENCES } from '../types';\n\n// Default cookie name for storing consent preferences\nconst DEFAULT_COOKIE_NAME = 'cookie-consent';\n\n// Default cookie options\nconst DEFAULT_COOKIE_OPTIONS = {\n expires: 365, // 1 year\n path: '/',\n sameSite: 'strict' as const\n};\n\n/**\n * Cookie manager for handling consent preferences\n */\nexport class CookieManager {\n private cookieName: string;\n private cookieOptions: Cookies.CookieAttributes;\n \n constructor(\n cookieName: string = DEFAULT_COOKIE_NAME,\n cookieOptions: Cookies.CookieAttributes = DEFAULT_COOKIE_OPTIONS\n ) {\n this.cookieName = cookieName;\n this.cookieOptions = cookieOptions;\n }\n\n /**\n * Get current consent preferences\n */\n getConsentPreferences(): ConsentPreferences {\n try {\n const cookieValue = this.getCookieValue();\n if (!cookieValue) {\n return { ...DEFAULT_CONSENT_PREFERENCES };\n }\n \n const parsed = JSON.parse(cookieValue) as Partial<ConsentPreferences>;\n \n // Always ensure necessary cookies are accepted\n return {\n ...DEFAULT_CONSENT_PREFERENCES,\n ...parsed,\n [ConsentCategory.Necessary]: true\n };\n } catch (error) {\n console.error('Error parsing consent preferences', error);\n return { ...DEFAULT_CONSENT_PREFERENCES };\n }\n }\n\n /**\n * Save consent preferences\n */\n saveConsentPreferences(preferences: Partial<ConsentPreferences>): ConsentPreferences {\n const currentPreferences = this.getConsentPreferences();\n const updatedPreferences: ConsentPreferences = {\n ...currentPreferences,\n ...preferences,\n [ConsentCategory.Necessary]: true, // Always ensure necessary cookies are accepted\n lastUpdated: new Date().toISOString()\n };\n\n try {\n this.setCookieValue(JSON.stringify(updatedPreferences));\n } catch (error) {\n console.error('Error saving consent preferences', error);\n }\n\n return updatedPreferences;\n }\n\n /**\n * Check if consent is given for a specific category\n */\n hasConsent(category: ConsentCategory): boolean {\n const preferences = this.getConsentPreferences();\n return preferences[category] === true;\n }\n\n /**\n * Accept all cookie categories\n */\n acceptAll(): ConsentPreferences {\n return this.saveConsentPreferences({\n [ConsentCategory.Necessary]: true,\n [ConsentCategory.Preferences]: true,\n [ConsentCategory.Analytics]: true,\n [ConsentCategory.Marketing]: true\n });\n }\n\n /**\n * Deny all non-necessary cookie categories\n */\n denyAll(): ConsentPreferences {\n return this.saveConsentPreferences({\n [ConsentCategory.Necessary]: true,\n [ConsentCategory.Preferences]: false,\n [ConsentCategory.Analytics]: false,\n [ConsentCategory.Marketing]: false\n });\n }\n\n /**\n * Check if consent has been given (for any category besides necessary)\n */\n hasConsentBeenGiven(): boolean {\n try {\n return this.getCookieValue() !== null;\n } catch {\n return false;\n }\n }\n\n /**\n * Get cookie value\n */\n private getCookieValue(): string | null {\n // For client-side usage\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n return Cookies.get(this.cookieName) || null;\n }\n \n // For server-side usage, return null since we can't access cookies directly\n return null;\n }\n\n /**\n * Set cookie value\n */\n private setCookieValue(value: string): void {\n // Only set cookies on the client-side\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n Cookies.set(this.cookieName, value, this.cookieOptions);\n }\n }\n}\n\n// Export a default instance\nexport const cookieManager = new CookieManager();\n","'use client';\n\nimport React, { createContext, useContext, useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { cookieManager, CookieManager } from './cookies';\nimport { ConsentCategory, DEFAULT_CONSENT_PREFERENCES } from '../types';\nimport type { ConsentPreferences } from '../types';\n\n// Define the consent context shape\ninterface ConsentContextType {\n // Consent state\n preferences: ConsentPreferences;\n isConsentGiven: boolean;\n showBanner: boolean;\n \n // Consent management methods\n acceptAll: () => void;\n denyAll: () => void;\n updatePreferences: (preferences: Partial<ConsentPreferences>, closeOnUpdate?: boolean) => void;\n closeBanner: () => void;\n resetBanner: () => void;\n hasConsentFor: (category: ConsentCategory) => boolean;\n}\n\n// Create context with default values\nconst ConsentContext = createContext<ConsentContextType>({\n preferences: DEFAULT_CONSENT_PREFERENCES,\n isConsentGiven: false,\n showBanner: false,\n acceptAll: () => {},\n denyAll: () => {},\n updatePreferences: () => {},\n closeBanner: () => {},\n resetBanner: () => {},\n hasConsentFor: () => false,\n});\n\n// Provider props\ninterface ConsentProviderProps {\n children: ReactNode;\n cookieName?: string;\n cookieExpires?: number;\n initialPreferences?: Partial<ConsentPreferences>;\n autoShowBanner?: boolean;\n}\n\n/**\n * Provider component for cookie consent management\n */\nexport const ConsentProvider: React.FC<ConsentProviderProps> = ({\n children,\n cookieName,\n cookieExpires,\n initialPreferences,\n autoShowBanner = true,\n}) => {\n // Initialize cookie manager if custom options are provided\n const [manager] = useState(() => {\n if (cookieName || cookieExpires) {\n return new CookieManager(\n cookieName,\n cookieExpires ? { expires: cookieExpires, path: '/', sameSite: 'strict' } : undefined\n );\n }\n return cookieManager;\n });\n\n // State\n const [preferences, setPreferences] = useState<ConsentPreferences>(DEFAULT_CONSENT_PREFERENCES);\n const [isConsentGiven, setIsConsentGiven] = useState(false);\n const [showBanner, setShowBanner] = useState(false);\n const [isMounted, setIsMounted] = useState(false);\n \n // State management\n\n // Initialize on mount (client-side only)\n useEffect(() => {\n const hasGivenConsent = manager.hasConsentBeenGiven();\n \n // Only apply initialPreferences if user hasn't given consent yet\n if (initialPreferences && !hasGivenConsent) {\n manager.saveConsentPreferences(initialPreferences);\n }\n \n const currentPreferences = manager.getConsentPreferences();\n setPreferences(currentPreferences);\n setIsConsentGiven(hasGivenConsent);\n \n // Show banner if consent not given and autoShowBanner is true\n setShowBanner(autoShowBanner && !hasGivenConsent);\n \n // Mark as mounted\n setIsMounted(true);\n }, [manager, initialPreferences, autoShowBanner]);\n\n // Update functions\n const acceptAll = () => {\n const updated = manager.acceptAll();\n setPreferences(updated);\n setIsConsentGiven(true);\n setShowBanner(false);\n // Update state\n };\n\n const denyAll = () => {\n const updated = manager.denyAll();\n setPreferences(updated);\n setIsConsentGiven(true);\n setShowBanner(false);\n // Update state\n };\n\n const updatePreferences = (newPreferences: Partial<ConsentPreferences>, closeOnUpdate: boolean = false) => {\n const updated = manager.saveConsentPreferences(newPreferences);\n setPreferences(updated);\n setIsConsentGiven(true);\n \n // Only close the banner if explicitly requested\n if (closeOnUpdate) {\n setShowBanner(false);\n }\n };\n\n const closeBanner = () => {\n setShowBanner(false);\n };\n\n const resetBanner = () => {\n setShowBanner(true);\n };\n\n const hasConsentFor = (category: ConsentCategory): boolean => {\n return manager.hasConsent(category);\n };\n\n // Skip rendering until mounted (hydration safety)\n if (!isMounted) {\n return <>{children}</>;\n }\n\n return (\n <ConsentContext.Provider\n value={{\n preferences,\n isConsentGiven,\n showBanner,\n acceptAll,\n denyAll,\n updatePreferences,\n closeBanner,\n resetBanner,\n hasConsentFor,\n }}\n >\n {children}\n </ConsentContext.Provider>\n );\n};\n\n/**\n * Hook for using consent context\n */\nexport const useConsentContext = () => {\n const context = useContext(ConsentContext);\n if (context === undefined) {\n throw new Error('useConsentContext must be used within a ConsentProvider');\n }\n return context;\n};\n","'use client';\n\nimport { useConsentContext } from '../core/ConsentProvider';\n\n/**\n * Interface for the useCookieBanner hook\n */\nexport interface UseCookieBannerResult {\n // Banner state\n isVisible: boolean;\n isConsentGiven: boolean;\n \n // User actions\n acceptAll: () => void;\n denyAll: () => void;\n close: () => void;\n show: () => void;\n}\n\n/**\n * Hook for managing the cookie consent banner\n * \n * @returns Banner state and methods\n * \n * @example\n * ```tsx\n * const CookieBanner = () => {\n * const { isVisible, acceptAll, denyAll, close } = useCookieBanner();\n * \n * if (!isVisible) return null;\n * \n * return (\n * <div className=\"cookie-banner\">\n * <p>We use cookies to improve your experience.</p>\n * <div className=\"cookie-banner-buttons\">\n * <button onClick={acceptAll}>Accept All</button>\n * <button onClick={denyAll}>Reject All</button>\n * <button onClick={close}>Close</button>\n * </div>\n * </div>\n * );\n * }\n * ```\n */\nexport function useCookieBanner(): UseCookieBannerResult {\n const {\n showBanner,\n isConsentGiven,\n acceptAll,\n denyAll,\n closeBanner,\n resetBanner,\n } = useConsentContext();\n\n // Update methods to ensure they close the banner\n return {\n isVisible: showBanner,\n isConsentGiven,\n acceptAll,\n denyAll,\n close: closeBanner,\n show: resetBanner,\n };\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useConsentContext } from '../core/ConsentProvider';\nimport { ConsentCategory } from '../types';\nimport type { ConsentPreferences } from '../types';\n\n/**\n * Interface for the useCookiePreferences hook\n */\nexport interface UseCookiePreferencesResult {\n // Preference data\n preferences: ConsentPreferences;\n isLoading: boolean;\n \n // Check specific category\n isEnabled: (category: ConsentCategory) => boolean;\n \n // Update methods\n updatePreferences: (preferences: Partial<ConsentPreferences>) => void;\n updateCategory: (category: ConsentCategory, enabled: boolean) => void;\n}\n\n/**\n * Hook for reading and updating cookie preferences\n * \n * @returns Cookie preferences state and update methods\n * \n * @example\n * ```tsx\n * const CookieSettings = () => {\n * const { preferences, isLoading, updateCategory } = useCookiePreferences();\n * \n * if (isLoading) return <div>Loading preferences...</div>;\n * \n * return (\n * <div className=\"cookie-settings\">\n * <h2>Cookie Settings</h2>\n * \n * <div className=\"cookie-setting\">\n * <input\n * type=\"checkbox\"\n * id=\"necessary\"\n * checked={preferences.necessary}\n * disabled={true}\n * />\n * <label htmlFor=\"necessary\">Necessary (Required)</label>\n * </div>\n * \n * <div className=\"cookie-setting\">\n * <input\n * type=\"checkbox\"\n * id=\"preferences\"\n * checked={preferences.preferences}\n * onChange={(e) => updateCategory('preferences', e.target.checked)}\n * />\n * <label htmlFor=\"preferences\">Preferences</label>\n * </div>\n * \n * <div className=\"cookie-setting\">\n * <input\n * type=\"checkbox\"\n * id=\"analytics\"\n * checked={preferences.analytics}\n * onChange={(e) => updateCategory('analytics', e.target.checked)}\n * />\n * <label htmlFor=\"analytics\">Analytics</label>\n * </div>\n * \n * <div className=\"cookie-setting\">\n * <input\n * type=\"checkbox\"\n * id=\"marketing\"\n * checked={preferences.marketing}\n * onChange={(e) => updateCategory('marketing', e.target.checked)}\n * />\n * <label htmlFor=\"marketing\">Marketing</label>\n * </div>\n * </div>\n * );\n * }\n * ```\n */\nexport function useCookiePreferences(): UseCookiePreferencesResult {\n const { preferences, updatePreferences, hasConsentFor } = useConsentContext();\n // Since ConsentProvider already handles the initial loading state,\n // we only need to track if we've received valid preferences from the context\n const isLoading = !preferences || Object.keys(preferences).length === 0;\n\n // Update a single category\n const updateCategory = (category: ConsentCategory, enabled: boolean) => {\n updatePreferences({ [category]: enabled }, false);\n };\n\n // Check if a category is enabled\n const isEnabled = (category: ConsentCategory) => {\n return hasConsentFor(category);\n };\n\n return {\n preferences,\n isLoading,\n isEnabled,\n updatePreferences,\n updateCategory,\n };\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useConsentContext } from '../core/ConsentProvider';\nimport { ConsentCategory } from '../types';\n\n/**\n * Interface for the useConsentGate hook\n */\nexport interface UseConsentGateResult {\n // State\n hasConsent: boolean;\n isLoading: boolean;\n \n // Show prompt\n showConsentPrompt: () => void;\n}\n\n/**\n * Hook for conditionally rendering content based on consent\n * \n * @param category - The consent category to check\n * @returns State indicating if content can be displayed\n * \n * @example\n * ```tsx\n * const YouTubeEmbed = ({ videoId }: { videoId: string }) => {\n * const { hasConsent, isLoading, showConsentPrompt } = useConsentGate(\n * ConsentCategory.Marketing\n * );\n * \n * if (isLoading) {\n * return <div>Loading...</div>;\n * }\n * \n * if (!hasConsent) {\n * return (\n * <div className=\"consent-placeholder\">\n * <p>This content requires marketing cookies consent.</p>\n * <button onClick={showConsentPrompt}>Manage Cookie Preferences</button>\n * </div>\n * );\n * }\n * \n * return (\n * <iframe\n * src={`https://www.youtube.com/embed/${videoId}`}\n * frameBorder=\"0\"\n * allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n * allowFullScreen\n * />\n * );\n * }\n * ```\n */\nexport function useConsentGate(category: ConsentCategory): UseConsentGateResult {\n const { hasConsentFor, resetBanner } = useConsentContext();\n const [isClient, setIsClient] = useState(false);\n \n // Handle server-side rendering\n useEffect(() => {\n setIsClient(true);\n }, []);\n \n // Check for consent (only client-side)\n const hasConsent = isClient ? hasConsentFor(category) : false;\n \n // Show the consent banner\n const showConsentPrompt = () => {\n resetBanner();\n };\n \n return {\n hasConsent,\n isLoading: !isClient,\n showConsentPrompt,\n };\n}\n","import { ConsentCategory, Script } from '../types';\n\n/**\n * Script manager for loading scripts based on consent\n */\nexport class ScriptManager {\n private scripts: Map<string, Script> = new Map();\n private loadedScripts: Set<string> = new Set();\n\n /**\n * Register a script\n */\n register(script: Script): void {\n if (!script.id) {\n throw new Error('Script ID is required');\n }\n \n if (!script.category) {\n throw new Error('Script category is required');\n }\n \n if (!script.src && !script.content) {\n throw new Error('Either src or content is required');\n }\n \n this.scripts.set(script.id, script);\n }\n\n /**\n * Register multiple scripts\n */\n registerBatch(scripts: Script[]): void {\n scripts.forEach(script => this.register(script));\n }\n\n /**\n * Load a script by ID if consent is given\n */\n loadScript(id: string, hasConsent: boolean): Promise<boolean> {\n const script = this.scripts.get(id);\n \n if (!script) {\n console.error(`Script with ID ${id} not found`);\n return Promise.resolve(false);\n }\n \n // Skip if already loaded\n if (this.loadedScripts.has(id)) {\n return Promise.resolve(true);\n }\n \n // Only load if consent is given\n if (!hasConsent) {\n return Promise.resolve(false);\n }\n \n return new Promise((resolve) => {\n // External script\n if (script.src) {\n this.loadExternalScript(script, () => {\n this.loadedScripts.add(id);\n resolve(true);\n });\n } \n // Inline script\n else if (script.content) {\n this.loadInlineScript(script);\n this.loadedScripts.add(id);\n resolve(true);\n }\n });\n }\n\n /**\n * Load scripts by category if consent is given\n */\n loadScriptsByCategory(category: ConsentCategory, hasConsent: boolean): Promise<boolean[]> {\n const categoryScripts = Array.from(this.scripts.values())\n .filter(script => script.category === category);\n \n return Promise.all(\n categoryScripts.map(script => this.loadScript(script.id, hasConsent))\n );\n }\n\n /**\n * Check if a script is loaded\n */\n isLoaded(id: string): boolean {\n return this.loadedScripts.has(id);\n }\n\n /**\n * Get all registered scripts\n */\n getAllScripts(): Script[] {\n return Array.from(this.scripts.values());\n }\n\n /**\n * Get scripts by category\n */\n getScriptsByCategory(category: ConsentCategory): Script[] {\n return Array.from(this.scripts.values())\n .filter(script => script.category === category);\n }\n\n /**\n * Load an external script\n */\n private loadExternalScript(script: Script, callback: () => void): void {\n if (typeof document === 'undefined') return;\n \n const scriptElement = document.createElement('script');\n \n // Add src attribute\n if (script.src) {\n scriptElement.src = script.src;\n }\n \n // Add custom attributes\n if (script.attributes) {\n Object.entries(script.attributes).forEach(([key, value]) => {\n scriptElement.setAttribute(key, value);\n });\n }\n \n // Set success callback\n scriptElement.onload = callback;\n \n // Set error handling\n scriptElement.onerror = (error) => {\n console.error(`Failed to load script: ${script.id}`, error);\n // Still call callback to resolve the promise, but log the error\n callback();\n };\n \n // Add to document\n document.head.appendChild(scriptElement);\n }\n\n /**\n * Load an inline script\n */\n private loadInlineScript(script: Script): void {\n if (typeof document === 'undefined' || !script.content) return;\n \n const scriptElement = document.createElement('script');\n \n // Set content\n scriptElement.text = script.content;\n \n // Add custom attributes\n if (script.attributes) {\n Object.entries(script.attributes).forEach(([key, value]) => {\n scriptElement.setAttribute(key, value);\n });\n }\n \n try {\n // Add to document\n document.head.appendChild(scriptElement);\n } catch (error) {\n console.error(`Error executing inline script: ${script.id}`, error);\n }\n }\n}\n\n// Create a default instance\nexport const scriptManager = new ScriptManager();\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useConsentContext } from '../core/ConsentProvider';\nimport { scriptManager } from '../scripts/ScriptManager';\nimport { ConsentCategory, Script } from '../types';\n\n/**\n * Interface for the useScriptLoader hook\n */\nexport interface UseScriptLoaderResult {\n register: (script: Script) => void;\n registerBatch: (scripts: Script[]) => void;\n load: (id: string) => Promise<boolean>;\n loadCategory: (category: ConsentCategory) => Promise<boolean[]>;\n isLoaded: (id: string) => boolean;\n}\n\n/**\n * Hook for loading scripts based on consent\n * \n * @returns Methods for registering and loading scripts\n * \n * @example\n * ```tsx\n * // In your layout or setup component\n * const MyAnalyticsSetup = () => {\n * const { register, load } = useScriptLoader();\n * \n * useEffect(() => {\n * // Register analytics scripts\n * register({\n * id: 'google-analytics',\n * category: ConsentCategory.Analytics,\n * src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX',\n * });\n * \n * register({\n * id: 'ga-config',\n * category: ConsentCategory.Analytics,\n * content: `\n * window.dataLayer = window.dataLayer || [];\n * function gtag(){dataLayer.push(arguments);}\n * gtag('js', new Date());\n * gtag('config', 'G-XXXXXXXXXX');\n * `,\n * });\n * \n * // Attempt to load (will only load if user has given consent)\n * load('google-analytics').then(() => {\n * load('ga-config');\n * });\n * }, [register, load]);\n * \n * return null; // This is a utility component with no UI\n * };\n * ```\n */\nexport function useScriptLoader(): UseScriptLoaderResult {\n const { hasConsentFor } = useConsentContext();\n const [isMounted, setIsMounted] = useState(false);\n \n // Handle server-side rendering\n useEffect(() => {\n setIsMounted(true);\n }, []);\n \n // Register a script\n const register = (script: Script) => {\n if (isMounted) {\n scriptManager.register(script);\n }\n };\n \n // Register multiple scripts\n const registerBatch = (scripts: Script[]) => {\n if (isMounted) {\n scriptManager.registerBatch(scripts);\n }\n };\n \n // Load a script by ID if consent is given\n const load = async (id: string): Promise<boolean> => {\n if (!isMounted) return false;\n \n const script = scriptManager.getAllScripts().find(s => s.id === id);\n \n if (!script) {\n console.error(`Script with ID ${id} not found`);\n return false;\n }\n \n const consent = hasConsentFor(script.category);\n return scriptManager.loadScript(id, consent);\n };\n \n // Load scripts by category if consent is given\n const loadCategory = (category: ConsentCategory): Promise<boolean[]> => {\n if (!isMounted) return Promise.resolve([]);\n \n const consent = hasConsentFor(category);\n return scriptManager.loadScriptsByCategory(category, consent);\n };\n \n // Check if a script is loaded\n const isLoaded = (id: string): boolean => {\n if (!isMounted) return false;\n return scriptManager.isLoaded(id);\n };\n \n return {\n register,\n registerBatch,\n load,\n loadCategory,\n isLoaded,\n };\n}\n","'use client';\n\nimport React from 'react';\nimport type { ReactNode } from 'react';\nimport { useConsentGate } from '../hooks/useConsentGate';\nimport { ConsentCategory, ConsentGateMessages, DEFAULT_CONSENT_GATE_MESSAGES } from '../types';\n\nexport interface ConsentGateProps {\n /**\n * The content to render when consent is given\n */\n children: ReactNode;\n \n /**\n * The consent category required\n */\n category: ConsentCategory;\n \n /**\n * Custom component to render when consent is not given\n */\n fallback?: ReactNode;\n \n /**\n * Custom loading component\n */\n loading?: ReactNode;\n \n /**\n * Whether to show the consent banner when clicked\n */\n showPromptOnClick?: boolean;\n \n /**\n * Custom messages for the consent gate\n */\n messages?: ConsentGateMessages;\n}\n\n/**\n * Component that conditionally renders content based on consent\n */\nexport const ConsentGate: React.FC<ConsentGateProps> = ({\n children,\n category,\n fallback,\n loading,\n showPromptOnClick = true,\n messages = {},\n}) => {\n const { hasConsent, isLoading, showConsentPrompt } = useConsentGate(category);\n \n // Merge custom messages with defaults\n const finalMessages = { ...DEFAULT_CONSENT_GATE_MESSAGES, ...messages };\n \n // Show loading state\n if (isLoading) {\n return loading ? <>{loading}</> : <div>{finalMessages.loading}</div>;\n }\n \n // Show content if consent is given\n if (hasConsent) {\n return <>{children}</>;\n }\n \n // Show fallback or default fallback\n return fallback ? (\n <>{fallback}</>\n ) : (\n <div className=\"cookie-consent-gate-fallback\">\n <p>{finalMessages.consentRequired?.replace('{category}', category)}</p>\n {showPromptOnClick && (\n <button\n onClick={showConsentPrompt}\n className=\"cookie-consent-gate-button\"\n >\n {finalMessages.managePreferences}\n </button>\n )}\n {/* \n CSS classes to be defined in consumer application:\n \n .cookie-consent-gate-fallback {\n padding: 1rem;\n border: 1px solid #ccc;\n border-radius: 0.25rem;\n background-color: #f8f9fa;\n margin: 0.5rem 0;\n }\n \n .cookie-consent-gate-button {\n padding: 0.5rem 1rem;\n background-color: #0070f3;\n color: white;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n }\n\n .cookie-consent-gate-button:hover {\n background-color: #0051a8;\n }\n */}\n </div>\n );\n};\n","'use client';\n\nimport React, { useEffect } from 'react';\nimport { useScriptLoader } from '../hooks/useScriptLoader';\nimport { Script } from '../types';\n\nexport interface ScriptLoaderProps {\n /**\n * Script to load\n */\n script: Script;\n \n /**\n * Callback when script is loaded\n */\n onLoad?: () => void;\n \n /**\n * Whether to auto-load the script\n * @default true\n */\n autoLoad?: boolean;\n}\n\n/**\n * Component that loads a script based on consent\n */\nexport const ScriptLoader: React.FC<ScriptLoaderProps> = ({\n script,\n onLoad,\n autoLoad = true,\n}) => {\n const { register, load, isLoaded } = useScriptLoader();\n \n // Register the script\n useEffect(() => {\n register(script);\n }, [register, script]);\n \n // Load the script if autoLoad is true\n useEffect(() => {\n if (autoLoad) {\n load(script.id).then(success => {\n if (success && onLoad) {\n onLoad();\n }\n });\n }\n }, [load, script.id, autoLoad, onLoad]);\n \n // This component doesn't render anything\n return null;\n};\n\nexport interface ScriptBatchLoaderProps {\n /**\n * Scripts to load\n */\n scripts: Script[];\n \n /**\n * Callback when all scripts are loaded\n */\n onLoad?: () => void;\n \n /**\n * Whether to auto-load the scripts\n * @default true\n */\n autoLoad?: boolean;\n}\n\n/**\n * Component that loads multiple scripts based on consent\n */\nexport const ScriptBatchLoader: React.FC<ScriptBatchLoaderProps> = ({\n scripts,\n onLoad,\n autoLoad = true,\n}) => {\n const { registerBatch, load } = useScriptLoader();\n \n // Register all scripts\n useEffect(() => {\n registerBatch(scripts);\n }, [registerBatch, scripts]);\n \n // Load all scripts if autoLoad is true\n useEffect(() => {\n if (autoLoad) {\n Promise.all(scripts.map(script => load(script.id)))\n .then(results => {\n if (results.every(Boolean) && onLoad) {\n onLoad();\n }\n });\n }\n }, [load, scripts, autoLoad, onLoad]);\n \n // This component doesn't render anything\n return null;\n};\n"]}