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

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 (111) hide show
  1. package/AGENTS.md +8 -5
  2. package/dist/component-hooks/use-headless-consent-ui.js +1 -1
  3. package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
  4. package/dist/components/iab-panel/atoms/vendor-list.js +1 -1
  5. package/dist/components/iab-panel/hooks/use-gvl-data.js +1 -1
  6. package/dist/components/iab-panel/index.js +1 -1
  7. package/dist/components/panel/index.js +1 -1
  8. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  9. package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -1
  10. package/dist/components/panel-trigger/panel-trigger.js +1 -1
  11. package/dist/components/preferences/atoms/accordion.js +1 -1
  12. package/dist/components/preferences/index.js +1 -1
  13. package/dist/components/shared/primitives/button.js +1 -1
  14. package/dist/components/shared/ui/accordion/accordion.js +1 -1
  15. package/dist/components/shared/ui/collapsible/collapsible.js +1 -1
  16. package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
  17. package/dist/components/shared/ui/switch/switch.js +1 -1
  18. package/dist/components/shared/ui/tabs/tabs.js +1 -1
  19. package/dist/devtools-launcher.js +2 -0
  20. package/dist/devtools.js +1 -1
  21. package/dist/draft-context.js +2 -0
  22. package/dist/draft.js +1 -1
  23. package/dist/external-iab-context.js +1 -1
  24. package/dist/gpp.js +2 -0
  25. package/dist/hooks/use-color-scheme.js +1 -1
  26. package/dist/hooks/use-headless-iab-consent-ui.js +1 -1
  27. package/dist/hooks.js +1 -1
  28. package/dist/index-parts/consent-banner.js +1 -0
  29. package/dist/index-parts/consent-dialog-link.js +1 -0
  30. package/dist/index-parts/consent-dialog-trigger.js +1 -0
  31. package/dist/index-parts/consent-dialog.js +1 -0
  32. package/dist/index-parts/consent-gate.js +1 -0
  33. package/dist/index-parts/core.js +1 -0
  34. package/dist/index-parts/draft.js +1 -0
  35. package/dist/index-parts/hooks.js +1 -0
  36. package/dist/index-parts/module-hooks.js +1 -0
  37. package/dist/index-parts/provider.js +1 -0
  38. package/dist/index-parts/theme.js +1 -0
  39. package/dist/index-parts/translations.js +1 -0
  40. package/dist/index.js +1 -1
  41. package/dist/kernel-selector.js +1 -1
  42. package/dist/module-hooks/iframe-blocker.js +1 -1
  43. package/dist/provider.js +1 -1
  44. package/dist/styles.tw3.css +27 -3
  45. package/dist/version.js +1 -1
  46. package/dist-types/component-hooks/use-headless-consent-ui.d.ts +4 -4
  47. package/dist-types/components/iab-panel/index.d.ts +0 -1
  48. package/dist-types/components/panel/index.d.ts +0 -1
  49. package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +5 -0
  50. package/dist-types/components/panel-trigger/panel-trigger.d.ts +0 -8
  51. package/dist-types/components/preferences/index.d.ts +0 -1
  52. package/dist-types/components/shared/ui/accordion/accordion.d.ts +0 -1
  53. package/dist-types/components/shared/ui/collapsible/collapsible.d.ts +0 -1
  54. package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +0 -1
  55. package/dist-types/components/shared/ui/switch/switch.d.ts +0 -1
  56. package/dist-types/components/shared/ui/tabs/tabs.d.ts +0 -1
  57. package/dist-types/devtools-launcher.d.ts +29 -0
  58. package/dist-types/draft-context.d.ts +31 -0
  59. package/dist-types/draft.d.ts +13 -36
  60. package/dist-types/gpp.d.ts +27 -0
  61. package/dist-types/hooks/use-iab-manager.d.ts +4 -4
  62. package/dist-types/hooks.d.ts +30 -5
  63. package/dist-types/index-parts/consent-banner.d.ts +7 -0
  64. package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
  65. package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
  66. package/dist-types/index-parts/consent-dialog.d.ts +7 -0
  67. package/dist-types/index-parts/consent-gate.d.ts +7 -0
  68. package/dist-types/index-parts/core.d.ts +8 -0
  69. package/dist-types/index-parts/draft.d.ts +7 -0
  70. package/dist-types/index-parts/hooks.d.ts +7 -0
  71. package/dist-types/index-parts/module-hooks.d.ts +7 -0
  72. package/dist-types/index-parts/provider.d.ts +7 -0
  73. package/dist-types/index-parts/theme.d.ts +8 -0
  74. package/dist-types/index-parts/translations.d.ts +7 -0
  75. package/dist-types/index.d.ts +15 -16
  76. package/dist-types/kernel-selector.d.ts +0 -8
  77. package/dist-types/module-hooks/iframe-blocker.d.ts +12 -7
  78. package/dist-types/provider.d.ts +47 -13
  79. package/dist-types/version.d.ts +1 -1
  80. package/docs/README.md +8 -5
  81. package/docs/concepts/choose-your-setup.md +22 -5
  82. package/docs/concepts/consent-state.md +60 -5
  83. package/docs/concepts/data-fetching.md +34 -11
  84. package/docs/customization/recipes.md +4 -5
  85. package/docs/customization/slots.md +3 -2
  86. package/docs/customization/stylesheets.md +29 -39
  87. package/docs/customization/tailwind.md +5 -5
  88. package/docs/customization/tokens.md +1 -1
  89. package/docs/customization/translations.md +33 -7
  90. package/docs/frameworks/react/components/consent-dialog-trigger.md +5 -0
  91. package/docs/frameworks/react/components/consent-dialog.md +2 -1
  92. package/docs/frameworks/react/components/consent-provider.md +6 -2
  93. package/docs/frameworks/react/components/dev-tools.md +24 -1
  94. package/docs/frameworks/react/gpp.md +163 -0
  95. package/docs/frameworks/react/headless.md +4 -4
  96. package/docs/frameworks/react/hooks.md +10 -5
  97. package/docs/frameworks/react/iab.md +24 -18
  98. package/docs/frameworks/react/quickstart.md +77 -16
  99. package/docs/frameworks/react/rendering.md +82 -11
  100. package/docs/frameworks/react/scripts.md +8 -3
  101. package/docs/frameworks/react/upgrade-v3.md +596 -0
  102. package/docs/frameworks/react/vendor-consent.md +6 -0
  103. package/docs/guides/banner-experiments.md +26 -5
  104. package/docs/guides/troubleshooting.md +3 -2
  105. package/docs/integrations/overview.md +28 -27
  106. package/docs/integrations/posthog.md +99 -11
  107. package/docs/integrations/sentry.md +416 -0
  108. package/docs/upgrade-v3.md +222 -314
  109. package/package.json +13 -8
  110. package/dist/ui-save.js +0 -1
  111. package/dist-types/ui-save.d.ts +0 -25
