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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/AGENTS.md +91 -72
  2. package/README.md +21 -17
  3. package/SKILL.md +34 -0
  4. package/dist/component-hooks/use-headless-consent-ui.js +1 -1
  5. package/dist/components/consent-gate/atoms.js +1 -1
  6. package/dist/components/consent-gate/consent-gate.js +1 -1
  7. package/dist/components/iab-panel/atoms/card.js +1 -1
  8. package/dist/components/iab-panel/atoms/feature-item.js +2 -0
  9. package/dist/components/iab-panel/atoms/header.js +1 -1
  10. package/dist/components/iab-panel/iab-panel.js +1 -1
  11. package/dist/components/iab-panel/index.js +1 -1
  12. package/dist/components/iab-prompt/atoms/overlay.js +1 -1
  13. package/dist/components/iab-prompt/atoms/root.js +1 -1
  14. package/dist/components/panel/atoms/card.js +1 -1
  15. package/dist/components/panel/atoms/root.js +1 -1
  16. package/dist/components/panel-trigger/atoms/button.js +1 -1
  17. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  18. package/dist/components/preferences/atoms/accordion.js +1 -1
  19. package/dist/components/prompt/atoms/overlay.js +1 -1
  20. package/dist/components/prompt/atoms/root.js +1 -1
  21. package/dist/components/prompt/components.js +1 -1
  22. package/dist/components/shared/libs/compose-refs.js +1 -0
  23. package/dist/components/shared/libs/slot.js +1 -1
  24. package/dist/components/shared/primitives/button.js +1 -1
  25. package/dist/components/shared/ui/dialog/dialog.js +1 -1
  26. package/dist/components/shared/ui/icon.js +1 -1
  27. package/dist/context/consent-tracking-context.js +1 -1
  28. package/dist/devtools.js +1 -1
  29. package/dist/draft.js +1 -1
  30. package/dist/hooks/use-focus-trap.js +1 -1
  31. package/dist/hooks.js +1 -1
  32. package/dist/iab/styles.tw3.css +4 -4
  33. package/dist/index.js +1 -1
  34. package/dist/module-hooks/iframe-blocker.js +1 -1
  35. package/dist/postcss-tailwind3.js +1 -0
  36. package/dist/provider.js +1 -1
  37. package/dist/server/fetch-ssr-data.js +1 -1
  38. package/dist/server/headers.js +1 -1
  39. package/dist/server/normalize-url.js +1 -1
  40. package/dist/styles.tw3.css +16 -16
  41. package/dist/transports/offline.js +1 -1
  42. package/dist/ui-save.js +1 -1
  43. package/dist/utils/merge-slot-props.js +1 -1
  44. package/dist/utils/theme-utils.js +1 -1
  45. package/dist/version.js +1 -1
  46. package/dist-types/component-hooks/use-headless-consent-ui.d.ts +1 -1
  47. package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
  48. package/dist-types/components/iab-panel/iab-panel.d.ts +2 -2
  49. package/dist-types/components/iab-panel/index.d.ts +5 -2
  50. package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
  51. package/dist-types/components/iab-prompt/iab-prompt.d.ts +2 -2
  52. package/dist-types/components/iab-prompt/index.d.ts +2 -2
  53. package/dist-types/components/panel/atoms/card.d.ts +1 -0
  54. package/dist-types/components/prompt/components.d.ts +6 -0
  55. package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
  56. package/dist-types/components/shared/ui/icon.d.ts +2 -1
  57. package/dist-types/context/consent-tracking-context.d.ts +10 -0
  58. package/dist-types/context/theme-context.d.ts +2 -2
  59. package/dist-types/context.d.ts +6 -0
  60. package/dist-types/devtools.d.ts +13 -2
  61. package/dist-types/draft.d.ts +10 -4
  62. package/dist-types/hooks/use-focus-trap.d.ts +3 -1
  63. package/dist-types/hooks.d.ts +54 -13
  64. package/dist-types/iab.d.ts +1 -1
  65. package/dist-types/index.d.ts +2 -2
  66. package/dist-types/postcss-tailwind3.d.ts +21 -0
  67. package/dist-types/provider.d.ts +22 -5
  68. package/dist-types/server/headers.d.ts +14 -4
  69. package/dist-types/server/normalize-url.d.ts +14 -7
  70. package/dist-types/server/types.d.ts +12 -1
  71. package/dist-types/transports/offline.d.ts +7 -16
  72. package/dist-types/ui-config-context.d.ts +7 -1
  73. package/dist-types/utils/merge-slot-props.d.ts +15 -1
  74. package/dist-types/utils/theme-utils.d.ts +17 -2
  75. package/dist-types/version.d.ts +1 -1
  76. package/docs/README.md +91 -72
  77. package/docs/assets/v3/bottom-bar.png +0 -0
  78. package/docs/assets/v3/brand-card.png +0 -0
  79. package/docs/assets/v3/brand-preferences.png +0 -0
  80. package/docs/assets/v3/choice-wall.png +0 -0
  81. package/docs/assets/v3/headless-bar-html.png +0 -0
  82. package/docs/assets/v3/headless-bar-mobile.png +0 -0
  83. package/docs/assets/v3/headless-bar.png +0 -0
  84. package/docs/assets/v3/slim-bar.png +0 -0
  85. package/docs/concepts/choose-your-setup.md +87 -0
  86. package/docs/{frameworks/react/concepts → concepts}/consent-categories.md +22 -7
  87. package/docs/{guides → concepts}/consent-state.md +71 -101
  88. package/docs/{guides → concepts}/data-fetching.md +31 -27
  89. package/docs/concepts/how-consent-works.md +123 -0
  90. package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +7 -59
  91. package/docs/customization/class-names.md +202 -0
  92. package/docs/customization/dark-mode.md +157 -0
  93. package/docs/customization/motion.md +119 -0
  94. package/docs/customization/overview.md +67 -34
  95. package/docs/customization/recipes.md +839 -49
  96. package/docs/customization/slots.md +216 -35
  97. package/docs/customization/stylesheets.md +147 -0
  98. package/docs/customization/tailwind.md +842 -0
  99. package/docs/customization/tokens.md +163 -96
  100. package/docs/customization/translations.md +61 -3
  101. package/docs/frameworks/react/callbacks.md +118 -0
  102. package/docs/frameworks/react/clear-on-revocation.md +106 -0
  103. package/docs/frameworks/react/components/consent-banner.md +42 -28
  104. package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
  105. package/docs/frameworks/react/components/consent-dialog-trigger.md +81 -76
  106. package/docs/frameworks/react/components/consent-dialog.md +56 -50
  107. package/docs/frameworks/react/components/consent-gate.md +37 -20
  108. package/docs/frameworks/react/components/consent-provider.md +126 -0
  109. package/docs/frameworks/react/components/consent-widget.md +23 -20
  110. package/docs/frameworks/react/components/dev-tools.md +52 -84
  111. package/docs/frameworks/react/components.md +105 -0
  112. package/docs/frameworks/react/compose.md +354 -0
  113. package/docs/frameworks/react/content-security-policy.md +126 -0
  114. package/docs/frameworks/react/customize.md +250 -0
  115. package/docs/frameworks/react/embeds.md +89 -0
  116. package/docs/frameworks/react/{hooks/overview.md → hooks.md} +21 -16
  117. package/docs/frameworks/react/{iab/overview.md → iab.md} +80 -31
  118. package/docs/frameworks/react/network-blocker.md +35 -41
  119. package/docs/frameworks/react/quickstart.md +139 -101
  120. package/docs/frameworks/react/rendering.md +128 -0
  121. package/docs/frameworks/react/scripts.md +115 -0
  122. package/docs/frameworks/react/translations.md +155 -0
  123. package/docs/frameworks/react/troubleshooting.md +92 -47
  124. package/docs/frameworks/react/vendor-consent.md +170 -0
  125. package/docs/guides/banner-experiments.md +654 -0
  126. package/docs/guides/troubleshooting.md +120 -47
  127. package/docs/guides/verify-consent.md +81 -49
  128. package/docs/integrations/adobe-analytics.md +167 -159
  129. package/docs/integrations/ahrefs-analytics.md +152 -154
  130. package/docs/integrations/amplitude.md +162 -156
  131. package/docs/integrations/building-integrations.md +136 -37
  132. package/docs/integrations/clearbit.md +154 -154
  133. package/docs/integrations/cloudflare-web-analytics.md +156 -156
  134. package/docs/integrations/cloudflare-zaraz.md +209 -261
  135. package/docs/integrations/crisp.md +164 -158
  136. package/docs/integrations/databuddy.md +157 -173
  137. package/docs/integrations/fathom-analytics.md +158 -156
  138. package/docs/integrations/front-chat.md +167 -167
  139. package/docs/integrations/google-maps.md +118 -83
  140. package/docs/integrations/google-tag-manager.md +178 -163
  141. package/docs/integrations/google-tag.md +163 -160
  142. package/docs/integrations/heap.md +163 -155
  143. package/docs/integrations/hightouch.md +161 -157
  144. package/docs/integrations/hotjar.md +159 -155
  145. package/docs/integrations/intercom.md +183 -153
  146. package/docs/integrations/klaviyo.md +486 -0
  147. package/docs/integrations/linkedin-insights.md +174 -150
  148. package/docs/integrations/logrocket.md +160 -156
  149. package/docs/integrations/matomo-analytics.md +188 -178
  150. package/docs/integrations/meta-pixel.md +188 -150
  151. package/docs/integrations/microsoft-clarity.md +163 -155
  152. package/docs/integrations/microsoft-uet.md +148 -154
  153. package/docs/integrations/mixpanel-analytics.md +155 -160
  154. package/docs/integrations/one-dollar-stats.md +166 -165
  155. package/docs/integrations/openai-pixel.md +204 -301
  156. package/docs/integrations/overview.md +137 -80
  157. package/docs/integrations/pinterest-tag.md +191 -183
  158. package/docs/integrations/pirsch.md +169 -159
  159. package/docs/integrations/plausible-analytics.md +172 -158
  160. package/docs/integrations/posthog.md +226 -241
  161. package/docs/integrations/promptwatch.md +154 -154
  162. package/docs/integrations/reddit-pixel.md +185 -157
  163. package/docs/integrations/rudderstack.md +201 -186
  164. package/docs/integrations/rybbit-analytics.md +171 -160
  165. package/docs/integrations/segment.md +182 -154
  166. package/docs/integrations/snapchat-pixel.md +186 -156
  167. package/docs/integrations/tiktok-pixel.md +171 -150
  168. package/docs/integrations/umami-analytics.md +163 -158
  169. package/docs/integrations/vercel-analytics.md +166 -157
  170. package/docs/integrations/x-pixel.md +176 -150
  171. package/docs/integrations/youtube.md +121 -86
  172. package/docs/upgrade-v3.md +475 -467
  173. package/package.json +15 -9
  174. package/docs/assets/v3/brand-bar.png +0 -0
  175. package/docs/assets/v3/mobile-card.png +0 -0
  176. package/docs/assets/v3/preferences.png +0 -0
  177. package/docs/frameworks/react/components/consent-manager-provider.md +0 -95
  178. package/docs/frameworks/react/script-loader.md +0 -69
  179. package/docs/frameworks/react/styling/overview.md +0 -266
  180. package/docs/guides/deployment-modes.md +0 -75
  181. package/docs/guides/shared-consent-controls.md +0 -158
  182. package/docs/integrations/clear-on-revocation.md +0 -167
  183. package/docs/integrations/granular-consent.md +0 -210
