@c15t/nextjs 2.2.1 → 3.0.0-alpha.0

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 (220) hide show
  1. package/AGENTS.md +102 -142
  2. package/README.md +4 -4
  3. package/dist/api.js +1 -0
  4. package/dist/config.js +1 -0
  5. package/dist/devtools.js +2 -0
  6. package/dist/headers.js +1 -0
  7. package/dist/iab/styles.css +1 -1
  8. package/dist/iab/styles.tw3.css +133 -19
  9. package/dist/index.js +1 -1
  10. package/dist/middleware.js +1 -0
  11. package/dist/node-bridge.js +1 -0
  12. package/dist/pages.js +1 -0
  13. package/dist/proxy.js +1 -0
  14. package/dist/root.js +2 -0
  15. package/dist/server.js +1 -0
  16. package/dist/static.js +1 -0
  17. package/dist/styles.css +1 -1
  18. package/dist/styles.tw3.css +173 -29
  19. package/dist/version.js +1 -1
  20. package/dist-types/api.d.ts +88 -0
  21. package/dist-types/config.d.ts +110 -0
  22. package/dist-types/devtools.d.ts +1 -0
  23. package/dist-types/headers.d.ts +4 -0
  24. package/dist-types/index.d.ts +28 -10
  25. package/dist-types/middleware.d.ts +15 -0
  26. package/dist-types/node-bridge.d.ts +57 -0
  27. package/dist-types/pages.d.ts +88 -0
  28. package/dist-types/proxy.d.ts +34 -0
  29. package/dist-types/root.d.ts +86 -0
  30. package/dist-types/server.d.ts +164 -0
  31. package/dist-types/static.d.ts +42 -0
  32. package/dist-types/types.d.ts +5 -36
  33. package/dist-types/version.d.ts +1 -1
  34. package/docs/README.md +102 -142
  35. package/docs/assets/v3/brand-bar.png +0 -0
  36. package/docs/assets/v3/brand-card.png +0 -0
  37. package/docs/assets/v3/choice-wall.png +0 -0
  38. package/docs/assets/v3/mobile-card.png +0 -0
  39. package/docs/assets/v3/preferences.png +0 -0
  40. package/docs/customization/overview.md +45 -0
  41. package/docs/customization/recipes.md +79 -0
  42. package/docs/customization/slots.md +55 -0
  43. package/docs/customization/tokens.md +76 -0
  44. package/docs/customization/translations.md +49 -0
  45. package/docs/frameworks/next/api-reference/data-fetching.md +416 -0
  46. package/docs/frameworks/next/app-router.md +403 -0
  47. package/docs/frameworks/next/client-side.md +118 -0
  48. package/docs/frameworks/next/components/consent-banner.md +251 -211
  49. package/docs/frameworks/next/components/consent-dialog-link.md +96 -35
  50. package/docs/frameworks/next/components/consent-dialog-trigger.md +74 -149
  51. package/docs/frameworks/next/components/consent-dialog.md +189 -134
  52. package/docs/frameworks/next/components/consent-manager-provider.md +60 -318
  53. package/docs/frameworks/next/components/consent-widget.md +172 -114
  54. package/docs/frameworks/next/components/dev-tools.md +199 -40
  55. package/docs/frameworks/next/components/frame.md +137 -42
  56. package/docs/frameworks/next/concepts/consent-categories.md +24 -89
  57. package/docs/frameworks/next/concepts/policy-presets.md +142 -0
  58. package/docs/frameworks/next/content-security-policy.md +189 -0
  59. package/docs/frameworks/next/data-fetching.md +74 -0
  60. package/docs/frameworks/next/geography-headers.md +251 -0
  61. package/docs/frameworks/next/headless.md +95 -185
  62. package/docs/frameworks/next/hooks/use-consent-manager/overview.md +42 -163
  63. package/docs/frameworks/next/iab/overview.md +37 -107
  64. package/docs/frameworks/next/optimization.md +158 -194
  65. package/docs/frameworks/next/pages-router.md +296 -0
  66. package/docs/frameworks/next/quickstart.md +31 -132
  67. package/docs/frameworks/next/script-loader.md +134 -467
  68. package/docs/frameworks/next/server-side.md +97 -130
  69. package/docs/frameworks/next/static-export.md +164 -0
  70. package/docs/frameworks/next/styling/overview.md +166 -250
  71. package/docs/frameworks/next/troubleshooting.md +134 -144
  72. package/docs/guides/consent-state.md +60 -0
  73. package/docs/guides/data-fetching.md +163 -0
  74. package/docs/guides/deployment-modes.md +63 -0
  75. package/docs/guides/troubleshooting.md +68 -0
  76. package/docs/guides/verify-consent.md +62 -0
  77. package/docs/integrations/adobe-analytics.md +239 -105
  78. package/docs/integrations/ahrefs-analytics.md +238 -104
  79. package/docs/integrations/amplitude.md +219 -157
  80. package/docs/integrations/building-integrations.md +32 -224
  81. package/docs/integrations/clearbit.md +247 -86
  82. package/docs/integrations/cloudflare-web-analytics.md +250 -84
  83. package/docs/integrations/crisp.md +251 -97
  84. package/docs/integrations/databuddy.md +259 -153
  85. package/docs/integrations/fathom-analytics.md +239 -96
  86. package/docs/integrations/google-maps.md +328 -207
  87. package/docs/integrations/google-tag-manager.md +248 -96
  88. package/docs/integrations/google-tag.md +261 -90
  89. package/docs/integrations/heap.md +222 -149
  90. package/docs/integrations/hightouch.md +225 -131
  91. package/docs/integrations/hotjar.md +239 -90
  92. package/docs/integrations/intercom.md +239 -98
  93. package/docs/integrations/linkedin-insights.md +243 -113
  94. package/docs/integrations/logrocket.md +241 -123
  95. package/docs/integrations/matomo-analytics.md +256 -111
  96. package/docs/integrations/meta-pixel.md +197 -324
  97. package/docs/integrations/microsoft-clarity.md +233 -114
  98. package/docs/integrations/microsoft-uet.md +245 -110
  99. package/docs/integrations/mixpanel-analytics.md +252 -87
  100. package/docs/integrations/openai-pixel.md +441 -0
  101. package/docs/integrations/overview.md +95 -133
  102. package/docs/integrations/pirsch.md +249 -96
  103. package/docs/integrations/plausible-analytics.md +241 -100
  104. package/docs/integrations/posthog.md +353 -214
  105. package/docs/integrations/promptwatch.md +251 -81
  106. package/docs/integrations/reddit-pixel.md +226 -173
  107. package/docs/integrations/rudderstack.md +244 -187
  108. package/docs/integrations/rybbit-analytics.md +244 -91
  109. package/docs/integrations/segment.md +238 -92
  110. package/docs/integrations/snapchat-pixel.md +240 -110
  111. package/docs/integrations/tiktok-pixel.md +249 -81
  112. package/docs/integrations/umami-analytics.md +242 -95
  113. package/docs/integrations/vercel-analytics.md +242 -90
  114. package/docs/integrations/x-pixel.md +238 -104
  115. package/docs/integrations/youtube.md +354 -142
  116. package/docs/upgrade-v3.md +334 -0
  117. package/iab/styles.css +1 -1
  118. package/iab/styles.tw3.css +1 -1
  119. package/package.json +106 -65
  120. package/readme.json +3 -3
  121. package/src/iab/styles.css +1 -1
  122. package/src/iab/styles.tw3.css +1 -1
  123. package/src/styles.css +1 -1
  124. package/src/styles.tw3.css +1 -1
  125. package/styles.css +1 -1
  126. package/styles.tw3.css +1 -1
  127. package/client/components/consent-dialog-link.js +0 -3
  128. package/client/components/integrations.js +0 -3
  129. package/dist/components/integrations/index.cjs +0 -1
  130. package/dist/components/integrations/index.js +0 -1
  131. package/dist/headless.cjs +0 -1
  132. package/dist/index.cjs +0 -1
  133. package/dist/libs/browser-initial-data.cjs +0 -1
  134. package/dist/libs/browser-initial-data.js +0 -1
  135. package/dist/libs/initial-data.cjs +0 -1
  136. package/dist/libs/initial-data.js +0 -1
  137. package/dist/types.cjs +0 -1
  138. package/dist/version.cjs +0 -1
  139. package/dist-types/components/integrations/index.d.ts +0 -1
  140. package/dist-types/libs/browser-initial-data.d.ts +0 -9
  141. package/dist-types/libs/initial-data.d.ts +0 -33
  142. package/docs/frameworks/next/building-headless-components.md +0 -379
  143. package/docs/frameworks/next/callbacks.md +0 -186
  144. package/docs/frameworks/next/concepts/client-modes.md +0 -177
  145. package/docs/frameworks/next/concepts/consent-models.md +0 -117
  146. package/docs/frameworks/next/concepts/cookie-management.md +0 -122
  147. package/docs/frameworks/next/concepts/glossary.md +0 -24
  148. package/docs/frameworks/next/concepts/initialization-flow.md +0 -149
  149. package/docs/frameworks/next/concepts/policy-packs.md +0 -230
  150. package/docs/frameworks/next/hooks/use-color-scheme.md +0 -41
  151. package/docs/frameworks/next/hooks/use-consent-manager/checking-consent.md +0 -96
  152. package/docs/frameworks/next/hooks/use-consent-manager/location-info.md +0 -97
  153. package/docs/frameworks/next/hooks/use-consent-manager/setting-consent.md +0 -94
  154. package/docs/frameworks/next/hooks/use-draggable.md +0 -59
  155. package/docs/frameworks/next/hooks/use-focus-trap.md +0 -42
  156. package/docs/frameworks/next/hooks/use-reduced-motion.md +0 -37
  157. package/docs/frameworks/next/hooks/use-ssr-status.md +0 -32
  158. package/docs/frameworks/next/hooks/use-text-direction.md +0 -50
  159. package/docs/frameworks/next/hooks/use-translations.md +0 -55
  160. package/docs/frameworks/next/iab/consent-banner.md +0 -91
  161. package/docs/frameworks/next/iab/consent-dialog.md +0 -129
  162. package/docs/frameworks/next/iab/use-gvl-data.md +0 -21
  163. package/docs/frameworks/next/iframe-blocking.md +0 -106
  164. package/docs/frameworks/next/internationalization.md +0 -207
  165. package/docs/frameworks/next/network-blocker.md +0 -140
  166. package/docs/frameworks/next/policy-packs.md +0 -248
  167. package/docs/frameworks/next/styling/classnames.md +0 -94
  168. package/docs/frameworks/next/styling/color-scheme.md +0 -84
  169. package/docs/frameworks/next/styling/css-variables.md +0 -53
  170. package/docs/frameworks/next/styling/slots.md +0 -94
  171. package/docs/frameworks/next/styling/tailwind.md +0 -137
  172. package/docs/frameworks/next/styling/tokens.md +0 -156
  173. package/docs/shared/concepts/client-modes.md +0 -103
  174. package/docs/shared/concepts/consent-categories.md +0 -41
  175. package/docs/shared/concepts/consent-models.md +0 -72
  176. package/docs/shared/concepts/cookie-management.md +0 -88
  177. package/docs/shared/concepts/glossary.md +0 -24
  178. package/docs/shared/concepts/initialization-flow.md +0 -105
  179. package/docs/shared/concepts/policy-packs.md +0 -225
  180. package/docs/shared/react/components/consent-banner.md +0 -242
  181. package/docs/shared/react/components/consent-dialog-link.md +0 -45
  182. package/docs/shared/react/components/consent-dialog-trigger.md +0 -185
  183. package/docs/shared/react/components/consent-dialog.md +0 -119
  184. package/docs/shared/react/components/consent-manager-provider.md +0 -225
  185. package/docs/shared/react/components/consent-widget.md +0 -121
  186. package/docs/shared/react/components/dev-tools.md +0 -81
  187. package/docs/shared/react/components/frame.md +0 -52
  188. package/docs/shared/react/guides/building-headless-components.md +0 -110
  189. package/docs/shared/react/guides/callbacks.md +0 -89
  190. package/docs/shared/react/guides/headless.md +0 -31
  191. package/docs/shared/react/guides/iframe-blocking.md +0 -65
  192. package/docs/shared/react/guides/internationalization.md +0 -123
  193. package/docs/shared/react/guides/network-blocker.md +0 -72
  194. package/docs/shared/react/guides/optimization.md +0 -44
  195. package/docs/shared/react/guides/policy-packs.md +0 -173
  196. package/docs/shared/react/guides/script-loader.md +0 -311
  197. package/docs/shared/react/hooks/use-color-scheme.md +0 -31
  198. package/docs/shared/react/hooks/use-consent-manager/checking-consent.md +0 -95
  199. package/docs/shared/react/hooks/use-consent-manager/location-info.md +0 -96
  200. package/docs/shared/react/hooks/use-consent-manager/overview.md +0 -74
  201. package/docs/shared/react/hooks/use-consent-manager/setting-consent.md +0 -93
  202. package/docs/shared/react/hooks/use-draggable.md +0 -30
  203. package/docs/shared/react/hooks/use-focus-trap.md +0 -20
  204. package/docs/shared/react/hooks/use-reduced-motion.md +0 -33
  205. package/docs/shared/react/hooks/use-ssr-status.md +0 -16
  206. package/docs/shared/react/hooks/use-text-direction.md +0 -38
  207. package/docs/shared/react/hooks/use-translations.md +0 -15
  208. package/docs/shared/react/iab/consent-banner.md +0 -60
  209. package/docs/shared/react/iab/consent-dialog.md +0 -76
  210. package/docs/shared/react/iab/overview.md +0 -80
  211. package/docs/shared/react/iab/use-gvl-data.md +0 -21
  212. package/docs/shared/react/styling/classnames.md +0 -93
  213. package/docs/shared/react/styling/color-scheme.md +0 -35
  214. package/docs/shared/react/styling/css-variables.md +0 -53
  215. package/docs/shared/react/styling/overview.md +0 -261
  216. package/docs/shared/react/styling/slots.md +0 -93
  217. package/docs/shared/react/styling/stylesheet-entrypoint.md +0 -8
  218. package/docs/shared/react/styling/tailwind.md +0 -88
  219. package/docs/shared/react/styling/tokens.md +0 -155
  220. package/docs/shared/troubleshooting.md +0 -82
