@c15t/react 3.0.0-alpha.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/AGENTS.md +10 -12
  2. package/README.md +41 -70
  3. package/SKILL.md +1 -1
  4. package/dist/aggregate-components.js +1 -1
  5. package/dist/components/consent-gate/atoms.js +1 -1
  6. package/dist/components/consent-gate/frame.js +2 -0
  7. package/dist/components/consent-gate/index.js +1 -1
  8. package/dist/components/iab-panel/atoms/root.js +1 -1
  9. package/dist/components/iab-panel/iab-panel.js +1 -1
  10. package/dist/components/iab-prompt/atoms/root.js +1 -1
  11. package/dist/components/iab-prompt/iab-prompt.js +1 -1
  12. package/dist/components/panel/atoms/root.js +1 -1
  13. package/dist/components/panel-trigger/atoms/root.js +1 -1
  14. package/dist/components/panel-trigger/panel-trigger.js +1 -1
  15. package/dist/components/panel-trigger/toolbar-loader.js +2 -0
  16. package/dist/components/preferences/atoms/root.js +1 -1
  17. package/dist/components/prompt/atoms/early-tap-script.js +2 -0
  18. package/dist/components/prompt/atoms/root.js +1 -1
  19. package/dist/components/prompt/prompt.js +1 -1
  20. package/dist/components/shared/dialog-sheets.js +1 -0
  21. package/dist/components/shared/first-paint-sheets.js +1 -0
  22. package/dist/components/shared/iab-dialog-sheets.js +1 -0
  23. package/dist/components/shared/iab-first-paint-sheets.js +1 -0
  24. package/dist/components/shared/primitives/button.js +1 -1
  25. package/dist/components/shared/surface-styles.js +2 -0
  26. package/dist/consent-gate.js +1 -1
  27. package/dist/context/index.js +1 -1
  28. package/dist/devtools.js +1 -1
  29. package/dist/hooks/use-iab-policy-guard.js +1 -0
  30. package/dist/iab/styles.tw3.css +2 -2
  31. package/dist/iab-context.js +1 -1
  32. package/dist/iab-dialog-deferred.js +2 -0
  33. package/dist/iab.js +1 -1
  34. package/dist/index-parts/consent-gate.js +1 -1
  35. package/dist/index-parts/core.js +1 -1
  36. package/dist/index-parts/frame.js +1 -0
  37. package/dist/index-parts/hosted.js +1 -0
  38. package/dist/index-parts/offline.js +1 -0
  39. package/dist/index-parts/presets.js +1 -0
  40. package/dist/index.js +1 -1
  41. package/dist/modes.js +1 -0
  42. package/dist/panel-link.js +1 -1
  43. package/dist/panel-trigger.js +1 -1
  44. package/dist/provider.js +1 -1
  45. package/dist/styles.tw3.css +2 -2
  46. package/dist/transports/hosted.js +1 -0
  47. package/dist/transports/manifest.js +1 -0
  48. package/dist/utils/deferred-module.js +1 -1
  49. package/dist/version.js +1 -1
  50. package/dist-types/chunk-warming.d.ts +7 -6
  51. package/dist-types/components/consent-gate/frame.d.ts +19 -0
  52. package/dist-types/components/consent-gate/index.d.ts +3 -19
  53. package/dist-types/components/iab-prompt/iab-prompt.d.ts +1 -1
  54. package/dist-types/components/panel/index.d.ts +1 -1
  55. package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
  56. package/dist-types/components/preferences/index.d.ts +1 -1
  57. package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
  58. package/dist-types/components/prompt/index.d.ts +1 -1
  59. package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
  60. package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
  61. package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
  62. package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
  63. package/dist-types/components/shared/surface-styles.d.ts +60 -0
  64. package/dist-types/consent-gate.d.ts +1 -1
  65. package/dist-types/context/index.d.ts +3 -3
  66. package/dist-types/context.d.ts +2 -0
  67. package/dist-types/gpp.d.ts +1 -1
  68. package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
  69. package/dist-types/iab-dialog-deferred.d.ts +36 -0
  70. package/dist-types/iab.d.ts +3 -2
  71. package/dist-types/index-parts/consent-gate.d.ts +1 -1
  72. package/dist-types/index-parts/core.d.ts +1 -2
  73. package/dist-types/index-parts/frame.d.ts +7 -0
  74. package/dist-types/index-parts/hosted.d.ts +7 -0
  75. package/dist-types/index-parts/offline.d.ts +7 -0
  76. package/dist-types/index-parts/presets.d.ts +7 -0
  77. package/dist-types/index.d.ts +5 -1
  78. package/dist-types/modes.d.ts +26 -0
  79. package/dist-types/panel-link.d.ts +1 -1
  80. package/dist-types/panel-trigger.d.ts +1 -1
  81. package/dist-types/provider.d.ts +22 -4
  82. package/dist-types/transports/hosted.d.ts +36 -0
  83. package/dist-types/transports/manifest.d.ts +48 -0
  84. package/dist-types/ui-config-context.d.ts +4 -0
  85. package/dist-types/version.d.ts +1 -1
  86. package/docs/README.md +10 -12
  87. package/docs/concepts/choose-your-setup.md +45 -8
  88. package/docs/concepts/consent-categories.md +1 -1
  89. package/docs/concepts/consent-state.md +5 -2
  90. package/docs/concepts/data-fetching.md +100 -40
  91. package/docs/concepts/modes.md +281 -0
  92. package/docs/customization/dark-mode.md +1 -1
  93. package/docs/customization/motion.md +2 -2
  94. package/docs/customization/overview.md +3 -2
  95. package/docs/customization/recipes.md +4 -4
  96. package/docs/customization/slots.md +25 -25
  97. package/docs/customization/stylesheets.md +161 -50
  98. package/docs/customization/tailwind.md +71 -50
  99. package/docs/customization/tokens.md +42 -13
  100. package/docs/frameworks/react/components/consent-banner.md +14 -12
  101. package/docs/frameworks/react/components/consent-dialog.md +15 -13
  102. package/docs/frameworks/react/components/consent-provider.md +51 -46
  103. package/docs/frameworks/react/components.md +16 -13
  104. package/docs/frameworks/react/compose.md +3 -3
  105. package/docs/frameworks/react/content-security-policy.md +35 -12
  106. package/docs/frameworks/react/customize.md +21 -13
  107. package/docs/frameworks/react/hooks.md +2 -2
  108. package/docs/frameworks/react/iab.md +56 -6
  109. package/docs/frameworks/react/quickstart.md +65 -99
  110. package/docs/frameworks/react/rendering.md +170 -94
  111. package/docs/frameworks/react/scripts.md +19 -30
  112. package/docs/frameworks/react/troubleshooting.md +100 -32
  113. package/docs/frameworks/react/upgrade-v3.md +133 -79
  114. package/docs/frameworks/react/vendor-consent.md +19 -7
  115. package/docs/guides/banner-experiments.md +21 -8
  116. package/docs/guides/troubleshooting.md +90 -26
  117. package/docs/guides/verify-consent.md +23 -8
  118. package/docs/integrations/adobe-analytics.md +60 -64
  119. package/docs/integrations/ahrefs-analytics.md +58 -63
  120. package/docs/integrations/amplitude.md +60 -64
  121. package/docs/integrations/clearbit.md +59 -63
  122. package/docs/integrations/cloudflare-web-analytics.md +56 -60
  123. package/docs/integrations/cloudflare-zaraz.md +55 -57
  124. package/docs/integrations/crisp.md +64 -69
  125. package/docs/integrations/databuddy.md +62 -64
  126. package/docs/integrations/fathom-analytics.md +56 -60
  127. package/docs/integrations/front-chat.md +56 -60
  128. package/docs/integrations/google-maps.md +25 -13
  129. package/docs/integrations/google-tag-manager.md +153 -77
  130. package/docs/integrations/google-tag.md +134 -78
  131. package/docs/integrations/heap.md +56 -60
  132. package/docs/integrations/hightouch.md +55 -60
  133. package/docs/integrations/hotjar.md +60 -64
  134. package/docs/integrations/intercom.md +55 -60
  135. package/docs/integrations/klaviyo.md +65 -66
  136. package/docs/integrations/linkedin-insights.md +58 -63
  137. package/docs/integrations/logrocket.md +55 -60
  138. package/docs/integrations/matomo-analytics.md +58 -60
  139. package/docs/integrations/meta-pixel.md +56 -60
  140. package/docs/integrations/microsoft-clarity.md +57 -60
  141. package/docs/integrations/microsoft-uet.md +58 -61
  142. package/docs/integrations/mixpanel-analytics.md +73 -75
  143. package/docs/integrations/one-dollar-stats.md +53 -59
  144. package/docs/integrations/openai-pixel.md +58 -60
  145. package/docs/integrations/overview.md +59 -42
  146. package/docs/integrations/pinterest-tag.md +56 -60
  147. package/docs/integrations/pirsch.md +54 -60
  148. package/docs/integrations/plausible-analytics.md +55 -60
  149. package/docs/integrations/posthog.md +56 -60
  150. package/docs/integrations/promptwatch.md +57 -63
  151. package/docs/integrations/reddit-pixel.md +57 -60
  152. package/docs/integrations/rudderstack.md +65 -67
  153. package/docs/integrations/rybbit-analytics.md +70 -75
  154. package/docs/integrations/segment.md +56 -60
  155. package/docs/integrations/sentry.md +65 -60
  156. package/docs/integrations/snapchat-pixel.md +54 -60
  157. package/docs/integrations/tiktok-pixel.md +59 -63
  158. package/docs/integrations/umami-analytics.md +54 -60
  159. package/docs/integrations/vercel-analytics.md +53 -59
  160. package/docs/integrations/vercel-speed-insights.md +317 -0
  161. package/docs/integrations/x-pixel.md +57 -63
  162. package/docs/integrations/youtube.md +25 -13
  163. package/package.json +18 -8
  164. package/docs/upgrade-v3.md +0 -429
