npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@meui-creative/cookies

v6.0.1

Published

GDPR-compliant cookie consent management for React with centralized Payload CMS configuration

Readme

@meui-creative/cookies

GDPR-compliant cookie consent management for React and Next.js with 5 preset layouts, script blocking, built-in integrations, and full Google Consent Mode V2 support.

Features

  • 5 Preset Layouts — From minimal bars to full sidebars
  • Fully Customizable — Override colors, position, spacing, typography, animations
  • Multi-language — Built-in translations (EN, CS, DE)
  • Google Consent Mode V2 — Automatic setup with all required parameters
  • Script Blocking — Blocks scripts/iframes until consent via data-cookie-category
  • Built-in Integrations — Google Analytics, GTM, Facebook Pixel, Hotjar, Clarity
  • Remote Config — Optional Payload CMS plugin for centralized management
  • Headless Mode — Use the hook only, build your own UI (zero UI dependencies)
  • TypeScript — Full type safety
  • SSR-safe — Portal-based rendering, "use client" directive for Next.js App Router
  • GDPR Compliant — Strict mode, consent versioning, audit-ready export

Installation

npm install @meui-creative/cookies framer-motion lucide-react

framer-motion and lucide-react are only needed if using the built-in component/presets. For headless usage (hook only), install just the main package.

Entry Points

| Import | What you get | |--------|-------------| | @meui-creative/cookies | Full library: CookieConsent component + useCookieConsent hook + API | | @meui-creative/cookies/headless | Hook + API only (no framer-motion/lucide-react dependency) | | @meui-creative/cookies/presets | Individual preset components: BannerDefault, BannerMinimal, BannerCard, BannerSidebar, BannerMeui | | @meui-creative/cookies/styles | CSS stylesheet | | @meui-creative/cookies/payload | Payload CMS plugin |


Quick Start

import { CookieConsent } from '@meui-creative/cookies'
import '@meui-creative/cookies/styles'

export default function Layout({ children }) {
  return (
    <>
      {children}
      <CookieConsent
        preset="default"
        language="en"
        version="1.0.0"
        mode="strict"
        links={{
          privacyPolicy: '/privacy',
          cookiePolicy: '/cookies',
        }}
        onAccept={(categories) => console.log('Accepted:', categories)}
        onDecline={() => console.log('Declined')}
      />
    </>
  )
}

The component renders via a React Portal, checks localStorage for existing consent on mount, shows/hides the banner automatically, and handles script blocking + Google Consent Mode out of the box.


Integrations

Pass integration IDs and the library loads them automatically when the user consents to the mapped category:

<CookieConsent
  integrations={{
    googleAnalytics: 'G-XXXXXXXXXX',    // category: analytics
    googleTagManager: 'GTM-XXXXXXX',    // category: analytics
    facebookPixel: '123456789',          // category: marketing
    hotjar: '1234567',                   // category: analytics
    clarity: 'xxxxxxxxxx',              // category: analytics
  }}
/>

Important: Remove existing Google tags

If you have Google Analytics or GTM script tags in your <head>, remove them and use the integrations prop instead. The library ensures the correct order: consent defaults (denied) -> load tag -> config -> consent update.

// Don't do this — bypasses consent
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXX"></script>

// Do this instead
<CookieConsent integrations={{ googleAnalytics: 'G-XXX' }} />

Script & Iframe Blocking

For scripts not covered by built-in integrations, mark them with type="text/plain" and data-cookie-category:

<!-- Only runs when "analytics" category is consented -->
<script type="text/plain" data-cookie-category="analytics" src="https://example.com/analytics.js"></script>

<!-- Inline scripts work too -->
<script type="text/plain" data-cookie-category="marketing">
  console.log('Runs only after marketing consent');
</script>

<!-- Iframes — src is auto-stripped until consent -->
<iframe data-cookie-category="marketing" src="https://www.youtube.com/embed/VIDEO_ID"></iframe>

The library also uses a MutationObserver to handle dynamically added scripts/iframes.

Categories: strictly-necessary (always on), functional, analytics, marketing


Google Consent Mode V2

The library automatically manages Google Consent Mode V2. No extra configuration needed.

On page load: all signals set to denied. On consent: signals updated to granted for consented categories.

| Category | Consent Mode signals | |----------|---------------------| | strictly-necessary | functionality_storage | | functional | functionality_storage, personalization_storage | | analytics | analytics_storage | | marketing | ad_storage, ad_user_data, ad_personalization | | (always) | security_storage |