@@ -10,6 +10,7 @@ import '@c15t/ui/styles/dialog';
10
10
  import type { FC } from 'react';
11
11
  import { IABConsentDialogCard } from './atoms/card.js';
12
12
  import { IABConsentDialogContent } from './atoms/content.js';
13
+ import { FeatureItem } from './atoms/feature-item.js';
13
14
  import { IABConsentDialogFooter } from './atoms/footer.js';
14
15
  import { IABConsentDialogHeader } from './atoms/header.js';
15
16
  import { IABConsentDialogOverlay } from './atoms/overlay.js';
@@ -32,19 +33,20 @@ export interface IABConsentDialogCompoundComponent extends FC<IABConsentDialogPr
32
33
  Content: typeof IABConsentDialogContent;
33
34
  Footer: typeof IABConsentDialogFooter;
34
35
  Overlay: typeof IABConsentDialogOverlay;
36
+ FeatureItem: typeof FeatureItem;
35
37
  PurposeItem: typeof PurposeItem;
36
38
  StackItem: typeof StackItem;
37
39
  VendorList: typeof VendorList;
38
40
  }
39
41
  /**
40
- * IAB TCF 2.3 compliant consent dialog dialog component.
42
+ * IAB TCF 2.4 compliant consent dialog dialog component.
41
43
  *
42
44
  * @remarks
43
45
  * This component serves as the main entry point for rendering an IAB-compliant consent dialog.
44
46
  * It provides a structured layout with required IAB TCF elements.
45
47
  *
46
48
  * Key features:
47
- * - IAB TCF 2.3 compliant
49
+ * - IAB TCF 2.4 compliant
48
50
  * - Fully accessible by default
49
51
  * - Customizable appearance
50
52
  * - Compound component pattern support
@@ -79,6 +81,7 @@ declare const IABConsentDialog: IABConsentDialogCompoundComponent;
79
81
  export default IABConsentDialog;
80
82
  export { IABConsentDialogCard } from './atoms/card.js';
81
83
  export { IABConsentDialogContent } from './atoms/content.js';
84
+ export { FeatureItem, type FeatureItemProps } from './atoms/feature-item.js';
82
85
  export { IABConsentDialogFooter } from './atoms/footer.js';
83
86
  export { IABConsentDialogHeader } from './atoms/header.js';
84
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
  /**
@@ -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,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;
@@ -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, ConsentKernel, 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 {
@@ -34,7 +34,7 @@ interface DraftSnapshot {
34
34
  isDirty: boolean;
35
35
  isStale: boolean;
36
36
  }
37
- declare const createDraftStore: (kernel: ConsentKernel, defaults?: Partial<ConsentState>) => {
37
+ declare const createDraftStore: (kernel: ConsentKernel, initialDefaults?: Partial<ConsentState>) => {
38
38
  acceptAll(): void;
39
39
  connect(): import("@c15t/core").Unsubscribe;
40
40
  getSnapshot: () => DraftSnapshot;
@@ -42,8 +42,14 @@ declare const createDraftStore: (kernel: ConsentKernel, defaults?: Partial<Conse
42
42
  kernel: ConsentKernel;
43
43
  rejectAll(): void;
44
44
  reset: () => void;
45
- save(input?: SaveInput, categories?: readonly AllConsentNames[], onSuccess?: () => void): Promise<SaveResult>;
45
+ save(input?: SaveInput, categories?: readonly AllConsentNames[], onSuccess?: () => void, uiSource?: SaveUISource): Promise<SaveResult>;
46
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;
47
53
  setVendor(vendorId: string, granted: boolean): void;
48
54
  subscribe(listener: () => void): () => void;
49
55
  update: (patch: Partial<ConsentState>) => void;
@@ -56,7 +62,7 @@ export interface ConsentDraftProviderProps {
56
62
  }
57
63
  export declare const ConsentDraftProvider: ({ children, initial, }: ConsentDraftProviderProps) => import("react").JSX.Element;
58
64
  /** Internal UI save path shared by stock controls and headless actions. */
