@c15t/react 3.0.0-alpha.2 → 3.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/AGENTS.md +91 -67
  2. package/README.md +21 -17
  3. package/SKILL.md +34 -0
  4. package/dist/aggregate-components.js +1 -1
  5. package/dist/chunk-warming.js +1 -1
  6. package/dist/component-hooks/use-headless-consent-ui.js +1 -1
  7. package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
  8. package/dist/component-hooks/use-panel-trigger.js +1 -1
  9. package/dist/components/consent-gate/atoms.js +1 -1
  10. package/dist/components/consent-gate/consent-gate.js +1 -1
  11. package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
  12. package/dist/components/iab-panel/atoms/card.js +1 -1
  13. package/dist/components/iab-panel/atoms/feature-item.js +2 -0
  14. package/dist/components/iab-panel/atoms/header.js +1 -1
  15. package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
  16. package/dist/components/iab-panel/atoms/stack-item.js +1 -1
  17. package/dist/components/iab-panel/iab-panel.js +1 -1
  18. package/dist/components/iab-panel/index.js +1 -1
  19. package/dist/components/iab-prompt/atoms/overlay.js +1 -1
  20. package/dist/components/iab-prompt/atoms/root.js +1 -1
  21. package/dist/components/panel/atoms/card.js +1 -1
  22. package/dist/components/panel/atoms/overlay.js +1 -1
  23. package/dist/components/panel/atoms/root.js +1 -1
  24. package/dist/components/panel/index.js +1 -1
  25. package/dist/components/panel/panel.js +1 -1
  26. package/dist/components/panel-trigger/atoms/button.js +1 -1
  27. package/dist/components/panel-trigger/atoms/icon.js +1 -1
  28. package/dist/components/panel-trigger/atoms/root.js +1 -1
  29. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  30. package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
  31. package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
  32. package/dist/components/preferences/atoms/accordion.js +1 -1
  33. package/dist/components/preferences/atoms/root.js +1 -1
  34. package/dist/components/preferences/atoms/vendor-list.js +1 -1
  35. package/dist/components/preferences/index.js +1 -1
  36. package/dist/components/prompt/atoms/overlay.js +1 -1
  37. package/dist/components/prompt/atoms/root.js +1 -1
  38. package/dist/components/prompt/components.js +1 -1
  39. package/dist/components/prompt/policy-actions.js +1 -1
  40. package/dist/components/shared/libs/compose-refs.js +1 -0
  41. package/dist/components/shared/libs/slot.js +1 -1
  42. package/dist/components/shared/primitives/button.js +1 -1
  43. package/dist/components/shared/ui/accordion/accordion.js +1 -1
  44. package/dist/components/shared/ui/collapsible/collapsible.js +1 -1
  45. package/dist/components/shared/ui/dialog/dialog.js +1 -1
  46. package/dist/components/shared/ui/icon.js +1 -1
  47. package/dist/components/shared/ui/logo.js +1 -1
  48. package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
  49. package/dist/components/shared/ui/switch/switch.js +1 -1
  50. package/dist/components/shared/ui/tabs/tabs.js +1 -1
  51. package/dist/consent-theme.js +1 -0
  52. package/dist/context/consent-tracking-context.js +1 -1
  53. package/dist/devtools.js +1 -1
  54. package/dist/draft.js +1 -1
  55. package/dist/external-iab-context.js +1 -1
  56. package/dist/headless.js +1 -1
  57. package/dist/hooks/use-committed-ref.js +2 -0
  58. package/dist/hooks/use-focus-trap.js +1 -1
  59. package/dist/hooks.js +1 -1
  60. package/dist/iab/styles.tw3.css +5 -45
  61. package/dist/iab-context.js +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/kernel-selector.js +1 -0
  64. package/dist/module-hooks/iframe-blocker.js +1 -1
  65. package/dist/module-hooks/network-blocker.js +1 -1
  66. package/dist/module-hooks/network-hold.js +2 -0
  67. package/dist/module-hooks/persistence.js +1 -1
  68. package/dist/panel.js +1 -1
  69. package/dist/postcss-tailwind3.js +1 -0
  70. package/dist/preferences.js +1 -2
  71. package/dist/provider.js +1 -1
  72. package/dist/server/fetch-ssr-data.js +1 -1
  73. package/dist/server/headers.js +1 -1
  74. package/dist/server/normalize-url.js +1 -1
  75. package/dist/styles.tw3.css +16 -61
  76. package/dist/transports/offline.js +1 -1
  77. package/dist/ui-save.js +1 -1
  78. package/dist/utils/deferred-module.js +1 -1
  79. package/dist/utils/merge-slot-props.js +1 -1
  80. package/dist/utils/theme-utils.js +1 -1
  81. package/dist/version.js +1 -1
  82. package/dist-types/chunk-warming.d.ts +41 -8
  83. package/dist-types/component-hooks/use-headless-consent-ui.d.ts +1 -1
  84. package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +1 -1
  85. package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
  86. package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +4 -1
  87. package/dist-types/components/iab-panel/atoms/stack-item.d.ts +6 -1
  88. package/dist-types/components/iab-panel/iab-panel.d.ts +2 -2
  89. package/dist-types/components/iab-panel/index.d.ts +6 -2
  90. package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
  91. package/dist-types/components/iab-prompt/iab-prompt.d.ts +2 -2
  92. package/dist-types/components/iab-prompt/index.d.ts +2 -2
  93. package/dist-types/components/panel/atoms/card.d.ts +1 -0
  94. package/dist-types/components/panel/index.d.ts +1 -0
  95. package/dist-types/components/panel/panel.d.ts +1 -1
  96. package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +20 -0
  97. package/dist-types/components/preferences/index.d.ts +1 -0
  98. package/dist-types/components/prompt/components.d.ts +6 -0
  99. package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
  100. package/dist-types/components/shared/ui/accordion/accordion.d.ts +1 -0
  101. package/dist-types/components/shared/ui/collapsible/collapsible.d.ts +1 -0
  102. package/dist-types/components/shared/ui/icon.d.ts +2 -1
  103. package/dist-types/components/shared/ui/logo.d.ts +0 -10
  104. package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +14 -0
  105. package/dist-types/components/shared/ui/switch/switch.d.ts +1 -0
  106. package/dist-types/components/shared/ui/tabs/tabs.d.ts +1 -0
  107. package/dist-types/consent-theme.d.ts +38 -0
  108. package/dist-types/context/consent-tracking-context.d.ts +10 -0
  109. package/dist-types/context/theme-context.d.ts +2 -2
  110. package/dist-types/context.d.ts +6 -0
  111. package/dist-types/devtools.d.ts +13 -2
  112. package/dist-types/draft.d.ts +50 -7
  113. package/dist-types/headless.d.ts +0 -1
  114. package/dist-types/hooks/use-committed-ref.d.ts +24 -0
  115. package/dist-types/hooks/use-focus-trap.d.ts +3 -1
  116. package/dist-types/hooks.d.ts +56 -13
  117. package/dist-types/iab.d.ts +1 -1
  118. package/dist-types/index.d.ts +4 -3
  119. package/dist-types/kernel-selector.d.ts +66 -0
  120. package/dist-types/module-hooks/iframe-blocker.d.ts +27 -0
  121. package/dist-types/module-hooks/network-blocker.d.ts +23 -0
  122. package/dist-types/module-hooks/network-hold.d.ts +47 -0
  123. package/dist-types/panel.d.ts +13 -1
  124. package/dist-types/postcss-tailwind3.d.ts +21 -0
  125. package/dist-types/preferences.d.ts +12 -1
  126. package/dist-types/provider.d.ts +62 -12
  127. package/dist-types/server/headers.d.ts +14 -4
  128. package/dist-types/server/normalize-url.d.ts +14 -7
  129. package/dist-types/server/types.d.ts +12 -1
  130. package/dist-types/transports/offline.d.ts +7 -16
  131. package/dist-types/ui-config-context.d.ts +9 -1
  132. package/dist-types/ui-save.d.ts +21 -1
  133. package/dist-types/utils/deferred-module.d.ts +3 -1
  134. package/dist-types/utils/merge-slot-props.d.ts +15 -1
  135. package/dist-types/utils/theme-utils.d.ts +17 -2
  136. package/dist-types/version.d.ts +1 -1
  137. package/docs/README.md +91 -67
  138. package/docs/assets/v3/bottom-bar.png +0 -0
  139. package/docs/assets/v3/brand-card.png +0 -0
  140. package/docs/assets/v3/brand-preferences.png +0 -0
  141. package/docs/assets/v3/choice-wall.png +0 -0
  142. package/docs/assets/v3/headless-bar-html.png +0 -0
  143. package/docs/assets/v3/headless-bar-mobile.png +0 -0
  144. package/docs/assets/v3/headless-bar.png +0 -0
  145. package/docs/assets/v3/slim-bar.png +0 -0
  146. package/docs/concepts/choose-your-setup.md +87 -0
  147. package/docs/{frameworks/react/concepts → concepts}/consent-categories.md +30 -8
  148. package/docs/concepts/consent-state.md +357 -0
  149. package/docs/{guides → concepts}/data-fetching.md +31 -27
  150. package/docs/concepts/how-consent-works.md +123 -0
  151. package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +7 -59
  152. package/docs/customization/class-names.md +202 -0
  153. package/docs/customization/dark-mode.md +157 -0
  154. package/docs/customization/motion.md +119 -0
  155. package/docs/customization/overview.md +67 -33
  156. package/docs/customization/recipes.md +839 -47
  157. package/docs/customization/slots.md +216 -35
  158. package/docs/customization/stylesheets.md +147 -0
  159. package/docs/customization/tailwind.md +842 -0
  160. package/docs/customization/tokens.md +166 -36
  161. package/docs/customization/translations.md +61 -3
  162. package/docs/frameworks/react/callbacks.md +118 -0
  163. package/docs/frameworks/react/clear-on-revocation.md +106 -0
  164. package/docs/frameworks/react/components/consent-banner.md +42 -28
  165. package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
  166. package/docs/frameworks/react/components/consent-dialog-trigger.md +81 -76
  167. package/docs/frameworks/react/components/consent-dialog.md +100 -55
  168. package/docs/frameworks/react/components/consent-gate.md +45 -24
  169. package/docs/frameworks/react/components/consent-provider.md +126 -0
  170. package/docs/frameworks/react/components/consent-widget.md +32 -20
  171. package/docs/frameworks/react/components/dev-tools.md +52 -84
  172. package/docs/frameworks/react/components.md +105 -0
  173. package/docs/frameworks/react/compose.md +354 -0
  174. package/docs/frameworks/react/content-security-policy.md +126 -0
  175. package/docs/frameworks/react/customize.md +250 -0
  176. package/docs/frameworks/react/embeds.md +89 -0
  177. package/docs/frameworks/react/hooks.md +65 -0
  178. package/docs/frameworks/react/iab.md +222 -0
  179. package/docs/frameworks/react/network-blocker.md +140 -0
  180. package/docs/frameworks/react/quickstart.md +139 -101
  181. package/docs/frameworks/react/rendering.md +128 -0
  182. package/docs/frameworks/react/scripts.md +115 -0
  183. package/docs/frameworks/react/translations.md +155 -0
  184. package/docs/frameworks/react/troubleshooting.md +92 -47
  185. package/docs/frameworks/react/vendor-consent.md +170 -0
  186. package/docs/guides/banner-experiments.md +654 -0
  187. package/docs/guides/troubleshooting.md +120 -47
  188. package/docs/guides/verify-consent.md +81 -49
  189. package/docs/integrations/adobe-analytics.md +168 -160
  190. package/docs/integrations/ahrefs-analytics.md +153 -155
  191. package/docs/integrations/amplitude.md +163 -157
  192. package/docs/integrations/building-integrations.md +136 -37
  193. package/docs/integrations/clearbit.md +155 -155
  194. package/docs/integrations/cloudflare-web-analytics.md +157 -157
  195. package/docs/integrations/cloudflare-zaraz.md +210 -262
  196. package/docs/integrations/crisp.md +165 -159
  197. package/docs/integrations/databuddy.md +158 -174
  198. package/docs/integrations/fathom-analytics.md +159 -157
  199. package/docs/integrations/front-chat.md +322 -0
  200. package/docs/integrations/google-maps.md +119 -84
  201. package/docs/integrations/google-tag-manager.md +179 -164
  202. package/docs/integrations/google-tag.md +164 -161
  203. package/docs/integrations/heap.md +164 -156
  204. package/docs/integrations/hightouch.md +162 -158
  205. package/docs/integrations/hotjar.md +160 -156
  206. package/docs/integrations/intercom.md +184 -154
  207. package/docs/integrations/klaviyo.md +486 -0
  208. package/docs/integrations/linkedin-insights.md +175 -151
  209. package/docs/integrations/logrocket.md +161 -157
  210. package/docs/integrations/matomo-analytics.md +189 -179
  211. package/docs/integrations/meta-pixel.md +189 -151
  212. package/docs/integrations/microsoft-clarity.md +164 -156
  213. package/docs/integrations/microsoft-uet.md +149 -155
  214. package/docs/integrations/mixpanel-analytics.md +156 -161
  215. package/docs/integrations/one-dollar-stats.md +306 -0
  216. package/docs/integrations/openai-pixel.md +205 -302
  217. package/docs/integrations/overview.md +143 -83
  218. package/docs/integrations/pinterest-tag.md +329 -0
  219. package/docs/integrations/pirsch.md +170 -160
  220. package/docs/integrations/plausible-analytics.md +173 -159
  221. package/docs/integrations/posthog.md +227 -242
  222. package/docs/integrations/promptwatch.md +155 -155
  223. package/docs/integrations/reddit-pixel.md +186 -158
  224. package/docs/integrations/rudderstack.md +202 -187
  225. package/docs/integrations/rybbit-analytics.md +172 -161
  226. package/docs/integrations/segment.md +183 -155
  227. package/docs/integrations/snapchat-pixel.md +187 -157
  228. package/docs/integrations/tiktok-pixel.md +172 -151
  229. package/docs/integrations/umami-analytics.md +164 -159
  230. package/docs/integrations/vercel-analytics.md +167 -158
  231. package/docs/integrations/x-pixel.md +177 -151
  232. package/docs/integrations/youtube.md +122 -87
  233. package/docs/upgrade-v3.md +490 -354
  234. package/package.json +15 -9
  235. package/dist/component-hooks/use-manager.js +0 -2
  236. package/dist-types/component-hooks/use-manager.d.ts +0 -45
  237. package/docs/assets/v3/brand-bar.png +0 -0
  238. package/docs/assets/v3/mobile-card.png +0 -0
  239. package/docs/assets/v3/preferences.png +0 -0
  240. package/docs/frameworks/react/components/consent-manager-provider.md +0 -75
  241. package/docs/frameworks/react/hooks/use-consent-manager/overview.md +0 -58
  242. package/docs/frameworks/react/iab/overview.md +0 -53
  243. package/docs/frameworks/react/script-loader.md +0 -63
  244. package/docs/frameworks/react/styling/overview.md +0 -217
  245. package/docs/guides/consent-state.md +0 -60
  246. package/docs/guides/deployment-modes.md +0 -75
  247. package/docs/integrations/clear-on-revocation.md +0 -167
  248. package/docs/integrations/granular-consent.md +0 -208
