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

@vstx/vxcookies

v1.1.8

Published

Cookie consent via init() only (<vx-cookies> web component). Default entry: React as peer dependency. Use @vstx/vxcookies/standalone when the host has no React.

Readme

@vstx/vxcookies

A cookie consent UI and runtime for web applications. It ships as a custom element (<vx-cookies>) backed by React, exposes a single integration surface via init(), and persists choices in a cc_cookie JSON format compatible with CookieConsentHelper (PHP) and similar stacks.


Features

  • One-shot integration — call init() once; the library registers the web component and appends <vx-cookies> to document.body.
  • Two distribution builds — use your app’s React 18+ (smaller, single React instance) or a standalone bundle with embedded React (no React required in the host). Standalone ships as ESM/CJS and as an optional IIFE global (window.VXCookies) for pages without <script type="module">.
  • Locales — German, English, and Spanish (translations.json + AvailableLocales).
  • Themes — dark (default) and light (AvailableThemes).
  • Categories — necessary, functional, analytics with toggles and settings modal.
  • Google tag / Consent Mode — updates gtag('consent', 'update', …) when analytics is allowed.
  • Deferred third-party scripts — scripts tagged with data-cookiecategory run after the user allows that category.
  • Global helper APIwindow.__cookieConsentApi for allowedCategory and reopening settings.
  • Styles — CSS is prepended into the JS bundle at build time (injects a <style data-vxcookies> tag). Separate .css files are also published if you prefer explicit imports.

Installation

npm install @vstx/vxcookies

Peer dependencies (default entry)

The main package entry expects React 18+ and React DOM 18+ in the consuming application (uses react-dom/client).

| Package | Version | |---------------|-----------| | react | >=18.0.0 | | react-dom | >=18.0.0 |

Peers are marked optional in peerDependenciesMeta for standalone-only consumers, but npm may still report ERESOLVE if your tree has an older React (e.g. 16). In that case either:

  • import @vstx/vxcookies/standalone and install with
    npm install @vstx/vxcookies --legacy-peer-deps, or
  • align the host app on React 18+ and use the default entry.

Quick start

React 18+ application (recommended)

import vxcookies from '@vstx/vxcookies';

vxcookies.init({
  locale: vxcookies.AvailableLocales.EN,
  theme: vxcookies.AvailableThemes.DARK,
  platform: {
    name: 'My Product',
    logoUrl: '/assets/logo.svg',
  },
  onFirstAccept: (data) => {
    console.log('Accepted categories:', data.accepted_categories);
  },
  onPreferencesChange: (consent, changedCategories) => {
    console.log('Consent updated', consent, changedCategories);
  },
});

No React (or React < 18)

import vxcookies from '@vstx/vxcookies/standalone';

vxcookies.init({
  /* same options as above */
});

Integración sin bundler (script clásico)

Cuando el HTML principal no usa módulos ES (p. ej. plantillas PHP que solo insertan <script src="…"> en el body), copia dist/standalone/vxcookies.standalone.iife.js a tu estático público (o instala el paquete y sirve node_modules/@vstx/vxcookies/dist/standalone/vxcookies.standalone.iife.js). El fichero es autocontenido (React incluido), minificado en el build de producción, expone window.VXCookies con la misma API que el default export del standalone ESM (init, AvailableLocales, AvailableThemes, CookieCategories, etc.) e inyecta los estilos con data-vxcookies igual que el bundle ESM.

<script src="/ruta/publica/vxcookies.standalone.iife.js"></script>
<script>
  VXCookies.init({
    locale: VXCookies.AvailableLocales.DE,
    platform: { name: '…', logoUrl: '…' },
  });
</script>

ESM (@vstx/vxcookies/standalone) sigue siendo la opción habitual con bundler o con <script type="module"> y URL publicada. IIFE (@vstx/vxcookies/standalone/iife) encaja en hosts legacy sin resolver import desde node_modules.

CommonJS

const vxcookies = require('@vstx/vxcookies');
vxcookies.init({ /* … */ });

Package exports

package.json exports (all paths are relative to the package root):

| Subpath | Description | |-----------------------------|--------------------------------------------------| | @vstx/vxcookies | ESM/CJS external build (peer React 18+) | | @vstx/vxcookies/standalone| ESM/CJS standalone build (bundled React) | | @vstx/vxcookies/standalone/iife | IIFE standalone (window.VXCookies), script clásico | | @vstx/vxcookies/style.css | External build stylesheet | | @vstx/vxcookies/standalone/style.css | Standalone stylesheet |

Artifacts live under dist/external/ and dist/standalone/ in the published tarball (incl. vxcookies.standalone.iife.js).


Public API

The default export is a plain object:

{
  init(options?: InitOptions): { destroy(): void } | undefined,
  // constants (see below)
}

