@c15t/react 3.0.0-alpha.0 → 3.0.0-alpha.1
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.
- package/AGENTS.md +1 -0
- package/dist/iab/styles.tw3.css +4 -110
- package/dist/provider.js +1 -1
- package/dist/styles.tw3.css +4 -110
- package/dist/version.js +1 -1
- package/dist-types/provider.d.ts +6 -1
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +1 -0
- package/docs/frameworks/react/components/consent-manager-provider.md +9 -0
- package/docs/frameworks/react/script-loader.md +8 -0
- package/docs/frameworks/react/styling/overview.md +10 -0
- package/docs/integrations/clear-on-revocation.md +167 -0
- package/package.json +6 -6
package/AGENTS.md
CHANGED
|
@@ -61,6 +61,7 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
|
|
|
61
61
|
- [Ahrefs Analytics](./docs/integrations/ahrefs-analytics.md): Configure Ahrefs Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
62
62
|
- [Amplitude](./docs/integrations/amplitude.md): Configure Amplitude with c15t v3, understand measurement permission and verify loading and revocation.
|
|
63
63
|
- [Custom integrations](./docs/integrations/building-integrations.md): Define loading, initialization and consent-change behavior for a vendor without a helper.
|
|
64
|
+
- [Clear on revocation](./docs/integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
|
|
64
65
|
- [Clearbit](./docs/integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
|
|
65
66
|
- [Cloudflare Web Analytics](./docs/integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
66
67
|
- [Crisp](./docs/integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
|
package/dist/iab/styles.tw3.css
CHANGED
|
@@ -5,116 +5,10 @@
|
|
|
5
5
|
* nested package CSS imports still include the complete stylesheet.
|
|
6
6
|
*/
|
|
7
7
|
/* default theme tokens (generated from defaultTheme) */
|
|
8
|
-
:root, :
|
|
9
|
-
|
|
10
|
-
--c15t-border-hover: hsl(0, 0%,
|
|
11
|
-
|
|
12
|
-
--c15t-duration-normal: 150ms;
|
|
13
|
-
--c15t-duration-slow: 200ms;
|
|
14
|
-
--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
15
|
-
--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
16
|
-
--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
17
|
-
--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
18
|
-
--c15t-font-family: system-ui, -apple-system, sans-serif;
|
|
19
|
-
--c15t-font-size-base: 1rem;
|
|
20
|
-
--c15t-font-size-lg: 1.125rem;
|
|
21
|
-
--c15t-font-size-sm: 0.875rem;
|
|
22
|
-
--c15t-font-weight-medium: 500;
|
|
23
|
-
--c15t-font-weight-normal: 400;
|
|
24
|
-
--c15t-font-weight-semibold: 600;
|
|
25
|
-
--c15t-line-height-normal: 1.5;
|
|
26
|
-
--c15t-line-height-relaxed: 1.75;
|
|
27
|
-
--c15t-line-height-tight: 1.25;
|
|
28
|
-
--c15t-overlay: hsla(0, 0%, 0%, 0.5);
|
|
29
|
-
--c15t-primary: hsl(228, 100%, 60%);
|
|
30
|
-
--c15t-primary-hover: hsl(228, 100%, 55%);
|
|
31
|
-
--c15t-radius-full: 9999px;
|
|
32
|
-
--c15t-radius-lg: 0.75rem;
|
|
33
|
-
--c15t-radius-md: 0.5rem;
|
|
34
|
-
--c15t-radius-sm: 0.25rem;
|
|
35
|
-
--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);
|
|
36
|
-
--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);
|
|
37
|
-
--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);
|
|
38
|
-
--c15t-space-lg: 1.5rem;
|
|
39
|
-
--c15t-space-md: 1rem;
|
|
40
|
-
--c15t-space-sm: 0.5rem;
|
|
41
|
-
--c15t-space-xl: 2rem;
|
|
42
|
-
--c15t-space-xs: 0.25rem;
|
|
43
|
-
--c15t-surface: hsl(0, 0%, 100%);
|
|
44
|
-
--c15t-surface-hover: hsl(0, 0%, 98%);
|
|
45
|
-
--c15t-switch-thumb: hsl(0, 0%, 100%);
|
|
46
|
-
--c15t-switch-track: hsl(0, 0%, 85%);
|
|
47
|
-
--c15t-switch-track-active: hsl(228, 100%, 60%);
|
|
48
|
-
--c15t-text: hsl(0, 0%, 10%);
|
|
49
|
-
--c15t-text-muted: hsl(0, 0%, 40%);
|
|
50
|
-
--c15t-text-on-primary: hsl(0, 0%, 100%);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
:root.dark, :host(.dark), .dark .c15t-theme-root, :root.c15t-dark, :host(.c15t-dark), .c15t-dark .c15t-theme-root {
|
|
54
|
-
--c15t-border: hsl(0, 0%, 20%);
|
|
55
|
-
--c15t-border-hover: hsl(0, 0%, 25%);
|
|
56
|
-
--c15t-duration-fast: 80ms;
|
|
57
|
-
--c15t-duration-normal: 150ms;
|
|
58
|
-
--c15t-duration-slow: 200ms;
|
|
59
|
-
--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
60
|
-
--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
61
|
-
--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
62
|
-
--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
63
|
-
--c15t-font-family: system-ui, -apple-system, sans-serif;
|
|
64
|
-
--c15t-font-size-base: 1rem;
|
|
65
|
-
--c15t-font-size-lg: 1.125rem;
|
|
66
|
-
--c15t-font-size-sm: 0.875rem;
|
|
67
|
-
--c15t-font-weight-medium: 500;
|
|
68
|
-
--c15t-font-weight-normal: 400;
|
|
69
|
-
--c15t-font-weight-semibold: 600;
|
|
70
|
-
--c15t-line-height-normal: 1.5;
|
|
71
|
-
--c15t-line-height-relaxed: 1.75;
|
|
72
|
-
--c15t-line-height-tight: 1.25;
|
|
73
|
-
--c15t-overlay: hsla(0, 0%, 0%, 0.7);
|
|
74
|
-
--c15t-primary: hsl(228, 100%, 70%);
|
|
75
|
-
--c15t-primary-hover: hsl(228, 100%, 65%);
|
|
76
|
-
--c15t-radius-full: 9999px;
|
|
77
|
-
--c15t-radius-lg: 0.75rem;
|
|
78
|
-
--c15t-radius-md: 0.5rem;
|
|
79
|
-
--c15t-radius-sm: 0.25rem;
|
|
80
|
-
--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);
|
|
81
|
-
--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);
|
|
82
|
-
--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);
|
|
83
|
-
--c15t-space-lg: 1.5rem;
|
|
84
|
-
--c15t-space-md: 1rem;
|
|
85
|
-
--c15t-space-sm: 0.5rem;
|
|
86
|
-
--c15t-space-xl: 2rem;
|
|
87
|
-
--c15t-space-xs: 0.25rem;
|
|
88
|
-
--c15t-surface: hsl(0, 0%, 7%);
|
|
89
|
-
--c15t-surface-hover: hsl(0, 0%, 10%);
|
|
90
|
-
--c15t-switch-thumb: hsl(0, 0%, 93%);
|
|
91
|
-
--c15t-switch-track: hsl(0, 0%, 25%);
|
|
92
|
-
--c15t-switch-track-active: hsl(228, 100%, 70%);
|
|
93
|
-
--c15t-text: hsl(0, 0%, 93%);
|
|
94
|
-
--c15t-text-muted: hsl(0, 0%, 60%);
|
|
95
|
-
--c15t-text-on-primary: hsl(0, 0%, 100%);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/*
|
|
99
|
-
* Utility class to disable transitions during theme switching.
|
|
100
|
-
* Apply this class to the root element before switching themes,
|
|
101
|
-
* then remove it after a short delay to prevent flash of
|
|
102
|
-
* animated content during the color scheme change.
|
|
103
|
-
*
|
|
104
|
-
* Example usage:
|
|
105
|
-
* document.documentElement.classList.add('c15t-no-transitions');
|
|
106
|
-
* // Switch theme...
|
|
107
|
-
* requestAnimationFrame(() => {
|
|
108
|
-
* document.documentElement.classList.remove('c15t-no-transitions');
|
|
109
|
-
* });
|
|
110
|
-
*/
|
|
111
|
-
.c15t-no-transitions,
|
|
112
|
-
.c15t-no-transitions *,
|
|
113
|
-
.c15t-no-transitions *::before,
|
|
114
|
-
.c15t-no-transitions *::after {
|
|
115
|
-
transition: none !important;
|
|
116
|
-
animation: none !important;
|
|
117
|
-
}
|
|
8
|
+
:root,:host,.c15t-theme-root{--c15t-border: hsl(0, 0%, 90%);--c15t-border-hover: hsl(0, 0%, 85%);--c15t-duration-fast: 80ms;--c15t-duration-normal: 150ms;--c15t-duration-slow: 200ms;--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);--c15t-font-family: system-ui, -apple-system, sans-serif;--c15t-font-size-base: 1rem;--c15t-font-size-lg: 1.125rem;--c15t-font-size-sm: 0.875rem;--c15t-font-weight-medium: 500;--c15t-font-weight-normal: 400;--c15t-font-weight-semibold: 600;--c15t-line-height-normal: 1.5;--c15t-line-height-relaxed: 1.75;--c15t-line-height-tight: 1.25;--c15t-overlay: hsla(0, 0%, 0%, 0.5);--c15t-primary: hsl(228, 100%, 60%);--c15t-primary-hover: hsl(228, 100%, 55%);--c15t-radius-full: 9999px;--c15t-radius-lg: 0.75rem;--c15t-radius-md: 0.5rem;--c15t-radius-sm: 0.25rem;--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);--c15t-space-lg: 1.5rem;--c15t-space-md: 1rem;--c15t-space-sm: 0.5rem;--c15t-space-xl: 2rem;--c15t-space-xs: 0.25rem;--c15t-surface: hsl(0, 0%, 100%);--c15t-surface-hover: hsl(0, 0%, 98%);--c15t-switch-thumb: hsl(0, 0%, 100%);--c15t-switch-track: hsl(0, 0%, 85%);--c15t-switch-track-active: hsl(228, 100%, 60%);--c15t-text: hsl(0, 0%, 10%);--c15t-text-muted: hsl(0, 0%, 40%);--c15t-text-on-primary: hsl(0, 0%, 100%);}
|
|
9
|
+
|
|
10
|
+
:root.dark,:host(.dark),.dark .c15t-theme-root,:root.c15t-dark,:host(.c15t-dark),.c15t-dark .c15t-theme-root{--c15t-border: hsl(0, 0%, 20%);--c15t-border-hover: hsl(0, 0%, 25%);--c15t-duration-fast: 80ms;--c15t-duration-normal: 150ms;--c15t-duration-slow: 200ms;--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);--c15t-font-family: system-ui, -apple-system, sans-serif;--c15t-font-size-base: 1rem;--c15t-font-size-lg: 1.125rem;--c15t-font-size-sm: 0.875rem;--c15t-font-weight-medium: 500;--c15t-font-weight-normal: 400;--c15t-font-weight-semibold: 600;--c15t-line-height-normal: 1.5;--c15t-line-height-relaxed: 1.75;--c15t-line-height-tight: 1.25;--c15t-overlay: hsla(0, 0%, 0%, 0.7);--c15t-primary: hsl(228, 100%, 70%);--c15t-primary-hover: hsl(228, 100%, 65%);--c15t-radius-full: 9999px;--c15t-radius-lg: 0.75rem;--c15t-radius-md: 0.5rem;--c15t-radius-sm: 0.25rem;--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);--c15t-space-lg: 1.5rem;--c15t-space-md: 1rem;--c15t-space-sm: 0.5rem;--c15t-space-xl: 2rem;--c15t-space-xs: 0.25rem;--c15t-surface: hsl(0, 0%, 7%);--c15t-surface-hover: hsl(0, 0%, 10%);--c15t-switch-thumb: hsl(0, 0%, 93%);--c15t-switch-track: hsl(0, 0%, 25%);--c15t-switch-track-active: hsl(228, 100%, 70%);--c15t-text: hsl(0, 0%, 93%);--c15t-text-muted: hsl(0, 0%, 60%);--c15t-text-on-primary: hsl(0, 0%, 100%);}
|
|
11
|
+
.c15t-no-transitions,.c15t-no-transitions *,.c15t-no-transitions *::before,.c15t-no-transitions *::after{transition: none !important;animation: none !important;}
|
|
118
12
|
|
|
119
13
|
/* primitives/button vars */
|
|
120
14
|
:root, :host{--button-primary:var(--c15t-primary);--button-primary-dark:var(--c15t-primary);--button-primary-hover:var(--c15t-primary-hover);--button-primary-hover-dark:var(--c15t-primary-hover);--button-neutral:var(--c15t-text-muted);--button-neutral-dark:var(--c15t-text-muted);--button-neutral-hover:var(--c15t-text);--button-neutral-hover-dark:var(--c15t-text);--button-neutral-soft:var(--c15t-surface-hover);--button-neutral-soft-dark:var(--c15t-surface-hover);--button-focus-ring:var(--c15t-primary);--button-focus-ring-dark:var(--c15t-primary);--button-text:var(--c15t-text);--button-text-dark:var(--c15t-text);--button-text-hover:var(--c15t-text);--button-text-hover-dark:var(--c15t-text);--button-background-color:var(--c15t-surface);--button-background-color-dark:var(--c15t-surface);--button-border:var(--c15t-border);--button-border-dark:var(--c15t-border);--button-hover-overlay:var(--c15t-surface-hover);--button-hover-overlay-dark:var(--c15t-surface-hover);--button-primary-hover-tint:color-mix(in srgb, var(--c15t-primary) 10%, transparent);--button-neutral-hover-tint:color-mix(in srgb, var(--c15t-text) 10%, transparent);--button-font:var(--c15t-font-family);--button-border-width:1px;--button-border-style:solid;--button-border-color:var(--c15t-border);--button-border-radius:var(--c15t-radius-md);--button-font-weight:var(--c15t-font-weight-medium);--button-font-size:var(--c15t-font-size-sm);--button-line-height:var(--c15t-line-height-tight);--button-transition:opacity var(--c15t-duration-fast) var(--c15t-easing), transform var(--c15t-duration-fast) var(--c15t-easing);--button-hover-transition-color:background-color var(--c15t-duration-fast) var(--c15t-easing);--button-hover-transition-full:background-color var(--c15t-duration-fast) var(--c15t-easing), box-shadow var(--c15t-duration-fast) var(--c15t-easing), color var(--c15t-duration-fast) var(--c15t-easing);--button-cursor:pointer;--button-shadow:var(--c15t-shadow-sm);--button-shadow-dark:var(--c15t-shadow-sm);--button-shadow-primary-focus:0 0 0 2px var(--button-focus-ring);--button-shadow-neutral-focus:0 0 0 2px var(--button-focus-ring);--button-shadow-primary-focus-dark:0 0 0 2px var(--button-focus-ring-dark);--button-shadow-neutral-focus-dark:0 0 0 2px var(--button-focus-ring-dark);--button-shadow-primary:var(--button-shadow), inset 0 0 0 1px var(--button-primary);--button-shadow-primary-dark:var(--button-shadow-dark), inset 0 0 0 1px var(--button-primary-dark);--button-shadow-primary-hover:none;--button-shadow-primary-hover-dark:none;--button-shadow-neutral:var(--button-shadow), inset 0 0 0 1px var(--button-neutral-soft);--button-shadow-neutral-dark:var(--button-shadow-dark), inset 0 0 0 1px var(--button-neutral-soft-dark);--button-shadow-neutral-hover:none;--button-shadow-neutral-hover-dark:none}
|
package/dist/provider.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{Fragment as e,jsx as r,jsxs as n}from"react/jsx-runtime";import{createConsentKernel as t,kernelConfigToInitResponse as i}from"@c15t/core";import{createWindowDebug as o,resolveWindowDebugMode as l}from"@c15t/core/modules/window-debug";import{resolvePolicyRules as
|
|
2
|
+
import{Fragment as e,jsx as r,jsxs as n}from"react/jsx-runtime";import{createConsentKernel as t,kernelConfigToInitResponse as i}from"@c15t/core";import{createWindowDebug as o,resolveWindowDebugMode as l}from"@c15t/core/modules/window-debug";import{resolvePolicyRules as c}from"@c15t/schema/types";import{deepMergeTranslations as s}from"@c15t/translations";import{defaultTheme as u,generateThemeCSS as a}from"@c15t/ui/theme";import{Suspense as d,lazy as f,useContext as m,useEffect as p,useMemo as g,useRef as v,useState as h}from"react";import{KernelContext as y,ProviderServicesContext as k}from"./context.js";import{useColorScheme as b}from"./hooks/use-color-scheme.js";import{usePersistence as R}from"./module-hooks/persistence.js";import{V3ThemeProvider as C}from"./theme-provider.js";import{defaultTranslationConfig as S}from"./utils/default-translation-config.js";let P=f(async()=>({default:(await import("./external-iab-context.js")).ExternalIABProvider})),w=c({countryCode:null,regionCode:null,rules:[{id:"disabled",match:{fallback:!0},model:"opt-out",prompt:"none"}]}),O={language:"en",translations:S.translations.en},x=function(e){if(e)return"externalId"in e?e:{externalId:e.id,identityProvider:e.identityProvider}},j=function(e){if(!e?.messages)return;let r=e.locale??S.defaultLanguage??"en",n=S.translations.en,t=e.messages[r]??e.messages.en??n,i=S.translations[r]??n;return{language:r,translations:s(i,t)}},K=function(e){return e.enabled??!0},E=function(e,r){let n=!1;return{...e,async init(t){if(n)return e.init?.(t)??{};n=!0;let i=await r(t);return i.response?i.response:e.init?.(i.context??t)??{}}}},L=function(e){return"function"==typeof e?.then},N=function(e){let{prefetch:r}=e;return!r||L(r)?{}:r},D=function(e){return void 0!==e&&Object.keys(e).length>0},_=function(e){"production"!==globalThis.process?.env?.NODE_ENV&&console.warn("c15t ConsentProvider: prefetch rejected; using transport init.",e)},q=function(e,r,n,t){let i={...r.initialOverrides??{},...n??{}};D(i)&&e.set.overrides(i),r.initialRecords&&e.getRecordsGeneration()===t&&e.hydrate(r.initialRecords)},A=function(e,r,n){var t,o;let{prefetch:l}=r;return L(l)?E(e,(t=Promise.resolve(l),o=r.overrides,async e=>{let r,l=n()?.getRecordsGeneration();try{r=await t??{}}catch(e){return _(e),{}}let c=i(r);if(c){let e={...c.resolvedOverrides??{},...o??{}};return D(e)&&(c.resolvedOverrides=e),{response:c}}let s=n();return s&&q(s,r,o,l),{context:{overrides:{...e.overrides,...r.initialOverrides??{},...o??{}},user:e.user}}})):e},B=function(e){if("function"!=typeof e.mode)throw Error("c15t ConsentProvider: set mode to hosted(), offline(), or custom().");return e.mode},I=function(e){let r=K(e),n=N(e),i=j(e.i18n)??O,o={consentCategories:e.consentCategories,prefetch:n,translations:i},l=B(e)(o),c={current:null},s=A(l,e,()=>c.current),u=t({...n,initialRecords:r?n.initialRecords:void 0,initialPrivacySignals:r?n.initialPrivacySignals:void 0,now:n.now??n.initialRecords?.now??(n.initialRecords?void 0:0),transport:s,initialPolicyResolution:r?n.initialPolicyResolution:w,initialOverrides:{...n.initialOverrides??{},...e.overrides??{}},initialUser:x(e.user)??n.initialUser,initialTranslations:n.initialTranslations??i,initialPolicyPending:n.initialPolicyPending??(r&&!n.initialPolicyResolution)});return c.current=u,u},T=function(e){if(e instanceof Error)return e.message;if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}},H=function(e,r){let n=v(r);p(()=>{n.current=r},[r]),p(()=>{let r=[e.events.on("choice:recorded",({snapshot:e,confirmed:r,actionAt:t})=>{n.current?.onChoiceRecorded?.({actionAt:t,confirmed:r,snapshot:e})}),e.events.on("permissions:changed",({snapshot:e,previous:r})=>{n.current?.onPermissionsChanged?.({previous:r,snapshot:e})}),e.events.on("command:error",e=>{n.current?.onError?.({error:T(e.error)})})];return()=>{for(let e of r)e()}},[e])},J=function(e,r,n,t){let i=v(n),o=v(null),l=v(null),c=v(null);p(()=>{if(!t)return;let n=x(r.user),i=JSON.stringify(n??null);if(null===o.current){o.current=i;return}o.current!==i&&(o.current=i,n&&(async()=>{try{await e.commands.identify(n)}catch{}})())},[e,r.user,t]),p(()=>{if(!t)return;let i=JSON.stringify(r.overrides??{});if(null===l.current){l.current=i;return}l.current!==i&&(l.current=i,e.set.overrides(r.overrides??{}),n&&e.commands.init())},[n,e,r.overrides,t]),p(()=>{!t||i.current===n||(i.current=n,n||e.set.activeUI("none"))},[n,e,t]),p(()=>{if("production"===globalThis.process?.env?.NODE_ENV)return;let e=JSON.stringify({i18n:r.i18n,mode:r.mode?.kind});if(null===c.current){c.current=e;return}c.current!==e&&(c.current=e,console.warn("c15t ConsentProvider: remount to change mode or i18n."))},[r])},F=({kernel:e,callbacks:r})=>(H(e,r),null),U=({enabled:e,kernel:r,prepared:n})=>{let t=v(!1),i=v(!1);return p(()=>{if(!e){t.current=!1;return}if(!t.current)if(t.current=!0,n){r.hydrate({now:i.current?Date.now():r.getServerSnapshot().evaluatedAt}),i.current=!0;let{gpc:e}=r.getSnapshot().privacySignals;e.detected&&e.active&&r.set.privacySignals({gpc:!0})}else r.commands.init()},[e,r,n]),null},G=[],M=({clearOnRevocation:e,storageConfig:r,nonce:n,options:t,scripts:i=G})=>{let o=m(y),l=v(null),c=v(null),s=v(null),u=v({config:e,storageConfig:r}),[a,d]=h(i.length>0),f=v(i),g=v(t),k=v(n);i.length>0&&!a&&d(!0),p(()=>{u.current={config:e,storageConfig:r},f.current=i,g.current=t,k.current=n},[e,r,n,t,i]),p(()=>{if(!o)return;let e=!1;return(async()=>{if(a){let{createScriptLoader:r}=await import("@c15t/core/modules/script-loader");if(e)return;l.current=r({kernel:o,nonce:k.current,onDebug:g.current?.onDebug,scripts:f.current})}let{config:r}=u.current;if(r){let{createClearOnRevocation:n}=await import("@c15t/core/modules/clear-on-revocation");if(e)return;s.current={config:r,create:n},c.current=n({config:r,kernel:o,storageConfig:u.current.storageConfig})}})(),()=>{e=!0,c.current?.dispose(),c.current=null,s.current=null,l.current?.dispose(),l.current=null}},[o,a]);let b=r?.storageKey;return p(()=>{let e=s.current;o&&e&&(c.current?.dispose(),c.current=e.create({config:e.config,kernel:o,storageConfig:{storageKey:b}}))},[o,b]),p(()=>{l.current?.updateScripts(i)},[i]),null},V=({options:e})=>{let r=m(y),n=v(null),t=v(e);return p(()=>{t.current=e},[e]),p(()=>{if(!r)return;let e=!1;return(async()=>{let{createNetworkBlocker:i}=await import("@c15t/core/modules/network-blocker");if(e)return;let o=t.current;n.current=i({enabled:o.enabled,kernel:r,logBlockedRequests:o.logBlockedRequests,onRequestBlocked:o.onRequestBlocked,rules:o.rules})})(),()=>{e=!0,n.current?.dispose(),n.current=null}},[r]),p(()=>{n.current?.updateRules(e.rules)},[e.rules]),p(()=>{void 0!==e.enabled&&n.current?.setEnabled(e.enabled)},[e.enabled]),null},z=({options:e,clearRef:r})=>{let n=R(e);return p(()=>(r.current=n.clear,()=>{r.current=null}),[n,r]),null},Q=({pkg:e,mode:r})=>(p(()=>{let n=o({mode:r,pkg:e});return()=>n.dispose()},[r,e]),null),W=({kernel:e})=>(p(()=>{let r=window,n=r.c15tKernel;return r.c15tKernel=e,()=>{if(r.c15tKernel===e){if(n){r.c15tKernel=n;return}delete r.c15tKernel}}},[e]),null),X=function(e){if(!1===e.persistence)return!1;let{storageConfig:r}=e,n=!!N(e).initialRecords;return!0===e.persistence||void 0===e.persistence?{skipHydration:n,storageConfig:r}:{...e.persistence,skipHydration:e.persistence.skipHydration??n,storageConfig:e.persistence.storageConfig??r}},Y=t=>{let{children:i}=t,o=t.options??{},c=K(o),[s,f]=h(()=>({clearOnRevocation:o.clearOnRevocation,disabledKernel:t.runtime?void 0:I({...o,enabled:!1}),external:t.runtime,kernel:t.runtime?.kernel??I({...o,enabled:!0})})),{clearOnRevocation:m,external:R}=s,S=c?s.kernel:s.disabledKernel??s.kernel,w=void 0===R,O=v(null),x=g(()=>({clearRecords:()=>{R?R.clearRecords():O.current?O.current():(S.hydrate({choice:null,noticeDismissal:null,optOutDirectives:[],subject:null}),S.events.emit({type:"records:cleared"}))},getConsentCategories:()=>{let{scope:e}=S.getSnapshot().policyRule,r=o.consentCategories;return["necessary",...e.filter(e=>!r?.length||r.includes(e))]},getPresentation:()=>o.presentation}),[S,o.consentCategories,o.presentation,R]),j=X(o),{scripts:E,networkBlocker:L}=o,D=o.__debugPkg??"@c15t/react",_=w?l(o.mode):"hosted";J(s.kernel,o,c,w);let q=v(0);p(()=>{if(!w)return;q.current+=1;let e=q.current;return()=>{queueMicrotask(()=>{q.current===e&&(s.kernel.dispose(),s.disabledKernel?.dispose())})}},[s,w]);let A=o.theme,B=g(()=>a(A??u,o.colorScheme).replace(/</gu,"\\3c "),[A,o.colorScheme]),T=g(()=>({colorScheme:o.colorScheme,disableAnimation:o.disableAnimation,noStyle:o.noStyle,scrollLock:o.scrollLock,theme:A,trapFocus:o.trapFocus}),[A,o.noStyle,o.disableAnimation,o.scrollLock,o.trapFocus,o.colorScheme]),H=g(()=>({components:o.components,legalLinks:o.legalLinks,presentation:o.presentation}),[o.components,o.legalLinks,o.presentation]);b(o.colorScheme);let G=n(e,{children:[w?n(e,{children:[r(F,{kernel:S,callbacks:o.callbacks}),r(Q,{pkg:D,mode:_}),r(W,{kernel:S}),c&&j?r(z,{options:j,clearRef:O}):null,r(U,{enabled:c,prepared:!!N(o).initialPolicyResolution,kernel:S}),E&&E.length>0||c&&m?r(M,{clearOnRevocation:c?m:void 0,storageConfig:j?j.storageConfig:o.storageConfig,nonce:o.nonce,options:o.scriptLoader,scripts:E}):null,c&&L?r(V,{options:L}):null]}):null,R?r(d,{fallback:i,children:r(P,{runtime:R,children:i})}):i]});return r(y.Provider,{value:S,children:r(k.Provider,{value:x,children:n(C,{themeConfig:T,uiConfig:H,children:[r("style",{id:"c15t-theme",nonce:o.nonce,dangerouslySetInnerHTML:{__html:B}}),G]})})})};export{Y as ConsentProvider};
|
package/dist/styles.tw3.css
CHANGED
|
@@ -5,116 +5,10 @@
|
|
|
5
5
|
* nested package CSS imports still include the complete stylesheet.
|
|
6
6
|
*/
|
|
7
7
|
/* default theme tokens (generated from defaultTheme) */
|
|
8
|
-
:root, :
|
|
9
|
-
|
|
10
|
-
--c15t-border-hover: hsl(0, 0%,
|
|
11
|
-
|
|
12
|
-
--c15t-duration-normal: 150ms;
|
|
13
|
-
--c15t-duration-slow: 200ms;
|
|
14
|
-
--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
15
|
-
--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
16
|
-
--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
17
|
-
--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
18
|
-
--c15t-font-family: system-ui, -apple-system, sans-serif;
|
|
19
|
-
--c15t-font-size-base: 1rem;
|
|
20
|
-
--c15t-font-size-lg: 1.125rem;
|
|
21
|
-
--c15t-font-size-sm: 0.875rem;
|
|
22
|
-
--c15t-font-weight-medium: 500;
|
|
23
|
-
--c15t-font-weight-normal: 400;
|
|
24
|
-
--c15t-font-weight-semibold: 600;
|
|
25
|
-
--c15t-line-height-normal: 1.5;
|
|
26
|
-
--c15t-line-height-relaxed: 1.75;
|
|
27
|
-
--c15t-line-height-tight: 1.25;
|
|
28
|
-
--c15t-overlay: hsla(0, 0%, 0%, 0.5);
|
|
29
|
-
--c15t-primary: hsl(228, 100%, 60%);
|
|
30
|
-
--c15t-primary-hover: hsl(228, 100%, 55%);
|
|
31
|
-
--c15t-radius-full: 9999px;
|
|
32
|
-
--c15t-radius-lg: 0.75rem;
|
|
33
|
-
--c15t-radius-md: 0.5rem;
|
|
34
|
-
--c15t-radius-sm: 0.25rem;
|
|
35
|
-
--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);
|
|
36
|
-
--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);
|
|
37
|
-
--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);
|
|
38
|
-
--c15t-space-lg: 1.5rem;
|
|
39
|
-
--c15t-space-md: 1rem;
|
|
40
|
-
--c15t-space-sm: 0.5rem;
|
|
41
|
-
--c15t-space-xl: 2rem;
|
|
42
|
-
--c15t-space-xs: 0.25rem;
|
|
43
|
-
--c15t-surface: hsl(0, 0%, 100%);
|
|
44
|
-
--c15t-surface-hover: hsl(0, 0%, 98%);
|
|
45
|
-
--c15t-switch-thumb: hsl(0, 0%, 100%);
|
|
46
|
-
--c15t-switch-track: hsl(0, 0%, 85%);
|
|
47
|
-
--c15t-switch-track-active: hsl(228, 100%, 60%);
|
|
48
|
-
--c15t-text: hsl(0, 0%, 10%);
|
|
49
|
-
--c15t-text-muted: hsl(0, 0%, 40%);
|
|
50
|
-
--c15t-text-on-primary: hsl(0, 0%, 100%);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
:root.dark, :host(.dark), .dark .c15t-theme-root, :root.c15t-dark, :host(.c15t-dark), .c15t-dark .c15t-theme-root {
|
|
54
|
-
--c15t-border: hsl(0, 0%, 20%);
|
|
55
|
-
--c15t-border-hover: hsl(0, 0%, 25%);
|
|
56
|
-
--c15t-duration-fast: 80ms;
|
|
57
|
-
--c15t-duration-normal: 150ms;
|
|
58
|
-
--c15t-duration-slow: 200ms;
|
|
59
|
-
--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
60
|
-
--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
61
|
-
--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);
|
|
62
|
-
--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
63
|
-
--c15t-font-family: system-ui, -apple-system, sans-serif;
|
|
64
|
-
--c15t-font-size-base: 1rem;
|
|
65
|
-
--c15t-font-size-lg: 1.125rem;
|
|
66
|
-
--c15t-font-size-sm: 0.875rem;
|
|
67
|
-
--c15t-font-weight-medium: 500;
|
|
68
|
-
--c15t-font-weight-normal: 400;
|
|
69
|
-
--c15t-font-weight-semibold: 600;
|
|
70
|
-
--c15t-line-height-normal: 1.5;
|
|
71
|
-
--c15t-line-height-relaxed: 1.75;
|
|
72
|
-
--c15t-line-height-tight: 1.25;
|
|
73
|
-
--c15t-overlay: hsla(0, 0%, 0%, 0.7);
|
|
74
|
-
--c15t-primary: hsl(228, 100%, 70%);
|
|
75
|
-
--c15t-primary-hover: hsl(228, 100%, 65%);
|
|
76
|
-
--c15t-radius-full: 9999px;
|
|
77
|
-
--c15t-radius-lg: 0.75rem;
|
|
78
|
-
--c15t-radius-md: 0.5rem;
|
|
79
|
-
--c15t-radius-sm: 0.25rem;
|
|
80
|
-
--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);
|
|
81
|
-
--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);
|
|
82
|
-
--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);
|
|
83
|
-
--c15t-space-lg: 1.5rem;
|
|
84
|
-
--c15t-space-md: 1rem;
|
|
85
|
-
--c15t-space-sm: 0.5rem;
|
|
86
|
-
--c15t-space-xl: 2rem;
|
|
87
|
-
--c15t-space-xs: 0.25rem;
|
|
88
|
-
--c15t-surface: hsl(0, 0%, 7%);
|
|
89
|
-
--c15t-surface-hover: hsl(0, 0%, 10%);
|
|
90
|
-
--c15t-switch-thumb: hsl(0, 0%, 93%);
|
|
91
|
-
--c15t-switch-track: hsl(0, 0%, 25%);
|
|
92
|
-
--c15t-switch-track-active: hsl(228, 100%, 70%);
|
|
93
|
-
--c15t-text: hsl(0, 0%, 93%);
|
|
94
|
-
--c15t-text-muted: hsl(0, 0%, 60%);
|
|
95
|
-
--c15t-text-on-primary: hsl(0, 0%, 100%);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/*
|
|
99
|
-
* Utility class to disable transitions during theme switching.
|
|
100
|
-
* Apply this class to the root element before switching themes,
|
|
101
|
-
* then remove it after a short delay to prevent flash of
|
|
102
|
-
* animated content during the color scheme change.
|
|
103
|
-
*
|
|
104
|
-
* Example usage:
|
|
105
|
-
* document.documentElement.classList.add('c15t-no-transitions');
|
|
106
|
-
* // Switch theme...
|
|
107
|
-
* requestAnimationFrame(() => {
|
|
108
|
-
* document.documentElement.classList.remove('c15t-no-transitions');
|
|
109
|
-
* });
|
|
110
|
-
*/
|
|
111
|
-
.c15t-no-transitions,
|
|
112
|
-
.c15t-no-transitions *,
|
|
113
|
-
.c15t-no-transitions *::before,
|
|
114
|
-
.c15t-no-transitions *::after {
|
|
115
|
-
transition: none !important;
|
|
116
|
-
animation: none !important;
|
|
117
|
-
}
|
|
8
|
+
:root,:host,.c15t-theme-root{--c15t-border: hsl(0, 0%, 90%);--c15t-border-hover: hsl(0, 0%, 85%);--c15t-duration-fast: 80ms;--c15t-duration-normal: 150ms;--c15t-duration-slow: 200ms;--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);--c15t-font-family: system-ui, -apple-system, sans-serif;--c15t-font-size-base: 1rem;--c15t-font-size-lg: 1.125rem;--c15t-font-size-sm: 0.875rem;--c15t-font-weight-medium: 500;--c15t-font-weight-normal: 400;--c15t-font-weight-semibold: 600;--c15t-line-height-normal: 1.5;--c15t-line-height-relaxed: 1.75;--c15t-line-height-tight: 1.25;--c15t-overlay: hsla(0, 0%, 0%, 0.5);--c15t-primary: hsl(228, 100%, 60%);--c15t-primary-hover: hsl(228, 100%, 55%);--c15t-radius-full: 9999px;--c15t-radius-lg: 0.75rem;--c15t-radius-md: 0.5rem;--c15t-radius-sm: 0.25rem;--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);--c15t-space-lg: 1.5rem;--c15t-space-md: 1rem;--c15t-space-sm: 0.5rem;--c15t-space-xl: 2rem;--c15t-space-xs: 0.25rem;--c15t-surface: hsl(0, 0%, 100%);--c15t-surface-hover: hsl(0, 0%, 98%);--c15t-switch-thumb: hsl(0, 0%, 100%);--c15t-switch-track: hsl(0, 0%, 85%);--c15t-switch-track-active: hsl(228, 100%, 60%);--c15t-text: hsl(0, 0%, 10%);--c15t-text-muted: hsl(0, 0%, 40%);--c15t-text-on-primary: hsl(0, 0%, 100%);}
|
|
9
|
+
|
|
10
|
+
:root.dark,:host(.dark),.dark .c15t-theme-root,:root.c15t-dark,:host(.c15t-dark),.c15t-dark .c15t-theme-root{--c15t-border: hsl(0, 0%, 20%);--c15t-border-hover: hsl(0, 0%, 25%);--c15t-duration-fast: 80ms;--c15t-duration-normal: 150ms;--c15t-duration-slow: 200ms;--c15t-easing: cubic-bezier(0.4, 0, 0.2, 1);--c15t-easing-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);--c15t-easing-out: cubic-bezier(0.215, 0.61, 0.355, 1);--c15t-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);--c15t-font-family: system-ui, -apple-system, sans-serif;--c15t-font-size-base: 1rem;--c15t-font-size-lg: 1.125rem;--c15t-font-size-sm: 0.875rem;--c15t-font-weight-medium: 500;--c15t-font-weight-normal: 400;--c15t-font-weight-semibold: 600;--c15t-line-height-normal: 1.5;--c15t-line-height-relaxed: 1.75;--c15t-line-height-tight: 1.25;--c15t-overlay: hsla(0, 0%, 0%, 0.7);--c15t-primary: hsl(228, 100%, 70%);--c15t-primary-hover: hsl(228, 100%, 65%);--c15t-radius-full: 9999px;--c15t-radius-lg: 0.75rem;--c15t-radius-md: 0.5rem;--c15t-radius-sm: 0.25rem;--c15t-shadow-lg: 0 8px 24px hsla(0, 0%, 0%, 0.12);--c15t-shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);--c15t-shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);--c15t-space-lg: 1.5rem;--c15t-space-md: 1rem;--c15t-space-sm: 0.5rem;--c15t-space-xl: 2rem;--c15t-space-xs: 0.25rem;--c15t-surface: hsl(0, 0%, 7%);--c15t-surface-hover: hsl(0, 0%, 10%);--c15t-switch-thumb: hsl(0, 0%, 93%);--c15t-switch-track: hsl(0, 0%, 25%);--c15t-switch-track-active: hsl(228, 100%, 70%);--c15t-text: hsl(0, 0%, 93%);--c15t-text-muted: hsl(0, 0%, 60%);--c15t-text-on-primary: hsl(0, 0%, 100%);}
|
|
11
|
+
.c15t-no-transitions,.c15t-no-transitions *,.c15t-no-transitions *::before,.c15t-no-transitions *::after{transition: none !important;animation: none !important;}
|
|
118
12
|
|
|
119
13
|
/* primitives/button vars */
|
|
120
14
|
:root, :host{--button-primary:var(--c15t-primary);--button-primary-dark:var(--c15t-primary);--button-primary-hover:var(--c15t-primary-hover);--button-primary-hover-dark:var(--c15t-primary-hover);--button-neutral:var(--c15t-text-muted);--button-neutral-dark:var(--c15t-text-muted);--button-neutral-hover:var(--c15t-text);--button-neutral-hover-dark:var(--c15t-text);--button-neutral-soft:var(--c15t-surface-hover);--button-neutral-soft-dark:var(--c15t-surface-hover);--button-focus-ring:var(--c15t-primary);--button-focus-ring-dark:var(--c15t-primary);--button-text:var(--c15t-text);--button-text-dark:var(--c15t-text);--button-text-hover:var(--c15t-text);--button-text-hover-dark:var(--c15t-text);--button-background-color:var(--c15t-surface);--button-background-color-dark:var(--c15t-surface);--button-border:var(--c15t-border);--button-border-dark:var(--c15t-border);--button-hover-overlay:var(--c15t-surface-hover);--button-hover-overlay-dark:var(--c15t-surface-hover);--button-primary-hover-tint:color-mix(in srgb, var(--c15t-primary) 10%, transparent);--button-neutral-hover-tint:color-mix(in srgb, var(--c15t-text) 10%, transparent);--button-font:var(--c15t-font-family);--button-border-width:1px;--button-border-style:solid;--button-border-color:var(--c15t-border);--button-border-radius:var(--c15t-radius-md);--button-font-weight:var(--c15t-font-weight-medium);--button-font-size:var(--c15t-font-size-sm);--button-line-height:var(--c15t-line-height-tight);--button-transition:opacity var(--c15t-duration-fast) var(--c15t-easing), transform var(--c15t-duration-fast) var(--c15t-easing);--button-hover-transition-color:background-color var(--c15t-duration-fast) var(--c15t-easing);--button-hover-transition-full:background-color var(--c15t-duration-fast) var(--c15t-easing), box-shadow var(--c15t-duration-fast) var(--c15t-easing), color var(--c15t-duration-fast) var(--c15t-easing);--button-cursor:pointer;--button-shadow:var(--c15t-shadow-sm);--button-shadow-dark:var(--c15t-shadow-sm);--button-shadow-primary-focus:0 0 0 2px var(--button-focus-ring);--button-shadow-neutral-focus:0 0 0 2px var(--button-focus-ring);--button-shadow-primary-focus-dark:0 0 0 2px var(--button-focus-ring-dark);--button-shadow-neutral-focus-dark:0 0 0 2px var(--button-focus-ring-dark);--button-shadow-primary:var(--button-shadow), inset 0 0 0 1px var(--button-primary);--button-shadow-primary-dark:var(--button-shadow-dark), inset 0 0 0 1px var(--button-primary-dark);--button-shadow-primary-hover:none;--button-shadow-primary-hover-dark:none;--button-shadow-neutral:var(--button-shadow), inset 0 0 0 1px var(--button-neutral-soft);--button-shadow-neutral-dark:var(--button-shadow-dark), inset 0 0 0 1px var(--button-neutral-soft-dark);--button-shadow-neutral-hover:none;--button-shadow-neutral-hover-dark:none}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let e="3.0.0-alpha.
|
|
1
|
+
let e="3.0.0-alpha.1";export{e as version};
|
package/dist-types/provider.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AllConsentNames, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User } from '@c15t/core';
|
|
1
|
+
import type { AllConsentNames, ClearOnRevocationConfig, ConsentPresentation, Callbacks, I18nConfig, KernelConfig, KernelOverrides, KernelUser, LegalLinks, ProviderTransportFactory, StorageConfig, User } from '@c15t/core';
|
|
2
2
|
import type { Script } from '@c15t/core/modules/script-loader';
|
|
3
3
|
import type { ConsentRuntime } from '@c15t/core/runtime';
|
|
4
4
|
import type { ReactNode } from 'react';
|
|
@@ -77,6 +77,11 @@ export interface ConsentProviderOptions extends Pick<ReactUIOptions, 'colorSchem
|
|
|
77
77
|
*/
|
|
78
78
|
prefetch?: ConsentProviderPrefetch | Promise<ConsentProviderPrefetch>;
|
|
79
79
|
callbacks?: ConsentProviderCallbacks;
|
|
80
|
+
/**
|
|
81
|
+
* Remove configured browser data when its consent permission is revoked.
|
|
82
|
+
* Initial-only: remount the provider to replace its cleanup configuration.
|
|
83
|
+
*/
|
|
84
|
+
clearOnRevocation?: ClearOnRevocationConfig;
|
|
80
85
|
scripts?: Script[];
|
|
81
86
|
scriptLoader?: UseScriptLoaderOptions;
|
|
82
87
|
networkBlocker?: UseNetworkBlockerOptions | false;
|
package/dist-types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "3.0.0-alpha.
|
|
1
|
+
export declare const version = "3.0.0-alpha.1";
|
package/docs/README.md
CHANGED
|
@@ -61,6 +61,7 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
|
|
|
61
61
|
- [Ahrefs Analytics](./integrations/ahrefs-analytics.md): Configure Ahrefs Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
62
62
|
- [Amplitude](./integrations/amplitude.md): Configure Amplitude with c15t v3, understand measurement permission and verify loading and revocation.
|
|
63
63
|
- [Custom integrations](./integrations/building-integrations.md): Define loading, initialization and consent-change behavior for a vendor without a helper.
|
|
64
|
+
- [Clear on revocation](./integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
|
|
64
65
|
- [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
|
|
65
66
|
- [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
66
67
|
- [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
|
|
@@ -60,3 +60,12 @@ An externally owned runtime can be passed through `runtime`. Its owner must
|
|
|
60
60
|
start and dispose it. A provider borrowing that runtime must not initialize or
|
|
61
61
|
dispose a second copy. See [consent state](../../../guides/consent-state.md) and
|
|
62
62
|
[deployment modes](../../../guides/deployment-modes.md).
|
|
63
|
+
|
|
64
|
+
## Clear data when consent is denied
|
|
65
|
+
|
|
66
|
+
Set `options.clearOnRevocation` to declare cookies, localStorage keys, and
|
|
67
|
+
sessionStorage keys by optional consent category. Cleanup waits for policy
|
|
68
|
+
resolution, then clears denied categories and later allowed-to-denied
|
|
69
|
+
transitions. This option is initial-only. See
|
|
70
|
+
[clear on revocation](../../../integrations/clear-on-revocation.md) for examples,
|
|
71
|
+
cookie scopes, and browser limits.
|
|
@@ -53,3 +53,11 @@ Use [custom integrations](../../integrations/building-integrations.md) for an
|
|
|
53
53
|
unlisted vendor and [verification](../../guides/verify-consent.md) for the network
|
|
54
54
|
checks. Google helpers have a separate
|
|
55
55
|
[Consent Mode contract](../../integrations/google-tag-manager.md).
|
|
56
|
+
|
|
57
|
+
## Clear stored tracking data
|
|
58
|
+
|
|
59
|
+
Script gating does not remove cookies or Web Storage entries that a script
|
|
60
|
+
already wrote. Add `clearOnRevocation` to `ConsentProvider.options` to remove
|
|
61
|
+
declared data when its category is denied. See
|
|
62
|
+
[clear on revocation](../../integrations/clear-on-revocation.md) for configuration
|
|
63
|
+
and browser limits.
|
|
@@ -37,6 +37,16 @@ Colors, radii, shadows, typography, and motion come from `--c15t-*` custom
|
|
|
37
37
|
properties. Set them on the provider through `theme`, or override the
|
|
38
38
|
variables directly in your CSS.
|
|
39
39
|
|
|
40
|
+
React and Next.js render the theme stylesheet in the server HTML before
|
|
41
|
+
the banner. Pass the same theme on the server and the first client render
|
|
42
|
+
so your custom tokens apply before hydration. The provider's `nonce`
|
|
43
|
+
option also applies to this stylesheet for Content Security Policy.
|
|
44
|
+
|
|
45
|
+
`colorScheme: 'dark'` applies dark tokens in the server HTML.
|
|
46
|
+
`colorScheme: 'system'` uses a CSS media query to follow the visitor's
|
|
47
|
+
preference before hydration. If your app manages dark mode through a
|
|
48
|
+
root class instead, include that class in the server HTML too.
|
|
49
|
+
|
|
40
50
|
```tsx
|
|
41
51
|
import { ConsentProvider, defineTheme } from 'c15t/react';
|
|
42
52
|
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Clear on revocation
|
|
3
|
+
description: Remove configured first-party cookies and Web Storage keys when
|
|
4
|
+
their consent category is denied.
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Configure cleanup
|
|
9
|
+
|
|
10
|
+
Add `clearOnRevocation` to your provider or runtime options. Declare only the
|
|
11
|
+
data owned by each optional category:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { hosted, type ClearOnRevocationConfig } from 'c15t';
|
|
15
|
+
import { createConsentRuntime } from 'c15t/runtime';
|
|
16
|
+
|
|
17
|
+
const clearOnRevocation = {
|
|
18
|
+
measurement: {
|
|
19
|
+
cookies: ['_ga', '_ga_*'],
|
|
20
|
+
localStorage: ['analytics:*'],
|
|
21
|
+
},
|
|
22
|
+
marketing: {
|
|
23
|
+
cookies: ['_fbp'],
|
|
24
|
+
sessionStorage: ['campaign-id'],
|
|
25
|
+
},
|
|
26
|
+
} satisfies ClearOnRevocationConfig;
|
|
27
|
+
|
|
28
|
+
const runtime = createConsentRuntime({
|
|
29
|
+
mode: hosted({ url: '/api/c15t' }),
|
|
30
|
+
clearOnRevocation,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Start in the browser after mount. The endpoint must serve your c15t backend.
|
|
34
|
+
runtime.start();
|
|
35
|
+
|
|
36
|
+
// Call runtime.dispose() when the app no longer needs consent management.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For React, pass the same configuration through `ConsentProvider.options`:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import type { ReactNode } from 'react';
|
|
43
|
+
import { ConsentProvider, hosted } from 'c15t/react';
|
|
44
|
+
|
|
45
|
+
const mode = hosted({ url: '/api/c15t' });
|
|
46
|
+
|
|
47
|
+
export function Consent({ children }: { children: ReactNode }) {
|
|
48
|
+
return (
|
|
49
|
+
<ConsentProvider
|
|
50
|
+
options={{
|
|
51
|
+
mode,
|
|
52
|
+
clearOnRevocation: {
|
|
53
|
+
measurement: { cookies: ['_ga', '_ga_*'] },
|
|
54
|
+
},
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</ConsentProvider>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The same option is available in Next.js and TanStack Start `ConsentRoot` props, Vue and
|
|
64
|
+
Nuxt configuration, Svelte providers, and Astro integration options. Solid and
|
|
65
|
+
other headless integrations can use `createConsentRuntime` as shown above.
|
|
66
|
+
Every adapter uses the same cleanup module.
|
|
67
|
+
|
|
68
|
+
Omitting `clearOnRevocation` leaves cleanup disabled. The provider option is
|
|
69
|
+
initial-only. Remount the provider to replace its cleanup configuration. For
|
|
70
|
+
a shared runtime, configure the runtime owner rather than a borrowing provider.
|
|
71
|
+
|
|
72
|
+
## Matching names and cookie scopes
|
|
73
|
+
|
|
74
|
+
Use an exact string or a nonempty prefix followed by `*`. `_ga_*` matches
|
|
75
|
+
`_ga_ABC123`; it does not match `_ga`. Regular expressions, wildcards in other
|
|
76
|
+
positions, and a bare `*` are unsupported. Web Storage keys may contain spaces,
|
|
77
|
+
Unicode, and punctuation. Cookie names use their raw spelling, without URL
|
|
78
|
+
decoding.
|
|
79
|
+
|
|
80
|
+
Cookies can share a name while having different domains or paths. Cleanup
|
|
81
|
+
tries the current host and its parent domains, and the current path and its
|
|
82
|
+
ancestors. To target a specific scope, use an object:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const clearOnRevocation = {
|
|
86
|
+
measurement: {
|
|
87
|
+
cookies: [
|
|
88
|
+
{ name: 'analytics-id', domain: 'example.com', path: '/' },
|
|
89
|
+
{ name: 'checkout-metrics', domain: '', path: '/checkout' },
|
|
90
|
+
{ name: 'partitioned-metrics', partitioned: true },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
An empty `domain` means host-only. Explicit domains and paths replace the
|
|
97
|
+
automatic attempts for that field. Exact names can be deleted at a configured
|
|
98
|
+
path even when the current page cannot read that cookie. Prefix matching can
|
|
99
|
+
only discover cookie names visible to the current page, so use an exact name
|
|
100
|
+
for a cookie on another path.
|
|
101
|
+
|
|
102
|
+
Partitioned cookies require `partitioned: true`; ordinary targets remove
|
|
103
|
+
unpartitioned cookies. Cookie deletion preserves the browser's `__Secure-`
|
|
104
|
+
and `__Host-` prefix requirements. c15t protects its own consent, notice,
|
|
105
|
+
privacy, pending-save, and IAB consent records in cookies and localStorage,
|
|
106
|
+
including configured custom storage keys, even if your patterns match them.
|
|
107
|
+
c15t does not store consent in sessionStorage, so targeted entries there are
|
|
108
|
+
removed even when their names match consent storage keys.
|
|
109
|
+
|
|
110
|
+
## When cleanup runs
|
|
111
|
+
|
|
112
|
+
The runtime attaches cleanup after persistence and the script loader. Cleanup
|
|
113
|
+
waits while the policy is pending. On the first settled snapshot, it removes
|
|
114
|
+
configured data for every denied category. This includes a new opt-in visitor
|
|
115
|
+
who has not made a choice and a returning visitor whose permission expired.
|
|
116
|
+
|
|
117
|
+
After that first pass, cleanup runs when a category changes from allowed to
|
|
118
|
+
denied. Saving a refusal, expiry, a policy change, Global Privacy Control,
|
|
119
|
+
or synchronized records can cause that transition. Under an opt-out policy,
|
|
120
|
+
an expired grant that remains effectively allowed does not trigger deletion.
|
|
121
|
+
The `necessary` category cannot be configured for cleanup.
|
|
122
|
+
|
|
123
|
+
Cleanup keeps waiting if a failed initial request leaves the policy pending.
|
|
124
|
+
If a previously settled policy falls back to denial after an initialization
|
|
125
|
+
failure, cleanup removes its configured data. A later successful retry cannot
|
|
126
|
+
restore deleted data.
|
|
127
|
+
|
|
128
|
+
Runtime construction, server rendering, draft checkbox edits, opening the
|
|
129
|
+
dialog, and disposal do not clear data. Cleanup does not poll storage or repeat
|
|
130
|
+
on unrelated UI updates.
|
|
131
|
+
|
|
132
|
+
## Use an existing kernel
|
|
133
|
+
|
|
134
|
+
For a manually assembled integration, attach the module in the browser after
|
|
135
|
+
persistence hydration and script-loader setup:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { createClearOnRevocation } from 'c15t/modules/clear-on-revocation';
|
|
139
|
+
|
|
140
|
+
const cleanup = createClearOnRevocation({
|
|
141
|
+
kernel,
|
|
142
|
+
config: { measurement: { cookies: ['_ga', '_ga_*'] } },
|
|
143
|
+
storageConfig,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Stop observing consent when this integration is torn down.
|
|
147
|
+
cleanup.dispose();
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Here `kernel` is your existing consent kernel. Pass the same `storageConfig`
|
|
151
|
+
used by persistence so cleanup protects custom record keys. Attaching the
|
|
152
|
+
module can immediately clear denied categories if the policy is already
|
|
153
|
+
settled. Do not also attach it when your provider or runtime owns cleanup.
|
|
154
|
+
|
|
155
|
+
## Browser limits
|
|
156
|
+
|
|
157
|
+
Cleanup can remove JavaScript-accessible first-party cookies and keys in the
|
|
158
|
+
current origin's `localStorage` and `sessionStorage`. It cannot remove
|
|
159
|
+
`HttpOnly` cookies or another origin's data. Keep `HttpOnly` protections and
|
|
160
|
+
use your server to expire cookies that require server access. Cookie deletion
|
|
161
|
+
must match the cookie's scope. See the
|
|
162
|
+
[browser cookie documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies).
|
|
163
|
+
|
|
164
|
+
Browser restrictions can prevent reads or deletions. Cleanup failures do not
|
|
165
|
+
block consent updates. A running SDK may write data again after a sweep, so
|
|
166
|
+
keep script gating and the integration's consent-change or teardown behavior
|
|
167
|
+
configured. Deleting a script element cannot undo JavaScript it already ran.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c15t/react",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
4
|
"description": "React cookie banner, consent manager, preference center, and headless CMP components with IAB TCF and Consent Mode support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ccpa",
|
|
@@ -233,16 +233,16 @@
|
|
|
233
233
|
"test:watch": "bun prebuild && vitest"
|
|
234
234
|
},
|
|
235
235
|
"dependencies": {
|
|
236
|
-
"@c15t/core": "3.0.0-alpha.
|
|
237
|
-
"@c15t/dev-tools": "3.0.0-alpha.
|
|
238
|
-
"@c15t/iab": "3.0.0-alpha.
|
|
236
|
+
"@c15t/core": "3.0.0-alpha.1",
|
|
237
|
+
"@c15t/dev-tools": "3.0.0-alpha.1",
|
|
238
|
+
"@c15t/iab": "3.0.0-alpha.1",
|
|
239
239
|
"@c15t/schema": "3.0.0-alpha.0",
|
|
240
240
|
"@c15t/translations": "3.0.0-alpha.0",
|
|
241
|
-
"@c15t/ui": "3.0.0-alpha.
|
|
241
|
+
"@c15t/ui": "3.0.0-alpha.1",
|
|
242
242
|
"@types/google.maps": "3.65.3"
|
|
243
243
|
},
|
|
244
244
|
"devDependencies": {
|
|
245
|
-
"@c15t/backend": "3.0.0-alpha.
|
|
245
|
+
"@c15t/backend": "3.0.0-alpha.1",
|
|
246
246
|
"@c15t/conformance": "0.0.1",
|
|
247
247
|
"@c15t/typescript-config": "0.0.1",
|
|
248
248
|
"@c15t/vitest-config": "1.0.0",
|