@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +97 -70
- package/README.md +21 -17
- package/SKILL.md +34 -0
- package/dist/aggregate-components.js +1 -1
- package/dist/chunk-warming.js +1 -1
- package/dist/component-hooks/use-headless-consent-ui.js +1 -1
- package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
- package/dist/component-hooks/use-panel-trigger.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -0
- package/dist/components/consent-gate/consent-gate.js +2 -0
- package/dist/components/consent-gate/frame.js +2 -0
- package/dist/components/consent-gate/index.js +2 -0
- package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
- package/dist/components/iab-panel/atoms/card.js +1 -1
- package/dist/components/iab-panel/atoms/feature-item.js +2 -0
- package/dist/components/iab-panel/atoms/header.js +1 -1
- package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
- package/dist/components/iab-panel/atoms/root.js +1 -1
- package/dist/components/iab-panel/atoms/stack-item.js +1 -1
- package/dist/components/iab-panel/atoms/vendor-list.js +1 -1
- package/dist/components/iab-panel/hooks/use-gvl-data.js +1 -1
- package/dist/components/iab-panel/iab-panel.js +1 -1
- package/dist/components/iab-panel/index.js +1 -1
- package/dist/components/iab-prompt/atoms/overlay.js +1 -1
- package/dist/components/iab-prompt/atoms/root.js +1 -1
- package/dist/components/iab-prompt/iab-prompt.js +1 -1
- package/dist/components/panel/atoms/card.js +1 -1
- package/dist/components/panel/atoms/overlay.js +1 -1
- package/dist/components/panel/atoms/root.js +1 -1
- package/dist/components/panel/panel.js +1 -1
- package/dist/components/panel-trigger/atoms/button.js +1 -1
- package/dist/components/panel-trigger/atoms/icon.js +1 -1
- package/dist/components/panel-trigger/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
- package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
- package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
- package/dist/components/panel-trigger/panel-trigger.js +1 -1
- package/dist/components/panel-trigger/toolbar-loader.js +2 -0
- package/dist/components/preferences/atoms/accordion.js +1 -1
- package/dist/components/preferences/atoms/root.js +1 -1
- package/dist/components/preferences/atoms/vendor-list.js +1 -0
- package/dist/components/preferences/index.js +1 -1
- package/dist/components/prompt/atoms/early-tap-script.js +2 -0
- package/dist/components/prompt/atoms/overlay.js +1 -1
- package/dist/components/prompt/atoms/root.js +1 -1
- package/dist/components/prompt/components.js +1 -1
- package/dist/components/prompt/policy-actions.js +1 -1
- package/dist/components/prompt/prompt.js +1 -1
- package/dist/components/shared/dialog-sheets.js +1 -0
- package/dist/components/shared/first-paint-sheets.js +1 -0
- package/dist/components/shared/iab-dialog-sheets.js +1 -0
- package/dist/components/shared/iab-first-paint-sheets.js +1 -0
- package/dist/components/shared/libs/compose-refs.js +1 -0
- package/dist/components/shared/libs/slot.js +1 -1
- package/dist/components/shared/primitives/button.js +1 -1
- package/dist/components/shared/primitives/legal-links/index.js +1 -1
- package/dist/components/shared/streamed-surface.js +2 -0
- package/dist/components/shared/surface-styles.js +2 -0
- package/dist/components/shared/ui/dialog/dialog.js +1 -1
- package/dist/components/shared/ui/icon.js +1 -1
- package/dist/components/shared/ui/logo.js +1 -1
- package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
- package/dist/consent-gate.js +2 -0
- package/dist/consent-theme.js +1 -0
- package/dist/context/consent-tracking-context.js +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context.js +1 -1
- package/dist/devtools-launcher.js +2 -0
- package/dist/devtools.js +1 -1
- package/dist/draft-context.js +2 -0
- package/dist/draft.js +1 -1
- package/dist/external-iab-context.js +1 -1
- package/dist/gpp.js +2 -0
- package/dist/headless.js +1 -1
- package/dist/hooks/use-color-scheme.js +1 -1
- package/dist/hooks/use-committed-ref.js +2 -0
- package/dist/hooks/use-focus-trap.js +1 -1
- package/dist/hooks/use-headless-iab-consent-ui.js +1 -1
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/hooks/use-late-entry.js +2 -0
- package/dist/hooks.js +1 -1
- package/dist/iab/styles.tw3.css +5 -45
- package/dist/iab-context.js +1 -1
- package/dist/iab-dialog-deferred.js +2 -0
- package/dist/iab.js +1 -1
- package/dist/index-parts/consent-banner.js +1 -0
- package/dist/index-parts/consent-dialog-link.js +1 -0
- package/dist/index-parts/consent-dialog-trigger.js +1 -0
- package/dist/index-parts/consent-dialog.js +1 -0
- package/dist/index-parts/consent-gate.js +1 -0
- package/dist/index-parts/core.js +1 -0
- package/dist/index-parts/draft.js +1 -0
- package/dist/index-parts/frame.js +1 -0
- package/dist/index-parts/hooks.js +1 -0
- package/dist/index-parts/hosted.js +1 -0
- package/dist/index-parts/module-hooks.js +1 -0
- package/dist/index-parts/offline.js +1 -0
- package/dist/index-parts/presets.js +1 -0
- package/dist/index-parts/provider.js +1 -0
- package/dist/index-parts/theme.js +1 -0
- package/dist/index-parts/translations.js +1 -0
- package/dist/index.js +1 -1
- package/dist/kernel-selector.js +1 -0
- package/dist/modes.js +1 -0
- package/dist/module-hooks/iframe-blocker.js +1 -1
- package/dist/module-hooks/network-blocker.js +1 -1
- package/dist/module-hooks/network-hold.js +2 -0
- package/dist/module-hooks/persistence.js +1 -1
- package/dist/panel-link.js +1 -1
- package/dist/panel-trigger.js +1 -1
- package/dist/panel.js +1 -1
- package/dist/postcss-tailwind3.js +1 -0
- package/dist/preferences.js +1 -2
- package/dist/provider.js +1 -1
- package/dist/server/fetch-ssr-data.js +1 -1
- package/dist/server/headers.js +1 -1
- package/dist/server/normalize-url.js +1 -1
- package/dist/styles.tw3.css +33 -51
- package/dist/transports/hosted.js +1 -0
- package/dist/transports/manifest.js +1 -0
- package/dist/transports/offline.js +1 -1
- package/dist/utils/deferred-module.js +2 -0
- package/dist/utils/merge-slot-props.js +1 -1
- package/dist/utils/theme-utils.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/aggregate-components.d.ts +2 -2
- package/dist-types/chunk-warming.d.ts +42 -8
- package/dist-types/component-hooks/use-headless-consent-ui.d.ts +5 -5
- package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +2 -2
- package/dist-types/components/consent-gate/atoms.d.ts +11 -0
- package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
- package/dist-types/components/consent-gate/frame.d.ts +19 -0
- package/dist-types/components/consent-gate/index.d.ts +25 -0
- package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
- package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
- package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
- package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +5 -2
- package/dist-types/components/iab-panel/atoms/stack-item.d.ts +7 -2
- package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
- package/dist-types/components/iab-panel/iab-panel.d.ts +3 -3
- package/dist-types/components/iab-panel/index.d.ts +29 -26
- package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +3 -3
- package/dist-types/components/iab-prompt/index.d.ts +19 -19
- package/dist-types/components/panel/atoms/card.d.ts +5 -4
- package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
- package/dist-types/components/panel/index.d.ts +8 -8
- package/dist-types/components/panel/panel.d.ts +3 -3
- package/dist-types/components/panel-link/index.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
- package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
- package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +25 -0
- package/dist-types/components/panel-trigger/index.d.ts +4 -4
- package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
- package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -17
- package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
- package/dist-types/components/panel-trigger/types.d.ts +1 -1
- package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
- package/dist-types/components/preferences/atoms/button.d.ts +1 -1
- package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
- package/dist-types/components/preferences/atoms/root.d.ts +1 -1
- package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
- package/dist-types/components/preferences/index.d.ts +14 -12
- package/dist-types/components/preferences/policy-actions.d.ts +2 -2
- package/dist-types/components/preferences/preferences.d.ts +1 -1
- package/dist-types/components/preferences/types.d.ts +1 -1
- package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
- package/dist-types/components/prompt/atoms/root.d.ts +4 -0
- package/dist-types/components/prompt/components.d.ts +9 -3
- package/dist-types/components/prompt/index.d.ts +12 -12
- package/dist-types/components/prompt/policy-actions.d.ts +2 -2
- package/dist-types/components/prompt/prompt.d.ts +5 -1
- package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
- package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
- package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
- package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
- package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
- package/dist-types/components/shared/policy-actions.d.ts +2 -2
- package/dist-types/components/shared/primitives/box.d.ts +1 -1
- package/dist-types/components/shared/primitives/button.d.ts +2 -2
- package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
- package/dist-types/components/shared/streamed-surface.d.ts +23 -0
- package/dist-types/components/shared/surface-styles.d.ts +60 -0
- package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
- package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
- package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
- package/dist-types/components/shared/ui/branding.d.ts +1 -1
- package/dist-types/components/shared/ui/button/button.d.ts +1 -1
- package/dist-types/components/shared/ui/button/index.d.ts +2 -2
- package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
- package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
- package/dist-types/components/shared/ui/icon.d.ts +2 -1
- package/dist-types/components/shared/ui/logo.d.ts +0 -10
- package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
- package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +13 -0
- package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
- package/dist-types/components/shared/ui/switch/switch.d.ts +1 -1
- package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
- package/dist-types/consent-gate.d.ts +1 -0
- package/dist-types/consent-theme.d.ts +38 -0
- package/dist-types/context/consent-tracking-context.d.ts +10 -0
- package/dist-types/context/index.d.ts +3 -3
- package/dist-types/context/theme-context.d.ts +3 -3
- package/dist-types/context.d.ts +25 -1
- package/dist-types/devtools-launcher.d.ts +29 -0
- package/dist-types/devtools.d.ts +13 -2
- package/dist-types/draft-context.d.ts +31 -0
- package/dist-types/draft.d.ts +81 -9
- package/dist-types/gpp.d.ts +27 -0
- package/dist-types/headless.d.ts +6 -7
- package/dist-types/hooks/use-committed-ref.d.ts +24 -0
- package/dist-types/hooks/use-focus-trap.d.ts +3 -1
- package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
- package/dist-types/hooks/use-iab-manager.d.ts +5 -5
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/hooks/use-late-entry.d.ts +14 -0
- package/dist-types/hooks/use-theme.d.ts +1 -1
- package/dist-types/hooks.d.ts +106 -11
- package/dist-types/iab-dialog-deferred.d.ts +36 -0
- package/dist-types/iab.d.ts +8 -7
- package/dist-types/index-parts/consent-banner.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
- package/dist-types/index-parts/consent-dialog.d.ts +7 -0
- package/dist-types/index-parts/consent-gate.d.ts +7 -0
- package/dist-types/index-parts/core.d.ts +7 -0
- package/dist-types/index-parts/draft.d.ts +7 -0
- package/dist-types/index-parts/frame.d.ts +7 -0
- package/dist-types/index-parts/hooks.d.ts +7 -0
- package/dist-types/index-parts/hosted.d.ts +7 -0
- package/dist-types/index-parts/module-hooks.d.ts +7 -0
- package/dist-types/index-parts/offline.d.ts +7 -0
- package/dist-types/index-parts/presets.d.ts +7 -0
- package/dist-types/index-parts/provider.d.ts +7 -0
- package/dist-types/index-parts/theme.d.ts +8 -0
- package/dist-types/index-parts/translations.d.ts +7 -0
- package/dist-types/index.d.ts +32 -28
- package/dist-types/kernel-selector.d.ts +68 -0
- package/dist-types/modes.d.ts +26 -0
- package/dist-types/module-hooks/iframe-blocker.d.ts +33 -1
- package/dist-types/module-hooks/network-blocker.d.ts +23 -0
- package/dist-types/module-hooks/network-hold.d.ts +47 -0
- package/dist-types/module-hooks.d.ts +4 -4
- package/dist-types/panel-link.d.ts +1 -1
- package/dist-types/panel-trigger.d.ts +1 -1
- package/dist-types/panel.d.ts +13 -1
- package/dist-types/postcss-tailwind3.d.ts +21 -0
- package/dist-types/preferences.d.ts +12 -1
- package/dist-types/primitives/accordion.d.ts +1 -1
- package/dist-types/primitives/button.d.ts +1 -1
- package/dist-types/primitives/collapsible.d.ts +1 -1
- package/dist-types/primitives/dialog.d.ts +1 -1
- package/dist-types/primitives/preference-item.d.ts +1 -1
- package/dist-types/primitives/switch.d.ts +1 -1
- package/dist-types/primitives/tabs.d.ts +1 -1
- package/dist-types/primitives.d.ts +7 -7
- package/dist-types/prompt.d.ts +1 -1
- package/dist-types/provider.d.ts +169 -28
- package/dist-types/server/fetch-ssr-data.d.ts +1 -1
- package/dist-types/server/headers.d.ts +14 -4
- package/dist-types/server/index.d.ts +5 -5
- package/dist-types/server/normalize-url.d.ts +14 -7
- package/dist-types/server/types.d.ts +12 -1
- package/dist-types/theme-provider.d.ts +2 -2
- package/dist-types/transports/hosted.d.ts +36 -0
- package/dist-types/transports/manifest.d.ts +48 -0
- package/dist-types/transports/offline.d.ts +7 -16
- package/dist-types/types/index.d.ts +3 -3
- package/dist-types/types/manager.d.ts +1 -1
- package/dist-types/types/theme/index.d.ts +1 -1
- package/dist-types/ui-config-context.d.ts +14 -2
- package/dist-types/utils/deferred-module.d.ts +13 -0
- package/dist-types/utils/index.d.ts +4 -4
- package/dist-types/utils/merge-slot-props.d.ts +17 -3
- package/dist-types/utils/merge-styles.d.ts +1 -1
- package/dist-types/utils/theme-utils.d.ts +18 -3
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +97 -70
- package/docs/assets/v3/bottom-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/brand-preferences.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/headless-bar-html.png +0 -0
- package/docs/assets/v3/headless-bar-mobile.png +0 -0
- package/docs/assets/v3/headless-bar.png +0 -0
- package/docs/assets/v3/slim-bar.png +0 -0
- package/docs/concepts/choose-your-setup.md +141 -0
- package/docs/concepts/consent-categories.md +84 -0
- package/docs/concepts/consent-state.md +421 -0
- package/docs/concepts/data-fetching.md +284 -0
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/concepts/modes.md +281 -0
- package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +8 -60
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +128 -0
- package/docs/customization/overview.md +68 -33
- package/docs/customization/recipes.md +838 -47
- package/docs/customization/slots.md +217 -35
- package/docs/customization/stylesheets.md +248 -0
- package/docs/customization/tailwind.md +863 -0
- package/docs/customization/tokens.md +167 -36
- package/docs/customization/translations.md +87 -3
- package/docs/frameworks/react/callbacks.md +118 -0
- package/docs/frameworks/react/clear-on-revocation.md +106 -0
- package/docs/frameworks/react/components/consent-banner.md +48 -27
- package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
- package/docs/frameworks/react/components/consent-dialog-trigger.md +86 -76
- package/docs/frameworks/react/components/consent-dialog.md +111 -58
- package/docs/frameworks/react/components/{frame.md → consent-gate.md} +70 -49
- package/docs/frameworks/react/components/consent-provider.md +143 -0
- package/docs/frameworks/react/components/consent-widget.md +69 -24
- package/docs/frameworks/react/components/dev-tools.md +76 -85
- package/docs/frameworks/react/components.md +113 -0
- package/docs/frameworks/react/compose.md +354 -0
- package/docs/frameworks/react/content-security-policy.md +149 -0
- package/docs/frameworks/react/customize.md +258 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/gpp.md +163 -0
- package/docs/frameworks/react/headless.md +4 -4
- package/docs/frameworks/react/hooks.md +70 -0
- package/docs/frameworks/react/iab.md +278 -0
- package/docs/frameworks/react/network-blocker.md +140 -0
- package/docs/frameworks/react/quickstart.md +171 -107
- package/docs/frameworks/react/rendering.md +285 -0
- package/docs/frameworks/react/scripts.md +114 -0
- package/docs/frameworks/react/translations.md +155 -0
- package/docs/frameworks/react/troubleshooting.md +189 -61
- package/docs/frameworks/react/upgrade-v3.md +652 -0
- package/docs/frameworks/react/vendor-consent.md +188 -0
- package/docs/guides/banner-experiments.md +688 -0
- package/docs/guides/troubleshooting.md +192 -54
- package/docs/guides/verify-consent.md +96 -49
- package/docs/integrations/adobe-analytics.md +177 -183
- package/docs/integrations/ahrefs-analytics.md +162 -178
- package/docs/integrations/amplitude.md +172 -180
- package/docs/integrations/building-integrations.md +137 -33
- package/docs/integrations/clearbit.md +164 -178
- package/docs/integrations/cloudflare-web-analytics.md +166 -180
- package/docs/integrations/cloudflare-zaraz.md +333 -0
- package/docs/integrations/crisp.md +174 -182
- package/docs/integrations/databuddy.md +167 -197
- package/docs/integrations/fathom-analytics.md +168 -180
- package/docs/integrations/front-chat.md +308 -0
- package/docs/integrations/google-maps.md +142 -108
- package/docs/integrations/google-tag-manager.md +258 -185
- package/docs/integrations/google-tag.md +226 -182
- package/docs/integrations/heap.md +173 -179
- package/docs/integrations/hightouch.md +171 -181
- package/docs/integrations/hotjar.md +169 -179
- package/docs/integrations/intercom.md +193 -177
- package/docs/integrations/klaviyo.md +473 -0
- package/docs/integrations/linkedin-insights.md +184 -174
- package/docs/integrations/logrocket.md +170 -180
- package/docs/integrations/matomo-analytics.md +198 -202
- package/docs/integrations/meta-pixel.md +198 -174
- package/docs/integrations/microsoft-clarity.md +173 -179
- package/docs/integrations/microsoft-uet.md +158 -178
- package/docs/integrations/mixpanel-analytics.md +165 -184
- package/docs/integrations/one-dollar-stats.md +292 -0
- package/docs/integrations/openai-pixel.md +214 -325
- package/docs/integrations/overview.md +153 -83
- package/docs/integrations/pinterest-tag.md +315 -0
- package/docs/integrations/pirsch.md +179 -183
- package/docs/integrations/plausible-analytics.md +182 -182
- package/docs/integrations/posthog.md +323 -264
- package/docs/integrations/promptwatch.md +164 -178
- package/docs/integrations/reddit-pixel.md +195 -181
- package/docs/integrations/rudderstack.md +211 -210
- package/docs/integrations/rybbit-analytics.md +181 -184
- package/docs/integrations/segment.md +192 -178
- package/docs/integrations/sentry.md +402 -0
- package/docs/integrations/snapchat-pixel.md +196 -180
- package/docs/integrations/tiktok-pixel.md +181 -174
- package/docs/integrations/umami-analytics.md +173 -182
- package/docs/integrations/vercel-analytics.md +176 -181
- package/docs/integrations/vercel-speed-insights.md +306 -0
- package/docs/integrations/x-pixel.md +186 -174
- package/docs/integrations/youtube.md +150 -111
- package/package.json +48 -17
- package/dist/component-hooks/use-manager.js +0 -2
- package/dist/components/frame/atoms.js +0 -1
- package/dist/components/frame/frame.js +0 -2
- package/dist/components/frame/index.js +0 -2
- package/dist/frame.js +0 -2
- package/dist/ui-save.js +0 -1
- package/dist-types/component-hooks/use-manager.d.ts +0 -40
- package/dist-types/components/frame/atoms.d.ts +0 -11
- package/dist-types/components/frame/frame.d.ts +0 -2
- package/dist-types/components/frame/index.d.ts +0 -24
- package/dist-types/frame.d.ts +0 -1
- package/dist-types/ui-save.d.ts +0 -5
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/frameworks/react/components/consent-manager-provider.md +0 -71
- package/docs/frameworks/react/concepts/consent-categories.md +0 -33
- package/docs/frameworks/react/hooks/use-consent-manager/overview.md +0 -58
- package/docs/frameworks/react/iab/overview.md +0 -53
- package/docs/frameworks/react/script-loader.md +0 -63
- package/docs/frameworks/react/styling/overview.md +0 -217
- package/docs/guides/consent-state.md +0 -60
- package/docs/guides/data-fetching.md +0 -163
- package/docs/guides/deployment-modes.md +0 -63
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/upgrade-v3.md +0 -334
- package/readme.json +0 -48
- package/src/iab/styles.css +0 -11
- package/src/styles.css +0 -10
- /package/dist/components/{frame → consent-gate}/types.js +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Customize
|
|
3
|
+
description: Change the colors, fonts, layout, button styles and copy of the
|
|
4
|
+
c15t banner and dialog in a React app with theme tokens, provider options and
|
|
5
|
+
slots, and load the stylesheet yourself when you need to.
|
|
6
|
+
group: frameworks
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Pick the right tool
|
|
10
|
+
|
|
11
|
+
| Change | Use |
|
|
12
|
+
| ------------------------------------ | ------------------------------------------------------------------- |
|
|
13
|
+
| Brand colors, fonts, radius, spacing | [Theme tokens](#change-colors-fonts-and-radius) |
|
|
14
|
+
| Light and dark colors, animation | [Dark mode and motion](#turn-on-dark-mode-and-change-motion) |
|
|
15
|
+
| Which button is filled or outlined | [`consentActions`](#style-the-action-buttons) |
|
|
16
|
+
| Banner shape and position | [`ConsentBanner` props or `presentation`](#change-the-banner-shape) |
|
|
17
|
+
| One element of a component | [Component parts](#style-one-component-part) |
|
|
18
|
+
| Labels and languages | [Copy and translations](#change-the-copy) |
|
|
19
|
+
| Different markup entirely | [Headless](./headless.md) |
|
|
20
|
+
|
|
21
|
+
[Customization](../../customization/overview.md) explains how these choices relate
|
|
22
|
+
across frameworks.
|
|
23
|
+
|
|
24
|
+
See the [design gallery](../../customization/recipes.md) for five banner designs,
|
|
25
|
+
from a bottom bar to a fully custom one, with tested code for this framework.
|
|
26
|
+
|
|
27
|
+
## Import the stylesheet yourself
|
|
28
|
+
|
|
29
|
+
A React app imports no c15t stylesheet. `ConsentBanner`, `ConsentDialog` and
|
|
30
|
+
the other stock components render the rules they use as `<style>` elements.
|
|
31
|
+
|
|
32
|
+
Import the stylesheet yourself with Tailwind CSS 3, to put c15t's rules in a
|
|
33
|
+
named cascade layer. Set `styles: false` in the provider
|
|
34
|
+
options, so the components add no second copy, and import the stylesheet once
|
|
35
|
+
in the module that renders `ConsentProvider`:
|
|
36
|
+
|
|
37
|
+
```tsx title="src/consent.tsx (partial)"
|
|
38
|
+
import 'c15t/react/styles.css';
|
|
39
|
+
|
|
40
|
+
// In the ConsentProvider options:
|
|
41
|
+
styles: false,
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
To import the stylesheet from CSS instead, put it at the top of your global
|
|
45
|
+
stylesheet, above any `@tailwind` directives. `postcss-import`, which Vite
|
|
46
|
+
uses, ignores an `@import` that follows other rules. Tailwind 3 also needs a
|
|
47
|
+
PostCSS plugin;
|
|
48
|
+
[Tailwind CSS](../../customization/tailwind.md#set-up-tailwind-css-3) shows the
|
|
49
|
+
setup.
|
|
50
|
+
|
|
51
|
+
## Change colors, fonts and radius
|
|
52
|
+
|
|
53
|
+
Colors, radii, shadows, typography, and motion come from `--c15t-*` custom
|
|
54
|
+
properties. The rules the components render set the default values, as
|
|
55
|
+
does `styles.css` when you import it with `styles: false`. To change them,
|
|
56
|
+
render `ConsentTheme` with your theme where your app renders on the server,
|
|
57
|
+
or override the variables directly in your CSS.
|
|
58
|
+
|
|
59
|
+
`ConsentTheme` renders a `<style id="c15t-theme">` element with the
|
|
60
|
+
variables for `theme`. It is not a client component: rendered from a Server
|
|
61
|
+
Component or another server-only file, the theme generator stays out of the
|
|
62
|
+
browser bundle. Rendered from a client component it still works, but the
|
|
63
|
+
browser downloads the generator (about 1.7 KB gzip). The provider no longer
|
|
64
|
+
turns `theme` tokens into CSS. It still reads `consentActions` and slot
|
|
65
|
+
styles from its `theme` option, and warns in development when `theme` holds
|
|
66
|
+
tokens but the page has no `c15t-theme` stylesheet.
|
|
67
|
+
|
|
68
|
+
| `ConsentTheme` prop | Purpose |
|
|
69
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `theme` | Colors, `dark` colors, typography, spacing, radius, shadows and motion. Defaults to the built-in theme. |
|
|
71
|
+
| `colorScheme` | `'dark'` makes the dark tokens the default before hydration. `'system'` follows `prefers-color-scheme` with a CSS media query. Omit it to follow a `dark` or `c15t-dark` class on `<html>`. |
|
|
72
|
+
| `nonce` | Content Security Policy nonce for the `<style>` element. |
|
|
73
|
+
|
|
74
|
+
Pass the same `colorScheme` to `ConsentTheme` and to the provider. If your
|
|
75
|
+
app manages dark mode through a root class, such as next-themes' `dark`
|
|
76
|
+
class, omit `colorScheme` and include that class in the server HTML.
|
|
77
|
+
[Dark mode](../../customization/dark-mode.md) covers `theme.dark`, `null` and
|
|
78
|
+
a dark first paint.
|
|
79
|
+
|
|
80
|
+
To switch between different token sets at runtime, render `ConsentTheme`
|
|
81
|
+
from a client component and change its props, which ships the generator.
|
|
82
|
+
|
|
83
|
+
Outside a component, call `generateThemeCSS(theme, colorScheme)` from
|
|
84
|
+
`c15t/react/utils`, or `@c15t/react/utils` with the scoped package. It
|
|
85
|
+
writes the same CSS as `ConsentTheme`. Outside React, import it from
|
|
86
|
+
`@c15t/ui/theme`. Call it on the server or at build time and put the result in a
|
|
87
|
+
`<style>` element or your stylesheet. It escapes `<`, so the result is safe
|
|
88
|
+
inside `<style>`.
|
|
89
|
+
|
|
90
|
+
A single-page app has no server render, so pick one of two ways:
|
|
91
|
+
|
|
92
|
+
* **Set the variables in your CSS.** Nothing extra ships to the browser:
|
|
93
|
+
|
|
94
|
+
```css title="src/index.css"
|
|
95
|
+
:root {
|
|
96
|
+
--c15t-primary: #2f6f4e;
|
|
97
|
+
--c15t-primary-hover: #24563c;
|
|
98
|
+
--c15t-text-on-primary: #fff;
|
|
99
|
+
--c15t-radius-lg: 4px;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
* **Render `ConsentTheme` next to the provider.** Use this when the theme lives
|
|
104
|
+
in TypeScript or changes at runtime. The browser downloads the theme
|
|
105
|
+
generator.
|
|
106
|
+
|
|
107
|
+
```tsx title="src/consent-theme.ts"
|
|
108
|
+
import { defineTheme } from 'c15t/react';
|
|
109
|
+
|
|
110
|
+
export const theme = defineTheme({
|
|
111
|
+
colors: { primary: '#2f6f4e', primaryHover: '#24563c' },
|
|
112
|
+
radius: { lg: '4px' },
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
In `src/consent.tsx`, render `<ConsentTheme theme={theme} />` from
|
|
117
|
+
`c15t/react` just before `<ConsentProvider>`.
|
|
118
|
+
|
|
119
|
+
In a server-rendered app, such as React Router framework mode, render
|
|
120
|
+
`ConsentTheme` in the root component so the `<style>` element is part of the
|
|
121
|
+
server HTML. [Theme tokens](../../customization/tokens.md) lists every variable.
|
|
122
|
+
|
|
123
|
+
`ConsentTheme` outranks a plain `:root` rule, wherever each one loads. If you
|
|
124
|
+
use both, a variable set in both places takes the `ConsentTheme` value. Write
|
|
125
|
+
your CSS overrides on `:root:root` to beat it, or move the values into the
|
|
126
|
+
theme.
|
|
127
|
+
|
|
128
|
+
## Style the action buttons
|
|
129
|
+
|
|
130
|
+
`consentActions` decides how each action looks. `default` applies to every
|
|
131
|
+
button, `primary` to the action the policy or your props mark primary, and
|
|
132
|
+
`accept`, `reject`, `customize` and `dismiss` to one action each. Pass it
|
|
133
|
+
through the provider's `theme` option:
|
|
134
|
+
|
|
135
|
+
```tsx title="src/consent.tsx"
|
|
136
|
+
<ConsentProvider
|
|
137
|
+
options={{
|
|
138
|
+
mode,
|
|
139
|
+
scripts,
|
|
140
|
+
theme: {
|
|
141
|
+
consentActions: {
|
|
142
|
+
primary: { variant: 'primary', mode: 'filled' },
|
|
143
|
+
dismiss: { variant: 'neutral', mode: 'stroke' },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
}}
|
|
147
|
+
>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The provider's `theme` option only reads `consentActions` and slot styles.
|
|
151
|
+
Tokens passed there do nothing, and the provider logs a warning in development.
|
|
152
|
+
Changing button styles does not change the policy or expire a saved choice.
|
|
153
|
+
|
|
154
|
+
## Change the banner shape
|
|
155
|
+
|
|
156
|
+
`ConsentBanner` takes `variant` (`floating`, `bar`, `widget` or `wall`) and
|
|
157
|
+
`position`. To use one shape everywhere, set `presentation.prompt` in the
|
|
158
|
+
provider options instead. This banner is a full-width bar for notices and a
|
|
159
|
+
card for choices:
|
|
160
|
+
|
|
161
|
+
```tsx title="src/regional-banner.tsx"
|
|
162
|
+
import { ConsentBanner, usePolicyRule } from 'c15t/react';
|
|
163
|
+
|
|
164
|
+
export function RegionalBanner() {
|
|
165
|
+
const policy = usePolicyRule();
|
|
166
|
+
return (
|
|
167
|
+
<ConsentBanner variant={policy?.prompt === 'notice' ? 'bar' : 'floating'} />
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Render `RegionalBanner` in place of `ConsentBanner` inside the provider.
|
|
173
|
+
[ConsentBanner](./components/consent-banner.md#variants)
|
|
174
|
+
lists every variant and position, and how to order buttons per policy.
|
|
175
|
+
|
|
176
|
+
## Style one component part
|
|
177
|
+
|
|
178
|
+
Each component part is a slot. Set slots in the provider options under
|
|
179
|
+
`components`, keyed by component and part. A slot takes any attribute the
|
|
180
|
+
element accepts, such as `className` or `style`.
|
|
181
|
+
|
|
182
|
+
The root also carries `data-variant`, so you can restyle one shape without
|
|
183
|
+
touching the others. Tailwind, giving a `bar` a brand-colored top edge and
|
|
184
|
+
tighter text:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<ConsentProvider
|
|
188
|
+
options={{
|
|
189
|
+
mode,
|
|
190
|
+
presentation: { prompt: { variant: 'bar' } },
|
|
191
|
+
components: {
|
|
192
|
+
banner: {
|
|
193
|
+
root: { className: 'group' },
|
|
194
|
+
card: {
|
|
195
|
+
className:
|
|
196
|
+
'group-data-[variant=bar]:border-t-4 group-data-[variant=bar]:border-t-emerald-600',
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
description: {
|
|
200
|
+
banner: { className: 'group-data-[variant=bar]:text-xs' },
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
}}
|
|
204
|
+
/>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`data-variant` sits on the root, so child slots use Tailwind's `group`
|
|
208
|
+
prefix to read it.
|
|
209
|
+
|
|
210
|
+
[Class names and CSS-in-JS](../../customization/class-names.md) shows CSS
|
|
211
|
+
Modules, vanilla-extract, StyleX and Emotion classes on a part.
|
|
212
|
+
|
|
213
|
+
Set `noStyle` on a component to drop the built-in classes from every part and
|
|
214
|
+
keep only what your slots pass. Set `noStyle` in the provider options to do it
|
|
215
|
+
for every component.
|
|
216
|
+
|
|
217
|
+
[Component parts](../../customization/slots.md) lists every part key under
|
|
218
|
+
`components` and the `data-*` attributes each part carries. Action buttons
|
|
219
|
+
carry `data-action`, so a single rule such as `[data-action='dismiss']`
|
|
220
|
+
styles one role across every surface. Right links are underlined text by
|
|
221
|
+
default, so the only button on a notice is the primary action.
|
|
222
|
+
|
|
223
|
+
[Component parts](../../customization/slots.md) lists every component's part keys
|
|
224
|
+
and when to drop the built-in styles with `noStyle`. The `ConsentGate`
|
|
225
|
+
placeholder's parts are `components['consent-gate'].root`, `.title` and
|
|
226
|
+
`.button`.
|
|
227
|
+
[Class names and CSS-in-JS](../../customization/class-names.md) covers CSS
|
|
228
|
+
Modules, vanilla-extract, StyleX and Emotion, and
|
|
229
|
+
[Tailwind CSS](../../customization/tailwind.md) covers utilities on parts.
|
|
230
|
+
|
|
231
|
+
## Turn on dark mode and change motion
|
|
232
|
+
|
|
233
|
+
Pass `colorScheme` in the provider options and the same value to
|
|
234
|
+
`ConsentTheme`. Leave it unset to follow a `dark` class on `<html>`, and add
|
|
235
|
+
dark colors with `theme.dark`. [Dark mode](../../customization/dark-mode.md)
|
|
236
|
+
covers each value and a dark first paint.
|
|
237
|
+
|
|
238
|
+
`disableAnimation` in the provider options turns off the banner and dialog
|
|
239
|
+
animations, and the same prop on `ConsentBanner` or `ConsentDialog` overrides
|
|
240
|
+
it for one surface. [Motion and animation](../../customization/motion.md) covers
|
|
241
|
+
the duration and easing tokens and reduced motion.
|
|
242
|
+
|
|
243
|
+
## Change the copy
|
|
244
|
+
|
|
245
|
+
Labels, descriptions and languages come from the translations in your Inth
|
|
246
|
+
project and from the provider's `i18n` option. For the visitor's language,
|
|
247
|
+
`i18n.messages` replace the project's copy key by key, and keys you leave out
|
|
248
|
+
keep the project's wording.
|
|
249
|
+
[Copy and translations](../../customization/translations.md) shows the message
|
|
250
|
+
keys. For one banner, `ConsentBanner` also accepts text props such as
|
|
251
|
+
`dismissButtonText`.
|
|
252
|
+
|
|
253
|
+
## Check the result
|
|
254
|
+
|
|
255
|
+
Clear site data and reload under a policy that shows a banner. Check the banner
|
|
256
|
+
and the preferences dialog, since both read the same tokens. Test a narrow
|
|
257
|
+
window, keyboard focus and contrast on the primary button. In development, the
|
|
258
|
+
console warns if `theme` holds tokens but the page has no `c15t-theme` style.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Embeds
|
|
3
|
+
description: Keep YouTube videos, maps and other iframes out of a React page
|
|
4
|
+
until their consent category is allowed, with ConsentGate or the iframe
|
|
5
|
+
blocker in ConsentProvider.
|
|
6
|
+
group: frameworks
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Pick a method
|
|
10
|
+
|
|
11
|
+
| Method | Use it when |
|
|
12
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `ConsentGate` | You render the iframe in a React component and want a placeholder until the visitor allows its category. |
|
|
14
|
+
| The iframe blocker | The iframe comes from markup you do not render with React, such as CMS or Markdown content. |
|
|
15
|
+
|
|
16
|
+
Both keep the iframe's `src` out of the page until the category is allowed, so
|
|
17
|
+
the embed's host receives no request before consent.
|
|
18
|
+
|
|
19
|
+
## Gate an embed with ConsentGate
|
|
20
|
+
|
|
21
|
+
Wrap the iframe in `ConsentGate` anywhere inside `ConsentProvider`:
|
|
22
|
+
|
|
23
|
+
```tsx title="src/video-embed.tsx"
|
|
24
|
+
import { ConsentDialogLink, ConsentGate } from 'c15t/react';
|
|
25
|
+
|
|
26
|
+
export const VideoEmbed = () => (
|
|
27
|
+
<ConsentGate
|
|
28
|
+
category="measurement"
|
|
29
|
+
placeholder={
|
|
30
|
+
<div className="placeholder">
|
|
31
|
+
<p>Allow measurement to load this YouTube video.</p>
|
|
32
|
+
<ConsentDialogLink>Choose video permissions</ConsentDialogLink>
|
|
33
|
+
</div>
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
<iframe
|
|
37
|
+
title="YouTube video"
|
|
38
|
+
sandbox="allow-scripts allow-same-origin allow-presentation"
|
|
39
|
+
src="https://www.youtube-nocookie.com/embed/czTksCF6X8Y?playsinline=1"
|
|
40
|
+
allow="encrypted-media; picture-in-picture"
|
|
41
|
+
allowFullScreen
|
|
42
|
+
/>
|
|
43
|
+
</ConsentGate>
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The iframe is absent from the page until the visitor allows measurement. The
|
|
48
|
+
`placeholder` shows a message and a
|
|
49
|
+
[`ConsentDialogLink`](./components/consent-dialog-link.md)
|
|
50
|
+
until then. When the visitor withdraws measurement, React removes the iframe.
|
|
51
|
+
|
|
52
|
+
Pick the category that matches what the embed does. The example uses
|
|
53
|
+
measurement for YouTube because its player measures views. A map or chat
|
|
54
|
+
widget usually belongs under functionality or experience.
|
|
55
|
+
[ConsentGate](./components/consent-gate.md) documents the
|
|
56
|
+
built-in placeholder and every prop.
|
|
57
|
+
|
|
58
|
+
## Gate an iframe with the iframe blocker
|
|
59
|
+
|
|
60
|
+
`ConsentProvider` runs the iframe blocker by default. Give an iframe
|
|
61
|
+
`data-src` instead of `src`, and a `data-category`:
|
|
62
|
+
|
|
63
|
+
```html title="Markup from your CMS"
|
|
64
|
+
<iframe
|
|
65
|
+
data-src="https://www.google.com/maps/embed?pb=YOUR_EMBED_ID"
|
|
66
|
+
data-category="functionality"
|
|
67
|
+
title="Store map"
|
|
68
|
+
></iframe>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
c15t sets `src` from `data-src` when the category is allowed and removes `src`
|
|
72
|
+
when the category is withdrawn. It watches the page, so iframes added later
|
|
73
|
+
are handled too. Add `data-vendor` with a vendor ID to also block the iframe
|
|
74
|
+
while the visitor has turned that vendor off.
|
|
75
|
+
|
|
76
|
+
To turn the blocker off, set `iframeBlocker: false` in the provider `options`.
|
|
77
|
+
|
|
78
|
+
## Verify the embeds
|
|
79
|
+
|
|
80
|
+
Open the production build in a private window with DevTools open, under a
|
|
81
|
+
policy that asks for consent.
|
|
82
|
+
|
|
83
|
+
1. No iframe has a `src` pointing at `youtube-nocookie.com` or
|
|
84
|
+
`google.com/maps`, and the Network panel shows no request to them.
|
|
85
|
+
2. Allow the embed's category and save. The iframe loads.
|
|
86
|
+
3. Withdraw the category and save. The page reloads without the embed.
|
|
87
|
+
|
|
88
|
+
The [YouTube](../../integrations/youtube.md) and
|
|
89
|
+
[Google Maps](../../integrations/google-maps.md) guides cover sizing and titles.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: IAB GPP
|
|
3
|
+
description: Add the IAB Global Privacy Platform API (__gpp) to a React app with
|
|
4
|
+
ConsentGPP from @c15t/react/gpp, so ad tech can read US state opt-outs and the
|
|
5
|
+
TCF EU consent string.
|
|
6
|
+
group: frameworks
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What GPP does
|
|
10
|
+
|
|
11
|
+
`ConsentGPP` from `@c15t/react/gpp` installs `window.__gpp`, the GPP 1.1 CMP
|
|
12
|
+
API, and keeps its GPP string in step with the visitor's choices. Prebid.js,
|
|
13
|
+
Google Ad Manager and other ad tech read US privacy signals from it.
|
|
14
|
+
|
|
15
|
+
## Turn on GPP
|
|
16
|
+
|
|
17
|
+
Render `ConsentGPP` inside `ConsentProvider`:
|
|
18
|
+
|
|
19
|
+
```tsx title="src/consent.tsx"
|
|
20
|
+
import { ConsentGPP } from '@c15t/react/gpp';
|
|
21
|
+
|
|
22
|
+
<ConsentProvider options={{ mode, scripts }}>
|
|
23
|
+
<ConsentGPP />
|
|
24
|
+
{children}
|
|
25
|
+
</ConsentProvider>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`ConsentGPP` renders nothing. It installs `__gpp` after it mounts and
|
|
29
|
+
removes it when it unmounts. It lives in its own entry, like
|
|
30
|
+
`@c15t/react/iab`, so apps that do not import it bundle none of the GPP
|
|
31
|
+
code. `@c15t/react` already depends on `@c15t/iab`; with the `c15t`
|
|
32
|
+
package, import from `c15t/react/gpp`.
|
|
33
|
+
|
|
34
|
+
The props are the GPP options listed below, for example
|
|
35
|
+
`<ConsentGPP usFallback="none" />`. It works the same with a runtime you
|
|
36
|
+
pass to `ConsentProvider` as `runtime`.
|
|
37
|
+
|
|
38
|
+
The GPP string follows the policy and location your backend resolves for the
|
|
39
|
+
visitor, so a US visitor's state comes from the backend. With `offline()`
|
|
40
|
+
mode, pass the state yourself, for example
|
|
41
|
+
`overrides: { country: 'US', region: 'CA' }`.
|
|
42
|
+
|
|
43
|
+
To add the TCF EU section for visitors under an `iab` policy, set up
|
|
44
|
+
[IAB TCF](./iab.md) as well.
|
|
45
|
+
|
|
46
|
+
## How the policy decides the section
|
|
47
|
+
|
|
48
|
+
The policy rule c15t matched for the visitor decides whether a section
|
|
49
|
+
applies. The visitor's location only picks which US section carries it.
|
|
50
|
+
|
|
51
|
+
| Matched rule and visitor | Section in the GPP string |
|
|
52
|
+
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
53
|
+
| `iab` rule, with IAB TCF set up | `tcfeuv2` (ID 2): the TC String the CMP confirmed, unchanged |
|
|
54
|
+
| `iab` rule, any visitor, with `tcf: false` | None; `applicableSections` is `[-1]` |
|
|
55
|
+
| Any other rule with the `preferences` or `opt-out` right, US visitor in a state with a section | That state's section, such as `usca` (ID 8) |
|
|
56
|
+
| The same rule, US visitor whose region is unknown or whose state has no section | `usnat` (ID 7), MSPA US National version 2; none with `usFallback: 'none'` |
|
|
57
|
+
| The same rule, `usApproach: 'national'` | `usnat` for every US visitor |
|
|
58
|
+
| A rule without those rights, such as `none` | None |
|
|
59
|
+
| A visitor outside the US under any rule other than `iab` | None |
|
|
60
|
+
|
|
61
|
+
Every `opt-in` and `opt-out` rule has the `preferences` right, and every
|
|
62
|
+
`opt-out` rule also has `opt-out`. A `none` rule has them only if you add
|
|
63
|
+
them. A rule that gives the visitor no way to opt out produces no US
|
|
64
|
+
section, even when the visitor sends a GPC signal.
|
|
65
|
+
|
|
66
|
+
State sections exist for California, Colorado, Connecticut, Delaware, Florida,
|
|
67
|
+
Iowa, Minnesota, Montana, Nebraska, New Hampshire, New Jersey, Oregon,
|
|
68
|
+
Tennessee, Texas, Utah and Virginia. Indiana, Kentucky, Maryland and Rhode
|
|
69
|
+
Island are not encoded yet: their published specifications start the section
|
|
70
|
+
with a header that the IAB reference implementation does not encode. Visitors
|
|
71
|
+
there get the fallback, `usnat` by default. So does a US visitor whose region
|
|
72
|
+
the geo headers did not supply.
|
|
73
|
+
|
|
74
|
+
The MSPA US National specification describes `usnat` for MSPA signatories
|
|
75
|
+
that chose the national approach. Without `mspaMode`, c15t reports the
|
|
76
|
+
fallback as a transaction the MSPA does not cover (`MspaCoveredTransaction:
|
|
77
|
+
2`), which still carries the opt-outs to vendors such as Prebid.js. If you
|
|
78
|
+
reserve `usnat` for the national approach, set `usFallback: 'none'`; those
|
|
79
|
+
visitors then get no section until their state resolves.
|
|
80
|
+
|
|
81
|
+
## What the US sections report
|
|
82
|
+
|
|
83
|
+
* `SaleOptOut`, `SharingOptOut` and `TargetedAdvertisingOptOut`: `1` (opted
|
|
84
|
+
out) when the `marketing` category is not permitted, otherwise `2`. A
|
|
85
|
+
refusal, a GPC signal the rule maps to `marketing` through
|
|
86
|
+
`privacySignals.gpc`, and an opt-in rule without a grant all count.
|
|
87
|
+
* The opt-out notices: `1` (given), since the rule offers an opt-out.
|
|
88
|
+
* The sharing or processing notice: `1` when the rule has the `disclosure`
|
|
89
|
+
right, otherwise `2`.
|
|
90
|
+
* `Gpc`: the browser's Global Privacy Control signal, in sections that have a
|
|
91
|
+
GPC subsection. It is reported even when the rule does not map GPC to a
|
|
92
|
+
category, so give US rules a `privacySignals.gpc` mapping if the opt-outs
|
|
93
|
+
should follow it too.
|
|
94
|
+
* Sensitive data and known-child consents: `0` (not applicable). c15t has no
|
|
95
|
+
category for them, so the string states that you do not process sensitive
|
|
96
|
+
data or knowingly process children's data. If you do, GPP from c15t does
|
|
97
|
+
not describe your processing; collect and signal that consent separately.
|
|
98
|
+
* `MspaCoveredTransaction`: `2` (not covered) unless you set `mspaMode`.
|
|
99
|
+
|
|
100
|
+
The notice fields are your attestation, made through the rule's rights:
|
|
101
|
+
c15t cannot see whether your privacy notice is on the page. Show the notices
|
|
102
|
+
the rule promises, including a persistent opt-out control.
|
|
103
|
+
|
|
104
|
+
## GPP options
|
|
105
|
+
|
|
106
|
+
Every field is optional. Pass them in the `gpp` option, where `gpp: true`
|
|
107
|
+
uses the defaults, as props on `ConsentGPP` in React, or to `mountGPP()` in
|
|
108
|
+
`@c15t/browser`.
|
|
109
|
+
|
|
110
|
+
| Option | Default | Effect |
|
|
111
|
+
| ------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `cmpId` | the IAB CMP ID c15t holds, else `1` | CMP ID reported by `ping`. The GPP specification has string creators without a registered ID, including MSPA US National creators, use `1`. A TCF EU section needs the registered ID its TC String names. |
|
|
113
|
+
| `usApproach` | `'state'` | `'state'` uses the visitor's state section. `'national'` reports `usnat` for every US visitor; the MSPA reserves it for signatories that chose the national approach. |
|
|
114
|
+
| `usFallback` | `'usnat'` | Under the state approach, the section for a US visitor whose state is unknown or has no section: `'usnat'` or `'none'`. |
|
|
115
|
+
| `mspaMode` | unset | `'opt-out-option'` or `'service-provider'`. Set it only if you signed the IAB Multi-State Privacy Agreement; the transaction is then reported as covered. In service provider mode the opt-outs are reported as not applicable. |
|
|
116
|
+
| `optOutCategories` | `['marketing']` | Categories whose refusal reports an opt-out of sale, sharing and targeted advertising. |
|
|
117
|
+
| `tcf` | `true` | Include the `tcfeuv2` section under an `iab` policy. It needs IAB TCF set up as well. |
|
|
118
|
+
|
|
119
|
+
## Check the signal
|
|
120
|
+
|
|
121
|
+
Open the browser console on a page with GPP on and call:
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
__gpp('ping', (data) => console.log(data));
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
For a California visitor who has not opted out, the result includes
|
|
128
|
+
`applicableSections: [8]`, `signalStatus: 'ready'` and
|
|
129
|
+
`parsedSections.usca[0].SaleOptOut === 2`. After the visitor refuses
|
|
130
|
+
`marketing`, `SaleOptOut` is `1`. `__gpp('getField', cb, 'usca.SaleOptOut')`
|
|
131
|
+
returns the same value. Scripts in iframes reach the API through the
|
|
132
|
+
`__gppLocator` frame and `postMessage`.
|
|
133
|
+
|
|
134
|
+
Under an `iab` rule, `parsedSections.tcfeuv2` uses the field names of the
|
|
135
|
+
IAB Europe TCF section, such as `PurposeConsent`, `VendorConsent` and
|
|
136
|
+
`PubRestrictions`. `getSection` and `getField` answer `null` for `tcfeuv2`,
|
|
137
|
+
as the IAB reference implementation does: TCF vendors read consent from
|
|
138
|
+
events, not on demand.
|
|
139
|
+
|
|
140
|
+
`signalStatus` stays `'not ready'` while the policy is pending, while the
|
|
141
|
+
banner or dialog is open, while an `iab` rule has no confirmed TC String,
|
|
142
|
+
and while a new TC String is decoded. Listeners added with
|
|
143
|
+
`addEventListener` get `signalStatus: 'not ready'`, then `cmpDisplayStatus`
|
|
144
|
+
and `sectionChange` events, then `signalStatus: 'ready'`.
|
|
145
|
+
|
|
146
|
+
## Ad tags that load before c15t
|
|
147
|
+
|
|
148
|
+
c15t installs `__gpp` in the browser once consent starts, after it loads the
|
|
149
|
+
GPP code. Vendor scripts that call `__gpp` earlier need a stub. c15t takes over
|
|
150
|
+
the calls and listeners a stub queued, whether the stub keeps listeners on
|
|
151
|
+
`__gpp.events`, as the GPP specification's sample does, or returns them from
|
|
152
|
+
`__gpp('events')`, as `@iabgpp/stub` does. Call `initializeGPPStub()` from
|
|
153
|
+
`@c15t/iab/gpp` in your first script, or use the IAB's own stub snippet.
|
|
154
|
+
When another stub already answers iframes, c15t leaves that to it, so each
|
|
155
|
+
iframe call gets one reply.
|
|
156
|
+
|
|
157
|
+
If a CMP that has already loaded owns `__gpp`, c15t leaves it in place.
|
|
158
|
+
The `gpp` option reports the conflict to the `onError` callback,
|
|
159
|
+
`ConsentGPP` logs it, and `mountGPP()` and `createGPP()` throw. Run one GPP
|
|
160
|
+
CMP per page.
|
|
161
|
+
|
|
162
|
+
GPP signals what the visitor chose; it does not block scripts. Gate vendor
|
|
163
|
+
scripts with c15t's script loading as well.
|
|
@@ -34,13 +34,13 @@ import { useHeadlessConsentUI, useTranslations } from 'c15t/react/headless';
|
|
|
34
34
|
|
|
35
35
|
const ACTION_LABELS = {
|
|
36
36
|
accept: 'acceptAll',
|
|
37
|
-
reject: 'rejectAll',
|
|
38
37
|
customize: 'customize',
|
|
39
38
|
dismiss: 'acknowledge',
|
|
39
|
+
reject: 'rejectAll',
|
|
40
40
|
save: 'save',
|
|
41
41
|
} as const;
|
|
42
42
|
|
|
43
|
-
export
|
|
43
|
+
export const Banner = () => {
|
|
44
44
|
const { banner, performAction, openDialog } = useHeadlessConsentUI();
|
|
45
45
|
const { common, rights } = useTranslations();
|
|
46
46
|
|
|
@@ -49,7 +49,7 @@ export function Banner() {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
return (
|
|
52
|
-
<section
|
|
52
|
+
<section aria-label="Privacy">
|
|
53
53
|
{banner.preferenceControls.map((right) => (
|
|
54
54
|
<button key={right} type="button" onClick={openDialog}>
|
|
55
55
|
{right === 'opt-out' ? rights?.optOut : rights?.preferences}
|
|
@@ -71,7 +71,7 @@ export function Banner() {
|
|
|
71
71
|
))}
|
|
72
72
|
</section>
|
|
73
73
|
);
|
|
74
|
-
}
|
|
74
|
+
};
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
`banner.actionGroups` is the resolved layout: reject and accept share a group
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hooks
|
|
3
|
+
description: Gate features and save consent choices in React components with the
|
|
4
|
+
focused hooks exported from c15t/react.
|
|
5
|
+
group: frameworks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Read only the state you need
|
|
9
|
+
|
|
10
|
+
Every hook reads the runtime from the nearest `ConsentProvider`, so call them
|
|
11
|
+
from components rendered inside that provider and import them from
|
|
12
|
+
`c15t/react`.
|
|
13
|
+
|
|
14
|
+
```tsx title="src/optional-feature.tsx"
|
|
15
|
+
import { useConsent } from 'c15t/react';
|
|
16
|
+
|
|
17
|
+
export const OptionalFeature = () => {
|
|
18
|
+
const allowed = useConsent('marketing');
|
|
19
|
+
return allowed ? <div>Optional marketing content</div> : null;
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Call hooks inside the consent provider. `useConsent` reads effective permission,
|
|
24
|
+
which can be true under an opt-out policy without a recorded grant.
|
|
25
|
+
|
|
26
|
+
| Need | Hook |
|
|
27
|
+
| ----------------------------------- | ------------------------------------------ |
|
|
28
|
+
| One category's current permission | `useConsent(category)` |
|
|
29
|
+
| All current permissions | `useConsents()` |
|
|
30
|
+
| Recorded per-category choices | `useExplicitChoice()` |
|
|
31
|
+
| Whether one declared vendor may run | `useVendorAllowed(id)` |
|
|
32
|
+
| Whether a prompt is required | `usePromptRequirement()` |
|
|
33
|
+
| Active policy and resolution | `usePolicyRule()`, `usePolicyResolution()` |
|
|
34
|
+
| Save an explicit choice | `useSaveConsents()` |
|
|
35
|
+
| Open or close a consent surface | `useSetActiveUI()` |
|
|
36
|
+
| Acknowledge a notice | `useDismissNotice()` |
|
|
37
|
+
|
|
38
|
+
## Save from a visitor action
|
|
39
|
+
|
|
40
|
+
Render this component inside your existing `ConsentProvider`.
|
|
41
|
+
|
|
42
|
+
```tsx title="src/reject-button.tsx"
|
|
43
|
+
import { useSaveConsents } from 'c15t/react';
|
|
44
|
+
|
|
45
|
+
export const RejectButton = () => {
|
|
46
|
+
const save = useSaveConsents();
|
|
47
|
+
return (
|
|
48
|
+
<button
|
|
49
|
+
type="button"
|
|
50
|
+
onClick={() => {
|
|
51
|
+
void save('none');
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
Reject optional
|
|
55
|
+
</button>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This is an isolated action example, not a complete policy-aware banner. Use the
|
|
61
|
+
stock UI or headless surface actions for a complete prompt. Do not call save on
|
|
62
|
+
mount to persist a state derived from permissions.
|
|
63
|
+
|
|
64
|
+
Use focused hooks for feature gates. For a complete custom prompt or preference
|
|
65
|
+
center, use `useHeadlessConsentUI()` for surface actions and `useConsentDraft()`
|
|
66
|
+
for staged choices, inside one `ConsentDraftProvider` so the save commits the
|
|
67
|
+
same draft. v3 has no `useConsentManager()`; the
|
|
68
|
+
[`use-consent-manager-to-hooks` codemod](https://v3.c15t.com/docs/cli/commands/codemods#migrate-useconsentmanager-to-v3-hooks)
|
|
69
|
+
rewrites most of its calls to hooks. Read [how consent works](../../concepts/how-consent-works.md#a-permission-is-not-a-recorded-choice) before
|
|
70
|
+
treating a callback as evidence of a choice.
|