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

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 (60) hide show
  1. package/AGENTS.md +2 -1
  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/preferences/atoms/accordion.js +1 -1
  5. package/dist/components/shared/primitives/button.js +1 -1
  6. package/dist/draft-context.js +2 -0
  7. package/dist/draft.js +1 -1
  8. package/dist/external-iab-context.js +1 -1
  9. package/dist/gpp.js +2 -0
  10. package/dist/hooks/use-color-scheme.js +1 -1
  11. package/dist/hooks.js +1 -1
  12. package/dist/index-parts/consent-banner.js +1 -0
  13. package/dist/index-parts/consent-dialog-link.js +1 -0
  14. package/dist/index-parts/consent-dialog-trigger.js +1 -0
  15. package/dist/index-parts/consent-dialog.js +1 -0
  16. package/dist/index-parts/consent-gate.js +1 -0
  17. package/dist/index-parts/core.js +1 -0
  18. package/dist/index-parts/draft.js +1 -0
  19. package/dist/index-parts/hooks.js +1 -0
  20. package/dist/index-parts/module-hooks.js +1 -0
  21. package/dist/index-parts/provider.js +1 -0
  22. package/dist/index-parts/theme.js +1 -0
  23. package/dist/index-parts/translations.js +1 -0
  24. package/dist/index.js +1 -1
  25. package/dist/kernel-selector.js +1 -1
  26. package/dist/module-hooks/iframe-blocker.js +1 -1
  27. package/dist/provider.js +1 -1
  28. package/dist/version.js +1 -1
  29. package/dist-types/draft-context.d.ts +31 -0
  30. package/dist-types/draft.d.ts +13 -36
  31. package/dist-types/gpp.d.ts +27 -0
  32. package/dist-types/hooks.d.ts +3 -0
  33. package/dist-types/index-parts/consent-banner.d.ts +7 -0
  34. package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
  35. package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
  36. package/dist-types/index-parts/consent-dialog.d.ts +7 -0
  37. package/dist-types/index-parts/consent-gate.d.ts +7 -0
  38. package/dist-types/index-parts/core.d.ts +8 -0
  39. package/dist-types/index-parts/draft.d.ts +7 -0
  40. package/dist-types/index-parts/hooks.d.ts +7 -0
  41. package/dist-types/index-parts/module-hooks.d.ts +7 -0
  42. package/dist-types/index-parts/provider.d.ts +7 -0
  43. package/dist-types/index-parts/theme.d.ts +8 -0
  44. package/dist-types/index-parts/translations.d.ts +7 -0
  45. package/dist-types/index.d.ts +14 -15
  46. package/dist-types/kernel-selector.d.ts +0 -8
  47. package/dist-types/module-hooks/iframe-blocker.d.ts +12 -7
  48. package/dist-types/provider.d.ts +36 -13
  49. package/dist-types/version.d.ts +1 -1
  50. package/docs/README.md +2 -1
  51. package/docs/concepts/consent-state.md +19 -5
  52. package/docs/customization/translations.md +1 -2
  53. package/docs/frameworks/react/components/consent-provider.md +6 -2
  54. package/docs/frameworks/react/components/dev-tools.md +1 -1
  55. package/docs/frameworks/react/gpp.md +163 -0
  56. package/docs/integrations/posthog.md +99 -11
  57. package/docs/upgrade-v3.md +22 -1
  58. package/package.json +12 -7
  59. package/dist/ui-save.js +0 -1
  60. package/dist-types/ui-save.d.ts +0 -25
package/AGENTS.md CHANGED
@@ -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](./docs/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](./docs/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](./docs/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](./docs/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](./docs/frameworks/react/headless.md): Build a custom consent banner in React with the c15t/react/headless hooks inside your ConsentProvider.
42
43
  - [Hooks](./docs/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](./docs/frameworks/react/iab.md): Mount the IAB TCF banner and dialog inside a React ConsentProvider and configure the CMP ID, policy and vendor data.