@@ -0,0 +1,19 @@
1
+ import * as atoms from './atoms.js';
2
+ import type { ConsentGateCompoundComponent, ConsentGateProps } from './types.js';
3
+ /** @deprecated Renamed to `ConsentGateRoot`. */
4
+ declare const FrameRoot: typeof atoms.ConsentGateRoot;
5
+ /** @deprecated Renamed to `ConsentGateTitle`. */
6
+ declare const FrameTitle: typeof atoms.ConsentGateTitle;
7
+ /** @deprecated Renamed to `ConsentGateButton`. */
8
+ declare const FrameButton: typeof atoms.ConsentGateButton;
9
+ /**
10
+ * @deprecated Renamed to `ConsentGate`. `Frame` will be removed in a
11
+ * future major release.
12
+ */
13
+ declare const Frame: ConsentGateCompoundComponent;
14
+ /** @deprecated Renamed to `ConsentGateProps`. */
15
+ type FrameProps = ConsentGateProps;
16
+ /** @deprecated Renamed to `ConsentGateCompoundComponent`. */
17
+ type FrameCompoundComponent = ConsentGateCompoundComponent;
18
+ export type { FrameCompoundComponent, FrameProps };
19
+ export { Frame, FrameButton, FrameRoot, FrameTitle };
@@ -1,5 +1,4 @@
1
- import * as atoms from './atoms.js';
2
- import type { ConsentGateCompoundComponent, ConsentGateProps } from './types.js';
1
+ import type { ConsentGateCompoundComponent } from './types.js';
3
2
  /**
4
3
  * Renders its children only while a consent category is allowed
5
4
  *
@@ -19,23 +18,8 @@ import type { ConsentGateCompoundComponent, ConsentGateProps } from './types.js'
19
18
  * @see {@link AllConsentNames} for consent categories
20
19
  */
