@c15t/nextjs 2.0.0-rc.0 → 2.0.0-rc.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.
Files changed (98) hide show
  1. package/README.md +10 -3
  2. package/client/components/consent-dialog-link.js +3 -0
  3. package/dist/headless.cjs +1 -1
  4. package/dist/iab/styles.css +12 -0
  5. package/dist/iab/styles.tw3.css +14 -0
  6. package/dist/index.cjs +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/libs/browser-initial-data.cjs +1 -0
  9. package/dist/libs/browser-initial-data.js +1 -0
  10. package/dist/libs/initial-data.cjs +1 -1
  11. package/dist/libs/initial-data.js +1 -1
  12. package/dist/styles.css +10 -0
  13. package/dist/styles.tw3.css +13 -0
  14. package/dist/types.cjs +1 -1
  15. package/dist/version.cjs +1 -1
  16. package/dist/version.js +1 -1
  17. package/{dist → dist-types}/headless.d.ts +0 -1
  18. package/{dist → dist-types}/index.d.ts +3 -2
  19. package/dist-types/libs/browser-initial-data.d.ts +9 -0
  20. package/{dist → dist-types}/libs/initial-data.d.ts +7 -2
  21. package/dist-types/types.d.ts +38 -0
  22. package/dist-types/version.d.ts +1 -0
  23. package/docs/README.md +73 -0
  24. package/docs/building-headless-components.md +377 -0
  25. package/docs/callbacks.md +184 -0
  26. package/docs/components/consent-banner.md +269 -0
  27. package/docs/components/consent-dialog-link.md +59 -0
  28. package/docs/components/consent-dialog-trigger.md +103 -0
  29. package/docs/components/consent-dialog.md +177 -0
  30. package/docs/components/consent-manager-provider.md +425 -0
  31. package/docs/components/consent-widget.md +133 -0
  32. package/docs/components/dev-tools.md +63 -0
  33. package/docs/components/frame.md +73 -0
  34. package/docs/concepts/client-modes.md +175 -0
  35. package/docs/concepts/consent-categories.md +97 -0
  36. package/docs/concepts/consent-models.md +116 -0
  37. package/docs/concepts/cookie-management.md +122 -0
  38. package/docs/concepts/glossary.md +23 -0
  39. package/docs/concepts/initialization-flow.md +148 -0
  40. package/docs/concepts/policy-packs.md +229 -0
  41. package/docs/headless.md +190 -0
  42. package/docs/hooks/use-color-scheme.md +40 -0
  43. package/docs/hooks/use-consent-manager/checking-consent.md +94 -0
  44. package/docs/hooks/use-consent-manager/location-info.md +95 -0
  45. package/docs/hooks/use-consent-manager/overview.md +420 -0
  46. package/docs/hooks/use-consent-manager/setting-consent.md +92 -0
  47. package/docs/hooks/use-draggable.md +57 -0
  48. package/docs/hooks/use-focus-trap.md +41 -0
  49. package/docs/hooks/use-reduced-motion.md +35 -0
  50. package/docs/hooks/use-ssr-status.md +31 -0
  51. package/docs/hooks/use-text-direction.md +49 -0
  52. package/docs/hooks/use-translations.md +118 -0
  53. package/docs/iab/consent-banner.md +94 -0
  54. package/docs/iab/consent-dialog.md +134 -0
  55. package/docs/iab/overview.md +126 -0
  56. package/docs/iab/use-gvl-data.md +20 -0
  57. package/docs/iframe-blocking.md +107 -0
  58. package/docs/integrations/building-integrations.md +405 -0
  59. package/docs/integrations/databuddy.md +203 -0
  60. package/docs/integrations/google-tag-manager.md +153 -0
  61. package/docs/integrations/google-tag.md +122 -0
  62. package/docs/integrations/linkedin-insights.md +109 -0
  63. package/docs/integrations/meta-pixel.md +342 -0
  64. package/docs/integrations/microsoft-uet.md +112 -0
  65. package/docs/integrations/overview.md +105 -0
  66. package/docs/integrations/posthog.md +199 -0
  67. package/docs/integrations/tiktok-pixel.md +113 -0
  68. package/docs/integrations/x-pixel.md +143 -0
  69. package/docs/internationalization.md +197 -0
  70. package/docs/network-blocker.md +178 -0
  71. package/docs/optimization.md +234 -0
  72. package/docs/policy-packs.md +246 -0
  73. package/docs/quickstart.md +161 -0
  74. package/docs/script-loader.md +321 -0
  75. package/docs/server-side.md +176 -0
  76. package/docs/styling/classnames.md +92 -0
  77. package/docs/styling/color-scheme.md +82 -0
  78. package/docs/styling/css-variables.md +92 -0
  79. package/docs/styling/overview.md +456 -0
  80. package/docs/styling/slots.md +127 -0
  81. package/docs/styling/tailwind.md +113 -0
  82. package/docs/styling/tokens.md +216 -0
  83. package/docs/troubleshooting.md +146 -0
  84. package/iab/styles.css +1 -0
  85. package/package.json +38 -17
  86. package/readme.json +4 -0
  87. package/src/iab/styles.css +12 -0
  88. package/src/iab/styles.tw3.css +14 -0
  89. package/src/styles.css +10 -0
  90. package/src/styles.tw3.css +13 -0
  91. package/styles.css +1 -0
  92. package/dist/headless.d.ts.map +0 -1
  93. package/dist/index.d.ts.map +0 -1
  94. package/dist/libs/initial-data.d.ts.map +0 -1
  95. package/dist/types.d.ts +0 -16
  96. package/dist/types.d.ts.map +0 -1
  97. package/dist/version.d.ts +0 -2
  98. package/dist/version.d.ts.map +0 -1