@@ -1,19 +1,52 @@
1
1
  /**
2
- * Chunk-warming registry (Vue-parity perf work, item #2).
2
+ * Chunk-warming registry for the deferred `ConsentDialog`.
3
3
  *
4
- * The aggregate `ConsentDialog` is lazy-loaded and — since the interaction
5
- * fix — deferred until it can actually render. That leaves one cold path:
6
- * the user's *first* "customize" click pays the chunk network+parse cost
7
- * under throttle. Surfaces register their lazy import here, and intent
8
- * signals (pointerenter/focus on the customize button) warm the chunk
9
- * before the click.
4
+ * The aggregate `ConsentDialog` is lazy-loaded and deferred until it can
5
+ * render, so the first open would otherwise wait for its chunk. Surfaces
6
+ * register their lazy import here, and two signals start it early:
7
+ *
8
+ * - Intent: pointerenter or focus on any `ConsentButton` that opens the
9
+ * dialog, including the stock banner's Customize button.
10
+ * - Idle: once the page has loaded and the browser is idle, while the banner
11
+ * is shown or a dialog trigger is mounted. This covers an immediate tap or
12
+ * focus-and-Enter, which leaves no lead time for intent warming.
10
13
  *
11
14
  * Module-level registry keeps banner components decoupled from the
12
15
  * aggregate exports (no context change, tree-shakes with the aggregate).
13
16
  */