Optional configuration

<CookieConsent
  consentModeOptions={{
    region: ['EU', 'US-CA'],     // Geographic regions
    urlPassthrough: true,         // Pass ad click info through URLs
    adsDataRedaction: true,       // Redact ads data when consent denied
  }}
/>

Verify in GTM Preview

  1. Open GTM Preview Mode
  2. Click the "Consent" tab
  3. Before accept: all signals show Denied
  4. After accept: consented signals show Granted
// Check in browser console
window.dataLayer.filter(e => e[0] === 'consent')

Design Presets

Choose from 5 professionally designed layouts, each with unique UX:

default - Classic Card

Color: Blue (#3b82f6) | Position: Bottom-left

Clean, professional design with large cookie icon. Perfect for corporate websites.

<CookieConsent />

meui - Compact with Inline Settings

Color: Green (#4A6953) | Position: Bottom-left

Original Meui design with expandable settings directly in banner. Saves modal interactions.

<CookieConsent preset="meui" />

minimal - Bottom Bar

Color: Black (#000) | Position: Full-width bottom

Horizontal bar spanning full width. Non-intrusive, great for blogs and content sites.

<CookieConsent preset="minimal" />

card - Accent Header

Color: Violet (#8b5cf6) | Position: Bottom-right

Modern card with colored header stripe and shield icon. Bold and eye-catching.

<CookieConsent preset="card" />

sidebar - Full-Height Panel

Color: Emerald (#10b981) | Position: Right sidebar

Full-height sidebar with detailed information and trust indicators. Best for complex consent needs.

<CookieConsent preset="sidebar" />

Customization

Every preset can be customized. Override color, position, language, or any style property:

Change Color

<CookieConsent
  preset="default"
  accentColor="#ec4899" // Pink
/>

Change Position

<CookieConsent
  preset="card"
  style={{
    position: 'top-center', // Move to top
  }}
/>

Change Language

<CookieConsent
  preset="meui"
  language="cs" // Czech
/>

Multiple Overrides

<CookieConsent
  preset="minimal"
  accentColor="#f97316"
  language="de"
  style={{
    position: 'top-center',
    animation: {
      direction: 'down',
      duration: 0.5,
    },
  }}
/>

Full Style Override

<CookieConsent
  preset="default"
  accentColor="#ff6600"
  borderRadius="sharp"
  style={{
    position: 'top-right',
    maxWidth: 'lg',              // 'sm' | 'md' | 'lg' | 'xl' or custom string
    spacing: 'comfortable',      // 'compact' | 'normal' | 'comfortable'
    background: '#1a1a1a',
    shadow: '2xl',               // 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
    border: { width: '2', color: '#333' },
    fontSize: { heading: 'lg', body: 'sm' },
    button: { shape: 'pill', size: 'lg' },
    modal: { shadow: 'xl' },
    animation: { direction: 'right', duration: 0.4, enabled: true },
  }}
/>

Position Options

All presets support 6 positions:

  • bottom-left | bottom-center | bottom-right
  • top-left | top-center | top-right

All Configuration Options

<CookieConsent
  // Design
  preset="default"             // 'default' | 'meui' | 'minimal' | 'card' | 'sidebar'
  accentColor="#3b82f6"        // Any CSS color
  borderRadius="rounded"       // 'rounded' | 'sharp'
  style={{ ... }}              // See Full Style Override above

  // Content & Language
  language="en"                // 'en' | 'cs' | 'de'
  descriptionMode="short"     // 'short' | 'long'

  // Behavior
  mode="strict"                // 'strict' (closing = decline) | 'soft' (closing = nothing)
  showSettingsButton={true}    // Show settings gear button in banner
  closeButton={true}           // Show X close button
  showRejectLink={true}        // Show reject all link
  version="1.0.0"             // Bump to force re-consent
  ttl={365}                    // Consent expiry in days
  domain=".example.com"       // Cookie domain for subdomain sharing

  // Legal Links
  links={{
    privacyPolicy: '/privacy',
    cookiePolicy: '/cookies',
  }}

  // Custom Categories (replaces defaults entirely)
  customCategories={[
    { id: 'essential', label: 'Essential', description: '...', required: true, enabled: true },
    { id: 'analytics', label: 'Analytics', description: '...', required: false, enabled: false },
  ]}

  // Integrations
  integrations={{
    googleAnalytics: 'G-XXXXXXXXXX',
    googleTagManager: 'GTM-XXXXXXX',
    facebookPixel: '123456789',
    hotjar: '1234567',
    clarity: 'xxxxxxxxxx',
  }}

  // Google Consent Mode V2
  consentModeOptions={{
    region: ['EU'],
    urlPassthrough: true,
    adsDataRedaction: true,
  }}

  // Remote Config (Payload CMS)
  apiUrl="https://your-cms.com/api/cookie-config"

  // Callbacks
  onAccept={(choices) => console.log('Accepted:', choices)}
  onDecline={() => console.log('Declined')}
  onChange={(choices) => console.log('Changed:', choices)}
  onReady={() => console.log('Consent loaded from storage')}
  onBlock={(src) => console.log('Script unblocked:', src)}
  onVersionChange={(prev) => console.log('Version changed from:', prev)}

  // Debug
  debug={false}
/>

Headless Mode

Import from @meui-creative/cookies/headless to use the hook without any UI dependencies:

import { useCookieConsent } from '@meui-creative/cookies/headless'

function CustomCookieBanner() {
  const {
    consent,        // { 'strictly-necessary': true, analytics: false, ... }
    hasConsent,     // Has the user made any choice?
    isReady,        // Initialization complete?
    categories,     // CategoryDefinition[]
    acceptAll,
    declineAll,
    setConsent,     // Granular: setConsent({ analytics: true, marketing: false })
    revokeConsent,
    exportConsent,
    showSettings,   // Dispatches event to open settings modal
  } = useCookieConsent({
    version: '1.0.0',
    language: 'en',
    integrations: { googleAnalytics: 'G-XXXXXXXXXX' },
  })

  if (!isReady || hasConsent) return null

  return (
    <div className="my-custom-banner">
      <h2>We use cookies</h2>
      <button onClick={acceptAll}>Accept All</button>
      <button onClick={declineAll}>Decline</button>
    </div>
  )
}

The hook handles all core logic — storage, script blocking, integrations, Google Consent Mode — you just provide the UI.


Programmatic API

import { showCookieSettings, revokeConsent, exportConsent } from '@meui-creative/cookies'

// Open settings modal from anywhere (e.g., footer link)
showCookieSettings()

// Revoke all consent
revokeConsent()

// Export consent record for GDPR data subject requests
const record = exportConsent()
// { version, timestamp, choices, userAgent, language, consentMethod, sourceUrl }

"Manage cookies" footer link

import { showCookieSettings } from '@meui-creative/cookies'

function Footer() {
  return <button onClick={showCookieSettings}>Cookie Settings</button>
}

Version Management

Set version on the component. When you bump it, all users are prompted to re-consent:

<CookieConsent version="2.0.0" />

Bump the version when you:

  • Add or remove cookie categories
  • Add a new integration that requires consent
  • Change what data a category covers
  • Need to comply with updated regulations

Consent also expires automatically after ttl days (default: 365).


Events

The library dispatches DOM events on window for integration with non-React code:

window.addEventListener('meui:consent:given', (e) => {
  console.log('Consent given:', e.detail.consent)
})

window.addEventListener('meui:consent:revoked', () => {
  console.log('Consent revoked')
})

window.addEventListener('meui:consent:version-changed', (e) => {
  console.log('Re-consent needed, previous version:', e.detail.previousVersion)
})

Events: meui:consent:given, meui:consent:revoked, meui:consent:changed, meui:consent:version-changed, meui:settings:opened


Remote Configuration (Payload CMS)

Manage consent texts and categories through a Payload CMS admin panel instead of hardcoding them.

1. Install plugin

// payload.config.ts
import { cookieConsentPlugin } from '@meui-creative/cookies/payload'

export default buildConfig({
  plugins: [
    cookieConsentPlugin({
      enabled: true,
      defaultVersion: '1.0.0',
    }),
  ],
})

This adds a cookie-config collection (version, texts in en/cs/de, categories, legal links) and a public GET /api/cookie-config endpoint.

2. Use in frontend

<CookieConsent
  preset="default"
  apiUrl="https://your-cms.com/api/cookie-config"
/>

The component fetches the remote config (cached for 24h with background refresh), using it for texts and categories. Styling remains controlled locally via props.


Storage

Consent is stored in two places:

  • localStorage (meui_cookie_consent) — Full record: version, timestamp, choices, userAgent, language, consentMethod, sourceUrl
  • Cookie (meui_cookie_consent) — Simplified comma-separated list of consented category IDs (for server-side reading)

Use exportConsent() to retrieve the full record for GDPR Article 7(1) compliance.


License

MIT