@lockerverse/react 0.1.16 → 0.2.18
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CreateLockerverseWidgetOptions, LockerversePaymentResult } from "@lockerverse/sdk/checkout";
|
|
2
1
|
import { loadStripe } from "@stripe/stripe-js";
|
|
3
2
|
import { CSSProperties, ComponentPropsWithoutRef } from "react";
|
|
3
|
+
import { CreateLockerverseWidgetOptions, LockerversePaymentResult } from "@lockerverse/sdk/checkout";
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
type LockerversePaymentSelectionItem = {
|
|
6
6
|
amountCents: number;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/lockerverse-payment.tsx"],"mappings":";;;;KAOY;EACN;EAAqB;;EACrB;EAAqB;;KAEf;KAEA;EACV;EACA;EACA;;KAGU,0BAA0B;EACpC;EACA;EACA;;KAGU;EACV;EACA;;KAGU,0BAA0B,iCACpC,KAAK;EACH,WAAW;EACX,qBAAqB,SAAS;EAC9B,sBAAsB,SAAS;EAC/B,WAAW;EACX,sBAAsB;EACtB,QAAQ;EACR,QAAQ;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/lockerverse-payment.tsx"],"mappings":";;;;KAOY;EACN;EAAqB;;EACrB;EAAqB;;KAEf;KAEA;EACV;EACA;EACA;;KAGU,0BAA0B;EACpC;EACA;EACA;;KAGU;EACV;EACA;;KAGU,0BAA0B,iCACpC,KAAK;EACH,WAAW;EACX,qBAAqB,SAAS;EAC9B,sBAAsB,SAAS;EAC/B,WAAW;EACX,sBAAsB;EACtB,QAAQ;EACR,QAAQ;;;;iBCwkCI,qBACd,YACA,UACA,WACA,eACA,aACA,OACA,SACA,mBACA,oBACA,kBACA,WACA,WACA,OACA,cACA,OACA,eACG,gBACF,0CAAuB,IAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createLockerverseCheckout as e}from"@lockerverse/sdk/checkout";import{AddressElement as t,Elements as n,PaymentElement as r,useElements as i,useStripe as a}from"@stripe/react-stripe-js";import{loadStripe as o}from"@stripe/stripe-js";import{useEffect as s,useId as c,useMemo as l,useRef as u,useState as d}from"react";import{Fragment as f,jsx as p,jsxs as m}from"react/jsx-runtime";import{array as h,email as g,minLength as _,minValue as ee,nonEmpty as v,number as y,object as te,pipe as b,regex as x,safeInteger as S,safeParse as C,strictObject as w,string as T,transform as E,trim as D,union as O}from"valibot";const k=/^#([\da-f]{3}|[\da-f]{6})$/i;function A(e){let t=k.exec(e.trim());if(!t)return;let[,n]=t;if(!n)return;let r=n.length===3?Array.from(n,e=>`${e}${e}`).join(``):n;return[0,2,4].map(e=>Number.parseInt(r.slice(e,e+2),16))}function j([e,t,n]){let[r=0,i=0,a=0]=[e,t,n].map((e=0)=>{let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4});return .2126*r+.7152*i+.0722*a}function ne(e){let t=A(e);if(!t)return;let n=j(t);return(n+.05)/.05>=1.05/(n+.05)?`#000`:`#fff`}const M=[`XS`,`S`,`M`,`L`,`XL`,`XXL`,`XXXL`],N=[`15`,`12`,`10`,`5`];function re({enabled:e,error:t,errorId:n,onChange:r,values:i}){if(!e)return null;let a=e=>r({...i,...e});return m(`div`,{className:`lockerverse-payment__tip-box`,children:[p(`p`,{children:`Add a tip to support the Lockerverse platform`}),m(`div`,{"aria-label":`Tip amount`,role:`radiogroup`,children:[N.map(e=>m(`button`,{"aria-pressed":i.tipPercent===e,onClick:()=>a({tipPercent:e}),type:`button`,children:[e,`%`]},e)),p(`button`,{"aria-pressed":i.tipPercent===`custom`,onClick:()=>a({tipPercent:`custom`}),type:`button`,children:`Other`})]}),i.tipPercent===`custom`?m(`label`,{children:[p(`span`,{children:`Custom tip`}),m(`span`,{className:`lockerverse-payment__money-input`,children:[p(`span`,{"aria-hidden":`true`,children:`$`}),p(`input`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,inputMode:`decimal`,name:`tip`,onChange:e=>a({customTip:e.currentTarget.value}),placeholder:`0.00`,value:i.customTip})]}),t?p(`span`,{className:`lockerverse-payment__field-message`,id:n,children:t}):null]}):p(`input`,{name:`tip`,type:`hidden`,value:i.tipPercent})]})}function P({checked:e,children:t,name:n,onChange:r}){return m(`label`,{className:`lockerverse-payment__check-row`,children:[p(`input`,{checked:e,name:n,onChange:e=>r(e.currentTarget.checked),type:`checkbox`}),p(`span`,{children:t})]})}function F({customFields:e,errors:t,fields:n,idPrefix:r,onChange:i,values:a}){let o=e=>i({...a,...e});return m(`div`,{className:`lockerverse-payment__additional-fields`,children:[n.memberId?m(`label`,{children:[p(`span`,{children:`Member ID`}),p(`input`,{name:`memberId`,onChange:e=>o({memberId:e.currentTarget.value}),placeholder:`Optional`,value:a.memberId})]}):null,n.merchSize?m(`label`,{children:[p(`span`,{children:`Size`}),p(`select`,{name:`merchSize`,onChange:e=>o({merchSize:e.currentTarget.value}),value:a.merchSize,children:M.map(e=>p(`option`,{value:e,children:e},e))})]}):null,n.promoCode?m(`label`,{children:[p(`span`,{children:`Promo code`}),p(`input`,{name:`promoCode`,onChange:e=>o({promoCode:e.currentTarget.value}),placeholder:`Optional`,value:a.promoCode})]}):null,e.map(e=>p(I,{error:t[e.id],field:e,idPrefix:r,onChange:t=>o({customFields:{...a.customFields,[e.id]:t}}),value:a.customFields[e.id]},e.id))]})}function ie({amountCents:e,enabled:t,onChange:n,values:r}){return t?m(P,{checked:r.includeServiceFee,name:`includeServiceFee`,onChange:e=>n({...r,includeServiceFee:e}),children:[`Add `,V(e),` to help cover processing fees`]}):null}function I({error:e,field:t,idPrefix:n,onChange:r,value:i}){let a=`custom:${t.id}`,o=`${n}-custom-${t.id}`,s=`${o}-error`;switch(t.type){case`text`:case`textarea`:return p(R,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});case`select`:case`multi_select`:return p(z,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});case`radio`:case`checkboxes`:return p(B,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});default:return null}}function L({error:e,id:t}){return e?p(`p`,{className:`lockerverse-payment__field-message`,id:t,children:e}):null}function R({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){let s={"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,id:e,name:i,onChange:e=>a(e.currentTarget.value),required:r.required,value:typeof o==`string`?o:``};return m(`label`,{htmlFor:e,children:[p(`span`,{children:r.label}),r.type===`textarea`?p(`textarea`,{...s}):p(`input`,{...s}),p(L,{error:t,id:n})]})}function z({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){return m(`label`,{htmlFor:e,children:[p(`span`,{children:r.label}),m(`select`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,id:e,multiple:r.type===`multi_select`,name:i,onChange:e=>a(r.type===`multi_select`?[...e.currentTarget.selectedOptions].map(e=>e.value):e.currentTarget.value),required:r.required,value:o??(r.type===`multi_select`?[]:``),children:[r.type===`select`?p(`option`,{value:``,children:`Select…`}):null,r.options.map(e=>p(`option`,{value:e.id,children:e.label},e.id))]}),p(L,{error:t,id:n})]})}function B({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){return m(`fieldset`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,children:[p(`legend`,{children:r.label}),r.options.map((t,n)=>{let s=Array.isArray(o)?o.includes(t.id):o===t.id;return m(`label`,{className:`lockerverse-payment__check-row`,children:[p(`input`,{checked:s,id:`${e}-${n}`,name:i,onChange:e=>{if(r.type===`radio`){a(t.id);return}let n=Array.isArray(o)?o:[];a(e.currentTarget.checked?[...n,t.id]:n.filter(e=>e!==t.id))},required:r.required,type:r.type===`radio`?`radio`:`checkbox`,value:t.id}),p(`span`,{children:t.label})]},t.id)}),p(L,{error:t,id:n})]})}function V(e){return new Intl.NumberFormat(`en-US`,{currency:`USD`,style:`currency`}).format(e/100)}const H=[`amountCents`,`discountableSubtotalCents`,`discountCents`,`serviceFeeCents`,`subtotalCents`,`tipCents`,`totalCents`];function ae(e,t){return H.some(n=>e[n]!==t[n])||e.payment.connectedAccountId!==t.payment.connectedAccountId||e.payment.currency!==t.payment.currency||JSON.stringify(e.appliedDiscount)!==JSON.stringify(t.appliedDiscount)||JSON.stringify(e.lineItems)!==JSON.stringify(t.lineItems)}function U(e){return e.checkoutStatus===`success`?{kind:`success`,payment:e}:e.checkoutStatus===`failed`?{kind:`failed`,payment:e}:{kind:`unresolved`,paymentReference:e.paymentReference,reason:e.checkoutStatus===`action_required`?`action_required`:`pending`}}async function W(e,t,n){if(t.checkoutStatus!==`action_required`)return U(t);if(t.clientSecret)try{await n.handleNextAction({clientSecret:t.clientSecret})}catch{}try{return U(await e.getPaymentStatus(t.paymentReference))}catch{return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`}}}async function G(e,t,n){let r;try{r=await e.submitPayment(t)}catch(t){let n=e.getState();if(n.phase!==`error`||!n.recoverablePaymentReference)throw t;try{r=await e.getPaymentStatus(n.recoverablePaymentReference)}catch{return{kind:`unresolved`,paymentReference:n.recoverablePaymentReference,reason:`recovery_failed`}}}return W(e,r,n)}const K=b(T(),D(),v()),q=b(y(),S(),ee(1)),oe=b(h(O([w({amountCents:q,productSlug:K}),w({productSlug:K,quantity:q})])),_(1)),se=b(T(),D(),x(/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/,`Enter a valid tip amount.`),E(e=>Math.round(Number(e)*100)),S(`Enter a valid tip amount.`));function ce(e){let t=C(se,e);return t.success?{cents:t.output,success:!0}:{message:t.issues[0]?.message??`Enter a valid tip amount.`,success:!1}}function le(e){let t=C(oe,e);return t.success?{success:!0,value:t.output}:{message:`Lockerverse payment configuration is invalid.`,success:!1}}const J=b(T(),D(),v(`Email is required.`),g(`Enter a valid email address.`)),Y=b(T(),D(),v(`Phone is required.`),x(/^\+[1-9]\d{6,14}$/,`Enter a valid phone number.`));function X(e){return e.trim().replace(/[().\s-]/g,``)}function ue(e,t){let n=t?{...e,phone:X(e.phone)}:e,r=te(t?{email:J,phone:Y}:{email:J}),i=C(r,n);if(i.success)return{errors:{},value:i.output};let a={};for(let e of i.issues){let t=e.path?.[0]?.key;(t===`email`||t===`phone`)&&!a[t]&&(a[t]=e.message)}return{errors:a,value:null}}function de(e,t){let n={};for(let r of e){if(!r.required)continue;let e=`${r.label} is required.`,i=t[r.id],a=r.type===`checkboxes`||r.type===`multi_select`?C(b(h(T()),_(1,e)),i??[]):C(b(T(),D(),v(e)),typeof i==`string`?i:``);a.success||(n[r.id]=a.issues[0]?.message??e)}return n}function fe(e,t,n){if(n.length===0)throw TypeError(`Lockerverse payment requires at least one Product.`);for(let r of n){let n=t.products.find(e=>e.slug===r.productSlug);if(!n)throw TypeError(`Product ${r.productSlug} is not available.`);`amountCents`in r?e.setAmount(n.slug,r.amountCents):e.setQuantity(n.slug,r.quantity)}}function Z(e){return new Intl.NumberFormat(`en-US`,{currency:`USD`,style:`currency`}).format(e/100)}function pe(e,t){return t.tipPercent===`custom`?ce(t.customTip):{cents:Math.round(e*Number(t.tipPercent)/100),success:!0}}const me=[{callingCode:`+1`,label:`🇺🇸 +1`,value:`US`},{callingCode:`+52`,label:`🇲🇽 +52`,value:`MX`},{callingCode:`+380`,label:`🇺🇦 +380`,value:`UA`},{callingCode:`+48`,label:`🇵🇱 +48`,value:`PL`},{callingCode:`+1`,label:`🇨🇦 +1`,value:`CA`},{callingCode:`+49`,label:`🇩🇪 +49`,value:`DE`},{callingCode:`+44`,label:`🇬🇧 +44`,value:`GB`},{callingCode:`+46`,label:`🇸🇪 +46`,value:`SE`},{callingCode:`+358`,label:`🇫🇮 +358`,value:`FI`},{callingCode:`+1`,label:`🇵🇷 +1`,value:`PR`}];function he(e,t){return e.trim().startsWith(`+`)?e:`${me.find(e=>e.value===t)?.callingCode??`+1`}${e}`}function ge(e,t){return e.map(e=>{let n=t[e.id];return e.type===`checkboxes`||e.type===`multi_select`?{fieldId:e.id,value:Array.isArray(n)?n:[]}:{fieldId:e.id,value:typeof n==`string`?n:``}})}function Q(e,t,n,r){return{email:n,...e.widget.fields.serviceFee?{includeServiceFee:t.includeServiceFee}:{},...e.widget.fields.promoCode&&t.promoCode.trim()?{promoCode:t.promoCode.trim()}:{},...e.widget.fields.tipping?{tipCents:r}:{}}}async function $(e,t){let n=e.getElement(`address`,{mode:t}),r=t===`billing`?`Billing`:`Shipping`;if(!n)throw Error(`${r} address is still loading.`);let i=await n.getValue();if(!i.complete)throw Error(`${r} address is required.`);return i.value}function _e(e,t,n,r){if(e.widget.fields.shipping)return n.shippingMatchesBilling?r:$(t,`shipping`)}function ve({billingAddress:e,catalog:t,email:n,phone:r,shippingAddress:i}){return{payment_method_data:{billing_details:{address:e.address,email:n,name:e.name,...t.widget.fields.phone?{phone:r}:{}}},...i?{shipping:{address:i.address,name:i.name,phone:t.widget.fields.phone?r:i.phone??null}}:{}}}function ye({catalog:e,confirmationToken:t,email:n,fieldValues:r,phone:i}){return{confirmationToken:t,customFieldAnswers:ge(e.widget.customFields,r.customFields),email:n,...e.widget.fields.memberId&&r.memberId.trim()?{memberId:r.memberId.trim()}:{},...e.widget.fields.merchSize?{merchSize:r.merchSize}:{},...e.widget.fields.phone?{phone:i}:{}}}async function be({catalog:e,checkout:t,elements:n,email:r,fieldValues:i,phone:a,quote:o,stripe:s}){let c=r.trim().toLowerCase(),l=X(a),u=pe(o.subtotalCents,i);if(!u.success)throw Error(u.message);let d=await t.calculateTotal(Q(e,i,c,u.cents));if(n.update({amount:d.totalCents}),ae(o,d))return{kind:`quote_changed`,quote:d};let f=await n.submit();if(f.error)throw Error(f.error.message);let p=await $(n,`billing`),m=await _e(e,n,i,p),h=await s.createConfirmationToken({elements:n,params:ve({billingAddress:p,catalog:e,email:c,phone:l,shippingAddress:m})});if(h.error)throw Error(h.error.message);let g=await G(t,ye({catalog:e,confirmationToken:h.confirmationToken.id,email:c,fieldValues:i,phone:l}),s);return g.kind===`failed`?{kind:`payment_failed`,message:`Payment was declined. Check your payment details and try again.`}:g.kind===`unresolved`?{kind:`payment_unresolved`,paymentReference:g.paymentReference,reason:g.reason}:{kind:`payment`,payment:g.payment,quote:d}}function xe({accentColor:e,catalog:t,checkout:r,onPaymentComplete:i,onPaymentUncertain:a,onQuoteChange:o,quote:s,onStateChange:c,stripeLoader:u,theme:d}){let f=l(()=>u(t.payment.publishableKey,s.payment.connectedAccountId?{stripeAccount:s.payment.connectedAccountId}:void 0),[t.payment.publishableKey,s.payment.connectedAccountId,u]);return p(n,{options:{amount:s.totalCents,appearance:{rules:{".Input:focus":{borderColor:e,boxShadow:`none`,outline:`none`}},theme:d===`light`?`stripe`:`night`,variables:{borderRadius:`8px`,colorBackground:d===`light`?`#f5f6f7`:`#101010`,colorDanger:d===`light`?`#c52b3e`:`#ef4444`,colorPrimary:e,colorText:d===`light`?`#121416`:`#ffffff`,colorTextPlaceholder:d===`light`?`#72767d`:`#6b6b6b`,colorTextSecondary:d===`light`?`#62666d`:`#a1a1aa`,focusBoxShadow:`none`,focusOutline:`none`,fontFamily:`Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif`,fontSizeBase:`16px`}},currency:s.payment.currency,excludedPaymentMethodTypes:[`us_bank_account`],mode:`payment`,syncAddressCheckbox:`none`},stripe:f,children:p(ke,{catalog:t,checkout:r,onPaymentComplete:i,onPaymentUncertain:a,onQuoteChange:o,onStateChange:c,quote:s})},`${t.payment.publishableKey}:${s.payment.connectedAccountId??`platform`}`)}function Se({label:e}){return m(`div`,{className:`lockerverse-payment__stripe-loader`,role:`status`,children:[p(`p`,{children:e}),m(`div`,{"aria-hidden":`true`,children:[p(`span`,{}),p(`span`,{}),p(`span`,{})]})]})}function Ce({onError:e,onReady:t,ready:n}){return m(`div`,{className:`lockerverse-payment__stripe-element`,"data-ready":n,children:[n?null:p(Se,{label:`Loading payment form...`}),p(r,{onLoadError:({error:t})=>e(t.message??`Payment form failed to load.`),onReady:t,options:{business:{name:`Lockerverse`},fields:{billingDetails:{email:`auto`}},layout:`tabs`,terms:{applePay:`auto`,auBecsDebit:`never`,bancontact:`never`,card:`always`,cashapp:`never`,googlePay:`never`,ideal:`never`,paypal:`auto`,sepaDebit:`never`,sofort:`never`,usBankAccount:`never`},wallets:{applePay:`auto`,googlePay:`never`}}})]})}function we({label:e,mode:n,onError:r,onReady:i,ready:a}){return m(`div`,{className:`lockerverse-payment__address`,children:[p(`h2`,{children:e}),m(`div`,{className:`lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address`,"data-ready":a,children:[a?null:p(Se,{label:`Loading ${e.toLowerCase()}...`}),p(t,{onLoadError:({error:t})=>r(t.message??`${e} failed to load.`),onReady:i,options:{autocomplete:{mode:`automatic`},mode:n}})]})]})}function Te({message:e}){return e?p(`p`,{className:`lockerverse-payment__field-message`,role:`alert`,children:e}):null}function Ee({customFieldErrors:e,emailRef:t,form:n,parsedTipSuccess:r,phoneRef:i,validationErrors:a}){if(a.email){t.current?.focus();return}if(a.phone){i.current?.focus();return}if(!r){n.querySelector(`[name="tip"]`)?.focus();return}let[o]=Object.keys(e);o&&n.querySelector(`[name="custom:${o}"]`)?.focus()}function De({onPaymentComplete:e,onPaymentUncertain:t,onQuoteChange:n,onStateChange:r,result:i,setDisplayedTotalCents:a,setPaymentError:o,setTerminalState:s}){if(i.kind===`quote_changed`){let e=`The total changed to ${Z(i.quote.totalCents)}. Review it and pay again.`;n(i.quote,e),a(i.quote.totalCents),r(`idle`);return}if(i.kind===`payment_failed`){o(i.message),r(`error`);return}if(i.kind===`payment_unresolved`){s({kind:`unresolved`,message:`Payment is still processing. Do not submit it again.`}),r(`unresolved`);try{t?.({paymentReference:i.paymentReference,reason:i.reason})}catch{}return}n(i.quote),s({kind:`success`,message:`Payment completed successfully.`}),r(`success`);try{e?.(i.payment)}catch{}}function Oe({email:e,emailErrorId:t,emailId:n,emailRef:r,errors:i,onEmailChange:a,onPhoneChange:o,onPhoneCountryChange:s,phone:c,phoneCountry:l,phoneEnabled:u,phoneErrorId:d,phoneId:h,phoneRef:g}){return m(`div`,{className:`lockerverse-payment__contact`,children:[p(`label`,{htmlFor:n,children:`Email`}),p(`input`,{"aria-describedby":i.email?t:void 0,"aria-invalid":i.email?`true`:void 0,autoComplete:`email`,id:n,name:`email`,onChange:e=>a(e.currentTarget.value),placeholder:`name@example.com`,ref:r,type:`email`,value:e}),i.email?p(`p`,{className:`lockerverse-payment__field-message`,id:t,children:i.email}):null,u?m(f,{children:[p(`label`,{htmlFor:h,children:`Phone`}),m(`div`,{className:`lockerverse-payment__phone-control`,children:[p(`select`,{"aria-label":`Phone number country`,name:`phoneCountry`,onChange:e=>s(e.currentTarget.value),value:l,children:me.map(e=>p(`option`,{value:e.value,children:e.label},e.value))}),p(`input`,{"aria-describedby":i.phone?d:void 0,"aria-invalid":i.phone?`true`:void 0,autoComplete:`tel`,id:h,inputMode:`tel`,name:`phone`,onChange:e=>o(e.currentTarget.value),placeholder:`(201) 555-0123`,ref:g,type:`tel`,value:c})]}),i.phone?p(`p`,{className:`lockerverse-payment__field-message`,id:d,children:i.phone}):null]}):null]})}function ke({catalog:e,checkout:t,onPaymentComplete:n,onPaymentUncertain:r,onQuoteChange:o,onStateChange:l,quote:f}){let[h,g]=d(``),[_,ee]=d(``),[v,y]=d(`US`),[te,b]=d({}),[x,S]=d(),[C,w]=d({}),[T,E]=d(),[D,O]=d(!1),[k,A]=d(),[j,ne]=d(!1),[M,N]=d(!1),[I,L]=d(!1),[R,z]=d({customFields:{},customTip:``,includeServiceFee:e.widget.fields.serviceFee,memberId:``,merchSize:`M`,promoCode:``,shippingMatchesBilling:!0,tipPercent:`10`}),[B,V]=d(f.totalCents),H=u(null),ae=u(null),U=u(null),W=i(),G=a(),K=`lockerverse-${c()}`,q=`${K}-email`,oe=`${q}-error`,se=`${K}-phone`,ce=`${se}-error`,le=`${K}-tip-error`,J=e.widget.fields.tipping?pe(f.subtotalCents,R):{cents:0,success:!0},Y=J.success?J.cents:null,X=Y??0,fe=B-X,me=!e.widget.fields.shipping||R.shippingMatchesBilling||I;s(()=>{if(D||Y===null)return;let n=t.previewTotal({...e.widget.fields.serviceFee?{includeServiceFee:R.includeServiceFee}:{},...e.widget.fields.tipping?{tipCents:Y}:{}});V(n.totalCents),W?.update({amount:n.totalCents})},[e.widget.fields.serviceFee,e.widget.fields.tipping,t,W,R.includeServiceFee,R.tipPercent,R.customTip,D,Y,f.subtotalCents]),s(()=>{D&&U.current?.focus()},[D]);function ge(e){b(t=>{let n={...t};return delete n[e],n})}function Q(e){z(e),w({}),E(void 0)}function $(e){S(e),l(`error`)}async function _e(i){i.preventDefault();let a=ue({email:h,phone:he(_,v)},e.widget.fields.phone),s=de(e.widget.customFields,R.customFields);if(!(a.value&&J.success)||Object.keys(s).length>0){b(a.errors),w(s),E(J.success?void 0:J.message),l(`invalid`);let e=i.currentTarget;queueMicrotask(()=>{Ee({customFieldErrors:s,emailRef:H,form:e,parsedTipSuccess:J.success,phoneRef:ae,validationErrors:a.errors})});return}if(b({}),w({}),!(W&&G)){S(`Payment form is still loading.`),l(`error`);return}S(void 0),O(!0),l(`submitting`);try{De({onPaymentComplete:n,onPaymentUncertain:r,onQuoteChange:o,onStateChange:l,result:await be({catalog:e,checkout:t,elements:W,email:h,fieldValues:R,phone:he(_,v),quote:f,stripe:G}),setDisplayedTotalCents:V,setPaymentError:S,setTerminalState:A})}catch(e){S(e instanceof Error?e.message:`Payment could not be completed.`),l(`error`)}finally{O(!1)}}return k?p(`p`,{className:`lockerverse-payment__payment-status`,ref:U,role:`status`,tabIndex:-1,children:k.message}):m(`form`,{"aria-busy":D,className:`lockerverse-payment__form`,noValidate:!0,onSubmit:_e,children:[p(`div`,{"data-lockerverse-input-region":``,inert:D?!0:void 0,children:m(`fieldset`,{className:`lockerverse-payment__input-fieldset`,disabled:D,children:[p(re,{enabled:e.widget.fields.tipping,error:T,errorId:le,onChange:Q,values:R}),p(Oe,{email:h,emailErrorId:oe,emailId:q,emailRef:H,errors:te,onEmailChange:e=>{g(e),ge(`email`)},onPhoneChange:e=>{ee(e),ge(`phone`)},onPhoneCountryChange:y,phone:_,phoneCountry:v,phoneEnabled:e.widget.fields.phone,phoneErrorId:ce,phoneId:se,phoneRef:ae}),p(Ce,{onError:$,onReady:()=>ne(!0),ready:j}),p(we,{label:`Billing address`,mode:`billing`,onError:$,onReady:()=>N(!0),ready:M}),e.widget.fields.shipping?m(`div`,{className:`lockerverse-payment__shipping`,children:[p(P,{checked:R.shippingMatchesBilling,name:`shippingMatchesBilling`,onChange:e=>{Q({...R,shippingMatchesBilling:e}),e||L(!1)},children:`Shipping is same as billing information`}),R.shippingMatchesBilling?null:p(we,{label:`Shipping address`,mode:`shipping`,onError:$,onReady:()=>L(!0),ready:I})]}):null,p(F,{customFields:e.widget.customFields,errors:C,fields:e.widget.fields,idPrefix:K,onChange:Q,values:R}),m(`div`,{className:`lockerverse-payment__actions`,children:[p(ie,{amountCents:f.serviceFeeCents||Math.round(f.subtotalCents*e.pricingPolicy.serviceFeeRateBasisPoints/1e4),enabled:e.widget.fields.serviceFee,onChange:Q,values:R}),p(`button`,{"aria-busy":D,"aria-label":`Process payment for ${Z(B)} total`,disabled:D||!(j&&M&&me),type:`submit`,children:D?`Processing…`:`Process Payment (${Z(fe)})${X>0?` + ${Z(X)} tip`:``}`})]})]})}),D?p(`p`,{className:`lockerverse-payment__payment-status`,ref:U,role:`status`,tabIndex:-1,children:`Processing payment…`}):null,p(Te,{message:x})]})}function Ae({apiBaseUrl:e,communitySlug:t,environment:n,fetch:r,onError:i,requestTimeoutMs:a,sentryDsn:o,widgetSlug:s}){let c={communitySlug:t,widgetSlug:s,...r?{fetch:r}:{},...i?{onError:i}:{},...a===void 0?{}:{requestTimeoutMs:a},...o===void 0?{}:{sentryDsn:o}};if(e===void 0){if(n===`development`)throw TypeError(`Lockerverse development checkout requires an API base URL.`);return{...c,...n===`production`?{environment:n}:{}}}if(!n)throw TypeError(`Lockerverse development checkout requires an environment.`);return{...c,apiBaseUrl:e,environment:n}}function je(){return m(`div`,{className:`lockerverse-payment__skeleton-loader-block`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-label`}),m(`div`,{className:`lockerverse-payment__skeleton-loader-content`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-full`}),m(`div`,{className:`lockerverse-payment__skeleton-loader-grid`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-half`}),p(`span`,{className:`lockerverse-payment__skeleton-loader-half`})]})]})]})}function Me(){return m(`div`,{className:`lockerverse-payment__loading`,children:[p(`span`,{"aria-live":`polite`,className:`lockerverse-payment__sr-only`,role:`status`,children:`Loading payment…`}),m(`div`,{"aria-hidden":`true`,className:`lockerverse-payment__skeleton`,children:[m(`div`,{className:`lockerverse-payment__skeleton-branding`,children:[p(`span`,{className:`lockerverse-payment__skeleton-avatar`}),p(`span`,{className:`lockerverse-payment__skeleton-community`})]}),m(`div`,{className:`lockerverse-payment__skeleton-contact`,children:[m(`div`,{className:`lockerverse-payment__skeleton-field`,children:[p(`span`,{className:`lockerverse-payment__skeleton-label`}),p(`span`,{className:`lockerverse-payment__skeleton-input`})]}),m(`div`,{className:`lockerverse-payment__skeleton-field`,children:[p(`span`,{className:`lockerverse-payment__skeleton-label`}),p(`span`,{className:`lockerverse-payment__skeleton-input`})]})]}),p(je,{}),p(je,{}),m(`div`,{className:`lockerverse-payment__skeleton-actions`,children:[p(`span`,{className:`lockerverse-payment__skeleton-check-line`}),p(`span`,{className:`lockerverse-payment__skeleton-button`})]})]})]})}function Ne({apiBaseUrl:t,branding:n,className:r,communitySlug:i,environment:a,fetch:c,onError:f,onPaymentComplete:h,onPaymentUncertain:g,requestTimeoutMs:_,selection:ee,sentryDsn:v,style:y,stripeLoader:te=o,theme:b=`dark`,widgetSlug:x,...S}){let C=l(()=>Ae({apiBaseUrl:t,communitySlug:i,environment:a,fetch:c,onError:f,requestTimeoutMs:_,sentryDsn:v,widgetSlug:x}),[t,i,a,c,f,_,v,x]),w=le(ee),T=w.success?JSON.stringify(w.value):`invalid-selection`,E=l(()=>w.success?JSON.parse(T):[],[T]),[D,O]=d(),[k,A]=d(),[j,M]=d(),[N,re]=d(),[P,F]=d(),[ie,I]=d(),[L,R]=d(`idle`),z=u(void 0);s(()=>{if(!w.success||L===`submitting`||L===`success`||L===`unresolved`||N===T||z.current===T)return;let t=!0,n=e(C);z.current=T,O(void 0),A(void 0),F(void 0),I(void 0),M(void 0);async function r(){try{let e=await n.load();fe(n,e,E);let r=await n.calculateTotal({...e.widget.fields.serviceFee?{includeServiceFee:!0}:{}});t&&(O(e),A(n),re(T),R(`idle`),M(r))}catch(e){t&&F(e instanceof Error?e.message:`Lockerverse payment could not load.`)}}return r(),()=>{t=!1,z.current===T&&(z.current=void 0)}},[C,N,w.success,L,T,E]);let B=[`lockerverse-payment`,r].filter(Boolean).join(` `),V=ne(y?.[`--lockerverse-accent`]??n?.accentColor??`#38d77a`),H={...y,...n?.accentColor&&y?.[`--lockerverse-accent`]===void 0?{"--lockerverse-accent":n.accentColor}:{},...V&&y?.[`--lockerverse-accent-contrast`]===void 0?{"--lockerverse-accent-contrast":V}:{}};return w.success?P?p(`section`,{...S,className:B,"data-lockerverse-theme":b,role:`alert`,children:P}):D&&k&&j?m(`section`,{...S,"aria-label":`Payment`,className:B,"data-lockerverse-theme":b,"data-payment-state":L,style:H,children:[m(`header`,{children:[D.widget.showCommunityBranding&&n?m(`div`,{className:`lockerverse-payment__branding`,children:[n.imageUrl?p(`img`,{alt:n.name,height:`48`,src:n.imageUrl,width:`48`}):null,p(`strong`,{children:n.name})]}):null,p(`h1`,{children:D.widget.title??D.widget.name}),D.widget.description?p(`p`,{children:D.widget.description}):null]}),ie?p(`p`,{className:`lockerverse-payment__payment-status`,role:`status`,children:ie}):null,p(xe,{accentColor:y?.[`--lockerverse-accent`]??n?.accentColor??`#38d77a`,catalog:D,checkout:k,onPaymentComplete:h,onPaymentUncertain:g,onQuoteChange:(e,t)=>{I(t),M(e)},onStateChange:R,quote:j,stripeLoader:te,theme:b})]}):p(`section`,{...S,"aria-busy":`true`,"aria-label":`Payment`,className:B,"data-lockerverse-theme":b,children:p(Me,{})}):p(`section`,{...S,className:B,"data-lockerverse-theme":b,role:`alert`,style:H,children:w.message})}export{Ne as LockerversePayment};
|
|
1
|
+
import{AddressElement as e,Elements as t,PaymentElement as n,useElements as r,useStripe as i}from"@stripe/react-stripe-js";import{loadStripe as a}from"@stripe/stripe-js";import{useEffect as o,useId as s,useMemo as c,useReducer as l,useRef as u,useState as d}from"react";import{Fragment as f,jsx as p,jsxs as m}from"react/jsx-runtime";import{LockerverseSdkError as h,createLockerverseCheckoutClient as g}from"@lockerverse/sdk/checkout";import{array as _,email as v,minLength as y,minValue as b,nonEmpty as x,number as S,object as C,pipe as w,regex as T,safeInteger as E,safeParse as D,strictObject as O,string as k,transform as A,trim as j,union as M}from"valibot";const N=/^#([\da-f]{3}|[\da-f]{6})$/i;function P(e){let t=N.exec(e.trim());if(!t)return;let[,n]=t;if(!n)return;let r=n.length===3?Array.from(n,e=>`${e}${e}`).join(``):n;return[0,2,4].map(e=>Number.parseInt(r.slice(e,e+2),16))}function ee([e,t,n]){let[r=0,i=0,a=0]=[e,t,n].map((e=0)=>{let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4});return .2126*r+.7152*i+.0722*a}function te(e){let t=P(e);if(!t)return;let n=ee(t);return(n+.05)/.05>=1.05/(n+.05)?`#000`:`#fff`}const ne=[`XS`,`S`,`M`,`L`,`XL`,`XXL`,`XXXL`],F=[`15`,`12`,`10`,`5`];function re({enabled:e,error:t,errorId:n,onChange:r,values:i}){if(!e)return null;let a=e=>r({...i,...e});return m(`div`,{className:`lockerverse-payment__tip-box`,children:[p(`p`,{children:`Add a tip to support the Lockerverse platform`}),m(`div`,{"aria-label":`Tip amount`,role:`radiogroup`,children:[F.map(e=>m(`button`,{"aria-pressed":i.tipPercent===e,onClick:()=>a({tipPercent:e}),type:`button`,children:[e,`%`]},e)),p(`button`,{"aria-pressed":i.tipPercent===`custom`,onClick:()=>a({tipPercent:`custom`}),type:`button`,children:`Other`})]}),i.tipPercent===`custom`?m(`label`,{children:[p(`span`,{children:`Custom tip`}),m(`span`,{className:`lockerverse-payment__money-input`,children:[p(`span`,{"aria-hidden":`true`,children:`$`}),p(`input`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,inputMode:`decimal`,name:`tip`,onChange:e=>a({customTip:e.currentTarget.value}),placeholder:`0.00`,value:i.customTip})]}),t?p(`span`,{className:`lockerverse-payment__field-message`,id:n,children:t}):null]}):p(`input`,{name:`tip`,type:`hidden`,value:i.tipPercent})]})}function ie({checked:e,children:t,name:n,onChange:r}){return m(`label`,{className:`lockerverse-payment__check-row`,children:[p(`input`,{checked:e,name:n,onChange:e=>r(e.currentTarget.checked),type:`checkbox`}),p(`span`,{children:t})]})}function ae({customFields:e,errors:t,fields:n,idPrefix:r,onChange:i,values:a}){let o=e=>i({...a,...e});return m(`div`,{className:`lockerverse-payment__additional-fields`,children:[n.memberId?m(`label`,{children:[p(`span`,{children:`Member ID`}),p(`input`,{name:`memberId`,onChange:e=>o({memberId:e.currentTarget.value}),placeholder:`Optional`,value:a.memberId})]}):null,n.merchSize?m(`label`,{children:[p(`span`,{children:`Size`}),p(`select`,{name:`merchSize`,onChange:e=>o({merchSize:e.currentTarget.value}),value:a.merchSize,children:ne.map(e=>p(`option`,{value:e,children:e},e))})]}):null,n.promoCode?m(`label`,{children:[p(`span`,{children:`Promo code`}),p(`input`,{name:`promoCode`,onChange:e=>o({promoCode:e.currentTarget.value}),placeholder:`Optional`,value:a.promoCode})]}):null,e.map(e=>p(se,{error:t[e.id],field:e,idPrefix:r,onChange:t=>o({customFields:{...a.customFields,[e.id]:t}}),value:a.customFields[e.id]},e.id))]})}function oe({amountCents:e,enabled:t,onChange:n,values:r}){return t?m(ie,{checked:r.includeServiceFee,name:`includeServiceFee`,onChange:e=>n({...r,includeServiceFee:e}),children:[`Add `,L(e),` to help cover processing fees`]}):null}function se({error:e,field:t,idPrefix:n,onChange:r,value:i}){let a=`custom:${t.id}`,o=`${n}-custom-${t.id}`,s=`${o}-error`;switch(t.type){case`text`:case`textarea`:return p(ce,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});case`select`:case`multi_select`:return p(le,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});case`radio`:case`checkboxes`:return p(ue,{controlId:o,error:e,errorId:s,field:t,name:a,onChange:r,value:i});default:return null}}function I({error:e,id:t}){return e?p(`p`,{className:`lockerverse-payment__field-message`,id:t,children:e}):null}function ce({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){let s={"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,id:e,name:i,onChange:e=>a(e.currentTarget.value),required:r.required,value:typeof o==`string`?o:``};return m(`label`,{htmlFor:e,children:[p(`span`,{children:r.label}),r.type===`textarea`?p(`textarea`,{...s}):p(`input`,{...s}),p(I,{error:t,id:n})]})}function le({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){return m(`label`,{htmlFor:e,children:[p(`span`,{children:r.label}),m(`select`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,id:e,multiple:r.type===`multi_select`,name:i,onChange:e=>a(r.type===`multi_select`?[...e.currentTarget.selectedOptions].map(e=>e.value):e.currentTarget.value),required:r.required,value:o??(r.type===`multi_select`?[]:``),children:[r.type===`select`?p(`option`,{value:``,children:`Select…`}):null,r.options.map(e=>p(`option`,{value:e.id,children:e.label},e.id))]}),p(I,{error:t,id:n})]})}function ue({controlId:e,error:t,errorId:n,field:r,name:i,onChange:a,value:o}){return m(`fieldset`,{"aria-describedby":t?n:void 0,"aria-invalid":t?`true`:void 0,children:[p(`legend`,{children:r.label}),r.options.map((t,n)=>{let s=Array.isArray(o)?o.includes(t.id):o===t.id;return m(`label`,{className:`lockerverse-payment__check-row`,children:[p(`input`,{checked:s,id:`${e}-${n}`,name:i,onChange:e=>{if(r.type===`radio`){a(t.id);return}let n=Array.isArray(o)?o:[];a(e.currentTarget.checked?[...n,t.id]:n.filter(e=>e!==t.id))},required:r.required,type:r.type===`radio`?`radio`:`checkbox`,value:t.id}),p(`span`,{children:t.label})]},t.id)}),p(I,{error:t,id:n})]})}function L(e){return new Intl.NumberFormat(`en-US`,{currency:`USD`,style:`currency`}).format(e/100)}const R=[`amountCents`,`discountableSubtotalCents`,`discountCents`,`serviceFeeCents`,`subtotalCents`,`tipCents`,`totalCents`];function z(e,t){return R.some(n=>e[n]!==t[n])||e.payment.connectedAccountId!==t.payment.connectedAccountId||e.payment.currency!==t.payment.currency||JSON.stringify(e.appliedDiscount)!==JSON.stringify(t.appliedDiscount)||JSON.stringify(e.lineItems)!==JSON.stringify(t.lineItems)}function B(e){return e.checkoutStatus===`success`?{kind:`success`,payment:e}:e.checkoutStatus===`failed`?{kind:`failed`,payment:e}:{kind:`unresolved`,paymentReference:e.paymentReference,reason:e.checkoutStatus===`action_required`?`action_required`:`pending`}}async function V(e,t,n){if(t.checkoutStatus!==`action_required`)return B(t);if(t.clientSecret)try{await n.handleNextAction({clientSecret:t.clientSecret})}catch{}try{return B(await e.getPaymentStatus(t.paymentReference))}catch{return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`}}}async function H(e,t,n){let r;try{r=await e.submitPayment(t)}catch(n){if(!(n instanceof h&&n.recoveryRecommended))throw n;try{r=await e.getPaymentStatus(t.checkout.paymentReference)}catch{return{kind:`unresolved`,paymentReference:t.checkout.paymentReference,reason:`recovery_failed`}}}return V(e,r,n)}const U=w(k(),j(),x()),W=w(S(),E(),b(1)),G=w(_(M([O({amountCents:W,productSlug:U}),O({productSlug:U,quantity:W})])),y(1)),de=w(k(),j(),T(/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/,`Enter a valid tip amount.`),A(e=>Math.round(Number(e)*100)),E(`Enter a valid tip amount.`));function fe(e){let t=D(de,e);return t.success?{cents:t.output,success:!0}:{message:t.issues[0]?.message??`Enter a valid tip amount.`,success:!1}}function K(e){let t=D(G,e);return t.success?{success:!0,value:t.output}:{message:`Lockerverse payment configuration is invalid.`,success:!1}}const q=w(k(),j(),x(`Email is required.`),v(`Enter a valid email address.`)),J=w(k(),j(),x(`Phone is required.`),T(/^\+[1-9]\d{6,14}$/,`Enter a valid phone number.`));function Y(e){return e.trim().replace(/[().\s-]/g,``)}function pe(e,t){let n=t?{...e,phone:Y(e.phone)}:e,r=C(t?{email:q,phone:J}:{email:q}),i=D(r,n);if(i.success)return{errors:{},value:i.output};let a={};for(let e of i.issues){let t=e.path?.[0]?.key;(t===`email`||t===`phone`)&&!a[t]&&(a[t]=e.message)}return{errors:a,value:null}}function me(e,t){let n={};for(let r of e){if(!r.required)continue;let e=`${r.label} is required.`,i=t[r.id],a=r.type===`checkboxes`||r.type===`multi_select`?D(w(_(k()),y(1,e)),i??[]):D(w(k(),j(),x(e)),typeof i==`string`?i:``);a.success||(n[r.id]=a.issues[0]?.message??e)}return n}function he(e,t){switch(t.type){case`loading`:return{configuration:t.configuration,phase:`loading`,revision:e.revision,selectionKey:t.selectionKey};case`ready`:return{catalog:t.catalog,checkoutItems:t.checkoutItems,client:t.client,configuration:t.configuration,phase:`ready`,preparedCheckout:t.preparedCheckout,revision:e.revision+1,selectionKey:t.selectionKey};case`error`:return{configuration:t.configuration,failure:t.failure,phase:`error`,revision:e.revision,selectionKey:t.selectionKey};case`checkout`:return e.phase===`ready`?{...e,preparedCheckout:t.preparedCheckout}:e;default:return e}}function ge(e,t){if(`amountCents`in t){if(e.pricingMode!==`custom`)throw TypeError(`Fixed-price Products do not accept custom amounts.`);if(e.minimumAmountCents!==null&&t.amountCents<e.minimumAmountCents)throw TypeError(`Product amount must be at least ${e.minimumAmountCents} cents.`);return{amountCents:t.amountCents,productId:e.id}}if(e.pricingMode!==`fixed`)throw TypeError(`Custom-amount Products do not accept quantities.`);if(e.minimumQuantity!==null&&t.quantity<e.minimumQuantity)throw TypeError(`Product quantity must be at least ${e.minimumQuantity}.`);if(e.maximumQuantity!==null&&t.quantity>e.maximumQuantity)throw TypeError(`Product quantity must not exceed ${e.maximumQuantity}.`);if(e.inventoryQuantity!==null&&t.quantity>e.inventoryQuantity)throw TypeError(`Requested Product quantity is unavailable.`);return{productId:e.id,quantity:t.quantity}}function X(e,t){if(t.length===0)throw TypeError(`Lockerverse payment requires at least one Product.`);return t.map(t=>{let n=e.products.find(e=>e.slug===t.productSlug);if(!n)throw TypeError(`Product ${t.productSlug} is not available.`);return ge(n,t)})}function Z(e,t){let{apiBaseUrl:n,communitySlug:r,environment:i,fetch:a,requestTimeoutMs:o,sentryDsn:s,widgetSlug:c}=e,l={communitySlug:r,widgetSlug:c,...a?{fetch:a}:{},...t?{onError:t}:{},...o===void 0?{}:{requestTimeoutMs:o},...s===void 0?{}:{sentryDsn:s}};if(n===void 0){if(i===`development`)throw TypeError(`Lockerverse development checkout requires an API base URL.`);return{...l,...i===`production`?{environment:i}:{}}}if(!i)throw TypeError(`Lockerverse development checkout requires an environment.`);return{...l,apiBaseUrl:n,environment:i}}function Q(e,t,n){return e?.configuration===t&&e.selectionKey===n}function _e({apiBaseUrl:e,communitySlug:t,environment:n,fetch:r,onError:i,paymentState:a,requestTimeoutMs:s,selection:d,sentryDsn:f,widgetSlug:p}){let m=c(()=>({apiBaseUrl:e,communitySlug:t,environment:n,fetch:r,requestTimeoutMs:s,sentryDsn:f,widgetSlug:p}),[e,t,n,r,s,f,p]),h=K(d),_=h.success?JSON.stringify(h.value):`invalid-selection`,v=c(()=>h.success?JSON.parse(_):[],[h.success,_]),[y,b]=l(he,{phase:`idle`,revision:0}),x=u(void 0),S=u(void 0),C=u(i);return C.current=i,o(()=>{if(!h.success||a===`submitting`||a===`success`||a===`unresolved`||Q(S.current,m,_)||Q(x.current,m,_))return;let e=!0,t={configuration:m,selectionKey:_};x.current=t,b({configuration:m,selectionKey:_,type:`loading`});async function n(){try{let n=g(Z(m,e=>C.current?.(e))),r=await n.load(),i=X(r,v),a=await n.calculateTotal({...r.widget.fields.serviceFee?{includeServiceFee:!0}:{},items:i});e&&(x.current=void 0,S.current=t,b({catalog:r,checkoutItems:i,client:n,configuration:m,preparedCheckout:a,selectionKey:_,type:`ready`}))}catch(n){e&&(x.current=void 0,S.current=t,b({configuration:m,failure:n instanceof Error?n.message:`Lockerverse payment could not load.`,selectionKey:_,type:`error`}))}}return n(),()=>{e=!1,Q(x.current,m,_)&&(x.current=void 0)}},[m,h.success,a,_,v]),{selectionError:h.success?void 0:h.message,session:y,updateCheckout:e=>b({preparedCheckout:e,type:`checkout`})}}function $(e){return new Intl.NumberFormat(`en-US`,{currency:`USD`,style:`currency`}).format(e/100)}function ve(e,t){return t.tipPercent===`custom`?fe(t.customTip):{cents:Math.round(e*Number(t.tipPercent)/100),success:!0}}const ye=[{callingCode:`+1`,label:`🇺🇸 +1`,value:`US`},{callingCode:`+52`,label:`🇲🇽 +52`,value:`MX`},{callingCode:`+380`,label:`🇺🇦 +380`,value:`UA`},{callingCode:`+48`,label:`🇵🇱 +48`,value:`PL`},{callingCode:`+1`,label:`🇨🇦 +1`,value:`CA`},{callingCode:`+49`,label:`🇩🇪 +49`,value:`DE`},{callingCode:`+44`,label:`🇬🇧 +44`,value:`GB`},{callingCode:`+46`,label:`🇸🇪 +46`,value:`SE`},{callingCode:`+358`,label:`🇫🇮 +358`,value:`FI`},{callingCode:`+1`,label:`🇵🇷 +1`,value:`PR`}];function be(e,t){return e.trim().startsWith(`+`)?e:`${ye.find(e=>e.value===t)?.callingCode??`+1`}${e}`}function xe(e,t){return e.map(e=>{let n=t[e.id];return e.type===`checkboxes`||e.type===`multi_select`?{fieldId:e.id,value:Array.isArray(n)?n:[]}:{fieldId:e.id,value:typeof n==`string`?n:``}})}function Se(e,t,n,r){return{email:n,...e.widget.fields.serviceFee?{includeServiceFee:t.includeServiceFee}:{},...e.widget.fields.promoCode&&t.promoCode.trim()?{promoCode:t.promoCode.trim()}:{},...e.widget.fields.tipping?{tipCents:r}:{}}}async function Ce(e,t){let n=e.getElement(`address`,{mode:t}),r=t===`billing`?`Billing`:`Shipping`;if(!n)throw Error(`${r} address is still loading.`);let i=await n.getValue();if(!i.complete)throw Error(`${r} address is required.`);return i.value}function we(e,t,n,r){if(e.widget.fields.shipping)return n.shippingMatchesBilling?r:Ce(t,`shipping`)}function Te({billingAddress:e,catalog:t,email:n,phone:r,shippingAddress:i}){return{payment_method_data:{billing_details:{address:e.address,email:n,name:e.name,...t.widget.fields.phone?{phone:r}:{}}},...i?{shipping:{address:i.address,name:i.name,phone:t.widget.fields.phone?r:i.phone??null}}:{}}}function Ee({catalog:e,confirmationToken:t,email:n,fieldValues:r,phone:i}){return{confirmationToken:t,customFieldAnswers:xe(e.widget.customFields,r.customFields),email:n,...e.widget.fields.memberId&&r.memberId.trim()?{memberId:r.memberId.trim()}:{},...e.widget.fields.merchSize?{merchSize:r.merchSize}:{},...e.widget.fields.phone?{phone:i}:{}}}async function De({catalog:e,checkoutItems:t,client:n,elements:r,email:i,fieldValues:a,phone:o,quote:s,stripe:c}){let l=i.trim().toLowerCase(),u=Y(o),d=ve(s.subtotalCents,a);if(!d.success)throw Error(d.message);let f=Se(e,a,l,d.cents),p=await n.calculateTotal({...f,items:t});if(await r.update({amount:p.totalCents}),z(s,p))return{kind:`quote_changed`,quote:p};let m=await r.submit();if(m.error)throw Error(m.error.message);let h=await Ce(r,`billing`),g=await we(e,r,a,h),_=await c.createConfirmationToken({elements:r,params:Te({billingAddress:h,catalog:e,email:l,phone:u,shippingAddress:g})});if(_.error)throw Error(_.error.message);let v=await H(n,{checkout:p,submission:Ee({catalog:e,confirmationToken:_.confirmationToken.id,email:l,fieldValues:a,phone:u})},c);return v.kind===`failed`?{kind:`payment_failed`,message:`Payment was declined. Check your payment details and try again.`}:v.kind===`unresolved`?{kind:`payment_unresolved`,paymentReference:v.paymentReference,reason:v.reason}:{kind:`payment`,payment:v.payment,quote:p}}function Oe({accentColor:e,catalog:n,checkoutItems:r,client:i,onPaymentComplete:a,onPaymentUncertain:o,onQuoteChange:s,quote:l,onStateChange:u,stripeLoader:d,theme:f}){let m=c(()=>d(n.payment.publishableKey,l.payment.connectedAccountId?{stripeAccount:l.payment.connectedAccountId}:void 0),[n.payment.publishableKey,l.payment.connectedAccountId,d]);return p(t,{options:{amount:l.totalCents,appearance:{rules:{".Input:focus":{borderColor:e,boxShadow:`none`,outline:`none`}},theme:f===`light`?`stripe`:`night`,variables:{borderRadius:`8px`,colorBackground:f===`light`?`#f5f6f7`:`#101010`,colorDanger:f===`light`?`#c52b3e`:`#ef4444`,colorPrimary:e,colorText:f===`light`?`#121416`:`#ffffff`,colorTextPlaceholder:f===`light`?`#72767d`:`#6b6b6b`,colorTextSecondary:f===`light`?`#62666d`:`#a1a1aa`,focusBoxShadow:`none`,focusOutline:`none`,fontFamily:`Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif`,fontSizeBase:`16px`}},currency:l.payment.currency,excludedPaymentMethodTypes:[`us_bank_account`],mode:`payment`,syncAddressCheckbox:`none`},stripe:m,children:p(Ie,{catalog:n,checkoutItems:r,client:i,onPaymentComplete:a,onPaymentUncertain:o,onQuoteChange:s,onStateChange:u,quote:l})},`${n.payment.publishableKey}:${l.payment.connectedAccountId??`platform`}`)}function ke({label:e}){return m(`div`,{className:`lockerverse-payment__stripe-loader`,role:`status`,children:[p(`p`,{children:e}),m(`div`,{"aria-hidden":`true`,children:[p(`span`,{}),p(`span`,{}),p(`span`,{})]})]})}function Ae({onError:e,onReady:t,ready:r}){return m(`div`,{className:`lockerverse-payment__stripe-element`,"data-ready":r,children:[r?null:p(ke,{label:`Loading payment form...`}),p(n,{onLoadError:({error:t})=>e(t.message??`Payment form failed to load.`),onReady:t,options:{business:{name:`Lockerverse`},fields:{billingDetails:{email:`auto`}},layout:`tabs`,terms:{applePay:`auto`,auBecsDebit:`never`,bancontact:`never`,card:`always`,cashapp:`never`,googlePay:`never`,ideal:`never`,paypal:`auto`,sepaDebit:`never`,sofort:`never`,usBankAccount:`never`},wallets:{applePay:`auto`,googlePay:`never`}}})]})}function je({label:t,mode:n,onError:r,onReady:i,ready:a}){return m(`div`,{className:`lockerverse-payment__address`,children:[p(`h2`,{children:t}),m(`div`,{className:`lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address`,"data-ready":a,children:[a?null:p(ke,{label:`Loading ${t.toLowerCase()}...`}),p(e,{onLoadError:({error:e})=>r(e.message??`${t} failed to load.`),onReady:i,options:{autocomplete:{mode:`automatic`},mode:n}})]})]})}function Me({message:e}){return e?p(`p`,{className:`lockerverse-payment__field-message`,role:`alert`,children:e}):null}function Ne({customFieldErrors:e,emailRef:t,form:n,parsedTipSuccess:r,phoneRef:i,validationErrors:a}){if(a.email){t.current?.focus();return}if(a.phone){i.current?.focus();return}if(!r){n.querySelector(`[name="tip"]`)?.focus();return}let[o]=Object.keys(e);o&&n.querySelector(`[name="custom:${o}"]`)?.focus()}function Pe({onPaymentComplete:e,onPaymentUncertain:t,onQuoteChange:n,onStateChange:r,result:i,setDisplayedTotalCents:a,setPaymentError:o,setTerminalState:s}){if(i.kind===`quote_changed`){let e=`The total changed to ${$(i.quote.totalCents)}. Review it and pay again.`;n(i.quote,e),a(i.quote.totalCents),r(`idle`);return}if(i.kind===`payment_failed`){o(i.message),r(`error`);return}if(i.kind===`payment_unresolved`){s({kind:`unresolved`,message:`Payment is still processing. Do not submit it again.`}),r(`unresolved`);try{t?.({paymentReference:i.paymentReference,reason:i.reason})}catch{}return}n(i.quote),s({kind:`success`,message:`Payment completed successfully.`}),r(`success`);try{e?.(i.payment)}catch{}}function Fe({email:e,emailErrorId:t,emailId:n,emailRef:r,errors:i,onEmailChange:a,onPhoneChange:o,onPhoneCountryChange:s,phone:c,phoneCountry:l,phoneEnabled:u,phoneErrorId:d,phoneId:h,phoneRef:g}){return m(`div`,{className:`lockerverse-payment__contact`,children:[p(`label`,{htmlFor:n,children:`Email`}),p(`input`,{"aria-describedby":i.email?t:void 0,"aria-invalid":i.email?`true`:void 0,autoComplete:`email`,id:n,name:`email`,onChange:e=>a(e.currentTarget.value),placeholder:`name@example.com`,ref:r,type:`email`,value:e}),i.email?p(`p`,{className:`lockerverse-payment__field-message`,id:t,children:i.email}):null,u?m(f,{children:[p(`label`,{htmlFor:h,children:`Phone`}),m(`div`,{className:`lockerverse-payment__phone-control`,children:[p(`select`,{"aria-label":`Phone number country`,name:`phoneCountry`,onChange:e=>s(e.currentTarget.value),value:l,children:ye.map(e=>p(`option`,{value:e.value,children:e.label},e.value))}),p(`input`,{"aria-describedby":i.phone?d:void 0,"aria-invalid":i.phone?`true`:void 0,autoComplete:`tel`,id:h,inputMode:`tel`,name:`phone`,onChange:e=>o(e.currentTarget.value),placeholder:`(201) 555-0123`,ref:g,type:`tel`,value:c})]}),i.phone?p(`p`,{className:`lockerverse-payment__field-message`,id:d,children:i.phone}):null]}):null]})}function Ie({catalog:e,checkoutItems:t,client:n,onPaymentComplete:a,onPaymentUncertain:c,onQuoteChange:l,onStateChange:f,quote:h}){let[g,_]=d(``),[v,y]=d(``),[b,x]=d(`US`),[S,C]=d({}),[w,T]=d(),[E,D]=d({}),[O,k]=d(),[A,j]=d(!1),[M,N]=d(),[P,ee]=d(!1),[te,ne]=d(!1),[F,se]=d(!1),[I,ce]=d({customFields:{},customTip:``,includeServiceFee:e.widget.fields.serviceFee,memberId:``,merchSize:`M`,promoCode:``,shippingMatchesBilling:!0,tipPercent:`10`}),[le,ue]=d(h.totalCents),L=u(null),R=u(null),z=u(null),B=r(),V=i(),H=`lockerverse-${s()}`,U=`${H}-email`,W=`${U}-error`,G=`${H}-phone`,de=`${G}-error`,fe=`${H}-tip-error`,K=e.widget.fields.tipping?ve(h.subtotalCents,I):{cents:0,success:!0},q=K.success?K.cents:null,J=q??0,Y=le-J,he=!e.widget.fields.shipping||I.shippingMatchesBilling||F;o(()=>{if(q===null)return;let t=e.widget.fields.serviceFee&&I.includeServiceFee?h.serviceFeeCents||Math.round(h.subtotalCents*e.pricingPolicy.serviceFeeRateBasisPoints/1e4):0,n=h.totalCents-h.serviceFeeCents-h.tipCents+t+q;ue(n),B?.update({amount:n})},[e.widget.fields.serviceFee,e.widget.fields.tipping,B,I.includeServiceFee,I.tipPercent,I.customTip,q,h.serviceFeeCents,h.tipCents,h.totalCents]),o(()=>{A&&z.current?.focus()},[A]);function ge(e){C(t=>{let n={...t};return delete n[e],n})}function X(e){ce(e),D({}),k(void 0)}function Z(e){T(e),f(`error`)}async function Q(r){r.preventDefault();let i=pe({email:g,phone:be(v,b)},e.widget.fields.phone),o=me(e.widget.customFields,I.customFields);if(!(i.value&&K.success)||Object.keys(o).length>0){C(i.errors),D(o),k(K.success?void 0:K.message),f(`invalid`);let e=r.currentTarget;queueMicrotask(()=>{Ne({customFieldErrors:o,emailRef:L,form:e,parsedTipSuccess:K.success,phoneRef:R,validationErrors:i.errors})});return}if(C({}),D({}),!(B&&V)){T(`Payment form is still loading.`),f(`error`);return}T(void 0),j(!0),f(`submitting`);try{Pe({onPaymentComplete:a,onPaymentUncertain:c,onQuoteChange:l,onStateChange:f,result:await De({catalog:e,checkoutItems:t,client:n,elements:B,email:g,fieldValues:I,phone:be(v,b),quote:h,stripe:V}),setDisplayedTotalCents:ue,setPaymentError:T,setTerminalState:N})}catch(e){T(e instanceof Error?e.message:`Payment could not be completed.`),f(`error`)}finally{j(!1)}}return M?p(`p`,{className:`lockerverse-payment__payment-status`,ref:z,role:`status`,tabIndex:-1,children:M.message}):m(`form`,{"aria-busy":A,className:`lockerverse-payment__form`,noValidate:!0,onSubmit:Q,children:[p(`div`,{"data-lockerverse-input-region":``,inert:A?!0:void 0,children:m(`fieldset`,{className:`lockerverse-payment__input-fieldset`,disabled:A,children:[p(re,{enabled:e.widget.fields.tipping,error:O,errorId:fe,onChange:X,values:I}),p(Fe,{email:g,emailErrorId:W,emailId:U,emailRef:L,errors:S,onEmailChange:e=>{_(e),ge(`email`)},onPhoneChange:e=>{y(e),ge(`phone`)},onPhoneCountryChange:x,phone:v,phoneCountry:b,phoneEnabled:e.widget.fields.phone,phoneErrorId:de,phoneId:G,phoneRef:R}),p(Ae,{onError:Z,onReady:()=>ee(!0),ready:P}),p(je,{label:`Billing address`,mode:`billing`,onError:Z,onReady:()=>ne(!0),ready:te}),e.widget.fields.shipping?m(`div`,{className:`lockerverse-payment__shipping`,children:[p(ie,{checked:I.shippingMatchesBilling,name:`shippingMatchesBilling`,onChange:e=>{X({...I,shippingMatchesBilling:e}),e||se(!1)},children:`Shipping is same as billing information`}),I.shippingMatchesBilling?null:p(je,{label:`Shipping address`,mode:`shipping`,onError:Z,onReady:()=>se(!0),ready:F})]}):null,p(ae,{customFields:e.widget.customFields,errors:E,fields:e.widget.fields,idPrefix:H,onChange:X,values:I}),m(`div`,{className:`lockerverse-payment__actions`,children:[p(oe,{amountCents:h.serviceFeeCents||Math.round(h.subtotalCents*e.pricingPolicy.serviceFeeRateBasisPoints/1e4),enabled:e.widget.fields.serviceFee,onChange:X,values:I}),p(`button`,{"aria-busy":A,"aria-label":`Process payment for ${$(le)} total`,disabled:A||!(P&&te&&he),type:`submit`,children:A?`Processing…`:`Process Payment (${$(Y)})${J>0?` + ${$(J)} tip`:``}`})]})]})}),A?p(`p`,{className:`lockerverse-payment__payment-status`,ref:z,role:`status`,tabIndex:-1,children:`Processing payment…`}):null,p(Me,{message:w})]})}function Le(){return m(`div`,{className:`lockerverse-payment__skeleton-loader-block`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-label`}),m(`div`,{className:`lockerverse-payment__skeleton-loader-content`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-full`}),m(`div`,{className:`lockerverse-payment__skeleton-loader-grid`,children:[p(`span`,{className:`lockerverse-payment__skeleton-loader-half`}),p(`span`,{className:`lockerverse-payment__skeleton-loader-half`})]})]})]})}function Re(){return m(`div`,{className:`lockerverse-payment__loading`,children:[p(`span`,{"aria-live":`polite`,className:`lockerverse-payment__sr-only`,role:`status`,children:`Loading payment…`}),m(`div`,{"aria-hidden":`true`,className:`lockerverse-payment__skeleton`,children:[m(`div`,{className:`lockerverse-payment__skeleton-branding`,children:[p(`span`,{className:`lockerverse-payment__skeleton-avatar`}),p(`span`,{className:`lockerverse-payment__skeleton-community`})]}),m(`div`,{className:`lockerverse-payment__skeleton-contact`,children:[m(`div`,{className:`lockerverse-payment__skeleton-field`,children:[p(`span`,{className:`lockerverse-payment__skeleton-label`}),p(`span`,{className:`lockerverse-payment__skeleton-input`})]}),m(`div`,{className:`lockerverse-payment__skeleton-field`,children:[p(`span`,{className:`lockerverse-payment__skeleton-label`}),p(`span`,{className:`lockerverse-payment__skeleton-input`})]})]}),p(Le,{}),p(Le,{}),m(`div`,{className:`lockerverse-payment__skeleton-actions`,children:[p(`span`,{className:`lockerverse-payment__skeleton-check-line`}),p(`span`,{className:`lockerverse-payment__skeleton-button`})]})]})]})}function ze({apiBaseUrl:e,branding:t,className:n,communitySlug:r,environment:i,fetch:s,onError:c,onPaymentComplete:l,onPaymentUncertain:u,requestTimeoutMs:f,selection:h,sentryDsn:g,style:_,stripeLoader:v=a,theme:y=`dark`,widgetSlug:b,...x}){let[S,C]=d(),[w,T]=d(`idle`),{selectionError:E,session:D,updateCheckout:O}=_e({apiBaseUrl:e,communitySlug:r,environment:i,fetch:s,onError:c,paymentState:w,requestTimeoutMs:f,selection:h,sentryDsn:g,widgetSlug:b});o(()=>{D.phase===`loading`&&C(void 0)},[D.phase]),o(()=>{D.phase===`ready`&&T(e=>e===`success`||e===`unresolved`?e:`idle`)},[D.phase,D.revision]);let k=[`lockerverse-payment`,n].filter(Boolean).join(` `),A=te(_?.[`--lockerverse-accent`]??t?.accentColor??`#38d77a`),j={..._,...t?.accentColor&&_?.[`--lockerverse-accent`]===void 0?{"--lockerverse-accent":t.accentColor}:{},...A&&_?.[`--lockerverse-accent-contrast`]===void 0?{"--lockerverse-accent-contrast":A}:{}};if(E)return p(`section`,{...x,className:k,"data-lockerverse-theme":y,role:`alert`,style:j,children:E});if(D.phase===`error`)return p(`section`,{...x,className:k,"data-lockerverse-theme":y,role:`alert`,children:D.failure});if(D.phase!==`ready`)return p(`section`,{...x,"aria-busy":`true`,"aria-label":`Payment`,className:k,"data-lockerverse-theme":y,children:p(Re,{})});let{catalog:M,checkoutItems:N,client:P,preparedCheckout:ee}=D;return m(`section`,{...x,"aria-label":`Payment`,className:k,"data-lockerverse-theme":y,"data-payment-state":w,style:j,children:[m(`header`,{children:[M.widget.showCommunityBranding&&t?m(`div`,{className:`lockerverse-payment__branding`,children:[t.imageUrl?p(`img`,{alt:t.name,height:`48`,src:t.imageUrl,width:`48`}):null,p(`strong`,{children:t.name})]}):null,p(`h1`,{children:M.widget.title??M.widget.name}),M.widget.description?p(`p`,{children:M.widget.description}):null]}),S?p(`p`,{className:`lockerverse-payment__payment-status`,role:`status`,children:S}):null,p(Oe,{accentColor:_?.[`--lockerverse-accent`]??t?.accentColor??`#38d77a`,catalog:M,checkoutItems:N,client:P,onPaymentComplete:l,onPaymentUncertain:u,onQuoteChange:(e,t)=>{C(t),O(e)},onStateChange:T,quote:ee,stripeLoader:v,theme:y})]})}export{ze as LockerversePayment};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["formatMoney"],"sources":["../src/accent-contrast.ts","../src/checkout-fields.tsx","../src/payment-attempt.ts","../src/payment-input.ts","../src/payment-validation.ts","../src/lockerverse-payment.tsx"],"sourcesContent":["const HEX_COLOR = /^#([\\da-f]{3}|[\\da-f]{6})$/i;\n\nfunction parseHexColor(color: string) {\n const match = HEX_COLOR.exec(color.trim());\n if (!match) {\n return;\n }\n const [, value] = match;\n if (!value) {\n return;\n }\n const expanded =\n value.length === 3\n ? Array.from(value, (character) => `${character}${character}`).join(\"\")\n : value;\n return [0, 2, 4].map((offset) =>\n Number.parseInt(expanded.slice(offset, offset + 2), 16)\n );\n}\n\nfunction relativeLuminance([red, green, blue]: number[]) {\n const [linearRed = 0, linearGreen = 0, linearBlue = 0] = [\n red,\n green,\n blue,\n ].map((channel = 0) => {\n const normalized = channel / 255;\n return normalized <= 0.040_45\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * linearRed + 0.7152 * linearGreen + 0.0722 * linearBlue;\n}\n\nexport function getAccentContrast(color: string) {\n const parsed = parseHexColor(color);\n if (!parsed) {\n return;\n }\n const luminance = relativeLuminance(parsed);\n const blackContrast = (luminance + 0.05) / 0.05;\n const whiteContrast = 1.05 / (luminance + 0.05);\n return blackContrast >= whiteContrast ? \"#000\" : \"#fff\";\n}\n","import type {\n LockerverseCustomField,\n LockerverseMultiOptionCustomField,\n LockerverseSingleOptionCustomField,\n LockerverseWidgetFields,\n} from \"@lockerverse/sdk/checkout\";\n\nexport const MERCH_SIZES = [\"XS\", \"S\", \"M\", \"L\", \"XL\", \"XXL\", \"XXXL\"] as const;\n\nexport type CheckoutFieldValues = {\n customTip: string;\n customFields: Record<string, string | string[]>;\n includeServiceFee: boolean;\n memberId: string;\n merchSize: (typeof MERCH_SIZES)[number];\n promoCode: string;\n shippingMatchesBilling: boolean;\n tipPercent: \"5\" | \"10\" | \"12\" | \"15\" | \"custom\";\n};\n\nconst TIP_OPTIONS = [\"15\", \"12\", \"10\", \"5\"] as const;\n\nexport function TipField({\n enabled,\n error,\n errorId,\n onChange,\n values,\n}: {\n enabled: boolean;\n error: string | undefined;\n errorId: string;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n if (!enabled) {\n return null;\n }\n const update = (next: Partial<CheckoutFieldValues>) =>\n onChange({ ...values, ...next });\n return (\n <div className=\"lockerverse-payment__tip-box\">\n <p>Add a tip to support the Lockerverse platform</p>\n <div aria-label=\"Tip amount\" role=\"radiogroup\">\n {TIP_OPTIONS.map((tip) => (\n <button\n aria-pressed={values.tipPercent === tip}\n key={tip}\n onClick={() => update({ tipPercent: tip })}\n type=\"button\"\n >\n {tip}%\n </button>\n ))}\n <button\n aria-pressed={values.tipPercent === \"custom\"}\n onClick={() => update({ tipPercent: \"custom\" })}\n type=\"button\"\n >\n Other\n </button>\n </div>\n {values.tipPercent === \"custom\" ? (\n <label>\n <span>Custom tip</span>\n <span className=\"lockerverse-payment__money-input\">\n <span aria-hidden=\"true\">$</span>\n <input\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n inputMode=\"decimal\"\n name=\"tip\"\n onChange={(event) =>\n update({ customTip: event.currentTarget.value })\n }\n placeholder=\"0.00\"\n value={values.customTip}\n />\n </span>\n {error ? (\n <span className=\"lockerverse-payment__field-message\" id={errorId}>\n {error}\n </span>\n ) : null}\n </label>\n ) : (\n <input name=\"tip\" type=\"hidden\" value={values.tipPercent} />\n )}\n </div>\n );\n}\n\nexport function CheckoutToggle({\n checked,\n children,\n name,\n onChange,\n}: {\n checked: boolean;\n children: React.ReactNode;\n name: string;\n onChange: (checked: boolean) => void;\n}) {\n return (\n <label className=\"lockerverse-payment__check-row\">\n <input\n checked={checked}\n name={name}\n onChange={(event) => onChange(event.currentTarget.checked)}\n type=\"checkbox\"\n />\n <span>{children}</span>\n </label>\n );\n}\n\nexport function AdditionalCheckoutFields({\n customFields,\n errors,\n fields,\n idPrefix,\n onChange,\n values,\n}: {\n customFields: LockerverseCustomField[];\n errors: Record<string, string>;\n fields: LockerverseWidgetFields;\n idPrefix: string;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n const update = (next: Partial<CheckoutFieldValues>) =>\n onChange({ ...values, ...next });\n\n return (\n <div className=\"lockerverse-payment__additional-fields\">\n {fields.memberId ? (\n <label>\n <span>Member ID</span>\n <input\n name=\"memberId\"\n onChange={(event) =>\n update({ memberId: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.memberId}\n />\n </label>\n ) : null}\n {fields.merchSize ? (\n <label>\n <span>Size</span>\n <select\n name=\"merchSize\"\n onChange={(event) =>\n update({\n merchSize: event.currentTarget\n .value as CheckoutFieldValues[\"merchSize\"],\n })\n }\n value={values.merchSize}\n >\n {MERCH_SIZES.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n ) : null}\n {fields.promoCode ? (\n <label>\n <span>Promo code</span>\n <input\n name=\"promoCode\"\n onChange={(event) =>\n update({ promoCode: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.promoCode}\n />\n </label>\n ) : null}\n {customFields.map((field) => (\n <CustomField\n error={errors[field.id]}\n field={field}\n idPrefix={idPrefix}\n key={field.id}\n onChange={(value) =>\n update({\n customFields: { ...values.customFields, [field.id]: value },\n })\n }\n value={values.customFields[field.id]}\n />\n ))}\n </div>\n );\n}\n\nexport function ServiceFeeField({\n amountCents,\n enabled,\n onChange,\n values,\n}: {\n amountCents: number;\n enabled: boolean;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n if (!enabled) {\n return null;\n }\n return (\n <CheckoutToggle\n checked={values.includeServiceFee}\n name=\"includeServiceFee\"\n onChange={(includeServiceFee) =>\n onChange({ ...values, includeServiceFee })\n }\n >\n Add {formatMoney(amountCents)} to help cover processing fees\n </CheckoutToggle>\n );\n}\n\nfunction CustomField({\n error,\n field,\n idPrefix,\n onChange,\n value,\n}: {\n error: string | undefined;\n field: LockerverseCustomField;\n idPrefix: string;\n onChange: (value: string | string[]) => void;\n value: string | string[] | undefined;\n}) {\n const name = `custom:${field.id}`;\n const controlId = `${idPrefix}-custom-${field.id}`;\n const errorId = `${controlId}-error`;\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n return (\n <TextCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n case \"select\":\n case \"multi_select\":\n return (\n <SelectCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n case \"radio\":\n case \"checkboxes\":\n return (\n <ChoiceCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n default:\n return null;\n }\n}\n\ntype CustomFieldControlProps = {\n controlId: string;\n error: string | undefined;\n errorId: string;\n name: string;\n onChange: (value: string | string[]) => void;\n value: string | string[] | undefined;\n};\n\nfunction FieldError({ error, id }: { error: string | undefined; id: string }) {\n if (!error) {\n return null;\n }\n return (\n <p className=\"lockerverse-payment__field-message\" id={id}>\n {error}\n </p>\n );\n}\n\nfunction TextCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: Extract<LockerverseCustomField, { type: \"text\" | \"textarea\" }>;\n}) {\n const commonProps = {\n \"aria-describedby\": error ? errorId : undefined,\n \"aria-invalid\": error ? (\"true\" as const) : undefined,\n id: controlId,\n name,\n onChange: (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => onChange(event.currentTarget.value),\n required: field.required,\n value: typeof value === \"string\" ? value : \"\",\n };\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n {field.type === \"textarea\" ? (\n <textarea {...commonProps} />\n ) : (\n <input {...commonProps} />\n )}\n <FieldError error={error} id={errorId} />\n </label>\n );\n}\n\nfunction SelectCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n <select\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n id={controlId}\n multiple={field.type === \"multi_select\"}\n name={name}\n onChange={(event) =>\n onChange(\n field.type === \"multi_select\"\n ? [...event.currentTarget.selectedOptions].map(\n (option) => option.value\n )\n : event.currentTarget.value\n )\n }\n required={field.required}\n value={value ?? (field.type === \"multi_select\" ? [] : \"\")}\n >\n {field.type === \"select\" ? <option value=\"\">Select…</option> : null}\n {field.options.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldError error={error} id={errorId} />\n </label>\n );\n}\n\nfunction ChoiceCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <fieldset\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n >\n <legend>{field.label}</legend>\n {field.options.map((option, index) => {\n const selected = Array.isArray(value)\n ? value.includes(option.id)\n : value === option.id;\n return (\n <label className=\"lockerverse-payment__check-row\" key={option.id}>\n <input\n checked={selected}\n id={`${controlId}-${index}`}\n name={name}\n onChange={(event) => {\n if (field.type === \"radio\") {\n onChange(option.id);\n return;\n }\n const selectedValues = Array.isArray(value) ? value : [];\n onChange(\n event.currentTarget.checked\n ? [...selectedValues, option.id]\n : selectedValues.filter((id) => id !== option.id)\n );\n }}\n required={field.required}\n type={field.type === \"radio\" ? \"radio\" : \"checkbox\"}\n value={option.id}\n />\n <span>{option.label}</span>\n </label>\n );\n })}\n <FieldError error={error} id={errorId} />\n </fieldset>\n );\n}\n\nfunction formatMoney(amountCents: number) {\n return new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amountCents / 100);\n}\n","import type {\n LockerverseCheckoutQuote,\n LockerversePaymentResult,\n LockerversePaymentSubmission,\n LockerverseWidget,\n} from \"@lockerverse/sdk/checkout\";\nimport type { Stripe } from \"@stripe/stripe-js\";\n\nconst AMOUNT_KEYS = [\n \"amountCents\",\n \"discountableSubtotalCents\",\n \"discountCents\",\n \"serviceFeeCents\",\n \"subtotalCents\",\n \"tipCents\",\n \"totalCents\",\n] as const satisfies readonly (keyof LockerverseCheckoutQuote)[];\n\nexport function hasMaterialQuoteChange(\n displayed: LockerverseCheckoutQuote,\n current: LockerverseCheckoutQuote\n) {\n return (\n AMOUNT_KEYS.some((key) => displayed[key] !== current[key]) ||\n displayed.payment.connectedAccountId !==\n current.payment.connectedAccountId ||\n displayed.payment.currency !== current.payment.currency ||\n JSON.stringify(displayed.appliedDiscount) !==\n JSON.stringify(current.appliedDiscount) ||\n JSON.stringify(displayed.lineItems) !== JSON.stringify(current.lineItems)\n );\n}\n\nexport type PaymentAttemptOutcome =\n | { kind: \"failed\"; payment: LockerversePaymentResult }\n | { kind: \"success\"; payment: LockerversePaymentResult }\n | {\n kind: \"unresolved\";\n paymentReference: string;\n reason: \"action_required\" | \"pending\" | \"recovery_failed\";\n };\n\nfunction classifyPayment(\n payment: LockerversePaymentResult\n): PaymentAttemptOutcome {\n if (payment.checkoutStatus === \"success\") {\n return { kind: \"success\", payment };\n }\n if (payment.checkoutStatus === \"failed\") {\n return { kind: \"failed\", payment };\n }\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason:\n payment.checkoutStatus === \"action_required\"\n ? \"action_required\"\n : \"pending\",\n };\n}\n\nasync function settleRequiredAction(\n checkout: LockerverseWidget,\n payment: LockerversePaymentResult,\n stripe: Stripe\n): Promise<PaymentAttemptOutcome> {\n if (payment.checkoutStatus !== \"action_required\") {\n return classifyPayment(payment);\n }\n if (payment.clientSecret) {\n try {\n await stripe.handleNextAction({ clientSecret: payment.clientSecret });\n } catch {\n // Status recovery below is authoritative even when Stripe UI fails.\n }\n }\n try {\n const recovered = await checkout.getPaymentStatus(payment.paymentReference);\n return classifyPayment(recovered);\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason: \"action_required\",\n };\n }\n}\n\nexport async function submitPaymentAttempt(\n checkout: LockerverseWidget,\n submission: LockerversePaymentSubmission,\n stripe: Stripe\n): Promise<PaymentAttemptOutcome> {\n let payment: LockerversePaymentResult;\n try {\n payment = await checkout.submitPayment(submission);\n } catch (error) {\n const state = checkout.getState();\n if (state.phase !== \"error\" || !state.recoverablePaymentReference) {\n throw error;\n }\n try {\n payment = await checkout.getPaymentStatus(\n state.recoverablePaymentReference\n );\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference: state.recoverablePaymentReference,\n reason: \"recovery_failed\",\n };\n }\n }\n return settleRequiredAction(checkout, payment, stripe);\n}\n","import {\n array,\n minLength,\n minValue,\n nonEmpty,\n number,\n pipe,\n regex,\n safeInteger,\n safeParse,\n strictObject,\n string,\n transform,\n trim,\n union,\n} from \"valibot\";\n\nconst productSlugSchema = pipe(string(), trim(), nonEmpty());\nconst positiveSafeIntegerSchema = pipe(number(), safeInteger(), minValue(1));\n\nconst paymentSelectionSchema = pipe(\n array(\n union([\n strictObject({\n amountCents: positiveSafeIntegerSchema,\n productSlug: productSlugSchema,\n }),\n strictObject({\n productSlug: productSlugSchema,\n quantity: positiveSafeIntegerSchema,\n }),\n ])\n ),\n minLength(1)\n);\n\nconst customTipSchema = pipe(\n string(),\n trim(),\n regex(/^(?:0|[1-9]\\d*)(?:\\.\\d{1,2})?$/, \"Enter a valid tip amount.\"),\n transform((value) => Math.round(Number(value) * 100)),\n safeInteger(\"Enter a valid tip amount.\")\n);\n\nexport function parseCustomTipCents(input: string) {\n const result = safeParse(customTipSchema, input);\n return result.success\n ? ({ cents: result.output, success: true } as const)\n : ({\n message: result.issues[0]?.message ?? \"Enter a valid tip amount.\",\n success: false,\n } as const);\n}\n\nexport function parsePaymentSelection(input: unknown) {\n const result = safeParse(paymentSelectionSchema, input);\n return result.success\n ? ({ success: true, value: result.output } as const)\n : ({\n message: \"Lockerverse payment configuration is invalid.\",\n success: false,\n } as const);\n}\n","import type { LockerverseCustomField } from \"@lockerverse/sdk/checkout\";\nimport {\n array,\n email,\n minLength,\n nonEmpty,\n object,\n pipe,\n regex,\n safeParse,\n string,\n trim,\n} from \"valibot\";\n\nconst emailSchema = pipe(\n string(),\n trim(),\n nonEmpty(\"Email is required.\"),\n email(\"Enter a valid email address.\")\n);\n\nconst phoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(\"Phone is required.\"),\n regex(/^\\+[1-9]\\d{6,14}$/, \"Enter a valid phone number.\")\n);\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport type ContactErrors = {\n email?: string;\n phone?: string;\n};\n\nexport function validateContact(\n input: { email: string; phone: string },\n requiresPhone: boolean\n) {\n const normalizedInput = requiresPhone\n ? { ...input, phone: normalizePhone(input.phone) }\n : input;\n const schema = requiresPhone\n ? object({ email: emailSchema, phone: phoneSchema })\n : object({ email: emailSchema });\n const result = safeParse(schema, normalizedInput);\n\n if (result.success) {\n return { errors: {} as ContactErrors, value: result.output } as const;\n }\n\n const errors: ContactErrors = {};\n for (const issue of result.issues) {\n const field = issue.path?.[0]?.key;\n if ((field === \"email\" || field === \"phone\") && !errors[field]) {\n errors[field] = issue.message;\n }\n }\n return { errors, value: null } as const;\n}\n\nexport function validateCustomFields(\n fields: LockerverseCustomField[],\n values: Record<string, string | string[]>\n) {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (!field.required) {\n continue;\n }\n const message = `${field.label} is required.`;\n const value = values[field.id];\n const result =\n field.type === \"checkboxes\" || field.type === \"multi_select\"\n ? safeParse(pipe(array(string()), minLength(1, message)), value ?? [])\n : safeParse(\n pipe(string(), trim(), nonEmpty(message)),\n typeof value === \"string\" ? value : \"\"\n );\n if (!result.success) {\n errors[field.id] = result.issues[0]?.message ?? message;\n }\n }\n return errors;\n}\n","import type {\n CreateLockerverseWidgetOptions,\n LockerverseCatalog,\n LockerverseCheckoutQuote,\n LockerverseCustomField,\n LockerverseCustomFieldAnswer,\n LockerverseWidget,\n} from \"@lockerverse/sdk/checkout\";\nimport { createLockerverseCheckout } from \"@lockerverse/sdk/checkout\";\nimport {\n AddressElement,\n Elements,\n PaymentElement,\n useElements,\n useStripe,\n} from \"@stripe/react-stripe-js\";\nimport type { Stripe, StripeElements } from \"@stripe/stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { getAccentContrast } from \"./accent-contrast.ts\";\nimport {\n AdditionalCheckoutFields,\n type CheckoutFieldValues,\n CheckoutToggle,\n ServiceFeeField,\n TipField,\n} from \"./checkout-fields.tsx\";\nimport {\n hasMaterialQuoteChange,\n submitPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport { parseCustomTipCents, parsePaymentSelection } from \"./payment-input.ts\";\nimport {\n normalizePhone,\n validateContact,\n validateCustomFields,\n} from \"./payment-validation.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\nfunction applySelection(\n checkout: LockerverseWidget,\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n) {\n if (selection.length === 0) {\n throw new TypeError(\"Lockerverse payment requires at least one Product.\");\n }\n for (const item of selection) {\n const product = catalog.products.find(\n (candidate) => candidate.slug === item.productSlug\n );\n if (!product) {\n throw new TypeError(`Product ${item.productSlug} is not available.`);\n }\n if (\"amountCents\" in item) {\n checkout.setAmount(product.slug, item.amountCents);\n } else {\n checkout.setQuantity(product.slug, item.quantity);\n }\n }\n}\n\nfunction formatMoney(amountCents: number) {\n return new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amountCents / 100);\n}\n\nfunction getTipCents(\n subtotalCents: number,\n values: Pick<CheckoutFieldValues, \"customTip\" | \"tipPercent\">\n) {\n if (values.tipPercent === \"custom\") {\n return parseCustomTipCents(values.customTip);\n }\n return {\n cents: Math.round((subtotalCents * Number(values.tipPercent)) / 100),\n success: true,\n } as const;\n}\n\nconst PHONE_COUNTRIES = [\n { callingCode: \"+1\", label: \"🇺🇸 +1\", value: \"US\" },\n { callingCode: \"+52\", label: \"🇲🇽 +52\", value: \"MX\" },\n { callingCode: \"+380\", label: \"🇺🇦 +380\", value: \"UA\" },\n { callingCode: \"+48\", label: \"🇵🇱 +48\", value: \"PL\" },\n { callingCode: \"+1\", label: \"🇨🇦 +1\", value: \"CA\" },\n { callingCode: \"+49\", label: \"🇩🇪 +49\", value: \"DE\" },\n { callingCode: \"+44\", label: \"🇬🇧 +44\", value: \"GB\" },\n { callingCode: \"+46\", label: \"🇸🇪 +46\", value: \"SE\" },\n { callingCode: \"+358\", label: \"🇫🇮 +358\", value: \"FI\" },\n { callingCode: \"+1\", label: \"🇵🇷 +1\", value: \"PR\" },\n] as const;\n\nfunction getInternationalPhone(phone: string, country: string) {\n if (phone.trim().startsWith(\"+\")) {\n return phone;\n }\n const callingCode =\n PHONE_COUNTRIES.find((option) => option.value === country)?.callingCode ??\n \"+1\";\n return `${callingCode}${phone}`;\n}\n\nfunction buildCustomFieldAnswers(\n fields: LockerverseCustomField[],\n values: Record<string, string | string[]>\n): LockerverseCustomFieldAnswer[] {\n return fields.map((field): LockerverseCustomFieldAnswer => {\n const value = values[field.id];\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return { fieldId: field.id, value: Array.isArray(value) ? value : [] };\n }\n return {\n fieldId: field.id,\n value: typeof value === \"string\" ? value : \"\",\n };\n });\n}\n\nfunction buildQuoteRequest(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n email: string,\n tipCents: number\n) {\n return {\n email,\n ...(catalog.widget.fields.serviceFee\n ? { includeServiceFee: fieldValues.includeServiceFee }\n : {}),\n ...(catalog.widget.fields.promoCode && fieldValues.promoCode.trim()\n ? { promoCode: fieldValues.promoCode.trim() }\n : {}),\n ...(catalog.widget.fields.tipping ? { tipCents } : {}),\n };\n}\n\nasync function getCompleteAddress(\n elements: StripeElements,\n mode: \"billing\" | \"shipping\"\n) {\n const addressElement = elements.getElement(\"address\", { mode });\n const label = mode === \"billing\" ? \"Billing\" : \"Shipping\";\n if (!addressElement) {\n throw new Error(`${label} address is still loading.`);\n }\n const address = await addressElement.getValue();\n if (!address.complete) {\n throw new Error(`${label} address is required.`);\n }\n return address.value;\n}\n\nfunction getShippingAddress(\n catalog: LockerverseCatalog,\n elements: StripeElements,\n fieldValues: CheckoutFieldValues,\n billingAddress: Awaited<ReturnType<typeof getCompleteAddress>>\n) {\n if (!catalog.widget.fields.shipping) {\n return;\n }\n return fieldValues.shippingMatchesBilling\n ? billingAddress\n : getCompleteAddress(elements, \"shipping\");\n}\n\nfunction buildConfirmationParams({\n billingAddress,\n catalog,\n email,\n phone,\n shippingAddress,\n}: {\n billingAddress: Awaited<ReturnType<typeof getCompleteAddress>>;\n catalog: LockerverseCatalog;\n email: string;\n phone: string;\n shippingAddress: Awaited<ReturnType<typeof getCompleteAddress>> | undefined;\n}) {\n return {\n payment_method_data: {\n billing_details: {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n ...(catalog.widget.fields.phone ? { phone } : {}),\n },\n },\n ...(shippingAddress\n ? {\n shipping: {\n address: shippingAddress.address,\n name: shippingAddress.name,\n phone: catalog.widget.fields.phone\n ? phone\n : (shippingAddress.phone ?? null),\n },\n }\n : {}),\n };\n}\n\nfunction buildPaymentRequest({\n catalog,\n confirmationToken,\n email,\n fieldValues,\n phone,\n}: {\n catalog: LockerverseCatalog;\n confirmationToken: string;\n email: string;\n fieldValues: CheckoutFieldValues;\n phone: string;\n}) {\n return {\n confirmationToken,\n customFieldAnswers: buildCustomFieldAnswers(\n catalog.widget.customFields,\n fieldValues.customFields\n ),\n email,\n ...(catalog.widget.fields.memberId && fieldValues.memberId.trim()\n ? { memberId: fieldValues.memberId.trim() }\n : {}),\n ...(catalog.widget.fields.merchSize\n ? { merchSize: fieldValues.merchSize }\n : {}),\n ...(catalog.widget.fields.phone ? { phone } : {}),\n };\n}\n\nasync function completePayment({\n catalog,\n checkout,\n elements,\n email,\n fieldValues,\n phone,\n quote,\n stripe,\n}: {\n catalog: LockerverseCatalog;\n checkout: LockerverseWidget;\n elements: StripeElements;\n email: string;\n fieldValues: CheckoutFieldValues;\n phone: string;\n quote: LockerverseCheckoutQuote;\n stripe: Stripe;\n}) {\n const normalizedEmail = email.trim().toLowerCase();\n const normalizedPhone = normalizePhone(phone);\n const parsedTip = getTipCents(quote.subtotalCents, fieldValues);\n if (!parsedTip.success) {\n throw new Error(parsedTip.message);\n }\n const currentQuote = await checkout.calculateTotal(\n buildQuoteRequest(catalog, fieldValues, normalizedEmail, parsedTip.cents)\n );\n elements.update({ amount: currentQuote.totalCents });\n if (hasMaterialQuoteChange(quote, currentQuote)) {\n return { kind: \"quote_changed\" as const, quote: currentQuote };\n }\n\n const elementSubmission = await elements.submit();\n if (elementSubmission.error) {\n throw new Error(elementSubmission.error.message);\n }\n\n const billingAddress = await getCompleteAddress(elements, \"billing\");\n const shippingAddress = await getShippingAddress(\n catalog,\n elements,\n fieldValues,\n billingAddress\n );\n\n const tokenResult = await stripe.createConfirmationToken({\n elements,\n params: buildConfirmationParams({\n billingAddress,\n catalog,\n email: normalizedEmail,\n phone: normalizedPhone,\n shippingAddress,\n }),\n });\n if (tokenResult.error) {\n throw new Error(tokenResult.error.message);\n }\n\n const outcome = await submitPaymentAttempt(\n checkout,\n buildPaymentRequest({\n catalog,\n confirmationToken: tokenResult.confirmationToken.id,\n email: normalizedEmail,\n fieldValues,\n phone: normalizedPhone,\n }),\n stripe\n );\n if (outcome.kind === \"failed\") {\n return {\n kind: \"payment_failed\" as const,\n message:\n \"Payment was declined. Check your payment details and try again.\",\n };\n }\n if (outcome.kind === \"unresolved\") {\n return {\n kind: \"payment_unresolved\" as const,\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n };\n }\n return {\n kind: \"payment\" as const,\n payment: outcome.payment,\n quote: currentQuote,\n };\n}\n\nfunction ReadyPayment({\n accentColor,\n catalog,\n checkout,\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n quote,\n onStateChange,\n stripeLoader,\n theme,\n}: {\n accentColor: string;\n catalog: LockerverseCatalog;\n checkout: LockerverseWidget;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerverseCheckoutQuote, notice?: string) => void;\n quote: LockerverseCheckoutQuote;\n onStateChange: (\n state:\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\"\n ) => void;\n stripeLoader: typeof loadStripe;\n theme: LockerversePaymentProps[\"theme\"];\n}) {\n const stripe = useMemo(\n () =>\n stripeLoader(\n catalog.payment.publishableKey,\n quote.payment.connectedAccountId\n ? { stripeAccount: quote.payment.connectedAccountId }\n : undefined\n ),\n [\n catalog.payment.publishableKey,\n quote.payment.connectedAccountId,\n stripeLoader,\n ]\n );\n\n return (\n <Elements\n key={`${catalog.payment.publishableKey}:${quote.payment.connectedAccountId ?? \"platform\"}`}\n options={{\n amount: quote.totalCents,\n appearance: {\n rules: {\n \".Input:focus\": {\n borderColor: accentColor,\n boxShadow: \"none\",\n outline: \"none\",\n },\n },\n theme: theme === \"light\" ? \"stripe\" : \"night\",\n variables: {\n borderRadius: \"8px\",\n colorBackground: theme === \"light\" ? \"#f5f6f7\" : \"#101010\",\n colorDanger: theme === \"light\" ? \"#c52b3e\" : \"#ef4444\",\n colorPrimary: accentColor,\n colorText: theme === \"light\" ? \"#121416\" : \"#ffffff\",\n colorTextPlaceholder: theme === \"light\" ? \"#72767d\" : \"#6b6b6b\",\n colorTextSecondary: theme === \"light\" ? \"#62666d\" : \"#a1a1aa\",\n focusBoxShadow: \"none\",\n focusOutline: \"none\",\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif\",\n fontSizeBase: \"16px\",\n },\n },\n currency: quote.payment.currency,\n excludedPaymentMethodTypes: [\"us_bank_account\"],\n mode: \"payment\",\n syncAddressCheckbox: \"none\",\n }}\n stripe={stripe}\n >\n <PaymentForm\n catalog={catalog}\n checkout={checkout}\n onPaymentComplete={onPaymentComplete}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={onQuoteChange}\n onStateChange={onStateChange}\n quote={quote}\n />\n </Elements>\n );\n}\n\nfunction StripeElementLoader({ label }: { label: string }) {\n return (\n <div className=\"lockerverse-payment__stripe-loader\" role=\"status\">\n <p>{label}</p>\n <div aria-hidden=\"true\">\n <span />\n <span />\n <span />\n </div>\n </div>\n );\n}\n\nfunction StripePaymentField({\n onError,\n onReady,\n ready,\n}: {\n onError: (message: string) => void;\n onReady: () => void;\n ready: boolean;\n}) {\n return (\n <div className=\"lockerverse-payment__stripe-element\" data-ready={ready}>\n {ready ? null : <StripeElementLoader label=\"Loading payment form...\" />}\n <PaymentElement\n onLoadError={({ error }) =>\n onError(error.message ?? \"Payment form failed to load.\")\n }\n onReady={onReady}\n options={{\n business: { name: \"Lockerverse\" },\n fields: { billingDetails: { email: \"auto\" } },\n layout: \"tabs\",\n terms: {\n applePay: \"auto\",\n auBecsDebit: \"never\",\n bancontact: \"never\",\n card: \"always\",\n cashapp: \"never\",\n googlePay: \"never\",\n ideal: \"never\",\n paypal: \"auto\",\n sepaDebit: \"never\",\n sofort: \"never\",\n usBankAccount: \"never\",\n },\n wallets: { applePay: \"auto\", googlePay: \"never\" },\n }}\n />\n </div>\n );\n}\n\nfunction StripeAddressField({\n label,\n mode,\n onError,\n onReady,\n ready,\n}: {\n label: string;\n mode: \"billing\" | \"shipping\";\n onError: (message: string) => void;\n onReady: () => void;\n ready: boolean;\n}) {\n return (\n <div className=\"lockerverse-payment__address\">\n <h2>{label}</h2>\n <div\n className=\"lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address\"\n data-ready={ready}\n >\n {ready ? null : (\n <StripeElementLoader label={`Loading ${label.toLowerCase()}...`} />\n )}\n <AddressElement\n onLoadError={({ error }) =>\n onError(error.message ?? `${label} failed to load.`)\n }\n onReady={onReady}\n options={{ autocomplete: { mode: \"automatic\" }, mode }}\n />\n </div>\n </div>\n );\n}\n\nfunction PaymentErrorMessage({ message }: { message: string | undefined }) {\n if (!message) {\n return null;\n }\n return (\n <p className=\"lockerverse-payment__field-message\" role=\"alert\">\n {message}\n </p>\n );\n}\n\ntype PaymentUiState =\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\";\n\ntype PaymentTerminalState = {\n kind: \"success\" | \"unresolved\";\n message: string;\n};\n\ntype CompletePaymentResult = Awaited<ReturnType<typeof completePayment>>;\n\nfunction focusFirstValidationError({\n customFieldErrors,\n emailRef,\n form,\n parsedTipSuccess,\n phoneRef,\n validationErrors,\n}: {\n customFieldErrors: Record<string, string>;\n emailRef: React.RefObject<HTMLInputElement | null>;\n form: HTMLFormElement;\n parsedTipSuccess: boolean;\n phoneRef: React.RefObject<HTMLInputElement | null>;\n validationErrors: { email?: string; phone?: string };\n}) {\n if (validationErrors.email) {\n emailRef.current?.focus();\n return;\n }\n if (validationErrors.phone) {\n phoneRef.current?.focus();\n return;\n }\n if (!parsedTipSuccess) {\n form.querySelector<HTMLElement>('[name=\"tip\"]')?.focus();\n return;\n }\n const [firstFieldId] = Object.keys(customFieldErrors);\n if (firstFieldId) {\n form.querySelector<HTMLElement>(`[name=\"custom:${firstFieldId}\"]`)?.focus();\n }\n}\n\nfunction applyPaymentOutcome({\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n result,\n setDisplayedTotalCents,\n setPaymentError,\n setTerminalState,\n}: {\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerverseCheckoutQuote, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n result: CompletePaymentResult;\n setDisplayedTotalCents: (total: number) => void;\n setPaymentError: (message: string) => void;\n setTerminalState: (state: PaymentTerminalState) => void;\n}) {\n if (result.kind === \"quote_changed\") {\n const notice = `The total changed to ${formatMoney(result.quote.totalCents)}. Review it and pay again.`;\n onQuoteChange(result.quote, notice);\n setDisplayedTotalCents(result.quote.totalCents);\n onStateChange(\"idle\");\n return;\n }\n if (result.kind === \"payment_failed\") {\n setPaymentError(result.message);\n onStateChange(\"error\");\n return;\n }\n if (result.kind === \"payment_unresolved\") {\n setTerminalState({\n kind: \"unresolved\",\n message: \"Payment is still processing. Do not submit it again.\",\n });\n onStateChange(\"unresolved\");\n try {\n onPaymentUncertain?.({\n paymentReference: result.paymentReference,\n reason: result.reason,\n });\n } catch {\n // Host callback failures must not unlock an uncertain payment.\n }\n return;\n }\n onQuoteChange(result.quote);\n setTerminalState({\n kind: \"success\",\n message: \"Payment completed successfully.\",\n });\n onStateChange(\"success\");\n try {\n onPaymentComplete?.(result.payment);\n } catch {\n // Host callback failures must not turn a completed payment into an error.\n }\n}\n\nfunction ContactFields({\n email,\n emailErrorId,\n emailId,\n emailRef,\n errors,\n onEmailChange,\n onPhoneChange,\n onPhoneCountryChange,\n phone,\n phoneCountry,\n phoneEnabled,\n phoneErrorId,\n phoneId,\n phoneRef,\n}: {\n email: string;\n emailErrorId: string;\n emailId: string;\n emailRef: React.RefObject<HTMLInputElement | null>;\n errors: { email?: string; phone?: string };\n onEmailChange: (value: string) => void;\n onPhoneChange: (value: string) => void;\n onPhoneCountryChange: (value: string) => void;\n phone: string;\n phoneCountry: string;\n phoneEnabled: boolean;\n phoneErrorId: string;\n phoneId: string;\n phoneRef: React.RefObject<HTMLInputElement | null>;\n}) {\n return (\n <div className=\"lockerverse-payment__contact\">\n <label htmlFor={emailId}>Email</label>\n <input\n aria-describedby={errors.email ? emailErrorId : undefined}\n aria-invalid={errors.email ? \"true\" : undefined}\n autoComplete=\"email\"\n id={emailId}\n name=\"email\"\n onChange={(event) => onEmailChange(event.currentTarget.value)}\n placeholder=\"name@example.com\"\n ref={emailRef}\n type=\"email\"\n value={email}\n />\n {errors.email ? (\n <p className=\"lockerverse-payment__field-message\" id={emailErrorId}>\n {errors.email}\n </p>\n ) : null}\n {phoneEnabled ? (\n <>\n <label htmlFor={phoneId}>Phone</label>\n <div className=\"lockerverse-payment__phone-control\">\n <select\n aria-label=\"Phone number country\"\n name=\"phoneCountry\"\n onChange={(event) =>\n onPhoneCountryChange(event.currentTarget.value)\n }\n value={phoneCountry}\n >\n {PHONE_COUNTRIES.map((country) => (\n <option key={country.value} value={country.value}>\n {country.label}\n </option>\n ))}\n </select>\n <input\n aria-describedby={errors.phone ? phoneErrorId : undefined}\n aria-invalid={errors.phone ? \"true\" : undefined}\n autoComplete=\"tel\"\n id={phoneId}\n inputMode=\"tel\"\n name=\"phone\"\n onChange={(event) => onPhoneChange(event.currentTarget.value)}\n placeholder=\"(201) 555-0123\"\n ref={phoneRef}\n type=\"tel\"\n value={phone}\n />\n </div>\n {errors.phone ? (\n <p className=\"lockerverse-payment__field-message\" id={phoneErrorId}>\n {errors.phone}\n </p>\n ) : null}\n </>\n ) : null}\n </div>\n );\n}\n\nfunction PaymentForm({\n catalog,\n checkout,\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n}: {\n catalog: LockerverseCatalog;\n checkout: LockerverseWidget;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerverseCheckoutQuote, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerverseCheckoutQuote;\n}) {\n const [email, setEmail] = useState(\"\");\n const [phone, setPhone] = useState(\"\");\n const [phoneCountry, setPhoneCountry] = useState(\"US\");\n const [errors, setErrors] = useState<{ email?: string; phone?: string }>({});\n const [paymentError, setPaymentError] = useState<string>();\n const [customFieldErrors, setCustomFieldErrors] = useState<\n Record<string, string>\n >({});\n const [tipError, setTipError] = useState<string>();\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [terminalState, setTerminalState] = useState<PaymentTerminalState>();\n const [isPaymentReady, setIsPaymentReady] = useState(false);\n const [isBillingAddressReady, setIsBillingAddressReady] = useState(false);\n const [isShippingAddressReady, setIsShippingAddressReady] = useState(false);\n const [fieldValues, setFieldValues] = useState<CheckoutFieldValues>({\n customFields: {},\n customTip: \"\",\n includeServiceFee: catalog.widget.fields.serviceFee,\n memberId: \"\",\n merchSize: \"M\",\n promoCode: \"\",\n shippingMatchesBilling: true,\n tipPercent: \"10\",\n });\n const [displayedTotalCents, setDisplayedTotalCents] = useState(\n quote.totalCents\n );\n const emailRef = useRef<HTMLInputElement>(null);\n const phoneRef = useRef<HTMLInputElement>(null);\n const statusRef = useRef<HTMLParagraphElement>(null);\n const elements = useElements();\n const stripe = useStripe();\n const idPrefix = `lockerverse-${useId()}`;\n const emailId = `${idPrefix}-email`;\n const emailErrorId = `${emailId}-error`;\n const phoneId = `${idPrefix}-phone`;\n const phoneErrorId = `${phoneId}-error`;\n const tipErrorId = `${idPrefix}-tip-error`;\n const parsedTip = catalog.widget.fields.tipping\n ? getTipCents(quote.subtotalCents, fieldValues)\n : ({ cents: 0, success: true } as const);\n const parsedTipCents = parsedTip.success ? parsedTip.cents : null;\n const displayedTipCents = parsedTipCents ?? 0;\n const displayedBaseCents = displayedTotalCents - displayedTipCents;\n const isRequiredShippingReady =\n !catalog.widget.fields.shipping ||\n fieldValues.shippingMatchesBilling ||\n isShippingAddressReady;\n\n useEffect(() => {\n if (isSubmitting || parsedTipCents === null) {\n return;\n }\n const preview = checkout.previewTotal({\n ...(catalog.widget.fields.serviceFee\n ? { includeServiceFee: fieldValues.includeServiceFee }\n : {}),\n ...(catalog.widget.fields.tipping ? { tipCents: parsedTipCents } : {}),\n });\n setDisplayedTotalCents(preview.totalCents);\n elements?.update({ amount: preview.totalCents });\n }, [\n catalog.widget.fields.serviceFee,\n catalog.widget.fields.tipping,\n checkout,\n elements,\n fieldValues.includeServiceFee,\n fieldValues.tipPercent,\n fieldValues.customTip,\n isSubmitting,\n parsedTipCents,\n quote.subtotalCents,\n ]);\n\n useEffect(() => {\n if (isSubmitting) {\n statusRef.current?.focus();\n }\n }, [isSubmitting]);\n\n function clearError(field: \"email\" | \"phone\") {\n setErrors((current) => {\n const next = { ...current };\n delete next[field];\n return next;\n });\n }\n\n function handleFieldValuesChange(nextValues: CheckoutFieldValues) {\n setFieldValues(nextValues);\n setCustomFieldErrors({});\n setTipError(undefined);\n }\n\n function handleStripeLoadError(message: string) {\n setPaymentError(message);\n onStateChange(\"error\");\n }\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const validation = validateContact(\n { email, phone: getInternationalPhone(phone, phoneCountry) },\n catalog.widget.fields.phone\n );\n const nextCustomFieldErrors = validateCustomFields(\n catalog.widget.customFields,\n fieldValues.customFields\n );\n if (\n !(validation.value && parsedTip.success) ||\n Object.keys(nextCustomFieldErrors).length > 0\n ) {\n setErrors(validation.errors);\n setCustomFieldErrors(nextCustomFieldErrors);\n setTipError(parsedTip.success ? undefined : parsedTip.message);\n onStateChange(\"invalid\");\n const form = event.currentTarget;\n queueMicrotask(() => {\n focusFirstValidationError({\n customFieldErrors: nextCustomFieldErrors,\n emailRef,\n form,\n parsedTipSuccess: parsedTip.success,\n phoneRef,\n validationErrors: validation.errors,\n });\n });\n return;\n }\n\n setErrors({});\n setCustomFieldErrors({});\n\n if (!(elements && stripe)) {\n setPaymentError(\"Payment form is still loading.\");\n onStateChange(\"error\");\n return;\n }\n\n setPaymentError(undefined);\n setIsSubmitting(true);\n onStateChange(\"submitting\");\n\n try {\n const result = await completePayment({\n catalog,\n checkout,\n elements,\n email,\n fieldValues,\n phone: getInternationalPhone(phone, phoneCountry),\n quote,\n stripe,\n });\n applyPaymentOutcome({\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n result,\n setDisplayedTotalCents,\n setPaymentError,\n setTerminalState,\n });\n } catch (error) {\n setPaymentError(\n error instanceof Error\n ? error.message\n : \"Payment could not be completed.\"\n );\n onStateChange(\"error\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n if (terminalState) {\n return (\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {terminalState.message}\n </p>\n );\n }\n\n return (\n <form\n aria-busy={isSubmitting}\n className=\"lockerverse-payment__form\"\n noValidate\n onSubmit={handleSubmit}\n >\n <div\n data-lockerverse-input-region=\"\"\n inert={isSubmitting ? true : undefined}\n >\n <fieldset\n className=\"lockerverse-payment__input-fieldset\"\n disabled={isSubmitting}\n >\n <TipField\n enabled={catalog.widget.fields.tipping}\n error={tipError}\n errorId={tipErrorId}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <ContactFields\n email={email}\n emailErrorId={emailErrorId}\n emailId={emailId}\n emailRef={emailRef}\n errors={errors}\n onEmailChange={(value) => {\n setEmail(value);\n clearError(\"email\");\n }}\n onPhoneChange={(value) => {\n setPhone(value);\n clearError(\"phone\");\n }}\n onPhoneCountryChange={setPhoneCountry}\n phone={phone}\n phoneCountry={phoneCountry}\n phoneEnabled={catalog.widget.fields.phone}\n phoneErrorId={phoneErrorId}\n phoneId={phoneId}\n phoneRef={phoneRef}\n />\n <StripePaymentField\n onError={handleStripeLoadError}\n onReady={() => setIsPaymentReady(true)}\n ready={isPaymentReady}\n />\n <StripeAddressField\n label=\"Billing address\"\n mode=\"billing\"\n onError={handleStripeLoadError}\n onReady={() => setIsBillingAddressReady(true)}\n ready={isBillingAddressReady}\n />\n {catalog.widget.fields.shipping ? (\n <div className=\"lockerverse-payment__shipping\">\n <CheckoutToggle\n checked={fieldValues.shippingMatchesBilling}\n name=\"shippingMatchesBilling\"\n onChange={(shippingMatchesBilling) => {\n handleFieldValuesChange({\n ...fieldValues,\n shippingMatchesBilling,\n });\n if (!shippingMatchesBilling) {\n setIsShippingAddressReady(false);\n }\n }}\n >\n Shipping is same as billing information\n </CheckoutToggle>\n {fieldValues.shippingMatchesBilling ? null : (\n <StripeAddressField\n label=\"Shipping address\"\n mode=\"shipping\"\n onError={handleStripeLoadError}\n onReady={() => setIsShippingAddressReady(true)}\n ready={isShippingAddressReady}\n />\n )}\n </div>\n ) : null}\n <AdditionalCheckoutFields\n customFields={catalog.widget.customFields}\n errors={customFieldErrors}\n fields={catalog.widget.fields}\n idPrefix={idPrefix}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <div className=\"lockerverse-payment__actions\">\n <ServiceFeeField\n amountCents={\n quote.serviceFeeCents ||\n Math.round(\n (quote.subtotalCents *\n catalog.pricingPolicy.serviceFeeRateBasisPoints) /\n 10_000\n )\n }\n enabled={catalog.widget.fields.serviceFee}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <button\n aria-busy={isSubmitting}\n aria-label={`Process payment for ${formatMoney(displayedTotalCents)} total`}\n disabled={\n isSubmitting ||\n !(\n isPaymentReady &&\n isBillingAddressReady &&\n isRequiredShippingReady\n )\n }\n type=\"submit\"\n >\n {isSubmitting\n ? \"Processing…\"\n : `Process Payment (${formatMoney(displayedBaseCents)})${\n displayedTipCents > 0\n ? ` + ${formatMoney(displayedTipCents)} tip`\n : \"\"\n }`}\n </button>\n </div>\n </fieldset>\n </div>\n {isSubmitting ? (\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n Processing payment…\n </p>\n ) : null}\n <PaymentErrorMessage message={paymentError} />\n </form>\n );\n}\n\nfunction createCheckoutOptions({\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n onError,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n}: {\n apiBaseUrl: string | undefined;\n communitySlug: string;\n environment: LockerversePaymentProps[\"environment\"];\n fetch: LockerversePaymentProps[\"fetch\"];\n onError: LockerversePaymentProps[\"onError\"];\n requestTimeoutMs: number | undefined;\n sentryDsn: string | null | undefined;\n widgetSlug: string;\n}): CreateLockerverseWidgetOptions {\n const common = {\n communitySlug,\n widgetSlug,\n ...(fetch ? { fetch } : {}),\n ...(onError ? { onError } : {}),\n ...(requestTimeoutMs === undefined ? {} : { requestTimeoutMs }),\n ...(sentryDsn === undefined ? {} : { sentryDsn }),\n };\n if (apiBaseUrl === undefined) {\n if (environment === \"development\") {\n throw new TypeError(\n \"Lockerverse development checkout requires an API base URL.\"\n );\n }\n return {\n ...common,\n ...(environment === \"production\" ? { environment } : {}),\n };\n }\n if (!environment) {\n throw new TypeError(\n \"Lockerverse development checkout requires an environment.\"\n );\n }\n return { ...common, apiBaseUrl, environment };\n}\n\nfunction SkeletonLoaderBlock() {\n return (\n <div className=\"lockerverse-payment__skeleton-loader-block\">\n <span className=\"lockerverse-payment__skeleton-loader-label\" />\n <div className=\"lockerverse-payment__skeleton-loader-content\">\n <span className=\"lockerverse-payment__skeleton-loader-full\" />\n <div className=\"lockerverse-payment__skeleton-loader-grid\">\n <span className=\"lockerverse-payment__skeleton-loader-half\" />\n <span className=\"lockerverse-payment__skeleton-loader-half\" />\n </div>\n </div>\n </div>\n );\n}\n\nfunction PaymentSkeleton() {\n return (\n <div className=\"lockerverse-payment__loading\">\n <span\n aria-live=\"polite\"\n className=\"lockerverse-payment__sr-only\"\n role=\"status\"\n >\n Loading payment…\n </span>\n <div aria-hidden=\"true\" className=\"lockerverse-payment__skeleton\">\n <div className=\"lockerverse-payment__skeleton-branding\">\n <span className=\"lockerverse-payment__skeleton-avatar\" />\n <span className=\"lockerverse-payment__skeleton-community\" />\n </div>\n <div className=\"lockerverse-payment__skeleton-contact\">\n <div className=\"lockerverse-payment__skeleton-field\">\n <span className=\"lockerverse-payment__skeleton-label\" />\n <span className=\"lockerverse-payment__skeleton-input\" />\n </div>\n <div className=\"lockerverse-payment__skeleton-field\">\n <span className=\"lockerverse-payment__skeleton-label\" />\n <span className=\"lockerverse-payment__skeleton-input\" />\n </div>\n </div>\n <SkeletonLoaderBlock />\n <SkeletonLoaderBlock />\n <div className=\"lockerverse-payment__skeleton-actions\">\n <span className=\"lockerverse-payment__skeleton-check-line\" />\n <span className=\"lockerverse-payment__skeleton-button\" />\n </div>\n </div>\n </div>\n );\n}\n\nexport function LockerversePayment({\n apiBaseUrl,\n branding,\n className,\n communitySlug,\n environment,\n fetch,\n onError,\n onPaymentComplete,\n onPaymentUncertain,\n requestTimeoutMs,\n selection,\n sentryDsn,\n style,\n stripeLoader = loadStripe,\n theme = \"dark\",\n widgetSlug,\n ...sectionProps\n}: LockerversePaymentProps) {\n const checkoutOptions = useMemo(\n () =>\n createCheckoutOptions({\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n onError,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n }),\n [\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n onError,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n ]\n );\n const parsedSelection = parsePaymentSelection(selection);\n const selectionKey = parsedSelection.success\n ? JSON.stringify(parsedSelection.value)\n : \"invalid-selection\";\n const stableSelection = useMemo(\n () =>\n parsedSelection.success\n ? (JSON.parse(selectionKey) as LockerversePaymentSelectionItem[])\n : [],\n [selectionKey]\n );\n const [catalog, setCatalog] = useState<LockerverseCatalog>();\n const [checkout, setCheckout] = useState<LockerverseWidget>();\n const [quote, setQuote] = useState<LockerverseCheckoutQuote>();\n const [loadedSelectionKey, setLoadedSelectionKey] = useState<string>();\n const [failure, setFailure] = useState<string>();\n const [notice, setNotice] = useState<string>();\n const [paymentState, setPaymentState] = useState<\n \"error\" | \"idle\" | \"invalid\" | \"submitting\" | \"success\" | \"unresolved\"\n >(\"idle\");\n const loadingSelectionKeyRef = useRef<string | undefined>(undefined);\n\n useEffect(() => {\n if (!parsedSelection.success) {\n return;\n }\n if (\n paymentState === \"submitting\" ||\n paymentState === \"success\" ||\n paymentState === \"unresolved\" ||\n loadedSelectionKey === selectionKey ||\n loadingSelectionKeyRef.current === selectionKey\n ) {\n return;\n }\n let active = true;\n const nextCheckout = createLockerverseCheckout(checkoutOptions);\n loadingSelectionKeyRef.current = selectionKey;\n setCatalog(undefined);\n setCheckout(undefined);\n setFailure(undefined);\n setNotice(undefined);\n setQuote(undefined);\n async function loadPayment() {\n try {\n const loadedCatalog = await nextCheckout.load();\n applySelection(nextCheckout, loadedCatalog, stableSelection);\n const loadedQuote = await nextCheckout.calculateTotal({\n ...(loadedCatalog.widget.fields.serviceFee\n ? { includeServiceFee: true }\n : {}),\n });\n if (active) {\n setCatalog(loadedCatalog);\n setCheckout(nextCheckout);\n setLoadedSelectionKey(selectionKey);\n setPaymentState(\"idle\");\n setQuote(loadedQuote);\n }\n } catch (error) {\n if (active) {\n setFailure(\n error instanceof Error\n ? error.message\n : \"Lockerverse payment could not load.\"\n );\n }\n }\n }\n loadPayment();\n return () => {\n active = false;\n if (loadingSelectionKeyRef.current === selectionKey) {\n loadingSelectionKeyRef.current = undefined;\n }\n };\n }, [\n checkoutOptions,\n loadedSelectionKey,\n parsedSelection.success,\n paymentState,\n selectionKey,\n stableSelection,\n ]);\n\n const rootClassName = [\"lockerverse-payment\", className]\n .filter(Boolean)\n .join(\" \");\n const effectiveAccent =\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\";\n const automaticAccentContrast = getAccentContrast(effectiveAccent);\n const rootStyle: LockerversePaymentProps[\"style\"] = {\n ...style,\n ...(branding?.accentColor && style?.[\"--lockerverse-accent\"] === undefined\n ? { \"--lockerverse-accent\": branding.accentColor }\n : {}),\n ...(automaticAccentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ? { \"--lockerverse-accent-contrast\": automaticAccentContrast }\n : {}),\n };\n\n if (!parsedSelection.success) {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n style={rootStyle}\n >\n {parsedSelection.message}\n </section>\n );\n }\n\n if (failure) {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n >\n {failure}\n </section>\n );\n }\n\n if (!(catalog && checkout && quote)) {\n return (\n <section\n {...sectionProps}\n aria-busy=\"true\"\n aria-label=\"Payment\"\n className={rootClassName}\n data-lockerverse-theme={theme}\n >\n <PaymentSkeleton />\n </section>\n );\n }\n\n return (\n <section\n {...sectionProps}\n aria-label=\"Payment\"\n className={rootClassName}\n data-lockerverse-theme={theme}\n data-payment-state={paymentState}\n style={rootStyle}\n >\n <header>\n {catalog.widget.showCommunityBranding && branding ? (\n <div className=\"lockerverse-payment__branding\">\n {branding.imageUrl ? (\n <img\n alt={branding.name}\n height=\"48\"\n src={branding.imageUrl}\n width=\"48\"\n />\n ) : null}\n <strong>{branding.name}</strong>\n </div>\n ) : null}\n <h1>{catalog.widget.title ?? catalog.widget.name}</h1>\n {catalog.widget.description ? (\n <p>{catalog.widget.description}</p>\n ) : null}\n </header>\n {notice ? (\n <p className=\"lockerverse-payment__payment-status\" role=\"status\">\n {notice}\n </p>\n ) : null}\n <ReadyPayment\n accentColor={\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n }\n catalog={catalog}\n checkout={checkout}\n onPaymentComplete={onPaymentComplete}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={(nextQuote, nextNotice) => {\n setNotice(nextNotice);\n setQuote(nextQuote);\n }}\n onStateChange={setPaymentState}\n quote={quote}\n stripeLoader={stripeLoader}\n theme={theme}\n />\n </section>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["formatMoney"],"sources":["../src/accent-contrast.ts","../src/checkout-fields.tsx","../src/payment-attempt.ts","../src/payment-input.ts","../src/payment-validation.ts","../src/use-checkout-session.ts","../src/lockerverse-payment.tsx"],"sourcesContent":["const HEX_COLOR = /^#([\\da-f]{3}|[\\da-f]{6})$/i;\n\nfunction parseHexColor(color: string) {\n const match = HEX_COLOR.exec(color.trim());\n if (!match) {\n return;\n }\n const [, value] = match;\n if (!value) {\n return;\n }\n const expanded =\n value.length === 3\n ? Array.from(value, (character) => `${character}${character}`).join(\"\")\n : value;\n return [0, 2, 4].map((offset) =>\n Number.parseInt(expanded.slice(offset, offset + 2), 16)\n );\n}\n\nfunction relativeLuminance([red, green, blue]: number[]) {\n const [linearRed = 0, linearGreen = 0, linearBlue = 0] = [\n red,\n green,\n blue,\n ].map((channel = 0) => {\n const normalized = channel / 255;\n return normalized <= 0.040_45\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * linearRed + 0.7152 * linearGreen + 0.0722 * linearBlue;\n}\n\nexport function getAccentContrast(color: string) {\n const parsed = parseHexColor(color);\n if (!parsed) {\n return;\n }\n const luminance = relativeLuminance(parsed);\n const blackContrast = (luminance + 0.05) / 0.05;\n const whiteContrast = 1.05 / (luminance + 0.05);\n return blackContrast >= whiteContrast ? \"#000\" : \"#fff\";\n}\n","import type {\n LockerverseCustomField,\n LockerverseMultiOptionCustomField,\n LockerverseSingleOptionCustomField,\n LockerverseWidgetFields,\n} from \"@lockerverse/sdk/checkout\";\n\nexport const MERCH_SIZES = [\"XS\", \"S\", \"M\", \"L\", \"XL\", \"XXL\", \"XXXL\"] as const;\n\nexport type CheckoutFieldValues = {\n customTip: string;\n customFields: Record<string, string | string[]>;\n includeServiceFee: boolean;\n memberId: string;\n merchSize: (typeof MERCH_SIZES)[number];\n promoCode: string;\n shippingMatchesBilling: boolean;\n tipPercent: \"5\" | \"10\" | \"12\" | \"15\" | \"custom\";\n};\n\nconst TIP_OPTIONS = [\"15\", \"12\", \"10\", \"5\"] as const;\n\nexport function TipField({\n enabled,\n error,\n errorId,\n onChange,\n values,\n}: {\n enabled: boolean;\n error: string | undefined;\n errorId: string;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n if (!enabled) {\n return null;\n }\n const update = (next: Partial<CheckoutFieldValues>) =>\n onChange({ ...values, ...next });\n return (\n <div className=\"lockerverse-payment__tip-box\">\n <p>Add a tip to support the Lockerverse platform</p>\n <div aria-label=\"Tip amount\" role=\"radiogroup\">\n {TIP_OPTIONS.map((tip) => (\n <button\n aria-pressed={values.tipPercent === tip}\n key={tip}\n onClick={() => update({ tipPercent: tip })}\n type=\"button\"\n >\n {tip}%\n </button>\n ))}\n <button\n aria-pressed={values.tipPercent === \"custom\"}\n onClick={() => update({ tipPercent: \"custom\" })}\n type=\"button\"\n >\n Other\n </button>\n </div>\n {values.tipPercent === \"custom\" ? (\n <label>\n <span>Custom tip</span>\n <span className=\"lockerverse-payment__money-input\">\n <span aria-hidden=\"true\">$</span>\n <input\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n inputMode=\"decimal\"\n name=\"tip\"\n onChange={(event) =>\n update({ customTip: event.currentTarget.value })\n }\n placeholder=\"0.00\"\n value={values.customTip}\n />\n </span>\n {error ? (\n <span className=\"lockerverse-payment__field-message\" id={errorId}>\n {error}\n </span>\n ) : null}\n </label>\n ) : (\n <input name=\"tip\" type=\"hidden\" value={values.tipPercent} />\n )}\n </div>\n );\n}\n\nexport function CheckoutToggle({\n checked,\n children,\n name,\n onChange,\n}: {\n checked: boolean;\n children: React.ReactNode;\n name: string;\n onChange: (checked: boolean) => void;\n}) {\n return (\n <label className=\"lockerverse-payment__check-row\">\n <input\n checked={checked}\n name={name}\n onChange={(event) => onChange(event.currentTarget.checked)}\n type=\"checkbox\"\n />\n <span>{children}</span>\n </label>\n );\n}\n\nexport function AdditionalCheckoutFields({\n customFields,\n errors,\n fields,\n idPrefix,\n onChange,\n values,\n}: {\n customFields: LockerverseCustomField[];\n errors: Record<string, string>;\n fields: LockerverseWidgetFields;\n idPrefix: string;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n const update = (next: Partial<CheckoutFieldValues>) =>\n onChange({ ...values, ...next });\n\n return (\n <div className=\"lockerverse-payment__additional-fields\">\n {fields.memberId ? (\n <label>\n <span>Member ID</span>\n <input\n name=\"memberId\"\n onChange={(event) =>\n update({ memberId: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.memberId}\n />\n </label>\n ) : null}\n {fields.merchSize ? (\n <label>\n <span>Size</span>\n <select\n name=\"merchSize\"\n onChange={(event) =>\n update({\n merchSize: event.currentTarget\n .value as CheckoutFieldValues[\"merchSize\"],\n })\n }\n value={values.merchSize}\n >\n {MERCH_SIZES.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n ) : null}\n {fields.promoCode ? (\n <label>\n <span>Promo code</span>\n <input\n name=\"promoCode\"\n onChange={(event) =>\n update({ promoCode: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.promoCode}\n />\n </label>\n ) : null}\n {customFields.map((field) => (\n <CustomField\n error={errors[field.id]}\n field={field}\n idPrefix={idPrefix}\n key={field.id}\n onChange={(value) =>\n update({\n customFields: { ...values.customFields, [field.id]: value },\n })\n }\n value={values.customFields[field.id]}\n />\n ))}\n </div>\n );\n}\n\nexport function ServiceFeeField({\n amountCents,\n enabled,\n onChange,\n values,\n}: {\n amountCents: number;\n enabled: boolean;\n onChange: (values: CheckoutFieldValues) => void;\n values: CheckoutFieldValues;\n}) {\n if (!enabled) {\n return null;\n }\n return (\n <CheckoutToggle\n checked={values.includeServiceFee}\n name=\"includeServiceFee\"\n onChange={(includeServiceFee) =>\n onChange({ ...values, includeServiceFee })\n }\n >\n Add {formatMoney(amountCents)} to help cover processing fees\n </CheckoutToggle>\n );\n}\n\nfunction CustomField({\n error,\n field,\n idPrefix,\n onChange,\n value,\n}: {\n error: string | undefined;\n field: LockerverseCustomField;\n idPrefix: string;\n onChange: (value: string | string[]) => void;\n value: string | string[] | undefined;\n}) {\n const name = `custom:${field.id}`;\n const controlId = `${idPrefix}-custom-${field.id}`;\n const errorId = `${controlId}-error`;\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n return (\n <TextCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n case \"select\":\n case \"multi_select\":\n return (\n <SelectCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n case \"radio\":\n case \"checkboxes\":\n return (\n <ChoiceCustomField\n controlId={controlId}\n error={error}\n errorId={errorId}\n field={field}\n name={name}\n onChange={onChange}\n value={value}\n />\n );\n default:\n return null;\n }\n}\n\ntype CustomFieldControlProps = {\n controlId: string;\n error: string | undefined;\n errorId: string;\n name: string;\n onChange: (value: string | string[]) => void;\n value: string | string[] | undefined;\n};\n\nfunction FieldError({ error, id }: { error: string | undefined; id: string }) {\n if (!error) {\n return null;\n }\n return (\n <p className=\"lockerverse-payment__field-message\" id={id}>\n {error}\n </p>\n );\n}\n\nfunction TextCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: Extract<LockerverseCustomField, { type: \"text\" | \"textarea\" }>;\n}) {\n const commonProps = {\n \"aria-describedby\": error ? errorId : undefined,\n \"aria-invalid\": error ? (\"true\" as const) : undefined,\n id: controlId,\n name,\n onChange: (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => onChange(event.currentTarget.value),\n required: field.required,\n value: typeof value === \"string\" ? value : \"\",\n };\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n {field.type === \"textarea\" ? (\n <textarea {...commonProps} />\n ) : (\n <input {...commonProps} />\n )}\n <FieldError error={error} id={errorId} />\n </label>\n );\n}\n\nfunction SelectCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n <select\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n id={controlId}\n multiple={field.type === \"multi_select\"}\n name={name}\n onChange={(event) =>\n onChange(\n field.type === \"multi_select\"\n ? [...event.currentTarget.selectedOptions].map(\n (option) => option.value\n )\n : event.currentTarget.value\n )\n }\n required={field.required}\n value={value ?? (field.type === \"multi_select\" ? [] : \"\")}\n >\n {field.type === \"select\" ? <option value=\"\">Select…</option> : null}\n {field.options.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldError error={error} id={errorId} />\n </label>\n );\n}\n\nfunction ChoiceCustomField({\n controlId,\n error,\n errorId,\n field,\n name,\n onChange,\n value,\n}: CustomFieldControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <fieldset\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n >\n <legend>{field.label}</legend>\n {field.options.map((option, index) => {\n const selected = Array.isArray(value)\n ? value.includes(option.id)\n : value === option.id;\n return (\n <label className=\"lockerverse-payment__check-row\" key={option.id}>\n <input\n checked={selected}\n id={`${controlId}-${index}`}\n name={name}\n onChange={(event) => {\n if (field.type === \"radio\") {\n onChange(option.id);\n return;\n }\n const selectedValues = Array.isArray(value) ? value : [];\n onChange(\n event.currentTarget.checked\n ? [...selectedValues, option.id]\n : selectedValues.filter((id) => id !== option.id)\n );\n }}\n required={field.required}\n type={field.type === \"radio\" ? \"radio\" : \"checkbox\"}\n value={option.id}\n />\n <span>{option.label}</span>\n </label>\n );\n })}\n <FieldError error={error} id={errorId} />\n </fieldset>\n );\n}\n\nfunction formatMoney(amountCents: number) {\n return new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amountCents / 100);\n}\n","import type {\n LockerverseCheckoutClient,\n LockerverseCheckoutQuote,\n LockerversePaymentResult,\n LockerverseSubmitPaymentInput,\n} from \"@lockerverse/sdk/checkout\";\nimport { LockerverseSdkError } from \"@lockerverse/sdk/checkout\";\nimport type { Stripe } from \"@stripe/stripe-js\";\n\nconst AMOUNT_KEYS = [\n \"amountCents\",\n \"discountableSubtotalCents\",\n \"discountCents\",\n \"serviceFeeCents\",\n \"subtotalCents\",\n \"tipCents\",\n \"totalCents\",\n] as const satisfies readonly (keyof LockerverseCheckoutQuote)[];\n\nexport function hasMaterialQuoteChange(\n displayed: LockerverseCheckoutQuote,\n current: LockerverseCheckoutQuote\n) {\n return (\n AMOUNT_KEYS.some((key) => displayed[key] !== current[key]) ||\n displayed.payment.connectedAccountId !==\n current.payment.connectedAccountId ||\n displayed.payment.currency !== current.payment.currency ||\n JSON.stringify(displayed.appliedDiscount) !==\n JSON.stringify(current.appliedDiscount) ||\n JSON.stringify(displayed.lineItems) !== JSON.stringify(current.lineItems)\n );\n}\n\nexport type PaymentAttemptOutcome =\n | { kind: \"failed\"; payment: LockerversePaymentResult }\n | { kind: \"success\"; payment: LockerversePaymentResult }\n | {\n kind: \"unresolved\";\n paymentReference: string;\n reason: \"action_required\" | \"pending\" | \"recovery_failed\";\n };\n\nfunction classifyPayment(\n payment: LockerversePaymentResult\n): PaymentAttemptOutcome {\n if (payment.checkoutStatus === \"success\") {\n return { kind: \"success\", payment };\n }\n if (payment.checkoutStatus === \"failed\") {\n return { kind: \"failed\", payment };\n }\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason:\n payment.checkoutStatus === \"action_required\"\n ? \"action_required\"\n : \"pending\",\n };\n}\n\nasync function settleRequiredAction(\n client: LockerverseCheckoutClient,\n payment: LockerversePaymentResult,\n stripe: Stripe\n): Promise<PaymentAttemptOutcome> {\n if (payment.checkoutStatus !== \"action_required\") {\n return classifyPayment(payment);\n }\n if (payment.clientSecret) {\n try {\n await stripe.handleNextAction({ clientSecret: payment.clientSecret });\n } catch {\n // Status recovery below is authoritative even when Stripe UI fails.\n }\n }\n try {\n const recovered = await client.getPaymentStatus(payment.paymentReference);\n return classifyPayment(recovered);\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason: \"action_required\",\n };\n }\n}\n\nexport async function submitPaymentAttempt(\n client: LockerverseCheckoutClient,\n input: LockerverseSubmitPaymentInput,\n stripe: Stripe\n): Promise<PaymentAttemptOutcome> {\n let payment: LockerversePaymentResult;\n try {\n payment = await client.submitPayment(input);\n } catch (error) {\n if (!(error instanceof LockerverseSdkError && error.recoveryRecommended)) {\n throw error;\n }\n try {\n payment = await client.getPaymentStatus(input.checkout.paymentReference);\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference: input.checkout.paymentReference,\n reason: \"recovery_failed\",\n };\n }\n }\n return settleRequiredAction(client, payment, stripe);\n}\n","import {\n array,\n minLength,\n minValue,\n nonEmpty,\n number,\n pipe,\n regex,\n safeInteger,\n safeParse,\n strictObject,\n string,\n transform,\n trim,\n union,\n} from \"valibot\";\n\nconst productSlugSchema = pipe(string(), trim(), nonEmpty());\nconst positiveSafeIntegerSchema = pipe(number(), safeInteger(), minValue(1));\n\nconst paymentSelectionSchema = pipe(\n array(\n union([\n strictObject({\n amountCents: positiveSafeIntegerSchema,\n productSlug: productSlugSchema,\n }),\n strictObject({\n productSlug: productSlugSchema,\n quantity: positiveSafeIntegerSchema,\n }),\n ])\n ),\n minLength(1)\n);\n\nconst customTipSchema = pipe(\n string(),\n trim(),\n regex(/^(?:0|[1-9]\\d*)(?:\\.\\d{1,2})?$/, \"Enter a valid tip amount.\"),\n transform((value) => Math.round(Number(value) * 100)),\n safeInteger(\"Enter a valid tip amount.\")\n);\n\nexport function parseCustomTipCents(input: string) {\n const result = safeParse(customTipSchema, input);\n return result.success\n ? ({ cents: result.output, success: true } as const)\n : ({\n message: result.issues[0]?.message ?? \"Enter a valid tip amount.\",\n success: false,\n } as const);\n}\n\nexport function parsePaymentSelection(input: unknown) {\n const result = safeParse(paymentSelectionSchema, input);\n return result.success\n ? ({ success: true, value: result.output } as const)\n : ({\n message: \"Lockerverse payment configuration is invalid.\",\n success: false,\n } as const);\n}\n","import type { LockerverseCustomField } from \"@lockerverse/sdk/checkout\";\nimport {\n array,\n email,\n minLength,\n nonEmpty,\n object,\n pipe,\n regex,\n safeParse,\n string,\n trim,\n} from \"valibot\";\n\nconst emailSchema = pipe(\n string(),\n trim(),\n nonEmpty(\"Email is required.\"),\n email(\"Enter a valid email address.\")\n);\n\nconst phoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(\"Phone is required.\"),\n regex(/^\\+[1-9]\\d{6,14}$/, \"Enter a valid phone number.\")\n);\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport type ContactErrors = {\n email?: string;\n phone?: string;\n};\n\nexport function validateContact(\n input: { email: string; phone: string },\n requiresPhone: boolean\n) {\n const normalizedInput = requiresPhone\n ? { ...input, phone: normalizePhone(input.phone) }\n : input;\n const schema = requiresPhone\n ? object({ email: emailSchema, phone: phoneSchema })\n : object({ email: emailSchema });\n const result = safeParse(schema, normalizedInput);\n\n if (result.success) {\n return { errors: {} as ContactErrors, value: result.output } as const;\n }\n\n const errors: ContactErrors = {};\n for (const issue of result.issues) {\n const field = issue.path?.[0]?.key;\n if ((field === \"email\" || field === \"phone\") && !errors[field]) {\n errors[field] = issue.message;\n }\n }\n return { errors, value: null } as const;\n}\n\nexport function validateCustomFields(\n fields: LockerverseCustomField[],\n values: Record<string, string | string[]>\n) {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (!field.required) {\n continue;\n }\n const message = `${field.label} is required.`;\n const value = values[field.id];\n const result =\n field.type === \"checkboxes\" || field.type === \"multi_select\"\n ? safeParse(pipe(array(string()), minLength(1, message)), value ?? [])\n : safeParse(\n pipe(string(), trim(), nonEmpty(message)),\n typeof value === \"string\" ? value : \"\"\n );\n if (!result.success) {\n errors[field.id] = result.issues[0]?.message ?? message;\n }\n }\n return errors;\n}\n","import type {\n CreateLockerverseWidgetOptions,\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutItem,\n LockerversePreparedCheckout,\n LockerverseProduct,\n} from \"@lockerverse/sdk/checkout\";\nimport { createLockerverseCheckoutClient } from \"@lockerverse/sdk/checkout\";\nimport { useEffect, useMemo, useReducer, useRef } from \"react\";\nimport { parsePaymentSelection } from \"./payment-input.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\nexport type CheckoutPaymentState =\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\";\n\ntype CheckoutConfiguration = {\n apiBaseUrl: LockerversePaymentProps[\"apiBaseUrl\"] | undefined;\n communitySlug: string;\n environment: LockerversePaymentProps[\"environment\"] | undefined;\n fetch: LockerversePaymentProps[\"fetch\"] | undefined;\n requestTimeoutMs: number | undefined;\n sentryDsn: string | null | undefined;\n widgetSlug: string;\n};\n\ntype SessionState =\n | { phase: \"idle\"; revision: number }\n | {\n configuration: CheckoutConfiguration;\n phase: \"loading\";\n revision: number;\n selectionKey: string;\n }\n | {\n configuration: CheckoutConfiguration;\n failure: string;\n phase: \"error\";\n revision: number;\n selectionKey: string;\n }\n | {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n configuration: CheckoutConfiguration;\n phase: \"ready\";\n preparedCheckout: LockerversePreparedCheckout;\n revision: number;\n selectionKey: string;\n };\n\ntype SessionAction =\n | {\n configuration: CheckoutConfiguration;\n selectionKey: string;\n type: \"loading\";\n }\n | {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n configuration: CheckoutConfiguration;\n preparedCheckout: LockerversePreparedCheckout;\n selectionKey: string;\n type: \"ready\";\n }\n | {\n configuration: CheckoutConfiguration;\n failure: string;\n selectionKey: string;\n type: \"error\";\n }\n | { preparedCheckout: LockerversePreparedCheckout; type: \"checkout\" };\n\ntype LoadIdentity = {\n configuration: CheckoutConfiguration;\n selectionKey: string;\n};\n\nfunction sessionReducer(\n state: SessionState,\n action: SessionAction\n): SessionState {\n switch (action.type) {\n case \"loading\":\n return {\n configuration: action.configuration,\n phase: \"loading\",\n revision: state.revision,\n selectionKey: action.selectionKey,\n };\n case \"ready\":\n return {\n catalog: action.catalog,\n checkoutItems: action.checkoutItems,\n client: action.client,\n configuration: action.configuration,\n phase: \"ready\",\n preparedCheckout: action.preparedCheckout,\n revision: state.revision + 1,\n selectionKey: action.selectionKey,\n };\n case \"error\":\n return {\n configuration: action.configuration,\n failure: action.failure,\n phase: \"error\",\n revision: state.revision,\n selectionKey: action.selectionKey,\n };\n case \"checkout\":\n return state.phase === \"ready\"\n ? { ...state, preparedCheckout: action.preparedCheckout }\n : state;\n default:\n return state;\n }\n}\n\nfunction buildCheckoutItem(\n product: LockerverseProduct,\n item: LockerversePaymentSelectionItem\n): LockerverseCheckoutItem {\n if (\"amountCents\" in item) {\n if (product.pricingMode !== \"custom\") {\n throw new TypeError(\"Fixed-price Products do not accept custom amounts.\");\n }\n if (\n product.minimumAmountCents !== null &&\n item.amountCents < product.minimumAmountCents\n ) {\n throw new TypeError(\n `Product amount must be at least ${product.minimumAmountCents} cents.`\n );\n }\n return { amountCents: item.amountCents, productId: product.id };\n }\n if (product.pricingMode !== \"fixed\") {\n throw new TypeError(\"Custom-amount Products do not accept quantities.\");\n }\n if (\n product.minimumQuantity !== null &&\n item.quantity < product.minimumQuantity\n ) {\n throw new TypeError(\n `Product quantity must be at least ${product.minimumQuantity}.`\n );\n }\n if (\n product.maximumQuantity !== null &&\n item.quantity > product.maximumQuantity\n ) {\n throw new TypeError(\n `Product quantity must not exceed ${product.maximumQuantity}.`\n );\n }\n if (\n product.inventoryQuantity !== null &&\n item.quantity > product.inventoryQuantity\n ) {\n throw new TypeError(\"Requested Product quantity is unavailable.\");\n }\n return { productId: product.id, quantity: item.quantity };\n}\n\nfunction buildCheckoutItems(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n): LockerverseCheckoutItem[] {\n if (selection.length === 0) {\n throw new TypeError(\"Lockerverse payment requires at least one Product.\");\n }\n return selection.map((item) => {\n const product = catalog.products.find(\n (candidate) => candidate.slug === item.productSlug\n );\n if (!product) {\n throw new TypeError(`Product ${item.productSlug} is not available.`);\n }\n return buildCheckoutItem(product, item);\n });\n}\n\nfunction createCheckoutOptions(\n configuration: CheckoutConfiguration,\n onError: LockerversePaymentProps[\"onError\"]\n): CreateLockerverseWidgetOptions {\n const {\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n } = configuration;\n const common = {\n communitySlug,\n widgetSlug,\n ...(fetch ? { fetch } : {}),\n ...(onError ? { onError } : {}),\n ...(requestTimeoutMs === undefined ? {} : { requestTimeoutMs }),\n ...(sentryDsn === undefined ? {} : { sentryDsn }),\n };\n if (apiBaseUrl === undefined) {\n if (environment === \"development\") {\n throw new TypeError(\n \"Lockerverse development checkout requires an API base URL.\"\n );\n }\n return {\n ...common,\n ...(environment === \"production\" ? { environment } : {}),\n };\n }\n if (!environment) {\n throw new TypeError(\n \"Lockerverse development checkout requires an environment.\"\n );\n }\n return { ...common, apiBaseUrl, environment };\n}\n\nfunction isSameLoad(\n identity: LoadIdentity | undefined,\n configuration: CheckoutConfiguration,\n selectionKey: string\n) {\n return (\n identity?.configuration === configuration &&\n identity.selectionKey === selectionKey\n );\n}\n\nexport function useCheckoutSession({\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n onError,\n paymentState,\n requestTimeoutMs,\n selection,\n sentryDsn,\n widgetSlug,\n}: CheckoutConfiguration & {\n onError: LockerversePaymentProps[\"onError\"];\n paymentState: CheckoutPaymentState;\n selection: LockerversePaymentProps[\"selection\"];\n}) {\n const configuration = useMemo<CheckoutConfiguration>(\n () => ({\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n }),\n [\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n requestTimeoutMs,\n sentryDsn,\n widgetSlug,\n ]\n );\n const parsedSelection = parsePaymentSelection(selection);\n const selectionKey = parsedSelection.success\n ? JSON.stringify(parsedSelection.value)\n : \"invalid-selection\";\n const stableSelection = useMemo(\n () =>\n parsedSelection.success\n ? (JSON.parse(selectionKey) as LockerversePaymentSelectionItem[])\n : [],\n [parsedSelection.success, selectionKey]\n );\n const [session, dispatch] = useReducer(sessionReducer, {\n phase: \"idle\",\n revision: 0,\n });\n const loadingRef = useRef<LoadIdentity | undefined>(undefined);\n const settledRef = useRef<LoadIdentity | undefined>(undefined);\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n useEffect(() => {\n if (!parsedSelection.success) {\n return;\n }\n if (\n paymentState === \"submitting\" ||\n paymentState === \"success\" ||\n paymentState === \"unresolved\" ||\n isSameLoad(settledRef.current, configuration, selectionKey) ||\n isSameLoad(loadingRef.current, configuration, selectionKey)\n ) {\n return;\n }\n\n let active = true;\n const identity = { configuration, selectionKey };\n loadingRef.current = identity;\n dispatch({ configuration, selectionKey, type: \"loading\" });\n\n async function loadPayment() {\n try {\n const client = createLockerverseCheckoutClient(\n createCheckoutOptions(configuration, (error) =>\n onErrorRef.current?.(error)\n )\n );\n const catalog = await client.load();\n const checkoutItems = buildCheckoutItems(catalog, stableSelection);\n const preparedCheckout = await client.calculateTotal({\n ...(catalog.widget.fields.serviceFee\n ? { includeServiceFee: true }\n : {}),\n items: checkoutItems,\n });\n if (active) {\n loadingRef.current = undefined;\n settledRef.current = identity;\n dispatch({\n catalog,\n checkoutItems,\n client,\n configuration,\n preparedCheckout,\n selectionKey,\n type: \"ready\",\n });\n }\n } catch (error) {\n if (active) {\n loadingRef.current = undefined;\n settledRef.current = identity;\n dispatch({\n configuration,\n failure:\n error instanceof Error\n ? error.message\n : \"Lockerverse payment could not load.\",\n selectionKey,\n type: \"error\",\n });\n }\n }\n }\n\n loadPayment();\n return () => {\n active = false;\n if (isSameLoad(loadingRef.current, configuration, selectionKey)) {\n loadingRef.current = undefined;\n }\n };\n }, [\n configuration,\n parsedSelection.success,\n paymentState,\n selectionKey,\n stableSelection,\n ]);\n\n return {\n selectionError: parsedSelection.success\n ? undefined\n : parsedSelection.message,\n session,\n updateCheckout: (preparedCheckout: LockerversePreparedCheckout) =>\n dispatch({ preparedCheckout, type: \"checkout\" }),\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutItem,\n LockerverseCustomField,\n LockerverseCustomFieldAnswer,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n AddressElement,\n Elements,\n PaymentElement,\n useElements,\n useStripe,\n} from \"@stripe/react-stripe-js\";\nimport type { Stripe, StripeElements } from \"@stripe/stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { getAccentContrast } from \"./accent-contrast.ts\";\nimport {\n AdditionalCheckoutFields,\n type CheckoutFieldValues,\n CheckoutToggle,\n ServiceFeeField,\n TipField,\n} from \"./checkout-fields.tsx\";\nimport {\n hasMaterialQuoteChange,\n submitPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport { parseCustomTipCents } from \"./payment-input.ts\";\nimport {\n normalizePhone,\n validateContact,\n validateCustomFields,\n} from \"./payment-validation.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\nimport {\n type CheckoutPaymentState,\n useCheckoutSession,\n} from \"./use-checkout-session.ts\";\n\nfunction formatMoney(amountCents: number) {\n return new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amountCents / 100);\n}\n\nfunction getTipCents(\n subtotalCents: number,\n values: Pick<CheckoutFieldValues, \"customTip\" | \"tipPercent\">\n) {\n if (values.tipPercent === \"custom\") {\n return parseCustomTipCents(values.customTip);\n }\n return {\n cents: Math.round((subtotalCents * Number(values.tipPercent)) / 100),\n success: true,\n } as const;\n}\n\nconst PHONE_COUNTRIES = [\n { callingCode: \"+1\", label: \"🇺🇸 +1\", value: \"US\" },\n { callingCode: \"+52\", label: \"🇲🇽 +52\", value: \"MX\" },\n { callingCode: \"+380\", label: \"🇺🇦 +380\", value: \"UA\" },\n { callingCode: \"+48\", label: \"🇵🇱 +48\", value: \"PL\" },\n { callingCode: \"+1\", label: \"🇨🇦 +1\", value: \"CA\" },\n { callingCode: \"+49\", label: \"🇩🇪 +49\", value: \"DE\" },\n { callingCode: \"+44\", label: \"🇬🇧 +44\", value: \"GB\" },\n { callingCode: \"+46\", label: \"🇸🇪 +46\", value: \"SE\" },\n { callingCode: \"+358\", label: \"🇫🇮 +358\", value: \"FI\" },\n { callingCode: \"+1\", label: \"🇵🇷 +1\", value: \"PR\" },\n] as const;\n\nfunction getInternationalPhone(phone: string, country: string) {\n if (phone.trim().startsWith(\"+\")) {\n return phone;\n }\n const callingCode =\n PHONE_COUNTRIES.find((option) => option.value === country)?.callingCode ??\n \"+1\";\n return `${callingCode}${phone}`;\n}\n\nfunction buildCustomFieldAnswers(\n fields: LockerverseCustomField[],\n values: Record<string, string | string[]>\n): LockerverseCustomFieldAnswer[] {\n return fields.map((field): LockerverseCustomFieldAnswer => {\n const value = values[field.id];\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return { fieldId: field.id, value: Array.isArray(value) ? value : [] };\n }\n return {\n fieldId: field.id,\n value: typeof value === \"string\" ? value : \"\",\n };\n });\n}\n\nfunction buildQuoteRequest(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n email: string,\n tipCents: number\n) {\n return {\n email,\n ...(catalog.widget.fields.serviceFee\n ? { includeServiceFee: fieldValues.includeServiceFee }\n : {}),\n ...(catalog.widget.fields.promoCode && fieldValues.promoCode.trim()\n ? { promoCode: fieldValues.promoCode.trim() }\n : {}),\n ...(catalog.widget.fields.tipping ? { tipCents } : {}),\n };\n}\n\nasync function getCompleteAddress(\n elements: StripeElements,\n mode: \"billing\" | \"shipping\"\n) {\n const addressElement = elements.getElement(\"address\", { mode });\n const label = mode === \"billing\" ? \"Billing\" : \"Shipping\";\n if (!addressElement) {\n throw new Error(`${label} address is still loading.`);\n }\n const address = await addressElement.getValue();\n if (!address.complete) {\n throw new Error(`${label} address is required.`);\n }\n return address.value;\n}\n\nfunction getShippingAddress(\n catalog: LockerverseCatalog,\n elements: StripeElements,\n fieldValues: CheckoutFieldValues,\n billingAddress: Awaited<ReturnType<typeof getCompleteAddress>>\n) {\n if (!catalog.widget.fields.shipping) {\n return;\n }\n return fieldValues.shippingMatchesBilling\n ? billingAddress\n : getCompleteAddress(elements, \"shipping\");\n}\n\nfunction buildConfirmationParams({\n billingAddress,\n catalog,\n email,\n phone,\n shippingAddress,\n}: {\n billingAddress: Awaited<ReturnType<typeof getCompleteAddress>>;\n catalog: LockerverseCatalog;\n email: string;\n phone: string;\n shippingAddress: Awaited<ReturnType<typeof getCompleteAddress>> | undefined;\n}) {\n return {\n payment_method_data: {\n billing_details: {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n ...(catalog.widget.fields.phone ? { phone } : {}),\n },\n },\n ...(shippingAddress\n ? {\n shipping: {\n address: shippingAddress.address,\n name: shippingAddress.name,\n phone: catalog.widget.fields.phone\n ? phone\n : (shippingAddress.phone ?? null),\n },\n }\n : {}),\n };\n}\n\nfunction buildPaymentRequest({\n catalog,\n confirmationToken,\n email,\n fieldValues,\n phone,\n}: {\n catalog: LockerverseCatalog;\n confirmationToken: string;\n email: string;\n fieldValues: CheckoutFieldValues;\n phone: string;\n}) {\n return {\n confirmationToken,\n customFieldAnswers: buildCustomFieldAnswers(\n catalog.widget.customFields,\n fieldValues.customFields\n ),\n email,\n ...(catalog.widget.fields.memberId && fieldValues.memberId.trim()\n ? { memberId: fieldValues.memberId.trim() }\n : {}),\n ...(catalog.widget.fields.merchSize\n ? { merchSize: fieldValues.merchSize }\n : {}),\n ...(catalog.widget.fields.phone ? { phone } : {}),\n };\n}\n\nasync function completePayment({\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n phone,\n quote,\n stripe,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n elements: StripeElements;\n email: string;\n fieldValues: CheckoutFieldValues;\n phone: string;\n quote: LockerversePreparedCheckout;\n stripe: Stripe;\n}) {\n const normalizedEmail = email.trim().toLowerCase();\n const normalizedPhone = normalizePhone(phone);\n const parsedTip = getTipCents(quote.subtotalCents, fieldValues);\n if (!parsedTip.success) {\n throw new Error(parsedTip.message);\n }\n const pricing = buildQuoteRequest(\n catalog,\n fieldValues,\n normalizedEmail,\n parsedTip.cents\n );\n const currentQuote = await client.calculateTotal({\n ...pricing,\n items: checkoutItems,\n });\n await elements.update({ amount: currentQuote.totalCents });\n if (hasMaterialQuoteChange(quote, currentQuote)) {\n return { kind: \"quote_changed\" as const, quote: currentQuote };\n }\n\n const elementSubmission = await elements.submit();\n if (elementSubmission.error) {\n throw new Error(elementSubmission.error.message);\n }\n\n const billingAddress = await getCompleteAddress(elements, \"billing\");\n const shippingAddress = await getShippingAddress(\n catalog,\n elements,\n fieldValues,\n billingAddress\n );\n\n const tokenResult = await stripe.createConfirmationToken({\n elements,\n params: buildConfirmationParams({\n billingAddress,\n catalog,\n email: normalizedEmail,\n phone: normalizedPhone,\n shippingAddress,\n }),\n });\n if (tokenResult.error) {\n throw new Error(tokenResult.error.message);\n }\n\n const outcome = await submitPaymentAttempt(\n client,\n {\n checkout: currentQuote,\n submission: buildPaymentRequest({\n catalog,\n confirmationToken: tokenResult.confirmationToken.id,\n email: normalizedEmail,\n fieldValues,\n phone: normalizedPhone,\n }),\n },\n stripe\n );\n if (outcome.kind === \"failed\") {\n return {\n kind: \"payment_failed\" as const,\n message:\n \"Payment was declined. Check your payment details and try again.\",\n };\n }\n if (outcome.kind === \"unresolved\") {\n return {\n kind: \"payment_unresolved\" as const,\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n };\n }\n return {\n kind: \"payment\" as const,\n payment: outcome.payment,\n quote: currentQuote,\n };\n}\n\nfunction ReadyPayment({\n accentColor,\n catalog,\n checkoutItems,\n client,\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n quote,\n onStateChange,\n stripeLoader,\n theme,\n}: {\n accentColor: string;\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n quote: LockerversePreparedCheckout;\n onStateChange: (\n state:\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\"\n ) => void;\n stripeLoader: typeof loadStripe;\n theme: LockerversePaymentProps[\"theme\"];\n}) {\n const stripe = useMemo(\n () =>\n stripeLoader(\n catalog.payment.publishableKey,\n quote.payment.connectedAccountId\n ? { stripeAccount: quote.payment.connectedAccountId }\n : undefined\n ),\n [\n catalog.payment.publishableKey,\n quote.payment.connectedAccountId,\n stripeLoader,\n ]\n );\n\n return (\n <Elements\n key={`${catalog.payment.publishableKey}:${quote.payment.connectedAccountId ?? \"platform\"}`}\n options={{\n amount: quote.totalCents,\n appearance: {\n rules: {\n \".Input:focus\": {\n borderColor: accentColor,\n boxShadow: \"none\",\n outline: \"none\",\n },\n },\n theme: theme === \"light\" ? \"stripe\" : \"night\",\n variables: {\n borderRadius: \"8px\",\n colorBackground: theme === \"light\" ? \"#f5f6f7\" : \"#101010\",\n colorDanger: theme === \"light\" ? \"#c52b3e\" : \"#ef4444\",\n colorPrimary: accentColor,\n colorText: theme === \"light\" ? \"#121416\" : \"#ffffff\",\n colorTextPlaceholder: theme === \"light\" ? \"#72767d\" : \"#6b6b6b\",\n colorTextSecondary: theme === \"light\" ? \"#62666d\" : \"#a1a1aa\",\n focusBoxShadow: \"none\",\n focusOutline: \"none\",\n fontFamily:\n \"Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif\",\n fontSizeBase: \"16px\",\n },\n },\n currency: quote.payment.currency,\n excludedPaymentMethodTypes: [\"us_bank_account\"],\n mode: \"payment\",\n syncAddressCheckbox: \"none\",\n }}\n stripe={stripe}\n >\n <PaymentForm\n catalog={catalog}\n checkoutItems={checkoutItems}\n client={client}\n onPaymentComplete={onPaymentComplete}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={onQuoteChange}\n onStateChange={onStateChange}\n quote={quote}\n />\n </Elements>\n );\n}\n\nfunction StripeElementLoader({ label }: { label: string }) {\n return (\n <div className=\"lockerverse-payment__stripe-loader\" role=\"status\">\n <p>{label}</p>\n <div aria-hidden=\"true\">\n <span />\n <span />\n <span />\n </div>\n </div>\n );\n}\n\nfunction StripePaymentField({\n onError,\n onReady,\n ready,\n}: {\n onError: (message: string) => void;\n onReady: () => void;\n ready: boolean;\n}) {\n return (\n <div className=\"lockerverse-payment__stripe-element\" data-ready={ready}>\n {ready ? null : <StripeElementLoader label=\"Loading payment form...\" />}\n <PaymentElement\n onLoadError={({ error }) =>\n onError(error.message ?? \"Payment form failed to load.\")\n }\n onReady={onReady}\n options={{\n business: { name: \"Lockerverse\" },\n fields: { billingDetails: { email: \"auto\" } },\n layout: \"tabs\",\n terms: {\n applePay: \"auto\",\n auBecsDebit: \"never\",\n bancontact: \"never\",\n card: \"always\",\n cashapp: \"never\",\n googlePay: \"never\",\n ideal: \"never\",\n paypal: \"auto\",\n sepaDebit: \"never\",\n sofort: \"never\",\n usBankAccount: \"never\",\n },\n wallets: { applePay: \"auto\", googlePay: \"never\" },\n }}\n />\n </div>\n );\n}\n\nfunction StripeAddressField({\n label,\n mode,\n onError,\n onReady,\n ready,\n}: {\n label: string;\n mode: \"billing\" | \"shipping\";\n onError: (message: string) => void;\n onReady: () => void;\n ready: boolean;\n}) {\n return (\n <div className=\"lockerverse-payment__address\">\n <h2>{label}</h2>\n <div\n className=\"lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address\"\n data-ready={ready}\n >\n {ready ? null : (\n <StripeElementLoader label={`Loading ${label.toLowerCase()}...`} />\n )}\n <AddressElement\n onLoadError={({ error }) =>\n onError(error.message ?? `${label} failed to load.`)\n }\n onReady={onReady}\n options={{ autocomplete: { mode: \"automatic\" }, mode }}\n />\n </div>\n </div>\n );\n}\n\nfunction PaymentErrorMessage({ message }: { message: string | undefined }) {\n if (!message) {\n return null;\n }\n return (\n <p className=\"lockerverse-payment__field-message\" role=\"alert\">\n {message}\n </p>\n );\n}\n\ntype PaymentUiState =\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\";\n\ntype PaymentTerminalState = {\n kind: \"success\" | \"unresolved\";\n message: string;\n};\n\ntype CompletePaymentResult = Awaited<ReturnType<typeof completePayment>>;\n\nfunction focusFirstValidationError({\n customFieldErrors,\n emailRef,\n form,\n parsedTipSuccess,\n phoneRef,\n validationErrors,\n}: {\n customFieldErrors: Record<string, string>;\n emailRef: React.RefObject<HTMLInputElement | null>;\n form: HTMLFormElement;\n parsedTipSuccess: boolean;\n phoneRef: React.RefObject<HTMLInputElement | null>;\n validationErrors: { email?: string; phone?: string };\n}) {\n if (validationErrors.email) {\n emailRef.current?.focus();\n return;\n }\n if (validationErrors.phone) {\n phoneRef.current?.focus();\n return;\n }\n if (!parsedTipSuccess) {\n form.querySelector<HTMLElement>('[name=\"tip\"]')?.focus();\n return;\n }\n const [firstFieldId] = Object.keys(customFieldErrors);\n if (firstFieldId) {\n form.querySelector<HTMLElement>(`[name=\"custom:${firstFieldId}\"]`)?.focus();\n }\n}\n\nfunction applyPaymentOutcome({\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n result,\n setDisplayedTotalCents,\n setPaymentError,\n setTerminalState,\n}: {\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n result: CompletePaymentResult;\n setDisplayedTotalCents: (total: number) => void;\n setPaymentError: (message: string) => void;\n setTerminalState: (state: PaymentTerminalState) => void;\n}) {\n if (result.kind === \"quote_changed\") {\n const notice = `The total changed to ${formatMoney(result.quote.totalCents)}. Review it and pay again.`;\n onQuoteChange(result.quote, notice);\n setDisplayedTotalCents(result.quote.totalCents);\n onStateChange(\"idle\");\n return;\n }\n if (result.kind === \"payment_failed\") {\n setPaymentError(result.message);\n onStateChange(\"error\");\n return;\n }\n if (result.kind === \"payment_unresolved\") {\n setTerminalState({\n kind: \"unresolved\",\n message: \"Payment is still processing. Do not submit it again.\",\n });\n onStateChange(\"unresolved\");\n try {\n onPaymentUncertain?.({\n paymentReference: result.paymentReference,\n reason: result.reason,\n });\n } catch {\n // Host callback failures must not unlock an uncertain payment.\n }\n return;\n }\n onQuoteChange(result.quote);\n setTerminalState({\n kind: \"success\",\n message: \"Payment completed successfully.\",\n });\n onStateChange(\"success\");\n try {\n onPaymentComplete?.(result.payment);\n } catch {\n // Host callback failures must not turn a completed payment into an error.\n }\n}\n\nfunction ContactFields({\n email,\n emailErrorId,\n emailId,\n emailRef,\n errors,\n onEmailChange,\n onPhoneChange,\n onPhoneCountryChange,\n phone,\n phoneCountry,\n phoneEnabled,\n phoneErrorId,\n phoneId,\n phoneRef,\n}: {\n email: string;\n emailErrorId: string;\n emailId: string;\n emailRef: React.RefObject<HTMLInputElement | null>;\n errors: { email?: string; phone?: string };\n onEmailChange: (value: string) => void;\n onPhoneChange: (value: string) => void;\n onPhoneCountryChange: (value: string) => void;\n phone: string;\n phoneCountry: string;\n phoneEnabled: boolean;\n phoneErrorId: string;\n phoneId: string;\n phoneRef: React.RefObject<HTMLInputElement | null>;\n}) {\n return (\n <div className=\"lockerverse-payment__contact\">\n <label htmlFor={emailId}>Email</label>\n <input\n aria-describedby={errors.email ? emailErrorId : undefined}\n aria-invalid={errors.email ? \"true\" : undefined}\n autoComplete=\"email\"\n id={emailId}\n name=\"email\"\n onChange={(event) => onEmailChange(event.currentTarget.value)}\n placeholder=\"name@example.com\"\n ref={emailRef}\n type=\"email\"\n value={email}\n />\n {errors.email ? (\n <p className=\"lockerverse-payment__field-message\" id={emailErrorId}>\n {errors.email}\n </p>\n ) : null}\n {phoneEnabled ? (\n <>\n <label htmlFor={phoneId}>Phone</label>\n <div className=\"lockerverse-payment__phone-control\">\n <select\n aria-label=\"Phone number country\"\n name=\"phoneCountry\"\n onChange={(event) =>\n onPhoneCountryChange(event.currentTarget.value)\n }\n value={phoneCountry}\n >\n {PHONE_COUNTRIES.map((country) => (\n <option key={country.value} value={country.value}>\n {country.label}\n </option>\n ))}\n </select>\n <input\n aria-describedby={errors.phone ? phoneErrorId : undefined}\n aria-invalid={errors.phone ? \"true\" : undefined}\n autoComplete=\"tel\"\n id={phoneId}\n inputMode=\"tel\"\n name=\"phone\"\n onChange={(event) => onPhoneChange(event.currentTarget.value)}\n placeholder=\"(201) 555-0123\"\n ref={phoneRef}\n type=\"tel\"\n value={phone}\n />\n </div>\n {errors.phone ? (\n <p className=\"lockerverse-payment__field-message\" id={phoneErrorId}>\n {errors.phone}\n </p>\n ) : null}\n </>\n ) : null}\n </div>\n );\n}\n\nfunction PaymentForm({\n catalog,\n checkoutItems,\n client,\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerversePreparedCheckout;\n}) {\n const [email, setEmail] = useState(\"\");\n const [phone, setPhone] = useState(\"\");\n const [phoneCountry, setPhoneCountry] = useState(\"US\");\n const [errors, setErrors] = useState<{ email?: string; phone?: string }>({});\n const [paymentError, setPaymentError] = useState<string>();\n const [customFieldErrors, setCustomFieldErrors] = useState<\n Record<string, string>\n >({});\n const [tipError, setTipError] = useState<string>();\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [terminalState, setTerminalState] = useState<PaymentTerminalState>();\n const [isPaymentReady, setIsPaymentReady] = useState(false);\n const [isBillingAddressReady, setIsBillingAddressReady] = useState(false);\n const [isShippingAddressReady, setIsShippingAddressReady] = useState(false);\n const [fieldValues, setFieldValues] = useState<CheckoutFieldValues>({\n customFields: {},\n customTip: \"\",\n includeServiceFee: catalog.widget.fields.serviceFee,\n memberId: \"\",\n merchSize: \"M\",\n promoCode: \"\",\n shippingMatchesBilling: true,\n tipPercent: \"10\",\n });\n const [displayedTotalCents, setDisplayedTotalCents] = useState(\n quote.totalCents\n );\n const emailRef = useRef<HTMLInputElement>(null);\n const phoneRef = useRef<HTMLInputElement>(null);\n const statusRef = useRef<HTMLParagraphElement>(null);\n const elements = useElements();\n const stripe = useStripe();\n const idPrefix = `lockerverse-${useId()}`;\n const emailId = `${idPrefix}-email`;\n const emailErrorId = `${emailId}-error`;\n const phoneId = `${idPrefix}-phone`;\n const phoneErrorId = `${phoneId}-error`;\n const tipErrorId = `${idPrefix}-tip-error`;\n const parsedTip = catalog.widget.fields.tipping\n ? getTipCents(quote.subtotalCents, fieldValues)\n : ({ cents: 0, success: true } as const);\n const parsedTipCents = parsedTip.success ? parsedTip.cents : null;\n const displayedTipCents = parsedTipCents ?? 0;\n const displayedBaseCents = displayedTotalCents - displayedTipCents;\n const isRequiredShippingReady =\n !catalog.widget.fields.shipping ||\n fieldValues.shippingMatchesBilling ||\n isShippingAddressReady;\n\n useEffect(() => {\n if (parsedTipCents === null) {\n return;\n }\n const previewServiceFeeCents =\n catalog.widget.fields.serviceFee && fieldValues.includeServiceFee\n ? quote.serviceFeeCents ||\n Math.round(\n (quote.subtotalCents *\n catalog.pricingPolicy.serviceFeeRateBasisPoints) /\n 10_000\n )\n : 0;\n const previewTotalCents =\n quote.totalCents -\n quote.serviceFeeCents -\n quote.tipCents +\n previewServiceFeeCents +\n parsedTipCents;\n setDisplayedTotalCents(previewTotalCents);\n elements?.update({ amount: previewTotalCents });\n }, [\n catalog.widget.fields.serviceFee,\n catalog.widget.fields.tipping,\n elements,\n fieldValues.includeServiceFee,\n fieldValues.tipPercent,\n fieldValues.customTip,\n parsedTipCents,\n quote.serviceFeeCents,\n quote.tipCents,\n quote.totalCents,\n ]);\n\n useEffect(() => {\n if (isSubmitting) {\n statusRef.current?.focus();\n }\n }, [isSubmitting]);\n\n function clearError(field: \"email\" | \"phone\") {\n setErrors((current) => {\n const next = { ...current };\n delete next[field];\n return next;\n });\n }\n\n function handleFieldValuesChange(nextValues: CheckoutFieldValues) {\n setFieldValues(nextValues);\n setCustomFieldErrors({});\n setTipError(undefined);\n }\n\n function handleStripeLoadError(message: string) {\n setPaymentError(message);\n onStateChange(\"error\");\n }\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const validation = validateContact(\n { email, phone: getInternationalPhone(phone, phoneCountry) },\n catalog.widget.fields.phone\n );\n const nextCustomFieldErrors = validateCustomFields(\n catalog.widget.customFields,\n fieldValues.customFields\n );\n if (\n !(validation.value && parsedTip.success) ||\n Object.keys(nextCustomFieldErrors).length > 0\n ) {\n setErrors(validation.errors);\n setCustomFieldErrors(nextCustomFieldErrors);\n setTipError(parsedTip.success ? undefined : parsedTip.message);\n onStateChange(\"invalid\");\n const form = event.currentTarget;\n queueMicrotask(() => {\n focusFirstValidationError({\n customFieldErrors: nextCustomFieldErrors,\n emailRef,\n form,\n parsedTipSuccess: parsedTip.success,\n phoneRef,\n validationErrors: validation.errors,\n });\n });\n return;\n }\n\n setErrors({});\n setCustomFieldErrors({});\n\n if (!(elements && stripe)) {\n setPaymentError(\"Payment form is still loading.\");\n onStateChange(\"error\");\n return;\n }\n\n setPaymentError(undefined);\n setIsSubmitting(true);\n onStateChange(\"submitting\");\n\n try {\n const result = await completePayment({\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n phone: getInternationalPhone(phone, phoneCountry),\n quote,\n stripe,\n });\n applyPaymentOutcome({\n onPaymentComplete,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n result,\n setDisplayedTotalCents,\n setPaymentError,\n setTerminalState,\n });\n } catch (error) {\n setPaymentError(\n error instanceof Error\n ? error.message\n : \"Payment could not be completed.\"\n );\n onStateChange(\"error\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n if (terminalState) {\n return (\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {terminalState.message}\n </p>\n );\n }\n\n return (\n <form\n aria-busy={isSubmitting}\n className=\"lockerverse-payment__form\"\n noValidate\n onSubmit={handleSubmit}\n >\n <div\n data-lockerverse-input-region=\"\"\n inert={isSubmitting ? true : undefined}\n >\n <fieldset\n className=\"lockerverse-payment__input-fieldset\"\n disabled={isSubmitting}\n >\n <TipField\n enabled={catalog.widget.fields.tipping}\n error={tipError}\n errorId={tipErrorId}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <ContactFields\n email={email}\n emailErrorId={emailErrorId}\n emailId={emailId}\n emailRef={emailRef}\n errors={errors}\n onEmailChange={(value) => {\n setEmail(value);\n clearError(\"email\");\n }}\n onPhoneChange={(value) => {\n setPhone(value);\n clearError(\"phone\");\n }}\n onPhoneCountryChange={setPhoneCountry}\n phone={phone}\n phoneCountry={phoneCountry}\n phoneEnabled={catalog.widget.fields.phone}\n phoneErrorId={phoneErrorId}\n phoneId={phoneId}\n phoneRef={phoneRef}\n />\n <StripePaymentField\n onError={handleStripeLoadError}\n onReady={() => setIsPaymentReady(true)}\n ready={isPaymentReady}\n />\n <StripeAddressField\n label=\"Billing address\"\n mode=\"billing\"\n onError={handleStripeLoadError}\n onReady={() => setIsBillingAddressReady(true)}\n ready={isBillingAddressReady}\n />\n {catalog.widget.fields.shipping ? (\n <div className=\"lockerverse-payment__shipping\">\n <CheckoutToggle\n checked={fieldValues.shippingMatchesBilling}\n name=\"shippingMatchesBilling\"\n onChange={(shippingMatchesBilling) => {\n handleFieldValuesChange({\n ...fieldValues,\n shippingMatchesBilling,\n });\n if (!shippingMatchesBilling) {\n setIsShippingAddressReady(false);\n }\n }}\n >\n Shipping is same as billing information\n </CheckoutToggle>\n {fieldValues.shippingMatchesBilling ? null : (\n <StripeAddressField\n label=\"Shipping address\"\n mode=\"shipping\"\n onError={handleStripeLoadError}\n onReady={() => setIsShippingAddressReady(true)}\n ready={isShippingAddressReady}\n />\n )}\n </div>\n ) : null}\n <AdditionalCheckoutFields\n customFields={catalog.widget.customFields}\n errors={customFieldErrors}\n fields={catalog.widget.fields}\n idPrefix={idPrefix}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <div className=\"lockerverse-payment__actions\">\n <ServiceFeeField\n amountCents={\n quote.serviceFeeCents ||\n Math.round(\n (quote.subtotalCents *\n catalog.pricingPolicy.serviceFeeRateBasisPoints) /\n 10_000\n )\n }\n enabled={catalog.widget.fields.serviceFee}\n onChange={handleFieldValuesChange}\n values={fieldValues}\n />\n <button\n aria-busy={isSubmitting}\n aria-label={`Process payment for ${formatMoney(displayedTotalCents)} total`}\n disabled={\n isSubmitting ||\n !(\n isPaymentReady &&\n isBillingAddressReady &&\n isRequiredShippingReady\n )\n }\n type=\"submit\"\n >\n {isSubmitting\n ? \"Processing…\"\n : `Process Payment (${formatMoney(displayedBaseCents)})${\n displayedTipCents > 0\n ? ` + ${formatMoney(displayedTipCents)} tip`\n : \"\"\n }`}\n </button>\n </div>\n </fieldset>\n </div>\n {isSubmitting ? (\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n Processing payment…\n </p>\n ) : null}\n <PaymentErrorMessage message={paymentError} />\n </form>\n );\n}\n\nfunction SkeletonLoaderBlock() {\n return (\n <div className=\"lockerverse-payment__skeleton-loader-block\">\n <span className=\"lockerverse-payment__skeleton-loader-label\" />\n <div className=\"lockerverse-payment__skeleton-loader-content\">\n <span className=\"lockerverse-payment__skeleton-loader-full\" />\n <div className=\"lockerverse-payment__skeleton-loader-grid\">\n <span className=\"lockerverse-payment__skeleton-loader-half\" />\n <span className=\"lockerverse-payment__skeleton-loader-half\" />\n </div>\n </div>\n </div>\n );\n}\n\nfunction PaymentSkeleton() {\n return (\n <div className=\"lockerverse-payment__loading\">\n <span\n aria-live=\"polite\"\n className=\"lockerverse-payment__sr-only\"\n role=\"status\"\n >\n Loading payment…\n </span>\n <div aria-hidden=\"true\" className=\"lockerverse-payment__skeleton\">\n <div className=\"lockerverse-payment__skeleton-branding\">\n <span className=\"lockerverse-payment__skeleton-avatar\" />\n <span className=\"lockerverse-payment__skeleton-community\" />\n </div>\n <div className=\"lockerverse-payment__skeleton-contact\">\n <div className=\"lockerverse-payment__skeleton-field\">\n <span className=\"lockerverse-payment__skeleton-label\" />\n <span className=\"lockerverse-payment__skeleton-input\" />\n </div>\n <div className=\"lockerverse-payment__skeleton-field\">\n <span className=\"lockerverse-payment__skeleton-label\" />\n <span className=\"lockerverse-payment__skeleton-input\" />\n </div>\n </div>\n <SkeletonLoaderBlock />\n <SkeletonLoaderBlock />\n <div className=\"lockerverse-payment__skeleton-actions\">\n <span className=\"lockerverse-payment__skeleton-check-line\" />\n <span className=\"lockerverse-payment__skeleton-button\" />\n </div>\n </div>\n </div>\n );\n}\n\nexport function LockerversePayment({\n apiBaseUrl,\n branding,\n className,\n communitySlug,\n environment,\n fetch,\n onError,\n onPaymentComplete,\n onPaymentUncertain,\n requestTimeoutMs,\n selection,\n sentryDsn,\n style,\n stripeLoader = loadStripe,\n theme = \"dark\",\n widgetSlug,\n ...sectionProps\n}: LockerversePaymentProps) {\n const [notice, setNotice] = useState<string>();\n const [paymentState, setPaymentState] =\n useState<CheckoutPaymentState>(\"idle\");\n const { selectionError, session, updateCheckout } = useCheckoutSession({\n apiBaseUrl,\n communitySlug,\n environment,\n fetch,\n onError,\n paymentState,\n requestTimeoutMs,\n selection,\n sentryDsn,\n widgetSlug,\n });\n\n useEffect(() => {\n if (session.phase === \"loading\") {\n setNotice(undefined);\n }\n }, [session.phase]);\n\n useEffect(() => {\n if (session.phase === \"ready\") {\n setPaymentState((current) =>\n current === \"success\" || current === \"unresolved\" ? current : \"idle\"\n );\n }\n }, [session.phase, session.revision]);\n\n const rootClassName = [\"lockerverse-payment\", className]\n .filter(Boolean)\n .join(\" \");\n const effectiveAccent =\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\";\n const automaticAccentContrast = getAccentContrast(effectiveAccent);\n const rootStyle: LockerversePaymentProps[\"style\"] = {\n ...style,\n ...(branding?.accentColor && style?.[\"--lockerverse-accent\"] === undefined\n ? { \"--lockerverse-accent\": branding.accentColor }\n : {}),\n ...(automaticAccentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ? { \"--lockerverse-accent-contrast\": automaticAccentContrast }\n : {}),\n };\n\n if (selectionError) {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n style={rootStyle}\n >\n {selectionError}\n </section>\n );\n }\n\n if (session.phase === \"error\") {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n >\n {session.failure}\n </section>\n );\n }\n\n if (session.phase !== \"ready\") {\n return (\n <section\n {...sectionProps}\n aria-busy=\"true\"\n aria-label=\"Payment\"\n className={rootClassName}\n data-lockerverse-theme={theme}\n >\n <PaymentSkeleton />\n </section>\n );\n }\n\n const { catalog, checkoutItems, client, preparedCheckout } = session;\n\n return (\n <section\n {...sectionProps}\n aria-label=\"Payment\"\n className={rootClassName}\n data-lockerverse-theme={theme}\n data-payment-state={paymentState}\n style={rootStyle}\n >\n <header>\n {catalog.widget.showCommunityBranding && branding ? (\n <div className=\"lockerverse-payment__branding\">\n {branding.imageUrl ? (\n <img\n alt={branding.name}\n height=\"48\"\n src={branding.imageUrl}\n width=\"48\"\n />\n ) : null}\n <strong>{branding.name}</strong>\n </div>\n ) : null}\n <h1>{catalog.widget.title ?? catalog.widget.name}</h1>\n {catalog.widget.description ? (\n <p>{catalog.widget.description}</p>\n ) : null}\n </header>\n {notice ? (\n <p className=\"lockerverse-payment__payment-status\" role=\"status\">\n {notice}\n </p>\n ) : null}\n <ReadyPayment\n accentColor={\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n }\n catalog={catalog}\n checkoutItems={checkoutItems}\n client={client}\n onPaymentComplete={onPaymentComplete}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={(nextQuote, nextNotice) => {\n setNotice(nextNotice);\n updateCheckout(nextQuote);\n }}\n onStateChange={setPaymentState}\n quote={preparedCheckout}\n stripeLoader={stripeLoader}\n theme={theme}\n />\n </section>\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lockerverse/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "React payment UI for Lockerverse",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"valibot": "1.4.2",
|
|
33
|
-
"@lockerverse/sdk": "0.
|
|
33
|
+
"@lockerverse/sdk": "0.2.18"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@size-limit/file": "13.0.3",
|