@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.10
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 +96 -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/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/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/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 +45 -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/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 +36 -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.d.ts +7 -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 +96 -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 +138 -0
- package/docs/concepts/consent-categories.md +84 -0
- package/docs/concepts/consent-state.md +421 -0
- package/docs/concepts/data-fetching.md +270 -0
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/concepts/modes.md +278 -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 +140 -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 +143 -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 +259 -0
- package/docs/frameworks/react/network-blocker.md +140 -0
- package/docs/frameworks/react/quickstart.md +220 -102
- package/docs/frameworks/react/rendering.md +263 -0
- package/docs/frameworks/react/scripts.md +114 -0
- package/docs/frameworks/react/translations.md +155 -0
- package/docs/frameworks/react/troubleshooting.md +188 -61
- package/docs/frameworks/react/upgrade-v3.md +651 -0
- package/docs/frameworks/react/vendor-consent.md +188 -0
- package/docs/guides/banner-experiments.md +672 -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 +152 -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/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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description: Gate a YouTube or map iframe behind consent with
|
|
4
|
-
showing a placeholder that opens the preference center until the
|
|
5
|
-
allowed.
|
|
2
|
+
title: ConsentGate
|
|
3
|
+
description: Gate a YouTube or map iframe behind consent with ConsentGate in
|
|
4
|
+
React, showing a placeholder that opens the preference center until the
|
|
5
|
+
category is allowed.
|
|
6
6
|
group: frameworks
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Gate an embed behind consent
|
|
10
10
|
|
|
11
|
-
`
|
|
11
|
+
`ConsentGate` mounts its children only while the effective permission for one
|
|
12
12
|
consent category is granted, and shows a placeholder otherwise. Wrap any
|
|
13
13
|
iframe or third-party widget that would set cookies or contact a vendor on
|
|
14
14
|
load. Render it anywhere inside the `ConsentProvider` from your
|
|
@@ -16,30 +16,30 @@ load. Render it anywhere inside the `ConsentProvider` from your
|
|
|
16
16
|
placeholder button opens.
|
|
17
17
|
|
|
18
18
|
```tsx title="src/product-video.tsx"
|
|
19
|
-
import {
|
|
19
|
+
import { ConsentGate } from 'c15t/react';
|
|
20
20
|
|
|
21
21
|
export function ProductVideo() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
return (
|
|
23
|
+
<ConsentGate category="marketing" className="video-frame">
|
|
24
|
+
<iframe
|
|
25
|
+
src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
|
|
26
|
+
title="Product tour"
|
|
27
|
+
loading="lazy"
|
|
28
|
+
allowFullScreen
|
|
29
|
+
style={{ width: '100%', aspectRatio: '16 / 9', border: 0 }}
|
|
30
|
+
/>
|
|
31
|
+
</ConsentGate>
|
|
32
|
+
);
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
`marketing` must be in your policy scope. If you set a non-empty
|
|
37
37
|
`options.consentCategories` list on `ConsentProvider`, include `marketing`
|
|
38
|
-
there too so the preference center can display and save it. `
|
|
38
|
+
there too so the preference center can display and save it. `ConsentGate` does
|
|
39
39
|
not add categories to that list.
|
|
40
40
|
|
|
41
41
|
The placeholder names the category using its title from your translations. Set `className` or `style`
|
|
42
|
-
on `
|
|
42
|
+
on `ConsentGate` to reserve the embed's space, so the page does not shift when the
|
|
43
43
|
placeholder is replaced.
|
|
44
44
|
|
|
45
45
|
## Props
|
|
@@ -51,51 +51,54 @@ placeholder is replaced.
|
|
|
51
51
|
| `placeholder` | `ReactNode` | built-in placeholder | Replaces the built-in title and button while the category is not allowed. Falsy values such as `null`, `false`, `0` and an empty string use the built-in placeholder. Pass an empty fragment, `<></>`, to render no placeholder content. |
|
|
52
52
|
|
|
53
53
|
Other `div` attributes such as `className`, `style` and `ref` apply to the
|
|
54
|
-
wrapper element that stays in the page in both states. `
|
|
54
|
+
wrapper element that stays in the page in both states. `ConsentGateProps` also
|
|
55
55
|
declares `noStyle` and `theme`, but the component does not apply them yet;
|
|
56
|
-
style the wrapper with `className
|
|
57
|
-
provider
|
|
56
|
+
style the wrapper with `className`, and style the built-in placeholder
|
|
57
|
+
through its parts in the provider options.
|
|
58
58
|
|
|
59
59
|
## Behavior
|
|
60
60
|
|
|
61
|
-
`
|
|
61
|
+
`ConsentGate` renders a `div` wrapper. Inside it, when the effective permission for
|
|
62
62
|
`category` is granted, it renders the children; otherwise it renders the
|
|
63
63
|
placeholder. Permission is the same value `useConsent(category)` returns,
|
|
64
64
|
so it can be granted under an opt-out rule before the visitor records a
|
|
65
65
|
choice, and a recorded grant can be overridden by a privacy signal.
|
|
66
66
|
|
|
67
67
|
While effective permission is denied, the children are absent from the DOM,
|
|
68
|
-
so an iframe or a third-party widget inside `
|
|
69
|
-
children unmount and the embed disappears. `
|
|
68
|
+
so an iframe or a third-party widget inside `ConsentGate` sends no requests. When the visitor later revokes it, the
|
|
69
|
+
children unmount and the embed disappears. `ConsentGate` does not depend on the
|
|
70
70
|
network blocker or the iframe blocker modules; use those for markup you
|
|
71
71
|
cannot wrap in a component.
|
|
72
72
|
|
|
73
|
-
The built-in placeholder shows the title `
|
|
74
|
-
consent to view this content
|
|
75
|
-
`consentTypes.<category>.title`, and a button labelled
|
|
76
|
-
|
|
73
|
+
The built-in placeholder shows the title `consentGate.title`,
|
|
74
|
+
`Accept {category} consent to view this content.`, with `{category}`
|
|
75
|
+
replaced by `consentTypes.<category>.title`, and a button labelled
|
|
76
|
+
`consentGate.actionButton`, `Enable {category} consent`. The button opens the
|
|
77
|
+
preference center; it
|
|
77
78
|
does not grant the category by itself, because the visitor still has to
|
|
78
79
|
save. Mount a `ConsentDialog` in the same provider so the button has
|
|
79
80
|
something to open.
|
|
80
81
|
|
|
81
82
|
Under a policy with `scopeMode: 'strict'`, a category outside the rule's
|
|
82
|
-
scope cannot be granted. The built-in placeholder then shows `
|
|
83
|
+
scope cannot be granted. The built-in placeholder then shows `consentGate.policyBlocked`,
|
|
83
84
|
"This content is unavailable under your region's consent policy.", without
|
|
84
85
|
the button, and a stored grant for that category stays blocked.
|
|
85
86
|
|
|
86
87
|
When the provider starts from a snapshot prefetched on the server, the
|
|
87
|
-
server renders the
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
server renders the placeholder for a denied category. For a granted
|
|
89
|
+
category it renders the empty wrapper, and the children mount once
|
|
90
|
+
hydration completes, so an iframe loads once even when the page streams
|
|
91
|
+
inside a `Suspense` boundary. A grant in the request cookie allows the
|
|
92
|
+
embed only when policy and privacy signals permit it. Browser privacy signals detected during hydration can
|
|
90
93
|
withdraw that permission. In a browser-only setup the
|
|
91
94
|
provider has no permission until it resolves policy on the client, so
|
|
92
|
-
`
|
|
95
|
+
`ConsentGate` shows the placeholder first and swaps in the embed after resolution
|
|
93
96
|
when the category is already granted.
|
|
94
97
|
|
|
95
|
-
`
|
|
98
|
+
`ConsentGate` is one component on this page; the per-vendor embed guides for
|
|
96
99
|
[YouTube](../../../integrations/youtube.md) and
|
|
97
100
|
[Google Maps](../../../integrations/google-maps.md) show a complete embed
|
|
98
|
-
configuration with sizing, titles and the same `
|
|
101
|
+
configuration with sizing, titles and the same `ConsentGate` usage across
|
|
99
102
|
frameworks.
|
|
100
103
|
|
|
101
104
|
To read the same permission in your own components, use `useConsent` from
|
|
@@ -104,34 +107,50 @@ also import from there.
|
|
|
104
107
|
|
|
105
108
|
## Composition
|
|
106
109
|
|
|
107
|
-
The placeholder parts are available as `
|
|
108
|
-
`
|
|
109
|
-
behavior. `
|
|
110
|
+
The placeholder parts are available as `ConsentGate.Root`, `ConsentGate.Title` and
|
|
111
|
+
`ConsentGate.Button` for a custom placeholder that keeps the built-in copy and
|
|
112
|
+
behavior. `ConsentGate.Title` and `ConsentGate.Button` accept `category` and fill in the
|
|
110
113
|
translated text; pass children to either to replace it.
|
|
111
114
|
|
|
112
115
|
```tsx
|
|
113
|
-
<
|
|
116
|
+
<ConsentGate
|
|
114
117
|
category="marketing"
|
|
115
118
|
placeholder={
|
|
116
|
-
<
|
|
117
|
-
<
|
|
119
|
+
<ConsentGate.Root>
|
|
120
|
+
<ConsentGate.Title category="marketing" />
|
|
118
121
|
<p>The video is also available on our channel.</p>
|
|
119
|
-
<
|
|
120
|
-
</
|
|
122
|
+
<ConsentGate.Button category="marketing">Choose cookies</ConsentGate.Button>
|
|
123
|
+
</ConsentGate.Root>
|
|
121
124
|
}
|
|
122
125
|
>
|
|
123
126
|
<iframe src="https://www.youtube-nocookie.com/embed/..." title="Product tour" />
|
|
124
|
-
</
|
|
127
|
+
</ConsentGate>
|
|
125
128
|
```
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
To restyle the built-in placeholder without replacing it, set its parts
|
|
131
|
+
under `components['consent-gate']` in the provider options. `root` is the
|
|
132
|
+
card, and `title` and `button` are its text and button. The `consentGate`, `consentGateTitle` and
|
|
133
|
+
`consentGateButton` theme slots reach the same parts. The button part
|
|
134
|
+
applies on top of `button.primary`.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
components: {
|
|
138
|
+
'consent-gate': {
|
|
139
|
+
root: { className: 'rounded-none' },
|
|
140
|
+
button: { className: 'font-semibold' },
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The built-in placeholder carries `data-testid="consent-gate-placeholder"`,
|
|
146
|
+
its title `data-testid="consent-gate-title"` and its button
|
|
147
|
+
`data-testid="consent-gate-button"`.
|
|
129
148
|
|
|
130
149
|
## Accessibility
|
|
131
150
|
|
|
132
151
|
The placeholder is plain text and a `button`, so it is readable and
|
|
133
152
|
operable without the embed. Give the iframe a descriptive `title`, and keep a
|
|
134
|
-
transcript, address or link outside the `
|
|
153
|
+
transcript, address or link outside the `ConsentGate` for visitors who decline
|
|
135
154
|
the category. A denied category may be fixed by policy, so opening the
|
|
136
155
|
preference center does not guarantee that the visitor can grant it.
|
|
137
156
|
|
|
@@ -142,7 +161,9 @@ center and is not restricted by policy or privacy signals such as GPC.
|
|
|
142
161
|
Load the page with the category denied. The placeholder text names the
|
|
143
162
|
category and the network panel shows no request to the embed's host. With a
|
|
144
163
|
prefetched snapshot, the server HTML contains the placeholder for a denied
|
|
145
|
-
category
|
|
164
|
+
category and neither placeholder nor embed for a granted category; the
|
|
165
|
+
embed appears after hydration and the network panel shows one request for
|
|
166
|
+
its document. Browser-only initialization
|
|
146
167
|
shows the placeholder before policy resolves, then replaces it with the
|
|
147
168
|
embed if the category is granted. After policy resolves, activate the
|
|
148
169
|
placeholder button: the preference center opens. Turn the category on and
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ConsentProvider
|
|
3
|
+
description: Mount ConsentProvider in a React app and configure its backend,
|
|
4
|
+
scripts, storage, blocking and presentation options.
|
|
5
|
+
group: frameworks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Mount one provider
|
|
9
|
+
|
|
10
|
+
`ConsentProvider` creates the consent runtime, loads the policy, stores the
|
|
11
|
+
visitor's choice and loads consent-gated scripts. Render one provider at the
|
|
12
|
+
root of your app and put the banner, dialog and a preferences link inside it.
|
|
13
|
+
The [quickstart](../quickstart.md) does this in
|
|
14
|
+
`src/consent.tsx`:
|
|
15
|
+
|
|
16
|
+
```tsx title="src/consent.tsx"
|
|
17
|
+
import { posthog } from '@c15t/integrations/posthog';
|
|
18
|
+
import {
|
|
19
|
+
ConsentBanner,
|
|
20
|
+
ConsentDialog,
|
|
21
|
+
ConsentDialogLink,
|
|
22
|
+
ConsentProvider,
|
|
23
|
+
manifest,
|
|
24
|
+
} from 'c15t/react';
|
|
25
|
+
import type { ReactNode } from 'react';
|
|
26
|
+
|
|
27
|
+
const options = {
|
|
28
|
+
// The policy the build downloaded from VITE_C15T_BACKEND_URL.
|
|
29
|
+
mode: manifest(),
|
|
30
|
+
scripts: [
|
|
31
|
+
posthog({
|
|
32
|
+
id: 'phc_your_project_key',
|
|
33
|
+
initOptions: { cookieless_mode: 'never' },
|
|
34
|
+
loadMode: 'after-consent',
|
|
35
|
+
}),
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
40
|
+
<ConsentProvider options={options}>
|
|
41
|
+
{children}
|
|
42
|
+
<ConsentBanner />
|
|
43
|
+
<ConsentDialog />
|
|
44
|
+
<footer>
|
|
45
|
+
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
46
|
+
</footer>
|
|
47
|
+
</ConsentProvider>
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`manifest()` from `c15t/react` resolves the policy from the snapshot
|
|
52
|
+
`consentManifest()` bundled, and sends consent choices to the backend URL the
|
|
53
|
+
plugin read from `VITE_C15T_BACKEND_URL` or `VITE_INTH_PROJECT_URL`. Set one
|
|
54
|
+
to the backend URL from your Inth project. To fetch the policy from the backend on every page
|
|
55
|
+
load instead, pass `hosted()` from `c15t/react`. The Next.js and TanStack Start adapters export `ConsentRoot` instead, which wraps
|
|
56
|
+
this provider and passes it server-resolved state.
|
|
57
|
+
|
|
58
|
+
## Provider options
|
|
59
|
+
|
|
60
|
+
Keep the provider mounted across client navigation. It reads `mode`,
|
|
61
|
+
`prefetch`, `persistence`, `storageConfig`, `clearOnRevocation`, `i18n` and
|
|
62
|
+
`experiment` once, when it mounts. Outside production, changing `mode`,
|
|
63
|
+
`i18n`, `experiment`, `persistence` or `storageConfig` logs a warning. Remount
|
|
64
|
+
the provider to change them. `scripts`, `vendors`, `networkBlocker`,
|
|
65
|
+
`iframeBlocker`, `consentCategories`, `overrides`, `user`, `callbacks` and
|
|
66
|
+
`enabled` apply when they change.
|
|
67
|
+
|
|
68
|
+
| Option | Purpose |
|
|
69
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `mode` | Required. `manifest()` for a bundled policy, `hosted()` for the backend's `/init`, `offline()` for local policies, all from `c15t/react`, or `custom()` for your own transport. See [consent modes](../../../concepts/modes.md) |
|
|
71
|
+
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper |
|
|
72
|
+
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md) |
|
|
73
|
+
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md) |
|
|
74
|
+
| `scriptLoader` | Options for the script loader module |
|
|
75
|
+
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false` |
|
|
76
|
+
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off |
|
|
77
|
+
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default |
|
|
78
|
+
| `storageConfig` | Storage key and cookie settings for the stored choice |
|
|
79
|
+
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied |
|
|
80
|
+
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true` |
|
|
81
|
+
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope |
|
|
82
|
+
| `overrides` | Force the country, region or language the policy is resolved for, for testing |
|
|
83
|
+
| `user` | Link consent records to a signed-in user |
|
|
84
|
+
| `callbacks` | Choice, permission and error events |
|
|
85
|
+
| `i18n` | Languages and message overrides |
|
|
86
|
+
| `legalLinks` | Privacy policy and other links shown in the banner and dialog |
|
|
87
|
+
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md) |
|
|
88
|
+
| `components` | Slot attributes per component part |
|
|
89
|
+
| `presentation` | Banner and dialog shape, position and blocking |
|
|
90
|
+
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md) |
|
|
91
|
+
| `journey` | Random id that links each `/init` to the save that follows. See [session reports](../../../concepts/data-fetching.md#link-an-init-to-the-save-that-follows) |
|
|
92
|
+
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone |
|
|
93
|
+
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations |
|
|
94
|
+
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior) |
|
|
95
|
+
| `nonce` | Content Security Policy nonce for script elements c15t inserts |
|
|
96
|
+
| `enabled` | Set `false` only when you deliberately bypass consent enforcement |
|
|
97
|
+
|
|
98
|
+
`enabled: false` grants categories and allows gated loading while suppressing
|
|
99
|
+
consent UI. It is not a way to fix failed initialization or hide a banner in
|
|
100
|
+
production.
|
|
101
|
+
|
|
102
|
+
## Observe changes without inventing choices
|
|
103
|
+
|
|
104
|
+
`onChoiceRecorded` reports explicit accept, reject and save actions.
|
|
105
|
+
`onPermissionsChanged` also covers changes caused by policy, expiry or privacy
|
|
106
|
+
signals. Hydration and notice dismissal do not become explicit choices.
|
|
107
|
+
|
|
108
|
+
An externally owned runtime can be passed through `runtime`. Its owner must
|
|
109
|
+
start and dispose it. A provider borrowing that runtime must not initialize or
|
|
110
|
+
dispose a second copy. Passing a different `runtime` moves the provider and its
|
|
111
|
+
hooks to the new runtime's kernel and unsubscribes them from the previous one.
|
|
112
|
+
The previous runtime keeps running until its owner disposes it. Switch the
|
|
113
|
+
provider to another runtime, or unmount it, before disposing the runtime it
|
|
114
|
+
renders. Changing between a borrowed runtime and a provider-created one still
|
|
115
|
+
requires remounting the provider. IAB actions taken before its handle is ready
|
|
116
|
+
wait for that handle. If the provider unmounts or switches runtimes first, a
|
|
117
|
+
pending `save()` rejects with an `AbortError` instead of waiting indefinitely.
|
|
118
|
+
See [how consent works](../../../concepts/how-consent-works.md#a-permission-is-not-a-recorded-choice) and
|
|
119
|
+
[choose your setup](../../../concepts/choose-your-setup.md).
|
|
120
|
+
|
|
121
|
+
## Reload after revocation
|
|
122
|
+
|
|
123
|
+
Removing a script cannot stop code that already ran. A vendor's listeners,
|
|
124
|
+
timers and widgets keep working until the page unloads. When an accept, reject
|
|
125
|
+
or save turns off a category or vendor that was granted, the provider reloads
|
|
126
|
+
the page once the save request settles, so the next page runs only permitted
|
|
127
|
+
code. `onBeforeConsentRevocationReload` runs just before the reload.
|
|
128
|
+
|
|
129
|
+
Otherwise, expiry, policy changes and privacy signals do not reload the page. Set
|
|
130
|
+
`reloadOnConsentRevoked: false` only when every gated vendor stops itself on
|
|
131
|
+
revocation, for example through its own opt-out API.
|
|
132
|
+
|
|
133
|
+
## Clear data when consent is denied
|
|
134
|
+
|
|
135
|
+
Set `options.clearOnRevocation` to declare cookies, localStorage keys, and
|
|
136
|
+
sessionStorage keys by optional consent category. Cleanup waits for policy
|
|
137
|
+
resolution, then clears denied categories and later allowed-to-denied
|
|
138
|
+
transitions. This option is initial-only. See
|
|
139
|
+
[clear on revocation](../clear-on-revocation.md) for examples,
|
|
140
|
+
cookie scopes, and browser limits.
|
|
@@ -8,7 +8,7 @@ group: frameworks
|
|
|
8
8
|
## Embed the preference center inline
|
|
9
9
|
|
|
10
10
|
`ConsentWidget` renders the preference center in the page flow instead of in
|
|
11
|
-
a modal: the category switches and the Reject
|
|
11
|
+
a modal: the category switches and the Reject All, Accept All and Save Settings
|
|
12
12
|
actions, without a title, backdrop or portal. Use it on a privacy or
|
|
13
13
|
settings page where the visitor expects the controls to be part of the
|
|
14
14
|
content. Render it anywhere inside the `ConsentProvider` from your
|
|
@@ -19,16 +19,16 @@ banner's Customize button and preference links still have a dialog to open.
|
|
|
19
19
|
import { ConsentWidget } from 'c15t/react';
|
|
20
20
|
|
|
21
21
|
export function PrivacyPage() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
return (
|
|
23
|
+
<main>
|
|
24
|
+
<h1>Privacy</h1>
|
|
25
|
+
<p>Choose which optional categories this site may use.</p>
|
|
26
|
+
<section aria-labelledby="cookie-preferences">
|
|
27
|
+
<h2 id="cookie-preferences">Cookie preferences</h2>
|
|
28
|
+
<ConsentWidget />
|
|
29
|
+
</section>
|
|
30
|
+
</main>
|
|
31
|
+
);
|
|
32
32
|
}
|
|
33
33
|
```
|
|
34
34
|
|
|
@@ -49,13 +49,16 @@ or dialog by itself.
|
|
|
49
49
|
|
|
50
50
|
The widget is the preference center without the modal around it: an
|
|
51
51
|
accordion with one row per category, each with a switch, followed by the
|
|
52
|
-
Reject
|
|
52
|
+
Reject All, Accept All and Save Settings actions. `ConsentDialog` renders this same
|
|
53
53
|
widget inside its card. Standalone, the widget renders in place, takes part
|
|
54
54
|
in server rendering, and does not touch the active surface, so it suits a
|
|
55
55
|
privacy page or an account settings screen.
|
|
56
56
|
|
|
57
57
|
The rows are `necessary` plus the categories in the active policy's scope,
|
|
58
|
-
narrowed to the provider `options.consentCategories`
|
|
58
|
+
narrowed to the categories the provider declares: `options.consentCategories`
|
|
59
|
+
and the categories of its scripts, network rules, vendors and discovered
|
|
60
|
+
frames. When nothing is declared, a permissive policy shows only `necessary`
|
|
61
|
+
and a strict one its whole scope.
|
|
59
62
|
The `necessary` switch is on and disabled. Row titles and descriptions come
|
|
60
63
|
from `consentTypes.<category>.title` and `.description`; the action labels
|
|
61
64
|
from `common.rejectAll`, `common.acceptAll` and `common.save`. One row is
|
|
@@ -68,8 +71,8 @@ until Save. The draft seeds each category from the recorded choice; without
|
|
|
68
71
|
one it uses `presentation.preferences.defaults` from the provider options,
|
|
69
72
|
and without that it is on under an opt-out rule and on only for the rule's
|
|
70
73
|
preselected categories under an opt-in rule. Save records the displayed
|
|
71
|
-
categories, then reseeds the draft from the new record. Accept
|
|
72
|
-
Reject
|
|
74
|
+
categories, then reseeds the draft from the new record. Accept All and
|
|
75
|
+
Reject All record immediately without a separate Save. A save answers a
|
|
73
76
|
choice prompt, so an open choice banner closes; it does not dismiss a
|
|
74
77
|
`notice` prompt, which keeps its own acknowledgement record. Unsaved toggles
|
|
75
78
|
are lost when the widget unmounts.
|
|
@@ -85,10 +88,35 @@ Privacy Control overrides shows a note under its row: "Your saved choice is
|
|
|
85
88
|
restricted by the current privacy settings." The switch still reflects the
|
|
86
89
|
saved value; the effective permission is off.
|
|
87
90
|
|
|
91
|
+
### Vendors
|
|
92
|
+
|
|
93
|
+
When the provider declares `vendors`, each category's expanded description
|
|
94
|
+
ends with one card per vendor whose category condition names that category,
|
|
95
|
+
styled like a category row: the vendor's name and a switch on the header,
|
|
96
|
+
and its description and privacy policy link behind the card's own expand
|
|
97
|
+
control. Cards start collapsed, so a long list stays one line per vendor,
|
|
98
|
+
and the category list scrolls inside the dialog rather than growing it.
|
|
99
|
+
A collapsed category or card renders its content element empty and mounts
|
|
100
|
+
the content the first time it opens, then keeps it mounted, so a long
|
|
101
|
+
vendor list costs nothing until a visitor expands its category.
|
|
102
|
+
Vendor switches edit the same draft as the category
|
|
103
|
+
switches and record on Save. Saving with one vendor off denies that vendor
|
|
104
|
+
only; the category stays granted and its other vendors keep loading. While
|
|
105
|
+
the category is off in the draft the vendor switches are disabled, with the
|
|
106
|
+
hint "Turn on this category to choose vendors." A vendor declared
|
|
107
|
+
`disabled`, or one that only falls under `necessary`, is listed without a
|
|
108
|
+
switch. Accept All and Reject All clear every vendor denial, including one
|
|
109
|
+
staged but not yet saved. Under an `iab` policy no vendor rows render.
|
|
110
|
+
Vendors that are only referenced by a script slug, without a name and
|
|
111
|
+
privacy policy URL, still gate loading but are not listed, and so does a
|
|
112
|
+
vendor whose condition negates a category, since no category row can
|
|
113
|
+
host it. See
|
|
114
|
+
[vendor consent](../vendor-consent.md).
|
|
115
|
+
|
|
88
116
|
### Actions
|
|
89
117
|
|
|
90
|
-
The preference center always renders Reject
|
|
91
|
-
Save as the primary action. `presentation.preferences.layout`,
|
|
118
|
+
The preference center always renders Reject All, Accept All and Save Settings, with
|
|
119
|
+
Save Settings as the primary action. `presentation.preferences.layout`,
|
|
92
120
|
`primaryActions`, `direction` and `uiProfile` in the provider options
|
|
93
121
|
reorder and restyle them; a layout that omits one of the three has it
|
|
94
122
|
restored. Customize and dismiss actions never render here.
|
|
@@ -102,8 +130,12 @@ such as `['disclosure']`, renders the widget and Save completes without
|
|
|
102
130
|
writing a consent record.
|
|
103
131
|
|
|
104
132
|
For a fully custom preference center, `useConsentDraft()` returns the same
|
|
105
|
-
draft: `values`, `displayedCategories`, `
|
|
106
|
-
`update`, `acceptAll`, `rejectAll`, `save` and `reset`.
|
|
133
|
+
draft: `values`, `displayedCategories`, `vendors`, `isDirty`, `isStale`,
|
|
134
|
+
`set`, `update`, `setVendor`, `acceptAll`, `rejectAll`, `save` and `reset`.
|
|
135
|
+
A custom vendor control alone takes `useVendorDraft()`, the vendor slice of
|
|
136
|
+
that draft: `vendors`, `setVendor`, `isDirty`, `isStale`, `save` and `reset`.
|
|
137
|
+
`useDeclaredVendors()`, `useVendorChoice()` and `useVendorAllowed(id)` read
|
|
138
|
+
the declared list, the recorded denials and one vendor's effective result.
|
|
107
139
|
|
|
108
140
|
`useConsentDraft` and `ConsentDraftProvider` import from `c15t/react`.
|
|
109
141
|
|
|
@@ -112,7 +144,10 @@ draft: `values`, `displayedCategories`, `isDirty`, `isStale`, `set`,
|
|
|
112
144
|
Each row is a disclosure: a button that expands the category description
|
|
113
145
|
and a switch beside it, so a visitor can read the description without
|
|
114
146
|
changing the choice. Each switch has the category title as its accessible
|
|
115
|
-
name.
|
|
147
|
+
name. A category's vendor cards sit in a `region` named "Vendors" with the
|
|
148
|
+
count; each card's expand button carries `aria-expanded`, each vendor
|
|
149
|
+
switch is named "Allow" followed by the vendor name, and is described by
|
|
150
|
+
the vendor's name element. The policy-change alert uses `role="alert"`, and a restriction note is
|
|
116
151
|
an `output` element linked to its switch through `aria-describedby`. The
|
|
117
152
|
root's `dir` attribute follows the active language.
|
|
118
153
|
|
|
@@ -122,7 +157,8 @@ Every part is available as `ConsentWidget.<Part>`. `Root` provides the
|
|
|
122
157
|
draft and accepts `noStyle`, `disableAnimation` and `uiSource`. `Accordion`
|
|
123
158
|
and `AccordionItems` render the stock rows; `AccordionItem`,
|
|
124
159
|
`AccordionTrigger`, `AccordionTriggerInner`, `AccordionContent`,
|
|
125
|
-
`AccordionArrow` and `Switch` build your own
|
|
160
|
+
`AccordionArrow` and `Switch` build your own; `VendorList` renders one
|
|
161
|
+
category's vendor rows and takes a `category` prop. `PolicyActions` renders the
|
|
126
162
|
resolved actions in `Footer` and `FooterSubGroup` and accepts `renderAction`
|
|
127
163
|
to replace one button; `AcceptAllButton`, `RejectButton`, `SaveButton` and
|
|
128
164
|
`CustomizeButton` are the individual buttons.
|
|
@@ -155,11 +191,20 @@ export function PreferenceCenter() {
|
|
|
155
191
|
Provider component slots for the stock structure are `manager.root`,
|
|
156
192
|
`manager.footer`, `manager.actionGroup`, `accordion.root`,
|
|
157
193
|
`accordion.triggerRow`, `accordion.title`, `accordion.control`,
|
|
158
|
-
`accordion-item.root`, `accordion-item.trigger`, `accordion-item.content
|
|
159
|
-
|
|
194
|
+
`accordion-item.root`, `accordion-item.trigger`, `accordion-item.content`,
|
|
195
|
+
`vendor-list.root`, `vendor-list.trigger`, `vendor-list.content`,
|
|
196
|
+
`vendor-list.item`, `vendor-list.header`,
|
|
197
|
+
`vendor-list.name`, `vendor-list.description`, `vendor-list.link`,
|
|
198
|
+
`vendor-list.control` and `tag.manager`.
|
|
199
|
+
|
|
200
|
+
`ConsentWidget` from the package root and from the
|
|
201
|
+
`c15t/react/consent-widget` subpath loads its code in a separate chunk the
|
|
202
|
+
first time it renders, so a page that never renders it does not download
|
|
203
|
+
it. `c15t/react/components/consent-widget` exports the widget without that
|
|
204
|
+
deferral, plus each part as a named export.
|
|
160
205
|
|
|
161
206
|
The compound parts import from `c15t/react` as properties of `ConsentWidget`.
|
|
162
|
-
See [
|
|
207
|
+
See [customize](../customize.md) for slots and tokens.
|
|
163
208
|
|
|
164
209
|
## Verify
|
|
165
210
|
|