There is no supported public React component export; integration is init() only.

init(options)

Runs when the document is ready. If document.readyState === 'loading', it defers until DOMContentLoaded.

  • Registers the custom element vx-cookies (if not already defined).
  • Creates <vx-cookies>, sets display: contents, mounts the React tree inside a child div, and appends the element to document.body.
  • If a vx-cookies node already exists, logs a warning and returns without duplicating.

Return value: mountWebComponent() returns { destroy() } to remove the host node from the DOM (advanced use).

InitOptions

| Option | Type | Description | |--------|------|-------------| | locale | string | Static locale (de | en | es). Use AvailableLocales.*. | | getLocale | () => string | Dynamic locale; overrides locale when set. | | platform | { name: string, logoUrl: string } | Branding in the banner/modal. | | getPlatform | () => object | Dynamic platform; overrides platform when set. | | theme | string | dark or light (AvailableThemes). | | getTheme | () => string | Dynamic theme. | | breakpoints | { mobile?: number, … } | Merged with defaults (DefaultBreakpoints); drives responsive layout. | | dataProtectionLegalTextGetter | () => string \| Promise<string> | HTML shown in the in-banner data protection panel. Optional — if omitted, the panel stays empty and no promise is rejected. | | onFirstAccept | (data: { accepted_categories: string[] }) => void | Invoked when consent is applied and the analytics category is among the accepted categories (see implementation in VXCookiesContext). | | onPreferencesChange | (consent, changedCategories: string[]) => void | Fired after the user saves settings in the modal if at least one category changed. |

Exported constants

Re-exported on the default object from constants.js:

  • CookieCategoriesNECESSARY, FUNCTIONAL, ANALYTICS (string values match cookie payload).
  • CookieSameSiteAttributesLAX, NONE (internal cookie write helper).
  • AvailableLocalesDE, EN, ES.
  • AvailableThemesDARK, LIGHT.
  • DefaultBreakpointsmobile, tablet, desktop (px).

Architecture (high level)

src/index.js              → default export: { init, …constants }
src/standalone/index.js   → same public API; standalone library entry (bundled React)
src/config.js             → runtime config + init(), DOM guards
src/web-component/        → <vx-cookies> + createRoot mount
src/components/         → VXCookies modal, consent, settings, primitives
src/context/              → VXCookiesProvider, consent state, callbacks
src/cookies.js            → cc_cookie read/write, gtag, deferred scripts
src/hooks/                → useBreakpoint
src/utils.js/             → translations, classNames helpers

vite.config.js                  → dev server (`root`: playground/)
vite/vite.config.external.js    → production lib → dist/external/
vite/vite.config.standalone.js  → production lib → dist/standalone/ (`vxcookies.js`, `vxcookies.cjs`, `vxcookies.standalone.iife.js`)
vite/vite.lib.shared.js         → shared CSS-in-JS inject plugin + loadEnv

The web component uses light DOM (no Shadow DOM) so global or imported CSS applies predictably.


Cookie format & backend compatibility

  • Cookie name: cc_cookie
  • Shape (JSON): includes at least level (string[] of category ids), consent_date, consent_uuid, last_consent_update.
  • Lifetime: 182 days, Path=/, SameSite=Lax, Secure on HTTPS.
  • Domain: the Domain attribute is set to window.location.hostname only when the hostname contains a dot and is not an IPv4 address (e.g. localhost and 192.168.x.x stay host-only cookies, which avoids broken Domain values on IPs).
  • Subdomains: example.com and www.example.com are different hosts; consent cookies are not automatically shared between them unless your deployment consistently uses one canonical host.

Helpers in src/cookies.js (getConsent, setConsent, hasConsent, allowedCategory) are used internally; the same cookie can be read server-side if naming and JSON stay aligned with your PHP/helper expectations.


Google Analytics / gtag

When consent is applied, the library calls gtagConsentUpdate, which runs:

gtag('consent', 'update', {
  ad_storage: granted ? 'granted' : 'denied',
  analytics_storage: granted ? 'granted' : 'denied',
});

granted is true when the analytics category is in the accepted list. Ensure window.gtag exists if you rely on this.


Deferred scripts (data-cookiecategory)

To load a script only after a category is allowed, use a non-executing placeholder so the browser does not run it before consent (use type="text/plain" or another non-JavaScript MIME type, not text/javascript):

<script
  type="text/plain"
  data-cookiecategory="analytics"
  data-src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"
></script>

When the user accepts that category, the library replaces these nodes with real <script type="text/javascript"> elements (similar in spirit to legacy cookieconsent behaviour). Category strings must match CookieCategories values (necessary, functional, analytics).


window.__cookieConsentApi

After the provider mounts, the library assigns:

window.__cookieConsentApi = {
  allowedCategory: (category) => boolean,
  showSettings: () => void,
};

Use this from non-React code to open the settings modal or check permissions. It is removed on unmount.


Styling notes

  • Build plugin (vite/vite.lib.shared.js): extracts the compiled CSS asset and prepends an IIFE that injects it into document.head once (data-vxcookies), so a simple JS import often suffices.
  • CSS modules use camelCase locals for class names in JS (localsConvention: 'camelCase').
  • Optional separate imports: @vstx/vxcookies/style.css or …/standalone/style.css.

Development

git clone https://github.com/Campoint/vxcookies.git
cd vxcookies
npm install
npm run dev      # Vite dev server; root = playground/
npm run build    # vite/vite.config.* → dist/external/ & dist/standalone/ (+ standalone IIFE)
npm run preview  # preview production playground build
  • Library source entry: src/index.js
  • Vite: npm run dev uses vite.config.js with root: playground/. Library production builds use vite/vite.config.external.js (peer React), vite/vite.config.standalone.js (bundled React), and shared vite/vite.lib.shared.js. Optional env: VITE_HOST, VITE_PORT (e.g. in .env at project root).

Playground layout

| Path | Role | |------|------| | playground/index.html | Dev server HTML shell; favicon, <div id="root">, and scripts that load vxcookies | | playground/main.jsx | Recommended Vite entry when enabled in HTML: calls init() then mounts a sample React “host” app | | playground/App.jsx | Dummy host UI (counter, links) — simulates an app that lives next to the cookie banner | | playground/main.css, App.css | Playground-only styles | | playground/assets/ | Images used by init({ platform: { logoUrl } }) (e.g. heidi.png) |

Two ways to run the playground

1. Test the built library (current default in index.html)
index.html uses an inline module that imports ../dist/external/vxcookies.js and style.css. You need a successful npm run build first, or the imports 404. Use this to verify production-like bundles without HMR on src/.

2. Develop the library with HMR (recommended for UI/logic work)
Point the HTML at the Vite-processed entry:

  1. In playground/index.html, comment out the inline <script type="module"> block that imports from dist/.
  2. Uncomment <script type="module" src="./main.jsx"></script>.

Then main.jsx loads the library from ../src/index.js (see useReactComponents below) so edits under src/ hot-reload with the dev server.

main.jsxuseReactComponents flag

const useReactComponents = true;

if (useReactComponents) {
  vxcookies = (await import('../src/index.js')).default;
} else {
  vxcookies = (await import('@vstx/vxcookies')).default;
}
  • useReactComponents === true — uses source (src/index.js): best for changing components, Less, or init behaviour.
  • useReactComponents === false — uses the installed npm package @vstx/vxcookies: smoke-test the same code consumers get (after npm link / local file: install).

Adjust init({ ... }) in main.jsx (locale, theme, platform, URLs, callbacks) to match what you want to test. The cookie UI is not rendered inside <div id="root">init() appends <vx-cookies> to document.body; App only represents the rest of the page.

After changing styles or library code

  • HMR path: save files under src/ or playground/; Vite refreshes as usual.
  • Dist path: run npm run build again to refresh dist/external and dist/standalone before testing the inline-dist HTML workflow or publishing.

Browser support

Requires APIs used by the bundle: custom elements, JSON/localStorage-free cookie I/O, and modern React 18 client APIs in whichever bundle you load. The default and standalone ESM entries assume the host can load ES modules; the standalone IIFE does not require type="module" in the page. For very old browsers, transpile or polyfill at the application level.


Limitations & caveats

  • init() is browser-only — guard any SSR imports so document is not accessed on the server, or load the library only on the client.
  • Single instance — one <vx-cookies> per page is assumed; duplicate init() calls are ignored with a console warning.
  • Multiple init() before DOMContentLoaded — if you call init() more than once while the document is still loading, each call registers a DOMContentLoaded handler; the first run mounts <vx-cookies>, and later runs may only log the “already initialized” warning without applying newer options. Call init() once with the final options (or wait until DOMContentLoaded yourself).
  • onFirstAccept naming — it runs when consent is applied with analytics included, not on every first acceptance of any category and not strictly “first visit only”; use hasConsent() / cookie inspection for “first visit” logic if needed.
  • Standalone vs host React — importing @vstx/vxcookies/standalone inside a React app loads a second React runtime (larger bundle, avoid unless you mean to).
  • Vanilla <script type="module"> + /node_modules/... URLs — the browser must be able to HTTP-fetch the module path; many setups do not expose node_modules as static files—prefer a bundler, copy vxcookies.js to a public URL, or use the standalone IIFE with a normal <script src>.

License

MIT © Campoint / VSTX

Links


Made with ❤️ by CMPNT for VSTX / Baukasten.