@@ -0,0 +1,425 @@
1
+ ---
2
+ title: ConsentManagerProvider
3
+ description: The root provider component that initializes the consent system and makes consent state available to all child components.
4
+ ---
5
+ `ConsentManagerProvider` is the root component for the c15t consent system. It initializes the consent store, detects the user's jurisdiction, resolves translations, and provides consent state to all child components via React context.
6
+
7
+ Every other c15t component and hook must be rendered inside this provider.
8
+
9
+ ## Basic Usage
10
+
11
+ ```tsx
12
+ import { type ReactNode } from 'react';
13
+ import { ConsentManagerProvider, ConsentBanner, ConsentDialog } from '@c15t/nextjs';
14
+
15
+ export default function ConsentManager({ children }: { children: ReactNode }) {
16
+ return (
17
+ <ConsentManagerProvider
18
+ options={{
19
+ mode: 'hosted',
20
+ backendURL: '/api/c15t',
21
+ consentCategories: ['necessary', 'measurement', 'marketing'],
22
+ }}
23
+ >
24
+ <ConsentBanner />
25
+ <ConsentDialog />
26
+ {children}
27
+ </ConsentManagerProvider>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## Options Reference
33
+
34
+ ### CommonInlineStoreOptions
35
+
36
+ |Property|Type|Description|Default|Required|
37
+ |:--|:--|:--|:--|:--:|
38
+ |enabled|boolean \|undefined|Whether c15t should be active.|true|Optional|
39
+ |callbacks|[Callbacks \|undefined](https://v2.c15t.com/docs/frameworks/react/callbacks)|Event callbacks for consent actions.|-|Optional|
40
+ |scripts|[Script \|undefined](https://v2.c15t.com/docs/frameworks/react/script-loader)|Dynamically load scripts based on consent state.|-|Optional|
41
+ |legalLinks|Object \|undefined|Configuration for the legal links.|-|Optional|
42
+ |storageConfig|StorageConfig \|undefined|Storage configuration for consent persistence.|-|Optional|
43
+ |user|User \|undefined|The user's information. Usually your own internal ID for the user from your auth provider.|-|Optional|
44
+ |overrides|Overrides \|undefined|Forcefully set values like country, region, language for the consent manager. These values will override the values detected from the browser.|-|Optional|
45
+ |networkBlocker|[NetworkBlockerConfig \|undefined](https://v2.c15t.com/docs/frameworks/react/network-blocker)|Configuration for the network request blocker.|-|Optional|
46
+ |iab|[IABConfig \|undefined](https://v2.c15t.com/docs/frameworks/react/iab/overview)|IAB TCF 2.3 configuration.|-|Optional|
47
+ |ssrData|[Object \|undefined](https://v2.c15t.com/docs/frameworks/react/server-side)|SSR-prefetched data for hydration.|-|Optional|
48
+
49
+ #### `callbacks` Callbacks
50
+
51
+ Event callbacks for consent actions.
52
+
53
+ |Property|Type|Description|Default|Required|
54
+ |:--|:--|:--|:--|:--:|
55
+ |onBannerFetched|Callback\<OnBannerFetchedPayload> \|undefined|Called when the consent banner is fetched.|-|Optional|
56
+ |onConsentSet|Callback\<OnConsentSetPayload> \|undefined|Called when the consent is set.|-|Optional|
57
+ |onConsentChanged|Callback\<OnConsentChangedPayload> \|undefined|Called only when an explicit consent save changes the previously saved consent state.|-|Optional|
58
+ |onError|Callback\<OnErrorPayload> \|undefined|Called when an error occurs.|-|Optional|
59
+ |onBeforeConsentRevocationReload|Callback\<OnConsentSetPayload> \|undefined|Called before the page reloads when consent is revoked.|-|Optional|
60
+
61
+ #### `scripts` Script
62
+
63
+ Dynamically load scripts based on consent state.
64
+
65
+ |Property|Type|Description|Default|Required|
66
+ |:--|:--|:--|:--|:--:|
67
+ |id|string|Unique identifier for the script|-|✅ Required|
68
+ |src|string \|undefined|URL of the script to load|-|Optional|
69
+ |textContent|string \|undefined|Inline JavaScript code to execute|-|Optional|
70
+ |category|HasCondition\<AllConsentNames>|Consent category or condition required to load this script|-|✅ Required|
71
+ |callbackOnly|boolean \|undefined|Whether this is a callback-only script that doesn't need to load an external resource. When true, no script tag will be added to the DOM, only callbacks will be executed.|-|Optional|
72
+ |persistAfterConsentRevoked|boolean \|undefined|Whether the script should persist after consent is revoked.|-|Optional|
73
+ |alwaysLoad|boolean \|undefined|Whether the script should always load regardless of consent state. This is useful for scripts like Google Tag Manager or PostHog that manage their own consent state internally. The script will load immediately and never be unloaded based on consent changes. Note: When using this option, you are responsible for ensuring the script itself respects user consent preferences through its own consent management.|-|Optional|
74
+ |fetchPriority|"high" \|"low" \|"auto" \|undefined|Priority hint for browser resource loading|-|Optional|
75
+ |attributes|Record\<string, string> \|undefined|Additional attributes to add to the script element|-|Optional|
76
+ |async|boolean \|undefined|Whether to use async loading|-|Optional|
77
+ |defer|boolean \|undefined|Whether to defer script loading|-|Optional|
78
+ |nonce|string \|undefined|Content Security Policy nonce|-|Optional|
79
+ |anonymizeId|boolean \|undefined|Whether to use an anonymized ID for the script element, this helps ensure the script is not blocked by ad blockers|-|Optional|
80
+ |target|"head" \|"body" \|undefined|Where to inject the script element in the DOM. Options: \`'head'\`: Scripts are appended to \`\<head>\` (default); \`'body'\`: Scripts are appended to \`\<body>\`|-|Optional|
81
+ |onBeforeLoad|((info: ScriptCallbackInfo) => void) \|undefined|Callback executed before the script is loaded|-|Optional|
82
+ |onLoad|((info: ScriptCallbackInfo) => void) \|undefined|Callback executed when the script loads successfully|-|Optional|
83
+ |onError|((info: ScriptCallbackInfo) => void) \|undefined|Callback executed if the script fails to load|-|Optional|
84
+ |onConsentChange|((info: ScriptCallbackInfo) => void) \|undefined|Callback executed whenever the consent store is changed. This callback only applies to scripts already loaded.|-|Optional|
85
+ |vendorId|string \|number \|undefined|IAB TCF vendor ID - links script to a registered vendor. When in IAB mode, the script will only load if this vendor has consent. Takes precedence over \`category\` when in IAB mode. Use custom vendor IDs (string or number) to gate non-IAB vendors too.|-|Optional|
86
+ |iabPurposes|number\[] \|undefined|IAB TCF purpose IDs this script requires consent for. When in IAB mode and no vendorId is set, the script will only load if ALL specified purposes have consent.|-|Optional|
87
+ |iabLegIntPurposes|number\[] \|undefined|IAB TCF legitimate interest purpose IDs. These purposes can operate under legitimate interest instead of consent. The script loads if all iabPurposes have consent OR all iabLegIntPurposes have legitimate interest established.|-|Optional|
88
+ |iabSpecialFeatures|number\[] \|undefined|IAB TCF special feature IDs this script requires. Options: 1: Use precise geolocation data; 2: Actively scan device characteristics for identification|-|Optional|
89
+
90
+ #### `legalLinks`
91
+
92
+ Configuration for the legal links.
93
+
94
+ |Property|Type|Description|Default|Required|
95
+ |:--|:--|:--|:--|:--:|
96
+ |privacyPolicy|LegalLink \|undefined|-|-|✅ Required|
97
+ |cookiePolicy|LegalLink \|undefined|-|-|✅ Required|
98
+ |termsOfService|LegalLink \|undefined|-|-|✅ Required|
99
+
100
+ #### `storageConfig` StorageConfig
101
+
102
+ Storage configuration for consent persistence.
103
+
104
+ |Property|Type|Description|Default|Required|
105
+ |:--|:--|:--|:--|:--:|
106
+ |storageKey|string \|undefined|Custom storage key for localStorage and cookies|-|Optional|
107
+ |crossSubdomain|boolean \|undefined|Enable cross-subdomain cookies by default|-|Optional|
108
+ |defaultDomain|string \|undefined|Custom default domain for cookies|-|Optional|
109
+ |defaultExpiryDays|number \|undefined|Default cookie expiration in days|-|Optional|
110
+
111
+ #### `user` User
112
+
113
+ The user's information. Usually your own internal ID for the user from your auth provider.
114
+
115
+ |Property|Type|Description|Default|Required|
116
+ |:--|:--|:--|:--|:--:|
117
+ |id|string|Usually your own internal ID for the user from your auth provider|-|✅ Required|
118
+ |identityProvider|string \|undefined|The identity provider of the user. Usually the name of the identity provider e.g. 'clerk', 'auth0', 'custom', etc.|-|Optional|
119
+
120
+ #### `overrides` Overrides
121
+
122
+ Forcefully set values like country, region, language for the consent manager. These values will override the values detected from the browser.
123
+
124
+ |Property|Type|Description|Default|Required|
125
+ |:--|:--|:--|:--|:--:|
126
+ |country|string \|undefined|Country code to forcefully set|-|Optional|
127
+ |region|string \|undefined|Region code to forcefully set|-|Optional|
128
+ |language|string \|undefined|Language code to forcefully set|-|Optional|
129
+ |gpc|boolean \|undefined|Override the Global Privacy Control (GPC) signal. When \`true\`, simulates GPC being active (opt-out of marketing/measurement). When \`false\`, suppresses the real browser GPC signal. When \`undefined\`, falls back to the browser's \`navigator.globalPrivacyControl\`.|-|Optional|
130
+
131
+ #### `networkBlocker` NetworkBlockerConfig
132
+
133
+ Configuration for the network request blocker.
134
+
135
+ |Property|Type|Description|Default|Required|
136
+ |:--|:--|:--|:--|:--:|
137
+ |enabled|boolean \|undefined|Whether the network blocker is enabled.|-|Optional|
138
+ |initialConsents|ConsentState \|undefined|The consent state snapshot that is currently used for blocking logic.|-|Optional|
139
+ |logBlockedRequests|boolean \|undefined|Whether to automatically log blocked requests to the console.|-|Optional|
140
+ |onRequestBlocked|((info: BlockedRequestInfo) => void) \|undefined|Callback invoked whenever a request is blocked.|-|Optional|
141
+ |rules|NetworkBlockerRule|Domain rules that determine which requests should be blocked.|-|✅ Required|
142
+
143
+ #### `iab` IABConfig
144
+
145
+ IAB TCF 2.3 configuration.
146
+
147
+ |Property|Type|Description|Default|Required|
148
+ |:--|:--|:--|:--|:--:|
149
+ |enabled|boolean|Enable IAB TCF 2.3 mode. Note: Only works in 'hosted' client mode (legacy alias: 'c15t') because it requires a backend. Options: Fetch GVL from gvl.consent.io; Initialize \_\_tcfapi CMP API; Generate TC Strings for IAB compliance|-|✅ Required|
150
+ |\_module|IABModule \|undefined|IAB runtime module injected by \`@c15t/iab\`.|-|Optional|
151
+ |cmpId|number \|undefined|CMP ID registered with IAB Europe. When using consent.io as the backend, this is automatically provided via the \`/init\` endpoint — no client-side configuration needed. Only set this if you self-host and have your own CMP registration. A valid (non-zero) CMP ID is required for IAB TCF compliance.|-|Optional|
152
+ |cmpVersion|string \|number \|undefined|CMP version. When omitted, defaults to package version from \`\~/cmp-defaults\` (which uses \~/version).|-|Optional|
153
+ |vendors|number\[] \|undefined|IAB-registered vendor IDs to include (optional). Used to scope the vendor list when fetching GVL or when hosted fallback paths are used (e.g. if GVL fetch fails).|-|Optional|
154
+ |customVendors|NonIABVendor \|undefined|Custom vendors not registered with IAB. These are displayed separately in the consent UI with a note that they have different privacy practices than IAB vendors.|-|Optional|
155
+ |publisherCountryCode|string \|undefined|Publisher country code (2-letter ISO).|-|Optional|
156
+ |isServiceSpecific|boolean \|undefined|Whether consent is service-specific (not global).|-|Optional|
157
+ |gvl|Object \|undefined \|null|Pre-loaded Global Vendor List for testing or SSR. Options: Testing (avoids network calls and mocking complexity); SSR (use server-fetched GVL); Offline/air-gapped deployments|-|Optional|
158
+
159
+ #### `ssrData`
160
+
161
+ SSR-prefetched data for hydration.
162
+
163
+ |Property|Type|Description|Default|Required|
164
+ |:--|:--|:--|:--|:--:|
165
+ |init|Object \|undefined \|null|Init endpoint response with jurisdiction, location, translations, and optional GVL.|-|✅ Required|
166
+ |gvl|Object \|undefined \|null|Global Vendor List data for IAB TCF mode. Note: When init returns 200 without gvl, client IAB settings are overridden to disabled.|-|Optional|
167
+ |metadata|SSRInitRequestMetadata \|undefined|Optional metadata for debugging SSR transport behavior.|-|Optional|
168
+
169
+ ### ConsentManagerContentOptions
170
+
171
+ |Property|Type|Description|Default|Required|
172
+ |:--|:--|:--|:--|:--:|
173
+ |i18n|I18nConfig \|undefined|Preferred i18n configuration in c15t v2.|-|Optional|
174
+ |translations|[TranslationConfig \|undefined](https://v2.c15t.com/docs/frameworks/react/internationalization)|Translation configuration to seed the store with.|-|Optional|
175
+ |consentCategories|[AllConsentNames \|undefined](https://v2.c15t.com/docs/frameworks/react/concepts/consent-categories)|Consent categories to show in the consent banner.|-|Optional|
176
+
177
+ #### `i18n` I18nConfig
178
+
179
+ Preferred i18n configuration in c15t v2.
180
+
181
+ |Property|Type|Description|Default|Required|
182
+ |:--|:--|:--|:--|:--:|
183
+ |messages|Record\<string, Partial\<Translations>> \|undefined|Translation message map keyed by language code (\`en\`, \`de\`, \`fr\`, ...).|-|✅ Required|
184
+ |locale|string \|undefined|Preferred language code used as the initial fallback locale.|-|Optional|
185
+ |detectBrowserLanguage|boolean \|undefined|Whether to auto-detect from browser language settings.|-|Optional|
186
+
187
+ #### `translations` TranslationConfig
188
+
189
+ Translation configuration to seed the store with.
190
+
191
+ |Property|Type|Description|Default|Required|
192
+ |:--|:--|:--|:--|:--:|
193
+ |translations|Record\<string, Partial\<Translations>> \|undefined|-|-|✅ Required|
194
+ |defaultLanguage|string \|undefined|-|-|Optional|
195
+ |disableAutoLanguageSwitch|boolean \|undefined|-|-|Optional|
196
+
197
+ ### UIOptions
198
+
199
+ |Property|Type|Description|Default|Required|
200
+ |:--|:--|:--|:--|:--:|
201
+ |theme|[Theme \|undefined](https://v2.c15t.com/docs/frameworks/react/styling/tokens)|Visual theme to apply.|-|Optional|
202
+ |disableAnimation|boolean \|undefined|Whether to disable animations.|false|Optional|
203
+ |scrollLock|boolean \|undefined|Whether to lock scroll when dialogs are open.|false|Optional|
204
+ |trapFocus|boolean \|undefined|Whether to trap focus within dialogs.|true|Optional|
205
+ |colorScheme|["light" \|"dark" \|"system" \|undefined](https://v2.c15t.com/docs/frameworks/react/styling/color-scheme)|Color scheme preference. With this option, you can force the theme to be light, dark or system. Otherwise, the theme will be detected if you have '.dark' classname in your document.|-|Optional|
206
+ |noStyle|[boolean \|undefined](https://v2.c15t.com/docs/frameworks/react/headless)|Whether to disable default styles.|false|Optional|
207
+
208
+ #### `theme` Theme
209
+
210
+ Visual theme to apply.
211
+
212
+ |Property|Type|Description|Default|Required|
213
+ |:--|:--|:--|:--|:--:|
214
+ |colors|ColorTokens \|undefined|Color palette for light mode.|-|Optional|
215
+ |dark|ColorTokens \|undefined|Dark mode color overrides.|-|Optional|
216
+ |typography|TypographyTokens \|undefined|Typography settings for text elements.|-|Optional|
217
+ |spacing|SpacingTokens \|undefined|Spacing scale for internal padding and margins.|-|Optional|
218
+ |radius|RadiusTokens \|undefined|Border radius scale for rounded corners.|-|Optional|
219
+ |shadows|ShadowTokens \|undefined|Box shadow scale for depth and elevation.|-|Optional|
220
+ |motion|MotionTokens \|undefined|Animation and transition timing.|-|Optional|
221
+ |consentActions|Object \|undefined|Semantic button styling for consent actions.|-|Optional|
222
+ |slots|ComponentSlots \|undefined|Component-specific style overrides.|-|Optional|
223
+
224
+ ## Mode: hosted vs offline
225
+
226
+ ```tsx
227
+ // Hosted mode — persists to hosted backend
228
+ <ConsentManagerProvider
229
+ options={{
230
+ mode: 'hosted',
231
+ backendURL: '/api/c15t',
232
+ }}
233
+ >
234
+
235
+ // Offline mode — local cookie storage only
236
+ <ConsentManagerProvider
237
+ options={{
238
+ mode: 'offline',
239
+ }}
240
+ >
241
+ ```
242
+
243
+ See [Client Modes](/docs/frameworks/next/concepts/client-modes) for a detailed comparison.
244
+
245
+ ## Legal Links
246
+
247
+ `legalLinks` defines the URLs shown in consent UI text (banner, dialog, and widget where applicable).
248
+ Configure only the links you want to expose.
249
+
250
+ ```tsx
251
+ <ConsentManagerProvider
252
+ options={{
253
+ backendURL: 'https://your-instance.c15t.dev',
254
+ legalLinks: {
255
+ privacyPolicy: {
256
+ href: '/privacy',
257
+ target: '_self',
258
+ },
259
+ cookiePolicy: {
260
+ href: '/cookies',
261
+ target: '_self',
262
+ },
263
+ termsOfService: {
264
+ href: 'https://example.com/terms',
265
+ target: '_blank',
266
+ rel: 'noopener noreferrer',
267
+ label: 'Terms of Service',
268
+ },
269
+ },
270
+ }}
271
+ >
272
+ ```
273
+
274
+ Notes:
275
+
276
+ * Omitting a key (for example `termsOfService`) hides that link.
277
+ * `label` overrides the translated text for that single link.
278
+ * Use `_self` for internal pages and `_blank` + `rel="noopener noreferrer"` for external pages.
279
+ * Control which of the configured links render in each component via the component's `legalLinks` prop.
280
+
281
+ ## Overrides
282
+
283
+ `overrides` lets you force location/language signals instead of browser or network detection.
284
+ This is useful for QA, local development, and preview environments.
285
+
286
+ ```tsx
287
+ <ConsentManagerProvider
288
+ options={{
289
+ backendURL: 'https://your-instance.c15t.dev',
290
+ overrides: {
291
+ country: 'DE',
292
+ region: 'BY',
293
+ language: 'de-DE',
294
+ },
295
+ }}
296
+ >
297
+ ```
298
+
299
+ You can also override Global Privacy Control (GPC) behavior during testing:
300
+
301
+ ```tsx
302
+ <ConsentManagerProvider
303
+ options={{
304
+ backendURL: 'https://your-instance.c15t.dev',
305
+ overrides: {
306
+ gpc: true,
307
+ },
308
+ }}
309
+ >
310
+ ```
311
+
312
+ > ⚠️ **Warning:**
313
+ > Treat overrides as an environment/testing tool. Avoid hard-coding production overrides unless that behavior is intentional for your deployment.
314
+
315
+ ## Policy Packs
316
+
317
+ In hosted mode (recommended), the backend resolves the correct policy automatically — no frontend policy config needed:
318
+
319
+ ```tsx
320
+ <ConsentManagerProvider
321
+ options={{
322
+ backendURL: 'https://your-instance.c15t.dev',
323
+ }}
324
+ >
325
+ ```
326
+
327
+ ### Fallback: Offline Policies
328
+
329
+ When no backend is available, `ConsentManagerProvider` accepts `offlinePolicy.policyPacks` for local policy resolution during development, testing, previews, or temporary backend outages:
330
+
331
+ ```tsx
332
+ <ConsentManagerProvider
333
+ options={{
334
+ mode: 'offline',
335
+ offlinePolicy: {
336
+ i18n: {
337
+ defaultProfile: 'default',
338
+ messages: {
339
+ default: {
340
+ translations: {
341
+ en: { cookieBanner: { title: 'Privacy choices' } },
342
+ },
343
+ },
344
+ qc: {
345
+ fallbackLanguage: 'fr',
346
+ translations: {
347
+ en: { cookieBanner: { title: 'Quebec Privacy Settings' } },
348
+ fr: { cookieBanner: { title: 'Paramètres de confidentialité du Québec' } },
349
+ },
350
+ },
351
+ },
352
+ },
353
+ policyPacks: [
354
+ {
355
+ id: 'qc_opt_in',
356
+ match: { regions: [{ country: 'CA', region: 'QC' }] },
357
+ i18n: { messageProfile: 'qc' },
358
+ consent: { model: 'opt-in', expiryDays: 365 },
359
+ ui: { mode: 'banner' },
360
+ },
361
+ {
362
+ id: 'default_world',
363
+ match: { isDefault: true },
364
+ consent: { model: 'none' },
365
+ ui: { mode: 'none' },
366
+ },
367
+ ],
368
+ },
369
+ overrides: {
370
+ country: 'CA',
371
+ region: 'QC',
372
+ },
373
+ }}
374
+ >
375
+ ```
376
+
377
+ Notes:
378
+
379
+ * `offlinePolicy` is only used in `offline` mode.
380
+ * Treat offline policies as a development/testing tool or resilience fallback, not the primary production source of truth.
381
+ * `offlinePolicy.i18n` lets offline mode mirror hosted `messageProfile` and profile-local `fallbackLanguage` behavior.
382
+ * Omitting `offlinePolicy.policyPacks` uses the built-in synthetic opt-in fallback banner. Hosted network fallback uses the same opt-in banner.
383
+ * `offlinePolicy: { policyPacks: [] }` is explicit no-banner mode.
384
+ * In hosted mode, backend `policyPacks` remain the source of truth — frontend offline policies never override a live backend decision.
385
+
386
+ Read the full guide at [Policy Packs](/docs/frameworks/react/policy-packs) and the conceptual model at [Policy Packs Concept](/docs/frameworks/react/concepts/policy-packs).
387
+
388
+ ## Props
389
+
390
+ ### ConsentManagerProviderProps
391
+
392
+ |Property|Type|Description|Default|Required|
393
+ |:--|:--|:--|:--|:--:|
394
+ |children|ReactNode|React children to render within the provider.|-|✅ Required|
395
+ |options|[ConsentManagerOptions](https://v2.c15t.com/docs/frameworks/react/components/consent-manager-provider)|Configuration options for the consent manager. This includes core, React, store, and translation settings.|-|✅ Required|
396
+
397
+ #### `options` ConsentManagerOptions
398
+
399
+ Configuration options for the consent manager. This includes core, React, store, and translation settings.
400
+
401
+ |Property|Type|Description|Default|Required|
402
+ |:--|:--|:--|:--|:--:|
403
+ |store|StoreOptions \|undefined|-|-|Optional|
404
+ |offlinePolicy|OfflinePolicyConfig \|undefined|Top-level offline policy configuration.|-|Optional|
405
+ |storageConfig|StorageConfig \|undefined|Storage configuration for consent persistence|-|Optional|
406
+ |mode|"c15t" \|"custom" \|"hosted" \|"offline" \|undefined|Operating mode - custom endpoint implementation|-|Optional|
407
+ |backendURL|string \|undefined|Backend URL is not used in custom mode|-|Optional|
408
+ |enabled|boolean \|undefined|Whether c15t should be active.|-|Optional|
409
+ |callbacks|Callbacks \|undefined|Event callbacks for consent actions.|-|Optional|
410
+ |scripts|Script \|undefined|Dynamically load scripts based on consent state.|-|Optional|
411
+ |legalLinks|Partial\<Record\<keyof LegalLinksTranslations, LegalLink>> \|undefined|Configuration for the legal links.|-|Optional|
412
+ |user|User \|undefined|The user's information. Usually your own internal ID for the user from your auth provider.|-|Optional|
413
+ |overrides|Overrides \|undefined|Forcefully set values like country, region, language for the consent manager. These values will override the values detected from the browser.|-|Optional|
414
+ |networkBlocker|NetworkBlockerConfig \|undefined|Configuration for the network request blocker.|-|Optional|
415
+ |iab|IABConfig \|undefined|IAB TCF 2.3 configuration.|-|Optional|
416
+ |ssrData|Promise\<SSRInitialData \|undefined> \|undefined|SSR-prefetched data for hydration.|-|Optional|
417
+ |theme|Theme \|undefined|Visual theme to apply.|-|Optional|
418
+ |disableAnimation|boolean \|undefined|Whether to disable animations.|-|Optional|
419
+ |scrollLock|boolean \|undefined|Whether to lock scroll when dialogs are open.|-|Optional|
420
+ |trapFocus|boolean \|undefined|Whether to trap focus within dialogs.|-|Optional|
421
+ |colorScheme|"light" \|"dark" \|"system" \|undefined|Color scheme preference. With this option, you can force the theme to be light, dark or system. Otherwise, the theme will be detected if you have '.dark' classname in your document.|-|Optional|
422
+ |noStyle|boolean \|undefined|Whether to disable default styles.|-|Optional|
423
+ |i18n|I18nConfig \|undefined|Preferred i18n configuration in c15t v2.|-|Optional|
424
+ |translations|TranslationConfig \|undefined|Translation configuration to seed the store with.|-|Optional|
425
+ |consentCategories|AllConsentNames \|undefined|Consent categories to show in the consent banner.|-|Optional|
@@ -0,0 +1,133 @@
1
+ ---
2
+ title: ConsentWidget
3
+ description: An inline consent management widget for embedding in settings or privacy pages. Shows category toggles with accordion layout.
4
+ ---
5
+ `ConsentWidget` is a standalone, inline consent management widget. Unlike `ConsentDialog` (which is a modal), the widget embeds directly in your page layout - ideal for privacy settings pages, account preferences, or any page where users should be able to manage consent without a modal overlay.
6
+
7
+ ## Basic Usage
8
+
9
+ ```tsx
10
+ import { ConsentWidget } from '@c15t/nextjs';
11
+
12
+ export function PrivacySettingsPage() {
13
+ return (
14
+ <>
15
+ <h1>Privacy Settings</h1>
16
+ <p>Manage your cookie preferences below.</p>
17
+ <ConsentWidget />
18
+ </>
19
+ );
20
+ }
21
+ ```
22
+
23
+ ## Configuration
24
+
25
+ ```tsx
26
+ <ConsentWidget
27
+ hideBranding
28
+ legalLinks={['privacyPolicy', 'cookiePolicy']}
29
+ noStyle={false}
30
+ disableAnimation={false}
31
+ />
32
+ ```
33
+
34
+ ## Accordion Behavior
35
+
36
+ Each consent category is rendered as an expandable accordion item. Clicking the category header expands it to show a description and any associated services. Users can toggle individual categories on or off using the switch control. The `necessary` category is always enabled and cannot be toggled.
37
+
38
+ ## Styling First
39
+
40
+ > ℹ️ **Info:**
41
+ > Most widget customization should stay in the stock component. Use theme tokens and slots such as consentWidgetAccordion, consentWidgetFooter, and toggle before reaching for compound components. See Styling Overview.
42
+
43
+ ```tsx
44
+ <ConsentManagerProvider
45
+ options={{
46
+ theme: {
47
+ colors: {
48
+ surface: '#fffdf8',
49
+ surfaceHover: '#f6f3ee',
50
+ },
51
+ slots: {
52
+ consentWidgetAccordion: 'rounded-3xl border border-black/10',
53
+ consentWidgetFooter: 'border-t border-black/10 px-6',
54
+ toggle: 'shadow-sm',
55
+ },
56
+ },
57
+ }}
58
+ >
59
+ <ConsentWidget />
60
+ </ConsentManagerProvider>
61
+ ```
62
+
63
+ Widget copy should be changed through `ConsentManagerProvider.options.i18n` so the inline UI stays aligned with the rest of the consent experience.
64
+
65
+ ## Advanced: Compound Components
66
+
67
+ Use compound components only when you need to rearrange the widget's existing primitives while keeping policy-aware action grouping:
68
+
69
+ ```tsx
70
+ <ConsentWidget.Root>
71
+ <ConsentWidget.Accordion type="multiple">
72
+ <ConsentWidget.AccordionItems />
73
+ </ConsentWidget.Accordion>
74
+ <ConsentWidget.PolicyActions />
75
+ </ConsentWidget.Root>
76
+ ```
77
+
78
+ * `ConsentWidget.Root` — Theme context provider
79
+ * `ConsentWidget.Accordion` — Radix-based accordion root
80
+ * `ConsentWidget.AccordionItems` — Auto-generates toggle items from consent config
81
+ * `ConsentWidget.AccordionItem` — Individual category item
82
+ * `ConsentWidget.AccordionTrigger` — Clickable header for each item
83
+ * `ConsentWidget.AccordionContent` — Collapsible content area
84
+ * `ConsentWidget.AccordionArrow` — Expand/collapse indicator
85
+ * `ConsentWidget.Switch` — Category toggle switch
86
+ * `ConsentWidget.PolicyActions` — Renders grouped policy-aware actions
87
+ * `ConsentWidget.Footer` — Footer container
88
+ * `ConsentWidget.FooterSubGroup` — Groups related buttons
89
+ * `ConsentWidget.AcceptAllButton` — Accepts all consent
90
+ * `ConsentWidget.RejectButton` — Rejects all consent
91
+ * `ConsentWidget.SaveButton` — Saves custom selections
92
+
93
+ ## Using `renderAction` with c15t Defaults
94
+
95
+ `ConsentWidget.PolicyActions` renders stock c15t buttons and translations by default.
96
+
97
+ ```tsx
98
+ <ConsentWidget.PolicyActions />
99
+ ```
100
+
101
+ `renderAction` is optional. Return the stock button compounds when you want custom mapping while preserving built-in c15t behavior and copy:
102
+
103
+ ```tsx
104
+ <ConsentWidget.PolicyActions
105
+ renderAction={(action, props) => {
106
+ const { key, ...buttonProps } = props
107
+
108
+ switch (action) {
109
+ case 'accept':
110
+ return <ConsentWidget.AcceptAllButton key={key} {...buttonProps} />
111
+ case 'reject':
112
+ return <ConsentWidget.RejectButton key={key} {...buttonProps} />
113
+ case 'customize':
114
+ return <ConsentWidget.SaveButton key={key} {...buttonProps} />
115
+ }
116
+ }}
117
+ />
118
+ ```
119
+
120
+ `renderAction` is still meant for stock button compounds. If you want completely custom button elements and handlers, use `useHeadlessConsentUI()` and render `dialog.actionGroups` manually instead of `ConsentWidget.PolicyActions`.
121
+
122
+ For a fixed footer layout, render `ConsentWidget.Footer` and `ConsentWidget.FooterSubGroup` manually instead of using `ConsentWidget.PolicyActions`.
123
+
124
+ If the stock widget structure is already correct, stay with tokens and slots instead of rebuilding the layout.
125
+
126
+ ## Props
127
+
128
+ ### ConsentWidgetProps
129
+
130
+ |Property|Type|Description|Default|Required|
131
+ |:--|:--|:--|:--|:--:|
132
+ |hideBranding|boolean \|undefined|Controls whether to hide the branding in the widget footer.|-|Optional|
133
+ |legalLinks|(keyof LegalLinksTranslations)\[] \|null \|undefined|Controls which legal links to display in the widget footer.|-|Optional|
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: DevTools
3
+ description: A development tool for inspecting consent state, geolocation, loaded scripts, and consent events in real time.
4
+ ---
5
+ `DevTools` is a floating panel that shows the internal state of the consent manager. Use it during development to inspect consent values, geolocation results, loaded scripts, and debug consent flows. Also exported as `C15TDevTools` if you need to avoid naming conflicts with other devtools.
6
+
7
+ > ℹ️ **Info:**
8
+ > DevTools should only be included in development builds. The component renders nothing to the React tree - it injects directly into document.body.
9
+
10
+ ## Installation
11
+
12
+ DevTools lives in a separate package to keep it out of production bundles:
13
+
14
+ ```bash
15
+ bun add -D @c15t/dev-tools
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```tsx
21
+ import { type ReactNode } from 'react';
22
+ import { ConsentManagerProvider } from '@c15t/nextjs';
23
+ import { DevTools } from '@c15t/dev-tools/react';
24
+
25
+ export function ConsentManager({ children }: { children: ReactNode }) {
26
+ return (
27
+ <ConsentManagerProvider options={{ mode: 'hosted', backendURL: '/api/c15t' }}>
28
+ {children}
29
+ {process.env.NODE_ENV === 'development' && <DevTools />}
30
+ </ConsentManagerProvider>
31
+ );
32
+ }
33
+ ```
34
+
35
+ ## Configuration
36
+
37
+ ```tsx
38
+ <DevTools
39
+ position="bottom-right" // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
40
+ defaultOpen={false} // Start with panel open
41
+ namespace="c15tStore" // Store namespace to connect to
42
+ disabled={false} // Disable without removing from tree
43
+ />
44
+ ```
45
+
46
+ ## Panels
47
+
48
+ |Panel|What it shows|
49
+ |--|--|
50
+ |**Consents**|Current consent state for all categories|
51
+ |**Location**|Detected jurisdiction, country, region, and consent model|
52
+ |**Scripts**|Configured scripts and their load status|
53
+ |**IAB**|IAB TCF state (when enabled) - TC string, vendor consents, purposes|
54
+ |**Events**|Timeline of consent events and state changes|
55
+ |**Actions**|Buttons to trigger consent actions (accept all, reject all, reset)|
56
+
57
+ ## Props
58
+
59
+ ### C15TDevToolsProps
60
+
61
+ |Property|Type|Description|Default|Required|
62
+ |:--|:--|:--|:--|:--:|
63
+ |disabled|boolean \|undefined|Whether the DevTools should be disabled Useful for production builds|false|Optional|