59
- export declare const useConsentSaveAction: () => (input?: SaveInput) => Promise<SaveResult>;
65
+ export declare const useConsentSaveAction: () => (input?: SaveInput, uiSource?: SaveUISource) => Promise<SaveResult>;
60
66
  /**
61
67
  * The nearest consent draft store, for the stock preference rows. Pair with
62
68
  * {@link useConsentDraftSlice} so a row re-renders only when its own slice
@@ -1,3 +1,4 @@
1
+ import type { FocusTrapOptions } from '@c15t/ui/utils/dom';
1
2
  import type { RefObject } from 'react';
2
3
  /**
3
4
  * Hook that manages focus trapping within a container.
@@ -8,7 +9,8 @@ import type { RefObject } from 'react';
8
9
  *
9
10
  * @param shouldTrap - Boolean indicating whether focus should be trapped
10
11
  * @param containerRef - Reference to the container element
12
+ * @param options - Where the trap puts focus when it starts
11
13
  *
12
14
  * @public
13
15
  */
14
- export declare const useFocusTrap: (shouldTrap: boolean, containerRef: RefObject<HTMLElement | null> | null) => void;
16
+ export declare const useFocusTrap: (shouldTrap: boolean, containerRef: RefObject<HTMLElement | null> | null, options?: FocusTrapOptions) => void;
@@ -17,7 +17,8 @@
17
17
  * observed through the selector hooks, whose subscription model handles
