@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.3

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 (241) hide show
  1. package/AGENTS.md +9 -2
  2. package/dist/aggregate-components.js +1 -1
  3. package/dist/chunk-warming.js +1 -1
  4. package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
  5. package/dist/component-hooks/use-panel-trigger.js +1 -1
  6. package/dist/components/consent-gate/atoms.js +1 -0
  7. package/dist/components/consent-gate/consent-gate.js +2 -0
  8. package/dist/components/consent-gate/index.js +2 -0
  9. package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
  10. package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
  11. package/dist/components/iab-panel/atoms/stack-item.js +1 -1
  12. package/dist/components/iab-panel/iab-panel.js +1 -1
  13. package/dist/components/iab-panel/index.js +1 -1
  14. package/dist/components/panel/atoms/overlay.js +1 -1
  15. package/dist/components/panel/atoms/root.js +1 -1
  16. package/dist/components/panel/index.js +1 -1
  17. package/dist/components/panel/panel.js +1 -1
  18. package/dist/components/panel-trigger/atoms/button.js +1 -1
  19. package/dist/components/panel-trigger/atoms/icon.js +1 -1
  20. package/dist/components/panel-trigger/atoms/root.js +1 -1
  21. package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
  22. package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
  23. package/dist/components/preferences/atoms/accordion.js +1 -1
  24. package/dist/components/preferences/atoms/root.js +1 -1
  25. package/dist/components/preferences/atoms/vendor-list.js +1 -0
  26. package/dist/components/preferences/index.js +1 -1
  27. package/dist/components/prompt/policy-actions.js +1 -1
  28. package/dist/components/shared/primitives/button.js +1 -1
  29. package/dist/components/shared/ui/accordion/accordion.js +1 -1
  30. package/dist/components/shared/ui/collapsible/collapsible.js +1 -1
  31. package/dist/components/shared/ui/logo.js +1 -1
  32. package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
  33. package/dist/components/shared/ui/switch/switch.js +1 -1
  34. package/dist/components/shared/ui/tabs/tabs.js +1 -1
  35. package/dist/consent-gate.js +2 -0
  36. package/dist/consent-theme.js +1 -0
  37. package/dist/draft.js +1 -1
  38. package/dist/external-iab-context.js +1 -1
  39. package/dist/headless.js +1 -1
  40. package/dist/hooks/use-committed-ref.js +2 -0
  41. package/dist/hooks.js +1 -1
  42. package/dist/iab/styles.tw3.css +1 -41
  43. package/dist/iab-context.js +1 -1
  44. package/dist/index.js +1 -1
  45. package/dist/kernel-selector.js +1 -0
  46. package/dist/module-hooks/iframe-blocker.js +1 -1
  47. package/dist/module-hooks/network-blocker.js +1 -1
  48. package/dist/module-hooks/network-hold.js +2 -0
  49. package/dist/module-hooks/persistence.js +1 -1
  50. package/dist/panel.js +1 -1
  51. package/dist/preferences.js +1 -2
  52. package/dist/provider.js +1 -1
  53. package/dist/styles.tw3.css +1 -43
  54. package/dist/ui-save.js +1 -1
  55. package/dist/utils/deferred-module.js +2 -0
  56. package/dist/version.js +1 -1
  57. package/dist-types/aggregate-components.d.ts +2 -2
  58. package/dist-types/chunk-warming.d.ts +41 -8
  59. package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +2 -2
  60. package/dist-types/components/consent-gate/atoms.d.ts +11 -0
  61. package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
  62. package/dist-types/components/consent-gate/index.d.ts +41 -0
  63. package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
  64. package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
  65. package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
  66. package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +5 -2
  67. package/dist-types/components/iab-panel/atoms/stack-item.d.ts +7 -2
  68. package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
  69. package/dist-types/components/iab-panel/iab-panel.d.ts +1 -1
  70. package/dist-types/components/iab-panel/index.d.ts +25 -24
  71. package/dist-types/components/iab-prompt/index.d.ts +17 -17
  72. package/dist-types/components/panel/atoms/card.d.ts +4 -4
  73. package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
  74. package/dist-types/components/panel/index.d.ts +8 -7
  75. package/dist-types/components/panel/panel.d.ts +3 -3
  76. package/dist-types/components/panel-link/index.d.ts +1 -1
  77. package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
  78. package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
  79. package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
  80. package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
  81. package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +20 -0
  82. package/dist-types/components/panel-trigger/index.d.ts +4 -4
  83. package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
  84. package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -9
  85. package/dist-types/components/panel-trigger/types.d.ts +1 -1
  86. package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
  87. package/dist-types/components/preferences/atoms/button.d.ts +1 -1
  88. package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
  89. package/dist-types/components/preferences/atoms/root.d.ts +1 -1
  90. package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
  91. package/dist-types/components/preferences/index.d.ts +14 -11
  92. package/dist-types/components/preferences/policy-actions.d.ts +2 -2
  93. package/dist-types/components/preferences/preferences.d.ts +1 -1
  94. package/dist-types/components/preferences/types.d.ts +1 -1
  95. package/dist-types/components/prompt/components.d.ts +3 -3
  96. package/dist-types/components/prompt/index.d.ts +11 -11
  97. package/dist-types/components/prompt/policy-actions.d.ts +2 -2
  98. package/dist-types/components/prompt/prompt.d.ts +1 -1
  99. package/dist-types/components/shared/policy-actions.d.ts +2 -2
  100. package/dist-types/components/shared/primitives/box.d.ts +1 -1
  101. package/dist-types/components/shared/primitives/button.d.ts +2 -2
  102. package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
  103. package/dist-types/components/shared/ui/accordion/accordion.d.ts +3 -2
  104. package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
  105. package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
  106. package/dist-types/components/shared/ui/branding.d.ts +1 -1
  107. package/dist-types/components/shared/ui/button/button.d.ts +1 -1
  108. package/dist-types/components/shared/ui/button/index.d.ts +2 -2
  109. package/dist-types/components/shared/ui/collapsible/collapsible.d.ts +1 -0
  110. package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
  111. package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
  112. package/dist-types/components/shared/ui/logo.d.ts +0 -10
  113. package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
  114. package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +14 -0
  115. package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
  116. package/dist-types/components/shared/ui/switch/switch.d.ts +2 -1
  117. package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
  118. package/dist-types/components/shared/ui/tabs/tabs.d.ts +1 -0
  119. package/dist-types/consent-gate.d.ts +1 -0
  120. package/dist-types/consent-theme.d.ts +38 -0
  121. package/dist-types/context/index.d.ts +3 -3
  122. package/dist-types/context/theme-context.d.ts +1 -1
  123. package/dist-types/draft.d.ts +96 -7
  124. package/dist-types/headless.d.ts +6 -7
  125. package/dist-types/hooks/use-committed-ref.d.ts +24 -0
  126. package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
  127. package/dist-types/hooks/use-iab-manager.d.ts +1 -1
  128. package/dist-types/hooks/use-theme.d.ts +1 -1
  129. package/dist-types/hooks.d.ts +30 -1
  130. package/dist-types/iab.d.ts +5 -5
  131. package/dist-types/index.d.ts +26 -25
  132. package/dist-types/kernel-selector.d.ts +66 -0
  133. package/dist-types/module-hooks/iframe-blocker.d.ts +27 -0
  134. package/dist-types/module-hooks/network-blocker.d.ts +23 -0
  135. package/dist-types/module-hooks/network-hold.d.ts +47 -0
  136. package/dist-types/module-hooks.d.ts +4 -4
  137. package/dist-types/panel-link.d.ts +1 -1
  138. package/dist-types/panel-trigger.d.ts +1 -1
  139. package/dist-types/panel.d.ts +13 -1
  140. package/dist-types/preferences.d.ts +12 -1
  141. package/dist-types/primitives/accordion.d.ts +1 -1
  142. package/dist-types/primitives/button.d.ts +1 -1
  143. package/dist-types/primitives/collapsible.d.ts +1 -1
  144. package/dist-types/primitives/dialog.d.ts +1 -1
  145. package/dist-types/primitives/preference-item.d.ts +1 -1
  146. package/dist-types/primitives/switch.d.ts +1 -1
  147. package/dist-types/primitives/tabs.d.ts +1 -1
  148. package/dist-types/primitives.d.ts +7 -7
  149. package/dist-types/prompt.d.ts +1 -1
  150. package/dist-types/provider.d.ts +62 -12
  151. package/dist-types/server/fetch-ssr-data.d.ts +1 -1
  152. package/dist-types/server/index.d.ts +5 -5
  153. package/dist-types/theme-provider.d.ts +2 -2
  154. package/dist-types/types/index.d.ts +3 -3
  155. package/dist-types/types/manager.d.ts +1 -1
  156. package/dist-types/types/theme/index.d.ts +1 -1
  157. package/dist-types/ui-config-context.d.ts +3 -1
  158. package/dist-types/ui-save.d.ts +21 -1
  159. package/dist-types/utils/deferred-module.d.ts +13 -0
  160. package/dist-types/utils/index.d.ts +4 -4
  161. package/dist-types/utils/merge-slot-props.d.ts +2 -2
  162. package/dist-types/utils/merge-styles.d.ts +1 -1
  163. package/dist-types/utils/theme-utils.d.ts +1 -1
  164. package/dist-types/version.d.ts +1 -1
  165. package/docs/README.md +9 -2
  166. package/docs/customization/overview.md +4 -3
  167. package/docs/customization/recipes.md +4 -2
  168. package/docs/customization/tokens.md +66 -3
  169. package/docs/frameworks/react/components/consent-dialog.md +46 -7
  170. package/docs/frameworks/react/components/{frame.md → consent-gate.md} +35 -31
  171. package/docs/frameworks/react/components/consent-manager-provider.md +35 -11
  172. package/docs/frameworks/react/components/consent-widget.md +48 -6
  173. package/docs/frameworks/react/concepts/consent-categories.md +38 -2
  174. package/docs/frameworks/react/hooks/{use-consent-manager/overview.md → overview.md} +7 -5
  175. package/docs/frameworks/react/iab/overview.md +121 -1
  176. package/docs/frameworks/react/network-blocker.md +146 -0
  177. package/docs/frameworks/react/script-loader.md +6 -0
  178. package/docs/frameworks/react/styling/overview.md +71 -22
  179. package/docs/guides/consent-state.md +327 -0
  180. package/docs/guides/deployment-modes.md +12 -0
  181. package/docs/guides/shared-consent-controls.md +158 -0
  182. package/docs/integrations/adobe-analytics.md +1 -1
  183. package/docs/integrations/ahrefs-analytics.md +1 -1
  184. package/docs/integrations/amplitude.md +1 -1
  185. package/docs/integrations/building-integrations.md +5 -0
  186. package/docs/integrations/clearbit.md +1 -1
  187. package/docs/integrations/cloudflare-web-analytics.md +1 -1
  188. package/docs/integrations/cloudflare-zaraz.md +399 -0
  189. package/docs/integrations/crisp.md +1 -1
  190. package/docs/integrations/databuddy.md +1 -1
  191. package/docs/integrations/fathom-analytics.md +1 -1
  192. package/docs/integrations/front-chat.md +322 -0
  193. package/docs/integrations/google-maps.md +21 -21
  194. package/docs/integrations/google-tag-manager.md +1 -1
  195. package/docs/integrations/google-tag.md +1 -1
  196. package/docs/integrations/granular-consent.md +210 -0
  197. package/docs/integrations/heap.md +1 -1
  198. package/docs/integrations/hightouch.md +1 -1
  199. package/docs/integrations/hotjar.md +1 -1
  200. package/docs/integrations/intercom.md +1 -1
  201. package/docs/integrations/linkedin-insights.md +1 -1
  202. package/docs/integrations/logrocket.md +1 -1
  203. package/docs/integrations/matomo-analytics.md +1 -1
  204. package/docs/integrations/meta-pixel.md +1 -1
  205. package/docs/integrations/microsoft-clarity.md +1 -1
  206. package/docs/integrations/microsoft-uet.md +1 -1
  207. package/docs/integrations/mixpanel-analytics.md +1 -1
  208. package/docs/integrations/one-dollar-stats.md +305 -0
  209. package/docs/integrations/openai-pixel.md +1 -1
  210. package/docs/integrations/overview.md +22 -18
  211. package/docs/integrations/pinterest-tag.md +321 -0
  212. package/docs/integrations/pirsch.md +1 -1
  213. package/docs/integrations/plausible-analytics.md +1 -1
  214. package/docs/integrations/posthog.md +1 -1
  215. package/docs/integrations/promptwatch.md +1 -1
  216. package/docs/integrations/reddit-pixel.md +1 -1
  217. package/docs/integrations/rudderstack.md +1 -1
  218. package/docs/integrations/rybbit-analytics.md +1 -1
  219. package/docs/integrations/segment.md +1 -1
  220. package/docs/integrations/snapchat-pixel.md +1 -1
  221. package/docs/integrations/tiktok-pixel.md +1 -1
  222. package/docs/integrations/umami-analytics.md +1 -1
  223. package/docs/integrations/vercel-analytics.md +1 -1
  224. package/docs/integrations/x-pixel.md +1 -1
  225. package/docs/integrations/youtube.md +27 -22
  226. package/docs/upgrade-v3.md +176 -1
  227. package/package.json +26 -16
  228. package/dist/component-hooks/use-manager.js +0 -2
  229. package/dist/components/frame/atoms.js +0 -1
  230. package/dist/components/frame/frame.js +0 -2
  231. package/dist/components/frame/index.js +0 -2
  232. package/dist/frame.js +0 -2
  233. package/dist-types/component-hooks/use-manager.d.ts +0 -40
  234. package/dist-types/components/frame/atoms.d.ts +0 -11
  235. package/dist-types/components/frame/frame.d.ts +0 -2
  236. package/dist-types/components/frame/index.d.ts +0 -24
  237. package/dist-types/frame.d.ts +0 -1
  238. package/readme.json +0 -48
  239. package/src/iab/styles.css +0 -11
  240. package/src/styles.css +0 -10
  241. /package/dist/components/{frame → consent-gate}/types.js +0 -0