@@ -1,225 +0,0 @@
1
- ---
2
- title: Consent Manager Provider
3
- description: Reference page for consent manager provider.
4
- group: reference
5
- ---
6
- `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.
7
-
8
- Every other c15t component and hook must be rendered inside this provider.
9
-
10
- ## Options Reference
11
-
12
- |Property|Value|
13
- |:--|:--|
14
- |Type Name|\`CommonInlineStoreOptions\`|
15
- |Source Path|\`./packages/ui/src/theme/options.ts\`|
16
-
17
- \*ExtractedTypeTable: Could not extract "CommonInlineStoreOptions" from "./packages/ui/src/theme/options.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
18
-
19
- |Property|Value|
20
- |:--|:--|
21
- |Type Name|\`ConsentManagerContentOptions\`|
22
- |Source Path|\`./packages/ui/src/theme/options.ts\`|
23
-
24
- \*ExtractedTypeTable: Could not extract "ConsentManagerContentOptions" from "./packages/ui/src/theme/options.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
25
-
26
- |Property|Value|
27
- |:--|:--|
28
- |Type Name|\`UIOptions\`|
29
- |Source Path|\`./packages/ui/src/theme/types.ts\`|
30
-
31
- \*ExtractedTypeTable: Could not extract "UIOptions" from "./packages/ui/src/theme/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
32
-
33
- ## Content Security Policy
34
-
35
- c15t injects a `<style id="c15t-theme">` element for your theme tokens, and the script loader injects a `<script>` element per consented vendor. Under a nonce-based Content Security Policy, both are blocked unless they carry your nonce.
36
-
37
- Pass it once through the `nonce` option and c15t applies it to everything it injects:
38
-
39
- ```tsx
40
- <ConsentManagerProvider
41
- options={{
42
- mode: 'offline',
43
- nonce: yourRequestNonce,
44
- }}
45
- >
46
- {children}
47
- </ConsentManagerProvider>
48
- ```
49
-
50
- A `nonce` set on an individual script definition still wins, so you can override a single vendor without changing the provider.
51
-
52
- > 📝 **Note:**
53
- > Browsers hide the nonce content attribute once a policy is active. Inspecting the element shows no nonce="", but element.nonce still returns the value — this is expected and not a sign that c15t dropped it.
54
-
55
- ### Inline style attributes
56
-
57
- The `nonce` option covers the elements c15t injects. It cannot cover inline `style="..."` attributes, which several components rely on — a nonce never authorizes a style attribute, because nonces apply to elements only.
58
-
59
- Style attributes are governed by `style-src-attr`, and when that directive is absent CSP falls back to `style-src`. A nonce-based style policy therefore blocks them:
60
-
61
- ```http
62
- style-src 'self' 'nonce-abc123';
63
- ```
64
-
65
- To keep the nonce requirement for stylesheets while still allowing style attributes, set `style-src-attr` explicitly:
66
-
67
- ```http
68
- style-src 'self' 'nonce-abc123';
69
- style-src-attr 'unsafe-inline';
70
- ```
71
-
72
- > ⚠️ **Warning:**
73
- > 'unsafe-inline' on style-src-attr permits any inline style attribute on the page. That is weaker than a nonce, but far narrower than replacing your nonce-based style-src with 'unsafe-inline', which would additionally authorize arbitrary injected \<style> elements. Note that adding 'unsafe-inline' alongside a nonce achieves nothing — a directive that specifies a nonce ignores it. If your threat model does not allow this, expect components that use inline styles to render unstyled.
74
-
75
- ## Legal Links
76
-
77
- `legalLinks` defines the URLs shown in consent UI text (banner, dialog, and widget where applicable).
78
- Configure only the links you want to expose.
79
-
80
- ```tsx
81
- <ConsentManagerProvider
82
- options={{
83
- backendURL: 'https://your-instance.c15t.dev',
84
- legalLinks: {
85
- privacyPolicy: {
86
- href: '/privacy',
87
- target: '_self',
88
- },
89
- cookiePolicy: {
90
- href: '/cookies',
91
- target: '_self',
92
- },
93
- termsOfService: {
94
- href: 'https://example.com/terms',
95
- target: '_blank',
96
- rel: 'noopener noreferrer',
97
- label: 'Terms of Service',
98
- },
99
- },
100
- }}
101
- >
102
- ```
103
-
104
- Notes:
105
-
106
- * Omitting a key (for example `termsOfService`) hides that link.
107
- * `label` overrides the translated text for that single link.
108
- * Use `_self` for internal pages and `_blank` + `rel="noopener noreferrer"` for external pages.
109
- * Control which of the configured links render in each component via the component's `legalLinks` prop.
110
-
111
- ## Overrides
112
-
113
- `overrides` lets you force location/language signals instead of browser or network detection.
114
- This is useful for QA, local development, and preview environments.
115
-
116
- ```tsx
117
- <ConsentManagerProvider
118
- options={{
119
- backendURL: 'https://your-instance.c15t.dev',
120
- overrides: {
121
- country: 'DE',
122
- region: 'BY',
123
- language: 'de-DE',
124
- },
125
- }}
126
- >
127
- ```
128
-
129
- You can also override Global Privacy Control (GPC) behavior during testing:
130
-
131
- ```tsx
132
- <ConsentManagerProvider
133
- options={{
134
- backendURL: 'https://your-instance.c15t.dev',
135
- overrides: {
136
- gpc: true,
137
- },
138
- }}
139
- >
140
- ```
141
-
142
- > ⚠️ **Warning:**
143
- > Treat overrides as an environment/testing tool. Avoid hard-coding production overrides unless that behavior is intentional for your deployment.
144
-
145
- ## Policy Packs
146
-
147
- In hosted mode (recommended), the backend resolves the correct policy automatically — no frontend policy config needed:
148
-
149
- ```tsx
150
- <ConsentManagerProvider
151
- options={{
152
- backendURL: 'https://your-instance.c15t.dev',
153
- }}
154
- >
155
- ```
156
-
157
- ### Fallback: Offline Policies
158
-
159
- When no backend is available, `ConsentManagerProvider` accepts `offlinePolicy.policyPacks` for local policy resolution during development, testing, previews, or temporary backend outages:
160
-
161
- ```tsx
162
- <ConsentManagerProvider
163
- options={{
164
- mode: 'offline',
165
- offlinePolicy: {
166
- i18n: {
167
- defaultProfile: 'default',
168
- messages: {
169
- default: {
170
- translations: {
171
- en: { cookieBanner: { title: 'Privacy choices' } },
172
- },
173
- },
174
- qc: {
175
- fallbackLanguage: 'fr',
176
- translations: {
177
- en: { cookieBanner: { title: 'Quebec Privacy Settings' } },
178
- fr: { cookieBanner: { title: 'Paramètres de confidentialité du Québec' } },
179
- },
180
- },
181
- },
182
- },
183
- policyPacks: [
184
- {
185
- id: 'qc_opt_in',
186
- match: { regions: [{ country: 'CA', region: 'QC' }] },
187
- i18n: { messageProfile: 'qc' },
188
- consent: { model: 'opt-in', expiryDays: 365 },
189
- ui: { mode: 'banner' },
190
- },
191
- {
192
- id: 'default_world',
193
- match: { isDefault: true },
194
- consent: { model: 'none' },
195
- ui: { mode: 'none' },
196
- },
197
- ],
198
- },
199
- overrides: {
200
- country: 'CA',
201
- region: 'QC',
202
- },
203
- }}
204
- >
205
- ```
206
-
207
- Notes:
208
-
209
- * `offlinePolicy` is only used in `offline` mode.
210
- * Treat offline policies as a development/testing tool or resilience fallback, not the primary production source of truth.
211
- * `offlinePolicy.i18n` lets offline mode mirror hosted `messageProfile` and profile-local `fallbackLanguage` behavior.
212
- * Omitting `offlinePolicy.policyPacks` uses the built-in synthetic opt-in fallback banner. Hosted network fallback uses the same opt-in banner.
213
- * `offlinePolicy: { policyPacks: [] }` is explicit no-banner mode.
214
- * In hosted mode, backend `policyPacks` remain the source of truth — frontend offline policies never override a live backend decision.
215
-
216
- 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).
217
-
218
- ## Props
219
-
220
- |Property|Value|
221
- |:--|:--|
222
- |Type Name|\`ConsentManagerProviderProps\`|
223
- |Source Path|\`./packages/react/src/types/consent-manager.ts\`|
224
-
225
- \*ExtractedTypeTable: Could not extract "ConsentManagerProviderProps" from "./packages/react/src/types/consent-manager.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
@@ -1,121 +0,0 @@
1
- ---
2
- title: Consent Widget
3
- description: Reference page for consent widget.
4
- group: reference
5
- ---
6
- `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.
7
-
8
- ## Configuration
9
-
10
- ```tsx
11
- <ConsentWidget
12
- hideBranding
13
- legalLinks={['privacyPolicy', 'cookiePolicy']}
14
- noStyle={false}
15
- disableAnimation={false}
16
- />
17
- ```
18
-
19
- ## Accordion Behavior
20
-
21
- 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.
22
-
23
- ## Styling First
24
-
25
- > ℹ️ **Info:**
26
- > Most widget customization should stay in the stock component. Use theme tokens and slots such as consentWidgetAccordion, consentWidgetFooter, consentWidgetFooterSubGroup, and toggle before reaching for compound components. See Styling Overview.
27
-
28
- ```tsx
29
- <ConsentManagerProvider
30
- options={{
31
- theme: {
32
- colors: {
33
- surface: '#fffdf8',
34
- surfaceHover: '#f6f3ee',
35
- },
36
- slots: {
37
- consentWidgetAccordion: 'rounded-3xl border border-black/10',
38
- consentWidgetFooter: 'border-t border-black/10 px-6',
39
- consentWidgetFooterSubGroup: 'gap-3',
40
- toggle: 'shadow-sm',
41
- },
42
- },
43
- }}
44
- >
45
- <ConsentWidget />
46
- </ConsentManagerProvider>
47
- ```
48
-
49
- Use `consentWidgetFooter` for styling the whole action area, such as border and padding. Use `consentWidgetFooterSubGroup` for spacing or alignment inside nested button groups.
50
-
51
- Widget copy should be changed through `ConsentManagerProvider.options.i18n` so the inline UI stays aligned with the rest of the consent experience.
52
-
53
- ## Advanced: Compound Components
54
-
55
- Use compound components only when you need to rearrange the widget's existing primitives while keeping policy-aware action grouping:
56
-
57
- ```tsx
58
- <ConsentWidget.Root>
59
- <ConsentWidget.Accordion type="multiple">
60
- <ConsentWidget.AccordionItems />
61
- </ConsentWidget.Accordion>
62
- <ConsentWidget.PolicyActions />
63
- </ConsentWidget.Root>
64
- ```
65
-
66
- * `ConsentWidget.Root` — Theme context provider
67
- * `ConsentWidget.Accordion` — Radix-based accordion root
68
- * `ConsentWidget.AccordionItems` — Auto-generates toggle items from consent config
69
- * `ConsentWidget.AccordionItem` — Individual category item
70
- * `ConsentWidget.AccordionTrigger` — Clickable header for each item
71
- * `ConsentWidget.AccordionContent` — Collapsible content area
72
- * `ConsentWidget.AccordionArrow` — Expand/collapse indicator
73
- * `ConsentWidget.Switch` — Category toggle switch
74
- * `ConsentWidget.PolicyActions` — Renders grouped policy-aware actions
75
- * `ConsentWidget.Footer` — Footer container
76
- * `ConsentWidget.FooterSubGroup` — Groups related buttons
77
- * `ConsentWidget.AcceptAllButton` — Accepts all consent
78
- * `ConsentWidget.RejectButton` — Rejects all consent
79
- * `ConsentWidget.SaveButton` — Saves custom selections
80
-
81
- ## Using `renderAction` with c15t Defaults
82
-
83
- `ConsentWidget.PolicyActions` renders stock c15t buttons and translations by default.
84
-
85
- ```tsx
86
- <ConsentWidget.PolicyActions />
87
- ```
88
-
89
- `renderAction` is optional. Return the stock button compounds when you want custom mapping while preserving built-in c15t behavior and copy:
90
-
91
- ```tsx
92
- <ConsentWidget.PolicyActions
93
- renderAction={(action, props) => {
94
- const { key, ...buttonProps } = props
95
-
96
- switch (action) {
97
- case 'accept':
98
- return <ConsentWidget.AcceptAllButton key={key} {...buttonProps} />
99
- case 'reject':
100
- return <ConsentWidget.RejectButton key={key} {...buttonProps} />
101
- case 'customize':
102
- return <ConsentWidget.SaveButton key={key} {...buttonProps} />
103
- }
104
- }}
105
- />
106
- ```
107
-
108
- `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`.
109
-
110
- For a fixed footer layout, render `ConsentWidget.Footer` and `ConsentWidget.FooterSubGroup` manually instead of using `ConsentWidget.PolicyActions`.
111
-
112
- If the stock widget structure is already correct, stay with tokens and slots instead of rebuilding the layout.
113
-
114
- ## Props
115
-
116
- |Property|Value|
117
- |:--|:--|
118
- |Type Name|\`ConsentWidgetProps\`|
119
- |Source Path|\`./packages/react/src/components/consent-widget/types.ts\`|
120
-
121
- \*ExtractedTypeTable: Could not extract "ConsentWidgetProps" from "./packages/react/src/components/consent-widget/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
@@ -1,81 +0,0 @@
1
- ---
2
- title: Dev Tools
3
- description: Reference page for dev tools.
4
- group: reference
5
- ---
6
- `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.
7
-
8
- > ⚠️ **Warning:**
9
- > DevTools should only be included in development builds. The component renders nothing to the React tree - it injects directly into document.body.
10
-
11
- ## Installation
12
-
13
- DevTools lives in a separate package to keep it out of production bundles:
14
-
15
- ```bash
16
- bun add -D @c15t/dev-tools
17
- ```
18
-
19
- ## Configuration
20
-
21
- ```tsx
22
- <DevTools
23
- position="bottom-right" // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
24
- defaultOpen={false} // Start with panel open
25
- namespace="c15tStore" // Store namespace to connect to
26
- disabled={false} // Disable without removing from tree
27
- />
28
- ```
29
-
30
- ## Panels
31
-
32
- |Panel|What it shows|
33
- |--|--|
34
- |**Consents**|Current consent state for all categories|
35
- |**Location**|Detected jurisdiction, country, region, and consent model|
36
- |**Scripts**|Configured scripts and their load status|
37
- |**IAB**|IAB TCF state (when enabled) - TC string, vendor consents, purposes|
38
- |**Events**|Timeline of consent events and state changes|
39
- |**Actions**|Buttons to trigger consent actions (accept all, reject all, reset)|
40
-
41
- ## TanStack Devtools
42
-
43
- `@c15t/dev-tools/tanstack` exposes a panel component and plugin factory that match TanStack Devtools' plugin API, so c15t can sit beside Query and Router without a custom mount adapter:
44
-
45
- ```tsx
46
- import * as React from 'react';
47
- import { useRouter } from '@tanstack/react-router';
48
- import { TanStackDevtools } from '@tanstack/react-devtools';
49
- import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools';
50
- import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools';
51
- import { c15tDevtools } from '@c15t/dev-tools/tanstack';
52
-
53
- export function AppDevtools() {
54
- const router = useRouter();
55
-
56
- return (
57
- <TanStackDevtools
58
- plugins={[
59
- {
60
- name: 'TanStack Query',
61
- render: <ReactQueryDevtoolsPanel />,
62
- },
63
- {
64
- name: 'TanStack Router',
65
- render: <TanStackRouterDevtoolsPanel router={router} />,
66
- },
67
- c15tDevtools(),
68
- ]}
69
- />
70
- );
71
- }
72
- ```
73
-
74
- ## Props
75
-
76
- |Property|Value|
77
- |:--|:--|
78
- |Type Name|\`C15TDevToolsProps\`|
79
- |Source Path|\`./packages/dev-tools/src/react.ts\`|
80
-
81
- \*ExtractedTypeTable: Could not extract "C15TDevToolsProps" from "./packages/dev-tools/src/react.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
@@ -1,52 +0,0 @@
1
- ---
2
- title: Frame
3
- description: Reference page for frame.
4
- group: reference
5
- ---
6
- `Frame` conditionally renders its children based on consent state. When consent for the specified category is not granted, a placeholder is shown instead. Children are not mounted at all until consent is given, preventing any network requests or script execution.
7
-
8
- ## Custom Placeholder
9
-
10
- Replace the default placeholder:
11
-
12
- ```tsx
13
- <Frame
14
- category="experience"
15
- placeholder={
16
- <div className="rounded-lg border p-8 text-center">
17
- <p>This content requires experience cookies.</p>
18
- <p>Please enable them in your privacy settings.</p>
19
- </div>
20
- }
21
- >
22
- <InteractiveWidget />
23
- </Frame>
24
- ```
25
-
26
- ## Compound Components
27
-
28
- Build fully custom placeholder layouts:
29
-
30
- ```tsx
31
- <Frame.Root category="marketing">
32
- <Frame.Title category="marketing" />
33
- <Frame.Button category="marketing" />
34
- </Frame.Root>
35
- ```
36
-
37
- * `Frame.Root` - Container with default placeholder styling
38
- * `Frame.Title` - Displays a consent-request message with the category name
39
- * `Frame.Button` - Button that opens the consent dialog for the specified category
40
-
41
- ## Automatic Category Registration
42
-
43
- When `Frame` mounts, it automatically adds its `category` to the active `consentCategories` list. This means you don't need to explicitly list the category in your provider's `consentCategories` option - if a `Frame` component uses it, it will be registered.
44
-
45
- ## Props
46
-
47
- |Property|Value|
48
- |:--|:--|
49
- |Type Name|\`FrameProps\`|
50
- |Source Path|\`./packages/react/src/components/frame/types.ts\`|
51
-
52
- \*ExtractedTypeTable: Could not extract "FrameProps" from "./packages/react/src/components/frame/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
@@ -1,110 +0,0 @@
1
- ---
2
- title: Building Headless Components
3
- description: Reference page for building headless components.
4
- group: reference
5
- ---
6
- Building custom consent UI is easier now because c15t exposes multiple layers of policy-aware primitives instead of forcing you to reconstruct banner rules by hand.
7
-
8
- Think of customization as a ladder:
9
-
10
- * stock component props for the shortest path
11
- * `ConsentBanner.PolicyActions` and `ConsentWidget.PolicyActions` when you want custom structure but still want c15t to resolve policy-aware actions
12
- * `useHeadlessConsentUI()` when you need fully manual action rendering, custom controls, or non-standard flow
13
-
14
- > ⚠️ **Warning:**
15
- > Headless is the last step in the customization ladder. Use this guide only when pre-built components, tokens, slots, compound components, and noStyle are no longer sufficient.
16
-
17
- The headless stack underneath that is:
18
-
19
- * `useHeadlessConsentUI()` for policy-aware banner/dialog actions, ordering, layout, and primary actions hints
20
- * `@c15t/ui/utils` for the pure policy-action helpers that framework packages build on
21
- * `useConsentManager()` for runtime state, categories, selected consent state, and policy metadata
22
- * `useTranslations()` for the resolved copy
23
- * `offlinePolicy.policyPacks` for offline previews that behave like backend policy resolution
24
-
25
- The split is intentional: `@c15t/ui` owns pure policy-action resolution, while the framework hooks own visibility, consent mutations, and reactive state.
26
-
27
- > ℹ️ **Info:**
28
- > This guide is about building your own components while still respecting resolved policy-pack behavior. For the general headless overview, see Headless Mode.
29
-
30
- ## Choose the Smallest Layer That Solves the Job
31
-
32
- Start with the smallest API surface that still gives you the behavior you need:
33
-
34
- * Stay with stock components when you only need theming, spacing, copy, or legal-link changes
35
- * Use `ConsentBanner.PolicyActions` or `ConsentWidget.PolicyActions` when you want a custom compound-component layout but still want grouped actions, ordering, and primary emphasis to come from policy
36
- * Add `renderAction` when the grouping is still correct but you want to remap actions to stock c15t button compounds
37
- * Reach for `useHeadlessConsentUI()` only when you need custom button elements, need to map `actionGroups` yourself, wire non-button controls, or coordinate the consent UI with a more custom state machine
38
-
39
- This order matters because every step down the ladder gives you more control, but also makes it easier for your UI to drift away from the resolved policy if you stop using the provided state.
40
-
41
- ## Before You Build Headless UI
42
-
43
- Do not use headless mode for problems that are still inside the stock component model:
44
-
45
- * Use `layout`, `direction`, `primaryButton`, and `legalLinks` before you rebuild banner markup
46
- * Use `theme.consentActions` before you swap out stock actions
47
- * Use tokens such as `colors.surface` and `colors.surfaceHover` before raw CSS overrides
48
- * Use slots such as `consentBannerCard`, `consentBannerFooter`, and `consentDialogCard` before compound components
49
- * Use `ConsentManagerProvider.options.i18n` before rebuilding UI just to change text
50
-
51
- A good rule: if the stock banner or dialog structure is still correct, you probably do not need headless mode.
52
-
53
- ## What the Headless Tooling Gives You
54
-
55
- The main win is that your custom UI can stay aligned with policy packs without duplicating policy logic in your components.
56
-
57
- `useHeadlessConsentUI()` already resolves:
58
-
59
- * which actions are allowed
60
- * the order those actions should render in
61
- * grouped actions from policy `layout`
62
- * layout `direction` (`row` or `column`)
63
- * the primary actions
64
- * UI profile and scroll-lock hints
65
- * whether the banner or dialog should currently be visible
66
-
67
- The hook also gives you the policy-aware action helpers you are expected to call:
68
-
69
- * `performBannerAction('accept' | 'reject')`
70
- * `performDialogAction('accept' | 'reject')`
71
- * `saveCustomPreferences()` for the dialog `customize` action
72
- * `openDialog()`, `openBanner()`, and `closeUI()` for surface visibility
73
-
74
- That means your component mostly focuses on markup and design-system concerns instead of re-implementing policy interpretation.
75
-
76
- For most compound-component layouts, start with `ConsentBanner.PolicyActions` or `ConsentWidget.PolicyActions`. They render stock c15t buttons and translations by default, and `renderAction` is only needed when you want to override which stock compound renders for each action. Reach for manual `actionGroups` mapping when you need action rendering that no longer fits the stock button compounds.
77
-
78
- ## What Headless Is Not For
79
-
80
- Headless mode is not the recommended path for:
81
-
82
- * changing the banner footer background
83
- * rounding the stock banner card
84
- * restyling stock banner or dialog buttons
85
- * changing consent copy
86
-
87
- Those should stay in the pre-built stack with tokens, slots, `theme.consentActions`, and provider `i18n`.
88
-
89
- ## What a Policy-Aware Headless Component Should Respect
90
-
91
- When you build custom banner or dialog components, make sure they use:
92
-
93
- * `activeUI` or `banner.isVisible` / `dialog.isVisible` for visibility
94
- * `allowedActions`, `actionGroups`, and `primaryActions` instead of hard-coding buttons
95
- * `primaryActions` for visual emphasis
96
- * `consentCategories` when deciding which category toggles to render
97
- * `policyDecision` when you want to debug why a specific UI state was chosen
98
-
99
- If you ignore those values, your custom UI can drift away from the resolved policy pack even though the underlying consent engine is configured correctly.
100
-
101
- ## Validation and Testing
102
-
103
- If you are building a reusable headless component library, validate your rendered UI against the resolved runtime policy in tests.
104
-
105
- The core package exposes:
106
-
107
- * `getEffectivePolicy(initData)` to read the resolved policy from `/init`
108
- * `validateUIAgainstPolicy({ policy, state })` to detect mismatches such as wrong actions, layout, or mode
109
-
110
- This is useful when your design system renders custom button arrangements and you want tests to catch policy drift early.
@@ -1,89 +0,0 @@
1
- ---
2
- title: Callbacks
3
- description: Reference page for callbacks.
4
- group: reference
5
- ---
6
- Callbacks let you run custom code at key points in the consent lifecycle. Define them in the provider or runtime `callbacks` option, or register them dynamically after initialization.
7
-
8
- For analytics SDKs and other change-only integrations, prefer `subscribeToConsentChanges()` or `onConsentChanged`. Use `onConsentSet` when you want the broader lifecycle signal, including initialization, automatic defaults, and replay-aware registration.
9
-
10
- ## Choose the Right Surface
11
-
12
- |Surface|Replays when registered late?|Fires on init / hydration / auto-grants?|Best for|
13
- |--|--|--|--|
14
- |`onBannerFetched`|Yes, via `setCallback('onBannerFetched', ...)` after init|Yes|Logging resolved policy, location, and translations|
15
- |`onConsentSet`|Yes, via `setCallback('onConsentSet', ...)`|Yes|Broad lifecycle hooks, debugging, and integrations that want the latest full state regardless of how it was reached|
16
- |`onConsentChanged`|No|No|Declarative change-only integrations|
17
- |`subscribeToConsentChanges()`|No|No|Canonical change-only subscriptions after mount|
18
-
19
- > ℹ️ **Info:**
20
- > Script.onConsentChange is a script-scoped lifecycle hook. It is not the global consent change API for analytics SDKs or other app-wide integrations.
21
-
22
- ## Available Callbacks
23
-
24
- ### `onBannerFetched`
25
-
26
- Called when the consent banner data is fetched from the backend (or loaded from SSR data). The payload includes jurisdiction info, location data, and resolved translations.
27
-
28
- ```tsx
29
- onBannerFetched: ({ jurisdiction, location, translations }) => {
30
- // jurisdiction: 'GDPR' | 'CCPA' | { code: 'GDPR', message: '...' } | ...
31
- // location: { countryCode: 'DE', regionCode: 'BY' }
32
- // translations: { language: 'de', translations: {...} }
33
- }
34
- ```
35
-
36
- ### `onConsentSet`
37
-
38
- Called whenever c15t broadly settles consent state: store initialization, automatic defaults during init, explicit saves, and replay via `setCallback('onConsentSet', ...)`.
39
-
40
- ```tsx
41
- onConsentSet: ({ preferences }) => {
42
- // preferences: { necessary: true, measurement: true, marketing: false, ... }
43
- console.log('Latest consent state:', preferences);
44
- }
45
- ```
46
-
47
- ### `onConsentChanged`
48
-
49
- Called only after an explicit `saveConsents()` or `setConsent()` that actually changes the saved consent state. It never fires on store creation, hydration, automatic grants, unchanged saves, or `setCallback('onConsentChanged', ...)`.
50
-
51
- ```tsx
52
- onConsentChanged: ({
53
- preferences,
54
- previousPreferences,
55
- allowedCategories,
56
- deniedCategories,
57
- previousAllowedCategories,
58
- previousDeniedCategories,
59
- }) => {
60
- analytics.syncConsent({
61
- allowedCategories,
62
- deniedCategories,
63
- previousAllowedCategories,
64
- previousDeniedCategories,
65
- });
66
- }
67
- ```
68
-
69
- ### `onError`
70
-
71
- Called when an error occurs during consent operations (e.g., API request failure). If no `onError` callback is provided, errors are logged to `console.error`.
72
-
73
- ```tsx
74
- onError: ({ error }) => {
75
- // error: string describing what went wrong
76
- Sentry.captureMessage(`Consent error: ${error}`);
77
- }
78
- ```
79
-
80
- ### `onBeforeConsentRevocationReload`
81
-
82
- Called synchronously before the page reloads due to consent revocation. This is your last chance to run cleanup before the reload. Keep this callback fast - avoid async operations.
83
-
84
- ```tsx
85
- onBeforeConsentRevocationReload: ({ preferences }) => {
86
- // Flush any pending data
87
- navigator.sendBeacon('/api/flush', JSON.stringify({ session: sessionId }));
88
- }
89
- ```