18
18
  * invalidation correctly.
19
19
  */
20
- import type { AllConsentNames, ConsentKernel, PromptPresentation, PreferencesPresentation, ConsentSnapshot, ConsentState, KernelActiveUI, KernelBranding, KernelIABState, KernelModel, KernelOverrides, KernelTranslations, KernelUser, LocationResponse, PolicyScopeMode, ResolvedVendor, VendorChoice } from '@c15t/core';
20
+ import type { AllConsentNames, ConsentKernel, ConsentPresentation, ExperimentAssignment, PromptPresentation, PreferencesPresentation, ConsentSnapshot, ConsentState, KernelActiveUI, KernelBranding, KernelIABState, KernelModel, KernelOverrides, KernelTranslations, KernelUser, LocationResponse, PolicyScopeMode, ResolvedVendor, VendorChoice } from '@c15t/core';
21
+ import type { Theme } from './types/theme/index.js';
21
22
  /**
22
23
  * Full snapshot accessor. Escape hatch for consumers that genuinely need
23
24
  * multiple slices. Prefer narrow hooks for re-render isolation.
@@ -108,14 +109,13 @@ export declare const useDeclaredVendors: () => readonly ResolvedVendor[];
108
109
  */
109
110
  export declare const useVendorChoice: () => Readonly<VendorChoice> | null;
110
111
  /**
111
- * Whether one vendor is allowed: its category condition passes and the
112
- * visitor has not turned it off.
112
+ * Whether one vendor may load: it is declared, its category condition
113
+ * passes, and outside IAB the visitor has not turned it off.
113
114
  *
114
- * @param vendorId - Vendor slug as declared in `vendors` or on a script.
115
- * @returns `false` while the vendor is denied outside `iab`, otherwise the
116
- * result of its declared category condition. An undeclared id is `true`:
117
- * nothing is known about its category, and a denial only exists for a vendor
118
- * the visitor saw.
115
+ * @param vendorId - Vendor id as declared in `vendors`, on a script or by
116
+ * the backend.
117
+ * @returns `true` while the vendor may load. An id nothing declares, such
118
+ * as a typo, returns `false` and logs a development warning.
119
119
  */
120
120
  export declare const useVendorAllowed: (vendorId: string) => boolean;
121
121
  /** Register categories used by scripts, frames, or other integrations. */
