@uninspired/auth-client 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cookie-banner.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e,t}from"./purgeLegacyTracking-C4nrnU7N.js";import n,{useCallback as r,useEffect as i,useState as a}from"react";import{Fragment as o,jsx as s,jsxs as c}from"react/jsx-runtime";import{createPortal as l}from"react-dom";import*as u from"@subframe/core";import{FeatherChevronLeft as d,FeatherChevronRight as f,FeatherInfo as p,FeatherPlus as m,FeatherStar as h,FeatherX as g}from"@subframe/core";import{Close as _,Content as v,Overlay as y,Portal as b,Root as x,Title as S}from"@radix-ui/react-dialog";const C=u.createTwClassNames([`text-caption`,`text-caption-bold`,`text-body`,`text-body-bold`,`text-heading-3`,`text-heading-2`,`text-heading-1`,`text-monospace-body`,`text-heading-section`,`text-heading-subsection`]),w=n.forwardRef(function({disabled:e=!1,variant:t=`brand-primary`,size:n=`medium`,children:r,icon:i=null,iconRight:a=null,loading:o=!1,className:l,type:d=`button`,...f},p){return c(`button`,{className:C(`group/3b777358 flex h-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-brand-600 px-3 text-left hover:bg-brand-500 active:bg-brand-600 disabled:cursor-default disabled:bg-neutral-200 hover:disabled:cursor-default hover:disabled:bg-neutral-200 active:disabled:cursor-default active:disabled:bg-neutral-200`,{"h-6 gap-1 px-2":n===`small`,"h-10 px-4":n===`large`,"bg-transparent hover:bg-[#ffffff29] active:bg-[#ffffff3d]":t===`inverse`,"bg-transparent hover:bg-error-50 active:bg-error-100":t===`destructive-tertiary`,"bg-error-50 hover:bg-error-100 active:bg-error-50":t===`destructive-secondary`,"bg-error-600 hover:bg-error-500 active:bg-error-600":t===`destructive-primary`,"bg-transparent hover:bg-neutral-100 active:bg-neutral-200":t===`neutral-tertiary`,"border border-solid border-neutral-border bg-default-background hover:bg-neutral-50 active:bg-default-background":t===`neutral-secondary`,"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100":t===`neutral-primary`,"bg-transparent hover:bg-brand-50 active:bg-brand-100":t===`brand-tertiary`,"bg-brand-50 hover:bg-brand-100 active:bg-brand-50":t===`brand-secondary`},l),ref:p,type:d,disabled:e,...f,children:[i?s(u.IconWrapper,{className:C(`text-body font-body text-white group-disabled/3b777358:text-neutral-400`,{hidden:o,"text-heading-3 font-heading-3":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:i}):null,s(`div`,{className:C(`hidden h-4 w-4 flex-none items-center justify-center gap-2`,{flex:o,"h-3 w-3":n===`small`}),children:s(u.Loader,{className:C(`text-caption font-caption text-white group-disabled/3b777358:text-neutral-400`,{"leading-[20px]":o,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`})})}),r?s(`span`,{className:C(`whitespace-nowrap text-heading-3 font-heading-3 text-white group-disabled/3b777358:text-neutral-400`,{hidden:o,"text-caption-bold font-caption-bold":n===`small`,"text-body-bold font-body-bold":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:r}):null,a?s(u.IconWrapper,{className:C(`text-body font-body text-white group-disabled/3b777358:text-neutral-400`,{"text-heading-3 font-heading-3":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:a}):null]})}),T=n.forwardRef(function({disabled:e=!1,variant:t=`neutral-tertiary`,size:n=`medium`,icon:r=s(m,{}),loading:i=!1,className:a,type:o=`button`,...l},d){return c(`button`,{className:C(`group/af9405b1 flex h-8 w-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-transparent text-left hover:bg-neutral-100 active:bg-neutral-50 disabled:cursor-default disabled:bg-neutral-100 hover:disabled:cursor-default active:disabled:cursor-default active:disabled:bg-neutral-100`,{"h-6 w-6":n===`small`,"h-10 w-10":n===`large`,"hover:bg-[#ffffff29] active:bg-[#ffffff3d]":t===`inverse`,"hover:bg-error-50 active:bg-error-100":t===`destructive-tertiary`,"bg-error-50 hover:bg-error-100 active:bg-error-50":t===`destructive-secondary`,"bg-error-600 hover:bg-error-500 active:bg-error-600":t===`destructive-primary`,"border border-solid border-neutral-border bg-white active:bg-white":t===`neutral-secondary`,"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100":t===`neutral-primary`,"hover:bg-brand-50 active:bg-brand-100":t===`brand-tertiary`,"bg-brand-50 hover:bg-brand-100 active:bg-brand-50":t===`brand-secondary`,"bg-brand-600 hover:bg-brand-500 active:bg-brand-600":t===`brand-primary`},a),ref:d,type:o,disabled:e,...l,children:[r?s(u.IconWrapper,{className:C(`text-heading-3 font-heading-3 text-neutral-700 group-disabled/af9405b1:text-neutral-400`,{hidden:i,"text-body font-body":n===`small`,"text-white":t===`inverse`||t===`destructive-primary`||t===`brand-primary`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:r}):null,s(u.Loader,{className:C(`hidden text-caption font-caption text-neutral-700 group-disabled/af9405b1:text-neutral-400`,{"inline-block":i,"text-white":t===`inverse`||t===`destructive-primary`||t===`brand-primary`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`})})]})}),E=n.forwardRef(function({className:e,...t},n){return s(u.Switch.Thumb,{asChild:!0,...t,children:s(`div`,{className:C(`flex h-3.5 w-3.5 flex-col items-start gap-2 rounded-full bg-white shadow-sm`,e),ref:n})})}),D=n.forwardRef(function({checked:e=!1,className:t,...n},r){return s(u.Switch.Root,{checked:e,asChild:!0,...n,children:s(`div`,{className:C(`group/7a464794 flex h-5 w-8 cursor-pointer flex-col items-start justify-center gap-2 rounded-full border border-solid border-neutral-200 bg-neutral-200 px-0.5 py-0.5 aria-[checked=true]:border aria-[checked=true]:border-solid aria-[checked=true]:border-brand-600 aria-[checked=true]:bg-brand-600`,t),ref:r,children:s(E,{})})})}),O=Object.assign(D,{Thumb:E}),k=n.forwardRef(function({disabled:e=!1,children:t,icon:n=s(h,{}),className:r,...i},a){return s(u.ToggleGroup.Item,{asChild:!0,disabled:e,...i,children:c(`div`,{className:C(`group/56dea6ed flex h-7 w-full cursor-pointer items-center justify-center gap-2 rounded-md px-2 py-1 active:bg-neutral-100 aria-[checked=true]:bg-default-background aria-[checked=true]:shadow-sm active:aria-[checked=true]:bg-default-background`,{"active:bg-transparent":e},r),ref:a,children:[n?s(u.IconWrapper,{className:C(`text-body font-body text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font`,{"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400":e}),children:n}):null,t?s(`span`,{className:C(`whitespace-nowrap text-caption-bold font-caption-bold text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font`,{"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400":e}),children:t}):null]})})}),A=n.forwardRef(function({children:e,className:t,...n},r){return e?s(u.ToggleGroup.Root,{asChild:!0,...n,children:s(`div`,{className:C(`flex items-center gap-0.5 overflow-hidden rounded-md bg-neutral-100 px-0.5 py-0.5`,t),ref:r,children:e})}):null}),j=Object.assign(A,{Item:k}),M=n.forwardRef(function({children:e,className:t,...n},r){return s(`div`,{className:C(`flex flex-col items-start gap-2 rounded-md border border-solid border-neutral-900 bg-neutral-800 px-2 py-1 shadow-lg`,t),ref:r,...n,children:e?s(`span`,{className:`text-caption font-caption text-white`,children:e}):null})}),N=`strictly-necessary`,P=`marketing-and-analytics`,F={analytics:!0,marketing:!0};function I(e){if(!e.analytics&&!e.marketing)return N;if(e.analytics&&e.marketing)return P}function L(e){if(e===`strictly-necessary`)return{analytics:!1,marketing:!1};if(e===`marketing-and-analytics`)return{analytics:!0,marketing:!0}}const R={necessary:{title:`Necessary`,sections:[{heading:`Why do we need this?`,body:`These are how you stay signed in across Uninspired products, how checkout with Paddle can complete a payment, and how we remember that you already answered this banner so we don't ask on every page load.`},{heading:`What is being stored?`,body:`HttpOnly authentication session cookies, shared on uninspired.app so one login works across our apps. Paddle may set its own cookies while you pay. We also set uninspired_consent for 180 days with your analytics and marketing choice (yes or no) — nothing else.`},{heading:`Can I turn this off?`,body:`No — the site can't sign you in, take payment, or keep this preference without them. They are not used for ads, and they are not PostHog or Meta.`}]},analytics:{title:`Analytics`,sections:[{heading:`Why do we need this?`,body:`We use PostHog to see which features people actually use, where checkout starts, when something errors, and what to build next. Same events fire whether you allow cookies or not; this toggle only changes how identifying and persistent that data is.`},{heading:`What is being tracked?`,body:`Page views, clicks (autocapture), and product events such as feature used, checkout started, sign-up, and login. We never send your email. Visible text and element attributes are masked. Session recordings, surveys, and heatmaps are off. Query strings and magic-link paths are stripped before anything leaves the browser.`},{heading:`Where is my data sent?`,body:`PostHog, hosted in the EU. If you allow this, PostHog may set cookies (about 180 days) and browser storage, and we attach events to your account id after you sign in. If you decline (or haven't chosen yet), capture stays cookieless: no analytics cookies, no local storage, no account linking. Server-side events then use a salted hash of your user id instead of the id itself.`}]},marketing:{title:`Marketing`,sections:[{heading:`Why do we need this?`,body:`So we can tell whether Meta ads (Facebook / Instagram) actually lead to someone viewing a product, starting checkout, or buying. This is the only marketing tracker we load.`},{heading:`What is being tracked?`,body:`The Meta Pixel, and only after you allow it. We then load Meta's script and can send PageView, ViewContent, InitiateCheckout, and Purchase. Purchase may include a transaction id so Meta can ignore duplicates. We do not send your email through the pixel. If you later turn this off, we tell Meta to stop sending; leftover Meta cookies may remain until they expire.`},{heading:`Where is my data sent?`,body:`Meta (Facebook). The pixel script is not loaded if you decline, so no Meta cookies are set from us in that case. There is no separate server-side Conversions API path from this banner.`}]}};function z({category:e,onClose:t}){let n=e?R[e]:null;return s(x,{open:e!==null,onOpenChange:e=>!e&&t(),children:c(b,{children:[s(y,{style:{position:`fixed`,inset:0,zIndex:1e4,background:`#00000099`},className:`data-[state=open]:animate-overlayShow`}),n?c(v,{style:{position:`fixed`,left:`50%`,top:`50%`,zIndex:1e4},className:`flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-none -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-y-auto rounded-md border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg data-[state=open]:animate-contentShow focus:outline-none sm:max-w-[480px]`,children:[c(`div`,{className:`flex w-full items-start justify-between gap-4`,children:[s(S,{className:`text-heading-1 font-heading-1 text-default-font`,children:n.title}),s(T,{icon:s(g,{}),"aria-label":`Close`,onClick:t})]}),s(`div`,{className:`flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto`,children:n.sections.map(e=>c(`div`,{className:`flex max-w-[448px] flex-col items-start gap-0.5`,children:[s(`span`,{className:`text-heading-2 font-heading-2 text-default-font`,children:e.heading}),s(`span`,{className:`text-body font-body text-default-font`,children:e.body})]},e.heading))}),s(`div`,{className:`flex w-full items-center justify-end gap-2`,children:s(_,{asChild:!0,children:s(w,{variant:`neutral-primary`,onClick:t,children:`Close`})})})]}):null]})})}function B(e){return e??F}function V({privacyPolicyUrl:n=`https://legal.uninspired.studio/page/us-privacy-policy/`}){let{pending:u,consent:p,setConsent:m}=e(),[h,g]=a(!1),[_,v]=a(!1),[y,b]=a(F),[x,S]=a(null);i(()=>{g(!0)},[]),i(()=>{u&&t()},[u]),i(()=>{if(u){v(!0),b(F);return}v(!1),b(B(p))},[u,p]);let C=r(()=>{b(B(p)),v(!0)},[p]),E=r(()=>{v(!1),b(B(p))},[p]),D=r(()=>{m(y),v(!1)},[y,m]),O=I(y);if(!h)return null;let k=u||_;return l(c(o,{children:[u?s(`div`,{style:{position:`fixed`,inset:0,zIndex:9998,background:`#00000099`,pointerEvents:`none`},"aria-hidden":!0}):null,!u&&!_?s(`div`,{style:{position:`fixed`,bottom:`1rem`,left:`1rem`,zIndex:9999},children:s(T,{icon:s(f,{}),"aria-label":`Open cookie preferences`,onClick:C})}):null,s(`div`,{style:{position:`fixed`,bottom:`1rem`,left:`1rem`,zIndex:9999},className:`flex w-[calc(100vw-2rem)] max-w-[512px] max-h-[calc(100dvh-2rem)] flex-col items-start transition-transform duration-300 ease-out ${k?`translate-x-0`:`-translate-x-[120%] pointer-events-none`}`,"aria-hidden":!k,children:c(`div`,{className:`relative w-full`,children:[u?null:s(`div`,{className:`absolute bottom-0 right-[-33px] z-10 flex h-[33px] w-[33px] flex-none flex-col items-start gap-2`,children:s(T,{icon:s(d,{}),"aria-label":`Close cookie preferences`,onClick:E})}),c(`div`,{className:`flex max-h-[calc(100dvh-2rem)] w-full flex-col items-start gap-5 overflow-y-auto rounded-lg border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg`,children:[c(`div`,{className:`flex w-full flex-col items-start gap-1`,children:[s(`span`,{className:`text-heading-1 font-heading-1 text-default-font`,children:`We use cookies.`}),s(`span`,{className:`w-full text-caption font-caption text-subtext-color`,children:`We'd love not to, but they tend to be really useful. If you want to help us make better products, please enable some of them. It's cool if you don't though.`}),c(`div`,{className:`flex flex-wrap items-start gap-1`,children:[s(`span`,{className:`text-caption font-caption text-subtext-color`,children:`For more information, please visit our`}),s(`a`,{href:n,target:`_blank`,rel:`noopener noreferrer`,className:`text-caption font-caption text-brand-700 underline-offset-2 hover:underline`,children:`Privacy Policy`})]})]}),c(`div`,{className:`flex w-full flex-col items-start rounded-lg border border-solid border-neutral-border`,children:[s(U,{title:`Necessary`,description:`Sign-in session, Paddle checkout, and this consent cookie.`,checked:!0,disabled:!0,onInfo:()=>S(`necessary`),tooltip:`Required for the site to work — this one stays on.`}),s(H,{}),s(U,{title:`Analytics`,description:`PostHog cookies and linking events to your account. Cookieless usage stats still run if you decline.`,checked:y.analytics,onCheckedChange:e=>b(t=>({...t,analytics:e})),onInfo:()=>S(`analytics`)}),s(H,{}),s(U,{title:`Marketing`,description:`Meta Pixel for ad measurement. The script is not loaded unless you allow it.`,checked:y.marketing,onCheckedChange:e=>b(t=>({...t,marketing:e})),onInfo:()=>S(`marketing`)})]}),c(`div`,{className:`flex w-full flex-col items-stretch justify-between gap-4 sm:flex-row sm:items-center sm:gap-8`,children:[c(j,{className:`w-full sm:w-auto`,value:O??``,onValueChange:e=>{let t=L(e);t&&b(t)},children:[s(j.Item,{icon:null,value:N,children:`Strictly Necessary`}),s(j.Item,{icon:null,value:P,children:`Marketing and Analytics`})]}),s(w,{className:`w-full shrink-0 sm:w-auto`,variant:`neutral-primary`,onClick:D,children:`Save`})]})]})]})}),s(z,{category:x,onClose:()=>S(null)})]}),document.body)}function H(){return s(`div`,{className:`flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border`})}function U({title:e,description:t,checked:n,disabled:r=!1,onCheckedChange:i,onInfo:a,tooltip:o}){let l=s(O,{checked:n,disabled:r,onCheckedChange:i,className:r?`cursor-not-allowed aria-[checked=true]:border-neutral-400 aria-[checked=true]:bg-neutral-400`:void 0});return c(`div`,{className:`flex w-full items-center justify-between px-3 py-2`,children:[c(`div`,{className:`flex flex-col items-start`,children:[s(`span`,{className:`text-body-bold font-body-bold text-default-font`,children:e}),s(`span`,{className:`text-caption font-caption text-subtext-color`,children:t})]}),c(`div`,{className:`flex items-center justify-center gap-1`,children:[s(T,{icon:s(p,{}),"aria-label":`More information about ${e}`,onClick:a}),o?s(u.Tooltip.Provider,{children:c(u.Tooltip.Root,{children:[s(u.Tooltip.Trigger,{asChild:!0,children:l}),s(u.Tooltip.Portal,{children:s(u.Tooltip.Content,{side:`top`,align:`center`,sideOffset:4,asChild:!0,children:s(M,{className:`h-auto w-auto max-w-[208px] flex-none`,children:o})})})]})}):l]})]})}export{V as CookieBanner};
|
|
1
|
+
import{n as e,t}from"./purgeLegacyTracking-C4nrnU7N.js";import n,{useCallback as r,useEffect as i,useState as a}from"react";import{Fragment as o,jsx as s,jsxs as c}from"react/jsx-runtime";import{createPortal as l}from"react-dom";import*as u from"@subframe/core";import{FeatherChevronLeft as d,FeatherChevronRight as f,FeatherInfo as p,FeatherPlus as m,FeatherStar as h,FeatherX as g}from"@subframe/core";import{Close as _,Content as v,Overlay as y,Portal as b,Root as x,Title as S}from"@radix-ui/react-dialog";const C=u.createTwClassNames([`text-caption`,`text-caption-bold`,`text-body`,`text-body-bold`,`text-heading-3`,`text-heading-2`,`text-heading-1`,`text-monospace-body`,`text-heading-section`,`text-heading-subsection`]),w=n.forwardRef(function({disabled:e=!1,variant:t=`brand-primary`,size:n=`medium`,children:r,icon:i=null,iconRight:a=null,loading:o=!1,className:l,type:d=`button`,...f},p){return c(`button`,{className:C(`group/3b777358 flex h-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-brand-600 px-3 text-left hover:bg-brand-500 active:bg-brand-600 disabled:cursor-default disabled:bg-neutral-200 hover:disabled:cursor-default hover:disabled:bg-neutral-200 active:disabled:cursor-default active:disabled:bg-neutral-200`,{"h-6 gap-1 px-2":n===`small`,"h-10 px-4":n===`large`,"bg-transparent hover:bg-[#ffffff29] active:bg-[#ffffff3d]":t===`inverse`,"bg-transparent hover:bg-error-50 active:bg-error-100":t===`destructive-tertiary`,"bg-error-50 hover:bg-error-100 active:bg-error-50":t===`destructive-secondary`,"bg-error-600 hover:bg-error-500 active:bg-error-600":t===`destructive-primary`,"bg-transparent hover:bg-neutral-100 active:bg-neutral-200":t===`neutral-tertiary`,"border border-solid border-neutral-border bg-default-background hover:bg-neutral-50 active:bg-default-background":t===`neutral-secondary`,"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100":t===`neutral-primary`,"bg-transparent hover:bg-brand-50 active:bg-brand-100":t===`brand-tertiary`,"bg-brand-50 hover:bg-brand-100 active:bg-brand-50":t===`brand-secondary`},l),ref:p,type:d,disabled:e,...f,children:[i?s(u.IconWrapper,{className:C(`text-body font-body text-white group-disabled/3b777358:text-neutral-400`,{hidden:o,"text-heading-3 font-heading-3":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:i}):null,s(`div`,{className:C(`hidden h-4 w-4 flex-none items-center justify-center gap-2`,{flex:o,"h-3 w-3":n===`small`}),children:s(u.Loader,{className:C(`text-caption font-caption text-white group-disabled/3b777358:text-neutral-400`,{"leading-[20px]":o,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`})})}),r?s(`span`,{className:C(`whitespace-nowrap text-heading-3 font-heading-3 text-white group-disabled/3b777358:text-neutral-400`,{hidden:o,"text-caption-bold font-caption-bold":n===`small`,"text-body-bold font-body-bold":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:r}):null,a?s(u.IconWrapper,{className:C(`text-body font-body text-white group-disabled/3b777358:text-neutral-400`,{"text-heading-3 font-heading-3":n===`large`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-neutral-700":t===`neutral-tertiary`||t===`neutral-secondary`||t===`neutral-primary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:a}):null]})}),T=n.forwardRef(function({disabled:e=!1,variant:t=`neutral-tertiary`,size:n=`medium`,icon:r=s(m,{}),loading:i=!1,className:a,type:o=`button`,...l},d){return c(`button`,{className:C(`group/af9405b1 flex h-8 w-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-transparent text-left hover:bg-neutral-100 active:bg-neutral-50 disabled:cursor-default disabled:bg-neutral-100 hover:disabled:cursor-default active:disabled:cursor-default active:disabled:bg-neutral-100`,{"h-6 w-6":n===`small`,"h-10 w-10":n===`large`,"hover:bg-[#ffffff29] active:bg-[#ffffff3d]":t===`inverse`,"hover:bg-error-50 active:bg-error-100":t===`destructive-tertiary`,"bg-error-50 hover:bg-error-100 active:bg-error-50":t===`destructive-secondary`,"bg-error-600 hover:bg-error-500 active:bg-error-600":t===`destructive-primary`,"border border-solid border-neutral-border bg-white active:bg-white":t===`neutral-secondary`,"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100":t===`neutral-primary`,"hover:bg-brand-50 active:bg-brand-100":t===`brand-tertiary`,"bg-brand-50 hover:bg-brand-100 active:bg-brand-50":t===`brand-secondary`,"bg-brand-600 hover:bg-brand-500 active:bg-brand-600":t===`brand-primary`},a),ref:d,type:o,disabled:e,...l,children:[r?s(u.IconWrapper,{className:C(`text-heading-3 font-heading-3 text-neutral-700 group-disabled/af9405b1:text-neutral-400`,{hidden:i,"text-body font-body":n===`small`,"text-white":t===`inverse`||t===`destructive-primary`||t===`brand-primary`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`}),children:r}):null,s(u.Loader,{className:C(`hidden text-caption font-caption text-neutral-700 group-disabled/af9405b1:text-neutral-400`,{"inline-block":i,"text-white":t===`inverse`||t===`destructive-primary`||t===`brand-primary`,"text-error-700":t===`destructive-tertiary`||t===`destructive-secondary`,"text-brand-700":t===`brand-tertiary`||t===`brand-secondary`})})]})}),E=n.forwardRef(function({className:e,...t},n){return s(u.Switch.Thumb,{asChild:!0,...t,children:s(`div`,{className:C(`flex h-3.5 w-3.5 flex-col items-start gap-2 rounded-full bg-white shadow-sm`,e),ref:n})})}),D=n.forwardRef(function({checked:e=!1,className:t,...n},r){return s(u.Switch.Root,{checked:e,asChild:!0,...n,children:s(`div`,{className:C(`group/7a464794 flex h-5 w-8 cursor-pointer flex-col items-start justify-center gap-2 rounded-full border border-solid border-neutral-200 bg-neutral-200 px-0.5 py-0.5 aria-[checked=true]:border aria-[checked=true]:border-solid aria-[checked=true]:border-brand-600 aria-[checked=true]:bg-brand-600`,t),ref:r,children:s(E,{})})})}),O=Object.assign(D,{Thumb:E}),k=n.forwardRef(function({disabled:e=!1,children:t,icon:n=s(h,{}),className:r,...i},a){return s(u.ToggleGroup.Item,{asChild:!0,disabled:e,...i,children:c(`div`,{className:C(`group/56dea6ed flex h-7 w-full cursor-pointer items-center justify-center gap-2 rounded-md px-2 py-1 active:bg-neutral-100 aria-[checked=true]:bg-default-background aria-[checked=true]:shadow-sm active:aria-[checked=true]:bg-default-background`,{"active:bg-transparent":e},r),ref:a,children:[n?s(u.IconWrapper,{className:C(`text-body font-body text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font`,{"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400":e}),children:n}):null,t?s(`span`,{className:C(`whitespace-nowrap text-caption-bold font-caption-bold text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font`,{"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400":e}),children:t}):null]})})}),A=n.forwardRef(function({children:e,className:t,...n},r){return e?s(u.ToggleGroup.Root,{asChild:!0,...n,children:s(`div`,{className:C(`flex items-center gap-0.5 overflow-hidden rounded-md bg-neutral-100 px-0.5 py-0.5`,t),ref:r,children:e})}):null}),j=Object.assign(A,{Item:k}),M=n.forwardRef(function({children:e,className:t,...n},r){return s(`div`,{className:C(`flex flex-col items-start gap-2 rounded-md border border-solid border-neutral-900 bg-neutral-800 px-2 py-1 shadow-lg`,t),ref:r,...n,children:e?s(`span`,{className:`text-caption font-caption text-white`,children:e}):null})}),N=`strictly-necessary`,P=`marketing-and-analytics`,F={analytics:!0,marketing:!0};function I(e){if(!e.analytics&&!e.marketing)return N;if(e.analytics&&e.marketing)return P}function L(e){if(e===`strictly-necessary`)return{analytics:!1,marketing:!1};if(e===`marketing-and-analytics`)return{analytics:!0,marketing:!0}}const R={necessary:{title:`Necessary`,sections:[{heading:`Why do we need this?`,body:`These are how you stay signed in across Uninspired products, how checkout with Paddle can complete a payment, and how we remember that you already answered this banner so we don't ask on every page load.`},{heading:`What is being stored?`,body:`HttpOnly authentication session cookies, shared on uninspired.app so one login works across our apps. Paddle may set its own cookies while you pay. We also set uninspired_consent for 180 days with your analytics and marketing choice (yes or no) — nothing else.`},{heading:`Can I turn this off?`,body:`No — the site can't sign you in, take payment, or keep this preference without them. They are not used for ads, and they are not PostHog or Meta.`}]},analytics:{title:`Analytics`,sections:[{heading:`Why do we need this?`,body:`We use PostHog to see which features people actually use, where checkout starts, when something errors, and what to build next. Same events fire whether you allow cookies or not; this toggle only changes how identifying and persistent that data is.`},{heading:`What is being tracked?`,body:`Page views, clicks (autocapture), and product events such as feature used, checkout started, sign-up, and login. We never send your email. Visible text and element attributes are masked. Session recordings, surveys, and heatmaps are off. Query strings and magic-link paths are stripped before anything leaves the browser.`},{heading:`Where is my data sent?`,body:`PostHog, hosted in the EU. If you allow this, PostHog may set cookies (about 180 days) and browser storage, and we attach events to your account id after you sign in. If you decline (or haven't chosen yet), capture stays cookieless: no analytics cookies, no local storage, no account linking. Server-side events then use a salted hash of your user id instead of the id itself.`}]},marketing:{title:`Marketing`,sections:[{heading:`Why do we need this?`,body:`So we can tell whether Meta ads (Facebook / Instagram) actually lead to someone viewing a product, starting checkout, or buying. This is the only marketing tracker we load.`},{heading:`What is being tracked?`,body:`The Meta Pixel, and only after you allow it. We then load Meta's script and can send PageView, ViewContent, InitiateCheckout, and Purchase. Purchase may include a transaction id so Meta can ignore duplicates. We do not send your email through the pixel. If you later turn this off, we tell Meta to stop sending; leftover Meta cookies may remain until they expire.`},{heading:`Where is my data sent?`,body:`Meta (Facebook). The pixel script is not loaded if you decline, so no Meta cookies are set from us in that case. There is no separate server-side Conversions API path from this banner.`}]}};function z({category:e,onClose:t}){let n=e?R[e]:null;return s(x,{open:e!==null,onOpenChange:e=>!e&&t(),children:c(b,{children:[s(y,{style:{position:`fixed`,inset:0,zIndex:1e4,background:`#00000099`},className:`data-[state=open]:animate-overlayShow`}),n?c(v,{style:{position:`fixed`,left:`50%`,top:`50%`,zIndex:1e4},className:`flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-none -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-y-auto rounded-[4px] border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg data-[state=open]:animate-contentShow focus:outline-none sm:max-w-[480px]`,children:[c(`div`,{className:`flex w-full items-start justify-between gap-4`,children:[s(S,{className:`text-heading-1 font-heading-1 text-default-font`,children:n.title}),s(T,{className:`!rounded-[4px]`,icon:s(g,{}),"aria-label":`Close`,onClick:t})]}),s(`div`,{className:`flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto`,children:n.sections.map(e=>c(`div`,{className:`flex max-w-[448px] flex-col items-start gap-0.5`,children:[s(`span`,{className:`text-heading-2 font-heading-2 text-default-font`,children:e.heading}),s(`span`,{className:`text-body font-body text-default-font`,children:e.body})]},e.heading))}),s(`div`,{className:`flex w-full items-center justify-end gap-2`,children:s(_,{asChild:!0,children:s(w,{className:`!rounded-[4px]`,variant:`neutral-primary`,onClick:t,children:`Close`})})})]}):null]})})}function B(e){return e??F}function V({privacyPolicyUrl:n=`https://legal.uninspired.studio/page/us-privacy-policy/`}){let{pending:u,consent:p,setConsent:m}=e(),[h,g]=a(!1),[_,v]=a(!1),[y,b]=a(F),[x,S]=a(null);i(()=>{g(!0)},[]),i(()=>{u&&t()},[u]),i(()=>{if(u){v(!0),b(F);return}v(!1),b(B(p))},[u,p]);let C=r(()=>{b(B(p)),v(!0)},[p]),E=r(()=>{v(!1),b(B(p))},[p]),D=r(()=>{m(y),v(!1)},[y,m]),O=I(y);if(!h)return null;let k=u||_;return l(c(o,{children:[u?s(`div`,{style:{position:`fixed`,inset:0,zIndex:9998,background:`#00000099`,pointerEvents:`none`},"aria-hidden":!0}):null,!u&&!_?s(`div`,{style:{position:`fixed`,bottom:`1rem`,left:`1rem`,zIndex:9999},children:s(T,{className:`!rounded-[4px]`,icon:s(f,{}),"aria-label":`Open cookie preferences`,onClick:C})}):null,s(`div`,{style:{position:`fixed`,bottom:`1rem`,left:`1rem`,zIndex:9999},className:`flex w-[calc(100vw-2rem)] max-w-[512px] max-h-[calc(100dvh-2rem)] flex-col items-start transition-transform duration-300 ease-out ${k?`translate-x-0`:`-translate-x-[120%] pointer-events-none`}`,"aria-hidden":!k,children:c(`div`,{className:`relative w-full`,children:[u?null:s(`div`,{className:`absolute bottom-0 right-[-33px] z-10 flex h-[33px] w-[33px] flex-none flex-col items-start gap-2`,children:s(T,{className:`!rounded-[4px]`,icon:s(d,{}),"aria-label":`Close cookie preferences`,onClick:E})}),c(`div`,{className:`flex max-h-[calc(100dvh-2rem)] w-full flex-col items-start gap-5 overflow-y-auto rounded-[8px] border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg`,children:[c(`div`,{className:`flex w-full flex-col items-start gap-1`,children:[s(`span`,{className:`text-heading-1 font-heading-1 text-default-font`,children:`We use cookies.`}),s(`span`,{className:`w-full text-caption font-caption text-subtext-color`,children:`We'd love not to, but they tend to be really useful. If you want to help us make better products, please enable some of them. It's cool if you don't though.`}),c(`div`,{className:`flex flex-wrap items-start gap-1`,children:[s(`span`,{className:`text-caption font-caption text-subtext-color`,children:`For more information, please visit our`}),s(`a`,{href:n,target:`_blank`,rel:`noopener noreferrer`,className:`text-caption font-caption underline-offset-2 hover:underline`,style:{color:`#ffff00`},children:`Privacy Policy`})]})]}),c(`div`,{className:`flex w-full flex-col items-start rounded-[8px] border border-solid border-neutral-border`,children:[s(U,{title:`Necessary`,description:`Sign-in session, Paddle checkout, and this consent cookie.`,checked:!0,disabled:!0,onInfo:()=>S(`necessary`),tooltip:`Required for the site to work — this one stays on.`}),s(H,{}),s(U,{title:`Analytics`,description:`PostHog cookies and linking events to your account. Cookieless usage stats still run if you decline.`,checked:y.analytics,onCheckedChange:e=>b(t=>({...t,analytics:e})),onInfo:()=>S(`analytics`)}),s(H,{}),s(U,{title:`Marketing`,description:`Meta Pixel for ad measurement. The script is not loaded unless you allow it.`,checked:y.marketing,onCheckedChange:e=>b(t=>({...t,marketing:e})),onInfo:()=>S(`marketing`)})]}),c(`div`,{className:`flex w-full flex-col items-stretch justify-between gap-4 sm:flex-row sm:items-center sm:gap-8`,children:[c(j,{className:`w-full !rounded-[4px] sm:w-auto`,value:O??``,onValueChange:e=>{let t=L(e);t&&b(t)},children:[s(j.Item,{className:`!rounded-[4px]`,icon:null,value:N,children:`Strictly Necessary`}),s(j.Item,{className:`!rounded-[4px]`,icon:null,value:P,children:`Marketing and Analytics`})]}),s(w,{className:`w-full shrink-0 !rounded-[4px] sm:w-auto`,variant:`neutral-primary`,onClick:D,children:`Save`})]})]})]})}),s(z,{category:x,onClose:()=>S(null)})]}),document.body)}function H(){return s(`div`,{className:`flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border`})}function U({title:e,description:t,checked:n,disabled:r=!1,onCheckedChange:i,onInfo:a,tooltip:o}){let l=s(O,{checked:n,disabled:r,onCheckedChange:i,className:r?`cursor-not-allowed !rounded-[9999px] aria-[checked=true]:border-neutral-400 aria-[checked=true]:bg-neutral-400`:`!rounded-[9999px] aria-[checked=true]:!border-[#ffff00] aria-[checked=true]:!bg-[#ffff00]`});return c(`div`,{className:`flex w-full items-center justify-between px-3 py-2`,children:[c(`div`,{className:`flex flex-col items-start`,children:[s(`span`,{className:`text-body-bold font-body-bold text-default-font`,children:e}),s(`span`,{className:`text-caption font-caption text-subtext-color`,children:t})]}),c(`div`,{className:`flex items-center justify-center gap-1`,children:[s(T,{className:`!rounded-[4px]`,icon:s(p,{}),"aria-label":`More information about ${e}`,onClick:a}),o?s(u.Tooltip.Provider,{children:c(u.Tooltip.Root,{children:[s(u.Tooltip.Trigger,{asChild:!0,children:l}),s(u.Tooltip.Portal,{children:s(u.Tooltip.Content,{side:`top`,align:`center`,sideOffset:4,asChild:!0,children:s(M,{className:`h-auto w-auto max-w-[208px] flex-none !rounded-[4px]`,children:o})})})]})}):l]})]})}export{V as CookieBanner};
|
|
2
2
|
//# sourceMappingURL=cookie-banner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-banner.js","names":["SubframeUtils.twClassNames","Button","ButtonComponent","SubframeUtils.twClassNames","IconButton","IconButtonComponent","SubframeUtils.twClassNames","Switch","SwitchComponent","SubframeUtils.twClassNames","ToggleGroup","ToggleGroupComponent","SubframeUtils.twClassNames","Tooltip","TooltipComponent"],"sources":["../../components/ui/utils.ts","../../components/ui/components/Button/Button.tsx","../../components/ui/components/Button/index.tsx","../../components/ui/components/IconButton/IconButton.tsx","../../components/ui/components/IconButton/index.tsx","../../components/ui/components/Switch/Switch.tsx","../../components/ui/components/Switch/index.tsx","../../components/ui/components/ToggleGroup/ToggleGroup.tsx","../../components/ui/components/ToggleGroup/index.tsx","../../components/ui/components/Tooltip/Tooltip.tsx","../../components/ui/components/Tooltip/index.tsx","../src/cookie-banner/consentPresets.ts","../src/cookie-banner/ConsentInfoDialog.tsx","../src/cookie-banner/CookieBanner.tsx"],"sourcesContent":["import * as SubframeCore from \"@subframe/core\";\n\nexport const twClassNames = SubframeCore.createTwClassNames([\n \"text-caption\",\n \"text-caption-bold\",\n \"text-body\",\n \"text-body-bold\",\n \"text-heading-3\",\n \"text-heading-2\",\n \"text-heading-1\",\n \"text-monospace-body\",\n \"text-heading-section\",\n \"text-heading-subsection\",\n]);\n","\"use client\";\n/*\n * Documentation:\n * Button — https://app.subframe.com/49eb78b484b2/library?component=Button_3b777358-b86b-40af-9327-891efc6826fe\n */\n\nimport React from \"react\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ButtonRootProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n variant?:\n | \"brand-primary\"\n | \"brand-secondary\"\n | \"brand-tertiary\"\n | \"neutral-primary\"\n | \"neutral-secondary\"\n | \"neutral-tertiary\"\n | \"destructive-primary\"\n | \"destructive-secondary\"\n | \"destructive-tertiary\"\n | \"inverse\";\n size?: \"large\" | \"medium\" | \"small\";\n children?: React.ReactNode;\n icon?: React.ReactNode;\n iconRight?: React.ReactNode;\n loading?: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n className?: string;\n}\n\nconst ButtonRoot = React.forwardRef<HTMLButtonElement, ButtonRootProps>(\n function ButtonRoot(\n {\n disabled = false,\n variant = \"brand-primary\",\n size = \"medium\",\n children,\n icon = null,\n iconRight = null,\n loading = false,\n className,\n type = \"button\",\n ...otherProps\n }: ButtonRootProps,\n ref\n ) {\n return (\n <button\n className={SubframeUtils.twClassNames(\n \"group/3b777358 flex h-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-brand-600 px-3 text-left hover:bg-brand-500 active:bg-brand-600 disabled:cursor-default disabled:bg-neutral-200 hover:disabled:cursor-default hover:disabled:bg-neutral-200 active:disabled:cursor-default active:disabled:bg-neutral-200\",\n {\n \"h-6 gap-1 px-2\": size === \"small\",\n \"h-10 px-4\": size === \"large\",\n \"bg-transparent hover:bg-[#ffffff29] active:bg-[#ffffff3d]\":\n variant === \"inverse\",\n \"bg-transparent hover:bg-error-50 active:bg-error-100\":\n variant === \"destructive-tertiary\",\n \"bg-error-50 hover:bg-error-100 active:bg-error-50\":\n variant === \"destructive-secondary\",\n \"bg-error-600 hover:bg-error-500 active:bg-error-600\":\n variant === \"destructive-primary\",\n \"bg-transparent hover:bg-neutral-100 active:bg-neutral-200\":\n variant === \"neutral-tertiary\",\n \"border border-solid border-neutral-border bg-default-background hover:bg-neutral-50 active:bg-default-background\":\n variant === \"neutral-secondary\",\n \"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100\":\n variant === \"neutral-primary\",\n \"bg-transparent hover:bg-brand-50 active:bg-brand-100\":\n variant === \"brand-tertiary\",\n \"bg-brand-50 hover:bg-brand-100 active:bg-brand-50\":\n variant === \"brand-secondary\",\n },\n className\n )}\n ref={ref}\n type={type}\n disabled={disabled}\n {...otherProps}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-white group-disabled/3b777358:text-neutral-400\",\n {\n hidden: loading,\n \"text-heading-3 font-heading-3\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n <div\n className={SubframeUtils.twClassNames(\n \"hidden h-4 w-4 flex-none items-center justify-center gap-2\",\n { flex: loading, \"h-3 w-3\": size === \"small\" }\n )}\n >\n <SubframeCore.Loader\n className={SubframeUtils.twClassNames(\n \"text-caption font-caption text-white group-disabled/3b777358:text-neutral-400\",\n {\n \"leading-[20px]\": loading,\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n />\n </div>\n {children ? (\n <span\n className={SubframeUtils.twClassNames(\n \"whitespace-nowrap text-heading-3 font-heading-3 text-white group-disabled/3b777358:text-neutral-400\",\n {\n hidden: loading,\n \"text-caption-bold font-caption-bold\": size === \"small\",\n \"text-body-bold font-body-bold\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {children}\n </span>\n ) : null}\n {iconRight ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-white group-disabled/3b777358:text-neutral-400\",\n {\n \"text-heading-3 font-heading-3\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {iconRight}\n </SubframeCore.IconWrapper>\n ) : null}\n </button>\n );\n }\n);\n\nexport const Button = ButtonRoot;\n","\"use client\";\nimport { Button as ButtonComponent } from \"./Button\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Button = ButtonComponent;\n","\"use client\";\n/*\n * Documentation:\n * Icon Button — https://app.subframe.com/49eb78b484b2/library?component=Icon+Button_af9405b1-8c54-4e01-9786-5aad308224f6\n */\n\nimport React from \"react\";\nimport { FeatherPlus } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface IconButtonRootProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n variant?:\n | \"brand-primary\"\n | \"brand-secondary\"\n | \"brand-tertiary\"\n | \"neutral-primary\"\n | \"neutral-secondary\"\n | \"neutral-tertiary\"\n | \"destructive-primary\"\n | \"destructive-secondary\"\n | \"destructive-tertiary\"\n | \"inverse\";\n size?: \"large\" | \"medium\" | \"small\";\n icon?: React.ReactNode;\n loading?: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n className?: string;\n}\n\nconst IconButtonRoot = React.forwardRef<HTMLButtonElement, IconButtonRootProps>(\n function IconButtonRoot(\n {\n disabled = false,\n variant = \"neutral-tertiary\",\n size = \"medium\",\n icon = <FeatherPlus />,\n loading = false,\n className,\n type = \"button\",\n ...otherProps\n }: IconButtonRootProps,\n ref\n ) {\n return (\n <button\n className={SubframeUtils.twClassNames(\n \"group/af9405b1 flex h-8 w-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-transparent text-left hover:bg-neutral-100 active:bg-neutral-50 disabled:cursor-default disabled:bg-neutral-100 hover:disabled:cursor-default active:disabled:cursor-default active:disabled:bg-neutral-100\",\n {\n \"h-6 w-6\": size === \"small\",\n \"h-10 w-10\": size === \"large\",\n \"hover:bg-[#ffffff29] active:bg-[#ffffff3d]\": variant === \"inverse\",\n \"hover:bg-error-50 active:bg-error-100\":\n variant === \"destructive-tertiary\",\n \"bg-error-50 hover:bg-error-100 active:bg-error-50\":\n variant === \"destructive-secondary\",\n \"bg-error-600 hover:bg-error-500 active:bg-error-600\":\n variant === \"destructive-primary\",\n \"border border-solid border-neutral-border bg-white active:bg-white\":\n variant === \"neutral-secondary\",\n \"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100\":\n variant === \"neutral-primary\",\n \"hover:bg-brand-50 active:bg-brand-100\":\n variant === \"brand-tertiary\",\n \"bg-brand-50 hover:bg-brand-100 active:bg-brand-50\":\n variant === \"brand-secondary\",\n \"bg-brand-600 hover:bg-brand-500 active:bg-brand-600\":\n variant === \"brand-primary\",\n },\n className\n )}\n ref={ref}\n type={type}\n disabled={disabled}\n {...otherProps}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-heading-3 font-heading-3 text-neutral-700 group-disabled/af9405b1:text-neutral-400\",\n {\n hidden: loading,\n \"text-body font-body\": size === \"small\",\n \"text-white\":\n variant === \"inverse\" ||\n variant === \"destructive-primary\" ||\n variant === \"brand-primary\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n <SubframeCore.Loader\n className={SubframeUtils.twClassNames(\n \"hidden text-caption font-caption text-neutral-700 group-disabled/af9405b1:text-neutral-400\",\n {\n \"inline-block\": loading,\n \"text-white\":\n variant === \"inverse\" ||\n variant === \"destructive-primary\" ||\n variant === \"brand-primary\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n />\n </button>\n );\n }\n);\n\nexport const IconButton = IconButtonRoot;\n","\"use client\";\nimport { IconButton as IconButtonComponent } from \"./IconButton\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const IconButton = IconButtonComponent;\n","\"use client\";\n/*\n * Documentation:\n * Switch — https://app.subframe.com/49eb78b484b2/library?component=Switch_7a464794-9ea9-4040-b1de-5bfb2ce599d9\n */\n\nimport React from \"react\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ThumbProps\n extends React.ComponentProps<typeof SubframeCore.Switch.Thumb> {\n className?: string;\n}\n\nconst Thumb = React.forwardRef<HTMLDivElement, ThumbProps>(function Thumb(\n { className, ...otherProps }: ThumbProps,\n ref\n) {\n return (\n <SubframeCore.Switch.Thumb asChild={true} {...otherProps}>\n <div\n className={SubframeUtils.twClassNames(\n \"flex h-3.5 w-3.5 flex-col items-start gap-2 rounded-full bg-white shadow-sm\",\n className\n )}\n ref={ref}\n />\n </SubframeCore.Switch.Thumb>\n );\n});\n\nexport interface SwitchRootProps\n extends React.ComponentProps<typeof SubframeCore.Switch.Root> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n className?: string;\n}\n\nconst SwitchRoot = React.forwardRef<HTMLDivElement, SwitchRootProps>(\n function SwitchRoot(\n { checked = false, className, ...otherProps }: SwitchRootProps,\n ref\n ) {\n return (\n <SubframeCore.Switch.Root\n checked={checked}\n asChild={true}\n {...otherProps}\n >\n <div\n className={SubframeUtils.twClassNames(\n \"group/7a464794 flex h-5 w-8 cursor-pointer flex-col items-start justify-center gap-2 rounded-full border border-solid border-neutral-200 bg-neutral-200 px-0.5 py-0.5 aria-[checked=true]:border aria-[checked=true]:border-solid aria-[checked=true]:border-brand-600 aria-[checked=true]:bg-brand-600\",\n className\n )}\n ref={ref}\n >\n <Thumb />\n </div>\n </SubframeCore.Switch.Root>\n );\n }\n);\n\nexport const Switch = Object.assign(SwitchRoot, {\n Thumb,\n});\n","\"use client\";\nimport { Switch as SwitchComponent } from \"./Switch\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Switch = SwitchComponent;\n","\"use client\";\n/*\n * Documentation:\n * Toggle Group — https://app.subframe.com/49eb78b484b2/library?component=Toggle+Group_2026f10a-e3cc-4c89-80da-a7259acae3b7\n */\n\nimport React from \"react\";\nimport { FeatherStar } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ItemProps\n extends React.ComponentProps<typeof SubframeCore.ToggleGroup.Item> {\n disabled?: boolean;\n children?: React.ReactNode;\n icon?: React.ReactNode;\n className?: string;\n}\n\nconst Item = React.forwardRef<HTMLDivElement, ItemProps>(function Item(\n {\n disabled = false,\n children,\n icon = <FeatherStar />,\n className,\n ...otherProps\n }: ItemProps,\n ref\n) {\n return (\n <SubframeCore.ToggleGroup.Item\n asChild={true}\n disabled={disabled}\n {...otherProps}\n >\n <div\n className={SubframeUtils.twClassNames(\n \"group/56dea6ed flex h-7 w-full cursor-pointer items-center justify-center gap-2 rounded-md px-2 py-1 active:bg-neutral-100 aria-[checked=true]:bg-default-background aria-[checked=true]:shadow-sm active:aria-[checked=true]:bg-default-background\",\n { \"active:bg-transparent\": disabled },\n className\n )}\n ref={ref}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font\",\n {\n \"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400\":\n disabled,\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n {children ? (\n <span\n className={SubframeUtils.twClassNames(\n \"whitespace-nowrap text-caption-bold font-caption-bold text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font\",\n {\n \"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400\":\n disabled,\n }\n )}\n >\n {children}\n </span>\n ) : null}\n </div>\n </SubframeCore.ToggleGroup.Item>\n );\n});\n\nexport interface ToggleGroupRootProps\n extends React.ComponentProps<typeof SubframeCore.ToggleGroup.Root> {\n children?: React.ReactNode;\n value?: string;\n onValueChange?: (value: string) => void;\n className?: string;\n}\n\nconst ToggleGroupRoot = React.forwardRef<HTMLDivElement, ToggleGroupRootProps>(\n function ToggleGroupRoot(\n { children, className, ...otherProps }: ToggleGroupRootProps,\n ref\n ) {\n return children ? (\n <SubframeCore.ToggleGroup.Root asChild={true} {...otherProps}>\n <div\n className={SubframeUtils.twClassNames(\n \"flex items-center gap-0.5 overflow-hidden rounded-md bg-neutral-100 px-0.5 py-0.5\",\n className\n )}\n ref={ref}\n >\n {children}\n </div>\n </SubframeCore.ToggleGroup.Root>\n ) : null;\n }\n);\n\nexport const ToggleGroup = Object.assign(ToggleGroupRoot, {\n Item,\n});\n","\"use client\";\nimport { ToggleGroup as ToggleGroupComponent } from \"./ToggleGroup\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const ToggleGroup = ToggleGroupComponent;\n","\"use client\";\n/*\n * Documentation:\n * Tooltip — https://app.subframe.com/49eb78b484b2/library?component=Tooltip_ccebd1e9-f6ac-4737-8376-0dfacd90c9f3\n */\n\nimport React from \"react\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface TooltipRootProps extends React.HTMLAttributes<HTMLDivElement> {\n children?: React.ReactNode;\n className?: string;\n}\n\nconst TooltipRoot = React.forwardRef<HTMLDivElement, TooltipRootProps>(\n function TooltipRoot(\n { children, className, ...otherProps }: TooltipRootProps,\n ref\n ) {\n return (\n <div\n className={SubframeUtils.twClassNames(\n \"flex flex-col items-start gap-2 rounded-md border border-solid border-neutral-900 bg-neutral-800 px-2 py-1 shadow-lg\",\n className\n )}\n ref={ref}\n {...otherProps}\n >\n {children ? (\n <span className=\"text-caption font-caption text-white\">\n {children}\n </span>\n ) : null}\n </div>\n );\n }\n);\n\nexport const Tooltip = TooltipRoot;\n","\"use client\";\nimport { Tooltip as TooltipComponent } from \"./Tooltip\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Tooltip = TooltipComponent;\n","import type { TrackingConsent } from \"@us-auth/types\";\n\nexport const PRESET_STRICTLY_NECESSARY = \"strictly-necessary\";\nexport const PRESET_MARKETING_AND_ANALYTICS = \"marketing-and-analytics\";\n\nexport type ConsentPreset =\n | typeof PRESET_STRICTLY_NECESSARY\n | typeof PRESET_MARKETING_AND_ANALYTICS;\n\nexport const DEFAULT_DRAFT_CONSENT: TrackingConsent = {\n analytics: true,\n marketing: true,\n};\n\nexport function consentToPreset(\n consent: Pick<TrackingConsent, \"analytics\" | \"marketing\">,\n): ConsentPreset | undefined {\n if (!consent.analytics && !consent.marketing) {\n return PRESET_STRICTLY_NECESSARY;\n }\n if (consent.analytics && consent.marketing) {\n return PRESET_MARKETING_AND_ANALYTICS;\n }\n return undefined;\n}\n\nexport function presetToConsent(preset: string): TrackingConsent | undefined {\n if (preset === PRESET_STRICTLY_NECESSARY) {\n return { analytics: false, marketing: false };\n }\n if (preset === PRESET_MARKETING_AND_ANALYTICS) {\n return { analytics: true, marketing: true };\n }\n return undefined;\n}\n","\"use client\";\n\nimport {\n Close,\n Content,\n Overlay,\n Portal,\n Root,\n Title,\n} from \"@radix-ui/react-dialog\";\nimport { FeatherX } from \"@subframe/core\";\nimport { Button } from \"@us-auth/components/components/Button\";\nimport { IconButton } from \"@us-auth/components/components/IconButton\";\n\nexport type ConsentInfoCategory = \"necessary\" | \"analytics\" | \"marketing\";\n\nconst INFO_COPY: Record<\n ConsentInfoCategory,\n { title: string; sections: { heading: string; body: string }[] }\n> = {\n necessary: {\n title: \"Necessary\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"These are how you stay signed in across Uninspired products, how checkout with Paddle can complete a payment, and how we remember that you already answered this banner so we don't ask on every page load.\",\n },\n {\n heading: \"What is being stored?\",\n body:\n \"HttpOnly authentication session cookies, shared on uninspired.app so one login works across our apps. Paddle may set its own cookies while you pay. We also set uninspired_consent for 180 days with your analytics and marketing choice (yes or no) — nothing else.\",\n },\n {\n heading: \"Can I turn this off?\",\n body:\n \"No — the site can't sign you in, take payment, or keep this preference without them. They are not used for ads, and they are not PostHog or Meta.\",\n },\n ],\n },\n analytics: {\n title: \"Analytics\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"We use PostHog to see which features people actually use, where checkout starts, when something errors, and what to build next. Same events fire whether you allow cookies or not; this toggle only changes how identifying and persistent that data is.\",\n },\n {\n heading: \"What is being tracked?\",\n body:\n \"Page views, clicks (autocapture), and product events such as feature used, checkout started, sign-up, and login. We never send your email. Visible text and element attributes are masked. Session recordings, surveys, and heatmaps are off. Query strings and magic-link paths are stripped before anything leaves the browser.\",\n },\n {\n heading: \"Where is my data sent?\",\n body:\n \"PostHog, hosted in the EU. If you allow this, PostHog may set cookies (about 180 days) and browser storage, and we attach events to your account id after you sign in. If you decline (or haven't chosen yet), capture stays cookieless: no analytics cookies, no local storage, no account linking. Server-side events then use a salted hash of your user id instead of the id itself.\",\n },\n ],\n },\n marketing: {\n title: \"Marketing\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"So we can tell whether Meta ads (Facebook / Instagram) actually lead to someone viewing a product, starting checkout, or buying. This is the only marketing tracker we load.\",\n },\n {\n heading: \"What is being tracked?\",\n body:\n \"The Meta Pixel, and only after you allow it. We then load Meta's script and can send PageView, ViewContent, InitiateCheckout, and Purchase. Purchase may include a transaction id so Meta can ignore duplicates. We do not send your email through the pixel. If you later turn this off, we tell Meta to stop sending; leftover Meta cookies may remain until they expire.\",\n },\n {\n heading: \"Where is my data sent?\",\n body:\n \"Meta (Facebook). The pixel script is not loaded if you decline, so no Meta cookies are set from us in that case. There is no separate server-side Conversions API path from this banner.\",\n },\n ],\n },\n};\n\nexport interface ConsentInfoDialogProps {\n category: ConsentInfoCategory | null;\n onClose: () => void;\n}\n\nexport function ConsentInfoDialog({ category, onClose }: ConsentInfoDialogProps) {\n const copy = category ? INFO_COPY[category] : null;\n\n return (\n <Root open={category !== null} onOpenChange={(open) => !open && onClose()}>\n <Portal>\n <Overlay\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 10000,\n background: \"#00000099\",\n }}\n className=\"data-[state=open]:animate-overlayShow\"\n />\n {copy ? (\n <Content\n style={{\n position: \"fixed\",\n left: \"50%\",\n top: \"50%\",\n zIndex: 10000,\n }}\n className=\"flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-none -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-y-auto rounded-md border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg data-[state=open]:animate-contentShow focus:outline-none sm:max-w-[480px]\"\n >\n <div className=\"flex w-full items-start justify-between gap-4\">\n <Title className=\"text-heading-1 font-heading-1 text-default-font\">\n {copy.title}\n </Title>\n <IconButton\n icon={<FeatherX />}\n aria-label=\"Close\"\n onClick={onClose}\n />\n </div>\n <div className=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto\">\n {copy.sections.map((section) => (\n <div\n key={section.heading}\n className=\"flex max-w-[448px] flex-col items-start gap-0.5\"\n >\n <span className=\"text-heading-2 font-heading-2 text-default-font\">\n {section.heading}\n </span>\n <span className=\"text-body font-body text-default-font\">\n {section.body}\n </span>\n </div>\n ))}\n </div>\n <div className=\"flex w-full items-center justify-end gap-2\">\n <Close asChild>\n <Button variant=\"neutral-primary\" onClick={onClose}>\n Close\n </Button>\n </Close>\n </div>\n </Content>\n ) : null}\n </Portal>\n </Root>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FeatherChevronLeft, FeatherChevronRight, FeatherInfo } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport { Button } from \"@us-auth/components/components/Button\";\nimport { IconButton } from \"@us-auth/components/components/IconButton\";\nimport { Switch } from \"@us-auth/components/components/Switch\";\nimport { ToggleGroup } from \"@us-auth/components/components/ToggleGroup\";\nimport { Tooltip } from \"@us-auth/components/components/Tooltip\";\nimport type { ConsentState, TrackingConsent } from \"@us-auth/types\";\nimport { purgeLegacyTracking } from \"../consent/purgeLegacyTracking\";\nimport { useTrackingConsent } from \"../consent/useTrackingConsent\";\nimport {\n consentToPreset,\n DEFAULT_DRAFT_CONSENT,\n PRESET_MARKETING_AND_ANALYTICS,\n PRESET_STRICTLY_NECESSARY,\n presetToConsent,\n} from \"./consentPresets\";\nimport {\n ConsentInfoDialog,\n type ConsentInfoCategory,\n} from \"./ConsentInfoDialog\";\n\nconst DEFAULT_PRIVACY_POLICY_URL =\n \"https://legal.uninspired.studio/page/us-privacy-policy/\";\n\nexport interface CookieBannerProps {\n privacyPolicyUrl?: string;\n}\n\nfunction draftFromConsent(consent: ConsentState): TrackingConsent {\n return consent ?? DEFAULT_DRAFT_CONSENT;\n}\n\nexport function CookieBanner({\n privacyPolicyUrl = DEFAULT_PRIVACY_POLICY_URL,\n}: CookieBannerProps) {\n const { pending, consent, setConsent } = useTrackingConsent();\n const [mounted, setMounted] = useState(false);\n const [panelOpen, setPanelOpen] = useState(false);\n const [draft, setDraft] = useState<TrackingConsent>(DEFAULT_DRAFT_CONSENT);\n const [infoCategory, setInfoCategory] = useState<ConsentInfoCategory | null>(\n null,\n );\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (!pending) return;\n purgeLegacyTracking();\n }, [pending]);\n\n useEffect(() => {\n if (pending) {\n setPanelOpen(true);\n setDraft(DEFAULT_DRAFT_CONSENT);\n return;\n }\n setPanelOpen(false);\n setDraft(draftFromConsent(consent));\n }, [pending, consent]);\n\n const openPanel = useCallback(() => {\n setDraft(draftFromConsent(consent));\n setPanelOpen(true);\n }, [consent]);\n\n const closePanel = useCallback(() => {\n setPanelOpen(false);\n setDraft(draftFromConsent(consent));\n }, [consent]);\n\n const save = useCallback(() => {\n setConsent(draft);\n setPanelOpen(false);\n }, [draft, setConsent]);\n\n const presetValue = consentToPreset(draft);\n\n if (!mounted) return null;\n\n const effectivePanelOpen = pending || panelOpen;\n const showCollapsedTab = !pending && !panelOpen;\n\n return createPortal(\n <>\n {pending ? (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 9998,\n background: \"#00000099\",\n pointerEvents: \"none\",\n }}\n aria-hidden\n />\n ) : null}\n\n {showCollapsedTab ? (\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n left: \"1rem\",\n zIndex: 9999,\n }}\n >\n <IconButton\n icon={<FeatherChevronRight />}\n aria-label=\"Open cookie preferences\"\n onClick={openPanel}\n />\n </div>\n ) : null}\n\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n left: \"1rem\",\n zIndex: 9999,\n }}\n className={`flex w-[calc(100vw-2rem)] max-w-[512px] max-h-[calc(100dvh-2rem)] flex-col items-start transition-transform duration-300 ease-out ${\n effectivePanelOpen\n ? \"translate-x-0\"\n : \"-translate-x-[120%] pointer-events-none\"\n }`}\n aria-hidden={!effectivePanelOpen}\n >\n <div className=\"relative w-full\">\n {!pending ? (\n <div className=\"absolute bottom-0 right-[-33px] z-10 flex h-[33px] w-[33px] flex-none flex-col items-start gap-2\">\n <IconButton\n icon={<FeatherChevronLeft />}\n aria-label=\"Close cookie preferences\"\n onClick={closePanel}\n />\n </div>\n ) : null}\n <div className=\"flex max-h-[calc(100dvh-2rem)] w-full flex-col items-start gap-5 overflow-y-auto rounded-lg border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg\">\n\n <div className=\"flex w-full flex-col items-start gap-1\">\n <span className=\"text-heading-1 font-heading-1 text-default-font\">\n We use cookies.\n </span>\n <span className=\"w-full text-caption font-caption text-subtext-color\">\n We'd love not to, but they tend to be really useful. If you\n want to help us make better products, please enable some of them.\n It's cool if you don't though.\n </span>\n <div className=\"flex flex-wrap items-start gap-1\">\n <span className=\"text-caption font-caption text-subtext-color\">\n For more information, please visit our\n </span>\n <a\n href={privacyPolicyUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-caption font-caption text-brand-700 underline-offset-2 hover:underline\"\n >\n Privacy Policy\n </a>\n </div>\n </div>\n\n <div className=\"flex w-full flex-col items-start rounded-lg border border-solid border-neutral-border\">\n <ConsentRow\n title=\"Necessary\"\n description=\"Sign-in session, Paddle checkout, and this consent cookie.\"\n checked={true}\n disabled\n onInfo={() => setInfoCategory(\"necessary\")}\n tooltip=\"Required for the site to work — this one stays on.\"\n />\n <RowDivider />\n <ConsentRow\n title=\"Analytics\"\n description=\"PostHog cookies and linking events to your account. Cookieless usage stats still run if you decline.\"\n checked={draft.analytics}\n onCheckedChange={(checked) =>\n setDraft((current) => ({ ...current, analytics: checked }))\n }\n onInfo={() => setInfoCategory(\"analytics\")}\n />\n <RowDivider />\n <ConsentRow\n title=\"Marketing\"\n description=\"Meta Pixel for ad measurement. The script is not loaded unless you allow it.\"\n checked={draft.marketing}\n onCheckedChange={(checked) =>\n setDraft((current) => ({ ...current, marketing: checked }))\n }\n onInfo={() => setInfoCategory(\"marketing\")}\n />\n </div>\n\n <div className=\"flex w-full flex-col items-stretch justify-between gap-4 sm:flex-row sm:items-center sm:gap-8\">\n <ToggleGroup\n className=\"w-full sm:w-auto\"\n value={presetValue ?? \"\"}\n onValueChange={(value: string) => {\n const next = presetToConsent(value);\n if (next) setDraft(next);\n }}\n >\n <ToggleGroup.Item icon={null} value={PRESET_STRICTLY_NECESSARY}>\n Strictly Necessary\n </ToggleGroup.Item>\n <ToggleGroup.Item\n icon={null}\n value={PRESET_MARKETING_AND_ANALYTICS}\n >\n Marketing and Analytics\n </ToggleGroup.Item>\n </ToggleGroup>\n <Button\n className=\"w-full shrink-0 sm:w-auto\"\n variant=\"neutral-primary\"\n onClick={save}\n >\n Save\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n <ConsentInfoDialog\n category={infoCategory}\n onClose={() => setInfoCategory(null)}\n />\n </>,\n document.body,\n );\n}\n\nfunction RowDivider() {\n return (\n <div className=\"flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border\" />\n );\n}\n\ninterface ConsentRowProps {\n title: string;\n description: string;\n checked: boolean;\n disabled?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n onInfo: () => void;\n tooltip?: string;\n}\n\nfunction ConsentRow({\n title,\n description,\n checked,\n disabled = false,\n onCheckedChange,\n onInfo,\n tooltip,\n}: ConsentRowProps) {\n const switchControl = (\n <Switch\n checked={checked}\n disabled={disabled}\n onCheckedChange={onCheckedChange}\n className={\n disabled\n ? \"cursor-not-allowed aria-[checked=true]:border-neutral-400 aria-[checked=true]:bg-neutral-400\"\n : undefined\n }\n />\n );\n\n return (\n <div className=\"flex w-full items-center justify-between px-3 py-2\">\n <div className=\"flex flex-col items-start\">\n <span className=\"text-body-bold font-body-bold text-default-font\">\n {title}\n </span>\n <span className=\"text-caption font-caption text-subtext-color\">\n {description}\n </span>\n </div>\n <div className=\"flex items-center justify-center gap-1\">\n <IconButton\n icon={<FeatherInfo />}\n aria-label={`More information about ${title}`}\n onClick={onInfo}\n />\n {tooltip ? (\n <SubframeCore.Tooltip.Provider>\n <SubframeCore.Tooltip.Root>\n <SubframeCore.Tooltip.Trigger asChild={true}>\n {switchControl}\n </SubframeCore.Tooltip.Trigger>\n <SubframeCore.Tooltip.Portal>\n <SubframeCore.Tooltip.Content\n side=\"top\"\n align=\"center\"\n sideOffset={4}\n asChild={true}\n >\n <Tooltip className=\"h-auto w-auto max-w-[208px] flex-none\">\n {tooltip}\n </Tooltip>\n </SubframeCore.Tooltip.Content>\n </SubframeCore.Tooltip.Portal>\n </SubframeCore.Tooltip.Root>\n </SubframeCore.Tooltip.Provider>\n ) : (\n switchControl\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cookie-banner.js","names":["SubframeUtils.twClassNames","Button","ButtonComponent","SubframeUtils.twClassNames","IconButton","IconButtonComponent","SubframeUtils.twClassNames","Switch","SwitchComponent","SubframeUtils.twClassNames","ToggleGroup","ToggleGroupComponent","SubframeUtils.twClassNames","Tooltip","TooltipComponent"],"sources":["../../components/ui/utils.ts","../../components/ui/components/Button/Button.tsx","../../components/ui/components/Button/index.tsx","../../components/ui/components/IconButton/IconButton.tsx","../../components/ui/components/IconButton/index.tsx","../../components/ui/components/Switch/Switch.tsx","../../components/ui/components/Switch/index.tsx","../../components/ui/components/ToggleGroup/ToggleGroup.tsx","../../components/ui/components/ToggleGroup/index.tsx","../../components/ui/components/Tooltip/Tooltip.tsx","../../components/ui/components/Tooltip/index.tsx","../src/cookie-banner/consentPresets.ts","../src/cookie-banner/ConsentInfoDialog.tsx","../src/cookie-banner/CookieBanner.tsx"],"sourcesContent":["import * as SubframeCore from \"@subframe/core\";\n\nexport const twClassNames = SubframeCore.createTwClassNames([\n \"text-caption\",\n \"text-caption-bold\",\n \"text-body\",\n \"text-body-bold\",\n \"text-heading-3\",\n \"text-heading-2\",\n \"text-heading-1\",\n \"text-monospace-body\",\n \"text-heading-section\",\n \"text-heading-subsection\",\n]);\n","\"use client\";\n/*\n * Documentation:\n * Button — https://app.subframe.com/49eb78b484b2/library?component=Button_3b777358-b86b-40af-9327-891efc6826fe\n */\n\nimport React from \"react\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ButtonRootProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n variant?:\n | \"brand-primary\"\n | \"brand-secondary\"\n | \"brand-tertiary\"\n | \"neutral-primary\"\n | \"neutral-secondary\"\n | \"neutral-tertiary\"\n | \"destructive-primary\"\n | \"destructive-secondary\"\n | \"destructive-tertiary\"\n | \"inverse\";\n size?: \"large\" | \"medium\" | \"small\";\n children?: React.ReactNode;\n icon?: React.ReactNode;\n iconRight?: React.ReactNode;\n loading?: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n className?: string;\n}\n\nconst ButtonRoot = React.forwardRef<HTMLButtonElement, ButtonRootProps>(\n function ButtonRoot(\n {\n disabled = false,\n variant = \"brand-primary\",\n size = \"medium\",\n children,\n icon = null,\n iconRight = null,\n loading = false,\n className,\n type = \"button\",\n ...otherProps\n }: ButtonRootProps,\n ref\n ) {\n return (\n <button\n className={SubframeUtils.twClassNames(\n \"group/3b777358 flex h-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-brand-600 px-3 text-left hover:bg-brand-500 active:bg-brand-600 disabled:cursor-default disabled:bg-neutral-200 hover:disabled:cursor-default hover:disabled:bg-neutral-200 active:disabled:cursor-default active:disabled:bg-neutral-200\",\n {\n \"h-6 gap-1 px-2\": size === \"small\",\n \"h-10 px-4\": size === \"large\",\n \"bg-transparent hover:bg-[#ffffff29] active:bg-[#ffffff3d]\":\n variant === \"inverse\",\n \"bg-transparent hover:bg-error-50 active:bg-error-100\":\n variant === \"destructive-tertiary\",\n \"bg-error-50 hover:bg-error-100 active:bg-error-50\":\n variant === \"destructive-secondary\",\n \"bg-error-600 hover:bg-error-500 active:bg-error-600\":\n variant === \"destructive-primary\",\n \"bg-transparent hover:bg-neutral-100 active:bg-neutral-200\":\n variant === \"neutral-tertiary\",\n \"border border-solid border-neutral-border bg-default-background hover:bg-neutral-50 active:bg-default-background\":\n variant === \"neutral-secondary\",\n \"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100\":\n variant === \"neutral-primary\",\n \"bg-transparent hover:bg-brand-50 active:bg-brand-100\":\n variant === \"brand-tertiary\",\n \"bg-brand-50 hover:bg-brand-100 active:bg-brand-50\":\n variant === \"brand-secondary\",\n },\n className\n )}\n ref={ref}\n type={type}\n disabled={disabled}\n {...otherProps}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-white group-disabled/3b777358:text-neutral-400\",\n {\n hidden: loading,\n \"text-heading-3 font-heading-3\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n <div\n className={SubframeUtils.twClassNames(\n \"hidden h-4 w-4 flex-none items-center justify-center gap-2\",\n { flex: loading, \"h-3 w-3\": size === \"small\" }\n )}\n >\n <SubframeCore.Loader\n className={SubframeUtils.twClassNames(\n \"text-caption font-caption text-white group-disabled/3b777358:text-neutral-400\",\n {\n \"leading-[20px]\": loading,\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n />\n </div>\n {children ? (\n <span\n className={SubframeUtils.twClassNames(\n \"whitespace-nowrap text-heading-3 font-heading-3 text-white group-disabled/3b777358:text-neutral-400\",\n {\n hidden: loading,\n \"text-caption-bold font-caption-bold\": size === \"small\",\n \"text-body-bold font-body-bold\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {children}\n </span>\n ) : null}\n {iconRight ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-white group-disabled/3b777358:text-neutral-400\",\n {\n \"text-heading-3 font-heading-3\": size === \"large\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-neutral-700\":\n variant === \"neutral-tertiary\" ||\n variant === \"neutral-secondary\" ||\n variant === \"neutral-primary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {iconRight}\n </SubframeCore.IconWrapper>\n ) : null}\n </button>\n );\n }\n);\n\nexport const Button = ButtonRoot;\n","\"use client\";\nimport { Button as ButtonComponent } from \"./Button\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Button = ButtonComponent;\n","\"use client\";\n/*\n * Documentation:\n * Icon Button — https://app.subframe.com/49eb78b484b2/library?component=Icon+Button_af9405b1-8c54-4e01-9786-5aad308224f6\n */\n\nimport React from \"react\";\nimport { FeatherPlus } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface IconButtonRootProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n disabled?: boolean;\n variant?:\n | \"brand-primary\"\n | \"brand-secondary\"\n | \"brand-tertiary\"\n | \"neutral-primary\"\n | \"neutral-secondary\"\n | \"neutral-tertiary\"\n | \"destructive-primary\"\n | \"destructive-secondary\"\n | \"destructive-tertiary\"\n | \"inverse\";\n size?: \"large\" | \"medium\" | \"small\";\n icon?: React.ReactNode;\n loading?: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n className?: string;\n}\n\nconst IconButtonRoot = React.forwardRef<HTMLButtonElement, IconButtonRootProps>(\n function IconButtonRoot(\n {\n disabled = false,\n variant = \"neutral-tertiary\",\n size = \"medium\",\n icon = <FeatherPlus />,\n loading = false,\n className,\n type = \"button\",\n ...otherProps\n }: IconButtonRootProps,\n ref\n ) {\n return (\n <button\n className={SubframeUtils.twClassNames(\n \"group/af9405b1 flex h-8 w-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-transparent text-left hover:bg-neutral-100 active:bg-neutral-50 disabled:cursor-default disabled:bg-neutral-100 hover:disabled:cursor-default active:disabled:cursor-default active:disabled:bg-neutral-100\",\n {\n \"h-6 w-6\": size === \"small\",\n \"h-10 w-10\": size === \"large\",\n \"hover:bg-[#ffffff29] active:bg-[#ffffff3d]\": variant === \"inverse\",\n \"hover:bg-error-50 active:bg-error-100\":\n variant === \"destructive-tertiary\",\n \"bg-error-50 hover:bg-error-100 active:bg-error-50\":\n variant === \"destructive-secondary\",\n \"bg-error-600 hover:bg-error-500 active:bg-error-600\":\n variant === \"destructive-primary\",\n \"border border-solid border-neutral-border bg-white active:bg-white\":\n variant === \"neutral-secondary\",\n \"bg-neutral-100 hover:bg-neutral-200 active:bg-neutral-100\":\n variant === \"neutral-primary\",\n \"hover:bg-brand-50 active:bg-brand-100\":\n variant === \"brand-tertiary\",\n \"bg-brand-50 hover:bg-brand-100 active:bg-brand-50\":\n variant === \"brand-secondary\",\n \"bg-brand-600 hover:bg-brand-500 active:bg-brand-600\":\n variant === \"brand-primary\",\n },\n className\n )}\n ref={ref}\n type={type}\n disabled={disabled}\n {...otherProps}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-heading-3 font-heading-3 text-neutral-700 group-disabled/af9405b1:text-neutral-400\",\n {\n hidden: loading,\n \"text-body font-body\": size === \"small\",\n \"text-white\":\n variant === \"inverse\" ||\n variant === \"destructive-primary\" ||\n variant === \"brand-primary\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n <SubframeCore.Loader\n className={SubframeUtils.twClassNames(\n \"hidden text-caption font-caption text-neutral-700 group-disabled/af9405b1:text-neutral-400\",\n {\n \"inline-block\": loading,\n \"text-white\":\n variant === \"inverse\" ||\n variant === \"destructive-primary\" ||\n variant === \"brand-primary\",\n \"text-error-700\":\n variant === \"destructive-tertiary\" ||\n variant === \"destructive-secondary\",\n \"text-brand-700\":\n variant === \"brand-tertiary\" || variant === \"brand-secondary\",\n }\n )}\n />\n </button>\n );\n }\n);\n\nexport const IconButton = IconButtonRoot;\n","\"use client\";\nimport { IconButton as IconButtonComponent } from \"./IconButton\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const IconButton = IconButtonComponent;\n","\"use client\";\n/*\n * Documentation:\n * Switch — https://app.subframe.com/49eb78b484b2/library?component=Switch_7a464794-9ea9-4040-b1de-5bfb2ce599d9\n */\n\nimport React from \"react\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ThumbProps\n extends React.ComponentProps<typeof SubframeCore.Switch.Thumb> {\n className?: string;\n}\n\nconst Thumb = React.forwardRef<HTMLDivElement, ThumbProps>(function Thumb(\n { className, ...otherProps }: ThumbProps,\n ref\n) {\n return (\n <SubframeCore.Switch.Thumb asChild={true} {...otherProps}>\n <div\n className={SubframeUtils.twClassNames(\n \"flex h-3.5 w-3.5 flex-col items-start gap-2 rounded-full bg-white shadow-sm\",\n className\n )}\n ref={ref}\n />\n </SubframeCore.Switch.Thumb>\n );\n});\n\nexport interface SwitchRootProps\n extends React.ComponentProps<typeof SubframeCore.Switch.Root> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n className?: string;\n}\n\nconst SwitchRoot = React.forwardRef<HTMLDivElement, SwitchRootProps>(\n function SwitchRoot(\n { checked = false, className, ...otherProps }: SwitchRootProps,\n ref\n ) {\n return (\n <SubframeCore.Switch.Root\n checked={checked}\n asChild={true}\n {...otherProps}\n >\n <div\n className={SubframeUtils.twClassNames(\n \"group/7a464794 flex h-5 w-8 cursor-pointer flex-col items-start justify-center gap-2 rounded-full border border-solid border-neutral-200 bg-neutral-200 px-0.5 py-0.5 aria-[checked=true]:border aria-[checked=true]:border-solid aria-[checked=true]:border-brand-600 aria-[checked=true]:bg-brand-600\",\n className\n )}\n ref={ref}\n >\n <Thumb />\n </div>\n </SubframeCore.Switch.Root>\n );\n }\n);\n\nexport const Switch = Object.assign(SwitchRoot, {\n Thumb,\n});\n","\"use client\";\nimport { Switch as SwitchComponent } from \"./Switch\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Switch = SwitchComponent;\n","\"use client\";\n/*\n * Documentation:\n * Toggle Group — https://app.subframe.com/49eb78b484b2/library?component=Toggle+Group_2026f10a-e3cc-4c89-80da-a7259acae3b7\n */\n\nimport React from \"react\";\nimport { FeatherStar } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface ItemProps\n extends React.ComponentProps<typeof SubframeCore.ToggleGroup.Item> {\n disabled?: boolean;\n children?: React.ReactNode;\n icon?: React.ReactNode;\n className?: string;\n}\n\nconst Item = React.forwardRef<HTMLDivElement, ItemProps>(function Item(\n {\n disabled = false,\n children,\n icon = <FeatherStar />,\n className,\n ...otherProps\n }: ItemProps,\n ref\n) {\n return (\n <SubframeCore.ToggleGroup.Item\n asChild={true}\n disabled={disabled}\n {...otherProps}\n >\n <div\n className={SubframeUtils.twClassNames(\n \"group/56dea6ed flex h-7 w-full cursor-pointer items-center justify-center gap-2 rounded-md px-2 py-1 active:bg-neutral-100 aria-[checked=true]:bg-default-background aria-[checked=true]:shadow-sm active:aria-[checked=true]:bg-default-background\",\n { \"active:bg-transparent\": disabled },\n className\n )}\n ref={ref}\n >\n {icon ? (\n <SubframeCore.IconWrapper\n className={SubframeUtils.twClassNames(\n \"text-body font-body text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font\",\n {\n \"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400\":\n disabled,\n }\n )}\n >\n {icon}\n </SubframeCore.IconWrapper>\n ) : null}\n {children ? (\n <span\n className={SubframeUtils.twClassNames(\n \"whitespace-nowrap text-caption-bold font-caption-bold text-subtext-color group-hover/56dea6ed:text-default-font group-aria-[checked=true]/56dea6ed:text-default-font\",\n {\n \"text-neutral-400 group-hover/56dea6ed:text-neutral-400 group-active/56dea6ed:text-neutral-400\":\n disabled,\n }\n )}\n >\n {children}\n </span>\n ) : null}\n </div>\n </SubframeCore.ToggleGroup.Item>\n );\n});\n\nexport interface ToggleGroupRootProps\n extends React.ComponentProps<typeof SubframeCore.ToggleGroup.Root> {\n children?: React.ReactNode;\n value?: string;\n onValueChange?: (value: string) => void;\n className?: string;\n}\n\nconst ToggleGroupRoot = React.forwardRef<HTMLDivElement, ToggleGroupRootProps>(\n function ToggleGroupRoot(\n { children, className, ...otherProps }: ToggleGroupRootProps,\n ref\n ) {\n return children ? (\n <SubframeCore.ToggleGroup.Root asChild={true} {...otherProps}>\n <div\n className={SubframeUtils.twClassNames(\n \"flex items-center gap-0.5 overflow-hidden rounded-md bg-neutral-100 px-0.5 py-0.5\",\n className\n )}\n ref={ref}\n >\n {children}\n </div>\n </SubframeCore.ToggleGroup.Root>\n ) : null;\n }\n);\n\nexport const ToggleGroup = Object.assign(ToggleGroupRoot, {\n Item,\n});\n","\"use client\";\nimport { ToggleGroup as ToggleGroupComponent } from \"./ToggleGroup\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const ToggleGroup = ToggleGroupComponent;\n","\"use client\";\n/*\n * Documentation:\n * Tooltip — https://app.subframe.com/49eb78b484b2/library?component=Tooltip_ccebd1e9-f6ac-4737-8376-0dfacd90c9f3\n */\n\nimport React from \"react\";\nimport * as SubframeUtils from \"../../utils\";\n\nexport interface TooltipRootProps extends React.HTMLAttributes<HTMLDivElement> {\n children?: React.ReactNode;\n className?: string;\n}\n\nconst TooltipRoot = React.forwardRef<HTMLDivElement, TooltipRootProps>(\n function TooltipRoot(\n { children, className, ...otherProps }: TooltipRootProps,\n ref\n ) {\n return (\n <div\n className={SubframeUtils.twClassNames(\n \"flex flex-col items-start gap-2 rounded-md border border-solid border-neutral-900 bg-neutral-800 px-2 py-1 shadow-lg\",\n className\n )}\n ref={ref}\n {...otherProps}\n >\n {children ? (\n <span className=\"text-caption font-caption text-white\">\n {children}\n </span>\n ) : null}\n </div>\n );\n }\n);\n\nexport const Tooltip = TooltipRoot;\n","\"use client\";\nimport { Tooltip as TooltipComponent } from \"./Tooltip\";\n\n/**\n * Add wrapper components and business logic here.\n * If you modify this file, disable Subframe sync for it to prevent overwrites.\n * Learn more: https://docs.subframe.com/concepts/syncing-components#wrapping-components\n */\n\nexport const Tooltip = TooltipComponent;\n","import type { TrackingConsent } from \"@us-auth/types\";\n\nexport const PRESET_STRICTLY_NECESSARY = \"strictly-necessary\";\nexport const PRESET_MARKETING_AND_ANALYTICS = \"marketing-and-analytics\";\n\nexport type ConsentPreset =\n | typeof PRESET_STRICTLY_NECESSARY\n | typeof PRESET_MARKETING_AND_ANALYTICS;\n\nexport const DEFAULT_DRAFT_CONSENT: TrackingConsent = {\n analytics: true,\n marketing: true,\n};\n\nexport function consentToPreset(\n consent: Pick<TrackingConsent, \"analytics\" | \"marketing\">,\n): ConsentPreset | undefined {\n if (!consent.analytics && !consent.marketing) {\n return PRESET_STRICTLY_NECESSARY;\n }\n if (consent.analytics && consent.marketing) {\n return PRESET_MARKETING_AND_ANALYTICS;\n }\n return undefined;\n}\n\nexport function presetToConsent(preset: string): TrackingConsent | undefined {\n if (preset === PRESET_STRICTLY_NECESSARY) {\n return { analytics: false, marketing: false };\n }\n if (preset === PRESET_MARKETING_AND_ANALYTICS) {\n return { analytics: true, marketing: true };\n }\n return undefined;\n}\n","\"use client\";\n\nimport {\n Close,\n Content,\n Overlay,\n Portal,\n Root,\n Title,\n} from \"@radix-ui/react-dialog\";\nimport { FeatherX } from \"@subframe/core\";\nimport { Button } from \"@us-auth/components/components/Button\";\nimport { IconButton } from \"@us-auth/components/components/IconButton\";\n\nexport type ConsentInfoCategory = \"necessary\" | \"analytics\" | \"marketing\";\n\nconst INFO_COPY: Record<\n ConsentInfoCategory,\n { title: string; sections: { heading: string; body: string }[] }\n> = {\n necessary: {\n title: \"Necessary\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"These are how you stay signed in across Uninspired products, how checkout with Paddle can complete a payment, and how we remember that you already answered this banner so we don't ask on every page load.\",\n },\n {\n heading: \"What is being stored?\",\n body:\n \"HttpOnly authentication session cookies, shared on uninspired.app so one login works across our apps. Paddle may set its own cookies while you pay. We also set uninspired_consent for 180 days with your analytics and marketing choice (yes or no) — nothing else.\",\n },\n {\n heading: \"Can I turn this off?\",\n body:\n \"No — the site can't sign you in, take payment, or keep this preference without them. They are not used for ads, and they are not PostHog or Meta.\",\n },\n ],\n },\n analytics: {\n title: \"Analytics\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"We use PostHog to see which features people actually use, where checkout starts, when something errors, and what to build next. Same events fire whether you allow cookies or not; this toggle only changes how identifying and persistent that data is.\",\n },\n {\n heading: \"What is being tracked?\",\n body:\n \"Page views, clicks (autocapture), and product events such as feature used, checkout started, sign-up, and login. We never send your email. Visible text and element attributes are masked. Session recordings, surveys, and heatmaps are off. Query strings and magic-link paths are stripped before anything leaves the browser.\",\n },\n {\n heading: \"Where is my data sent?\",\n body:\n \"PostHog, hosted in the EU. If you allow this, PostHog may set cookies (about 180 days) and browser storage, and we attach events to your account id after you sign in. If you decline (or haven't chosen yet), capture stays cookieless: no analytics cookies, no local storage, no account linking. Server-side events then use a salted hash of your user id instead of the id itself.\",\n },\n ],\n },\n marketing: {\n title: \"Marketing\",\n sections: [\n {\n heading: \"Why do we need this?\",\n body:\n \"So we can tell whether Meta ads (Facebook / Instagram) actually lead to someone viewing a product, starting checkout, or buying. This is the only marketing tracker we load.\",\n },\n {\n heading: \"What is being tracked?\",\n body:\n \"The Meta Pixel, and only after you allow it. We then load Meta's script and can send PageView, ViewContent, InitiateCheckout, and Purchase. Purchase may include a transaction id so Meta can ignore duplicates. We do not send your email through the pixel. If you later turn this off, we tell Meta to stop sending; leftover Meta cookies may remain until they expire.\",\n },\n {\n heading: \"Where is my data sent?\",\n body:\n \"Meta (Facebook). The pixel script is not loaded if you decline, so no Meta cookies are set from us in that case. There is no separate server-side Conversions API path from this banner.\",\n },\n ],\n },\n};\n\nexport interface ConsentInfoDialogProps {\n category: ConsentInfoCategory | null;\n onClose: () => void;\n}\n\nexport function ConsentInfoDialog({ category, onClose }: ConsentInfoDialogProps) {\n const copy = category ? INFO_COPY[category] : null;\n\n return (\n <Root open={category !== null} onOpenChange={(open) => !open && onClose()}>\n <Portal>\n <Overlay\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 10000,\n background: \"#00000099\",\n }}\n className=\"data-[state=open]:animate-overlayShow\"\n />\n {copy ? (\n <Content\n style={{\n position: \"fixed\",\n left: \"50%\",\n top: \"50%\",\n zIndex: 10000,\n }}\n className=\"flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-none -translate-x-1/2 -translate-y-1/2 flex-col gap-4 overflow-y-auto rounded-[4px] border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg data-[state=open]:animate-contentShow focus:outline-none sm:max-w-[480px]\"\n >\n <div className=\"flex w-full items-start justify-between gap-4\">\n <Title className=\"text-heading-1 font-heading-1 text-default-font\">\n {copy.title}\n </Title>\n <IconButton\n className=\"!rounded-[4px]\"\n icon={<FeatherX />}\n aria-label=\"Close\"\n onClick={onClose}\n />\n </div>\n <div className=\"flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto\">\n {copy.sections.map((section) => (\n <div\n key={section.heading}\n className=\"flex max-w-[448px] flex-col items-start gap-0.5\"\n >\n <span className=\"text-heading-2 font-heading-2 text-default-font\">\n {section.heading}\n </span>\n <span className=\"text-body font-body text-default-font\">\n {section.body}\n </span>\n </div>\n ))}\n </div>\n <div className=\"flex w-full items-center justify-end gap-2\">\n <Close asChild>\n <Button className=\"!rounded-[4px]\" variant=\"neutral-primary\" onClick={onClose}>\n Close\n </Button>\n </Close>\n </div>\n </Content>\n ) : null}\n </Portal>\n </Root>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FeatherChevronLeft, FeatherChevronRight, FeatherInfo } from \"@subframe/core\";\nimport * as SubframeCore from \"@subframe/core\";\nimport { Button } from \"@us-auth/components/components/Button\";\nimport { IconButton } from \"@us-auth/components/components/IconButton\";\nimport { Switch } from \"@us-auth/components/components/Switch\";\nimport { ToggleGroup } from \"@us-auth/components/components/ToggleGroup\";\nimport { Tooltip } from \"@us-auth/components/components/Tooltip\";\nimport type { ConsentState, TrackingConsent } from \"@us-auth/types\";\nimport { purgeLegacyTracking } from \"../consent/purgeLegacyTracking\";\nimport { useTrackingConsent } from \"../consent/useTrackingConsent\";\nimport {\n consentToPreset,\n DEFAULT_DRAFT_CONSENT,\n PRESET_MARKETING_AND_ANALYTICS,\n PRESET_STRICTLY_NECESSARY,\n presetToConsent,\n} from \"./consentPresets\";\nimport {\n ConsentInfoDialog,\n type ConsentInfoCategory,\n} from \"./ConsentInfoDialog\";\n\nconst DEFAULT_PRIVACY_POLICY_URL =\n \"https://legal.uninspired.studio/page/us-privacy-policy/\";\n\nexport interface CookieBannerProps {\n privacyPolicyUrl?: string;\n}\n\nfunction draftFromConsent(consent: ConsentState): TrackingConsent {\n return consent ?? DEFAULT_DRAFT_CONSENT;\n}\n\nexport function CookieBanner({\n privacyPolicyUrl = DEFAULT_PRIVACY_POLICY_URL,\n}: CookieBannerProps) {\n const { pending, consent, setConsent } = useTrackingConsent();\n const [mounted, setMounted] = useState(false);\n const [panelOpen, setPanelOpen] = useState(false);\n const [draft, setDraft] = useState<TrackingConsent>(DEFAULT_DRAFT_CONSENT);\n const [infoCategory, setInfoCategory] = useState<ConsentInfoCategory | null>(\n null,\n );\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (!pending) return;\n purgeLegacyTracking();\n }, [pending]);\n\n useEffect(() => {\n if (pending) {\n setPanelOpen(true);\n setDraft(DEFAULT_DRAFT_CONSENT);\n return;\n }\n setPanelOpen(false);\n setDraft(draftFromConsent(consent));\n }, [pending, consent]);\n\n const openPanel = useCallback(() => {\n setDraft(draftFromConsent(consent));\n setPanelOpen(true);\n }, [consent]);\n\n const closePanel = useCallback(() => {\n setPanelOpen(false);\n setDraft(draftFromConsent(consent));\n }, [consent]);\n\n const save = useCallback(() => {\n setConsent(draft);\n setPanelOpen(false);\n }, [draft, setConsent]);\n\n const presetValue = consentToPreset(draft);\n\n if (!mounted) return null;\n\n const effectivePanelOpen = pending || panelOpen;\n const showCollapsedTab = !pending && !panelOpen;\n\n return createPortal(\n <>\n {pending ? (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 9998,\n background: \"#00000099\",\n pointerEvents: \"none\",\n }}\n aria-hidden\n />\n ) : null}\n\n {showCollapsedTab ? (\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n left: \"1rem\",\n zIndex: 9999,\n }}\n >\n <IconButton\n className=\"!rounded-[4px]\"\n icon={<FeatherChevronRight />}\n aria-label=\"Open cookie preferences\"\n onClick={openPanel}\n />\n </div>\n ) : null}\n\n <div\n style={{\n position: \"fixed\",\n bottom: \"1rem\",\n left: \"1rem\",\n zIndex: 9999,\n }}\n className={`flex w-[calc(100vw-2rem)] max-w-[512px] max-h-[calc(100dvh-2rem)] flex-col items-start transition-transform duration-300 ease-out ${\n effectivePanelOpen\n ? \"translate-x-0\"\n : \"-translate-x-[120%] pointer-events-none\"\n }`}\n aria-hidden={!effectivePanelOpen}\n >\n <div className=\"relative w-full\">\n {!pending ? (\n <div className=\"absolute bottom-0 right-[-33px] z-10 flex h-[33px] w-[33px] flex-none flex-col items-start gap-2\">\n <IconButton\n className=\"!rounded-[4px]\"\n icon={<FeatherChevronLeft />}\n aria-label=\"Close cookie preferences\"\n onClick={closePanel}\n />\n </div>\n ) : null}\n <div className=\"flex max-h-[calc(100dvh-2rem)] w-full flex-col items-start gap-5 overflow-y-auto rounded-[8px] border border-solid border-neutral-border bg-default-background px-4 py-4 shadow-lg\">\n\n <div className=\"flex w-full flex-col items-start gap-1\">\n <span className=\"text-heading-1 font-heading-1 text-default-font\">\n We use cookies.\n </span>\n <span className=\"w-full text-caption font-caption text-subtext-color\">\n We'd love not to, but they tend to be really useful. If you\n want to help us make better products, please enable some of them.\n It's cool if you don't though.\n </span>\n <div className=\"flex flex-wrap items-start gap-1\">\n <span className=\"text-caption font-caption text-subtext-color\">\n For more information, please visit our\n </span>\n <a\n href={privacyPolicyUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-caption font-caption underline-offset-2 hover:underline\"\n style={{ color: \"#ffff00\" }}\n >\n Privacy Policy\n </a>\n </div>\n </div>\n\n <div className=\"flex w-full flex-col items-start rounded-[8px] border border-solid border-neutral-border\">\n <ConsentRow\n title=\"Necessary\"\n description=\"Sign-in session, Paddle checkout, and this consent cookie.\"\n checked={true}\n disabled\n onInfo={() => setInfoCategory(\"necessary\")}\n tooltip=\"Required for the site to work — this one stays on.\"\n />\n <RowDivider />\n <ConsentRow\n title=\"Analytics\"\n description=\"PostHog cookies and linking events to your account. Cookieless usage stats still run if you decline.\"\n checked={draft.analytics}\n onCheckedChange={(checked) =>\n setDraft((current) => ({ ...current, analytics: checked }))\n }\n onInfo={() => setInfoCategory(\"analytics\")}\n />\n <RowDivider />\n <ConsentRow\n title=\"Marketing\"\n description=\"Meta Pixel for ad measurement. The script is not loaded unless you allow it.\"\n checked={draft.marketing}\n onCheckedChange={(checked) =>\n setDraft((current) => ({ ...current, marketing: checked }))\n }\n onInfo={() => setInfoCategory(\"marketing\")}\n />\n </div>\n\n <div className=\"flex w-full flex-col items-stretch justify-between gap-4 sm:flex-row sm:items-center sm:gap-8\">\n <ToggleGroup\n className=\"w-full !rounded-[4px] sm:w-auto\"\n value={presetValue ?? \"\"}\n onValueChange={(value: string) => {\n const next = presetToConsent(value);\n if (next) setDraft(next);\n }}\n >\n <ToggleGroup.Item\n className=\"!rounded-[4px]\"\n icon={null}\n value={PRESET_STRICTLY_NECESSARY}\n >\n Strictly Necessary\n </ToggleGroup.Item>\n <ToggleGroup.Item\n className=\"!rounded-[4px]\"\n icon={null}\n value={PRESET_MARKETING_AND_ANALYTICS}\n >\n Marketing and Analytics\n </ToggleGroup.Item>\n </ToggleGroup>\n <Button\n className=\"w-full shrink-0 !rounded-[4px] sm:w-auto\"\n variant=\"neutral-primary\"\n onClick={save}\n >\n Save\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n <ConsentInfoDialog\n category={infoCategory}\n onClose={() => setInfoCategory(null)}\n />\n </>,\n document.body,\n );\n}\n\nfunction RowDivider() {\n return (\n <div className=\"flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border\" />\n );\n}\n\ninterface ConsentRowProps {\n title: string;\n description: string;\n checked: boolean;\n disabled?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n onInfo: () => void;\n tooltip?: string;\n}\n\nfunction ConsentRow({\n title,\n description,\n checked,\n disabled = false,\n onCheckedChange,\n onInfo,\n tooltip,\n}: ConsentRowProps) {\n const switchControl = (\n <Switch\n checked={checked}\n disabled={disabled}\n onCheckedChange={onCheckedChange}\n className={\n disabled\n ? \"cursor-not-allowed !rounded-[9999px] aria-[checked=true]:border-neutral-400 aria-[checked=true]:bg-neutral-400\"\n : \"!rounded-[9999px] aria-[checked=true]:!border-[#ffff00] aria-[checked=true]:!bg-[#ffff00]\"\n }\n />\n );\n\n return (\n <div className=\"flex w-full items-center justify-between px-3 py-2\">\n <div className=\"flex flex-col items-start\">\n <span className=\"text-body-bold font-body-bold text-default-font\">\n {title}\n </span>\n <span className=\"text-caption font-caption text-subtext-color\">\n {description}\n </span>\n </div>\n <div className=\"flex items-center justify-center gap-1\">\n <IconButton\n className=\"!rounded-[4px]\"\n icon={<FeatherInfo />}\n aria-label={`More information about ${title}`}\n onClick={onInfo}\n />\n {tooltip ? (\n <SubframeCore.Tooltip.Provider>\n <SubframeCore.Tooltip.Root>\n <SubframeCore.Tooltip.Trigger asChild={true}>\n {switchControl}\n </SubframeCore.Tooltip.Trigger>\n <SubframeCore.Tooltip.Portal>\n <SubframeCore.Tooltip.Content\n side=\"top\"\n align=\"center\"\n sideOffset={4}\n asChild={true}\n >\n <Tooltip className=\"h-auto w-auto max-w-[208px] flex-none !rounded-[4px]\">\n {tooltip}\n </Tooltip>\n </SubframeCore.Tooltip.Content>\n </SubframeCore.Tooltip.Portal>\n </SubframeCore.Tooltip.Root>\n </SubframeCore.Tooltip.Provider>\n ) : (\n switchControl\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|