@@ -1,4 +1,5 @@
1
- import type { AllConsentNames, ConsentKernel, ConsentState, SaveResult, SaveInput, SaveUISource } from '@c15t/core';
1
+ import type { AllConsentNames, ConsentState, SaveResult } from '@c15t/core';
2
+ import type { PreferenceDraft, PreferenceDraftState } from '@c15t/core/preference-draft';
2
3
  import type { ReactNode } from 'react';
3
4
  /** A local, unmasked selection, committed only by an explicit save. */
4
5
  export interface ConsentDraftHandle {
@@ -27,61 +28,37 @@ export interface ConsentDraftHandle {
27
28
  save: () => Promise<SaveResult>;
28
29
  reset: () => void;
29
30
  }
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>;
31
+ type DraftStore = PreferenceDraft;
58
32
  export interface ConsentDraftProviderProps {
59
33
  children: ReactNode;
60
34
  /** Defaults apply only to categories without an explicit receipt. */
61
35
  initial?: Partial<ConsentState>;
62
36
  }
37
+ /**
38
+ * Share one draft with every draft hook and stock control below it. The
39
+ * preference dialog renders one, so its switches, vendor rows and save
40
+ * button stage into and confirm the same draft.
41
+ */
63
42
  export declare const ConsentDraftProvider: ({ children, initial, }: ConsentDraftProviderProps) => import("react").JSX.Element;
64
- /** Internal UI save path shared by stock controls and headless actions. */
65
- export declare const useConsentSaveAction: () => (input?: SaveInput, uiSource?: SaveUISource) => Promise<SaveResult>;
66
43
  /**
67
- * The nearest consent draft store, for the stock preference rows. Pair with
44
+ * The nearest consent draft, for the stock preference rows. Pair with
68
45
  * {@link useConsentDraftSlice} so a row re-renders only when its own slice
69
46
  * changes, not on every staged edit elsewhere in the draft.
70
47
  *
71
- * @returns The shared draft store, or a local one outside a provider.
48
+ * @returns The shared draft, or a local one outside a provider.
72
49
  * @internal
73
50
  */
74
51
  export declare const useConsentDraftStore: () => DraftStore;
75
52
  /**
76
- * Subscribes to one slice of a consent draft store.
53
+ * Subscribes to one slice of a consent draft.
77
54
  *
78
- * @param store - Store from {@link useConsentDraftStore}.
55
+ * @param draft - Draft from {@link useConsentDraftStore}.
79
56
  * @param selector - Picks the slice. Return a primitive or a reference the
80
57
  * draft already holds.
81
58
  * @returns The selected slice.
82
59
  * @internal
83
60
  */
84
- export declare const useConsentDraftSlice: <SliceType>(store: DraftStore, selector: (draft: DraftSnapshot) => SliceType) => SliceType;
61
+ export declare const useConsentDraftSlice: <SliceType>(draft: DraftStore, selector: (state: PreferenceDraftState) => SliceType) => SliceType;
85
62
  /** Read and edit displayed choices without replacing masked effective permissions. */
86
63
  export declare const useConsentDraft: () => ConsentDraftHandle;
87
64
  /** The vendor slice of the consent draft, for a custom vendor control. */
@@ -0,0 +1,27 @@
1
+ import type { RuntimeGPPOptions } from '@c15t/core/runtime';
2
+ /** Props for {@link ConsentGPP}: the GPP options, all optional. */
3
+ export type ConsentGPPProps = RuntimeGPPOptions;
4
+ /**
5
+ * Installs `window.__gpp`, the IAB GPP CMP API, on the surrounding
6
+ * provider's kernel and keeps its GPP string in step with the visitor's
7
+ * choices. Renders nothing. Unmounting removes `__gpp`.
8
+ *
9
+ * Render it inside `ConsentProvider` (or `ConsentRoot` in Next.js and
10
+ * TanStack Start). Every prop is plain data, so a Server Component can
11
+ * render it.
12
+ *
13
+ * @param props - GPP options. See `RuntimeGPPOptions`.
14
+ * @returns `null`.
15
+ * @throws {Error} When rendered outside a consent provider.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * import { ConsentGPP } from '@c15t/react/gpp';
20
+ *
21
+ * <ConsentProvider options={{ mode: hosted({ url }) }}>
22
+ * <ConsentGPP usFallback="none" />
23
+ * <App />
24
+ * </ConsentProvider>
25
+ * ```
26
+ */
27
+ export declare const ConsentGPP: ({ cmpId, mspaMode, optOutCategories, tcf, usApproach, usFallback, }: ConsentGPPProps) => null;
@@ -11,8 +11,8 @@ export declare const useIABConsentManager: (overrides?: ConsentPresentation) =>
11
11
  actionGroups: import("@c15t/core").PresentationAction[][];
12
12
  primaryActions: import("@c15t/core").PresentationAction[];
13
13
  diagnostics: import("@c15t/core").PresentationDiagnostic[];
14
- rights: readonly import("@c15t/schema/types").PolicyRight[];
15
- preferenceControls: Exclude<import("@c15t/schema/types").PolicyRight, 'disclosure'>[];
14
+ rights: readonly import("@c15t/schema").PolicyRight[];
15
+ preferenceControls: Exclude<import("@c15t/schema").PolicyRight, 'disclosure'>[];
16
16
  direction: 'row' | 'column';
17
17
  uiProfile: 'balanced' | 'compact' | 'strict';
18
18
  scrollLock: boolean;
@@ -32,8 +32,8 @@ export declare const useIABConsentManager: (overrides?: ConsentPresentation) =>
32
32
  actionGroups: import("@c15t/core").PresentationAction[][];
33
33
  primaryActions: import("@c15t/core").PresentationAction[];
34
34
  diagnostics: import("@c15t/core").PresentationDiagnostic[];
35
- rights: readonly import("@c15t/schema/types").PolicyRight[];
36
- preferenceControls: Exclude<import("@c15t/schema/types").PolicyRight, 'disclosure'>[];
35
+ rights: readonly import("@c15t/schema").PolicyRight[];
36
+ preferenceControls: Exclude<import("@c15t/schema").PolicyRight, 'disclosure'>[];
37
37
  direction: 'row' | 'column';
38
38
  uiProfile: 'balanced' | 'compact' | 'strict';
39
39
  scrollLock: boolean;
@@ -84,13 +84,35 @@ export declare const usePolicyScopeMode: () => PolicyScopeMode;
84
84
  export declare const useIABSnapshot: () => Readonly<KernelIABState> | null;
85
85
  /** Is IAB active? */
86
86
  export declare const useIABEnabled: () => boolean;
87
- /** Consent for a specific IAB vendor. Accepts numeric or string IDs; IAB
88
- * vendors are numeric but the kernel stores them as strings for
89
- * uniformity with custom vendors. */
87
+ /**
88
+ * The preference centre's consent selection for one IAB vendor, including
89
+ * changes the visitor has not saved yet. Use it to render a control, not to
90
+ * gate a vendor: the saved choice is the TC string that `__tcfapi` serves,
91
+ * and `useIABSnapshot()?.authority` holds its decoded signals.
92
+ *
93
+ * @param vendorId - Numeric or string ID. IAB vendors are numeric; the
94
+ * kernel stores IDs as strings so custom vendors fit the same map.
95
+ * @returns Whether the vendor is selected.
96
+ */
90
97
  export declare const useVendorConsent: (vendorId: string | number) => boolean;
91
- /** Consent for a specific IAB purpose (1–11). */
98
+ /**
99
+ * The preference centre's consent selection for one IAB purpose (1-11),
100
+ * including changes the visitor has not saved yet. Use it to render a
101
+ * control, not to gate a vendor: see {@link useVendorConsent}.
102
+ *
103
+ * @param purposeId - IAB purpose ID.
104
+ * @returns Whether the purpose is selected.
105
+ */
92
106
  export declare const usePurposeConsent: (purposeId: number) => boolean;
93
- /** Opt-in for a special feature (1 = geolocation, 2 = device ID). */
107
+ /**
108
+ * The preference centre's opt-in selection for one special feature
109
+ * (1 = geolocation, 2 = device ID), including changes the visitor has not
110
+ * saved yet. Use it to render a control, not to gate a vendor: see
111
+ * {@link useVendorConsent}.
112
+ *
113
+ * @param featureId - IAB special feature ID.
114
+ * @returns Whether the special feature is selected.
115
+ */
94
116
  export declare const useSpecialFeatureOptIn: (featureId: number) => boolean;
95
117
  /** Latest TCF string. `null` until the IAB module encodes one. */
96
118
  export declare const useTCString: () => string | null;
@@ -144,6 +166,9 @@ export declare const useSetOverrides: () => (input: KernelOverrides) => void;
144
166
  export declare const useSetLanguage: () => (code: string) => void;
145
167
  /**
146
168
  * Sync mutation: set the active UI surface (banner/dialog/none).
169
+ *
170
+ * Explicit navigation: a pending save on this kernel can no longer close or
171
+ * restore a surface once the visitor navigated.
147
172
  */
148
173
  export declare const useSetActiveUI: () => (ui: KernelActiveUI) => void;
149
174
  /**
@@ -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 { ConsentBanner, useConsentBannerSurface } from '../components/prompt/index.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 { ConsentDialogLink } from '../components/panel-link/index.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 { ConsentDialogTrigger, ConsentDialogTriggerToolbar, } from '../components/panel-trigger/index.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 { ConsentDialog, ConsentWidget } from '../aggregate-components.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 { ConsentGate, Frame } from '../components/consent-gate/index.js';
@@ -0,0 +1,8 @@
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 { createConsentKernel, custom, hosted, policyRulePresets, } from '@c15t/core';
8
+ 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 { ConsentDraftProvider, useConsentDraft, useVendorDraft, } from '../draft.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 { useActiveUI, useBranding, useConsent, useConsents, useDeclaredVendors, useDismissNotice, useEffectivePermissions, useExperiment, useExplicitChoice, useHasConsentPolicy, useHasConsentPreferences, useHasConsentUI, useIABEnabled, useIABSnapshot, useIdentify, useInit, useLocation, useModel, useNoticeDismissal, useOverrides, usePolicyCategories, usePolicyResolution, usePolicyRule, usePolicyScopeMode, usePreferencesPresentation, usePrivacySignals, usePromptPresentation, usePromptRequirement, usePurposeConsent, useRegisterConsentCategories, useResolvedPresentation, useResolvedTheme, useRestrictions, useSaveConsents, useSetActiveUI, useSetLanguage, useSetOverrides, useSnapshot, useSpecialFeatureOptIn, useSubscribeToConsentChanges, useTCString, useUser, useVendorAllowed, useVendorChoice, useVendorConsent, } from '../hooks.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 { useIframeBlocker, useNetworkBlocker, usePersistence, useScriptLoader, } from '../module-hooks.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 { ConsentProvider } from '../provider.js';
@@ -0,0 +1,8 @@
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 { ConsentTheme } from '../consent-theme.js';
8
+ export { defineTheme } from '../types/theme/index.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 { useTranslations } from '../component-hooks/use-translations.js';
@@ -31,32 +31,31 @@
31
31
  * cache patching. No method rewriting. Provider boot work is explicit
32
32
  * module wiring around a single per-mount kernel.
33
33
  */
34
- export type { ConsentKernel, ConsentSnapshot, ConsentState, HostedTransportOptions, InitContext, InitResponse, InitResult, KernelConfig, KernelEvent, KernelOverrides, KernelTransport, KernelUser, Listener, HostedModeOptions, ProviderTransportContext, ProviderTransportFactory, ProviderTransportKind, SavePayload, SaveResult, Unsubscribe, } from '@c15t/core';
35
- export { createConsentKernel, custom, hosted } from '@c15t/core';
34
+ export type { AllConsentNames, ClearOnRevocationConfig, ConsentKernel, ConsentSnapshot, ConsentState, HostedTransportOptions, InitContext, InitResponse, InitResult, KernelConfig, KernelEvent, KernelOverrides, KernelTransport, KernelUser, Listener, HostedModeOptions, PolicyRule, ProviderTransportContext, ProviderTransportFactory, ProviderTransportKind, SavePayload, SaveResult, Unsubscribe, } from '@c15t/core';
36
35
  export type { OfflineModeOptions } from './transports/offline.js';
37
- export { offline } from './transports/offline.js';
38
- export { ConsentDialog, ConsentWidget } from './aggregate-components.js';
39
36
  export type { ConsentBannerButton, ConsentBannerLayout, ConsentBannerProps, ConsentBannerRight, ConsentBannerRightLinkProps, ConsentBannerRightsProps, ConsentBannerSurface, } from './components/prompt/index.js';
40
- export { ConsentBanner, type ConsentBannerCompoundComponent, useConsentBannerSurface, } from './components/prompt/index.js';
41
37
  export type { ConsentDialogCompoundComponent, ConsentDialogProps, } from './components/panel/index.js';
42
38
  export type { ConsentDialogLinkProps } from './components/panel-link/index.js';
43
- export { ConsentDialogLink } from './components/panel-link/index.js';
44
39
  export type { ConsentDialogTriggerProps, ConsentDialogTriggerToolbarAction, ConsentDialogTriggerToolbarPreferences, ConsentDialogTriggerToolbarProps, TriggerOrientation, } from './components/panel-trigger/index.js';
45
- export { ConsentDialogTrigger, ConsentDialogTriggerToolbar, } from './components/panel-trigger/index.js';
46
40
  export type { ConsentWidgetCompoundComponent, ConsentWidgetProps, } from './components/preferences/index.js';
47
41
  export type { ConsentGateProps, FrameProps } from './components/consent-gate/index.js';
48
- export { ConsentGate, Frame } from './components/consent-gate/index.js';
49
42
  export type { ConsentDraftHandle, ConsentDraftProviderProps, VendorDraftHandle, } from './draft.js';
50
- export { ConsentDraftProvider, useConsentDraft, useVendorDraft } from './draft.js';
51
- export { useTranslations } from './component-hooks/use-translations.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
43
  export type { UseIframeBlockerOptions, UseNetworkBlockerOptions, UsePersistenceOptions, UseScriptLoaderOptions, } from './module-hooks.js';
54
- export { useIframeBlocker, useNetworkBlocker, usePersistence, useScriptLoader, } from './module-hooks.js';
55
44
  export type { ConsentProviderOptions, ConsentProviderCallbacks, ConsentProviderPrefetch, ConsentProviderProps, ExternalRuntimeProviderOptions, ExternalRuntimeProviderProps, OwnedRuntimeProviderProps, } from './provider.js';
56
- export { ConsentProvider } from './provider.js';
57
- export { ConsentTheme } from './consent-theme.js';
58
45
  export type { ConsentThemeProps } from './consent-theme.js';
46
+ export type { Theme } from './types/theme/index.js';
47
+ export type { ConsentBannerCompoundComponent } from './components/prompt/index.js';
59
48
  export type { ReactUIOptions } from './types/manager.js';
60
- export { defineTheme, type Theme } from './types/theme/index.js';
61
- export { useExplicitChoice, useEffectivePermissions, usePromptRequirement, useNoticeDismissal, usePrivacySignals, usePolicyResolution, usePolicyRule, useRestrictions, useDismissNotice, } from './hooks.js';
62
49
  export type { ConsentPresentation, PromptPresentation, PreferencesPresentation, PresentationAction, PromptPosition, PromptVariant, ResolvedConsentPresentation, } from '@c15t/core';
50
+ export * from './index-parts/core.js';
51
+ export * from './index-parts/consent-dialog.js';
52
+ export * from './index-parts/consent-banner.js';
53
+ export * from './index-parts/consent-dialog-link.js';
54
+ export * from './index-parts/consent-dialog-trigger.js';
55
+ export * from './index-parts/consent-gate.js';
56
+ export * from './index-parts/draft.js';
57
+ export * from './index-parts/translations.js';
58
+ export * from './index-parts/module-hooks.js';
59
+ export * from './index-parts/provider.js';
60
+ export * from './index-parts/theme.js';
61
+ export * from './index-parts/hooks.js';
@@ -56,11 +56,3 @@ export declare const useCategoryAllowed: (category: AllConsentNames) => boolean;
56
56
  * @internal
57
57
  */
58
58
  export declare const useTranslationLanguage: () => string;
59
- /**
60
- * Categories the preference surface lists: `necessary` plus the recorded
61
- * choice scope, or the policy scope when no choice scope applies.
62
- *
63
- * @returns A list whose identity changes only when the scope does.
64
- * @internal
65
- */
66
- export declare const useDisplayedCategories: () => readonly AllConsentNames[];
@@ -1,5 +1,5 @@
1
1
  import type { ConsentKernel } from '@c15t/core';
2
- import type { IframeBlockerHandle } from '@c15t/core/modules/iframe-blocker';
2
+ import type { IframeBlockerHandle, IframeBlockerOptions } from '@c15t/core/modules/iframe-blocker';
3
3
  export interface UseIframeBlockerOptions {
4
4
  disableAutomaticBlocking?: boolean;
5
5
  }
@@ -21,13 +21,18 @@ export declare const useIframeBlocker: (options?: UseIframeBlockerOptions) => If
21
21
  */
22
22
  export declare const watchGatedIframes: (kernel: ConsentKernel, onFound: () => void) => () => void;
23
23
  /**
24
- * The provider's default iframe blocker. Loads the blocker module when the
25
- * first gated iframe (`data-category` or `data-vendor`) is on the page
26
- * instead of on every mount, so pages without one never download it.
24
+ * The provider's iframe blocker. Loads the blocker module when the first
25
+ * gated iframe (`data-category` or `data-vendor`) is on the page instead of
26
+ * on every mount, so pages without one never download it. Until then it
27
+ * pauses gated frames that arrive with a `src` consent does not allow.
27
28
  *
28
- * @param options - Blocker options. With `disableAutomaticBlocking` the
29
- * module loads at once, as it did before.
29
+ * Passed to the provider runtime as its `createIframeBlocker` module.
30
+ *
31
+ * @param options - The kernel and blocker options. With
32
+ * `disableAutomaticBlocking` the module loads at once.
33
+ * @returns A handle; `processAllIframes()` reaches the blocker once it has
34
+ * loaded.
30
35
  * @internal
31
36
  */
32
- export declare const useIframeBlockerOnDemand: (options?: UseIframeBlockerOptions) => void;
37
+ export declare const createIframeBlockerOnDemand: ({ disableAutomaticBlocking, kernel, }: IframeBlockerOptions) => IframeBlockerHandle;
33
38
  export type { IframeBlockerHandle };
@@ -1,6 +1,7 @@
1
- import type { AllConsentNames, ClearOnRevocationConfig, ConsentExperiment, ExperimentState, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User, Vendor } from '@c15t/core';
1
+ import type { AllConsentNames, Callbacks, ClearOnRevocationConfig, ConsentExperiment, ConsentPresentation, ExperimentState, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User, Vendor } from '@c15t/core';
2
2
  import type { Script } from '@c15t/core/modules/script-loader';
3
- import type { ConsentControlOptions, ConsentRuntime } from '@c15t/core/runtime';
3
+ import type { ConsentControlOptions } from '@c15t/core/runtime';
4
+ import type { ConsentRuntime, ConsentRuntimeModules, ResolveStreamedInit } from '@c15t/core/runtime/provider';
4
5
  import type { ReactNode } from 'react';
5
6
  import type { DialogPreload } from './chunk-warming.js';
6
7
  import type { UseNetworkBlockerOptions, UsePersistenceOptions, UseScriptLoaderOptions } from './module-hooks.js';
@@ -56,6 +57,12 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
56
57
  * ```
57
58
  */
58
59
  mode: ProviderTransportFactory;
60
+ /**
61
+ * Where the visitor's choice is stored. Read once, like `persistence`:
62
+ * the stored records and the data clearing that protects them stay at
63
+ * the location the provider mounted with. Outside production, a change
64
+ * logs a warning; remount the provider to move storage.
65
+ */
59
66
  storageConfig?: StorageConfig;
60
67
  user?: User | KernelUser;
61
68
  overrides?: KernelOverrides;
@@ -123,6 +130,10 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
123
130
  * is paused.
124
131
  */
125
132
  iframeBlocker?: UseIframeBlockerOptions | false;
133
+ /**
134
+ * Store the visitor's choice in a cookie and localStorage. On by default.
135
+ * Read once, when the provider mounts; see `storageConfig`.
136
+ */
126
137
  persistence?: boolean | UsePersistenceOptions;
127
138
  i18n?: Partial<I18nConfig>;
128
139
  /** Categories to offer alongside discovered integration categories, within policy scope. */
@@ -150,6 +161,27 @@ export interface ConsentProviderOptions extends ConsentControlOptions, Pick<Reac
150
161
  * @internal
151
162
  */
152
163
  __debugPkg?: string;
164
+ /**
165
+ * The code that applies a `prefetch` promise, from
166
+ * `@c15t/core/runtime/streamed-init`. Without it the provider loads that
167
+ * code once `prefetch` is a promise, so an app that never streams one
168
+ * doesn't download it. A framework root whose state is usually streamed
169
+ * (`ConsentRoot`) passes it, so the state applies as soon as it arrives
170
+ * instead of after one more request. Read once, at mount.
171
+ * @internal
172
+ */
173
+ __resolveStreamedInit?: ResolveStreamedInit;
174
+ /**
175
+ * `preloadScriptLoaderWith` from
176
+ * `@c15t/core/runtime/script-loader-preload`. With it the runtime starts
177
+ * the script loader's download during the first render when consent
178
+ * already lets a script run, instead of from the mount effect. A
179
+ * framework root whose state usually holds a returning visitor's choice
180
+ * (`ConsentRoot`) passes it; without it the provider ships none of that
181
+ * decision. Read once, at mount.
182
+ * @internal
183
+ */
184
+ __preloadScriptLoader?: (load: () => Promise<unknown>) => ConsentRuntimeModules['preloadScriptLoader'];
153
185
  }
154
186
  /**
155
187
  * Options accepted when an external runtime supplies the kernel.
@@ -187,19 +219,21 @@ export type ConsentProviderProps = OwnedRuntimeProviderProps | ExternalRuntimePr
187
219
  /**
188
220
  * v3 ConsentProvider.
189
221
  *
190
- * Retains the enabled kernel while disabled mode uses a separate permissive
191
- * kernel, so toggling enabled preserves recorded choices. Provides the active
192
- * kernel via context and wires the curated v2-like options surface to v3
193
- * modules. It does not mirror the
194
- * snapshot into React state; selector hooks still subscribe directly to
195
- * the kernel through `useSyncExternalStore`.
222
+ * Builds one consent runtime (`createConsentProviderRuntime`) per mounted
223
+ * provider and renders its kernel: the kernel goes into context, and
224
+ * selector hooks subscribe to it through `useSyncExternalStore`. New
225
+ * options reach the runtime through `update()`, which applies only what
226
+ * changed; `mode`, `i18n`, `experiment`, `prefetch`, `persistence`,
227
+ * `storageConfig` and `clearOnRevocation` are read once. While `enabled` is
228
+ * `false` the runtime renders a separate permissive kernel, so toggling it
229
+ * keeps the visitor's records.
196
230
  *
197
231
  * Pass `runtime` to render a runtime someone else created. The provider
198
- * then borrows its kernel and mounts none of the side-effecting modules —
199
- * no second `init()`, no second persistence handle, no second `window.c15t`
200
- * — and does not dispose it on unmount. Handing it a different runtime
201
- * switches the tree to that runtime's kernel; switching between a borrowed
202
- * runtime and a provider-built kernel still needs a remount.
232
+ * then borrows its kernel and starts nothing — no second `init()`, no
233
+ * second persistence handle, no second `window.c15t` — and does not
234
+ * dispose it on unmount. Handing it a different runtime switches the tree
235
+ * to that runtime's kernel; switching between a borrowed runtime and a
236
+ * provider-built one still needs a remount.
203
237
  *
204
238
  * @example
205
239
  * ```tsx
@@ -1 +1 @@
1
- export declare const version = "3.0.0-alpha.4";
1
+ export declare const version = "3.0.0-alpha.6";
package/docs/README.md CHANGED
@@ -15,7 +15,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
15
15
  - [How consent works](./concepts/how-consent-works.md): What c15t decides on each page load, the difference between a permission and a recorded choice, and what happens when a visitor saves.
16
16
  - [Customize the interface](./customization/overview.md): Change c15t's consent banner and dialog one step at a time, from a prop to your own markup, and find where each step lives in your framework.
17
17
  - [Verify consent](./guides/verify-consent.md): Check in a production build that vendor requests wait for consent, rejection survives a reload, preferences reopen and privacy signals apply.
18
- - [Migrate to v3](./upgrade-v3.md): Upgrade a c15t v2 app to v3. Covers packages, the Next.js and React providers, the JavaScript runtime, custom UI built on useConsentManager, callbacks, policies, stored consent and a self-hosted backend.
18
+ - [Migrate to v3](./upgrade-v3.md): Upgrade from c15t v2 to v3. Pick the guide for the v2 package you use (@c15t/nextjs, @c15t/react or the c15t store), rename @c15t/scripts, keep visitors' choices, and upgrade a self-hosted backend and the Node.js SDK.
19
19
 
20
20
  ## More documentation
21
21
 
@@ -38,6 +38,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
38
38
  - [Content Security Policy](./frameworks/react/content-security-policy.md): Run c15t in a React app under a Content Security Policy, allow the consent backend and vendor hosts, and pass a nonce to ConsentProvider and ConsentTheme.
39
39
  - [Customize](./frameworks/react/customize.md): Change the colors, fonts, layout, button styles and copy of the c15t banner and dialog in a React app with the stylesheet, theme tokens, provider options and slots.
40
40
  - [Embeds](./frameworks/react/embeds.md): Keep YouTube videos, maps and other iframes out of a React page until their consent category is allowed, with ConsentGate or the iframe blocker in ConsentProvider.
41
+ - [IAB GPP](./frameworks/react/gpp.md): Add the IAB Global Privacy Platform API (__gpp) to a React app with ConsentGPP from @c15t/react/gpp, so ad tech can read US state opt-outs and the TCF EU consent string.
41
42
  - [Headless](./frameworks/react/headless.md): Build a custom consent banner in React with the c15t/react/headless hooks inside your ConsentProvider.
42
43
  - [Hooks](./frameworks/react/hooks.md): Gate features and save consent choices in React components with the focused hooks exported from c15t/react.
43
44
  - [IAB TCF](./frameworks/react/iab.md): Mount the IAB TCF banner and dialog inside a React ConsentProvider and configure the CMP ID, policy and vendor data.
@@ -47,6 +48,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
47
48
  - [Scripts](./frameworks/react/scripts.md): Load vendor scripts by consent category in a React app with ConsentProvider, and clear stored data or reload the page when a visitor withdraws consent.
48
49
  - [Translations](./frameworks/react/translations.md): Where c15t banner and dialog copy comes from in a React app, how the browser picks the visitor's language, and how to override copy and switch languages with the provider's i18n option and hooks.
49
50
  - [Troubleshooting](./frameworks/react/troubleshooting.md): Fix a missing banner, early vendor requests, unstyled components and theme warnings in a React app that uses c15t/react.
51
+ - [Upgrade from v2](./frameworks/react/upgrade-v3.md): Upgrade a React app from c15t v2 (@c15t/react) to v3. Covers packages, ConsentProvider and transports, the useConsentManager codemod, callbacks, policies, styles, IAB and stored consent.
50
52
  - [Vendor consent](./frameworks/react/vendor-consent.md): Let visitors allow a category such as marketing in a React app and still turn off one vendor in it, with the vendors option on ConsentProvider and useVendorAllowed.
51
53
 
52
54
  ## Concepts
@@ -54,7 +56,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
54
56
  - [Choose your setup](./concepts/choose-your-setup.md): Pick the c15t setup for your framework, rendering mode and hosting, and decide who runs the consent backend.
55
57
  - [Consent categories](./concepts/consent-categories.md): Assign scripts, embeds and features to c15t consent categories, and understand which categories the preference dialog shows.
56
58
  - [Consent state reference](./concepts/consent-state.md): How c15t saves choices, gates IAB vendors, hydrates server records and keeps browser tabs and storage in step.
57
- - [Data fetching](./concepts/data-fetching.md): How c15t gets policy data through a cached manifest, backend /init, the browser or offline rules, and where consent choices are saved.
59
+ - [Data fetching](./concepts/data-fetching.md): Choose the recommended build-time policy snapshot or runtime manifest fetching, backend /init, browser resolution or offline rules, and understand where consent choices are saved.
58
60
  - [How consent works](./concepts/how-consent-works.md): What c15t decides on each page load, the difference between a permission and a recorded choice, and what happens when a visitor saves.
59
61
  - [Policies](./concepts/policies.md): How policy models, prompts and scope decide what c15t asks visitors, where to change the rules, and why a banner may not appear.
60
62
 
@@ -72,7 +74,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
72
74
  - [Customize the interface](./customization/overview.md): Change c15t's consent banner and dialog one step at a time, from a prop to your own markup, and find where each step lives in your framework.
73
75
  - [Banner designs](./customization/recipes.md): Five consent banner designs built with c15t, from one prop to your own markup, with tested code for React, Vue, Svelte, Astro and plain HTML.
74
76
  - [Component parts](./customization/slots.md): Find every part of c15t's banner, dialog, widget, trigger and ConsentGate placeholder, its key in your framework's part API, and the data attributes to select on.
75
- - [Stylesheets and CSS layers](./customization/stylesheets.md): Load the right c15t stylesheet for your framework, see when the dialog's CSS loads, order c15t's cascade layer against your own, and run c15t without its styles.
77
+ - [Stylesheets and CSS layers](./customization/stylesheets.md): Load the right c15t stylesheet for your framework, see which file holds the dialog's rules, order c15t's cascade layer against your own, and run c15t without its styles.
76
78
  - [Tailwind CSS](./customization/tailwind.md): Load c15t's styles next to Tailwind CSS 4 or 3 in every framework, put utilities on c15t component parts, and use Tailwind's dark variant with c15t.
77
79
  - [Theme tokens](./customization/tokens.md): Change c15t's colors, type, radius, spacing, shadows and motion with theme tokens, and see every --c15t-* variable with its default.
78
80
  - [Copy and translations](./customization/translations.md): Change consent wording through i18n and test the complete prompt and preferences flow.
@@ -111,12 +113,13 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
111
113
  - [Pinterest Tag](./integrations/pinterest-tag.md): Load the Pinterest Tag only after marketing consent with the c15t pinterestTag helper, guard pintrk event calls, and check it in DevTools.
112
114
  - [Pirsch](./integrations/pirsch.md): Load Pirsch Analytics only after measurement consent with the c15t pirsch helper, keep custom event bindings working, and check it in DevTools.
113
115
  - [Plausible Analytics](./integrations/plausible-analytics.md): Load the Plausible Analytics tracker only after measurement consent with the c15t plausibleAnalytics helper, and check it in DevTools.
114
- - [PostHog](./integrations/posthog.md): Load PostHog before or after measurement consent with the c15t posthog helper, choose its cookieless behavior, and sync consent with an SDK you already initialize.
116
+ - [PostHog](./integrations/posthog.md): Load PostHog before or after measurement consent with the c15t posthog helper, choose its cookieless behavior, turn off PostHog modules you do not use, and sync consent with an SDK you already initialize.
115
117
  - [Promptwatch](./integrations/promptwatch.md): Load the Promptwatch attribution client only after measurement consent with the c15t promptwatch helper, and check it in DevTools.
116
118
  - [Reddit Pixel](./integrations/reddit-pixel.md): Load the Reddit Pixel only after marketing consent with the c15t redditPixel helper, guard rdt conversion calls, and check it in DevTools.
117
119
  - [RudderStack](./integrations/rudderstack.md): Load the RudderStack JavaScript SDK after measurement consent with the c15t rudderstack helper, or map c15t categories to destination consent IDs, and check each mode.
118
120
  - [Rybbit Analytics](./integrations/rybbit-analytics.md): Load Rybbit Analytics only after measurement consent with the c15t rybbitAnalytics helper, map its tracking options to data attributes, and check it in DevTools.
119
121
  - [Segment](./integrations/segment.md): Load Segment Analytics.js only after measurement consent with the c15t segment helper, guard your own track and identify calls, and check it in DevTools.
122
+ - [Sentry](./integrations/sentry.md): Configure Sentry's CDN or your own SDK with consent for error monitoring, Session Replay and user data.
120
123
  - [Snapchat Pixel](./integrations/snapchat-pixel.md): Load the Snapchat Pixel only after marketing consent with the c15t snapchatPixel helper, guard snaptr event calls, and check it in DevTools.
121
124
  - [TikTok Pixel](./integrations/tiktok-pixel.md): Load the TikTok Pixel only after marketing consent with the c15t tiktokPixel helper, guard ttq event calls, and check it in DevTools.
122
125
  - [Umami Analytics](./integrations/umami-analytics.md): Load the Umami Analytics tracker only after measurement consent with the c15t umamiAnalytics helper, point it at a self-hosted instance, and check it in DevTools.
@@ -126,4 +129,4 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
126
129
 
127
130
  ## Reference
128
131
 
129
- - [Migrate to v3](./upgrade-v3.md): Upgrade a c15t v2 app to v3. Covers packages, the Next.js and React providers, the JavaScript runtime, custom UI built on useConsentManager, callbacks, policies, stored consent and a self-hosted backend.
132
+ - [Migrate to v3](./upgrade-v3.md): Upgrade from c15t v2 to v3. Pick the guide for the v2 package you use (@c15t/nextjs, @c15t/react or the c15t store), rename @c15t/scripts, keep visitors' choices, and upgrade a self-hosted backend and the Node.js SDK.