14
17
  type Warmer = () => void;
18
+ /**
19
+ * When the deferred consent dialog starts loading before it opens.
20
+ *
21
+ * - `'idle'`: after the page's load event, in browser idle time, while the
22
+ * banner is shown or a button that opens the dialog is mounted. Also on
23
+ * hover or focus of such a button.
24
+ * - `'intent'`: only on hover or focus of a button that opens the dialog.
25
+ *
26
+ * @public
27
+ */
28
+ export type DialogPreload = 'idle' | 'intent';
15
29
  /** Register a lazy chunk's import trigger. Returns an unregister fn. */
16
30
  export declare const registerDialogChunkWarmer: (warmer: Warmer) => () => void;
17
- /** Fire all registered warmers once (idempotent). */
31
+ /**
32
+ * Fire every registered warmer. Warmers share one in-flight import, so
33
+ * repeated calls are cheap, and a call after a failed import retries it.
34
+ */
18
35
  export declare const warmDialogChunk: () => void;
36
+ /**
37
+ * Hold an idle-warming gate open while `active`: the dialog loads in the next
38
+ * idle period after the page's load event, if a gate is still open then.
39
+ * Consumers opt out with `preloadDialog: 'intent'`.
40
+ *
41
+ * @param active - Whether the dialog can be opened soon from this component,
42
+ * for example because the banner is shown or a trigger is mounted.
43
+ * @internal
44
+ */
45
+ export declare const useIdleDialogWarming: (active: boolean) => void;
46
+ /**
47
+ * Reset module state between tests.
48
+ *
49
+ * @internal
50
+ */
51
+ export declare const resetDialogChunkWarmingForTests: () => void;
19
52
  export {};