@@ -125,7 +125,21 @@ export declare const useRegisterConsentCategories: () => (categories: readonly A
125
125
  */
126
126
  export declare const useSetOverrides: () => (input: KernelOverrides) => void;
127
127
  /**
128
- * Sync mutation: switch active language.
128
+ * Switch the consent language and load its copy.
129
+ *
130
+ * Stores the language override and runs init again, so the banner and
131
+ * dialog show copy in that language: a hosted backend returns it, and
132
+ * offline mode takes it from the bundled translations and `i18n.messages`.
133
+ * Setting the current language does nothing. A disabled provider stores
134
+ * the language without running init.
135
+ *
136
+ * @returns A setter that takes a language code such as `'de'`.
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * const setLanguage = useSetLanguage();
141
+ * <button onClick={() => setLanguage('de')}>Deutsch</button>
142
+ * ```
129
143
  */
130
144
  export declare const useSetLanguage: () => (code: string) => void;
131
145
  /**
@@ -161,8 +175,6 @@ export declare const usePromptRequirement: () => ConsentSnapshot['promptRequirem
161
175
  export declare const useNoticeDismissal: () => ConsentSnapshot['noticeDismissal'];
162
176
  /** Read privacySignals from the kernel without a competing projection. */
163
177
  export declare const usePrivacySignals: () => ConsentSnapshot['privacySignals'];
164
- /** Read optOutDirectives from the kernel without a competing projection. */
165
- export declare const useOptOutDirectives: () => ConsentSnapshot['optOutDirectives'];
166
178
  /** Read resolution from the kernel without a competing projection. */
167
179
  export declare const usePolicyResolution: () => ConsentSnapshot['resolution'];
168
180
  /** Read policyRule from the kernel without a competing projection. */
@@ -171,7 +183,36 @@ export declare const usePolicyRule: () => ConsentSnapshot['policyRule'];
171
183
  export declare const useRestrictions: () => ConsentSnapshot['restrictions'];
172
184
  /** Dismiss the current local notice without recording a category choice. */
173
185
  export declare const useDismissNotice: () => ConsentKernel['commands']['dismissNotice'];
174
- /** Host first-layer presentation. */
186
+ /**
187
+ * The presentation experiment arm this visitor runs. Built-in assignment
188
+ * lands after mount; a host-resolved `variant` is known at once.
189
+ *
190
+ * @returns The assignment, or `null` while no experiment is configured, the
191
+ * arm is not assigned yet, or the visitor's policy rejects it.
192
+ *
193
+ * @example
194
+ * ```tsx
195
+ * const arm = useExperiment();
196
+ * return arm ? <p>{arm.id}: {arm.variant}</p> : null;
197
+ * ```
198
+ */
199
+ export declare const useExperiment: () => Readonly<ExperimentAssignment> | null;
200
+ /**
201
+ * The host presentation with the assigned experiment arm merged over it.
202
+ *
203
+ * @returns The presentation to render: `options.presentation` itself while
204
+ * no arm is assigned.
205
+ */
206
+ export declare const useResolvedPresentation: () => ConsentPresentation | undefined;
207
+ /**
208
+ * The host theme with the assigned experiment arm's `theme` merged over it.
209
+ * Render its tokens with `<ConsentTheme theme={useResolvedTheme()} />`.
210
+ *
211
+ * @returns The theme to render: `options.theme` itself while no arm is
212
+ * assigned or the arm has no theme.
213
+ */
214
+ export declare const useResolvedTheme: () => Theme | undefined;
215
+ /** Host first-layer presentation, with the experiment arm applied. */
175
216
  export declare const usePromptPresentation: () => PromptPresentation;
176
- /** Host persistent preferences presentation. */
217
+ /** Host persistent preferences presentation, with the experiment arm applied. */
177
218
  export declare const usePreferencesPresentation: () => PreferencesPresentation;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * IAB TCF 2.3 React components and hooks.
2
+ * IAB TCF 2.4 React components and hooks.
3
3
  *
4
4
  * This subpath export contains all IAB-specific React UI. It is only
5
5
  * loaded when explicitly imported from '@c15t/react/iab'.
@@ -49,7 +49,7 @@ export { ConsentGate, Frame } from './components/consent-gate/index.js';
49
49
  export type { ConsentDraftHandle, ConsentDraftProviderProps, VendorDraftHandle, } from './draft.js';
50
50
  export { ConsentDraftProvider, useConsentDraft, useVendorDraft } from './draft.js';
51
51
  export { useTranslations } from './component-hooks/use-translations.js';
52
- export { useActiveUI, useBranding, useConsent, useConsents, useHasConsentPolicy, useHasConsentPreferences, useHasConsentUI, useIABEnabled, useIABSnapshot, useIdentify, useInit, useLocation, useModel, useOverrides, usePromptPresentation, usePolicyCategories, usePreferencesPresentation, usePolicyScopeMode, usePurposeConsent, useRegisterConsentCategories, useSaveConsents, useSetActiveUI, useSetLanguage, useSetOverrides, useSnapshot, useSpecialFeatureOptIn, useSubscribeToConsentChanges, useTCString, useUser, useDeclaredVendors, useVendorAllowed, useVendorChoice, useVendorConsent, } from './hooks.js';
52
+ export { useActiveUI, useBranding, useConsent, useConsents, useExperiment, useHasConsentPolicy, useHasConsentPreferences, useHasConsentUI, useIABEnabled, useIABSnapshot, useIdentify, useInit, useLocation, useModel, useOverrides, usePromptPresentation, usePolicyCategories, usePreferencesPresentation, useResolvedPresentation, useResolvedTheme, usePolicyScopeMode, usePurposeConsent, useRegisterConsentCategories, useSaveConsents, useSetActiveUI, useSetLanguage, useSetOverrides, useSnapshot, useSpecialFeatureOptIn, useSubscribeToConsentChanges, useTCString, useUser, useDeclaredVendors, useVendorAllowed, useVendorChoice, useVendorConsent, } from './hooks.js';
53
53
  export type { UseIframeBlockerOptions, UseNetworkBlockerOptions, UsePersistenceOptions, UseScriptLoaderOptions, } from './module-hooks.js';
54
54
  export { useIframeBlocker, useNetworkBlocker, usePersistence, useScriptLoader, } from './module-hooks.js';
55
55
  export type { ConsentProviderOptions, ConsentProviderCallbacks, ConsentProviderPrefetch, ConsentProviderProps, ExternalRuntimeProviderOptions, ExternalRuntimeProviderProps, OwnedRuntimeProviderProps, } from './provider.js';
@@ -58,5 +58,5 @@ export { ConsentTheme } from './consent-theme.js';
58
58
  export type { ConsentThemeProps } from './consent-theme.js';
59
59
  export type { ReactUIOptions } from './types/manager.js';
60
60
  export { defineTheme, type Theme } from './types/theme/index.js';
61
- export { useExplicitChoice, useEffectivePermissions, usePromptRequirement, useNoticeDismissal, usePrivacySignals, useOptOutDirectives, usePolicyResolution, usePolicyRule, useRestrictions, useDismissNotice, } from './hooks.js';
61
+ export { useExplicitChoice, useEffectivePermissions, usePromptRequirement, useNoticeDismissal, usePrivacySignals, usePolicyResolution, usePolicyRule, useRestrictions, useDismissNotice, } from './hooks.js';
62
62
  export type { ConsentPresentation, PromptPresentation, PreferencesPresentation, PresentationAction, PromptPosition, PromptVariant, ResolvedConsentPresentation, } from '@c15t/core';
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Tailwind 3 PostCSS plugin for c15t stylesheets, re-exported from
3
+ * `@c15t/ui/postcss-tailwind3` so an app that installs `@c15t/react` can list
4
+ * `@c15t/react/postcss-tailwind3` without installing `@c15t/ui`.
5
+ * See `@c15t/ui/postcss-tailwind3` for what the plugin does. It must come
6
+ * before `tailwindcss`.
7
+ *
8
+ * @example
9
+ * ```js
10
+ * // postcss.config.mjs
11
+ * export default {
12
+ * plugins: {
13
+ * '@c15t/react/postcss-tailwind3': {},
14
+ * tailwindcss: {},
15
+ * autoprefixer: {},
16
+ * },
17
+ * };
18
+ * ```
19
+ */
20
+ export * from '@c15t/ui/postcss-tailwind3';
21
+ export { default } from '@c15t/ui/postcss-tailwind3';
@@ -1,4 +1,4 @@
1
- import type { AllConsentNames, ClearOnRevocationConfig, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User, Vendor } from '@c15t/core';
1
+ import type { AllConsentNames, ClearOnRevocationConfig, ConsentExperiment, ExperimentState, 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
3
  import type { ConsentControlOptions, ConsentRuntime } from '@c15t/core/runtime';
4
4
  import type { ReactNode } from 'react';
@@ -8,12 +8,23 @@ import type { UseIframeBlockerOptions } from './module-hooks/iframe-blocker.js';
8
8
  import type { ReactUIOptions } from './types/manager.js';
9
9
  import type { ReactComponentSlots } from './types/slots.js';
10
10
  /** Events emitted by the mounted provider without snapshot-derived consent aliases. */
11
- export type ConsentProviderCallbacks = Pick<Callbacks, 'onChoiceRecorded' | 'onPermissionsChanged' | 'onError' | 'onBeforeConsentRevocationReload'>;
12
- /** Prepared policy and records; legacy consent projections are not provider inputs. */
13
- export type ConsentProviderPrefetch = Omit<KernelConfig, 'initialDraft' | 'transport'>;
11
+ export type ConsentProviderCallbacks = Pick<Callbacks, 'onChoiceRecorded' | 'onPermissionsChanged' | 'onSurfaceShown' | 'onError' | 'onBeforeConsentRevocationReload'>;
12
+ /**
13
+ * Prepared policy and records; legacy consent projections are not provider
14
+ * inputs. An `experiment` a server helper resolved runs instead of
15
+ * `options.experiment`.
16
+ */
17
+ export type ConsentProviderPrefetch = Omit<KernelConfig, 'initialDraft' | 'transport'> & ExperimentState;
14
18
  export interface ConsentProviderOptions extends ConsentControlOptions, Pick<ReactUIOptions, 'colorScheme' | 'disableAnimation' | 'noStyle' | 'scrollLock' | 'theme' | 'trapFocus'> {
15
19
  enabled?: boolean;
16
20
  presentation?: ConsentPresentation;
21
+ /**
22
+ * A/B experiment on prompt/preferences presentation. The assigned arm is
23
+ * merged over `presentation`, exposed through `useExperiment()`, and
24
+ * recorded with every impression and choice. Initial-only: remount the
25
+ * provider to change the experiment.
26
+ */
27
+ experiment?: ConsentExperiment;
17
28
  /**
18
29
  * Content Security Policy nonce applied to DOM nodes c15t injects.
19
30
  *
@@ -147,13 +158,19 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
147
158
  * Everything the component tree still owns — theme, slots, legal links —
148
159
  * is unchanged.
149
160
  */
150
- export type ExternalRuntimeProviderOptions = Omit<ConsentProviderOptions, 'mode' | 'vendors'> & {
161
+ export type ExternalRuntimeProviderOptions = Omit<ConsentProviderOptions, 'callbacks' | 'mode' | 'vendors'> & {
151
162
  mode?: ConsentProviderOptions['mode'];
152
163
  /**
153
164
  * Not accepted here: the runtime owner declares vendors through
154
165
  * `createConsentRuntime({ vendors })`, and the kernel carries them.
155
166
  */
156
167
  vendors?: never;
168
+ /**
169
+ * Not accepted here: the runtime owner passes callbacks to
170
+ * `createConsentRuntime({ callbacks })`, and the runtime runs them.
171
+ * Passing them anyway logs a warning in development.
172
+ */
173
+ callbacks?: never;
157
174
  };
158
175
  /** The provider builds and owns its own kernel. */
159
176
  export interface OwnedRuntimeProviderProps {
@@ -1,5 +1,10 @@
1
- declare const FORWARDED_HEADERS: readonly ["x-c15t-country", "cf-ipcountry", "x-vercel-ip-country", "x-amz-cf-ipcountry", "x-country-code", "x-country", "x-c15t-region", "cf-region-code", "x-vercel-ip-country-region", "x-region-code", "accept-language", "x-c15t-gpc", "sec-gpc", "x-c15t-version", "user-agent", "x-forwarded-host", "x-forwarded-for", "purpose", "sec-purpose", "next-router-prefetch", "x-middleware-prefetch"];
2
- type ForwardedHeader = (typeof FORWARDED_HEADERS)[number];
1
+ declare const FORWARDED_HEADERS: readonly ["x-c15t-country", "cf-ipcountry", "x-vercel-ip-country", "x-amz-cf-ipcountry", "x-country-code", "x-country", "x-c15t-region", "cf-region-code", "x-vercel-ip-country-region", "x-region-code", "accept-language", "x-c15t-gpc", "sec-gpc", "x-c15t-version", "user-agent", "x-forwarded-for", "purpose", "sec-purpose", "next-router-prefetch", "x-middleware-prefetch"];
2
+ /**
3
+ * Forwarding headers a client can set to name a host or scheme. Passed to
4
+ * the backend only when the app trusts them.
5
+ */
6
+ export declare const CLIENT_FORWARDING_HEADERS: readonly ['forwarded', 'x-forwarded-host', 'x-forwarded-proto'];
7
+ type ForwardedHeader = (typeof FORWARDED_HEADERS)[number] | (typeof CLIENT_FORWARDING_HEADERS)[number];
3
8
  type RelevantHeaders = Partial<Record<ForwardedHeader, string>>;
4
9
  /**
5
10
  * Extracts relevant headers for consent management from the request headers.
@@ -12,10 +17,13 @@ type RelevantHeaders = Partial<Record<ForwardedHeader, string>>;
12
17
  * The extracted headers include:
13
18
  * - Country headers (cf-ipcountry, x-vercel-ip-country, etc.)
14
19
  * - Region headers (x-vercel-ip-country-region, x-region-code)
15
- * - Standard headers (accept-language, user-agent, x-forwarded-*)
20
+ * - Standard headers (accept-language, user-agent, x-forwarded-for)
16
21
  * - Prefetch headers (purpose, sec-purpose, next-router-prefetch, x-middleware-prefetch)
17
22
  *
18
23
  * @param headersList - The Headers object from the incoming request
24
+ * @param options - `trustForwardedHeaders` also copies `forwarded`,
25
+ * `x-forwarded-host` and `x-forwarded-proto`, which any client can send.
26
+ * Leave it off unless a proxy you control sets them and drops incoming ones.
19
27
  * @returns An object containing the relevant headers for consent management
20
28
  *
21
29
  * @example
@@ -28,5 +36,7 @@ type RelevantHeaders = Partial<Record<ForwardedHeader, string>>;
28
36
  *
29
37
  * @public
30
38
  */
31
- export declare const extractRelevantHeaders: (headersList: Headers) => RelevantHeaders;
39
+ export declare const extractRelevantHeaders: (headersList: Headers, options?: {
40
+ trustForwardedHeaders?: boolean;
41
+ }) => RelevantHeaders;
32
42
  export {};
@@ -21,16 +21,21 @@ export declare const validateBackendURL: (backendURL: string) => {
21
21
  normalizedURL: string;
22
22
  };
23
23
  /**
24
- * Normalizes a backend URL, resolving relative URLs using request headers.
24
+ * Normalizes a backend URL, resolving relative URLs against the request.
25
25
  *
26
26
  * @remarks
27
27
  * For absolute URLs, returns the URL as-is (with trailing slash trimmed).
28
- * For relative URLs, attempts to construct the full URL using:
29
- * 1. x-forwarded-proto + x-forwarded-host/host headers
30
- * 2. Referer header as fallback
28
+ * A relative URL resolves against the `host` header: over `https` for a
29
+ * domain name, and over `http` for `localhost`, an IP address or a
30
+ * single-label host. `x-forwarded-host`, `x-forwarded-proto` and `forwarded`
31
+ * are read only when `trustForwardedHeaders` is set, because any client can
32
+ * send them; the `referer` header is never used.
31
33
  *
32
34
  * @param backendURL - The backend URL (absolute or relative)
33
35
  * @param headersList - The Headers object from the incoming request
36
+ * @param options - `trustForwardedHeaders`: resolve against the request's
37
+ * forwarding headers. Set it only behind a proxy that sets them and drops
38
+ * incoming ones.
34
39
  * @returns The normalized absolute URL, or null if it cannot be determined
35
40
  *
36
41
  * @example
@@ -41,11 +46,13 @@ export declare const validateBackendURL: (backendURL: string) => {
41
46
  * normalizeBackendURL('https://api.example.com/', headers);
42
47
  * // Returns: 'https://api.example.com'
43
48
  *
44
- * // Relative URL - resolved from headers
49
+ * // Relative URL - resolved from the host header
45
50
  * normalizeBackendURL('/api/consent', headers);
46
- * // Returns: 'https://example.com/api/consent' (based on headers)
51
+ * // Returns: 'https://example.com/api/consent' (for `host: example.com`)
47
52
  * ```
48
53
  *
49
54
  * @public
50
55
  */
51
- export declare const normalizeBackendURL: (backendURL: string, headersList: Headers) => string | null;
56
+ export declare const normalizeBackendURL: (backendURL: string, headersList: Headers, options?: {
57
+ trustForwardedHeaders?: boolean;
58
+ }) => string | null;
@@ -12,9 +12,20 @@ import type { Overrides, SSRInitialData } from '@c15t/core';
12
12
  export interface FetchSSRDataOptionsBase {
13
13
  /**
14
14
  * The backend URL to fetch consent data from.
15
- * Can be absolute (https://...) or relative (/api/consent).
15
+ * Can be absolute (https://...) or relative (/api/consent). A relative
16
+ * URL resolves against the request's `host` header.
16
17
  */
17
18
  backendURL: string;
19
+ /**
20
+ * Resolve a relative `backendURL` against the request's `forwarded`,
21
+ * `x-forwarded-host` and `x-forwarded-proto` headers instead of `host`.
22
+ * Any client can send those headers, so set this only behind a proxy
23
+ * that sets them and drops incoming ones. Also forwards those three
24
+ * headers to the backend, which is skipped otherwise.
25
+ *
26
+ * @default false
27
+ */
28
+ trustForwardedHeaders?: boolean;
18
29
  /**
19
30
  * Optional overrides for geo-location.
20
31
  */
@@ -1,18 +1,9 @@
1
- import type { ProviderTransportFactory } from '@c15t/core';
2
- import type { PolicyRule } from '@c15t/schema/types';
3
- /** Policy rules evaluated locally when initialization runs. */
4
- export interface OfflineModeOptions {
5
- /**
6
- * Rules to resolve locally. Omit them to use `recommendedPolicyRules()`:
7
- * strict opt-in for Europe, the UK, Quebec and unknown locations, opt-out
8
- * for the US states with a privacy law, and `none` everywhere else.
9
- * Passing rules replaces that pack entirely.
10
- */
11
- policyRules?: PolicyRule[];
12
- }
13
1
  /**
14
- * Resolve local rules outside render and hydration.
15
- * @param options - Explicit policy rules; absence resolves the recommended pack.
16
- * @returns A provider transport with no network requests.
2
+ * Offline mode for the React provider: core's `offline()`, which resolves
3
+ * policy rules locally and switches copy when `overrides.language` or
4
+ * `useSetLanguage()` names a language the bundle or `i18n.messages` has.
5
+ * The language a server prefetch detected from `Accept-Language` keeps the
6
+ * startup copy.
17
7
  */
18
- export declare const offline: (options?: OfflineModeOptions) => ProviderTransportFactory;
8
+ export { offline } from '@c15t/core';
9
+ export type { OfflineModeOptions } from '@c15t/core';
@@ -1,9 +1,15 @@
1
- import type { LegalLinks, ConsentPresentation } from '@c15t/core';
1
+ import type { ConsentExperiment, ConsentPresentation, LegalLinks } from '@c15t/core';
2
2
  import type { DialogPreload } from './chunk-warming.js';
3
3
  import type { ReactComponentSlots } from './types/slots.js';
4
+ import type { Theme } from './types/theme/index.js';
4
5
  export interface V3UIConfigValue {
5
6
  components?: ReactComponentSlots;
7
+ /** The host's base presentation, before any experiment arm is applied. */
6
8
  presentation?: ConsentPresentation;
9
+ /** The configured experiment; the assigned arm lives on the snapshot. */
10
+ experiment?: ConsentExperiment;
11
+ /** The host's base theme, before any experiment arm is applied. */
12
+ theme?: Theme;
7
13
  legalLinks?: LegalLinks;
8
14
  preloadDialog?: DialogPreload;
9
15
  }