@@ -0,0 +1,47 @@
1
+ import type { NetworkBlockerRule } from '@c15t/core/modules/network-blocker';
2
+ import type { NetworkHold } from '@c15t/core/modules/network-hold';
3
+ /**
4
+ * How long a hold started during render waits for its component to commit.
5
+ * A render React throws away never commits, so nothing else would end its
6
+ * hold. When this runs out the hold ends, and since nothing checked consent
7
+ * for the requests it held, they get the blocker's answer for a blocked
8
+ * request instead of being sent.
9
+ * @internal
10
+ */
11
+ export declare const UNCOMMITTED_HOLD_MS = 10000;
12
+ /**
13
+ * The render-time hold behind one network blocker mount.
14
+ * @internal
15
+ */
16
+ export interface EarlyNetworkHold {
17
+ /**
18
+ * Call from the mount effect, before loading the blocker. Keeps the hold
19
+ * from expiring, starts a new one if it already ended (a StrictMode or
20
+ * kernel re-run after the blocker took over, or a commit that came after
21
+ * the expiry), and returns it for `createNetworkBlocker({ hold })`. A
22
+ * disabled blocker gets a hold that holds nothing, so it cannot end
23
+ * another caller's hold.
24
+ */
25
+ claim: (rules: readonly NetworkBlockerRule[], enabled: boolean | undefined) => NetworkHold;
26
+ /**
27
+ * Call from the mount effect's cleanup. Ends a hold no blocker took
28
+ * over, unless the effect runs again first (StrictMode, a kernel change).
29
+ * Nothing checked consent for what that hold held, so those requests get
30
+ * the blocker's answer for a blocked request instead of being sent.
31
+ */
32
+ unmount: () => void;
33
+ }
34
+ /**
35
+ * Hold requests matching `rules` from this component's first render in the
36
+ * browser, before any child renders or runs an effect. The network blocker
37
+ * loads after mount and takes the hold over.
38
+ *
39
+ * Rendering is not side-effect free: the first render patches `fetch` and
40
+ * `XMLHttpRequest`. That is safe because the hold only delays matching
41
+ * requests, a render React discards ends its hold after
42
+ * {@link UNCOMMITTED_HOLD_MS} (failing what it held as blocked), and on the
43
+ * server it does nothing.
44
+ *
45
+ * @internal
46
+ */
47
+ export declare const useEarlyNetworkHold: (rules: readonly NetworkBlockerRule[], enabled: boolean | undefined) => EarlyNetworkHold;
@@ -1,4 +1,4 @@
1
- export { type IframeBlockerHandle, type UseIframeBlockerOptions, useIframeBlocker, } from './module-hooks/iframe-blocker';
2
- export { type BlockedRequestInfo, type NetworkBlockerHandle, type NetworkBlockerRule, type UseNetworkBlockerOptions, useNetworkBlocker, } from './module-hooks/network-blocker';
3
- export { type PersistenceHandle, type PersistenceOptions, type UsePersistenceOptions, usePersistence, } from './module-hooks/persistence';
4
- export { type Script, type ScriptLoaderDebugEvent, type ScriptLoaderHandle, type UseScriptLoaderOptions, useScriptLoader, } from './module-hooks/script-loader';
1
+ export { type IframeBlockerHandle, type UseIframeBlockerOptions, useIframeBlocker, } from './module-hooks/iframe-blocker.js';
2
+ export { type BlockedRequestInfo, type NetworkBlockerHandle, type NetworkBlockerRule, type UseNetworkBlockerOptions, useNetworkBlocker, } from './module-hooks/network-blocker.js';
3
+ export { type PersistenceHandle, type PersistenceOptions, type UsePersistenceOptions, usePersistence, } from './module-hooks/persistence.js';
4
+ export { type Script, type ScriptLoaderDebugEvent, type ScriptLoaderHandle, type UseScriptLoaderOptions, useScriptLoader, } from './module-hooks/script-loader.js';
@@ -1 +1 @@
1
- export * from './components/panel-link';
1
+ export * from './components/panel-link/index.js';
@@ -1 +1 @@
1
- export * from './components/panel-trigger';
1
+ export * from './components/panel-trigger/index.js';
@@ -1 +1,13 @@
1
- export * from './components/panel';
1
+ /**
2
+ * `@c15t/react/consent-dialog`: the deferred `ConsentDialog`, the same
3
+ * component the `@c15t/react` entry exports. Its implementation and styles
4
+ * load when the dialog first opens, or earlier when something preloads it,
5
+ * so importing this entry adds nothing heavy to the first load.
6
+ *
7
+ * The eager dialog and its individual parts (`Card`, `Header`, `Overlay`,
8
+ * ...) are in `@c15t/react/components/consent-dialog`.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ export { ConsentDialog } from './aggregate-components.js';
13
+ export type { ConsentDialogCompoundComponent, ConsentDialogProps, } from './components/panel/index.js';
@@ -1 +1,12 @@
1
- export * from './components/preferences';
1
+ /**
2
+ * `@c15t/react/consent-widget`: the deferred `ConsentWidget`, the same
3
+ * component the `@c15t/react` entry exports. Its implementation and styles
4
+ * load when the widget first renders.
5
+ *
6
+ * The eager widget and its individual parts (`Accordion`, `Switch`, `Footer`,
7
+ * ...) are in `@c15t/react/components/consent-widget`.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ export { ConsentWidget } from './aggregate-components.js';
12
+ export type { ConsentWidgetCompoundComponent, ConsentWidgetProps, } from './components/preferences/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/accordion';
1
+ export * from '../components/shared/ui/accordion/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/button';
1
+ export * from '../components/shared/ui/button/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/collapsible';
1
+ export * from '../components/shared/ui/collapsible/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/dialog';
1
+ export * from '../components/shared/ui/dialog/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/preference-item';
1
+ export * from '../components/shared/ui/preference-item/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/switch';
1
+ export * from '../components/shared/ui/switch/index.js';
@@ -1 +1 @@
1
- export * from '../components/shared/ui/tabs';
1
+ export * from '../components/shared/ui/tabs/index.js';
@@ -1,7 +1,7 @@
1
- export * as Accordion from './components/shared/ui/accordion';
2
- export * as Button from './components/shared/ui/button';
3
- export * as Collapsible from './components/shared/ui/collapsible';
4
- export * as Dialog from './components/shared/ui/dialog';
5
- export * as PreferenceItem from './components/shared/ui/preference-item';
6
- export * as Switch from './components/shared/ui/switch';
7
- export * as Tabs from './components/shared/ui/tabs';
1
+ export * as Accordion from './components/shared/ui/accordion/index.js';
2
+ export * as Button from './components/shared/ui/button/index.js';
3
+ export * as Collapsible from './components/shared/ui/collapsible/index.js';
4
+ export * as Dialog from './components/shared/ui/dialog/index.js';
5
+ export * as PreferenceItem from './components/shared/ui/preference-item/index.js';
6
+ export * as Switch from './components/shared/ui/switch/index.js';
7
+ export * as Tabs from './components/shared/ui/tabs/index.js';
@@ -1 +1 @@
1
- export * from './components/prompt';
1
+ export * from './components/prompt/index.js';
@@ -1,15 +1,17 @@
1
- import type { AllConsentNames, ClearOnRevocationConfig, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User } from '@c15t/core';
1
+ import type { AllConsentNames, ClearOnRevocationConfig, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User, Vendor } from '@c15t/core';
2
2
  import type { Script } from '@c15t/core/modules/script-loader';
3
- import type { ConsentRuntime } from '@c15t/core/runtime';
3
+ import type { ConsentControlOptions, ConsentRuntime } from '@c15t/core/runtime';
4
4
  import type { ReactNode } from 'react';
5
- import type { UseNetworkBlockerOptions, UsePersistenceOptions, UseScriptLoaderOptions } from './module-hooks';
6
- import type { ReactUIOptions } from './types/manager';
7
- import type { ReactComponentSlots } from './types/slots';
5
+ import type { DialogPreload } from './chunk-warming.js';
6
+ import type { UseNetworkBlockerOptions, UsePersistenceOptions, UseScriptLoaderOptions } from './module-hooks.js';
7
+ import type { UseIframeBlockerOptions } from './module-hooks/iframe-blocker.js';
8
+ import type { ReactUIOptions } from './types/manager.js';
9
+ import type { ReactComponentSlots } from './types/slots.js';
8
10
  /** Events emitted by the mounted provider without snapshot-derived consent aliases. */