@@ -64,5 +64,5 @@ export declare const useHeadlessConsentUI: (overrides?: ConsentPresentation) =>
64
64
  performAction: (action: PresentationAction) => void | Promise<import("@c15t/core").SaveResult> | Promise<import("@c15t/core").NoticeDismissResult>;
65
65
  performBannerAction: (action: PresentationAction) => void | Promise<import("@c15t/core").SaveResult> | Promise<import("@c15t/core").NoticeDismissResult>;
66
66
  performDialogAction: (action: PresentationAction) => void | Promise<import("@c15t/core").SaveResult> | Promise<import("@c15t/core").NoticeDismissResult>;
67
- saveCustomPreferences: (input?: import("@c15t/core").SaveInput) => Promise<import("@c15t/core").SaveResult>;
67
+ saveCustomPreferences: (input?: import("@c15t/core").SaveInput, uiSource?: import("@c15t/core").SaveUISource) => Promise<import("@c15t/core").SaveResult>;
68
68
  };
@@ -1,5 +1,5 @@
1
1
  export declare const useHeadlessIABConsentUI: () => {
2
- activeUI: import("@c15t/core").ActiveUI;
2
+ activeUI: "banner" | "dialog" | "none";
3
3
  banner: {
4
4
  isReady: boolean;
5
5
  vendorCount: number;
@@ -0,0 +1,28 @@
1
+ import type { FC } from 'react';
2
+ import type { ProcessedFeature } from '../types.js';
3
+ /** Props for {@link FeatureItem}. */
4
+ export interface FeatureItemProps {
5
+ /** The feature, as a display-model row or processed GVL feature. */
6
+ feature: ProcessedFeature;
7
+ /**
8
+ * The row's `data-testid`. Comes from the shared display model, which
9
+ * namespaces it by row kind.
10
+ */
11
+ testId?: string;
12
+ }
13
+ /**
14
+ * One informational IAB Feature row.
15
+ *
16
+ * TCF Policies v5.0.b forbid showing Features next to a control that
17
+ * cannot be disabled, so this row has no switch, no lock and no per-vendor
18
+ * toggles. It shows the name, the description, the illustrations and the
19
+ * names of the vendors that use the feature.
20
+ *
21
+ * @param props - The feature and its test id.
22
+ * @returns The collapsible feature row.
23
+ * @example
24
+ * ```tsx
25
+ * <FeatureItem feature={row} testId={row.testId} />
26
+ * ```
27
+ */
28
+ export declare const FeatureItem: FC<FeatureItemProps>;
@@ -1,7 +1,10 @@
1
1
  import type { FC } from 'react';
2
2
  import type { ProcessedPurpose, VendorId } from '../types.js';
3
3
  interface PurposeItemProps {
4
- purpose: ProcessedPurpose;
4
+ /** A purpose, or a display-model row carrying `hasConsentBasis`. */
5
+ purpose: ProcessedPurpose & {
6
+ hasConsentBasis?: boolean;
7
+ };
5
8
  /**
6
9
  * The row's `data-testid`. Comes from the shared display model, which
7
10
  * namespaces it by row kind — a purpose, a special purpose and a
@@ -1,7 +1,12 @@
1
1
  import type { FC } from 'react';
2
2
  import type { ProcessedStack, VendorId } from '../types.js';
3
3
  interface StackItemProps {
4
- stack: ProcessedStack;
4
+ /** A stack, or a display-model stack row whose purposes carry `hasConsentBasis`. */
5
+ stack: Omit<ProcessedStack, 'purposes'> & {
6
+ purposes: (ProcessedStack['purposes'][number] & {
7
+ hasConsentBasis?: boolean;
8
+ })[];
9
+ };
5
10
  consents: Record<number, boolean>;
6
11
  onToggle: (purposeId: number, value: boolean) => void;
7
12
  vendorConsents: Record<string, boolean>;
@@ -64,10 +64,10 @@ export interface IABConsentDialogProps {
64
64
  uiSource?: string;
65
65
  }
66
66
  /**
67
- * IAB TCF 2.3 compliant consent dialog dialog.
67
+ * IAB TCF 2.4 compliant consent dialog dialog.
68
68
  *
69
69
  * @remarks
70
- * This component implements the required IAB TCF 2.3 UI elements:
70
+ * This component implements the required IAB TCF 2.4 UI elements:
71
71
  * - Tabbed interface for Purposes and Vendors
72
72
  * - Purpose grouping with stacks
73
73
  * - Individual purpose and vendor consent toggles
@@ -6,9 +6,11 @@
6
6
  * It follows the compound components pattern, allowing for flexible composition
7
7
  * of the consent dialog's parts.
8
8
  */
9
+ import '@c15t/ui/styles/dialog';
9
10
  import type { FC } from 'react';
10
11
  import { IABConsentDialogCard } from './atoms/card.js';
11
12
  import { IABConsentDialogContent } from './atoms/content.js';
13
+ import { FeatureItem } from './atoms/feature-item.js';
12
14
  import { IABConsentDialogFooter } from './atoms/footer.js';
13
15
  import { IABConsentDialogHeader } from './atoms/header.js';
14
16
  import { IABConsentDialogOverlay } from './atoms/overlay.js';
@@ -31,19 +33,20 @@ export interface IABConsentDialogCompoundComponent extends FC<IABConsentDialogPr
31
33
  Content: typeof IABConsentDialogContent;
32
34
  Footer: typeof IABConsentDialogFooter;
33
35
  Overlay: typeof IABConsentDialogOverlay;
36
+ FeatureItem: typeof FeatureItem;
34
37
  PurposeItem: typeof PurposeItem;
35
38
  StackItem: typeof StackItem;
36
39
  VendorList: typeof VendorList;
37
40
  }
38
41
  /**
39
- * IAB TCF 2.3 compliant consent dialog dialog component.
42
+ * IAB TCF 2.4 compliant consent dialog dialog component.
40
43
  *
41
44
  * @remarks
42
45
  * This component serves as the main entry point for rendering an IAB-compliant consent dialog.
43
46
  * It provides a structured layout with required IAB TCF elements.
44
47
  *
45
48
  * Key features:
46
- * - IAB TCF 2.3 compliant
49
+ * - IAB TCF 2.4 compliant
47
50
  * - Fully accessible by default
48
51
  * - Customizable appearance
49
52
  * - Compound component pattern support
@@ -78,6 +81,7 @@ declare const IABConsentDialog: IABConsentDialogCompoundComponent;
78
81
  export default IABConsentDialog;
79
82
  export { IABConsentDialogCard } from './atoms/card.js';
80
83
  export { IABConsentDialogContent } from './atoms/content.js';
84
+ export { FeatureItem, type FeatureItemProps } from './atoms/feature-item.js';
81
85
  export { IABConsentDialogFooter } from './atoms/footer.js';
82
86
  export { IABConsentDialogHeader } from './atoms/header.js';
83
87
  export { IABConsentDialogOverlay } from './atoms/overlay.js';
@@ -45,6 +45,10 @@ interface IABTranslations {
45
45
  title: string;
46
46
  tooltip: string;
47
47
  };
48
+ features: {
49
+ title: string;
50
+ description: string;
51
+ };
48
52
  vendorList: {
49
53
  search: string;
50
54
  showingCount: string;
@@ -42,10 +42,10 @@ export interface IABConsentBannerProps {
42
42
  uiSource?: string;
43
43
  }
44
44
  /**
45
- * IAB TCF 2.3 compliant cookie consent banner.
45
+ * IAB TCF 2.4 compliant cookie consent banner.
46
46
  *
47
47
  * @remarks
48
- * This component implements the required IAB TCF 2.3 UI elements:
48
+ * This component implements the required IAB TCF 2.4 UI elements:
49
49
  * - Partner count disclosure
50
50
  * - Purpose summary
51
51
  * - Legitimate interest notice
@@ -32,14 +32,14 @@ export interface IABConsentBannerCompoundComponent extends FC<IABConsentBannerPr
32
32
  Overlay: typeof IABConsentBannerOverlay;
33
33
  }
34
34
  /**
35
- * IAB TCF 2.3 compliant cookie consent banner component.
35
+ * IAB TCF 2.4 compliant cookie consent banner component.
36
36
  *
37
37
  * @remarks
38
38
  * This component serves as the main entry point for rendering an IAB-compliant consent banner.
39
39
  * It provides a structured layout with required IAB TCF elements.
40
40
  *
41
41
  * Key features:
42
- * - IAB TCF 2.3 compliant
42
+ * - IAB TCF 2.4 compliant
43
43
  * - Fully accessible by default
44
44
  * - Customizable appearance
45
45
  * - Compound component pattern support
@@ -25,6 +25,7 @@ declare const ConsentDialogHeader: import("react").ForwardRefExoticComponent<Omi
25
25
  * - Uses proper heading semantics for accessibility
26
26
  * - Should be used within ConsentDialogHeader
27
27
  * - Supports theme customization
28
+ * - Renders an `h2`; with `asChild` the child element takes its place
28
29
  */
29
30
  declare const ConsentDialogHeaderTitle: import("react").ForwardRefExoticComponent<Omit<BoxProps, "slotKey"> & import("react").RefAttributes<HTMLDivElement>>;
30
31
  /**
@@ -6,6 +6,7 @@
6
6
  * It follows the compound components pattern, allowing for flexible composition
7
7
  * of the dialog's parts.
8
8
  */
9
+ import '@c15t/ui/styles/dialog';
9
10
  import type { FC } from 'react';
10
11
  import { Card, ConsentCustomizationCard, ConsentDialogContent, ConsentDialogFooter, ConsentDialogHeader, ConsentDialogHeaderDescription, ConsentDialogHeaderTitle, Content, Footer, Header, HeaderDescription, HeaderTitle } from './atoms/card.js';
11
12
  import { Overlay } from './atoms/overlay.js';
@@ -37,7 +37,7 @@ export interface ConsentDialogProps {
37
37
  trapFocus?: boolean;
38
38
  /**
39
39
  * Control the open state. If omitted the dialog follows
40
- * `useConsentManager().activeUI === 'dialog'`.
40
+ * `useActiveUI() === 'dialog'`.
41
41
  */
42
42
  open?: boolean;
43
43
  /**
@@ -0,0 +1,20 @@
1
+ import type { SVGProps } from 'react';
2
+ /**
3
+ * Dialog-trigger icons, kept apart from the branding logos: the banner renders
4
+ * the logos on every page, while these only ship with the dialog trigger.
5
+ */
6
+ interface IconProps {
7
+ title?: string;
8
+ titleId?: string;
9
+ }
10
+ /**
11
+ * Fingerprint icon for privacy/consent contexts.
12
+ * A generic icon representing user identity and privacy.
13
+ */
14
+ export declare const FingerprintIcon: ({ title, titleId, ...props }: SVGProps<SVGSVGElement> & IconProps) => import("react").JSX.Element;
15
+ /**
16
+ * Settings/gear icon for preference contexts.
17
+ * A generic icon representing configuration and settings.
18
+ */
19
+ export declare const SettingsIcon: ({ title, titleId, ...props }: SVGProps<SVGSVGElement> & IconProps) => import("react").JSX.Element;
20
+ export {};
@@ -7,6 +7,7 @@
7
7
  * of the widget's parts.
8
8
  *
9
9
  */
10
+ import '@c15t/ui/styles/dialog';
10
11
  import type { FC } from 'react';
11
12
  import { Accordion, AccordionArrow, AccordionContent, AccordionItem, AccordionItems, AccordionTrigger, AccordionTriggerInner, Switch, VendorList } from './atoms/accordion.js';
12
13
  import { AcceptAllButton, CustomizeButton, RejectButton, SaveButton } from './atoms/button.js';
@@ -16,12 +16,18 @@ export type ConsentBannerRight = Exclude<PolicyRight, 'disclosure'>;
16
16
  * @remarks
17
17
  * Provides the main heading for the consent notice.
18
18
  * Implements proper heading semantics and supports theming.
19
+ * Renders an `h2`. With `asChild`, the child element, such as an `h1`,
20
+ * takes its place and receives the title's class and attributes.
19
21
  *
20
22
  * @example
21
23
  * ```tsx
22
24
  * <ConsentBannerTitle>
23
25
  * Cookie Preferences
24
26
  * </ConsentBannerTitle>
27
+ *
28
+ * <ConsentBannerTitle asChild>
29
+ * <h1>Cookie Preferences</h1>
30
+ * </ConsentBannerTitle>
25
31
  * ```
26
32
  */
27
33
  declare const ConsentBannerTitle: import("react").ForwardRefExoticComponent<Omit<BoxProps, "slotKey"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,20 @@
1
+ import type { Ref, RefCallback } from 'react';
2
+ /**
3
+ * Combine refs so one element fills all of them.
4
+ *
5
+ * @param refs - Callback refs, object refs, or `undefined`.
6
+ * @returns A callback ref that calls or assigns each ref in order.
7
+ * @internal
8
+ */
9
+ export declare const composeRefs: <ElementType>(...refs: (Ref<ElementType> | undefined)[]) => RefCallback<ElementType>;
10
+ /**
11
+ * {@link composeRefs} for two refs, with a stable identity while they stay
12
+ * the same, so React does not detach and reattach the element on every
13
+ * render.
14
+ *
15
+ * @param first - A callback ref, object ref, or `undefined`.
16
+ * @param second - A callback ref, object ref, or `undefined`.
17
+ * @returns A memoized callback ref.
18
+ * @internal
19
+ */
20
+ export declare const useComposedRefs: <ElementType>(first: Ref<ElementType> | undefined, second: Ref<ElementType> | undefined) => RefCallback<ElementType>;
@@ -1,4 +1,5 @@
1
1
  import type { AccordionType } from '@c15t/ui/primitives/accordion';
2
+ import '@c15t/ui/styles/dialog';
2
3
  import type { ButtonHTMLAttributes, ElementType, HTMLAttributes } from 'react';
3
4
  import type { PolymorphicComponentProps } from '../../libs/polymorphic.js';
4
5
  import type { ThemeValue } from '../../../../types/theme/index.js';
@@ -1,3 +1,4 @@
1
+ import '@c15t/ui/styles/dialog';
1
2
  import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react';
2
3
  export declare const collapsibleVariants: () => {
3
4
  content: (options?: {
@@ -1,6 +1,7 @@
1
1
  import type { ElementType, JSX, SVGProps } from 'react';
2
2
  type LucideIconProps = SVGProps<SVGSVGElement> & {
3
- title: string;
3
+ /** Omit for a decorative icon that must add nothing to an accessible name. */
4
+ title?: string;
4
5
  iconPath: JSX.Element;
5
6
  };
6
7
  export declare const LucideIcon: ({ title, iconPath }: LucideIconProps) => ElementType;
@@ -16,14 +16,4 @@ export declare const InthLogo: (props: SVGProps<SVGSVGElement> & IconProps) => i
16
16
  * INTH icon-only mark for compact placements like floating triggers.
17
17
  */
18
18
  export declare const InthIconOnly: (props: SVGProps<SVGSVGElement> & IconProps) => import("react").JSX.Element;
19
- /**
20
- * Fingerprint icon for privacy/consent contexts.
21
- * A generic icon representing user identity and privacy.
22
- */
23
- export declare const FingerprintIcon: ({ title, titleId, ...props }: SVGProps<SVGSVGElement> & IconProps) => import("react").JSX.Element;
24
- /**
25
- * Settings/gear icon for preference contexts.
26
- * A generic icon representing configuration and settings.
27
- */
28
- export declare const SettingsIcon: ({ title, titleId, ...props }: SVGProps<SVGSVGElement> & IconProps) => import("react").JSX.Element;
29
19
  export {};
@@ -1,4 +1,5 @@
1
1
  import type { ConsentComponentSlotKey } from '@c15t/schema/config';
2
+ import '@c15t/ui/styles/dialog';
2
3
  import type { HTMLAttributes, ReactNode } from 'react';
3
4
  export type PreferenceItemVariantsProps = Record<never, never>;
4
5
  export declare const preferenceItemVariants: () => {
@@ -66,6 +67,19 @@ export interface PreferenceItemTitleProps extends HTMLAttributes<HTMLHeadingElem
66
67
  }
67
68
  declare const PreferenceItemTitle: import("react").ForwardRefExoticComponent<PreferenceItemTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
68
69
  export interface PreferenceItemContentProps extends HTMLAttributes<HTMLDivElement> {
70
+ /**
71
+ * Render the children while the item has never been opened.
72
+ *
73
+ * By default the content element is always rendered, so the trigger's
74
+ * `aria-controls` target exists, but its children mount the first time
75
+ * the item opens and then stay mounted, so the close transition and any
76
+ * state inside them survive. Collapsed content is `inert` and
77
+ * `aria-hidden` either way. Set this when collapsed children must be in
78
+ * the DOM, for example when custom CSS shows them.
79
+ *
80
+ * @defaultValue false
81
+ */
82
+ forceMount?: boolean;
69
83
  innerClassName?: string;
70
84
  innerSlotKey?: ConsentComponentSlotKey;
71
85
  noStyle?: boolean;
@@ -1,3 +1,4 @@
1
+ import '@c15t/ui/styles/dialog';
1
2
  import type { ButtonHTMLAttributes } from 'react';
2
3
  import type { ThemeValue } from '../../../../types/theme/index.js';
3
4
  export type SwitchSize = 'medium' | 'small';
@@ -1,4 +1,5 @@
1
1
  import type { TabsOrientation } from '@c15t/ui/primitives/tabs';
2
+ import '@c15t/ui/styles/dialog';
2
3
  import type { HTMLAttributes, ReactNode } from 'react';
3
4
  export interface TabsVariantsProps {
4
5
  orientation?: TabsOrientation;
@@ -0,0 +1,38 @@
1
+ import type { Theme } from './types/theme/index.js';
2
+ /** Props for {@link ConsentTheme}. */
3
+ export interface ConsentThemeProps {
4
+ /**
5
+ * Theme tokens: colors, dark colors, typography, spacing, radius,
6
+ * shadows and motion. Defaults to the built-in theme, which the package
7
+ * stylesheet already contains, so omit it only to pick a `colorScheme`
8
+ * before hydration.
9
+ */
10
+ theme?: Theme;
11
+ /**
12
+ * Color scheme to apply before hydration. `'dark'` makes the dark
13
+ * tokens the default, and `'system'` follows `prefers-color-scheme`.
14
+ * Omit it to follow the `dark` / `c15t-dark` class on `<html>`. Pass the
15
+ * same value as the provider's `colorScheme` option.
16
+ */
17
+ colorScheme?: 'light' | 'dark' | 'system' | null;
18
+ /** Content Security Policy nonce for the `<style>` element. */
19
+ nonce?: string;
20
+ }
21
+ /**
22
+ * Renders the `--c15t-*` CSS variables for a theme as a `<style>` element.
23
+ *
24
+ * Render it once, next to the consent provider, where your framework renders
25
+ * on the server. The provider does not generate theme CSS itself.
26
+ *
27
+ * @param props - The theme, color scheme and CSP nonce.
28
+ * @returns A `<style id="c15t-theme">` element.
29
+ * @example
30
+ * ```tsx
31
+ * // app/layout.tsx (Server Component)
32
+ * import { ConsentTheme } from '@c15t/nextjs';
33
+ * import { theme } from './consent-theme';
34
+ *
35
+ * <ConsentTheme theme={theme} colorScheme="system" />
36
+ * ```
37
+ */
38
+ export declare const ConsentTheme: ({ theme, colorScheme, nonce, }: ConsentThemeProps) => import("react").JSX.Element;
@@ -1,3 +1,4 @@
1
+ import type { SaveUISource } from '@c15t/core';
1
2
  /**
2
3
  * Value provided by the ConsentTrackingContext.
3
4
  *
@@ -30,3 +31,12 @@ export declare const ConsentTrackingContext: import("react").Context<ConsentTrac
30
31
  * @public
31
32
  */
32
33
  export declare const useConsentTracking: () => ConsentTrackingValue;
34
+ /**
35
+ * Narrow a tracking `uiSource` to a value the kernel records. Custom labels
36
+ * fall back to the kernel's `activeUI` attribution.
37
+ *
38
+ * @param value - The `uiSource` from props or context.
39
+ * @returns A kernel save source, or `undefined` to keep the default.
40
+ * @public
41
+ */
42
+ export declare const toSaveUISource: (value: string | undefined) => SaveUISource | undefined;
@@ -41,10 +41,10 @@ export interface ThemeContextValue {
41
41
  */
42
42
  trapFocus?: boolean;
43
43
  /**
44
- * Color scheme preference.
44
+ * Color scheme preference. `null` when the provider leaves the class alone.
45
45
  * @default 'system'
46
46
  */
47
- colorScheme?: 'light' | 'dark' | 'system';
47
+ colorScheme?: 'light' | 'dark' | 'system' | null;
48
48
  }
49
49
  /**
50
50
  * Context for providing theme values to components.
@@ -13,5 +13,11 @@ export interface ProviderServices {
13
13
  clearRecords: () => void;
14
14
  getPresentation: () => ConsentPresentation | undefined;
15
15
  getConsentCategories: () => readonly AllConsentNames[];
16
+ /**
17
+ * Store a language override and load its copy: init runs again on the
18
+ * provider's own kernel while it is enabled, and a borrowed runtime
19
+ * reinitializes itself.
20
+ */
21
+ setLanguage: (code: string) => void;
16
22
  }
17
23
  export declare const ProviderServicesContext: import("react").Context<ProviderServices | null>;
@@ -15,7 +15,7 @@ export type DevToolsProps = ConsentDevToolsProps;
15
15
  * @param props - Presentation options passed to the DevTools engine.
16
16
  * @returns `null`; the engine mounts its interface into `document.body`.
17
17
  */
18
- export declare const ConsentDevTools: ({ disabled, clearRecords, getPresentation, defaultOpen, defaultTab, getConsentCategories, maxEvents, position, }: ConsentDevToolsProps) => null;
18
+ export declare const ConsentDevTools: ({ disabled, clearRecords, getPresentation, defaultOpen, defaultTab, getConsentCategories, maxEvents, position, shadow, }: ConsentDevToolsProps) => null;
19
19
  /** Compatible short name for {@link ConsentDevTools}. */
20
20
  export declare const DevTools: typeof ConsentDevTools;
21
21
  /** Backward-compatible name for {@link ConsentDevTools}. */
@@ -24,13 +24,24 @@ export declare const C15TDevTools: typeof ConsentDevTools;
24
24
  export interface C15tTanStackDevtoolsPanelProps extends HTMLAttributes<HTMLDivElement>, Pick<DevToolsOptions, 'defaultTab' | 'maxEvents' | 'getConsentCategories' | 'getPresentation' | 'clearRecords'> {
25
25
  /** Prevents the embedded DevTools engine from mounting. @default false */
26
26
  disabled?: boolean;
27
+ /**
28
+ * Color scheme of the surrounding devtools shell. Omit to follow the
29
+ * operating system. {@link c15tDevtools} passes TanStack's theme.
30
+ */
31
+ theme?: TanStackDevtoolsTheme;
32
+ }
33
+ /** Color scheme TanStack Devtools passes to plugin panels. */
34
+ export type TanStackDevtoolsTheme = 'light' | 'dark';
35
+ /** Props React TanStack Devtools passes to a plugin's render function. */
36
+ export interface TanStackDevtoolsPluginProps {
37
+ theme?: TanStackDevtoolsTheme;
27
38
  }
28
39
  /** Plugin configuration accepted by React TanStack Devtools. */
29
40
  export interface TanStackDevtoolsPlugin {
30
41
  id?: string;
31
42
  name: string;
32
43
  defaultOpen?: boolean;
33
- render: ReactElement;
44
+ render: (element: HTMLElement, props?: TanStackDevtoolsPluginProps | TanStackDevtoolsTheme) => ReactElement;
34
45
  }
35
46
  /** Options for {@link c15tDevtools}. */
36
47
  export interface C15tDevtoolsPluginOptions extends C15tTanStackDevtoolsPanelProps {
@@ -1,4 +1,4 @@
1
- import type { AllConsentNames, ConsentState, SaveResult, SaveInput } from '@c15t/core';
1
+ import type { AllConsentNames, ConsentKernel, ConsentState, SaveResult, SaveInput, SaveUISource } from '@c15t/core';
2
2
  import type { ReactNode } from 'react';
3
3
  /** A local, unmasked selection, committed only by an explicit save. */
4
4
  export interface ConsentDraftHandle {
@@ -27,6 +27,34 @@ export interface ConsentDraftHandle {
27
27
  save: () => Promise<SaveResult>;
28
28
  reset: () => void;
29
29
  }
30
+ interface DraftSnapshot {
31
+ values: ConsentState;
32
+ displayedCategories: readonly AllConsentNames[];
33
+ vendors: Record<string, boolean>;
34
+ isDirty: boolean;
35
+ isStale: boolean;
36
+ }
37
+ declare const createDraftStore: (kernel: ConsentKernel, initialDefaults?: Partial<ConsentState>) => {
38
+ acceptAll(): void;
39
+ connect(): import("@c15t/core").Unsubscribe;
40
+ getSnapshot: () => DraftSnapshot;
41
+ /** The kernel this draft reads from and saves into. */
42
+ kernel: ConsentKernel;
43
+ rejectAll(): void;
44
+ reset: () => void;
45
+ save(input?: SaveInput, categories?: readonly AllConsentNames[], onSuccess?: () => void, uiSource?: SaveUISource): Promise<SaveResult>;
46
+ set(category: AllConsentNames, value: boolean): void;
47
+ /**
48
+ * Replace the defaults a category without a receipt seeds from. A
49
+ * clean draft reseeds at once, so an experiment arm assigned after
50
+ * mount shows its own defaults; edits the visitor already made stay.
51
+ */
52
+ setDefaults(next: Partial<ConsentState> | undefined): void;
53
+ setVendor(vendorId: string, granted: boolean): void;
54
+ subscribe(listener: () => void): () => void;
55
+ update: (patch: Partial<ConsentState>) => void;
56
+ };
57
+ type DraftStore = ReturnType<typeof createDraftStore>;
30
58
  export interface ConsentDraftProviderProps {
31
59
  children: ReactNode;
32
60
  /** Defaults apply only to categories without an explicit receipt. */
@@ -34,12 +62,26 @@ export interface ConsentDraftProviderProps {
34
62
  }
35
63
  export declare const ConsentDraftProvider: ({ children, initial, }: ConsentDraftProviderProps) => import("react").JSX.Element;
36
64
  /** Internal UI save path shared by stock controls and headless actions. */
37
- export declare const useConsentSaveAction: () => (input?: SaveInput) => Promise<SaveResult>;
38
- /** Keep the compatibility manager selection and its save on the same draft. */
39
- export declare const useConsentManagerDraft: () => {
40
- draft: ConsentDraftHandle;
41
- save: (input?: SaveInput) => Promise<SaveResult>;
42
- };
65
+ export declare const useConsentSaveAction: () => (input?: SaveInput, uiSource?: SaveUISource) => Promise<SaveResult>;
66
+ /**
67
+ * The nearest consent draft store, for the stock preference rows. Pair with
68
+ * {@link useConsentDraftSlice} so a row re-renders only when its own slice
69
+ * changes, not on every staged edit elsewhere in the draft.
70
+ *
71
+ * @returns The shared draft store, or a local one outside a provider.
72
+ * @internal
73
+ */
74
+ export declare const useConsentDraftStore: () => DraftStore;
75
+ /**
76
+ * Subscribes to one slice of a consent draft store.
77
+ *
78
+ * @param store - Store from {@link useConsentDraftStore}.
79
+ * @param selector - Picks the slice. Return a primitive or a reference the
80
+ * draft already holds.
81
+ * @returns The selected slice.
82
+ * @internal
83
+ */
84
+ export declare const useConsentDraftSlice: <SliceType>(store: DraftStore, selector: (draft: DraftSnapshot) => SliceType) => SliceType;
43
85
  /** Read and edit displayed choices without replacing masked effective permissions. */
44
86
  export declare const useConsentDraft: () => ConsentDraftHandle;
45
87
  /** The vendor slice of the consent draft, for a custom vendor control. */
@@ -81,3 +123,4 @@ export interface VendorDraftHandle {
81
123
  * @public
82
124
  */
83
125
  export declare const useVendorDraft: () => VendorDraftHandle;
126
+ export {};
@@ -6,7 +6,6 @@
6
6
  */
7
7
  export { defaultTranslationConfig, detectBrowserLanguage, mergeTranslationConfigs, prepareTranslationConfig, } from '@c15t/core';
8
8
  export { type ConsentDialogTriggerVisibility, type UseConsentDialogTriggerOptions, type UseConsentDialogTriggerResult, useConsentDialogTrigger, } from './component-hooks/use-panel-trigger.js';
9
- export { useConsentManager } from './component-hooks/use-manager.js';
10
9
  export { type HeadlessConsentBannerAction, type HeadlessConsentBannerState, type HeadlessConsentDialogAction, type HeadlessConsentDialogState, type HeadlessConsentSurface, type HeadlessConsentSurfaceAction, type HeadlessConsentSurfaceState, type HeadlessConsentWriteAction, useHeadlessConsentUI, } from './component-hooks/use-headless-consent-ui.js';
11
10
  export { useTranslations } from './component-hooks/use-translations.js';
12
11
  export { useColorScheme } from './hooks/use-color-scheme.js';