@c15t/react 3.0.0-alpha.3 → 3.0.0-alpha.4
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 +91 -72
- package/README.md +21 -17
- package/SKILL.md +34 -0
- package/dist/component-hooks/use-headless-consent-ui.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -1
- package/dist/components/consent-gate/consent-gate.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/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/root.js +1 -1
- package/dist/components/panel-trigger/atoms/button.js +1 -1
- package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
- package/dist/components/preferences/atoms/accordion.js +1 -1
- 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/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/ui/dialog/dialog.js +1 -1
- package/dist/components/shared/ui/icon.js +1 -1
- package/dist/context/consent-tracking-context.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/draft.js +1 -1
- package/dist/hooks/use-focus-trap.js +1 -1
- package/dist/hooks.js +1 -1
- package/dist/iab/styles.tw3.css +4 -4
- package/dist/index.js +1 -1
- package/dist/module-hooks/iframe-blocker.js +1 -1
- package/dist/postcss-tailwind3.js +1 -0
- 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 +16 -16
- package/dist/transports/offline.js +1 -1
- package/dist/ui-save.js +1 -1
- 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/component-hooks/use-headless-consent-ui.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
- package/dist-types/components/iab-panel/iab-panel.d.ts +2 -2
- package/dist-types/components/iab-panel/index.d.ts +5 -2
- package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +2 -2
- package/dist-types/components/iab-prompt/index.d.ts +2 -2
- package/dist-types/components/panel/atoms/card.d.ts +1 -0
- package/dist-types/components/prompt/components.d.ts +6 -0
- package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
- package/dist-types/components/shared/ui/icon.d.ts +2 -1
- package/dist-types/context/consent-tracking-context.d.ts +10 -0
- package/dist-types/context/theme-context.d.ts +2 -2
- package/dist-types/context.d.ts +6 -0
- package/dist-types/devtools.d.ts +13 -2
- package/dist-types/draft.d.ts +10 -4
- package/dist-types/hooks/use-focus-trap.d.ts +3 -1
- package/dist-types/hooks.d.ts +54 -13
- package/dist-types/iab.d.ts +1 -1
- package/dist-types/index.d.ts +2 -2
- package/dist-types/postcss-tailwind3.d.ts +21 -0
- package/dist-types/provider.d.ts +22 -5
- package/dist-types/server/headers.d.ts +14 -4
- package/dist-types/server/normalize-url.d.ts +14 -7
- package/dist-types/server/types.d.ts +12 -1
- package/dist-types/transports/offline.d.ts +7 -16
- package/dist-types/ui-config-context.d.ts +7 -1
- package/dist-types/utils/merge-slot-props.d.ts +15 -1
- package/dist-types/utils/theme-utils.d.ts +17 -2
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +91 -72
- 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 +87 -0
- package/docs/{frameworks/react/concepts → concepts}/consent-categories.md +22 -7
- package/docs/{guides → concepts}/consent-state.md +71 -101
- package/docs/{guides → concepts}/data-fetching.md +31 -27
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +7 -59
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +119 -0
- package/docs/customization/overview.md +67 -34
- package/docs/customization/recipes.md +839 -49
- package/docs/customization/slots.md +216 -35
- package/docs/customization/stylesheets.md +147 -0
- package/docs/customization/tailwind.md +842 -0
- package/docs/customization/tokens.md +163 -96
- package/docs/customization/translations.md +61 -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 +42 -28
- package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
- package/docs/frameworks/react/components/consent-dialog-trigger.md +81 -76
- package/docs/frameworks/react/components/consent-dialog.md +56 -50
- package/docs/frameworks/react/components/consent-gate.md +37 -20
- package/docs/frameworks/react/components/consent-provider.md +126 -0
- package/docs/frameworks/react/components/consent-widget.md +23 -20
- package/docs/frameworks/react/components/dev-tools.md +52 -84
- package/docs/frameworks/react/components.md +105 -0
- package/docs/frameworks/react/compose.md +354 -0
- package/docs/frameworks/react/content-security-policy.md +126 -0
- package/docs/frameworks/react/customize.md +250 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/{hooks/overview.md → hooks.md} +21 -16
- package/docs/frameworks/react/{iab/overview.md → iab.md} +80 -31
- package/docs/frameworks/react/network-blocker.md +35 -41
- package/docs/frameworks/react/quickstart.md +139 -101
- package/docs/frameworks/react/rendering.md +128 -0
- package/docs/frameworks/react/scripts.md +115 -0
- package/docs/frameworks/react/translations.md +155 -0
- package/docs/frameworks/react/troubleshooting.md +92 -47
- package/docs/frameworks/react/vendor-consent.md +170 -0
- package/docs/guides/banner-experiments.md +654 -0
- package/docs/guides/troubleshooting.md +120 -47
- package/docs/guides/verify-consent.md +81 -49
- package/docs/integrations/adobe-analytics.md +167 -159
- package/docs/integrations/ahrefs-analytics.md +152 -154
- package/docs/integrations/amplitude.md +162 -156
- package/docs/integrations/building-integrations.md +136 -37
- package/docs/integrations/clearbit.md +154 -154
- package/docs/integrations/cloudflare-web-analytics.md +156 -156
- package/docs/integrations/cloudflare-zaraz.md +209 -261
- package/docs/integrations/crisp.md +164 -158
- package/docs/integrations/databuddy.md +157 -173
- package/docs/integrations/fathom-analytics.md +158 -156
- package/docs/integrations/front-chat.md +167 -167
- package/docs/integrations/google-maps.md +118 -83
- package/docs/integrations/google-tag-manager.md +178 -163
- package/docs/integrations/google-tag.md +163 -160
- package/docs/integrations/heap.md +163 -155
- package/docs/integrations/hightouch.md +161 -157
- package/docs/integrations/hotjar.md +159 -155
- package/docs/integrations/intercom.md +183 -153
- package/docs/integrations/klaviyo.md +486 -0
- package/docs/integrations/linkedin-insights.md +174 -150
- package/docs/integrations/logrocket.md +160 -156
- package/docs/integrations/matomo-analytics.md +188 -178
- package/docs/integrations/meta-pixel.md +188 -150
- package/docs/integrations/microsoft-clarity.md +163 -155
- package/docs/integrations/microsoft-uet.md +148 -154
- package/docs/integrations/mixpanel-analytics.md +155 -160
- package/docs/integrations/one-dollar-stats.md +166 -165
- package/docs/integrations/openai-pixel.md +204 -301
- package/docs/integrations/overview.md +137 -80
- package/docs/integrations/pinterest-tag.md +191 -183
- package/docs/integrations/pirsch.md +169 -159
- package/docs/integrations/plausible-analytics.md +172 -158
- package/docs/integrations/posthog.md +226 -241
- package/docs/integrations/promptwatch.md +154 -154
- package/docs/integrations/reddit-pixel.md +185 -157
- package/docs/integrations/rudderstack.md +201 -186
- package/docs/integrations/rybbit-analytics.md +171 -160
- package/docs/integrations/segment.md +182 -154
- package/docs/integrations/snapchat-pixel.md +186 -156
- package/docs/integrations/tiktok-pixel.md +171 -150
- package/docs/integrations/umami-analytics.md +163 -158
- package/docs/integrations/vercel-analytics.md +166 -157
- package/docs/integrations/x-pixel.md +176 -150
- package/docs/integrations/youtube.md +121 -86
- package/docs/upgrade-v3.md +475 -467
- package/package.json +15 -9
- 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 -95
- package/docs/frameworks/react/script-loader.md +0 -69
- package/docs/frameworks/react/styling/overview.md +0 -266
- package/docs/guides/deployment-modes.md +0 -75
- package/docs/guides/shared-consent-controls.md +0 -158
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/integrations/granular-consent.md +0 -210
|
@@ -0,0 +1,126 @@
|
|
|
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 {
|
|
18
|
+
ConsentBanner,
|
|
19
|
+
ConsentDialog,
|
|
20
|
+
ConsentDialogLink,
|
|
21
|
+
ConsentProvider,
|
|
22
|
+
hosted,
|
|
23
|
+
} from 'c15t/react';
|
|
24
|
+
import type { ReactNode } from 'react';
|
|
25
|
+
|
|
26
|
+
import { scripts } from './scripts';
|
|
27
|
+
|
|
28
|
+
import 'c15t/react/styles.css';
|
|
29
|
+
|
|
30
|
+
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
31
|
+
|
|
32
|
+
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
33
|
+
<ConsentProvider options={{ mode, scripts }}>
|
|
34
|
+
{children}
|
|
35
|
+
<ConsentBanner />
|
|
36
|
+
<ConsentDialog />
|
|
37
|
+
<footer>
|
|
38
|
+
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
39
|
+
</footer>
|
|
40
|
+
</ConsentProvider>
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`hosted({ url })` points the provider at your Inth backend. Replace
|
|
45
|
+
`https://your-project.inth.app` with the URL from your Inth project. The
|
|
46
|
+
Next.js and TanStack Start adapters export `ConsentRoot` instead, which wraps
|
|
47
|
+
this provider and passes it server-resolved state.
|
|
48
|
+
|
|
49
|
+
## Provider options
|
|
50
|
+
|
|
51
|
+
Keep the provider mounted across client navigation. It reads `mode`,
|
|
52
|
+
`prefetch`, `persistence`, `clearOnRevocation` and the module options once,
|
|
53
|
+
when it mounts. Remount the provider to change them.
|
|
54
|
+
|
|
55
|
+
| Option | Purpose |
|
|
56
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `mode` | Required. `hosted({ url })` for a backend, `offline()` for local policies, or `custom()` for your own transport |
|
|
58
|
+
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper |
|
|
59
|
+
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md) |
|
|
60
|
+
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md) |
|
|
61
|
+
| `scriptLoader` | Options for the script loader module |
|
|
62
|
+
| `networkBlocker` | Rules that hold `fetch` and `XMLHttpRequest` calls until their category is allowed, or `false` |
|
|
63
|
+
| `iframeBlocker` | Gates DOM iframes that carry `data-category`. On by default; `false` turns it off |
|
|
64
|
+
| `persistence` | Stores the visitor's choice in a cookie and localStorage. On by default |
|
|
65
|
+
| `storageConfig` | Storage key and cookie settings for the stored choice |
|
|
66
|
+
| `clearOnRevocation` | Cookies and storage keys to delete when a category is denied |
|
|
67
|
+
| `reloadOnConsentRevoked` | Reload the page after the visitor turns off a granted category or vendor. Defaults to `true` |
|
|
68
|
+
| `consentCategories` | Categories the preference dialog offers alongside those your scripts use, within the policy's scope |
|
|
69
|
+
| `overrides` | Force the country, region or language the policy is resolved for, for testing |
|
|
70
|
+
| `user` | Link consent records to a signed-in user |
|
|
71
|
+
| `callbacks` | Choice, permission and error events |
|
|
72
|
+
| `i18n` | Languages and message overrides |
|
|
73
|
+
| `legalLinks` | Privacy policy and other links shown in the banner and dialog |
|
|
74
|
+
| `theme` | `consentActions` and slot styles. Tokens go through `ConsentTheme`; see [customize](../customize.md) |
|
|
75
|
+
| `components` | Slot attributes per component part |
|
|
76
|
+
| `presentation` | Banner and dialog shape, position and blocking |
|
|
77
|
+
| `experiment` | A/B test of `presentation`, read once at mount. See [banner experiments](../../../guides/banner-experiments.md) |
|
|
78
|
+
| `colorScheme` | `'light'`, `'dark'`, `'system'`, or `null` to leave the `c15t-dark` class alone |
|
|
79
|
+
| `noStyle`, `disableAnimation` | Drop the built-in styles, or turn off animations |
|
|
80
|
+
| `preloadDialog` | When the deferred `ConsentDialog` starts loading: `'idle'` (default) or `'intent'`; see [ConsentDialog](./consent-dialog.md#behavior) |
|
|
81
|
+
| `nonce` | Content Security Policy nonce for script elements c15t inserts |
|
|
82
|
+
| `enabled` | Set `false` only when you deliberately bypass consent enforcement |
|
|
83
|
+
|
|
84
|
+
`enabled: false` grants categories and allows gated loading while suppressing
|
|
85
|
+
consent UI. It is not a way to fix failed initialization or hide a banner in
|
|
86
|
+
production.
|
|
87
|
+
|
|
88
|
+
## Observe changes without inventing choices
|
|
89
|
+
|
|
90
|
+
`onChoiceRecorded` reports explicit accept, reject and save actions.
|
|
91
|
+
`onPermissionsChanged` also covers changes caused by policy, expiry or privacy
|
|
92
|
+
signals. Hydration and notice dismissal do not become explicit choices.
|
|
93
|
+
|
|
94
|
+
An externally owned runtime can be passed through `runtime`. Its owner must
|
|
95
|
+
start and dispose it. A provider borrowing that runtime must not initialize or
|
|
96
|
+
dispose a second copy. Passing a different `runtime` moves the provider and its
|
|
97
|
+
hooks to the new runtime's kernel and unsubscribes them from the previous one.
|
|
98
|
+
The previous runtime keeps running until its owner disposes it. Switch the
|
|
99
|
+
provider to another runtime, or unmount it, before disposing the runtime it
|
|
100
|
+
renders. Changing between a borrowed runtime and a provider-created one still
|
|
101
|
+
requires remounting the provider. IAB actions taken before its handle is ready
|
|
102
|
+
wait for that handle. If the provider unmounts or switches runtimes first, a
|
|
103
|
+
pending `save()` rejects with an `AbortError` instead of waiting indefinitely.
|
|
104
|
+
See [how consent works](../../../concepts/how-consent-works.md#a-permission-is-not-a-recorded-choice) and
|
|
105
|
+
[choose your setup](../../../concepts/choose-your-setup.md).
|
|
106
|
+
|
|
107
|
+
## Reload after revocation
|
|
108
|
+
|
|
109
|
+
Removing a script cannot stop code that already ran. A vendor's listeners,
|
|
110
|
+
timers and widgets keep working until the page unloads. When an accept, reject
|
|
111
|
+
or save turns off a category or vendor that was granted, the provider reloads
|
|
112
|
+
the page once the save request settles, so the next page runs only permitted
|
|
113
|
+
code. `onBeforeConsentRevocationReload` runs just before the reload.
|
|
114
|
+
|
|
115
|
+
Otherwise, expiry, policy changes and privacy signals do not reload the page. Set
|
|
116
|
+
`reloadOnConsentRevoked: false` only when every gated vendor stops itself on
|
|
117
|
+
revocation, for example through its own opt-out API.
|
|
118
|
+
|
|
119
|
+
## Clear data when consent is denied
|
|
120
|
+
|
|
121
|
+
Set `options.clearOnRevocation` to declare cookies, localStorage keys, and
|
|
122
|
+
sessionStorage keys by optional consent category. Cleanup waits for policy
|
|
123
|
+
resolution, then clears denied categories and later allowed-to-denied
|
|
124
|
+
transitions. This option is initial-only. See
|
|
125
|
+
[clear on revocation](../clear-on-revocation.md) for examples,
|
|
126
|
+
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.
|
|
@@ -102,18 +105,18 @@ only; the category stays granted and its other vendors keep loading. While
|
|
|
102
105
|
the category is off in the draft the vendor switches are disabled, with the
|
|
103
106
|
hint "Turn on this category to choose vendors." A vendor declared
|
|
104
107
|
`disabled`, or one that only falls under `necessary`, is listed without a
|
|
105
|
-
switch. Accept
|
|
108
|
+
switch. Accept All and Reject All clear every vendor denial, including one
|
|
106
109
|
staged but not yet saved. Under an `iab` policy no vendor rows render.
|
|
107
110
|
Vendors that are only referenced by a script slug, without a name and
|
|
108
111
|
privacy policy URL, still gate loading but are not listed, and so does a
|
|
109
112
|
vendor whose condition negates a category, since no category row can
|
|
110
113
|
host it. See
|
|
111
|
-
[
|
|
114
|
+
[vendor consent](../vendor-consent.md).
|
|
112
115
|
|
|
113
116
|
### Actions
|
|
114
117
|
|
|
115
|
-
The preference center always renders Reject
|
|
116
|
-
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`,
|
|
117
120
|
`primaryActions`, `direction` and `uiProfile` in the provider options
|
|
118
121
|
reorder and restyle them; a layout that omits one of the three has it
|
|
119
122
|
restored. Customize and dismiss actions never render here.
|
|
@@ -201,7 +204,7 @@ it. `c15t/react/components/consent-widget` exports the widget without that
|
|
|
201
204
|
deferral, plus each part as a named export.
|
|
202
205
|
|
|
203
206
|
The compound parts import from `c15t/react` as properties of `ConsentWidget`.
|
|
204
|
-
See [
|
|
207
|
+
See [customize](../customize.md) for slots and tokens.
|
|
205
208
|
|
|
206
209
|
## Verify
|
|
207
210
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: DevTools
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Inspect consent state, location, loaded scripts and consent events
|
|
4
|
+
in a React app during development with the c15t DevTools panel.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -12,42 +12,44 @@ group: frameworks
|
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
|
-
No extra package is required
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
when you need the imperative `createDevTools({ kernel })` API.
|
|
15
|
+
No extra package is required. The React adapter and its engine are included
|
|
16
|
+
with the `c15t` package. Install `@c15t/dev-tools` directly only when you
|
|
17
|
+
need the imperative `createDevTools({ kernel })` API.
|
|
19
18
|
|
|
20
|
-
##
|
|
19
|
+
## Render DevTools in development builds
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
Render `DevTools` inside `ConsentProvider`. This example loads it only in
|
|
22
|
+
development with Vite's `import.meta.env.DEV` flag, so production bundles never
|
|
23
|
+
download it. For another bundler, use its development flag instead; for
|
|
24
|
+
example, webpack projects can use a configured
|
|
25
|
+
`process.env.NODE_ENV === 'development'` replacement, since `process` is not a
|
|
26
|
+
browser global.
|
|
26
27
|
|
|
27
|
-
```tsx
|
|
28
|
-
import { lazy, Suspense
|
|
29
|
-
import { ConsentProvider, hosted } from 'c15t/react';
|
|
30
|
-
|
|
31
|
-
const DevTools =
|
|
32
|
-
import.meta.env.DEV
|
|
33
|
-
? lazy(() =>
|
|
34
|
-
import('c15t/react/devtools').then(({ DevTools }) => ({ default: DevTools })),
|
|
35
|
-
)
|
|
36
|
-
: () => null;
|
|
28
|
+
```tsx title="src/consent-devtools.tsx"
|
|
29
|
+
import { lazy, Suspense } from 'react';
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
const DevTools = import.meta.env.DEV
|
|
32
|
+
? lazy(() =>
|
|
33
|
+
import('c15t/react/devtools').then(({ DevTools }) => ({
|
|
34
|
+
default: DevTools,
|
|
35
|
+
}))
|
|
36
|
+
)
|
|
37
|
+
: null;
|
|
38
|
+
|
|
39
|
+
export function ConsentDevTools() {
|
|
40
|
+
return DevTools ? (
|
|
41
|
+
<Suspense fallback={null}>
|
|
42
|
+
<DevTools />
|
|
43
|
+
</Suspense>
|
|
44
|
+
) : null;
|
|
47
45
|
}
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
|
|
48
|
+
Render `<ConsentDevTools />` inside the provider from your
|
|
49
|
+
[quickstart](../quickstart.md), next to the banner. Import the
|
|
50
|
+
component from `c15t/react/devtools` when you installed the `c15t` package, or
|
|
51
|
+
from `@c15t/react/devtools` when you installed `@c15t/react` directly.
|
|
52
|
+
`@c15t/dev-tools` exports the imperative engine, not the React component.
|
|
51
53
|
|
|
52
54
|
If the CLI cannot identify your bundler's development flag, it generates
|
|
53
55
|
`const DevTools = false` with a setup comment. Replace `false` with your
|
|
@@ -69,14 +71,16 @@ DevTools disabled instead of assuming browser globals or loading it in productio
|
|
|
69
71
|
`position` accepts any corner: `top-left`, `top-right`, `bottom-left`, or
|
|
70
72
|
`bottom-right`. Set `defaultOpen` to open the initial panel and `defaultTab`
|
|
71
73
|
to choose that panel. `maxEvents` limits captured kernel and script events.
|
|
72
|
-
Set `disabled` to prevent mounting without removing the component.
|
|
74
|
+
Set `disabled` to prevent mounting without removing the component. The
|
|
75
|
+
panel renders inside a shadow root by default, so page CSS does not reach
|
|
76
|
+
it. `shadow={false}` mounts it in the light DOM with its stylesheet in
|
|
77
|
+
`<head>`.
|
|
73
78
|
|
|
74
79
|
## Panels
|
|
75
80
|
|
|
76
81
|
Accept and reject apply only to categories displayed by the provider, leaving
|
|
77
|
-
hidden consent values unchanged. `necessary` always remains enabled.
|
|
78
|
-
|
|
79
|
-
React adapter use the current policy categories by default.
|
|
82
|
+
hidden consent values unchanged. `necessary` always remains enabled. The
|
|
83
|
+
React adapter uses the current policy categories by default.
|
|
80
84
|
|
|
81
85
|
For an imperative integration with a narrower UI, pass
|
|
82
86
|
`getConsentCategories: () => ['necessary', 'measurement']` to
|
|
@@ -168,55 +172,6 @@ For custom inspection tools, `getIABControls(kernel)` and
|
|
|
168
172
|
The getter returns undefined before module initialization and after disposal.
|
|
169
173
|
A snapshot without an attached IAB module is read-only in DevTools.
|
|
170
174
|
|
|
171
|
-
## Vue and Svelte
|
|
172
|
-
|
|
173
|
-
Vue imports `ConsentDevTools` from `c15t/vue/devtools`.
|
|
174
|
-
Render it in the app where the c15t plugin provides
|
|
175
|
-
the kernel. In Nuxt, the configured c15t module provides that context.
|
|
176
|
-
|
|
177
|
-
```vue
|
|
178
|
-
<script setup lang="ts">
|
|
179
|
-
import { defineAsyncComponent } from 'vue';
|
|
180
|
-
|
|
181
|
-
const DevTools = import.meta.env.DEV
|
|
182
|
-
? defineAsyncComponent(() => import('c15t/vue/devtools'))
|
|
183
|
-
: null;
|
|
184
|
-
</script>
|
|
185
|
-
|
|
186
|
-
<template>
|
|
187
|
-
<DevTools v-if="DevTools" position="bottom-right" />
|
|
188
|
-
</template>
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
In Nuxt, use `import.meta.dev` instead of `import.meta.env.DEV`.
|
|
192
|
-
Svelte imports the adapter from `@c15t/svelte/devtools` and renders it
|
|
193
|
-
inside `ConsentManagerProvider`.
|
|
194
|
-
|
|
195
|
-
```svelte
|
|
196
|
-
<script lang="ts">
|
|
197
|
-
import { ConsentManagerProvider, offline } from '@c15t/svelte';
|
|
198
|
-
|
|
199
|
-
const devTools = import.meta.env.DEV
|
|
200
|
-
? import('@c15t/svelte/devtools')
|
|
201
|
-
: null;
|
|
202
|
-
</script>
|
|
203
|
-
|
|
204
|
-
<ConsentManagerProvider options={{ mode: offline() }}>
|
|
205
|
-
{#if devTools}
|
|
206
|
-
{#await devTools then { ConsentDevTools }}
|
|
207
|
-
<ConsentDevTools position="bottom-right" />
|
|
208
|
-
{/await}
|
|
209
|
-
{/if}
|
|
210
|
-
</ConsentManagerProvider>
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
Both adapters accept `position`, `defaultOpen`, `defaultTab`, `maxEvents`,
|
|
214
|
-
`shadow` (`false` renders into the page instead of a shadow root),
|
|
215
|
-
and `getConsentCategories`. Changing these presentation options recreates
|
|
216
|
-
the panel and clears its event history. They do not accept React's `disabled`
|
|
217
|
-
prop; conditionally render them instead. Unmounting removes the panel and
|
|
218
|
-
subscriptions without changing consent.
|
|
219
|
-
|
|
220
175
|
## TanStack Devtools
|
|
221
176
|
|
|
222
177
|
Each embedded panel owns its event history and subscriptions. Unmounting it
|
|
@@ -257,6 +212,19 @@ export function AppDevtools() {
|
|
|
257
212
|
|
|
258
213
|
In a Next.js app, import `c15tDevtools` from `c15t/next/devtools` instead. Scoped installs use `@c15t/react/devtools` and `@c15t/nextjs/devtools`.
|
|
259
214
|
|
|
215
|
+
The c15t panel follows the TanStack Devtools light or dark theme, not your app's consent theme. If you write the plugin entry yourself, use a render function and pass the theme to `C15tTanStackDevtoolsPanel`:
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
import { C15tTanStackDevtoolsPanel } from 'c15t/react/devtools';
|
|
219
|
+
|
|
220
|
+
const c15tPlugin = {
|
|
221
|
+
name: 'Consent',
|
|
222
|
+
render: (_element: HTMLElement, { theme }: { theme: 'light' | 'dark' }) => (
|
|
223
|
+
<C15tTanStackDevtoolsPanel theme={theme} />
|
|
224
|
+
),
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
260
228
|
## Props
|
|
261
229
|
|
|
262
230
|
| Property | Type | Description | Default | Required |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Components
|
|
3
|
+
description: Every c15t component a React app imports from c15t/react, what each
|
|
4
|
+
renders, where each one mounts, and which to start with.
|
|
5
|
+
group: frameworks
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Component reference
|
|
9
|
+
|
|
10
|
+
`c15t/react` exports the provider, the consent UI and the hooks from one
|
|
11
|
+
import path. Every component except `ConsentProvider` and `ConsentTheme`
|
|
12
|
+
reads the runtime the provider creates, so render them inside
|
|
13
|
+
`ConsentProvider`.
|
|
14
|
+
|
|
15
|
+
| Component | Renders | Reference |
|
|
16
|
+
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
17
|
+
| `ConsentProvider` | The consent runtime, which loads the policy, stores the choice and loads scripts. No markup of its own | [ConsentProvider](./components/consent-provider.md) |
|
|
18
|
+
| `ConsentBanner` | The banner, when the visitor's policy asks for one | [ConsentBanner](./components/consent-banner.md) |
|
|
19
|
+
| `ConsentDialog` | The preference center as a modal | [ConsentDialog](./components/consent-dialog.md) |
|
|
20
|
+
| `ConsentWidget` | The preference center inline in a page, for a privacy route | [ConsentWidget](./components/consent-widget.md) |
|
|
21
|
+
| `ConsentDialogLink` | An unstyled button that opens the dialog, for your footer | [ConsentDialogLink](./components/consent-dialog-link.md) |
|
|
22
|
+
| `ConsentDialogTrigger` | A floating, draggable button that opens the dialog. `ConsentDialogTriggerToolbar` adds your own actions beside it | [ConsentDialogTrigger](./components/consent-dialog-trigger.md) |
|
|
23
|
+
| `ConsentGate` | Its children while a category is allowed, a placeholder otherwise | [ConsentGate](./components/consent-gate.md) |
|
|
24
|
+
| `ConsentTheme` | A `<style>` element with your theme tokens | [Customize](./customize.md) |
|
|
25
|
+
| `DevTools` from `c15t/react/devtools` | A development panel for consent state, scripts and events | [DevTools](./components/dev-tools.md) |
|
|
26
|
+
|
|
27
|
+
Mount one `ConsentProvider` at the root of the app and keep it mounted across
|
|
28
|
+
client navigation. The provider reads `mode` and its module options once,
|
|
29
|
+
when it mounts.
|
|
30
|
+
|
|
31
|
+
## Start with the provider, banner and dialog
|
|
32
|
+
|
|
33
|
+
Most apps start with four components. `ConsentProvider` holds the runtime,
|
|
34
|
+
`ConsentBanner` and `ConsentDialog` ask for a choice, and a
|
|
35
|
+
`ConsentDialogLink` lets visitors reopen their preferences. The [quickstart](./quickstart.md) puts them in
|
|
36
|
+
one file:
|
|
37
|
+
|
|
38
|
+
```tsx title="src/consent.tsx"
|
|
39
|
+
import {
|
|
40
|
+
ConsentBanner,
|
|
41
|
+
ConsentDialog,
|
|
42
|
+
ConsentDialogLink,
|
|
43
|
+
ConsentProvider,
|
|
44
|
+
hosted,
|
|
45
|
+
} from 'c15t/react';
|
|
46
|
+
import type { ReactNode } from 'react';
|
|
47
|
+
|
|
48
|
+
import { scripts } from './scripts';
|
|
49
|
+
|
|
50
|
+
import 'c15t/react/styles.css';
|
|
51
|
+
|
|
52
|
+
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
53
|
+
|
|
54
|
+
export const Consent = ({ children }: { children: ReactNode }) => (
|
|
55
|
+
<ConsentProvider options={{ mode, scripts }}>
|
|
56
|
+
{children}
|
|
57
|
+
<ConsentBanner />
|
|
58
|
+
<ConsentDialog />
|
|
59
|
+
<footer>
|
|
60
|
+
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
61
|
+
</footer>
|
|
62
|
+
</ConsentProvider>
|
|
63
|
+
);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Add `ConsentWidget`, `ConsentDialogTrigger` or `ConsentGate` later, where a
|
|
67
|
+
page needs them. Keep `ConsentDialog` mounted even when you add a widget,
|
|
68
|
+
because the banner's Customize button and every dialog link open it.
|
|
69
|
+
|
|
70
|
+
## Server-rendered React apps
|
|
71
|
+
|
|
72
|
+
React Router framework mode, Remix and other server-rendered React apps use the
|
|
73
|
+
same components. `ConsentProvider` renders on the server without touching
|
|
74
|
+
browser APIs, and the banner mounts after hydration, once the browser has
|
|
75
|
+
resolved the policy. [Rendering](./rendering.md#react-router-remix-and-other-server-rendered-apps)
|
|
76
|
+
explains the trade-off.
|
|
77
|
+
|
|
78
|
+
## IAB TCF components
|
|
79
|
+
|
|
80
|
+
Import `IABProvider`, `IABConsentBanner` and `IABConsentDialog` from
|
|
81
|
+
`c15t/react/iab`, render them inside `ConsentProvider` next to
|
|
82
|
+
`ConsentBanner` and `ConsentDialog`, and load `c15t/react/iab/styles.css`. The stock banner and dialog stay closed
|
|
83
|
+
under an IAB policy. See
|
|
84
|
+
[IAB TCF](./iab.md).
|
|
85
|
+
|
|
86
|
+
## Other entry points
|
|
87
|
+
|
|
88
|
+
| Import | Exports | Use |
|
|
89
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| `c15t/react/consent-banner`, `c15t/react/consent-dialog`, `c15t/react/consent-widget`, `c15t/react/consent-dialog-link`, `c15t/react/consent-dialog-trigger`, `c15t/react/consent-gate` | One component each | A module that needs one component without the rest of the adapter |
|
|
91
|
+
| `c15t/react/headless` | Headless hooks | Your own banner and dialog markup. See [headless](./headless.md) |
|
|
92
|
+
| `c15t/react/server` | `fetchSSRData` and its helpers | Resolve `/init` in a server loader. See [rendering](./rendering.md#skip-the-browsers-first-init-request) |
|
|
93
|
+
| `c15t/react/devtools` | `DevTools` | Development only |
|
|
94
|
+
|
|
95
|
+
## Check the components
|
|
96
|
+
|
|
97
|
+
Load the app in a private window under a policy that asks for a choice:
|
|
98
|
+
|
|
99
|
+
1. The banner shows, and DevTools Network has no requests to your vendors'
|
|
100
|
+
hosts.
|
|
101
|
+
2. Click the footer's `ConsentDialogLink`. The dialog opens with every optional
|
|
102
|
+
category off.
|
|
103
|
+
3. Allow one category and save. Its vendor requests appear, and a
|
|
104
|
+
`ConsentGate` for that category mounts its children.
|
|
105
|
+
4. Reload. The banner stays closed, and the link still reopens the dialog.
|