21
20
  declare const ConsentGate: ConsentGateCompoundComponent;
22
- /**
23
- * @deprecated Renamed to {@link ConsentGate}. `Frame` will be removed in a
24
- * future major release.
25
- */
26
- declare const Frame: ConsentGateCompoundComponent;
27
- /** @deprecated Renamed to {@link ConsentGateProps}. */
28
- type FrameProps = ConsentGateProps;
29
- /** @deprecated Renamed to {@link ConsentGateCompoundComponent}. */
30
- type FrameCompoundComponent = ConsentGateCompoundComponent;
31
- /** @deprecated Renamed to `ConsentGateRoot`. */
32
- declare const FrameRoot: typeof atoms.ConsentGateRoot;
33
- /** @deprecated Renamed to `ConsentGateTitle`. */
34
- declare const FrameTitle: typeof atoms.ConsentGateTitle;
35
- /** @deprecated Renamed to `ConsentGateButton`. */
36
- declare const FrameButton: typeof atoms.ConsentGateButton;
37
21
  export { ConsentGateButton, ConsentGateRoot, ConsentGateTitle } from './atoms.js';
38
22
  export type { ConsentGateCompoundComponent, ConsentGateProps } from './types.js';
39
23
  export { ConsentGate };
40
- export type { FrameCompoundComponent, FrameProps };
41
- export { Frame, FrameButton, FrameRoot, FrameTitle };
24
+ export type { FrameCompoundComponent, FrameProps } from './frame.js';
25
+ export { Frame, FrameButton, FrameRoot, FrameTitle } from './frame.js';
@@ -57,7 +57,7 @@ export interface IABConsentBannerProps {
57
57
  * ```tsx
58
58
  * <ConsentProvider
59
59
  * options={{
60
- * mode: hosted({ url: '/api/c15t' }),
60
+ * mode: hosted({ backendURL: '/api/c15t' }),
61
61
  * iab: { cmpId: 123, vendors: [1, 2, 10] },
62
62
  * }}
63
63
  * >
@@ -57,7 +57,7 @@ export interface ConsentDialogCompoundComponent extends FC<ConsentDialogProps> {
57
57
  * ```tsx
58
58
  * <ConsentProvider
59
59
  * options={{
60
- * mode: hosted({ url: '/api/c15t' }),
60
+ * mode: hosted({ backendURL: '/api/c15t' }),
61
61
  * components: {
62
62
  * dialog: {
63
63
  * card: { className: 'rounded-3xl shadow-xl' },
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Loads the trigger toolbar on demand. The single-button trigger becomes a
3
+ * toolbar only while `<ConsentDevTools>` is mounted, so apps without
4
+ * DevTools never download it. The DevTools entry registers the toolbar when
5
+ * it loads, so the swap to a toolbar never waits on a request.
6
+ *
7
+ * @internal
8
+ * @packageDocumentation
9
+ */
10
+ import type { TriggerToolbar } from './atoms/toolbar.js';
11
+ /** The toolbar view the trigger renders while DevTools is mounted. */
12
+ export type TriggerToolbarComponent = typeof TriggerToolbar;
13
+ /**
14
+ * Make the toolbar available synchronously.
15
+ *
16
+ * @param component - The toolbar view.
17
+ * @internal
18
+ */
19
+ export declare const registerTriggerToolbar: (component: TriggerToolbarComponent) => void;
20
+ /**
21
+ * The toolbar view when it has loaded or been registered.
22
+ *
23
+ * @returns The toolbar view, or `undefined` while it is not loaded.
24
+ * @internal
25
+ */
26
+ export declare const getTriggerToolbar: () => TriggerToolbarComponent | undefined;
27
+ /**
28
+ * Load the toolbar view. A failed load is not cached, so a later call
29
+ * retries.
30
+ *
31
+ * @returns The toolbar view.
32
+ * @internal
33
+ */
34
+ export declare const loadTriggerToolbar: () => Promise<TriggerToolbarComponent>;
@@ -67,7 +67,7 @@ export interface ConsentWidgetCompoundComponent extends FC<ConsentWidgetProps> {
67
67
  * ```tsx
68
68
  * <ConsentProvider
69
69
  * options={{
70
- * mode: hosted({ url: '/api/c15t' }),
70
+ * mode: hosted({ backendURL: '/api/c15t' }),
71
71
  * components: {
72
72
  * accordion: {
73
73
  * root: { className: 'rounded-3xl border border-black/10' },
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Keeps a banner tap made before hydration.
3
+ *
4
+ * A server-rendered banner shows long before React attaches its handlers.
5
+ * The inline script records an accept, reject, dismiss or customize tap in
6
+ * that gap and hides the banner. Once this component mounts, the banner's
7
+ * own handlers work: it stops the script and records the tap when the
8
+ * runtime has started. See `@c15t/core/surface-actions`.
9
+ *
10
+ * The script is in the server HTML. A banner that hydrates keeps it, inert
11
+ * once claimed, so hydration changes nothing in the markup. A banner React
12
+ * renders in the browser has its handlers at once, and a script it inserts
13
+ * would never run, so there it renders nothing.
14
+ *
15
+ * @internal
16
+ */
17
+ export declare const EarlyTapScript: () => import("react").JSX.Element | null;
@@ -62,7 +62,7 @@ export interface ConsentBannerCompoundComponent extends FC<ConsentBannerProps> {
62
62
  * ```tsx
63
63
  * <ConsentProvider
64
64
  * options={{
65
- * mode: hosted({ url: '/api/c15t' }),
65
+ * mode: hosted({ backendURL: '/api/c15t' }),
66
66
  * i18n: {
67
67
  * locale: 'en',
68
68
  * messages: {
@@ -0,0 +1,9 @@
1
+ import type { SurfaceStyleSheet } from './surface-styles.js';
2
+ /**
3
+ * What the dialog and the preference widget render: the first-paint sheet,
4
+ * then the dialog and widget rules. Only their lazy chunks import this, so
5
+ * the dialog rules load with the dialog's code.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare const DIALOG_SHEETS: readonly SurfaceStyleSheet[];
@@ -0,0 +1,8 @@
1
+ import type { SurfaceStyleSheet } from './surface-styles.js';
2
+ /**
3
+ * What the banner, trigger and ConsentGate render: tokens, every c15t
4
+ * variable and the first-paint rules of `styles.css`.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare const FIRST_PAINT_SHEETS: readonly SurfaceStyleSheet[];
@@ -0,0 +1,3 @@
1
+ import type { SurfaceStyleSheet } from './surface-styles.js';
2
+ /** Styles for a standalone IAB dialog, loaded with its code. @internal */
3
+ export declare const IAB_DIALOG_SHEETS: readonly SurfaceStyleSheet[];
@@ -0,0 +1,3 @@
1
+ import type { SurfaceStyleSheet } from './surface-styles.js';
2
+ /** The shared tokens and IAB banner rules. @internal */
3
+ export declare const IAB_FIRST_PAINT_SHEETS: readonly SurfaceStyleSheet[];
@@ -0,0 +1,60 @@
1
+ /** A stylesheet from `@c15t/ui/styles/sheets/*`. */
2
+ export interface SurfaceStyleSheet {
3
+ /** Dedupes the stylesheet: a page renders each `id` once. */
4
+ id: string;
5
+ /** The stylesheet text. Empty for a deferred sheet. */
6
+ css: string;
7
+ /**
8
+ * Loads the text of a deferred sheet. A browser bundle gets one in place
9
+ * of `css` when the framework already put the sheet in the server HTML,
10
+ * as the Next.js adapter does, so the text ships once.
11
+ */
12
+ load?: () => Promise<string>;
13
+ }
14
+ /**
15
+ * Starts loading the deferred sheets the page does not hold yet. Safe to
16
+ * call often: each sheet loads once, and the next call retries a failed
17
+ * load.
18
+ *
19
+ * @internal
20
+ */
21
+ export declare const preloadSurfaceSheets: (sheets: readonly SurfaceStyleSheet[]) => Promise<void>;
22
+ /**
23
+ * Whether a surface can show: its deferred sheets are in the page or
24
+ * loaded. Starts loading the missing ones after mount, so a surface that
25
+ * renders later, like a banner waiting on the browser's consent fetch,
26
+ * finds them ready. Hydration reads `true`: the server rendered the sheets
27
+ * it rendered the surface with.
28
+ *
29
+ * @internal
30
+ */
31
+ export declare const useSurfaceSheetsReady: (sheets: readonly SurfaceStyleSheet[], noStyle?: boolean) => boolean;
32
+ /**
33
+ * Renders the stylesheets a stock surface needs as `<style>` elements.
34
+ *
35
+ * The banner, trigger, ConsentGate, dialog and widget each render the
36
+ * sheets they use, so an app that imports no c15t stylesheet still gets
37
+ * styled surfaces, and no stylesheet `<link>` holds back the first paint.
38
+ * A server-rendered surface puts its rules in the HTML. A surface that
39
+ * renders in the browser, like the dialog, inserts them with its own code.
40
+ *
41
+ * In React 19 the elements move to `<head>` and each `id` renders once per
42
+ * page; later sheets follow earlier ones, which keeps the cascade order of
43
+ * `styles.css`. React 18 renders them in place, next to the surface, and
44
+ * so does React 19 when the provider sets a `nonce`: React drops the nonce
45
+ * from a style it moves to `<head>` unless the app passed the same nonce to
46
+ * React's server renderer, and a style without it would break a
47
+ * nonce-based policy.
48
+ *
49
+ * Renders nothing when the provider sets `styles: false` (the app imports
50
+ * `styles.css` itself) or `noStyle`.
51
+ *
52
+ * @param props.sheets - The stylesheets, in cascade order.
53
+ * @param props.noStyle - The surface's own `noStyle` prop.
54
+ * @returns The `<style>` elements, or `null`.
55
+ * @internal
56
+ */
57
+ export declare const SurfaceStyles: ({ sheets, noStyle, }: {
58
+ sheets: readonly SurfaceStyleSheet[];
59
+ noStyle?: boolean;
60
+ }) => (import("react").JSX.Element | null)[] | null;
@@ -1 +1 @@
1
- export * from './components/consent-gate/index.js';
1
+ export { ConsentGate, ConsentGateButton, type ConsentGateCompoundComponent, type ConsentGateProps, ConsentGateRoot, ConsentGateTitle, Frame, FrameButton, type FrameCompoundComponent, type FrameProps, FrameRoot, FrameTitle, } from './components/consent-gate/index.js';
@@ -1,3 +1,3 @@
1
- export * from '../context.js';
2
- export * from './consent-tracking-context.js';
3
- export * from './theme-context.js';
1
+ export { HydrationSnapshotContext, KernelContext, type ProviderServices, ProviderServicesContext, StreamedPrefetchContext, } from '../context.js';
2
+ export { ConsentTrackingContext, type ConsentTrackingValue, toSaveUISource, useConsentTracking, } from './consent-tracking-context.js';
3
+ export { GlobalThemeContext, LocalThemeContext, type ThemeContextValue, } from './theme-context.js';
@@ -14,6 +14,8 @@ export interface ProviderServices {
14
14
  clearRecords: () => void;
15
15
  getPresentation: () => ConsentPresentation | undefined;
16
16
  getConsentCategories: () => readonly AllConsentNames[];
17
+ /** Whether the runtime has started: records hydrated, prefetch adopted. */
18
+ isStarted: () => boolean;
17
19
  /**
18
20
  * Store a language override and load its copy: init runs again on the
19
21
  * provider's own kernel while it is enabled, and a borrowed runtime
@@ -18,7 +18,7 @@ export type ConsentGPPProps = RuntimeGPPOptions;
18
18
  * ```tsx
19
19
  * import { ConsentGPP } from '@c15t/react/gpp';
20
20
  *
21
- * <ConsentProvider options={{ mode: hosted({ url }) }}>
21
+ * <ConsentProvider options={{ mode: hosted({ backendURL }) }}>
22
22
  * <ConsentGPP usFallback="none" />
23
23
  * <App />
24
24
  * </ConsentProvider>
@@ -0,0 +1,35 @@
1
+ import { IABUnavailableError } from '@c15t/core';
2
+ /**
3
+ * Record that `IABProvider` is part of the app. `@c15t/react/iab` calls
4
+ * this when it loads.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare const markIABProviderLoaded: () => void;
9
+ /**
10
+ * The error the standard surfaces throw for an `iab` policy without
11
+ * `<IABProvider>`.
12
+ *
13
+ * @returns A fresh {@link IABUnavailableError}.
14
+ * @internal
15
+ */
16
+ export declare const missingIABProviderError: () => IABUnavailableError;
17
+ /**
18
+ * Throw while rendering when the visitor's policy needs a CMP and the app
19
+ * has none.
20
+ *
21
+ * The standard banner and dialog do not answer for the IAB model, so
22
+ * without `<IABProvider>` a visitor under an `iab` policy would see no
23
+ * consent UI at all. Throwing during render reaches error boundaries and
24
+ * framework error overlays, on the server render and in the browser alike,
25
+ * since both read the same snapshot.
26
+ *
27
+ * `<IABProvider>` usually sits beside the standard surfaces rather than
28
+ * around them, so a missing IAB context alone does not prove the app has
29
+ * none. The check also passes once `@c15t/react/iab` has loaded.
30
+ *
31
+ * @throws {IABUnavailableError} When the policy needs IAB and neither an
32
+ * IAB context nor `@c15t/react/iab` is present.
33
+ * @internal
34
+ */
35
+ export declare const useIABPolicyGuard: () => void;
@@ -0,0 +1,36 @@
1
+ import type { IABConsentDialogCompoundComponent } from './components/iab-panel/index.js';
2
+ /**
3
+ * The IAB TCF preference centre: purposes, stacks, special features and
4
+ * per-vendor consent and legitimate-interest controls.
5
+ *
6
+ * @remarks
7
+ * The component code loads on demand. It downloads in the browser's first
8
+ * idle period after the page's `load` event while the IAB banner is shown,
9
+ * on hover or focus of the banner's Customize button or partners link, or
10
+ * when the dialog opens, whichever comes first. `preloadDialog: 'intent'` in
11
+ * the provider options skips the idle load. `open={true}` or `showTrigger`
12
+ * loads it on mount under a model `models` lists; under another model,
13
+ * `showTrigger` loads only the trigger.
14
+ *
15
+ * The compound parts (`IABConsentDialog.Root`, `.Card`, `.Header`, `.Tabs`,
16
+ * `.TabButton`, `.Content`, `.Footer`, `.Overlay`, `.FeatureItem`,
17
+ * `.PurposeItem`, `.StackItem`, `.VendorList`) load the same module when
18
+ * they render.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * <IABProvider cmpId={28}>
23
+ * <IABConsentBanner />
24
+ * <IABConsentDialog />
25
+ * </IABProvider>
26
+ * ```
27
+ *
28
+ * @public
29
+ */
30
+ export declare const IABConsentDialog: IABConsentDialogCompoundComponent;
31
+ /**
32
+ * Reset the warming state shared by mounted dialogs between tests.
33
+ *
34
+ * @internal
35
+ */
36
+ export declare const resetIABDialogWarmingForTests: () => void;
@@ -12,7 +12,7 @@
12
12
  * import { IABProvider, IABConsentBanner, IABConsentDialog } from '@c15t/react/iab';
13
13
  *
14
14
  * <ConsentProvider
15
- * options={{ mode: hosted({ url: '/api/c15t' }) }}
15
+ * options={{ mode: hosted({ backendURL: '/api/c15t' }) }}
16
16
  * >
17
17
  * <IABProvider cmpId={28}>
18
18
  * <IABConsentBanner />
@@ -24,7 +24,8 @@
24
24
  * @packageDocumentation
25
25
  */
26
26
  export { IABConsentBanner, type IABConsentBannerProps, } from './components/iab-prompt/index.js';
27
- export { IABConsentDialog, type IABConsentDialogProps, } from './components/iab-panel/index.js';
27
+ export type { IABConsentDialogProps } from './components/iab-panel/index.js';
28
+ export { IABConsentDialog } from './iab-dialog-deferred.js';
28
29
  export { type HeadlessIABBannerAction, type HeadlessIABBannerState, type HeadlessIABDialogAction, type HeadlessIABDialogState, type HeadlessIABPreferenceTab, type UseHeadlessIABConsentUIResult, useHeadlessIABConsentUI, } from './hooks/use-headless-iab-consent-ui.js';
29
30
  export { IABProvider } from './iab-context.js';
30
31
  export type { IABProviderProps } from './iab-context.js';
@@ -4,4 +4,4 @@
4
4
  * (esbuild) does not treat every module the index names as part of an app
5
5
  * that imports one hook: only the groups it uses are live.
6
6
  */
7
- export { ConsentGate, Frame } from '../components/consent-gate/index.js';
7
+ export { ConsentGate } from '../components/consent-gate/index.js';
@@ -4,5 +4,4 @@
4
4
  * (esbuild) does not treat every module the index names as part of an app
5
5
  * that imports one hook: only the groups it uses are live.
6
6
  */
7
- export { createConsentKernel, custom, hosted, policyRulePresets, } from '@c15t/core';
8
- export { offline } from '../transports/offline.js';
7
+ export { createConsentKernel, custom } from '@c15t/core';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * One group of `@c15t/react`'s public exports. The package index re-exports
3
+ * each group with `export *`, so a bundler that splits code by reachability
4
+ * (esbuild) does not treat every module the index names as part of an app
5
+ * that imports one hook: only the groups it uses are live.
6
+ */
7
+ export { Frame } from '../components/consent-gate/frame.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * One group of `@c15t/react`'s public exports. The package index re-exports
3
+ * each group with `export *`, so a bundler that splits code by reachability
4
+ * (esbuild) does not treat every module the index names as part of an app
5
+ * that imports one hook: only the groups it uses are live.
6
+ */
7
+ export { hosted } from '@c15t/core';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * One group of `@c15t/react`'s public exports. The package index re-exports
3
+ * each group with `export *`, so a bundler that splits code by reachability
4
+ * (esbuild) does not treat every module the index names as part of an app
5
+ * that imports one hook: only the groups it uses are live.
6
+ */
7
+ export { offline } from '../transports/offline.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * One group of `@c15t/react`'s public exports. The package index re-exports
3
+ * each group with `export *`, so a bundler that splits code by reachability
4
+ * (esbuild) does not treat every module the index names as part of an app
5
+ * that imports one hook: only the groups it uses are live.
6
+ */
7
+ export { policyRulePresets } from '@c15t/core';
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * function App({ children }) {
13
13
  * return (
14
- * <ConsentProvider options={{ mode: hosted({ url: '/api/c15t' }) }}>
14
+ * <ConsentProvider options={{ mode: hosted({ backendURL: '/api/c15t' }) }}>
15
15
  * {children}
16
16
  * </ConsentProvider>
17
17
  * );
@@ -48,11 +48,15 @@ export type { ConsentBannerCompoundComponent } from './components/prompt/index.j
48
48
  export type { ReactUIOptions } from './types/manager.js';
49
49
  export type { ConsentPresentation, PromptPresentation, PreferencesPresentation, PresentationAction, PromptPosition, PromptVariant, ResolvedConsentPresentation, } from '@c15t/core';
50
50
  export * from './index-parts/core.js';
51
+ export * from './index-parts/hosted.js';
52
+ export * from './index-parts/offline.js';
53
+ export * from './index-parts/presets.js';
51
54
  export * from './index-parts/consent-dialog.js';
52
55
  export * from './index-parts/consent-banner.js';
53
56
  export * from './index-parts/consent-dialog-link.js';
54
57
  export * from './index-parts/consent-dialog-trigger.js';
55
58
  export * from './index-parts/consent-gate.js';
59
+ export * from './index-parts/frame.js';
56
60
  export * from './index-parts/draft.js';
57
61
  export * from './index-parts/translations.js';
58
62
  export * from './index-parts/module-hooks.js';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `@c15t/react/modes` — the single-page app modes, defaulting to what the
3
+ * build integration downloaded.
4
+ *
5
+ * `manifest()` and `hosted()` here read `@c15t/core/generated`, which
6
+ * `consentManifest()` from `c15t/build` fills with the policy snapshot and
7
+ * the backend URL. `c15t/react` exports these in place of the plain
8
+ * `hosted()` from `@c15t/react`.
9
+ *
10
+ * The package index does not import this module. Server-framework packages
11
+ * re-export the index, and their browser bundles must not import
12
+ * `@c15t/core/generated`: Next.js fails the build when they do.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * import { ConsentProvider, manifest } from 'c15t/react';
17
+ *
18
+ * <ConsentProvider options={{ mode: manifest() }}>{children}</ConsentProvider>;
19
+ * ```
20
+ */
21
+ export { hosted } from './transports/hosted.js';
22
+ export type { HostedOptions } from './transports/hosted.js';
23
+ export { manifest } from './transports/manifest.js';
24
+ export type { BrowserManifestModeFactory, ManifestModeOptions, } from './transports/manifest.js';
25
+ export { offline } from './transports/offline.js';
26
+ export type { OfflineModeOptions } from './transports/offline.js';
@@ -1 +1 @@
1
- export * from './components/panel-link/index.js';
1
+ export { ConsentDialogLink, type ConsentDialogLinkProps, } from './components/panel-link/index.js';
@@ -1 +1 @@
1
- export * from './components/panel-trigger/index.js';
1
+ export { ConsentDialogTrigger, type ConsentDialogTriggerCompound, type ConsentDialogTriggerProps, ConsentDialogTriggerToolbar, type ConsentDialogTriggerToolbarAction, type ConsentDialogTriggerToolbarPreferences, type ConsentDialogTriggerToolbarProps, type CornerPosition, TriggerButton, type TriggerButtonProps, TriggerIcon, type TriggerIconProps, type TriggerIconType, type TriggerOrientation, TriggerRoot, type TriggerRootProps, type TriggerSize, TriggerText, type TriggerTextProps, type TriggerVisibility, type UseDraggableOptions, type UseDraggableReturn, useDraggable, useTriggerContext, } from './components/panel-trigger/index.js';
@@ -40,11 +40,29 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
40
40
  * @remarks
41
41
  * Set this when your CSP uses a nonce-based policy instead of
42
42
  * `'unsafe-inline'`. The provider forwards it to every `<script>`
43
- * element created by the script loader. A per-script `nonce` still takes
43
+ * element created by the script loader, and to the `<style>` elements
44
+ * the stock surfaces render. A per-script `nonce` still takes
44
45
  * precedence. Pass the same nonce to `ConsentTheme`, which renders the
45
46
  * theme `<style>` element.
46
47
  */
47
48
  nonce?: string;
49
+ /**
50
+ * Whether the stock surfaces render their own stylesheets.
51
+ *
52
+ * @remarks
53
+ * The banner, dialog trigger, ConsentGate, dialog and preference widget
54
+ * each render the c15t rules they use as a `<style>` element: in the
55
+ * server-rendered HTML, or with the surface's own code in the browser.
56
+ * No c15t stylesheet `<link>` then holds back the page's first paint.
57
+ * React 19 moves them into `<head>` and renders each once. They carry
58
+ * {@link ConsentProviderOptions.nonce}.
59
+ *
60
+ * Set `false` when the app imports `styles.css` itself, for example to
61
+ * run it through Tailwind CSS 3 or to put it in a named cascade layer.
62
+ *
63
+ * @default true
64
+ */
65
+ styles?: boolean;
48
66
  /**
49
67
  * Transport factory the provider builds its kernel with. Required.
50
68
  *
@@ -57,7 +75,7 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
57
75
  * ```tsx
58
76
  * import { ConsentProvider, hosted, offline } from '@c15t/react';
59
77
  *
60
- * <ConsentProvider options={{ mode: hosted({ url: '/api/c15t' }) }}>
78
+ * <ConsentProvider options={{ mode: hosted({ backendURL: '/api/c15t' }) }}>
61
79
  * {children}
62
80
  * </ConsentProvider>
63
81
  *
@@ -101,7 +119,7 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
101
119
  * // app/layout.tsx — stays synchronous, so the shell prerenders.
102
120
  * const config = resolveConsent({ backendURL });
103
121
  * return (
104
- * <ConsentProvider options={{ mode: hosted({ url }), prefetch: config }}>
122
+ * <ConsentProvider options={{ mode: hosted({ backendURL }), prefetch: config }}>
105
123
  * {children}
106
124
  * </ConsentProvider>
107
125
  * );
@@ -261,7 +279,7 @@ export type ConsentProviderProps = OwnedRuntimeProviderProps | ExternalRuntimePr
261
279
  * ```tsx
262
280
  * import { createConsentRuntime } from '@c15t/core/runtime';
263
281
  *
264
- * const runtime = createConsentRuntime({ mode: hosted({ url: '/api/c15t' }) });
282
+ * const runtime = createConsentRuntime({ mode: hosted({ backendURL: '/api/c15t' }) });
265
283
  * runtime.start();
266
284
  *
267
285
  * <ConsentProvider runtime={runtime} options={{ theme }}>
@@ -0,0 +1,36 @@
1
+ import type { HostedModeFactory, HostedModeOptions } from '@c15t/core';
2
+ /** Options for {@link hosted}. `backendURL` defaults to the build's. */
3
+ export type HostedOptions = Omit<HostedModeOptions, 'backendURL'> & {
4
+ /**
5
+ * Backend URL, relative (`/api/c15t`) or absolute. Defaults to the URL
6
+ * `consentManifest()` from `c15t/build` read from
7
+ * `VITE_C15T_BACKEND_URL` or `VITE_INTH_PROJECT_URL`.
8
+ */
9
+ backendURL?: string;
10
+ };
11
+ /**
12
+ * Build a hosted factory, taking the backend URL from the build when the
13
+ * options name none.
14
+ *
15
+ * @param options - The page's options.
16
+ * @param buildBackendURL - The backend URL the build read, if any.
17
+ * @returns A hosted transport factory.
18
+ * @throws {Error} When neither names a backend URL.
19
+ * @internal
20
+ */
21
+ export declare const hostedWithBuild: (options: HostedOptions, buildBackendURL: string | undefined) => HostedModeFactory;
22
+ /**
23
+ * Ask the backend's `/init` for every visitor's policy.
24
+ *
25
+ * @param options - Backend URL, init headers and request overrides.
26
+ * @returns A transport factory for the provider's `mode`, carrying its
27
+ * options.
28
+ * @throws {Error} When no backend URL is passed and the build set none.
29
+ * @example
30
+ * ```tsx
31
+ * import { ConsentProvider, hosted } from 'c15t/react';
32
+ *
33
+ * <ConsentProvider options={{ mode: hosted() }}>{children}</ConsentProvider>;
34
+ * ```
35
+ */
36
+ export declare const hosted: (options?: HostedOptions) => HostedModeFactory;
@@ -0,0 +1,48 @@
1
+ import type { BrowserManifestModeFactory, BrowserManifestOptions } from '@c15t/core/transports/manifest-browser';
2
+ /**
3
+ * Manifest mode for the React provider: core's browser resolver, with the
4
+ * policy and backend URL the build integration downloaded as defaults.
5
+ */
6
+ import type { ConsentManifest } from '@c15t/schema/types';
7
+ /** What a build integration downloaded, as `@c15t/core/generated` exports it. */
8
+ export interface BuildOutput {
9
+ backendURL?: string;
10
+ snapshot?: ConsentManifest;
11
+ }
12
+ /**
13
+ * Fill the options the page left out from the build: the backend URL that
14
+ * saves go to, and the snapshot unless the page passed one, a
15
+ * `manifestURL`, or `source: 'runtime'`.
16
+ *
17
+ * @param options - The page's options.
18
+ * @param build - What the build downloaded.
19
+ * @returns The options `manifest()` resolves with.
20
+ * @internal
21
+ */
22
+ export declare const withBuildDefaults: (options: BrowserManifestOptions, build: BuildOutput) => BrowserManifestOptions;
23
+ /**
24
+ * Resolve the policy in the browser from the backend's consent manifest.
25
+ *
26
+ * Without options it uses what `consentManifest()` from `c15t/build`
27
+ * downloaded: the snapshot and the backend URL from
28
+ * `VITE_C15T_BACKEND_URL` or `VITE_INTH_PROJECT_URL`, both served as
29
+ * `c15t/generated`. Without a
30
+ * snapshot, such as in dev after a failed fetch, it fetches
31
+ * `${backendURL}/manifest` at runtime. Saves go to the backend either way.
32
+ * With `manifestURL` or `source: 'runtime'`, also pass `source: 'runtime'`
33
+ * to `consentManifest()`, so the build downloads no snapshot.
34
+ *
35
+ * @param options - Overrides: your own `snapshot`, `source: 'runtime'`, a
36
+ * `manifestURL`, a `backendURL`, or the visitor's location as `inputs`.
37
+ * @returns A transport factory for the provider's `mode`, carrying its
38
+ * options.
39
+ * @throws {Error} When no snapshot, manifest URL or backend URL is known.
40
+ * @example
41
+ * ```tsx
42
+ * import { ConsentProvider, manifest } from 'c15t/react';
43
+ *
44
+ * <ConsentProvider options={{ mode: manifest() }}>{children}</ConsentProvider>;
45
+ * ```
46
+ */
47
+ export declare const manifest: (options?: BrowserManifestOptions) => BrowserManifestModeFactory;
48
+ export type { BrowserManifestModeFactory, BrowserManifestOptions as ManifestModeOptions, } from '@c15t/core/transports/manifest-browser';
@@ -12,6 +12,10 @@ export interface V3UIConfigValue {
12
12
  theme?: Theme;
13
13
  legalLinks?: LegalLinks;
14
14
  preloadDialog?: DialogPreload;
15
+ /** CSP nonce for the `<style>` elements the surfaces render. */
16
+ nonce?: string;
17
+ /** `false` when the app loads `styles.css` itself. */
18
+ styles?: boolean;
15
19
  }
16
20
  export declare const V3UIConfigContext: import("react").Context<V3UIConfigValue>;
17
21
  export declare const useUIConfig: () => V3UIConfigValue;
@@ -1 +1 @@
1
- export declare const version = "3.0.0-alpha.8";
1
+ export declare const version = "3.0.0";