'use client'; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { Cookie } from 'lucide-react'; import { useEffect, useState } from 'react'; import { CONSENT_CATEGORIES } from './categories.js'; import { useConsentContext } from './ConsentContext.js'; /** * Colours and radius come from CSS custom properties with built-in fallbacks, * so the banner looks right with no setup, and re-skinning per client means * declaring a few variables — no imports, no props, no specificity fights: * * ```css * :root { * --ipal-primary: #16a34a; * --ipal-radius: 1rem; * } * ``` * * Available: --ipal-surface, --ipal-border, --ipal-text, --ipal-text-strong, * --ipal-text-muted, --ipal-primary, --ipal-primary-hover, --ipal-primary-text, * --ipal-hover, --ipal-radius. Each has a `-dark` counterpart used under * Tailwind's `dark:` variant (e.g. --ipal-surface-dark). * * Layout stays in Tailwind: spacing and flow aren't things a brand changes, and * exposing them as tokens would mean re-inventing CSS one variable at a time. */ const surface = 'bg-[var(--ipal-surface,#fff)] dark:bg-[var(--ipal-surface-dark,#171717)]'; const border = 'border-[var(--ipal-border,#e5e5e5)] dark:border-[var(--ipal-border-dark,#262626)]'; const radius = 'rounded-[var(--ipal-radius,0.375rem)]'; const accent = 'text-[var(--ipal-primary,#2563eb)]'; const defaults = { primaryButton: `${radius} px-3 py-1.5 text-sm font-medium bg-[var(--ipal-primary,#2563eb)] text-[var(--ipal-primary-text,#fff)] hover:bg-[var(--ipal-primary-hover,#1d4ed8)]`, root: `fixed inset-x-0 bottom-0 z-50 border-t p-4 shadow-lg ${surface} ${border}`, secondaryButton: `${radius} px-3 py-1.5 text-sm font-medium text-[var(--ipal-text,#404040)] hover:bg-[var(--ipal-hover,#f5f5f5)] dark:text-[var(--ipal-text-dark,#e5e5e5)] dark:hover:bg-[var(--ipal-hover-dark,#262626)]` }; const bodyText = 'text-[var(--ipal-text,#404040)] dark:text-[var(--ipal-text-dark,#d4d4d4)]'; const strongText = 'text-[var(--ipal-text-strong,#171717)] dark:text-[var(--ipal-text-strong-dark,#f5f5f5)]'; const mutedText = 'text-[var(--ipal-text-muted,#737373)] dark:text-[var(--ipal-text-muted-dark,#a3a3a3)]'; export function CookieBanner({ classNames } = {}) { const { acceptAll, decided, rejectAll, savePreferences, state, texts } = useConsentContext(); const [showSettings, setShowSettings] = useState(false); const [choices, setChoices] = useState(state); useEffect(()=>{ setChoices(state); }, [ state ]); if (decided) { return null; } const toggle = (cat)=>{ if (cat === 'necessary') { return; } setChoices((prev)=>({ ...prev, [cat]: !prev[cat] })); }; const rootClass = classNames?.root ?? defaults.root; const primaryClass = classNames?.primaryButton ?? defaults.primaryButton; const secondaryClass = classNames?.secondaryButton ?? defaults.secondaryButton; return /*#__PURE__*/ _jsx("div", { "aria-label": "Cookie consent", className: rootClass, "data-ipal": "banner", role: "dialog", children: /*#__PURE__*/ _jsx("div", { className: "mx-auto max-w-4xl", children: !showSettings ? /*#__PURE__*/ _jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [ /*#__PURE__*/ _jsxs("div", { className: "flex items-start gap-3", children: [ /*#__PURE__*/ _jsx(Cookie, { "aria-hidden": "true", className: `h-6 w-6 shrink-0 ${accent}` }), /*#__PURE__*/ _jsxs("p", { className: `text-justify text-sm ${bodyText}`, children: [ texts.message, texts.privacyLink && /*#__PURE__*/ _jsxs(_Fragment, { children: [ ' ', /*#__PURE__*/ _jsx("a", { className: `${accent} underline hover:no-underline`, href: texts.privacyLink.href, children: texts.privacyLink.label }) ] }) ] }) ] }), /*#__PURE__*/ _jsxs("div", { className: "flex shrink-0 gap-2", children: [ /*#__PURE__*/ _jsx("button", { className: secondaryClass, onClick: ()=>setShowSettings(true), children: texts.buttons.settings }), /*#__PURE__*/ _jsx("button", { className: secondaryClass, onClick: rejectAll, children: texts.buttons.reject }), /*#__PURE__*/ _jsx("button", { className: primaryClass, onClick: acceptAll, children: texts.buttons.acceptAll }) ] }) ] }) : /*#__PURE__*/ _jsxs("div", { className: "flex flex-col gap-4", children: [ /*#__PURE__*/ _jsxs("h2", { className: `flex items-center gap-2 text-base font-semibold ${strongText}`, children: [ /*#__PURE__*/ _jsx(Cookie, { "aria-hidden": "true", className: `h-5 w-5 ${accent}` }), texts.settingsTitle ] }), /*#__PURE__*/ _jsx("ul", { className: "flex flex-col gap-3", children: CONSENT_CATEGORIES.map((cat)=>/*#__PURE__*/ _jsxs("li", { className: "flex items-start justify-between gap-4", children: [ /*#__PURE__*/ _jsxs("div", { children: [ /*#__PURE__*/ _jsx("p", { className: `text-sm font-medium ${strongText}`, children: texts.categories[cat].title }), /*#__PURE__*/ _jsx("p", { className: `text-xs ${mutedText}`, children: texts.categories[cat].description }) ] }), /*#__PURE__*/ _jsx("input", { checked: cat === 'necessary' ? true : choices[cat], className: "mt-1 h-4 w-4 shrink-0 accent-[var(--ipal-primary,#2563eb)]", disabled: cat === 'necessary', onChange: ()=>toggle(cat), type: "checkbox" }) ] }, cat)) }), /*#__PURE__*/ _jsxs("div", { className: "flex justify-end gap-2", children: [ /*#__PURE__*/ _jsx("button", { className: secondaryClass, onClick: ()=>setShowSettings(false), children: texts.buttons.back }), /*#__PURE__*/ _jsx("button", { className: primaryClass, onClick: ()=>savePreferences(choices), children: texts.buttons.save }) ] }) ] }) }) }); } //# sourceMappingURL=CookieBanner.js.map