UNPKG

@whotechs/react-gdpr-cookie-banner

Version:

A modern, customizable GDPR & Google Consent Mode v2 compliant cookie consent banner

214 lines (202 loc) 17.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var styled = require('styled-components'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __makeTemplateObject(cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var defaultProps = { primaryColor: '#FFD700', textColor: '#FFFFFF', backgroundColor: 'rgba(0, 0, 0, 0.95)', className: '', onPreferencesUpdate: function () { }, titleText: 'Privacy Preferences Center', descriptionText: 'We use cookies and similar technologies to help personalize content, tailor and measure ads, and provide a better experience. By clicking "Accept All", you agree to this use. You can manage your preferences below. These settings will apply to all websites in this domain.', showDelay: 1000, gtmContainerId: '' }; var BannerContainer = styled__default["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: ", ";\n color: ", ";\n padding: 1.5rem;\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n z-index: 9999;\n transform: ", ";\n transition: transform 0.3s ease-in-out;\n opacity: ", ";\n visibility: ", ";\n max-width: 1200px;\n margin: 0 auto;\n border-top-left-radius: 12px;\n border-top-right-radius: 12px;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);\n \n @media (max-width: 768px) {\n padding: 1rem;\n }\n"], ["\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n background: ", ";\n color: ", ";\n padding: 1.5rem;\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n z-index: 9999;\n transform: ", ";\n transition: transform 0.3s ease-in-out;\n opacity: ", ";\n visibility: ", ";\n max-width: 1200px;\n margin: 0 auto;\n border-top-left-radius: 12px;\n border-top-right-radius: 12px;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);\n \n @media (max-width: 768px) {\n padding: 1rem;\n }\n"])), function (props) { return props.backgroundColor; }, function (props) { return props.textColor; }, function (_a) { var show = _a.show; return (show ? 'translateY(0)' : 'translateY(100%)'); }, function (_a) { var show = _a.show; return (show ? '1' : '0'); }, function (_a) { var show = _a.show; return (show ? 'visible' : 'hidden'); }); var Message = styled__default["default"].div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: 1rem;\n"], ["\n display: flex;\n flex-direction: column;\n gap: 1rem;\n"]))); var Title = styled__default["default"].h3(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n margin: 0;\n font-size: 1.2rem;\n font-weight: 600;\n"], ["\n margin: 0;\n font-size: 1.2rem;\n font-weight: 600;\n"]))); var Description = styled__default["default"].p(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n margin: 0;\n font-size: 0.9rem;\n line-height: 1.5;\n color: rgba(255, 255, 255, 0.9);\n"], ["\n margin: 0;\n font-size: 0.9rem;\n line-height: 1.5;\n color: rgba(255, 255, 255, 0.9);\n"]))); var PreferenceSection = styled__default["default"].div(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n"], ["\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n"]))); var PreferenceItem = styled__default["default"].div(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: 0.5rem;\n"], ["\n display: flex;\n align-items: center;\n gap: 0.5rem;\n"]))); var Switch = styled__default["default"].label(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n position: relative;\n display: inline-block;\n width: 48px;\n height: 24px;\n \n input {\n opacity: 0;\n width: 0;\n height: 0;\n \n &:checked + span {\n background-color: ", ";\n }\n \n &:checked + span:before {\n transform: translateX(24px);\n }\n \n &:disabled + span {\n opacity: 0.5;\n cursor: not-allowed;\n }\n }\n \n span {\n position: absolute;\n cursor: pointer;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: #ccc;\n transition: 0.3s;\n border-radius: 24px;\n \n &:before {\n position: absolute;\n content: \"\";\n height: 18px;\n width: 18px;\n left: 3px;\n bottom: 3px;\n background-color: white;\n transition: 0.3s;\n border-radius: 50%;\n }\n }\n"], ["\n position: relative;\n display: inline-block;\n width: 48px;\n height: 24px;\n \n input {\n opacity: 0;\n width: 0;\n height: 0;\n \n &:checked + span {\n background-color: ", ";\n }\n \n &:checked + span:before {\n transform: translateX(24px);\n }\n \n &:disabled + span {\n opacity: 0.5;\n cursor: not-allowed;\n }\n }\n \n span {\n position: absolute;\n cursor: pointer;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: #ccc;\n transition: 0.3s;\n border-radius: 24px;\n \n &:before {\n position: absolute;\n content: \"\";\n height: 18px;\n width: 18px;\n left: 3px;\n bottom: 3px;\n background-color: white;\n transition: 0.3s;\n border-radius: 50%;\n }\n }\n"])), function (props) { return props.$primaryColor; }); var ButtonGroup = styled__default["default"].div(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n display: flex;\n gap: 1rem;\n margin-top: 1rem;\n \n @media (max-width: 768px) {\n flex-direction: column;\n }\n"], ["\n display: flex;\n gap: 1rem;\n margin-top: 1rem;\n \n @media (max-width: 768px) {\n flex-direction: column;\n }\n"]))); var Button = styled__default["default"].button(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 0.9rem;\n \n &.accept-all {\n background: ", ";\n color: black;\n border: none;\n \n &:hover {\n filter: brightness(0.9);\n }\n }\n \n &.accept-selected {\n background: transparent;\n color: ", ";\n border: 1px solid ", ";\n \n &:hover {\n background: ", "1A;\n }\n }\n \n &.decline-all {\n background: transparent;\n color: ", ";\n border: 1px solid ", ";\n \n &:hover {\n background: ", "1A;\n }\n }\n \n @media (max-width: 768px) {\n width: 100%;\n }\n"], ["\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n font-size: 0.9rem;\n \n &.accept-all {\n background: ", ";\n color: black;\n border: none;\n \n &:hover {\n filter: brightness(0.9);\n }\n }\n \n &.accept-selected {\n background: transparent;\n color: ", ";\n border: 1px solid ", ";\n \n &:hover {\n background: ", "1A;\n }\n }\n \n &.decline-all {\n background: transparent;\n color: ", ";\n border: 1px solid ", ";\n \n &:hover {\n background: ", "1A;\n }\n }\n \n @media (max-width: 768px) {\n width: 100%;\n }\n"])), function (props) { return props.$primaryColor; }, function (props) { return props.$textColor; }, function (props) { return props.$primaryColor; }, function (props) { return props.$primaryColor; }, function (props) { return props.$textColor; }, function (props) { return props.$textColor; }, function (props) { return props.$textColor; }); var CookieBanner = function (props) { var _a = __assign(__assign({}, defaultProps), props), primaryColor = _a.primaryColor, textColor = _a.textColor, backgroundColor = _a.backgroundColor, className = _a.className, onPreferencesUpdate = _a.onPreferencesUpdate, titleText = _a.titleText, descriptionText = _a.descriptionText, showDelay = _a.showDelay, gtmContainerId = _a.gtmContainerId; var _b = React.useState(false), show = _b[0], setShow = _b[1]; var _c = React.useState({ essential: true, analytics_storage: false, ad_storage: false, ad_user_data: false, ad_personalization: false }), preferences = _c[0], setPreferences = _c[1]; var updateGoogleConsent = function (prefs) { if (!gtmContainerId) return; window.dataLayer = window.dataLayer || []; window.gtag = window.gtag || function () { window.dataLayer.push(arguments); }; window.gtag('consent', 'update', { 'ad_user_data': prefs.ad_user_data ? 'granted' : 'denied', 'ad_personalization': prefs.ad_personalization ? 'granted' : 'denied', 'ad_storage': prefs.ad_storage ? 'granted' : 'denied', 'analytics_storage': prefs.analytics_storage ? 'granted' : 'denied' }); }; React.useEffect(function () { var checkConsent = function () { try { var savedConsent = localStorage.getItem('cookieConsent'); if (!savedConsent) { setShow(true); if (gtmContainerId) { window.dataLayer = window.dataLayer || []; window.gtag = window.gtag || function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } window.dataLayer.push(arguments); }; window.gtag('consent', 'default', { 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'ad_storage': 'denied', 'analytics_storage': 'denied', 'wait_for_update': 500 }); } } else { var savedPreferences = JSON.parse(savedConsent); setPreferences(savedPreferences); updateGoogleConsent(savedPreferences); } } catch (error) { console.error('localStorage error:', error); setShow(true); } }; if (typeof window !== 'undefined') { setTimeout(checkConsent, showDelay); } }, [showDelay, gtmContainerId]); var handlePreferenceChange = function (key) { setPreferences(function (prev) { var _a; return (__assign(__assign({}, prev), (_a = {}, _a[key] = !prev[key], _a))); }); }; var handleAcceptAll = function () { var allAccepted = { essential: true, analytics_storage: true, ad_storage: true, ad_user_data: true, ad_personalization: true }; setPreferences(allAccepted); localStorage.setItem('cookieConsent', JSON.stringify(allAccepted)); updateGoogleConsent(allAccepted); onPreferencesUpdate(allAccepted); setShow(false); }; var handleAcceptSelected = function () { localStorage.setItem('cookieConsent', JSON.stringify(preferences)); updateGoogleConsent(preferences); onPreferencesUpdate(preferences); setShow(false); }; var handleDeclineAll = function () { var allDeclined = { essential: true, analytics_storage: false, ad_storage: false, ad_user_data: false, ad_personalization: false }; setPreferences(allDeclined); localStorage.setItem('cookieConsent', JSON.stringify(allDeclined)); updateGoogleConsent(allDeclined); onPreferencesUpdate(allDeclined); setShow(false); }; return (React__default["default"].createElement(BannerContainer, { show: show, backgroundColor: backgroundColor, textColor: textColor, className: className, role: "dialog", "aria-modal": "true", "aria-label": "Cookie consent preferences" }, React__default["default"].createElement(Message, null, React__default["default"].createElement(Title, null, titleText), React__default["default"].createElement(Description, null, descriptionText)), React__default["default"].createElement(PreferenceSection, null, React__default["default"].createElement(PreferenceItem, null, React__default["default"].createElement(Switch, { "$primaryColor": primaryColor }, React__default["default"].createElement("input", { type: "checkbox", checked: preferences.essential, disabled: true, "aria-label": "Essential cookies" }), React__default["default"].createElement("span", null)), React__default["default"].createElement("span", null, "Essential Cookies (Required)")), React__default["default"].createElement(PreferenceItem, null, React__default["default"].createElement(Switch, { "$primaryColor": primaryColor }, React__default["default"].createElement("input", { type: "checkbox", checked: preferences.analytics_storage, onChange: function () { return handlePreferenceChange('analytics_storage'); }, "aria-label": "Analytics cookies" }), React__default["default"].createElement("span", null)), React__default["default"].createElement("span", null, "Analytics Cookies")), React__default["default"].createElement(PreferenceItem, null, React__default["default"].createElement(Switch, { "$primaryColor": primaryColor }, React__default["default"].createElement("input", { type: "checkbox", checked: preferences.ad_storage, onChange: function () { return handlePreferenceChange('ad_storage'); }, "aria-label": "Advertising cookies" }), React__default["default"].createElement("span", null)), React__default["default"].createElement("span", null, "Advertising Cookies")), React__default["default"].createElement(PreferenceItem, null, React__default["default"].createElement(Switch, { "$primaryColor": primaryColor }, React__default["default"].createElement("input", { type: "checkbox", checked: preferences.ad_personalization, onChange: function () { return handlePreferenceChange('ad_personalization'); }, "aria-label": "Personalization cookies" }), React__default["default"].createElement("span", null)), React__default["default"].createElement("span", null, "Personalization"))), React__default["default"].createElement(ButtonGroup, null, React__default["default"].createElement(Button, { "$primaryColor": primaryColor, "$textColor": textColor, className: "accept-all", onClick: handleAcceptAll, "aria-label": "Accept all cookies" }, "Accept All"), React__default["default"].createElement(Button, { "$primaryColor": primaryColor, "$textColor": textColor, className: "accept-selected", onClick: handleAcceptSelected, "aria-label": "Accept selected cookies" }, "Accept Selected"), React__default["default"].createElement(Button, { "$primaryColor": primaryColor, "$textColor": textColor, className: "decline-all", onClick: handleDeclineAll, "aria-label": "Decline all cookies" }, "Decline All")))); }; var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9; exports.CookieBanner = CookieBanner; //# sourceMappingURL=index.js.map