9
- export type ConsentProviderCallbacks = Pick<Callbacks, 'onChoiceRecorded' | 'onPermissionsChanged' | 'onError'>;
11
+ export type ConsentProviderCallbacks = Pick<Callbacks, 'onChoiceRecorded' | 'onPermissionsChanged' | 'onError' | 'onBeforeConsentRevocationReload'>;
10
12
  /** Prepared policy and records; legacy consent projections are not provider inputs. */
11
13
  export type ConsentProviderPrefetch = Omit<KernelConfig, 'initialDraft' | 'transport'>;
12
- export interface ConsentProviderOptions extends Pick<ReactUIOptions, 'colorScheme' | 'disableAnimation' | 'noStyle' | 'scrollLock' | 'theme' | 'trapFocus'> {
14
+ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<ReactUIOptions, 'colorScheme' | 'disableAnimation' | 'noStyle' | 'scrollLock' | 'theme' | 'trapFocus'> {
13
15
  enabled?: boolean;
14
16
  presentation?: ConsentPresentation;
15
17
  /**
@@ -17,9 +19,10 @@ export interface ConsentProviderOptions extends Pick<ReactUIOptions, 'colorSchem
17
19
  *
18
20
  * @remarks
19
21
  * Set this when your CSP uses a nonce-based policy instead of
20
- * `'unsafe-inline'`. The provider forwards it to the injected theme
21
- * `<style>` element and to every `<script>` element created by the
22
- * script loader. A per-script `nonce` still takes precedence.
22
+ * `'unsafe-inline'`. The provider forwards it to every `<script>`
23
+ * element created by the script loader. A per-script `nonce` still takes
24
+ * precedence. Pass the same nonce to `ConsentTheme`, which renders the
25
+ * theme `<style>` element.
23
26
  */
24
27
  nonce?: string;
25
28
  /**
@@ -82,15 +85,55 @@ export interface ConsentProviderOptions extends Pick<ReactUIOptions, 'colorSchem
82
85
  * Initial-only: remount the provider to replace its cleanup configuration.
83
86
  */
84
87
  clearOnRevocation?: ClearOnRevocationConfig;
88
+ /**
89
+ * Reload the page after an accept, reject or save turns off a category or
90
+ * vendor that was granted, or after a `consentSource` withdraws one.
91
+ * Removing a script cannot stop code that already ran, so the reload
92
+ * starts a document with only permitted code. Waits for the save request.
93
+ * Set `false` to handle revocation yourself.
94
+ * @default true
95
+ */
96
+ reloadOnConsentRevoked?: boolean;
85
97
  scripts?: Script[];
98
+ /**
99
+ * Vendors offered for vendor-level consent outside IAB. Each sits inside a
100
+ * category; a visitor can grant the category and still turn one vendor
101
+ * off. Scripts, network rules and iframes name a vendor through `vendor`
102
+ * or `data-vendor`. Merged with vendors the backend returns and with slugs
103
+ * found on scripts and rules; presentation declared here wins.
104
+ */
105
+ vendors?: Vendor[];
86
106
  scriptLoader?: UseScriptLoaderOptions;
87
107
  networkBlocker?: UseNetworkBlockerOptions | false;
108
+ /**
109
+ * Discover and gate DOM iframes with data-category. Enabled by default.
110
+ * The blocker loads when the first gated iframe is on the page; until it
111
+ * runs, a gated iframe that arrives with a `src` consent does not allow
112
+ * is paused.
113
+ */
114
+ iframeBlocker?: UseIframeBlockerOptions | false;
88
115
  persistence?: boolean | UsePersistenceOptions;
89
116
  i18n?: Partial<I18nConfig>;
117
+ /** Categories to offer alongside discovered integration categories, within policy scope. */
90
118
  consentCategories?: AllConsentNames[];
91
119
  /** Per-component slot attribute overrides (shared contract with @c15t/vue). */
92
120
  components?: ReactComponentSlots;
93
121
  legalLinks?: LegalLinks;
122
+ /**
123
+ * When the deferred `<ConsentDialog />` starts loading before it opens.
124
+ *
125
+ * - `'idle'` (default): after the page's load event, in browser idle time,
126
+ * while the banner is shown or a button that opens the dialog is
127
+ * mounted, and on hover or focus of such a button. Skipped when the
128
+ * visitor has Save-Data on or a 2G-class connection.
129
+ * - `'intent'`: only on hover or focus of a button that opens the dialog.
130
+ *
131
+ * Neither loads the dialog on a visit that shows no banner and has no
132
+ * dialog trigger.
133
+ *
134
+ * @default 'idle'
135
+ */
136
+ preloadDialog?: DialogPreload;
94
137
  /**
95
138
  * Adapter package name reported by `window.c15t`.
96
139
  * @internal
@@ -104,8 +147,13 @@ export interface ConsentProviderOptions extends Pick<ReactUIOptions, 'colorSchem
104
147
  * Everything the component tree still owns — theme, slots, legal links —
105
148
  * is unchanged.
106
149
  */
107
- export type ExternalRuntimeProviderOptions = Omit<ConsentProviderOptions, 'mode'> & {
150
+ export type ExternalRuntimeProviderOptions = Omit<ConsentProviderOptions, 'mode' | 'vendors'> & {
108
151
  mode?: ConsentProviderOptions['mode'];
152
+ /**
153
+ * Not accepted here: the runtime owner declares vendors through
154
+ * `createConsentRuntime({ vendors })`, and the kernel carries them.
155
+ */
156
+ vendors?: never;
109
157
  };
110
158
  /** The provider builds and owns its own kernel. */
111
159
  export interface OwnedRuntimeProviderProps {
@@ -132,7 +180,9 @@ export type ConsentProviderProps = OwnedRuntimeProviderProps | ExternalRuntimePr
132
180
  * Pass `runtime` to render a runtime someone else created. The provider
133
181
  * then borrows its kernel and mounts none of the side-effecting modules —
134
182
  * no second `init()`, no second persistence handle, no second `window.c15t`
135
- * — and does not dispose it on unmount.
183
+ * — and does not dispose it on unmount. Handing it a different runtime
184
+ * switches the tree to that runtime's kernel; switching between a borrowed
185
+ * runtime and a provider-built kernel still needs a remount.
136
186
  *
137
187
  * @example
138
188
  * ```tsx
@@ -1,5 +1,5 @@
1
1
  import type { SSRInitialData } from '@c15t/core';
2
- import type { FetchSSRDataOptions } from './types';
2
+ import type { FetchSSRDataOptions } from './types.js';
3
3
  /**
4
4
  * Fetches initial consent data on the server for SSR hydration.
5
5
  *
@@ -24,8 +24,8 @@
24
24
  *
25
25
  * @packageDocumentation
26
26
  */
27
- export { fetchSSRData } from './fetch-ssr-data';
28
- export { extractRelevantHeaders } from './headers';
29
- export { createSSRInitCacheKey } from './init-cache-key';
30
- export { normalizeBackendURL, validateBackendURL } from './normalize-url';
31
- export type { FetchSSRDataOptions, FetchSSRDataOptionsBase, FetchSSRDataResult, } from './types';
27
+ export { fetchSSRData } from './fetch-ssr-data.js';
28
+ export { extractRelevantHeaders } from './headers.js';
29
+ export { createSSRInitCacheKey } from './init-cache-key.js';
30
+ export { normalizeBackendURL, validateBackendURL } from './normalize-url.js';
31
+ export type { FetchSSRDataOptions, FetchSSRDataOptionsBase, FetchSSRDataResult, } from './types.js';
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { ThemeContextValue } from './context/theme-context';
3
- import type { V3UIConfigValue } from './ui-config-context';
2
+ import type { ThemeContextValue } from './context/theme-context.js';
3
+ import type { V3UIConfigValue } from './ui-config-context.js';
4
4
  interface V3ThemeProviderProps {
5
5
  themeConfig: ThemeContextValue;
6
6
  uiConfig: V3UIConfigValue;
@@ -1,3 +1,3 @@
1
- export * from './manager';
2
- export * from './slots';
3
- export * from './theme';
1
+ export * from './manager.js';
2
+ export * from './slots.js';
3
+ export * from './theme/index.js';
@@ -1,5 +1,5 @@
1
1
  import type { UIOptions } from '@c15t/ui/theme';
2
- import type { ReactComponentSlots } from './slots';
2
+ import type { ReactComponentSlots } from './slots.js';
3
3
  /**
4
4
  * React-specific UI configuration options.
5
5
  *
@@ -1 +1 @@
1
- export * from './style-types';
1
+ export * from './style-types.js';
@@ -1,9 +1,11 @@
1
1
  import type { LegalLinks, ConsentPresentation } from '@c15t/core';
2
- import type { ReactComponentSlots } from './types/slots';
2
+ import type { DialogPreload } from './chunk-warming.js';
3
+ import type { ReactComponentSlots } from './types/slots.js';
3
4
  export interface V3UIConfigValue {
4
5
  components?: ReactComponentSlots;
5
6
  presentation?: ConsentPresentation;
6
7
  legalLinks?: LegalLinks;
8
+ preloadDialog?: DialogPreload;
7
9
  }
8
10
  export declare const V3UIConfigContext: import("react").Context<V3UIConfigValue>;
9
11
  export declare const useUIConfig: () => V3UIConfigValue;
@@ -1,5 +1,25 @@
1
1
  import type { ConsentKernel, SaveResult } from '@c15t/core';
2
2
  /** Explicit navigation supersedes a pending UI action, even to the same dialog. */
3
3
  export declare const invalidateConsentUIAction: (kernel: ConsentKernel) => void;
4
- /** Keep an open preferences dialog available until its own save succeeds. */
4
+ /**
5
+ * Close the preferences dialog as soon as its choice is recorded locally.
6
+ *
7
+ * The kernel commits the receipt and updates permissions synchronously, so
8
+ * the dialog closes in the task that handled the click. Storage is written
9
+ * one task later, still ahead of the request, and the request runs after:
10
+ * its outcome never reopens the dialog, and a failed request stays queued
11
+ * for replay by the kernel. A save that recorded nothing (an unchanged
12
+ * selection) closes when it resolves successfully, unless explicit
13
+ * navigation or a newer action came first.
14
+ */
5
15
  export declare const saveConsentUI: (kernel: ConsentKernel, save: () => Promise<SaveResult>, canClose: () => boolean) => Promise<SaveResult>;
16
+ /**
17
+ * Close an IAB surface in the task that handled the click.
18
+ *
19
+ * An IAB choice commits once its TC string is encoded, which can wait on the
20
+ * TCF library chunk but never on the backend. The surface closes first and
21
+ * comes back only when that local step recorded nothing (the vendor list
22
+ * failed to load, or the policy changed underneath), so the visitor can try
23
+ * again. A failed backend request never reopens it.
24
+ */
25
+ export declare const saveIABConsentUI: (kernel: ConsentKernel, save: () => Promise<void> | void) => Promise<void>;
@@ -0,0 +1,13 @@
1
+ import type { ComponentType } from 'react';
2
+ /**
3
+ * Share an on-demand module across exports and preloading. Ready client
4
+ * retries run synchronously; Suspense retains server rendering and hydration.
5
+ * A failed import is cached for rendered exports only, so a failed preload
6
+ * does not stop a later open from retrying.
7
+ *
8
+ * @internal
9
+ */
10
+ export declare const createDeferredModule: <ModuleType>(importModule: () => Promise<ModuleType>) => {
11
+ component<Props extends object>(select: (module: ModuleType) => ComponentType<Props>): ComponentType<Props>;
12
+ preload(): Promise<void>;
13
+ };
@@ -1,4 +1,4 @@
1
- export * from './cn';
2
- export * from './default-translation-config';
3
- export * from './merge-styles';
4
- export * from './theme-utils';
1
+ export * from './cn.js';
2
+ export * from './default-translation-config.js';
3
+ export * from './merge-styles.js';
4
+ export * from './theme-utils.js';
@@ -1,7 +1,7 @@
1
1
  import type { ConsentComponentSlotKey } from '@c15t/schema/config';
2
2
  import type { ClassValue } from '@c15t/ui/utils';
3
- import type { ReactComponentSlots, ReactSlotProps } from '../types/slots';
4
- import type { CSSPropertiesWithVars } from '../types/theme';
3
+ import type { ReactComponentSlots, ReactSlotProps } from '../types/slots.js';
4
+ import type { CSSPropertiesWithVars } from '../types/theme/index.js';
5
5
  type MergeSlotPropsInput = ReactSlotProps & {
6
6
  baseClassName?: ClassValue;
7
7
  noStyle?: boolean;
@@ -1,4 +1,4 @@
1
- import type { ClassNameStyle, ThemeValue } from '../types/theme';
1
+ import type { ClassNameStyle, ThemeValue } from '../types/theme/index.js';
2
2
  /**
3
3
  * Merges two styles objects, handling theme values and style properties.
4
4
  * This React version uses React-specific types but uses the core logic from @c15t/ui.
@@ -3,7 +3,7 @@
3
3
  * Handles token-to-CSS variable conversion and dark mode overrides.
4
4
  */
5
5
  import type { ThemeCSSVariables } from '@c15t/ui/theme';
6
- import type { Theme } from '../types/theme/style-types';
6
+ import type { Theme } from '../types/theme/style-types.js';
7
7
  /**
8
8
  * Default design tokens for the v2 theme system.
9
9
  */
@@ -1 +1 @@
1
- export declare const version = "3.0.0-alpha.1";
1
+ export declare const version = "3.0.0-alpha.3";
package/docs/README.md CHANGED
@@ -25,15 +25,16 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
25
25
  - [ConsentDialog](./frameworks/react/components/consent-dialog.md): Open the c15t preference center as a modal ConsentDialog in a React app, wire its triggers and control blocking, focus and policy gating.
26
26
  - [ConsentDialogLink](./frameworks/react/components/consent-dialog-link.md): Add a ConsentDialogLink to a React footer so visitors reopen the c15t preference center from your own text link, with asChild and rights data.
27
27
  - [ConsentDialogTrigger](./frameworks/react/components/consent-dialog-trigger.md): Floating button and toolbar that reopen the preference center after the first prompt.
28
+ - [ConsentGate](./frameworks/react/components/consent-gate.md): Gate a YouTube or map iframe behind consent with ConsentGate in React, showing a placeholder that opens the preference center until the category is allowed.
28
29
  - [ConsentProvider](./frameworks/react/components/consent-manager-provider.md): Configure the v3 consent runtime and share its state with child components.
29
30
  - [ConsentWidget](./frameworks/react/components/consent-widget.md): Embed the c15t preference center inline with ConsentWidget on a React privacy page, with draft toggles that record a choice only on Save.
30
31
  - [DevTools](./frameworks/react/components/dev-tools.md): A development tool for inspecting consent state, geolocation, loaded scripts, and consent events in real time.
31
- - [Frame](./frameworks/react/components/frame.md): Gate a YouTube or map iframe behind consent with Frame in React, showing a placeholder that opens the preference center until the category is allowed.
32
32
  - [Consent categories](./frameworks/react/concepts/consent-categories.md): Assign optional features to categories and understand how policy scope affects permission.
33
33
  - [Policy presets](./frameworks/react/concepts/policy-presets.md): Understand how policy rules affect React prompts, permissions and persistent privacy controls.
34
34
  - [Headless](./frameworks/react/headless.md): Build a custom consent banner in React with the c15t/react/headless hooks inside your ConsentProvider.
35
- - [Hooks](./frameworks/react/hooks/use-consent-manager/overview.md): Gate features and save consent choices in React components with the focused hooks exported from c15t/react.
35
+ - [Hooks](./frameworks/react/hooks/overview.md): Gate features and save consent choices in React components with the focused hooks exported from c15t/react.
36
36
  - [IAB TCF](./frameworks/react/iab/overview.md): Mount the IAB TCF banner and dialog inside a React ConsentProvider and configure the CMP ID, policy and vendor data.
37
+ - [Block network requests](./frameworks/react/network-blocker.md): Block fetch and XHR calls to third-party domains in a React app until the visitor grants their consent category.
37
38
  - [Quickstart](./frameworks/react/quickstart.md): Connect a React application to Inth and add consent UI, persistence and a preferences link.
38
39
  - [Load scripts with consent](./frameworks/react/script-loader.md): Register vendor scripts once and let effective permissions control loading.
39
40
  - [Styling](./frameworks/react/styling/overview.md): Import the React stylesheet and theme c15t components with tokens, slots, and class names on ConsentProvider.
@@ -44,6 +45,7 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
44
45
  - [Understand consent state](./guides/consent-state.md): Distinguish policy resolution, effective permissions, explicit choices, notices and privacy signals.
45
46
  - [Data fetching and transports](./guides/data-fetching.md): Choose cached manifests, backend init or offline policy resolution, and understand where consent records are saved.
46
47
  - [Choose a deployment mode](./guides/deployment-modes.md): Choose who runs your consent backend, then select manifest, init or offline resolution for your deployment.
48
+ - [Share consent controls across frameworks](./guides/shared-consent-controls.md): Use the same c15t script lifecycle, external consent source, and event controls in every framework.
47
49
  - [Troubleshoot consent](./guides/troubleshooting.md): Diagnose missing banners, early vendor requests, lost choices and hydration differences.
48
50
  - [Verify consent before shipping](./guides/verify-consent.md): Test requests, policy resolution, persistence, navigation and preference changes in a production build.
49
51
 
@@ -64,12 +66,15 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
64
66
  - [Clear on revocation](./integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
65
67
  - [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
66
68
  - [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
69
+ - [Cloudflare Zaraz](./integrations/cloudflare-zaraz.md): Synchronize c15t permissions with Zaraz purposes while Cloudflare manages your tools.
67
70
  - [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
68
71
  - [Databuddy](./integrations/databuddy.md): Configure Databuddy's initial and updated consent state with c15t v3.
69
72
  - [Fathom Analytics](./integrations/fathom-analytics.md): Configure Fathom Analytics with c15t v3, understand measurement permission and verify loading and revocation.
73
+ - [Front Chat](./integrations/front-chat.md): Load the Front Chat widget with functionality permission, forward CSP nonces and clear the session on revocation.
70
74
  - [Google Maps](./integrations/google-maps.md): Prevent a map iframe from mounting before the required permission.
71
75
  - [Google Tag](./integrations/google-tag.md): Configure gtag with c15t Consent Mode signals and understand its loading behavior.
72
76
  - [Google Tag Manager](./integrations/google-tag-manager.md): Load GTM with c15t consent signals and verify the tags inside your container.
77
+ - [Granular consent](./integrations/granular-consent.md): Let visitors grant a category and still turn one vendor off, without adopting IAB TCF.
73
78
  - [Heap](./integrations/heap.md): Configure Heap with c15t v3, understand measurement permission and verify loading and revocation.
74
79
  - [Hightouch](./integrations/hightouch.md): Configure Hightouch with c15t v3, understand measurement permission and verify loading and revocation.
75
80
  - [Hotjar](./integrations/hotjar.md): Configure Hotjar with c15t v3, understand measurement permission and verify loading and revocation.
@@ -81,8 +86,10 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
81
86
  - [Microsoft Clarity](./integrations/microsoft-clarity.md): Configure Microsoft Clarity with c15t v3, understand measurement permission and verify loading and revocation.
82
87
  - [Microsoft UET](./integrations/microsoft-uet.md): Configure Microsoft UET with c15t v3, understand marketing permission and verify loading and revocation.
83
88
  - [Mixpanel](./integrations/mixpanel-analytics.md): Configure Mixpanel with c15t v3, understand measurement permission and verify loading and revocation.
89
+ - [OneDollarStats](./integrations/one-dollar-stats.md): Load the OneDollarStats tracker with measurement permission, forward its settings and verify loading and revocation.
84
90
  - [OpenAI Pixel](./integrations/openai-pixel.md): Configure the OpenAI Measurement Pixel for ChatGPT Ads with c15t v3, manage marketing permission and verify conversion delivery.
85
91
  - [Overview](./integrations/overview.md): Find all c15t integrations for analytics, tag managers, advertising, chat and embedded content.
92
+ - [Pinterest Tag](./integrations/pinterest-tag.md): Configure the Pinterest Tag with c15t v3, track typed events and verify marketing permission, revocation and reload.
86
93
  - [Pirsch](./integrations/pirsch.md): Configure Pirsch with c15t v3, understand measurement permission and verify loading and revocation.
87
94
  - [Plausible Analytics](./integrations/plausible-analytics.md): Configure Plausible Analytics with c15t v3, understand measurement permission and verify loading and revocation.
88
95
  - [PostHog](./integrations/posthog.md): Choose PostHog loading and cookieless behavior, configure the region, and synchronize v3 permissions.
@@ -34,10 +34,11 @@ layout can be restored by the policy renderer.
34
34
  ## Use the adapter's configuration shape
35
35
 
36
36
  React and Next.js accept provider `theme`, `presentation` and `components`
37
- options. Vue and Nuxt expose their own shared configuration, including CSS
37
+ options, and render theme tokens with `ConsentTheme` on the server. Vue and Nuxt expose their own shared configuration, including CSS
38
38
  `tokens` and component slots. Svelte accepts its provider options and theme
39
- contract. Astro serializes integration options and uses the selected adapter for
40
- dialogs. Do not move a configuration object between frameworks without checking
39
+ slots; SvelteKit renders the token CSS from a server `load`. Astro serializes
40
+ integration options, renders the theme tokens on the server and uses the
41
+ selected adapter for dialogs. Do not move a configuration object between frameworks without checking
41
42
  the target types.
42
43
 
43
44
  Read [tokens and CSS](./tokens.md),
@@ -26,8 +26,10 @@ export const brandTheme = defineTheme({
26
26
 
27
27
  ```
28
28
 
29
- Install `@c15t/ui` to use `defineTheme` directly. Pass `brandTheme` as `theme` in
30
- your existing React or Next.js provider options. Keep your Inth mode and script
29
+ Install `@c15t/ui` to use `defineTheme` directly. Render
30
+ `<ConsentTheme theme={brandTheme} />` on the server for the tokens, and pass
31
+ `brandTheme` as `theme` in your existing React or Next.js provider options for
32
+ the action styles. Keep your Inth mode and script
31
33
  configuration. The theme source above is also imported by the runnable example,
32
34
  so the rendered result and the documentation use the same values.
33
35
 
@@ -11,10 +11,53 @@ React, Next.js and Svelte provide `styles.css`. Import the adapter's stylesheet
11
11
  at the app's global entry point. Vue includes styles in its components; Astro
12
12
  adds styles through its integration.
13
13
 
14
+ The stylesheet blocks rendering, so it carries only what a first paint can
15
+ show: the default tokens, every c15t CSS variable, and the rules for the
16
+ banner, `ConsentDialogTrigger` and the `ConsentGate` placeholder. The consent
17
+ dialog and preference widget bring their own rules. Each rule reaches the page
18
+ once.
19
+
14
20
  ```tsx
15
21
  import 'c15t/react/styles.css';
16
22
  ```
17
23
 
24
+ | File | Holds | Loaded by |
25
+ | -------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------- |
26
+ | `styles.css` or `styles.tw3.css` | Default tokens, all variables, banner, trigger and `ConsentGate` rules | Your app, once |
27
+ | `@c15t/ui/styles/dialog.css` | Dialog and preference widget rules | The dialog component, with its lazy chunk |
28
+ | `@c15t/ui/styles/primitives.css` | Rules for the `@c15t/ui/styles/primitives` class maps | Svelte's `styles.css`, or your app if it renders those class maps |
29
+ | `iab/styles.css` | IAB TCF banner and dialog rules and variables | Your app, after `styles.css` |
30
+
31
+ In React, Next.js and TanStack Start, the dialog's module imports
32
+ `@c15t/ui/styles/dialog.css`. The bundler emits it with the dialog's chunk and
33
+ loads it before that chunk runs, so the dialog never renders unstyled. The
34
+ chunk loads after first paint, by the time the dialog first opens. Do not
35
+ import `dialog.css` yourself. The `@c15t/react/components/consent-dialog`,
36
+ `/components/consent-widget`, `/primitives`, `/primitives/*` and `/iab` entry
37
+ points import it as soon as you import them, because they render dialog parts
38
+ outside the lazy chunk.
39
+
40
+ These modules import the stylesheet through `@c15t/ui/styles/dialog`. Under
41
+ the `node` export condition that module imports nothing, so server code that
42
+ loads `@c15t/react` with plain Node, such as the Pages Router or an SSR build
43
+ that keeps dependencies external, does not fail on the `.css` file. In your
44
+ own components, import `@c15t/ui/styles/dialog` rather than the `.css` file
45
+ if the module can run on the server.
46
+
47
+ Svelte loads its dialog with the page, so `c15t/svelte/styles.css` also
48
+ imports the dialog and primitive rules. Astro injects the banner rules; the
49
+ React and Svelte dialog islands import the rest, and Astro links those
50
+ stylesheets on every page, so in Astro the dialog rules still block rendering.
51
+ Vue components import their own stylesheets.
52
+
53
+ The dialog rules sit in `@layer components` and declare no variables, so
54
+ tokens from `theme`, variables you override in your own CSS, and Tailwind 4
55
+ utilities still win over them even though they load later. If you import
56
+ `styles.css` into a named layer, such as `@import 'c15t/react/styles.css'
57
+ layer(c15t)`, the dialog rules still join the top-level `components` layer.
58
+ List `components` in your layer order statement, for example
59
+ `@layer c15t, components, app;`, so it does not land after your own layers.
60
+
18
61
  The standard stylesheet places rules in `@layer components`. For Tailwind 3,
19
62
  use the `styles.tw3.css` entry instead of the standard stylesheet, between the
20
63
  components and utilities directives in your Tailwind entry:
@@ -26,6 +69,18 @@ components and utilities directives in your Tailwind entry:
26
69
  @tailwind utilities;
27
70
  ```
28
71
 
72
+ Tailwind 3 also processes the dialog stylesheet the bundler loads, and it
73
+ rejects a stylesheet that uses `@layer components` without its own
74
+ `@tailwind components` directive. Add the c15t plugin before `tailwindcss` in
75
+ your PostCSS config. It removes the layer wrapper from c15t's stylesheets so
76
+ Tailwind 3 accepts them and its preflight does not override them:
77
+
78
+ ```js title="postcss.config.mjs"
79
+ export default {
80
+ plugins: ['@c15t/ui/postcss-tailwind3', 'tailwindcss', 'autoprefixer'],
81
+ };
82
+ ```
83
+
29
84
  Do not load both c15t stylesheet variants. For Tailwind 4 or unlayered CSS,
30
85
  inspect layer order before reaching for `!important`.
31
86
 
@@ -48,9 +103,17 @@ export const theme = defineTheme({
48
103
  });
49
104
  ```
50
105
 
51
- Install `@c15t/ui` if importing its theme helper directly. Pass `theme` in your
52
- provider options. `consentActions` selects styling by action role. A per-action
53
- entry overrides `primary`, which overrides `default`.
106
+ Install `@c15t/ui` if importing its theme helper directly. The browser does
107
+ not turn tokens into CSS. In React and Next.js, render
108
+ `<ConsentTheme theme={theme} />` where the app renders on the server, and pass
109
+ `theme` in your provider options for `consentActions`. Elsewhere, call
110
+ `generateThemeCSS(theme)` from `@c15t/ui/theme` on the server or at build time
111
+ and put the result in a `<style>` element or your stylesheet. See
112
+ [React styling](../frameworks/react/styling/overview.md) and
113
+ [Next.js styling](https://c15t.com/docs/frameworks/next/styling/overview).
114
+
115
+ `consentActions` selects styling by action role. A per-action entry overrides
116
+ `primary`, which overrides `default`.
54
117
 
55
118
  ## Target a prompt with CSS
56
119