@@ -111,7 +112,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
111
112
  - [Pinterest Tag](./docs/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
113
  - [Pirsch](./docs/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
114
  - [Plausible Analytics](./docs/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](./docs/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.
115
+ - [PostHog](./docs/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
116
  - [Promptwatch](./docs/integrations/promptwatch.md): Load the Promptwatch attribution client only after measurement consent with the c15t promptwatch helper, and check it in DevTools.
116
117
  - [Reddit Pixel](./docs/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
118
  - [RudderStack](./docs/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.
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{actionAppearanceFromTheme as e,resolveConsentPresentation as r}from"@c15t/core";import{useCallback as o,useContext as s,useEffect as t,useMemo as c}from"react";import{GlobalThemeContext as n}from"../context/theme-context.js";import{useConsentSaveAction as a}from"../draft.js";import{useActiveUI as i,useDismissNotice as p,usePolicyRule as l,useResolvedPresentation as m,useSetActiveUI as u}from"../hooks.js";import{useTheme as f}from"../hooks/use-theme.js";let d=function(d){let g=i(),h=l(),k=m(),b=s(n),j=c(()=>({preferences:{scrollLock:b.scrollLock,trapFocus:b.trapFocus,...k?.preferences},prompt:{scrollLock:b.scrollLock,trapFocus:b.trapFocus,...k?.prompt}}),[k,b.scrollLock,b.trapFocus]),{theme:v}=f(),F=c(()=>e(v),[v]),L=a(),_=p(),A=u(),x=c(()=>({...r({actionAppearance:F,override:d?.prompt,policy:h,presentation:j,surface:"prompt"}),isVisible:"banner"===g}),[h,j,d?.prompt,g,F]),C=c(()=>({...r({actionAppearance:F,override:d?.preferences,policy:h,presentation:j,surface:"preferences"}),isVisible:"dialog"===g}),[h,j,d?.preferences,g,F]);t(()=>{if(globalThis.process?.env?.NODE_ENV!=="production")for(let e of[...x.diagnostics,...C.diagnostics])console.warn(`c15t presentation: ${e.message}`,e.actions)},[x.diagnostics,C.diagnostics]);let V=o(()=>A("banner"),[A]),w=o(()=>A("dialog"),[A]),D=o(()=>A("none"),[A]),E=o(e=>{switch(e){case"accept":return L("all");case"reject":return L("none");case"save":return L();case"dismiss":return _();case"customize":return A("dialog");default:return}},[L,_,A]);return{activeUI:g,banner:x,closeUI:D,dialog:C,openBanner:V,openDialog:w,performAction:E,performBannerAction:E,performDialogAction:E,saveCustomPreferences:L}};export{d as useHeadlessConsentUI};
2
+ import{actionAppearanceFromTheme as e,resolveConsentPresentation as r}from"@c15t/core";import{useCallback as o,useContext as s,useEffect as t,useMemo as c}from"react";import{GlobalThemeContext as n}from"../context/theme-context.js";import{useConsentSaveAction as a}from"../draft-context.js";import{useActiveUI as i,useDismissNotice as p,usePolicyRule as l,useResolvedPresentation as m,useSetActiveUI as u}from"../hooks.js";import{useTheme as f}from"../hooks/use-theme.js";let d=function(d){let g=i(),h=l(),k=m(),b=s(n),j=c(()=>({preferences:{scrollLock:b.scrollLock,trapFocus:b.trapFocus,...k?.preferences},prompt:{scrollLock:b.scrollLock,trapFocus:b.trapFocus,...k?.prompt}}),[k,b.scrollLock,b.trapFocus]),{theme:v}=f(),F=c(()=>e(v),[v]),L=a(),_=p(),x=u(),A=c(()=>({...r({actionAppearance:F,override:d?.prompt,policy:h,presentation:j,surface:"prompt"}),isVisible:"banner"===g}),[h,j,d?.prompt,g,F]),C=c(()=>({...r({actionAppearance:F,override:d?.preferences,policy:h,presentation:j,surface:"preferences"}),isVisible:"dialog"===g}),[h,j,d?.preferences,g,F]);t(()=>{if(globalThis.process?.env?.NODE_ENV!=="production")for(let e of[...A.diagnostics,...C.diagnostics])console.warn(`c15t presentation: ${e.message}`,e.actions)},[A.diagnostics,C.diagnostics]);let V=o(()=>x("banner"),[x]),w=o(()=>x("dialog"),[x]),D=o(()=>x("none"),[x]),E=o(e=>{switch(e){case"accept":return L("all");case"reject":return L("none");case"save":return L();case"dismiss":return _();case"customize":return x("dialog");default:return}},[L,_,x]);return{activeUI:g,banner:A,closeUI:D,dialog:C,openBanner:V,openDialog:w,performAction:E,performBannerAction:E,performDialogAction:E,saveCustomPreferences:L}};export{d as useHeadlessConsentUI};
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{resolveIABBannerSummary as e}from"@c15t/iab/headless";import{useCallback as o,useContext as s,useMemo as t}from"react";import{KernelContext as r}from"../context.js";import{useActiveUI as a,usePreferencesPresentation as c,usePromptPresentation as n,useSetActiveUI as l}from"../hooks.js";import{useIAB as i}from"../iab-context.js";import{saveIABConsentUI as m}from"../ui-save.js";let d=function(){let d=i(),f=s(r),p=a()??"none",u=n(),b=c(),v=l(),j=t(()=>e(d),[d]),g=o(()=>{d?.setPreferenceCenterTab("vendors"),v("dialog")},[d,v]),k=o(()=>v("none"),[v]),_=o(e=>{e?.tab&&d?.setPreferenceCenterTab(e.tab),v("dialog")},[d,v]),A=o(async e=>{d&&("accept"===e?d.acceptAll():"reject"===e&&d.rejectAll(),await (f?m(f,d.save):d.save()))},[d,f]),C=o(async e=>{"customize"===e?_():await A(e)},[_,A]),I=o(e=>A("customize"===e?void 0:e),[A]);return{activeUI:p,banner:{...j,scrollLock:u.scrollLock},closeUI:k,dialog:{isReady:!!(d?.gvl||d?.gvlReference),scrollLock:b.scrollLock},iab:d,openDialog:_,openVendorsDialog:g,performBannerAction:C,performDialogAction:I}};export{d as useHeadlessIABConsentUI};
2
+ import{saveIABConsentSurface as e}from"@c15t/core/surface-actions";import{resolveIABBannerSummary as o}from"@c15t/iab/headless";import{useCallback as t,useContext as s,useMemo as r}from"react";import{KernelContext as c}from"../context.js";import{useActiveUI as a,usePreferencesPresentation as n,usePromptPresentation as l,useSetActiveUI as i}from"../hooks.js";import{useIAB as m}from"../iab-context.js";let f=function(){let f=m(),d=s(c),p=a()??"none",u=l(),b=n(),v=i(),g=r(()=>o(f),[f]),j=t(()=>{f?.setPreferenceCenterTab("vendors"),v("dialog")},[f,v]),k=t(()=>v("none"),[v]),_=t(e=>{e?.tab&&f?.setPreferenceCenterTab(e.tab),v("dialog")},[f,v]),A=t(async o=>{f&&("accept"===o?f.acceptAll():"reject"===o&&f.rejectAll(),await (d?e(d,f.save):f.save()))},[f,d]),C=t(async e=>{"customize"===e?_():await A(e)},[_,A]),I=t(e=>A("customize"===e?void 0:e),[A]);return{activeUI:p,banner:{...g,scrollLock:u.scrollLock},closeUI:k,dialog:{isReady:!!(f?.gvl||f?.gvlReference),scrollLock:b.scrollLock},iab:f,openDialog:_,openVendorsDialog:j,performBannerAction:C,performDialogAction:I}};export{f as useHeadlessIABConsentUI};
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import o from"@c15t/ui/styles/components/accordion";import{createContext as n,forwardRef as i,useCallback as r,useContext as a,useMemo as c}from"react";import{useTranslations as d}from"../../../component-hooks/use-translations.js";import{Box as s}from"../../shared/primitives/box.js";import{LucideIcon as l}from"../../shared/ui/icon.js";import{useConsentDraftSlice as m,useConsentDraftStore as p}from"../../../draft.js";import{useExplicitChoice as g,useRestrictions as u}from"../../../hooks.js";import{useTheme as y}from"../../../hooks/use-theme.js";import{useDisplayedCategories as h}from"../../../kernel-selector.js";import{ConsentWidgetVendorList as f}from"./vendor-list.js";import*as w from"../../shared/ui/preference-item/index.js";import*as C from"../../shared/ui/switch/index.js";let v=[{defaultValue:!0,description:"Required for basic site functionality",disabled:!0,display:!0,gdprType:1,name:"necessary"},{defaultValue:!1,description:"Enables enhanced features",display:!0,gdprType:2,name:"functionality"},{defaultValue:!1,description:"Analytics and performance measurement",display:!0,gdprType:4,name:"measurement"},{defaultValue:!1,description:"Improves your experience",display:!0,gdprType:3,name:"experience"},{defaultValue:!1,description:"Advertising and marketing",display:!0,gdprType:5,name:"marketing"}],A=n(null),S=function(){let e=a(A);if(!e)throw Error("ConsentWidgetAccordion components must be used within ConsentWidgetAccordion");return e},N=i(({children:t,...n},i)=>e(s,{ref:i,baseClassName:o.triggerRow,...n,children:t}));N.displayName="ConsentWidgetAccordionTrigger";let b=w.Trigger,T=w.Content,W=w.Leading,j=C.Root,I=({"data-testid":t,children:n,className:i,noStyle:a,onValueChange:d,style:l,type:m="multiple",value:p,...g})=>{let{noStyle:u}=y(),h=a??u,f=c(()=>Array.isArray(p)?p:p?[p]:[],[p]),w=r((e,t)=>{if("single"===m)return void d?.(t?e:"");let o=t?[...new Set([...f,e])]:f.filter(t=>t!==e);d?.(o)},[d,f,m]),C=c(()=>({noStyle:h,onToggleItem:w,openValues:f}),[h,w,f]);return e(A.Provider,{value:C,children:e(s,{className:i,"data-testid":t??"consent-widget-accordion",noStyle:a,style:l,slotKey:"accordion.root",baseClassName:o.list,...g,children:n})})},K=l({iconPath:e("path",{d:"M5 12h14M12 5v14"})}),V=l({iconPath:e("path",{d:"M5 12h14"})}),k=({consent:n,title:i,description:r,restricted:a,open:c,noStyle:d,onToggleItem:s})=>{let l=p(),g=m(l,e=>e.values[n.name]);return t(w.Root,{className:d?void 0:o.item,"data-testid":`consent-widget-accordion-item-${n.name}`,noStyle:!0,onOpenChange:e=>s(n.name,e),open:c,slotKey:"accordion-item.root",children:[t(N,{slotKey:"accordion.triggerRow",children:[t(b,{className:d?void 0:o.trigger,"data-testid":`consent-widget-accordion-trigger-${n.name}`,noStyle:!0,slotKey:"accordion-item.trigger",children:[e(W,{className:d?void 0:o.arrow,"data-testid":`consent-widget-accordion-arrow-${n.name}`,noStyle:!0,slotKey:"accordion.arrow",children:c?e(V,{"aria-hidden":"true"}):e(K,{"aria-hidden":"true"})}),e(w.Header,{noStyle:!0,slotKey:"accordion.header",children:e(w.Title,{className:d?void 0:o.title,noStyle:!0,slotKey:"accordion.title",children:i})})]}),e(w.Control,{className:d?void 0:o.control,noStyle:!0,slotKey:"accordion.control",children:e(j,{"aria-label":i,checked:g,"aria-describedby":a?`c15t-restriction-${n.name}`:void 0,onCheckedChange:e=>l.set(n.name,e),disabled:n.disabled,size:"small","data-testid":`consent-widget-switch-${n.name}`})})]}),a?e("output",{className:d?void 0:o.restriction,"data-testid":`consent-widget-restriction-${n.name}`,id:`c15t-restriction-${n.name}`,children:"Your saved choice is restricted by the current privacy settings."}):null,t(T,{className:d?void 0:o.content,"data-testid":`consent-widget-accordion-content-${n.name}`,innerClassName:d?void 0:o.contentInner,innerSlotKey:"accordion.contentInner",slotKey:"accordion-item.content",viewportClassName:d?void 0:o.contentViewport,viewportSlotKey:"accordion.contentViewport",children:[r,e(f,{category:n.name,noStyle:d})]})]})},$=()=>{let t=h(),o=g(),n=u(),i=function(e){if("necessary"===e)return!1;let t=o?.categories[e];return t?.value===!0&&(n[e]?.length??0)>0},{noStyle:r,onToggleItem:a,openValues:s}=S(),{consentTypes:l}=d();return c(()=>{let e=new Set(t);return v.filter(t=>e.has(t.name))},[t]).map(t=>e(k,{consent:t,description:l[t.name]?.description??t.description,noStyle:r,onToggleItem:a,open:s.includes(t.name),restricted:i(t.name),title:l[t.name]?.title??t.name.replace(/_/gu," ").replace(/\b\w/gu,e=>e.toUpperCase())},t.name))},x=i(({className:t,...n},i)=>e(w.Root,{ref:i,className:[o.item,t].filter(Boolean).join(" "),noStyle:!0,...n}));x.displayName="ConsentWidgetAccordionItem";let R=b,L=N,M=T,P=W,E=I,q=j,z=$,B=x,H=f;export{E as Accordion,P as AccordionArrow,M as AccordionContent,B as AccordionItem,z as AccordionItems,L as AccordionTrigger,R as AccordionTriggerInner,I as ConsentWidgetAccordion,W as ConsentWidgetAccordionArrow,T as ConsentWidgetAccordionContent,x as ConsentWidgetAccordionItem,$ as ConsentWidgetAccordionItems,N as ConsentWidgetAccordionTrigger,b as ConsentWidgetAccordionTriggerInner,j as ConsentWidgetSwitch,f as ConsentWidgetVendorList,q as Switch,H as VendorList};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import o from"@c15t/ui/styles/components/accordion";import{createContext as n,forwardRef as i,useCallback as r,useContext as a,useMemo as c}from"react";import{useTranslations as d}from"../../../component-hooks/use-translations.js";import{Box as s}from"../../shared/primitives/box.js";import{LucideIcon as l}from"../../shared/ui/icon.js";import{useConsentDraftSlice as m,useConsentDraftStore as p}from"../../../draft.js";import{useExplicitChoice as g,useRestrictions as u}from"../../../hooks.js";import{useTheme as y}from"../../../hooks/use-theme.js";import{ConsentWidgetVendorList as h}from"./vendor-list.js";import*as f from"../../shared/ui/preference-item/index.js";import*as w from"../../shared/ui/switch/index.js";let C=[{defaultValue:!0,description:"Required for basic site functionality",disabled:!0,display:!0,gdprType:1,name:"necessary"},{defaultValue:!1,description:"Enables enhanced features",display:!0,gdprType:2,name:"functionality"},{defaultValue:!1,description:"Analytics and performance measurement",display:!0,gdprType:4,name:"measurement"},{defaultValue:!1,description:"Improves your experience",display:!0,gdprType:3,name:"experience"},{defaultValue:!1,description:"Advertising and marketing",display:!0,gdprType:5,name:"marketing"}],v=n(null),A=function(){let e=a(v);if(!e)throw Error("ConsentWidgetAccordion components must be used within ConsentWidgetAccordion");return e},S=i(({children:t,...n},i)=>e(s,{ref:i,baseClassName:o.triggerRow,...n,children:t}));S.displayName="ConsentWidgetAccordionTrigger";let N=f.Trigger,b=f.Content,T=f.Leading,W=w.Root,j=({"data-testid":t,children:n,className:i,noStyle:a,onValueChange:d,style:l,type:m="multiple",value:p,...g})=>{let{noStyle:u}=y(),h=a??u,f=c(()=>Array.isArray(p)?p:p?[p]:[],[p]),w=r((e,t)=>{if("single"===m)return void d?.(t?e:"");let o=t?[...new Set([...f,e])]:f.filter(t=>t!==e);d?.(o)},[d,f,m]),C=c(()=>({noStyle:h,onToggleItem:w,openValues:f}),[h,w,f]);return e(v.Provider,{value:C,children:e(s,{className:i,"data-testid":t??"consent-widget-accordion",noStyle:a,style:l,slotKey:"accordion.root",baseClassName:o.list,...g,children:n})})},I=l({iconPath:e("path",{d:"M5 12h14M12 5v14"})}),K=l({iconPath:e("path",{d:"M5 12h14"})}),V=({consent:n,title:i,description:r,restricted:a,open:c,noStyle:d,onToggleItem:s})=>{let l=p(),g=m(l,e=>e.values[n.name]);return t(f.Root,{className:d?void 0:o.item,"data-testid":`consent-widget-accordion-item-${n.name}`,noStyle:!0,onOpenChange:e=>s(n.name,e),open:c,slotKey:"accordion-item.root",children:[t(S,{slotKey:"accordion.triggerRow",children:[t(N,{className:d?void 0:o.trigger,"data-testid":`consent-widget-accordion-trigger-${n.name}`,noStyle:!0,slotKey:"accordion-item.trigger",children:[e(T,{className:d?void 0:o.arrow,"data-testid":`consent-widget-accordion-arrow-${n.name}`,noStyle:!0,slotKey:"accordion.arrow",children:c?e(K,{"aria-hidden":"true"}):e(I,{"aria-hidden":"true"})}),e(f.Header,{noStyle:!0,slotKey:"accordion.header",children:e(f.Title,{className:d?void 0:o.title,noStyle:!0,slotKey:"accordion.title",children:i})})]}),e(f.Control,{className:d?void 0:o.control,noStyle:!0,slotKey:"accordion.control",children:e(W,{"aria-label":i,checked:g,"aria-describedby":a?`c15t-restriction-${n.name}`:void 0,onCheckedChange:e=>l.set(n.name,e),disabled:n.disabled,size:"small","data-testid":`consent-widget-switch-${n.name}`})})]}),a?e("output",{className:d?void 0:o.restriction,"data-testid":`consent-widget-restriction-${n.name}`,id:`c15t-restriction-${n.name}`,children:"Your saved choice is restricted by the current privacy settings."}):null,t(b,{className:d?void 0:o.content,"data-testid":`consent-widget-accordion-content-${n.name}`,innerClassName:d?void 0:o.contentInner,innerSlotKey:"accordion.contentInner",slotKey:"accordion-item.content",viewportClassName:d?void 0:o.contentViewport,viewportSlotKey:"accordion.contentViewport",children:[r,e(h,{category:n.name,noStyle:d})]})]})},$=()=>{let t=m(p(),e=>e.displayedCategories),o=g(),n=u(),i=function(e){if("necessary"===e)return!1;let t=o?.categories[e];return t?.value===!0&&(n[e]?.length??0)>0},{noStyle:r,onToggleItem:a,openValues:s}=A(),{consentTypes:l}=d();return c(()=>t.flatMap(e=>C.filter(t=>t.name===e)),[t]).map(t=>e(V,{consent:t,description:l[t.name]?.description??t.description,noStyle:r,onToggleItem:a,open:s.includes(t.name),restricted:i(t.name),title:l[t.name]?.title??t.name.replace(/_/gu," ").replace(/\b\w/gu,e=>e.toUpperCase())},t.name))},k=i(({className:t,...n},i)=>e(f.Root,{ref:i,className:[o.item,t].filter(Boolean).join(" "),noStyle:!0,...n}));k.displayName="ConsentWidgetAccordionItem";let x=N,R=S,M=b,L=T,P=j,E=W,q=$,z=k,B=h;export{P as Accordion,L as AccordionArrow,M as AccordionContent,z as AccordionItem,q as AccordionItems,R as AccordionTrigger,x as AccordionTriggerInner,j as ConsentWidgetAccordion,T as ConsentWidgetAccordionArrow,b as ConsentWidgetAccordionContent,k as ConsentWidgetAccordionItem,$ as ConsentWidgetAccordionItems,S as ConsentWidgetAccordionTrigger,N as ConsentWidgetAccordionTriggerInner,W as ConsentWidgetSwitch,h as ConsentWidgetVendorList,E as Switch,B as VendorList};
@@ -1 +1 @@
1
- import{jsx as t}from"react/jsx-runtime";import{forwardRef as o,useCallback as e}from"react";import{useIdleDialogWarming as n,warmDialogChunk as r}from"../../../chunk-warming.js";import{toSaveUISource as i,useConsentTracking as a}from"../../../context/consent-tracking-context.js";import{useConsentSaveAction as s}from"../../../draft.js";import{useDismissNotice as c,useSetActiveUI as m}from"../../../hooks.js";import{useTheme as d}from"../../../hooks/use-theme.js";import{useUIConfig as l}from"../../../ui-config-context.js";import{getSlotProps as u,mergeSlotProps as f}from"../../../utils/merge-slot-props.js";import{Slot as p}from"../libs/slot.js";import*as v from"../ui/button/index.js";let y=["primary","secondary","neutral","consentAction","isPrimary","performDefaultAction"],b=function(t){if(t.variant||t.mode)return{mode:t.mode??"stroke",variant:t.variant??"neutral"};let o=t.theme?.consentActions,e=[t.consentAction&&"save"!==t.consentAction?o?.[t.consentAction]:void 0,t.isPrimary?o?.primary:void 0,o?.default,{mode:"stroke",variant:t.isPrimary?"primary":"neutral"}];return{mode:e.find(t=>t?.mode)?.mode??"stroke",variant:e.find(t=>t?.variant)?.variant??"neutral"}},j=o(({asChild:o,className:j,style:k,noStyle:g,action:h,slotKey:C,baseClassName:P,variant:x,mode:A,size:E="small",consentAction:w,isPrimary:N,onClick:F,onFocus:S,onPointerEnter:q,closeConsentBanner:B=!1,closeConsentDialog:O=!1,performDefaultAction:z=!0,category:D,...V},G)=>{let H=s(),{uiSource:I}=a(),J=e(t=>H(t,i(I)),[H,I]),K=m(),L=c(),{noStyle:M,theme:Q}=d(),{components:R}=l(),T=b({consentAction:w,isPrimary:N,mode:A,theme:Q,variant:x}),U="primary"===T.variant?"button.primary":"button.secondary",W=f(u(R,C??U),{baseClassName:[v.buttonVariants({mode:T.mode,size:E,variant:T.variant}).root(),P],className:j,noStyle:M||g,style:{...k}});if(!D&&"set-consent"===h)throw Error("Category is required for set-consent action");let X=e(t=>{if(F?.(t),t.defaultPrevented)return;let o="accept-consent"===h||"reject-consent"===h||"custom-consent"===h;if((B||O)&&!o&&K("none"),"open-consent-dialog"===h&&K("dialog"),z&&"open-consent-dialog"!==h)switch(h){case"accept-consent":J("all");break;case"reject-consent":J("none");break;case"custom-consent":J();break;case"dismiss-notice":L();break;case"set-consent":if(!D)throw Error("Category is required for set-consent action");J({[D]:!0})}},[B,O,F,J,K,h,D,L,z]),Y="open-consent-dialog"===h;n(Y);let Z=S??W.onFocus,$=q??W.onPointerEnter,_=e(t=>{Z?.(t),Y&&r()},[Z,Y]),tt=e(t=>{$?.(t),Y&&r()},[$,Y]),to=Object.fromEntries(Object.entries(V).filter(([t])=>!y.includes(t))),te=!(M||g);return t(o?p:"button",{ref:G,type:o?void 0:"button","data-variant":te?T.variant:void 0,"data-mode":te?T.mode:void 0,"data-size":te?E:void 0,"data-action":w,...W,onClick:X,onFocus:_,onPointerEnter:tt,...to})});j.displayName="ConsentButton";export{j as ConsentButton};
1
+ import{jsx as t}from"react/jsx-runtime";import{forwardRef as o,useCallback as e}from"react";import{useIdleDialogWarming as n,warmDialogChunk as r}from"../../../chunk-warming.js";import{toSaveUISource as i,useConsentTracking as a}from"../../../context/consent-tracking-context.js";import{useConsentSaveAction as s}from"../../../draft-context.js";import{useDismissNotice as c,useSetActiveUI as m}from"../../../hooks.js";import{useTheme as d}from"../../../hooks/use-theme.js";import{useUIConfig as l}from"../../../ui-config-context.js";import{getSlotProps as u,mergeSlotProps as f}from"../../../utils/merge-slot-props.js";import{Slot as p}from"../libs/slot.js";import*as v from"../ui/button/index.js";let y=["primary","secondary","neutral","consentAction","isPrimary","performDefaultAction"],b=function(t){if(t.variant||t.mode)return{mode:t.mode??"stroke",variant:t.variant??"neutral"};let o=t.theme?.consentActions,e=[t.consentAction&&"save"!==t.consentAction?o?.[t.consentAction]:void 0,t.isPrimary?o?.primary:void 0,o?.default,{mode:"stroke",variant:t.isPrimary?"primary":"neutral"}];return{mode:e.find(t=>t?.mode)?.mode??"stroke",variant:e.find(t=>t?.variant)?.variant??"neutral"}},j=o(({asChild:o,className:j,style:k,noStyle:g,action:h,slotKey:x,baseClassName:C,variant:P,mode:A,size:E="small",consentAction:w,isPrimary:N,onClick:F,onFocus:S,onPointerEnter:q,closeConsentBanner:B=!1,closeConsentDialog:O=!1,performDefaultAction:z=!0,category:D,...V},G)=>{let H=s(),{uiSource:I}=a(),J=e(t=>H(t,i(I)),[H,I]),K=m(),L=c(),{noStyle:M,theme:Q}=d(),{components:R}=l(),T=b({consentAction:w,isPrimary:N,mode:A,theme:Q,variant:P}),U="primary"===T.variant?"button.primary":"button.secondary",W=f(u(R,x??U),{baseClassName:[v.buttonVariants({mode:T.mode,size:E,variant:T.variant}).root(),C],className:j,noStyle:M||g,style:{...k}});if(!D&&"set-consent"===h)throw Error("Category is required for set-consent action");let X=e(t=>{if(F?.(t),t.defaultPrevented)return;let o="accept-consent"===h||"reject-consent"===h||"custom-consent"===h;if((B||O)&&!o&&K("none"),"open-consent-dialog"===h&&K("dialog"),z&&"open-consent-dialog"!==h)switch(h){case"accept-consent":J("all");break;case"reject-consent":J("none");break;case"custom-consent":J();break;case"dismiss-notice":L();break;case"set-consent":if(!D)throw Error("Category is required for set-consent action");J({[D]:!0})}},[B,O,F,J,K,h,D,L,z]),Y="open-consent-dialog"===h;n(Y);let Z=S??W.onFocus,$=q??W.onPointerEnter,_=e(t=>{Z?.(t),Y&&r()},[Z,Y]),tt=e(t=>{$?.(t),Y&&r()},[$,Y]),to=Object.fromEntries(Object.entries(V).filter(([t])=>!y.includes(t))),te=!(M||g);return t(o?p:"button",{ref:G,type:o?void 0:"button","data-variant":te?T.variant:void 0,"data-mode":te?T.mode:void 0,"data-size":te?E:void 0,"data-action":w,...W,onClick:X,onFocus:_,onPointerEnter:tt,...to})});j.displayName="ConsentButton";export{j as ConsentButton};
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{saveConsentSurface as e}from"@c15t/core/surface-actions";import{createContext as t,useCallback as r,useContext as o}from"react";import{KernelContext as n,ProviderServicesContext as s}from"./context.js";import{useResolvedPresentation as a}from"./hooks.js";import{useCommittedRef as i}from"./hooks/use-committed-ref.js";let u=t(null),f={ok:!1},c=function(){let e=o(n);if(!e)throw Error("Consent drafts require a ConsentProvider.");return e},l=function(e){let t=i(c());return r(()=>t.current===e,[t,e])},d=async function(e,t,r,o){let{createPreferenceDraft:n}=await import("@c15t/core/preference-draft");return n(e,{defaults:t}).save({categories:r,uiSource:o})},m=function(){let t=c(),n=o(s),i=o(u),m=i?.kernel===t?i:null,v=a()?.preferences?.defaults,p=l(t);return r((r,o)=>{if(!p())return Promise.resolve(f);let s=n?.getConsentCategories(),a="all"===r||"none"===r;return e(t,()=>m&&(a||void 0===r)?m.save({categories:s,input:r,uiSource:o}):void 0===r?d(t,v,s,o):t.commands.save(r,{...void 0!==s&&{categories:s},...void 0!==o&&{uiSource:o}}),()=>void 0!==r||!m?.getState().isDirty)},[v,m,p,t,n])};export{u as DraftContext,f as REFUSED,m as useConsentSaveAction,c as useDraftKernel,l as useKernelGuard};
package/dist/draft.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e}from"react/jsx-runtime";import{deniedVendorIds as t,vendorRenders as r}from"@c15t/core";import{createContext as o,useCallback as n,useContext as i,useEffect as s,useMemo as l,useState as a,useSyncExternalStore as c}from"react";import{KernelContext as u,ProviderServicesContext as f}from"./context.js";import{useResolvedPresentation as d}from"./hooks.js";import{useCommittedRef as p}from"./hooks/use-committed-ref.js";import{saveConsentUI as y}from"./ui-save.js";let v=function(e,t,r){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,value:r,writable:!0})},m=function(e){let r={};if("iab"===e.model)return r;let o=t(e)??new Set;for(let t of e.vendors?.declared??[])v(r,t.id,!o.has(t.id));return r},g=function(e){return"iab"===e.model?"":JSON.stringify((e.vendors?.declared??[]).filter(r).map(e=>[e.id,!0===e.disabled,e.category]).sort(([e],[t])=>String(e).localeCompare(String(t))))},h=function(e){let t=new Set;if("iab"===e.model)return t;for(let r of e.vendors?.declared??[])!0!==r.disabled&&t.add(r.id);return t},S=function(e,t){let r=Object.keys(e);return r.length===Object.keys(t).length&&r.every(r=>e[r]===t[r])},C=function(e,t){let r={experience:!1,functionality:!1,marketing:!1,measurement:!1,necessary:!0};for(let o of e.evaluationPolicy.choiceScope??e.policyRule.scope)r[o]=e.explicitChoice?.categories[o]?.value??t?.[o]??("opt-out"===e.policyRule.model||e.policyRule.preselectedCategories.includes(o));return r},b=function(e,t){if(e===t)return!0;if(!e||!t)return!1;for(let r of new Set([...Object.keys(e),...Object.keys(t)]))if(e[r]!==t[r])return!1;return!0},j=function(e,t){let r=t,o=0,n=0,i=e.getSnapshot(),s=C(i,r),l=m(i),a=h(i),c=g(i),{fingerprint:u}=i.evaluationPolicy.choice,f={displayedCategories:["necessary",...i.evaluationPolicy.choiceScope??i.policyRule.scope],isDirty:!1,isStale:!1,values:s,vendors:l},d=new Set,p=e=>{for(let t of(f=e,d))t()},y=(e,t)=>f.displayedCategories.some(t=>e[t]!==s[t])||!S(t,l),j=()=>{o+=1,s=C(i=e.getSnapshot(),r),l=m(i),a=h(i),c=g(i),({fingerprint:u}=i.evaluationPolicy.choice),p({displayedCategories:["necessary",...i.evaluationPolicy.choiceScope??i.policyRule.scope],isDirty:!1,isStale:!1,values:s,vendors:l})},D=e=>{let t={...f.values},r=!1;for(let o of f.displayedCategories)"necessary"!==o&&"boolean"==typeof e[o]&&t[o]!==e[o]&&(t[o]=e[o],r=!0);r&&(o+=1,p({...f,isDirty:y(t,f.vendors),values:t}))},P=e=>{let t={...f.vendors},r=!1;for(let[o,n]of Object.entries(e))a.has(o)&&"boolean"==typeof n&&t[o]!==n&&(v(t,o,n),r=!0);r&&(o+=1,p({...f,isDirty:y(f.values,t),vendors:t}))},k=()=>{let e={};for(let t of Object.keys(l))v(e,t,!0);return e},O=()=>{let t=e.getSnapshot();if(i.explicitChoice===t.explicitChoice&&i.policyRule===t.policyRule&&i.evaluationPolicy===t.evaluationPolicy&&i.vendors===t.vendors&&i.vendorChoice===t.vendorChoice&&i.model===t.model)return;let r=t.evaluationPolicy.choiceScope??t.policyRule.scope,o=f.displayedCategories.length!==r.length+1||r.some(e=>!f.displayedCategories.includes(e)),n=g(t)!==c,s=u!==t.evaluationPolicy.choice.fingerprint||o||n;i=t,f.isDirty?s&&!f.isStale&&p({...f,isStale:!0}):j()};return{acceptAll(){D(Object.fromEntries(f.displayedCategories.map(e=>[e,!0]))),P(k())},connect:()=>(O(),e.subscribe(O)),getSnapshot:()=>f,kernel:e,rejectAll(){D(Object.fromEntries(f.displayedCategories.map(e=>[e,!1]))),P(k())},reset:j,async save(t,r,i,s){if(u!==e.getSnapshot().evaluationPolicy.choice.fingerprint||f.isStale)return p({...f,isStale:!0}),{ok:!1};let a={},c=new Set(r??f.displayedCategories);for(let e of f.displayedCategories)"necessary"!==e&&c.has(e)&&(a[e]=f.values[e]);let d=n+=1,y={};if("all"!==t&&"none"!==t)for(let[e,t]of Object.entries(f.vendors))l[e]!==t&&v(y,e,t);let m=e.commands.save(t??a,{categories:r,...Object.keys(y).length>0&&{vendors:y},...void 0!==s&&{uiSource:s}}),g=o,h=await m;return h.ok&&d===n&&o===g&&!f.isStale&&u===e.getSnapshot().evaluationPolicy.choice.fingerprint&&(j(),i?.()),h},set(e,t){D({[e]:t})},setDefaults(e){!b(r,e)&&(r=e,f.isDirty||j())},setVendor(e,t){P({[e]:t})},subscribe:e=>(d.add(e),()=>{d.delete(e)}),update:D}},D=o(null),P=function(){let e=i(u);if(!e)throw Error("Consent drafts require a ConsentProvider.");return e},k=function(e,t){let[r,o]=a(()=>({kernel:e,store:j(e,t)}));if(r.kernel===e)return r.store;let n={kernel:e,store:j(e,t)};return o(n),n.store},O=({children:t,initial:r})=>{let o=P(),n=i(D),l=d(),a=r??l?.preferences?.defaults,c=k(o,a),u=n&&!r&&n.kernel===o?n:c;return s(()=>u.connect(),[u]),s(()=>{c.setDefaults(a)},[c,a]),e(D.Provider,{value:u,children:t})},w=function(){let e=P(),t=i(D),r=d(),o=r?.preferences?.defaults,n=k(e,o),l=t?.kernel===e?t:n;return s(()=>l===t?void 0:l.connect(),[t,l]),s(()=>{n.setDefaults(o)},[n,o]),l},A=function(e){let t=p(P());return n(()=>t.current===e.kernel,[t,e])},R={ok:!1},x=function(e){let t=P(),r=i(f),o=A(e);return n((n,i)=>{if(!o())return Promise.resolve(R);let s=!1;return y(t,()=>e.save(n,r?.getConsentCategories(),()=>{s=!0},i),()=>s)},[o,t,e,r])},V=function(e){let t=c(e.subscribe,e.getSnapshot,e.getSnapshot),r=A(e);return l(()=>{let o=e=>(...t)=>{r()&&e(...t)};return{...t,acceptAll:o(e.acceptAll),rejectAll:o(e.rejectAll),reset:o(e.reset),save:(...t)=>r()?e.save(...t):Promise.resolve(R),set:o(e.set),setVendor:o(e.setVendor),update:o(e.update)}},[r,t,e])},_=function(){return x(w())},E=function(){return w()},q=function(e,t){let r=()=>t(e.getSnapshot());return c(e.subscribe,r,r)},J=function(){return V(w())},N=function(){let{isDirty:e,isStale:t,reset:r,save:o,setVendor:n,vendors:i}=V(w());return l(()=>({isDirty:e,isStale:t,reset:r,save:o,setVendor:n,vendors:i}),[e,t,r,o,n,i])};export{O as ConsentDraftProvider,J as useConsentDraft,q as useConsentDraftSlice,E as useConsentDraftStore,_ as useConsentSaveAction,N as useVendorDraft};
2
+ import{jsx as e}from"react/jsx-runtime";import{createPreferenceDraft as t}from"@c15t/core/preference-draft";import{useContext as r,useEffect as n,useMemo as s,useState as a,useSyncExternalStore as f}from"react";import{DraftContext as o,REFUSED as u,useDraftKernel as l,useKernelGuard as c}from"./draft-context.js";import{useResolvedPresentation as d}from"./hooks.js";let i=function(e,r){let[s,f]=a(()=>({draft:t(e,{defaults:r}),kernel:e}));if(n(()=>{s.draft.setDefaults(r)},[s.draft,r]),s.kernel===e)return s.draft;let o={draft:t(e,{defaults:r}),kernel:e};return f(o),o.draft},p=({children:t,initial:n})=>{let s=l(),a=r(o),f=d(),u=i(s,n??f?.preferences?.defaults),c=a&&!n&&a.kernel===s?a:u;return e(o.Provider,{value:c,children:t})},m=function(){let e=l(),t=r(o),n=i(e,d()?.preferences?.defaults);return t?.kernel===e?t:n},D=function(e){let t=f(e.subscribe,e.getState,e.getState),r=c(e.kernel);return s(()=>{let n=e=>(...t)=>{r()&&e(...t)};return{...t,acceptAll:n(e.acceptAll),rejectAll:n(e.rejectAll),reset:n(e.reset),save:()=>r()?e.save():Promise.resolve(u),set:n(e.set),setVendor:n(e.setVendor),update:n(e.update)}},[e,r,t])},C=function(){return m()},S=function(e,t){let r=()=>t(e.getState());return f(e.subscribe,r,r)},v=function(){return D(m())},j=function(){let{isDirty:e,isStale:t,reset:r,save:n,setVendor:a,vendors:f}=D(m());return s(()=>({isDirty:e,isStale:t,reset:r,save:n,setVendor:a,vendors:f}),[e,t,r,n,a,f])};export{p as ConsentDraftProvider,v as useConsentDraft,S as useConsentDraftSlice,C as useConsentDraftStore,j as useVendorDraft};
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e}from"react/jsx-runtime";import{useCallback as t,useEffect as r,useMemo as i,useState as o,useSyncExternalStore as n}from"react";import{IABContext as a}from"./context/iab-context-value.js";import{useCommittedRef as c}from"./hooks/use-committed-ref.js";let u=function(){return null},l=({runtime:l,children:s})=>{let[m,d]=o("purposes"),f=n(e=>l.onIABChange(e),()=>l.iab,u),p=i(()=>{let e,t,r;return e=!1,t=!1,{actions:r=[],activate:()=>{e=!0,t=!1},deactivate:()=>{e=!1,queueMicrotask(()=>{if(!e)for(let e of(t=!0,r.splice(0)))e.cancel()})},isClosed:()=>t,runtime:l}},[l]),v=c(p);r(()=>{p.activate();let e=()=>{let e=p.runtime.iab;if(e)for(let t of p.actions.splice(0))t.run(e)},t=p.runtime.onIABChange(e);return e(),()=>{t(),p.deactivate()}},[p]);let h=t(e=>{let t=new Promise((t,r)=>{let i=()=>r(new DOMException("External IAB provider unmounted or changed runtimes.","AbortError"));if(p.isClosed()||v.current!==p)return void i();let o=async i=>{try{await e(i),t()}catch(e){r(e)}},n=p.runtime.iab;n?o(n):p.actions.push({cancel:i,run:o})});return t.catch(()=>void 0),t},[v,p]),x=i(()=>({handle:f,run:h,setTab:d,tab:m}),[f,h,m]);return e(a.Provider,{value:x,children:s})};export{l as ExternalIABProvider};
2
+ import{jsx as e}from"react/jsx-runtime";import{useCallback as r,useEffect as t,useMemo as i,useState as o,useSyncExternalStore as n}from"react";import{IABContext as a}from"./context/iab-context-value.js";import{useCommittedRef as c}from"./hooks/use-committed-ref.js";let u=function(){return null},s=({runtime:s,children:l})=>{let[m,d]=o("purposes"),f=n(e=>s.subscribe(e),()=>s.iab,u),p=i(()=>{let e,r,t;return e=!1,r=!1,{actions:t=[],activate:()=>{e=!0,r=!1},deactivate:()=>{e=!1,queueMicrotask(()=>{if(!e)for(let e of(r=!0,t.splice(0)))e.cancel()})},isClosed:()=>r,runtime:s}},[s]),v=c(p);t(()=>{p.activate();let e=()=>{let e=p.runtime.iab;if(e)for(let r of p.actions.splice(0))r.run(e)},r=p.runtime.subscribe(e);return e(),()=>{r(),p.deactivate()}},[p]);let b=r(e=>{let r=new Promise((r,t)=>{let i=()=>t(new DOMException("External IAB provider unmounted or changed runtimes.","AbortError"));if(p.isClosed()||v.current!==p)return void i();let o=async i=>{try{await e(i),r()}catch(e){t(e)}},n=p.runtime.iab;n?o(n):p.actions.push({cancel:i,run:o})});return r.catch(()=>void 0),r},[v,p]),x=i(()=>({handle:f,run:b,setTab:d,tab:m}),[f,b,m]);return e(a.Provider,{value:x,children:l})};export{s as ExternalIABProvider};
package/dist/gpp.js ADDED
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{createGPP as t}from"@c15t/iab/gpp";import{useContext as r,useEffect as e}from"react";import{KernelContext as o}from"./context.js";let n=({cmpId:n,mspaMode:i,optOutCategories:s,tcf:l,usApproach:c,usFallback:p})=>{let m=r(o);if(!m)throw Error("c15t: ConsentGPP must be rendered inside <ConsentProvider> from @c15t/react.");let a=s?.join(",");return e(()=>{let r=null;try{r=t({cmpId:n,kernel:m,mspaMode:i,optOutCategories:a?.split(","),tcf:l,usApproach:c,usFallback:p})}catch(t){console.error("c15t: GPP was not installed.",t)}return()=>r?.dispose()},[a,n,m,i,l,c,p]),null};export{n as ConsentGPP};
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{setupColorScheme as e}from"@c15t/ui/utils";import{useEffect as o}from"react";let r=function(r){o(()=>{if(null!==r)return e(r)},[r])};export{r as useColorScheme};
2
+ import{setupColorScheme as e}from"@c15t/ui/utils/color-scheme";import{useEffect as o}from"react";let r=function(r){o(()=>{if(null!==r)return e(r)},[r])};export{r as useColorScheme};
package/dist/hooks.js CHANGED
@@ -1 +1 @@
1
- import{applyExperimentAssignment as e,applyExperimentTheme as s,isVendorAllowed as o}from"@c15t/core";import{useCallback as n,useContext as t,useMemo as u,useSyncExternalStore as r}from"react";import{ProviderServicesContext as i}from"./context.js";import{useGateSelector as a,useKernel as c,useKernelSelector as l}from"./kernel-selector.js";import{useUIConfig as f}from"./ui-config-context.js";import{invalidateConsentUIAction as h}from"./ui-save.js";let m=function(){let e=c();return r(s=>e.subscribe(s),()=>e.getSnapshot(),()=>e.getServerSnapshot())},p=function(e){return l(s=>s.effectivePermissions[e])},d=function(){return l(e=>e.effectivePermissions)},k=function(){return l(e=>e.overrides)},_=function(){return l(e=>e.user)},g=function(){return l(e=>e.location)},C=function(){return l(e=>e.translations)},P=function(){return l(e=>e.branding)},v=function(){return l(e=>"matched"===e.resolution.status)},S=function(){return l(e=>!e.externalPermissions&&"matched"===e.resolution.status&&("none"!==e.policyRule.prompt||e.policyRule.rights.length>0))},y=function(){return l(e=>!!e.externalPermissions||"matched"===e.resolution.status&&("none"!==e.policyRule.prompt||e.policyRule.rights.length>0))},R=function(){return l(e=>"matched"===e.resolution.status?e.model:null)},I=function(){return l(e=>e.activeUI)},b=function(){return l(e=>e.policyRule.scope)},x=function(){return l(e=>e.policyRule.scopeMode)},A=function(){return l(e=>e.iab)},U=function(){return l(e=>e.iab?.enabled??!1)},E=function(e){let s=String(e);return l(e=>e.iab?.vendorConsents[s]??!1)},T=function(e){return l(s=>s.iab?.purposeConsents[e]??!1)},V=function(e){return l(s=>s.iab?.specialFeatureOptIns[e]??!1)},D=function(){return l(e=>e.iab?.tcString??null)},O=[],B=function(){return l(e=>"iab"===e.model?O:e.vendors?.declared??O)},H=function(){return l(e=>e.vendorChoice)},L=function(e){return a((s,n)=>o(s,e,n))},M=function(){return c().set.registerConsentCategories},N=function(){return c().set.overrides},j=function(){let e=c(),s=t(i);return n(o=>{s?s.setLanguage(o):o!==e.getSnapshot().overrides.language&&(e.set.language(o),e.commands.init())},[e,s])},q=function(){let e=c();return n(s=>{h(e),e.set.activeUI(s)},[e])},F=function(){return c().commands.save},w=function(){let e=c();return n(s=>e.events.on("permissions:changed",({snapshot:e})=>s(e.effectivePermissions)),[e])},z=function(){return c().commands.identify},G=function(){return c().commands.init},J=function(){return l(e=>e.explicitChoice)},K=function(){return l(e=>e.effectivePermissions)},Q=function(){return l(e=>e.promptRequirement)},W=function(){return l(e=>e.noticeDismissal)},X=function(){return l(e=>e.privacySignals)},Y=function(){return l(e=>e.resolution)},Z=function(){return l(e=>e.policyRule)},$=function(){return l(e=>e.restrictions)},ee=function(){return c().commands.dismissNotice},es=function(){return l(e=>e.experiment)},eo=function(){let{experiment:s,presentation:o}=f(),n=es();return u(()=>e(o,s,n),[o,s,n])},en=function(){let{experiment:e,theme:o}=f(),n=es();return u(()=>s(o,e,n),[o,e,n])},et={},eu={},er=function(){return eo()?.prompt??et},ei=function(){return eo()?.preferences??eu};export{I as useActiveUI,P as useBranding,p as useConsent,d as useConsents,B as useDeclaredVendors,ee as useDismissNotice,K as useEffectivePermissions,es as useExperiment,J as useExplicitChoice,v as useHasConsentPolicy,y as useHasConsentPreferences,S as useHasConsentUI,U as useIABEnabled,A as useIABSnapshot,z as useIdentify,G as useInit,g as useLocation,R as useModel,W as useNoticeDismissal,k as useOverrides,b as usePolicyCategories,Y as usePolicyResolution,Z as usePolicyRule,x as usePolicyScopeMode,ei as usePreferencesPresentation,X as usePrivacySignals,er as usePromptPresentation,Q as usePromptRequirement,T as usePurposeConsent,M as useRegisterConsentCategories,eo as useResolvedPresentation,en as useResolvedTheme,$ as useRestrictions,F as useSaveConsents,q as useSetActiveUI,j as useSetLanguage,N as useSetOverrides,m as useSnapshot,V as useSpecialFeatureOptIn,w as useSubscribeToConsentChanges,D as useTCString,C as useTranslations,_ as useUser,L as useVendorAllowed,H as useVendorChoice,E as useVendorConsent};
1
+ import{applyExperimentAssignment as e,applyExperimentTheme as s,isVendorAllowed as o}from"@c15t/core";import{hasConsentPreferences as n,hasConsentUI as t,showConsentSurface as u}from"@c15t/core/surface-actions";import{useCallback as r,useContext as i,useMemo as a,useSyncExternalStore as c}from"react";import{ProviderServicesContext as f}from"./context.js";import{useGateSelector as l,useKernel as h,useKernelSelector as d}from"./kernel-selector.js";import{useUIConfig as m}from"./ui-config-context.js";let p=function(){let e=h();return c(s=>e.subscribe(s),()=>e.getSnapshot(),()=>e.getServerSnapshot())},k=function(e){return d(s=>s.effectivePermissions[e])},_=function(){return d(e=>e.effectivePermissions)},C=function(){return d(e=>e.overrides)},g=function(){return d(e=>e.user)},P=function(){return d(e=>e.location)},v=function(){return d(e=>e.translations)},S=function(){return d(e=>e.branding)},y=function(){return d(e=>"matched"===e.resolution.status)},I=function(){return d(t)},R=function(){return d(n)},b=function(){return d(e=>"matched"===e.resolution.status?e.model:null)},A=function(){return d(e=>e.activeUI)},x=function(){return d(e=>e.policyRule.scope)},U=function(){return d(e=>e.policyRule.scopeMode)},E=function(){return d(e=>e.iab)},T=function(){return d(e=>e.iab?.enabled??!1)},V=function(e){let s=String(e);return d(e=>e.iab?.vendorConsents[s]??!1)},D=function(e){return d(s=>s.iab?.purposeConsents[e]??!1)},O=function(e){return d(s=>s.iab?.specialFeatureOptIns[e]??!1)},B=function(){return d(e=>e.iab?.tcString??null)},H=[],L=function(){return d(e=>"iab"===e.model?H:e.vendors?.declared??H)},M=function(){return d(e=>e.vendorChoice)},N=function(e){return l((s,n)=>o(s,e,n))},j=function(){return h().set.registerConsentCategories},q=function(){return h().set.overrides},F=function(){let e=h(),s=i(f);return r(o=>{s?s.setLanguage(o):o!==e.getSnapshot().overrides.language&&(e.set.language(o),e.commands.init())},[e,s])},w=function(){let e=h();return r(s=>u(e,s),[e])},z=function(){return h().commands.save},G=function(){let e=h();return r(s=>e.events.on("permissions:changed",({snapshot:e})=>s(e.effectivePermissions)),[e])},J=function(){return h().commands.identify},K=function(){return h().commands.init},Q=function(){return d(e=>e.explicitChoice)},W=function(){return d(e=>e.effectivePermissions)},X=function(){return d(e=>e.promptRequirement)},Y=function(){return d(e=>e.noticeDismissal)},Z=function(){return d(e=>e.privacySignals)},$=function(){return d(e=>e.resolution)},ee=function(){return d(e=>e.policyRule)},es=function(){return d(e=>e.restrictions)},eo=function(){return h().commands.dismissNotice},en=function(){return d(e=>e.experiment)},et=function(){let{experiment:s,presentation:o}=m(),n=en();return a(()=>e(o,s,n),[o,s,n])},eu=function(){let{experiment:e,theme:o}=m(),n=en();return a(()=>s(o,e,n),[o,e,n])},er={},ei={},ea=function(){return et()?.prompt??er},ec=function(){return et()?.preferences??ei};export{A as useActiveUI,S as useBranding,k as useConsent,_ as useConsents,L as useDeclaredVendors,eo as useDismissNotice,W as useEffectivePermissions,en as useExperiment,Q as useExplicitChoice,y as useHasConsentPolicy,R as useHasConsentPreferences,I as useHasConsentUI,T as useIABEnabled,E as useIABSnapshot,J as useIdentify,K as useInit,P as useLocation,b as useModel,Y as useNoticeDismissal,C as useOverrides,x as usePolicyCategories,$ as usePolicyResolution,ee as usePolicyRule,U as usePolicyScopeMode,ec as usePreferencesPresentation,Z as usePrivacySignals,ea as usePromptPresentation,X as usePromptRequirement,D as usePurposeConsent,j as useRegisterConsentCategories,et as useResolvedPresentation,eu as useResolvedTheme,es as useRestrictions,z as useSaveConsents,w as useSetActiveUI,F as useSetLanguage,q as useSetOverrides,p as useSnapshot,O as useSpecialFeatureOptIn,G as useSubscribeToConsentChanges,B as useTCString,v as useTranslations,g as useUser,N as useVendorAllowed,M as useVendorChoice,V as useVendorConsent};
@@ -0,0 +1 @@
1
+ export{ConsentBanner,useConsentBannerSurface}from"../components/prompt/index.js";
@@ -0,0 +1 @@
1
+ export{ConsentDialogLink}from"../components/panel-link/index.js";
@@ -0,0 +1 @@
1
+ export{ConsentDialogTrigger,ConsentDialogTriggerToolbar}from"../components/panel-trigger/index.js";
@@ -0,0 +1 @@
1
+ export{ConsentDialog,ConsentWidget}from"../aggregate-components.js";
@@ -0,0 +1 @@
1
+ export{ConsentGate,Frame}from"../components/consent-gate/index.js";
@@ -0,0 +1 @@
1
+ export{createConsentKernel,custom,hosted}from"@c15t/core";export{offline}from"../transports/offline.js";
@@ -0,0 +1 @@
1
+ export{ConsentDraftProvider,useConsentDraft,useVendorDraft}from"../draft.js";
@@ -0,0 +1 @@
1
+ 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 @@
1
+ export{useIframeBlocker,useNetworkBlocker,usePersistence,useScriptLoader}from"../module-hooks.js";
@@ -0,0 +1 @@
1
+ export{ConsentProvider}from"../provider.js";
@@ -0,0 +1 @@
1
+ export{ConsentTheme}from"../consent-theme.js";export{defineTheme}from"../types/theme/index.js";
@@ -0,0 +1 @@
1
+ export{useTranslations}from"../component-hooks/use-translations.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{createConsentKernel,custom,hosted}from"@c15t/core";export{offline}from"./transports/offline.js";export{ConsentDialog,ConsentWidget}from"./aggregate-components.js";export{ConsentBanner,useConsentBannerSurface}from"./components/prompt/index.js";export{ConsentDialogLink}from"./components/panel-link/index.js";export{ConsentDialogTrigger,ConsentDialogTriggerToolbar}from"./components/panel-trigger/index.js";export{ConsentGate,Frame}from"./components/consent-gate/index.js";export{ConsentDraftProvider,useConsentDraft,useVendorDraft}from"./draft.js";export{useTranslations}from"./component-hooks/use-translations.js";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";export{useIframeBlocker,useNetworkBlocker,usePersistence,useScriptLoader}from"./module-hooks.js";export{ConsentProvider}from"./provider.js";export{ConsentTheme}from"./consent-theme.js";export{defineTheme}from"./types/theme/index.js";
1
+ export*from"./index-parts/core.js";export*from"./index-parts/consent-dialog.js";export*from"./index-parts/consent-banner.js";export*from"./index-parts/consent-dialog-link.js";export*from"./index-parts/consent-dialog-trigger.js";export*from"./index-parts/consent-gate.js";export*from"./index-parts/draft.js";export*from"./index-parts/translations.js";export*from"./index-parts/module-hooks.js";export*from"./index-parts/provider.js";export*from"./index-parts/theme.js";export*from"./index-parts/hooks.js";
@@ -1 +1 @@
1
- import{evaluateConsent as e}from"@c15t/core";import{useContext as t,useMemo as r,useSyncExternalStore as o}from"react";import{KernelContext as n}from"./context.js";import{defaultTranslationConfig as s}from"./utils/default-translation-config.js";let a=function(){let e=t(n);if(!e)throw Error("c15t: no kernel in context. Wrap your app with <ConsentProvider options={...}> from @c15t/react.");return e},l=function(e){let t=a();return o(e=>t.subscribe(e),()=>e(t.getSnapshot()),()=>e(t.getServerSnapshot()))},u=function(e){let t=a();return o(e=>t.subscribe(e),()=>e(t.getSnapshot(),Date.now()),()=>{let r=t.getServerSnapshot();return e(r,r.evaluatedAt)})},c=function(t){return u((r,o)=>e({category:t},r,o))},i=function(){return l(e=>e.translations?.language??s.defaultLanguage)},p=function(){let e=l(e=>e.evaluationPolicy.choiceScope??e.policyRule.scope);return r(()=>["necessary",...e],[e])};export{c as useCategoryAllowed,p as useDisplayedCategories,u as useGateSelector,a as useKernel,l as useKernelSelector,i as useTranslationLanguage};
1
+ import{evaluateConsent as e}from"@c15t/core";import{useContext as t,useSyncExternalStore as r}from"react";import{KernelContext as n}from"./context.js";import{defaultTranslationConfig as o}from"./utils/default-translation-config.js";let a=function(){let e=t(n);if(!e)throw Error("c15t: no kernel in context. Wrap your app with <ConsentProvider options={...}> from @c15t/react.");return e},s=function(e){let t=a();return r(e=>t.subscribe(e),()=>e(t.getSnapshot()),()=>e(t.getServerSnapshot()))},l=function(e){let t=a();return r(e=>t.subscribe(e),()=>e(t.getSnapshot(),Date.now()),()=>{let r=t.getServerSnapshot();return e(r,r.evaluatedAt)})},u=function(t){return l((r,n)=>e({category:t},r,n))},c=function(){return s(e=>e.translations?.language??o.defaultLanguage)};export{u as useCategoryAllowed,l as useGateSelector,a as useKernel,s as useKernelSelector,c as useTranslationLanguage};
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{allConsentNames as e,getEffectiveGateState as t,has as r,isVendorDenied as a}from"@c15t/core";import{useEffect as o,useRef as c,useState as n}from"react";import{useRequiredKernel as u}from"./shared.js";let i=()=>import("@c15t/core/modules/iframe-blocker"),l=function(e={}){let t=u(),r=c(null),[a,l]=n(()=>({dispose(){r.current?.dispose(),r.current=null},processAllIframes(){r.current?.processAllIframes()}}));return o(()=>{let a=!1;return(async()=>{let{createIframeBlocker:o}=await i();a||(r.current=o({disableAutomaticBlocking:e.disableAutomaticBlocking,kernel:t}))})(),()=>{a=!0,r.current?.dispose(),r.current=null}},[t,e.disableAutomaticBlocking]),a},d="iframe[data-category], iframe[data-vendor]",s=function(e){try{return 1===e.nodeType&&"IFRAME"===e.tagName.toUpperCase()}catch{return!1}},f=function(o,c){let n=c.getSnapshot(),u=o.getAttribute("data-category");if(null!==u){if(!e.includes(u))return!1;let{effectivePermissions:a}=t(n);if(!r(u,a))return!1}let i=o.getAttribute("data-vendor");return!i||"iab"===n.model||!(n.vendorChoice?.denied.includes(i)&&(!n.vendors?.declared.some(e=>e.id===i)||a(n,i)))},m=function(e,t){let r=e.getAttribute("src");!(r&&e.matches(d))||f(e,t)||(e.hasAttribute("data-src")||e.setAttribute("data-src",r),e.removeAttribute("src"),e.setAttribute("data-c15t-paused",""))},b=function(e){try{return e.matches(d)}catch{return!1}},y=function(e){let t=new Set;for(let r of e)for(let e of("attributes"===r.type&&s(r.target)&&t.add(r.target),Array.from(r.addedNodes))){if(s(e)){t.add(e);continue}try{if(1===e.nodeType)for(let r of Array.from(e.querySelectorAll("iframe")))t.add(r)}catch{}}return[...t].filter(b)},p=function(e,t){if("u"<typeof document||!document.body)return t(),()=>{};document.querySelector(d)&&t();let r=new MutationObserver(r=>{let a=y(r);if(0!==a.length){for(let t of a)try{m(t,e)}catch{}t()}});return r.observe(document.body,{attributeFilter:["data-category","data-vendor","src"],attributes:!0,childList:!0,subtree:!0}),()=>r.disconnect()},A=function(e={}){let t=u(),{disableAutomaticBlocking:r}=e;o(()=>{let e=!1,a=null,o=!1,c=()=>{},n=()=>{o||(o=!0,(async()=>{let n;try{n=await i()}catch{o=!1;return}e||(c(),a=n.createIframeBlocker({disableAutomaticBlocking:r,kernel:t}))})())};return r?n():c=p(t,n),()=>{e=!0,c(),a?.dispose(),a=null}},[t,r])};export{l as useIframeBlocker,A as useIframeBlockerOnDemand,p as watchGatedIframes};
2
+ import{allConsentNames as e,getEffectiveGateState as t,has as r,isVendorDenied as a}from"@c15t/core";import{useEffect as o,useRef as c,useState as n}from"react";import{useRequiredKernel as i}from"./shared.js";let l=()=>import("@c15t/core/modules/iframe-blocker"),u=function(e={}){let t=i(),r=c(null),[a,u]=n(()=>({dispose(){r.current?.dispose(),r.current=null},processAllIframes(){r.current?.processAllIframes()}}));return o(()=>{let a=!1;return(async()=>{let{createIframeBlocker:o}=await l();a||(r.current=o({disableAutomaticBlocking:e.disableAutomaticBlocking,kernel:t}))})(),()=>{a=!0,r.current?.dispose(),r.current=null}},[t,e.disableAutomaticBlocking]),a},s="iframe[data-category], iframe[data-vendor]",d=function(e){try{return 1===e.nodeType&&"IFRAME"===e.tagName.toUpperCase()}catch{return!1}},f=function(o,c){let n=c.getSnapshot(),i=o.getAttribute("data-category");if(null!==i){if(!e.includes(i))return!1;let{effectivePermissions:a}=t(n);if(!r(i,a))return!1}let l=o.getAttribute("data-vendor");return!l||"iab"===n.model||!(n.vendorChoice?.denied.includes(l)&&(!n.vendors?.declared.some(e=>e.id===l)||a(n,l)))},m=function(e,t){let r=e.getAttribute("src");!(r&&e.matches(s))||f(e,t)||(e.hasAttribute("data-src")||e.setAttribute("data-src",r),e.removeAttribute("src"),e.setAttribute("data-c15t-paused",""))},b=function(e){try{return e.matches(s)}catch{return!1}},p=function(e){let t=new Set;for(let r of e)for(let e of("attributes"===r.type&&d(r.target)&&t.add(r.target),Array.from(r.addedNodes))){if(d(e)){t.add(e);continue}try{if(1===e.nodeType)for(let r of Array.from(e.querySelectorAll("iframe")))t.add(r)}catch{}}return[...t].filter(b)},y=function(e,t){if("u"<typeof document||!document.body)return t(),()=>{};document.querySelector(s)&&t();let r=new MutationObserver(r=>{let a=p(r);if(0!==a.length){for(let t of a)try{m(t,e)}catch{}t()}});return r.observe(document.body,{attributeFilter:["data-category","data-vendor","src"],attributes:!0,childList:!0,subtree:!0}),()=>r.disconnect()},A=function({disableAutomaticBlocking:e,kernel:t}){let r=!1,a=null,o=!1,c=()=>{},n=()=>{o||(o=!0,(async()=>{let n;try{n=await l()}catch{o=!1;return}r||(c(),a=n.createIframeBlocker({disableAutomaticBlocking:e,kernel:t}))})())};return e?n():c=y(t,n),{dispose(){r=!0,c(),a?.dispose(),a=null},processAllIframes(){a?.processAllIframes()}}};export{A as createIframeBlockerOnDemand,u as useIframeBlocker,y as watchGatedIframes};
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{applyExperimentAssignment as t,applyExperimentTheme as o,createConsentKernel as i,declareOwnedVendors as s,disabledPolicyResolution as l,extractConsentNamesFromCondition as c,forgetOwnedVendors as a,hostExperiment as u,kernelConfigToInitResponse as d,resolveLocalTranslations as p,resolveVendors as m,seedExperiment as g,startExperiment as f,watchRevocationReload as v}from"@c15t/core";import{createWindowDebug as h,resolveWindowDebugMode as y}from"@c15t/core/modules/window-debug";import{connectConsentSource as k}from"@c15t/core/runtime/controls";import{deepMergeTranslations as S}from"@c15t/translations";import{applyThemeSlots as C}from"@c15t/ui/utils";import{useContext as b,useEffect as w,useMemo as x,useRef as R,useState as P,useSyncExternalStore as O}from"react";import{KernelContext as E,ProviderServicesContext as N}from"./context.js";import{ExternalIABProvider as B}from"./external-iab-context.js";import{useColorScheme as D}from"./hooks/use-color-scheme.js";import{useIframeBlockerOnDemand as j}from"./module-hooks/iframe-blocker.js";import{useEarlyNetworkHold as L}from"./module-hooks/network-hold.js";import{usePersistence as V}from"./module-hooks/persistence.js";import{V3ThemeProvider as T}from"./theme-provider.js";import{defaultTranslationConfig as _}from"./utils/default-translation-config.js";let M={language:"en",translations:_.translations.en},q=function(e){if(e)return"externalId"in e?e:{externalId:e.id,identityProvider:e.identityProvider}},A=function(e){if(!e?.messages)return;let r=e.locale??_.defaultLanguage??"en",n=_.translations.en,t=e.messages[r]??e.messages.en??n,o=_.translations[r]??n;return{language:r,translations:S(o,t)}},J=function(e){return e.enabled??!0},K=function(e,r){let n=!1;return{...e,async init(t){if(n)return e.init?.(t)??{};n=!0;let o=await r(t);return o.response?o.response:e.init?.(o.context??t)??{}}}},F=function(e){return"function"==typeof e?.then},I=function(e){let{prefetch:r}=e;return!r||F(r)?{}:r},H=function(e){let{prefetch:r}=e;return u(e.experiment,F(r)?void 0:r)},U=function(){"production"!==globalThis.process?.env?.NODE_ENV&&console.warn("c15t ConsentProvider: the streamed consent state carries an experiment, but the provider mounted before it arrived and runs none. Await resolveConsent(), or also pass `experiment` to the provider options.")},G=function(e){return void 0!==e&&Object.keys(e).length>0},W=function(e){"production"!==globalThis.process?.env?.NODE_ENV&&console.warn("c15t ConsentProvider: prefetch rejected; using transport init.",e)},z=function(e,r,n,t){let o={...r.initialOverrides??{},...n??{}};G(o)&&e.set.overrides(o),r.initialRecords&&e.getRecordsGeneration()===t&&e.hydrate(r.initialRecords)},Q=function(e,r,n,t){var o,i,s;let{prefetch:l}=r;return F(l)?K(e,(o=Promise.resolve(l),i=r.overrides,s=void 0!==r.experiment,async e=>{let r,l=n()?.getRecordsGeneration();try{r=await o??{}}catch(e){return W(e),{}}r.experiment&&!s&&U(),t(r);let c=d(r);if(c){let e={...c.resolvedOverrides??{},...i??{}};return G(e)&&(c.resolvedOverrides=e),{response:c}}let a=n();return a&&z(a,r,i,l),{context:{overrides:{...e.overrides,...r.initialOverrides??{},...i??{}},user:e.user}}})):e},X=function(e){if("function"!=typeof e.mode)throw Error("c15t ConsentProvider: set mode to hosted(), offline(), or custom().");return e.mode},Y=function(e){"production"!==globalThis.process?.env?.NODE_ENV&&console.warn(e)},Z=function(e,r,n){let t=m({config:e.vendors,existing:n.initialVendors?.declared,onWarn:Y,owners:r}),o=n.initialVendors?.listVersion??null;return t.length>0||null!==o?{declared:t,listVersion:o}:void 0},$=function(e){let r=J(e),n=I(e),t=A(e.i18n)??M,o=n,s={consentCategories:e.consentCategories,get prefetch(){return o},translations:t,translationsFor:r=>p(r,e.i18n?.messages)},a=X(e)(s),u={current:null},d=Q(a,e,()=>u.current,e=>{o=e}),m=[...e.scripts??[],...e.networkBlocker?e.networkBlocker.rules??[]:[]],f=Z(e,m,n),v=r?g(H(e),n.initialExperiment,!!n.initialPolicyResolution&&!n.initialPolicyPending):{},h=i({...n,consentCategories:e.consentCategories,inferredConsentCategories:[...m.flatMap(e=>c(e.category)),...(f?.declared??[]).flatMap(e=>c(e.category))],initialExperiment:v.initialExperiment,initialExperimentPending:v.initialExperimentPending,initialVendors:f,initialExternalPermissions:r&&e.consentSource?{}:void 0,initialRecords:r&&!e.consentSource?n.initialRecords:void 0,initialPrivacySignals:r?n.initialPrivacySignals:void 0,now:n.now??n.initialRecords?.now??(n.initialRecords?void 0:0),transport:d,initialPolicyResolution:r?n.initialPolicyResolution:l(),initialOverrides:{...n.initialOverrides??{},...e.overrides??{}},initialUser:q(e.user)??n.initialUser,initialTranslations:n.initialTranslations??t,translationOverrides:e.i18n?.messages,initialPolicyPending:!e.consentSource&&(n.initialPolicyPending??(r&&!n.initialPolicyResolution))});return u.current=h,h},ee=function(e){if(e instanceof Error)return e.message;if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}},er=function(e,r,n){let t=R(r),o=R(n);w(()=>{t.current=r,o.current=n},[r,n]),w(()=>v({getOnBeforeReload:()=>t.current?.onBeforeConsentRevocationReload,isEnabled:()=>!1!==o.current,kernel:e}),[e]),w(()=>{let r=[e.events.on("init:applied",({snapshot:r})=>{let n=r.vendors?.declared??[];n.length>0&&e.set.registerConsentCategories(n.flatMap(e=>c(e.category)))}),e.events.on("choice:recorded",({type:e,...r})=>{t.current?.onChoiceRecorded?.(r)}),e.events.on("permissions:changed",({snapshot:e,previous:r})=>{t.current?.onPermissionsChanged?.({previous:r,snapshot:e})}),e.events.on("surface:shown",({type:e,...r})=>{t.current?.onSurfaceShown?.(r)}),e.events.on("command:error",e=>{t.current?.onError?.({error:ee(e.error)})})];return()=>{for(let e of r)e()}},[e])},en=function(e,r,n,t){let o=R(n),i=R(null),l=R(null),u=R(null);w(()=>{if(!t)return;let n=q(r.user),o=JSON.stringify(n??null);if(null===i.current){i.current=o;return}i.current!==o&&(i.current=o,n&&(async()=>{try{await e.commands.identify(n)}catch{}})())},[e,r.user,t]),w(()=>{if(!t)return;let o=JSON.stringify(r.overrides??{});if(null===l.current){l.current=o;return}l.current!==o&&(l.current=o,e.set.overrides(r.overrides??{}),n&&e.commands.init())},[n,e,r.overrides,t]),w(()=>{!t||o.current===n||(o.current=n,n||e.set.activeUI("none"))},[n,e,t]);let d=R(null),p=R(Symbol("consent-provider"));w(()=>{if(!t)return;let n=[...r.scripts??[],...r.networkBlocker?r.networkBlocker.rules??[]:[]],o=JSON.stringify([r.vendors??[],n.map(e=>[e.vendor??null,e.category])]);if(null===d.current){d.current=o,s(e,n,p.current);return}if(d.current===o)return;d.current=o;let i=e.getSnapshot().vendors?.declared??[],l=m({config:r.vendors,existing:i.flatMap(e=>{let r="manifest"===e.source?e:e.shadowed;if(r?.source!=="manifest")return[];let{ownerCategory:n,...t}=r;return[t]}),onWarn:Y});e.set.vendors({declared:l},{replaceSource:"config"}),s(e,n,p.current);let a=[...l.flatMap(e=>c(e.category)),...n.flatMap(e=>c(e.category))];a.length>0&&e.set.registerConsentCategories(a)},[e,r.networkBlocker,r.scripts,r.vendors,t]),w(()=>()=>{a(e,p.current),d.current=null},[e]),w(()=>{if("production"===globalThis.process?.env?.NODE_ENV)return;let e=JSON.stringify({experiment:H(r),i18n:r.i18n,mode:r.mode?.kind});if(null===u.current){u.current=e;return}u.current!==e&&(u.current=e,console.warn("c15t ConsentProvider: remount to change mode, i18n or experiment."))},[r])},et=({kernel:e,callbacks:r,reloadOnConsentRevoked:n})=>(er(e,r,n),null),eo=({enabled:e,kernel:r,prepared:n})=>{let t=R(!1),o=R(!1);return w(()=>{if(!e){t.current=!1;return}if(!t.current)if(t.current=!0,n){r.hydrate({now:o.current?Date.now():r.getServerSnapshot().evaluatedAt}),o.current=!0,r.markLive();let{gpc:e}=r.getSnapshot().privacySignals;e.detected&&e.active&&r.set.privacySignals({gpc:!0})}else r.commands.init()},[e,r,n]),null},ei=[],es=({clearOnRevocation:e,storageConfig:r,nonce:n,options:t,scripts:o=ei})=>{let i=b(E),s=R(null),l=R(null),c=R(null),a=R({config:e,storageConfig:r}),[u,d]=P(o.length>0),p=R(o),m=R(t),g=R(n);o.length>0&&!u&&d(!0),w(()=>{a.current={config:e,storageConfig:r},p.current=o,m.current=t,g.current=n},[e,r,n,t,o]),w(()=>{if(!i)return;let e=!1;return(async()=>{if(u){let{createScriptLoader:r}=await import("@c15t/core/modules/script-loader");if(e)return;s.current=r({kernel:i,nonce:g.current,onDebug:m.current?.onDebug,scripts:p.current})}let{config:r}=a.current;if(r){let{createClearOnRevocation:n}=await import("@c15t/core/modules/clear-on-revocation");if(e)return;c.current={config:r,create:n},l.current=n({config:r,kernel:i,storageConfig:a.current.storageConfig})}})(),()=>{e=!0,l.current?.dispose(),l.current=null,c.current=null,s.current?.dispose(),s.current=null}},[i,u]);let f=r?.storageKey;return w(()=>{let e=c.current;i&&e&&(l.current?.dispose(),l.current=e.create({config:e.config,kernel:i,storageConfig:{storageKey:f}}))},[i,f]),w(()=>{s.current?.updateScripts(o)},[o]),null},el=({options:e})=>(j(e),null),ec=({options:e})=>{let r=b(E),n=R(null),t=R(e),o=L(e.rules,e.enabled);return w(()=>{t.current=e},[e]),w(()=>{if(!r)return;let e=!1,i=o.claim(t.current.rules,t.current.enabled);return(async()=>{let{createNetworkBlocker:o}=await import("@c15t/core/modules/network-blocker");if(e)return;let s=t.current;n.current=o({enabled:s.enabled,hold:i,kernel:r,logBlockedRequests:s.logBlockedRequests,onRequestBlocked:s.onRequestBlocked,rules:s.rules})})(),()=>{e=!0,n.current?.dispose(),n.current=null,o.unmount()}},[o,r]),w(()=>{n.current?.updateRules(e.rules)},[e.rules]),w(()=>{void 0!==e.enabled&&n.current?.setEnabled(e.enabled)},[e.enabled]),null},ea=({options:e,clearRef:r})=>{let n=V(e);return w(()=>(r.current=n.clear,()=>{r.current=null}),[n,r]),null},eu=({experiment:e,kernel:r,options:n})=>(w(()=>f({...n,experiment:e,kernel:r}),[e,r,n]),null),ed=({pkg:e,mode:r})=>(w(()=>{let n=h({mode:r,pkg:e});return()=>n.dispose()},[r,e]),null),ep=function(e){if(!1===e.persistence)return!1;let{storageConfig:r}=e,n=!!I(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}},em=function(e,r,n){let t=e.external?r??e.external:void 0,o=t?.kernel??e.kernel;return{active:o,external:t,rendered:n?o:e.disabledKernel??o}},eg=i=>{let{children:s}=i,l=i.options??{},c=J(l),[a,u]=P(()=>({clearOnRevocation:l.clearOnRevocation,consentSource:l.consentSource,disabledKernel:i.runtime?void 0:$({...l,enabled:!1}),experiment:H(l),experimentOptions:{presentation:l.presentation,storageConfig:l.storageConfig,theme:l.theme},external:i.runtime,kernel:i.runtime?.kernel??$({...l,enabled:!0})})),{clearOnRevocation:d,experiment:p}=a,{active:m,external:g,rendered:f}=em(a,i.runtime,c),v=void 0===g;w(()=>{(v||void 0!==l.consentCategories)&&f.set.consentCategories(l.consentCategories)},[f,v,l.consentCategories]);let h=R(null),S=function({clearRef:e,consentSource:r,enabled:n,experiment:o,externalRuntime:i,kernel:s,presentation:l}){return x(()=>({clearRecords:()=>{i?i.clearRecords():e.current?e.current():(s.hydrate({choice:null,noticeDismissal:null,subject:null,vendorChoice:null}),s.events.emit({type:"records:cleared"}))},getConsentCategories:()=>{let e=s.getSnapshot();return["necessary",...e.evaluationPolicy.choiceScope??e.policyRule.scope]},getPresentation:()=>t(l,o,s.getSnapshot().experiment),setLanguage:e=>{if(e!==s.getSnapshot().overrides.language){if(s.set.language(e),i)return void i.reinit();n&&!r&&s.commands.init()}}}),[e,s,l,o,i,n,r])}({clearRef:h,consentSource:a.consentSource,enabled:c,experiment:p,externalRuntime:g,kernel:f,presentation:l.presentation}),b=a.consentSource?void 0:ep(l),{scripts:j,networkBlocker:L}=l;w(()=>{if(v&&a.consentSource&&c)return k(f,a.consentSource)},[c,f,a,v]);let V=l.__debugPkg??"@c15t/react",_=v?y(l.mode):"hosted";en(m,l,c,v);let M=R(0);w(()=>{if(!v)return;M.current+=1;let e=M.current;return()=>{queueMicrotask(()=>{M.current===e&&(a.kernel.dispose(),a.disabledKernel?.dispose())})}},[a,v]);let q=!v&&void 0!==l.callbacks;w(()=>{"production"!==process.env.NODE_ENV&&q&&console.warn("c15t ConsentProvider: `options.callbacks` is ignored when you pass `runtime`. Pass them to createConsentRuntime({ callbacks }) instead.")},[q]);let A=O(e=>f.subscribe(e),()=>f.getSnapshot().experiment,()=>f.getServerSnapshot().experiment),K=x(()=>o(l.theme,p,A),[l.theme,p,A]);w(()=>{"production"===process.env.NODE_ENV||!K||!["colors","dark","motion","radius","shadows","spacing","typography"].some(e=>e in K)||document.getElementById("c15t-theme")||console.warn("c15t: `theme` tokens are no longer turned into CSS in the browser. Render <ConsentTheme theme={theme} /> on the server, or put the CSS from generateThemeCSS() in your stylesheet. See https://c15t.com/docs/frameworks/react/customize")},[K]);let F=x(()=>({colorScheme:l.colorScheme,disableAnimation:l.disableAnimation,noStyle:l.noStyle,scrollLock:l.scrollLock,theme:K,trapFocus:l.trapFocus}),[K,l.noStyle,l.disableAnimation,l.scrollLock,l.trapFocus,l.colorScheme]),U=x(()=>({components:C(K?.slots,l.components,"className"),experiment:p,legalLinks:l.legalLinks,preloadDialog:l.preloadDialog,presentation:l.presentation,theme:l.theme}),[K?.slots,l.components,p,l.legalLinks,l.preloadDialog,l.presentation,l.theme]);D(l.colorScheme);let G=n(e,{children:[v?n(e,{children:[r(et,{kernel:f,callbacks:l.callbacks,reloadOnConsentRevoked:l.reloadOnConsentRevoked}),r(ed,{pkg:V,mode:_}),c&&b?r(ea,{options:b,clearRef:h}):null,c&&p&&!g&&!a.consentSource?r(eu,{experiment:p,kernel:f,options:a.experimentOptions}):null,r(eo,{enabled:c&&!a.consentSource,prepared:!!I(l).initialPolicyResolution,kernel:f}),j&&j.length>0||c&&d?r(es,{clearOnRevocation:c?d:void 0,storageConfig:b?b.storageConfig:l.storageConfig,nonce:l.nonce,options:l.scriptLoader,scripts:j}):null,c&&!1!==l.iframeBlocker?r(el,{options:l.iframeBlocker}):null,c&&L?r(ec,{options:L}):null]}):null,g?r(B,{runtime:g,children:s}):s]});return r(E.Provider,{value:f,children:r(N.Provider,{value:S,children:r(T,{themeConfig:F,uiConfig:U,children:G})})})};export{eg as ConsentProvider};
2
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{applyExperimentAssignment as o,applyExperimentTheme as r,hostExperiment as n,watchRevocationReload as i}from"@c15t/core";import{createPersistence as c}from"@c15t/core/modules/persistence";import{createWindowDebug as s}from"@c15t/core/modules/window-debug";import{createConsentProviderRuntime as a,lazyRuntimeModule as l,lazyStreamPrefetch as m,streamPrefetchWith as u}from"@c15t/core/runtime/provider";import{applyThemeSlots as d}from"@c15t/ui/utils";import{useCallback as p,useEffect as h,useLayoutEffect as f,useMemo as g,useReducer as k,useState as v,useSyncExternalStore as y}from"react";import{KernelContext as b,ProviderServicesContext as S}from"./context.js";import{ExternalIABProvider as w}from"./external-iab-context.js";import{useColorScheme as C}from"./hooks/use-color-scheme.js";import{createIframeBlockerOnDemand as x}from"./module-hooks/iframe-blocker.js";import{UNCOMMITTED_HOLD_MS as L}from"./module-hooks/network-hold.js";import{V3ThemeProvider as j}from"./theme-provider.js";let P=(e,t)=>{let o,r=!1;return(async()=>{try{let{connectConsentSource:n}=await import("@c15t/core/runtime/controls");r||(o=n(e,t))}catch{}})(),()=>{r=!0,o?.()}},N=new WeakMap,R=function(e){if("function"!=typeof e)return e;let t=N.get(e);return t||(t=Object.assign(t=>e(Object.create(t,{iabEnabled:{value:void 0}})),{kind:e.kind}),N.set(e,t)),t},O=function(e){return{...e,mode:R(e.mode),pkg:e.__debugPkg??"@c15t/react"}},D=new Set,E=0,_=function(e){var t;let o,{networkBlocker:r}=e,n=a(O(e),(t=e.__resolveStreamedInit,{connectConsentSource:P,createClearOnRevocation:l(async()=>(await import("@c15t/core/modules/clear-on-revocation")).createClearOnRevocation),createIframeBlocker:x,createNetworkBlocker:l(async()=>(await import("@c15t/core/modules/network-blocker")).createNetworkBlocker),createPersistence:c,createScriptLoader:l(async()=>(await import("@c15t/core/modules/script-loader")).createScriptLoader),createWindowDebug:s,streamPrefetch:t?u(t):m,watchRevocationReload:i})),d=e,p=!1,h=!1,f=0;E+=1;let g={expire(){D.delete(g),clearTimeout(o),p=!0,n.dispose()},holdKey:!1!==e.enabled&&r&&!1!==r.enabled?JSON.stringify(r.rules):null,sequence:E};"u"<typeof window?h=!0:(D.add(g),o=setTimeout(g.expire,L));let k=function(){if(p)return!1;if(h)return!0;if(h=!0,D.delete(g),clearTimeout(o),null!==g.holdKey)for(let e of D)e.sequence<g.sequence&&e.holdKey===g.holdKey&&e.expire();return!0};return{apply(e){e!==d&&(d=e,n.update(O(e)).catch(()=>void 0))},mount(){if(!k())return null;let e=f+=1;return n.start(),()=>{queueMicrotask(()=>{f===e&&n.dispose()})}},runtime:n}},T=function(){let e=null;return{get:t=>e??=_(t),reset(){e=null}}},q=e=>e+1,B=function(e){let[t]=v(T),[,o]=k(q,0),r=p(()=>{t.reset(),o()},[t]);return e?{entry:t.get(e),rebuild:r}:void 0},K="u"<typeof document?h:f,A=({entry:e,options:t,rebuild:o})=>(K(()=>e.apply(t),[e,t]),h(()=>{let t=e.mount();return t||void o()},[e,o]),null),F=()=>()=>void 0,I=i=>{let{children:c}=i,s=i.options??{},[a]=v(()=>i.runtime),l=B(a?void 0:s),m=l?.entry.runtime,u=a?i.runtime??a:void 0,p=m??u,f=y(m?m.subscribe:F,()=>p.kernel,()=>p.kernel),[k]=v(()=>{var e;return a?a.experiment??n(s.experiment,(e=s.prefetch,"function"==typeof e?.then)?void 0:s.prefetch):void 0}),x=m?m.experiment:k,L=u?s.consentCategories:void 0;h(()=>{u&&void 0!==L&&u.setConsentCategories(L)},[u,L]);let{presentation:P}=s,N=g(()=>({clearRecords:()=>p.clearRecords(),getConsentCategories:()=>p.consentCategories,getPresentation:()=>o(P,x,f.getSnapshot().experiment),setLanguage:e=>p.setLanguage(e)}),[x,f,P,p]),R=!!u&&void 0!==s.callbacks;h(()=>{"production"!==process.env.NODE_ENV&&R&&console.warn("c15t ConsentProvider: `options.callbacks` is ignored when you pass `runtime`. Pass them to createConsentRuntime({ callbacks }) instead.")},[R]);let O=y(e=>f.subscribe(e),()=>f.getSnapshot().experiment,()=>f.getServerSnapshot().experiment),D=g(()=>r(s.theme,x,O),[s.theme,x,O]);h(()=>{"production"===process.env.NODE_ENV||!D||!["colors","dark","motion","radius","shadows","spacing","typography"].some(e=>e in D)||document.getElementById("c15t-theme")||console.warn("c15t: `theme` tokens are no longer turned into CSS in the browser. Render <ConsentTheme theme={theme} /> on the server, or put the CSS from generateThemeCSS() in your stylesheet. See https://c15t.com/docs/frameworks/react/customize")},[D]);let E=g(()=>({colorScheme:s.colorScheme,disableAnimation:s.disableAnimation,noStyle:s.noStyle,scrollLock:s.scrollLock,theme:D,trapFocus:s.trapFocus}),[D,s.noStyle,s.disableAnimation,s.scrollLock,s.trapFocus,s.colorScheme]),_=g(()=>({components:d(D?.slots,s.components,"className"),experiment:x,legalLinks:s.legalLinks,preloadDialog:s.preloadDialog,presentation:s.presentation,theme:s.theme}),[D?.slots,s.components,x,s.legalLinks,s.preloadDialog,s.presentation,s.theme]);return C(s.colorScheme),e(b.Provider,{value:f,children:e(S.Provider,{value:N,children:t(j,{themeConfig:E,uiConfig:_,children:[l?e(A,{entry:l.entry,options:s,rebuild:l.rebuild}):null,u?e(w,{runtime:u,children:c}):c]})})})};export{I as ConsentProvider};
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- let e="3.0.0-alpha.4";export{e as version};
1
+ let e="3.0.0-alpha.5";export{e as version};
@@ -0,0 +1,31 @@
1
+ import type { ConsentKernel, SaveInput, SaveResult, SaveUISource } from '@c15t/core';
2
+ import type { PreferenceDraft } from '@c15t/core/preference-draft';
3
+ /**
4
+ * The draft a `ConsentDraftProvider` shares. Here, apart from the draft
5
+ * module, so the banner's buttons can read it without loading the draft:
6
+ * the draft only runs once a preference surface renders.
7
+ */
8
+ export declare const DraftContext: import("react").Context<PreferenceDraft | null>;
9
+ export declare const REFUSED: SaveResult;
10
+ /** The kernel in context; throws outside a provider. */
11
+ export declare const useDraftKernel: () => ConsentKernel;
12
+ /**
13
+ * Whether `owner` is still the kernel this component last committed.
14
+ *
15
+ * A handle or save action kept across a runtime switch, by an async submit
16
+ * or a descendant's layout effect in the switch commit, calls through this,
17
+ * so it records nothing into the previous runtime. The committed kernel is
18
+ * read at call time (see `useCommittedRef`). A component that only unmounts
19
+ * keeps its last kernel, so a submit that outlives its dialog still saves.
20
+ */
21
+ export declare const useKernelGuard: (owner: ConsentKernel) => () => boolean;
22
+ /**
23
+ * Internal UI save path shared by stock controls and headless actions.
24
+ *
25
+ * Inside a `ConsentDraftProvider` an omitted input saves the shared draft.
26
+ * Bulk and explicit inputs go straight to the kernel; a bulk one also
27
+ * discards the draft's staged edits.
28
+ *
29
+ * @internal
30
+ */
31
+ export declare const useConsentSaveAction: () => (input?: SaveInput, uiSource?: SaveUISource) => Promise<SaveResult>;
@@ -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;
@@ -144,6 +144,9 @@ export declare const useSetOverrides: () => (input: KernelOverrides) => void;
144
144
  export declare const useSetLanguage: () => (code: string) => void;
145
145
  /**
146
146
  * Sync mutation: set the active UI surface (banner/dialog/none).
147
+ *
148
+ * Explicit navigation: a pending save on this kernel can no longer close or
149
+ * restore a surface once the visitor navigated.
147
150
  */
148
151
  export declare const useSetActiveUI: () => (ui: KernelActiveUI) => void;
149
152
  /**
@@ -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 } 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';