@lockerverse/react 0.2.171-dev.1 → 0.2.173

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/MIGRATIONS.md CHANGED
@@ -36,7 +36,46 @@ If it cannot be found, report that limit and use the baseline review below. Do n
36
36
  claim that every historical migration was applied. Read this file even if the
37
37
  version already matches: a previous upgrade may have missed host adoption steps.
38
38
 
39
- ## 0.2.171-dev.1 — SDK payment recovery and completion UI
39
+ ## 0.2.173 — widget ACH and SDK checkout UI
40
+
41
+ ### Bank authorization terms
42
+
43
+ - **Affected:** React payment widgets with ACH enabled.
44
+ - **Automatic:** Stripe displays its bank authorization terms before payment confirmation.
45
+ - **Adoption:** update the matching SDK/React pair. No prop changes are required.
46
+ - **Check:** confirm that the bank authorization text is visible when a bank account is selected.
47
+
48
+ ### Widget ACH and subscription payment recovery
49
+
50
+ - **Affected:** Core checkout data and React payment widgets.
51
+ - **Automatic:** bank payment availability follows the stored community setting
52
+ returned by the backend. Missing policy remains disabled.
53
+ Pending payments keep their existing payment reference. A failed subscription
54
+ invoice can return `action_required` with `requiresAction: false` and `retryUrl`;
55
+ React shows a link to pay the same invoice instead of creating a second subscription.
56
+ Bank microdeposit verification uses the same recovery link for Stripe's hosted
57
+ verification page.
58
+ - **Required for custom payment UI:** preserve the reference for pending and
59
+ action-required results. Handle `retryUrl` by opening the provider recovery page, and recover
60
+ status before permitting a new checkout. Do not treat submission as settlement.
61
+ - **Adoption:** deploy the matching backend policy and recovery contract before
62
+ enabling ACH. Existing React hosts need no component prop changes. Keep Core and
63
+ React versions matched when upgrading. Auction payment methods are unchanged.
64
+ - **Check:** verify disabled/enabled bank visibility and pending, bank
65
+ verification, invoice retry, success, and terminal failure in Stripe test mode.
66
+ Do not create a live transaction for this check.
67
+
68
+ ### Check pending payment status
69
+
70
+ - **Affected:** React payment widgets with unresolved payments.
71
+ - **Automatic behavior:** the existing pending-payment screen now offers Check
72
+ payment status. It checks the saved payment reference and cannot submit a new
73
+ payment. The control is disabled while the check runs.
74
+ - **Required host changes:** none. Update Core and React together.
75
+ - **Verification:** complete a test bank payment, return to its pending checkout,
76
+ and check its status. Confirm completion clears recovery storage.
77
+
78
+ ### SDK payment recovery and completion UI
40
79
 
41
80
  - **Affected:** React payment widgets and custom hosts that persist payment recovery.
42
81
  - **Optional adoption:** pass `recoveryStorageKey` to `LockerversePayment` to let
@@ -58,7 +97,7 @@ version already matches: a previous upgrade may have missed host adoption steps.
58
97
  verify a changed selection cannot discard it. Check both paid and free order
59
98
  confirmation panels. Do not submit a live transaction for this check.
60
99
 
61
- ## 0.2.169-dev.1 — six-month payment widgets
100
+ ## 0.2.170 — six-month payment widgets
62
101
 
63
102
  Affected: @lockerverse/sdk checkout and @lockerverse/react payment widgets.
64
103
 
@@ -74,31 +113,6 @@ Affected: @lockerverse/sdk checkout and @lockerverse/react payment widgets.
74
113
  submission. Do not submit a live payment for an integration check.
75
114
 
76
115
 
77
- ## 0.2.168-dev.1 — bank authorization terms
78
-
79
- - **Affected:** React payment widgets with ACH enabled.
80
- - **Automatic:** Stripe displays its bank authorization terms before payment confirmation.
81
- - **Adoption:** update the matching SDK/React development pair. No prop changes are required.
82
- - **Check:** confirm that the bank authorization text is visible when a bank account is selected.
83
-
84
- ## 0.2.167-dev.1 — widget ACH and subscription payment recovery
85
-
86
- - **Affected:** Core checkout data and React payment widgets.
87
- - **Automatic:** bank payment availability follows the organization default and
88
- community override returned by the backend. Missing policy remains disabled.
89
- Pending payments keep their existing payment reference. A failed subscription
90
- invoice can return `action_required` with `requiresAction: false` and `retryUrl`;
91
- React shows a link to pay the same invoice instead of creating a second subscription.
92
- - **Required for custom payment UI:** preserve the reference for pending and
93
- action-required results. Handle `retryUrl` by opening that invoice, and recover
94
- status before permitting a new checkout. Do not treat submission as settlement.
95
- - **Adoption:** deploy the matching backend policy and recovery contract before
96
- enabling ACH. Existing React hosts need no component prop changes. Keep Core and
97
- React versions matched when upgrading. Auction payment methods are unchanged.
98
- - **Check:** verify disabled/inherited/enabled bank visibility and pending, bank
99
- verification, invoice retry, success, and terminal failure in Stripe test mode.
100
- Do not create a live transaction for this check.
101
-
102
116
  ## 0.2.166 — single dropdown arrow
103
117
 
104
118
  - **Affected:** native single-select custom fields in React signup and payment forms.
@@ -1,2 +1,2 @@
1
- import{t as e}from"./format-money.js";import{t}from"./host-callback.js";import{n,t as r}from"./accent-contrast.js";import{d as i,i as a,n as o,p as s,t as c,u as l}from"./phone-field.js";import{a as u,i as d,n as f,r as p,s as m}from"./custom-fields.js";import{t as h}from"./form-skeleton.js";import{t as g}from"./payment-summary.js";import{i as _,n as v,r as y,t as b}from"./stripe-loader.js";import{useCallback as x,useEffect as S,useId as C,useLayoutEffect as w,useMemo as T,useReducer as E,useRef as D,useState as O}from"react";import{Fragment as k,jsx as A,jsxs as j}from"react/jsx-runtime";import{LockerverseSdkError as M,estimateLockerverseCheckout as N}from"@lockerverse/sdk/checkout";import{AddressElement as P,Elements as F,PaymentElement as I,useElements as L,useStripe as R}from"@stripe/react-stripe-js";import{array as z,literal as B,minLength as V,minValue as H,nonEmpty as ee,nullable as te,number as ne,object as U,optional as W,pipe as G,regex as K,safeInteger as re,safeParse as q,strictObject as ie,string as J,trim as ae,union as oe}from"valibot";function se({ariaDescribedBy:e,ariaLabel:t,ariaLabelledBy:n,className:r,id:i,invalid:a=!1,name:o,onValueChange:s,options:c,value:l}){return A(`select`,{"aria-describedby":e,"aria-invalid":a||void 0,"aria-label":t,"aria-labelledby":n,className:[`lockerverse-form__control`,`lockerverse-form__select`,r].filter(Boolean).join(` `),id:i,name:o,onChange:e=>s(e.currentTarget.value),value:l,children:c.map(e=>A(`option`,{value:e.value,children:e.label},e.value))})}const ce=[`XS`,`S`,`M`,`L`,`XL`,`XXL`,`XXXL`],Y=[`15`,`12`,`10`,`5`],X=[...Y,`custom`];function le({enabled:e,error:t,errorId:n,onChange:r,values:i}){if(!e)return null;let a=e=>r({...i,...e}),o=(e,t)=>{let n=X.indexOf(t),r;switch(e.key){case`ArrowDown`:case`ArrowRight`:r=(n+1)%X.length;break;case`ArrowLeft`:case`ArrowUp`:r=(n-1+X.length)%X.length;break;case`Home`:r=0;break;case`End`:r=X.length-1;break;default:return}e.preventDefault();let i=X[r];i&&((e.currentTarget.closest(`[role="radiogroup"]`)?.querySelectorAll(`input[type="radio"]`))?.[r]?.focus(),a({tipPercent:i}))};return j(`div`,{className:`lockerverse-payment__tip-box`,children:[A(`p`,{children:`Add a tip to support the Lockerverse platform`}),j(`div`,{"aria-label":`Tip amount`,role:`radiogroup`,children:[Y.map(e=>j(`label`,{className:`lockerverse-payment__tip-choice`,children:[A(`input`,{checked:i.tipPercent===e,name:`tipPercent`,onChange:()=>a({tipPercent:e}),onKeyDown:t=>o(t,e),tabIndex:i.tipPercent===e?0:-1,type:`radio`,value:e}),j(`span`,{children:[e,`%`]})]},e)),j(`label`,{className:`lockerverse-payment__tip-choice`,children:[A(`input`,{checked:i.tipPercent===`custom`,name:`tipPercent`,onChange:()=>a({tipPercent:`custom`}),onKeyDown:e=>o(e,`custom`),tabIndex:i.tipPercent===`custom`?0:-1,type:`radio`,value:`custom`}),A(`span`,{children:`Other`})]})]}),i.tipPercent===`custom`?j(`label`,{children:[A(`span`,{children:`Custom tip`}),j(`span`,{className:`lockerverse-payment__money-input`,children:[A(`span`,{"aria-hidden":`true`,children:`$`}),A(`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?A(`span`,{className:`lockerverse-payment__field-message`,id:n,children:t}):null]}):A(`input`,{name:`tip`,type:`hidden`,value:i.tipPercent})]})}function ue({checked:e,children:t,name:n,onChange:r}){let i=C();return j(`label`,{className:`lockerverse-payment__check-row`,htmlFor:i,children:[A(l,{checked:e,id:i,name:n,onChange:e=>r(e.currentTarget.checked)}),A(`span`,{children:t})]})}function de({customFields:e,errors:t,fields:n,idPrefix:r,isPromoApplying:i,memberIdLabel:a,onChange:o,onApplyPromo:s,promoError:c,values:l}){let u=e=>o({...l,...e});return j(`div`,{className:`lockerverse-payment__additional-fields`,children:[n.memberId?j(`label`,{children:[A(`span`,{children:a?.trim()||`Member ID`}),A(`input`,{name:`memberId`,onChange:e=>u({memberId:e.currentTarget.value}),placeholder:`Optional`,value:l.memberId})]}):null,n.merchSize?j(`div`,{className:`lockerverse-payment__field`,children:[A(`span`,{id:`${r}-merch-size-label`,children:`Size`}),A(se,{ariaLabelledBy:`${r}-merch-size-label`,name:`merchSize`,onValueChange:e=>{let t=ce.find(t=>t===e);t&&u({merchSize:t})},options:ce.map(e=>({label:e,value:e})),value:l.merchSize})]}):null,n.promoCode?j(`div`,{className:`lockerverse-payment__field`,children:[A(`span`,{id:`${r}-promo-code-label`,children:`Promo code`}),j(`div`,{className:`lockerverse-payment__promo-control`,children:[A(`input`,{"aria-describedby":c?`${r}-promo-code-error`:void 0,"aria-invalid":c?`true`:void 0,"aria-labelledby":`${r}-promo-code-label`,name:`promoCode`,onChange:e=>u({promoCode:e.currentTarget.value}),placeholder:`Optional`,value:l.promoCode}),A(`button`,{disabled:!l.promoCode.trim()||i,onClick:s,type:`button`,children:i?`Applying…`:`Apply`})]}),c?A(`p`,{className:`lockerverse-payment__field-message`,id:`${r}-promo-code-error`,role:`alert`,children:c}):null]}):null,A(f,{choiceClassName:`lockerverse-payment__check-row`,errorClassName:`lockerverse-payment__field-message`,errors:t,fields:e,idPrefix:r,onChange:e=>u({customFields:e}),values:l.customFields})]})}function fe({amountCents:t,enabled:n,onChange:r,values:i}){return n?j(ue,{checked:i.includeServiceFee,name:`includeServiceFee`,onChange:e=>r({...i,includeServiceFee:e}),children:[`Add `,e(t),` to help cover processing fees`]}):null}function Z(e){return{error:void 0,message:void 0,status:e?`recovering`:`editing`}}function Q(e,t,n){return t.includes(e.status)?{...e,...n}:e}function pe(e,t){if(e.status===`sold_out`||e.status===`succeeded`||e.status===`unresolved`)return e;switch(t.type){case`field_changed`:return Q(e,[`editing`,`invalid`,`refreshing_quote`],{error:void 0,status:`editing`});case`validation_failed`:return Q(e,[`editing`],{status:`invalid`});case`quote_refresh_started`:return Q(e,[`editing`,`invalid`],{status:`refreshing_quote`});case`quote_refresh_succeeded`:return Q(e,[`refreshing_quote`],{error:void 0,status:`editing`});case`quote_refresh_failed`:return Q(e,[`refreshing_quote`],{error:t.error??e.error,status:`editing`});case`submission_started`:return Q(e,[`editing`,`invalid`,`refreshing_quote`],{error:void 0,status:`submitting`});case`submission_validation_failed`:return Q(e,[`submitting`],{error:void 0,status:`invalid`});case`quote_changed`:return Q(e,[`submitting`],{status:`editing`});case`retryable_failure`:return Q(e,[`editing`,`invalid`,`submitting`],{error:t.error,status:`editing`});case`recovery_failed`:return Q(e,[`recovering`],{error:t.error,status:`editing`});case`sold_out`:return{error:void 0,message:void 0,status:`sold_out`};case`succeeded`:return Q(e,[`recovering`,`submitting`],{message:t.message,status:`succeeded`});case`unresolved`:{let n={message:t.message,status:`unresolved`};return t.retryUrl&&(n.retryUrl=t.retryUrl),Q(e,[`recovering`,`submitting`],n)}default:return e}}function me(e){return e.status===`editing`||e.status===`invalid`||e.status===`refreshing_quote`?e.error:void 0}function he(e){return e.status===`sold_out`?`sold_out`:e.status===`succeeded`?`success`:e.status===`unresolved`?`unresolved`:e.status===`submitting`||e.status===`recovering`?`submitting`:e.status===`invalid`?`invalid`:me(e)?`error`:`idle`}function ge(e){return e.status===`submitting`}const _e=[`amountCents`,`discountableSubtotalCents`,`discountCents`,`serviceFeeCents`,`subtotalCents`,`tipCents`,`totalCents`],ve=[`discountableSubtotalCents`,`discountCents`,`subtotalCents`];function ye(e,t,n,r){return(n===t.totalCents?ve:_e).some(n=>e[n]!==t[n])||r!==t.payment.connectedAccountId||e.authoritative&&(e.payment.connectedAccountId!==r||e.payment.currency!==t.payment.currency)||JSON.stringify(e.appliedDiscount)!==JSON.stringify(t.appliedDiscount)||JSON.stringify(e.lineItems)!==JSON.stringify(t.lineItems)}function be(e){if(e.checkoutStatus===`success`)return{kind:`success`,payment:e};if(e.checkoutStatus===`failed`)return{kind:`failed`,payment:e};let t={kind:`unresolved`,paymentReference:e.paymentReference,reason:e.checkoutStatus===`action_required`?`action_required`:`pending`};return e.retryUrl&&(t.retryUrl=e.retryUrl),t}async function xe(e,t,n){if(t.checkoutStatus!==`action_required`||!t.requiresAction)return be(t);if(!n)return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`};if(t.clientSecret)try{await n.handleNextAction({clientSecret:t.clientSecret})}catch{}try{return be(await e.getPaymentStatus(t.paymentReference))}catch{return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`}}}async function Se(e,t,n){let r;try{r=await e.submitPayment(t)}catch(n){if(!(n instanceof M&&n.recoveryRecommended))throw n;try{r=await e.getPaymentStatus(t.checkout.paymentReference)}catch{return{kind:`unresolved`,paymentReference:t.checkout.paymentReference,reason:`recovery_failed`}}}return xe(e,r,n)}async function Ce(e,t,n){try{return xe(e,await e.getPaymentStatus(t),n)}catch{return{kind:`unresolved`,paymentReference:t,reason:`recovery_failed`}}}const we=G(J(),ae(),ee()),Te=G(ne(),re(),H(1)),Ee=G(z(oe([ie({amountCents:Te,productSlug:we}),ie({productSlug:we,quantity:Te}),ie({productSlug:we})])),V(1)),De=G(J(),ae(),K(/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/,`Enter a valid tip amount.`));function Oe(e){let t=q(De,e);if(!t.success)return{message:t.issues[0]?.message??`Enter a valid tip amount.`,success:!1};let[n=`0`,r=``]=t.output.split(`.`),i=BigInt(n)*100n+BigInt(r.padEnd(2,`0`));return i>BigInt(2**53-1)?{message:`Enter a valid tip amount.`,success:!1}:{cents:Number(i),success:!0}}function ke(e){let t=q(Ee,e);return t.success?{success:!0,value:t.output}:{message:`Lockerverse payment configuration is invalid.`,success:!1}}const Ae=`This promo code is invalid or cannot be applied.`;function je(e,t){return t.tipPercent===`custom`?t.customTip.trim()?Oe(t.customTip):{cents:0,success:!0}:{cents:Math.round(e*Number(t.tipPercent)/100),success:!0}}function Me(e,t,n,r){let i={};return n&&(i.email=n),e.widget.fields.serviceFee&&(i.includeServiceFee=t.includeServiceFee),e.widget.fields.promoCode&&t.promoCode.trim()&&(i.promoCode=t.promoCode.trim()),e.widget.fields.tipping&&(i.tipCents=r),i}function Ne(e,t,n){let r=e.widget.fields.tipping?je(n.subtotalCents,t):{cents:0,success:!0};if(!r.success)return{parsedTip:r,totalCents:null};let i=e.widget.fields.serviceFee&&t.includeServiceFee?n.serviceFeeCents||Math.round(n.subtotalCents*e.pricingPolicy.serviceFeeRateBasisPoints/1e4):0;return{parsedTip:r,totalCents:n.totalCents-n.serviceFeeCents-n.tipCents+i+r.cents}}function Pe(e,t){return{displayedTotalCents:e.totalCents,promoError:t&&e.appliedDiscount?.source!==`promo_code`?Ae:void 0}}function Fe(e,t){let n;return t||(n=e instanceof Error?e.message:`The order total could not be updated.`),{paymentError:n,promoError:t?Ae:void 0}}function Ie(e,t){if(!e?.complete)throw Error(`${t} address is required.`);return e.value}function Le(e,t,n,r){if(e.widget.fields.shipping)return t.shippingMatchesBilling?n:Ie(r.shipping,`Shipping`)}function Re({billingAddress:e,catalog:t,email:n,phone:r,shippingAddress:i}){let a={payment_method_data:{billing_details:t.widget.fields.phone?{address:e.address,email:n,name:e.name,phone:r}:{address:e.address,email:n,name:e.name}}};return i?{...a,shipping:{address:i.address,name:i.name,phone:t.widget.fields.phone?r:i.phone??null}}:a}function ze({catalog:e,checkoutItems:t,confirmationToken:n,email:r,fieldValues:i,metadata:a,phone:o,shippingAddress:s}){let c={customFieldAnswers:p(u(e,t),i.customFields),email:r};if(n&&(c.confirmationToken=n),a&&(c.metadata=a),e.widget.fields.memberId&&i.memberId.trim()&&(c.memberId=i.memberId.trim()),e.widget.fields.merchSize&&(c.merchSize=i.merchSize),e.widget.fields.phone&&(c.phone=o),s){let e={city:s.address.city??``,country:s.address.country,line1:s.address.line1??``,postal_code:s.address.postal_code??``,state:s.address.state??``};s.address.line2&&(e.line2=s.address.line2),c.shipping={address:e,name:s.name}}return c}function Be(e){if(!e())throw Error(`Payment component is no longer active.`)}function Ve(e,n){t(e,n)}function He(e,t,n,r){return e.kind===`failed`?{kind:`payment_failed`,message:r}:e.kind===`unresolved`?{kind:`payment_unresolved`,paymentReference:e.paymentReference,reason:e.reason,retryUrl:e.retryUrl}:{email:n,kind:`payment`,payment:e.payment,quote:t}}async function Ue({addresses:e,catalog:t,checkoutItems:n,client:r,elements:i,email:a,fieldValues:o,isAttemptActive:s,locallyPreviewedTotalCents:c,metadata:l,onPaymentRecoveryChange:u,phone:d,quote:f,stripe:p,stripeConnectedAccountId:m}){let h=a.trim().toLowerCase(),g=y(d),_=je(f.subtotalCents,o);if(!_.success)throw Error(_.message);let v=await r.calculateTotal({...Me(t,o,h,_.cents),catalog:t,items:n});if(Be(s),v.totalCents>0&&ye(f,v,c,m))return{kind:`quote_changed`,quote:v};let b,x;if(v.totalCents===0)t.widget.fields.shipping&&(b=Le(t,o,Ie(e.billing,`Billing`),e));else{if(!(i&&p))throw Error(`Payment form is still loading.`);await i.update({amount:v.totalCents}),Be(s);let n=await i.submit();if(Be(s),n.error)throw Error(n.error.message);let r=Ie(e.billing,`Billing`);b=Le(t,o,r,e);let a=await p.createConfirmationToken({elements:i,params:Re({billingAddress:r,catalog:t,email:h,phone:g,shippingAddress:b})});if(Be(s),a.error)throw Error(a.error.message);x=a.confirmationToken.id}Ve(u,{connectedAccountId:v.payment.connectedAccountId,paymentReference:v.paymentReference});let S=await Se(r,{checkout:v,submission:ze({catalog:t,checkoutItems:n,confirmationToken:x,email:h,fieldValues:o,metadata:l,phone:g,shippingAddress:b})},p);return Be(s),He(S,v,h,v.totalCents===0?`Order could not be completed. Review the details and try again.`:`Payment was declined. Check your payment details and try again.`)}function We(e,n){t(e,n)}function Ge(e,n){t(e,n)}function Ke(e,t){return{...e,...t}}function qe(e){let t={message:e.reason===`action_required`?`Payment needs your attention. Keep this checkout open.`:`Payment is not complete. Check its status before you try again.`,type:`unresolved`};return e.retryUrl&&(t.retryUrl=e.retryUrl),t}function Je(e,t,n){return e.kind===`unresolved`&&e.reason===`action_required`&&!e.retryUrl&&!t&&!n}function Ye(e){return e instanceof M&&e.serverCode===`PAYMENT_WIDGET_SALES_LIMIT_REACHED`}function Xe({nextQuote:e,onQuoteChange:t,setDisplayedTotalCents:n,setPromoError:r,updateState:i,validatePromo:a}){let o=Pe(e,a);i({type:`quote_refresh_succeeded`}),n(o.displayedTotalCents),t(e),a&&r(o.promoError)}function Ze({error:e,setPromoError:t,updateState:n,validatePromo:r}){let i=Fe(e,r);r&&t(i.promoError),n(i.paymentError===void 0?{type:`quote_refresh_failed`}:{error:i.paymentError,type:`quote_refresh_failed`})}function Qe({onPaymentComplete:n,onPaymentRecoveryChange:r,onPaymentUncertain:i,onQuoteChange:a,result:o,setDisplayedTotalCents:s,dispatchState:c}){if(o.kind===`quote_changed`){let t=`The total changed to ${e(o.quote.totalCents)}. Review it and pay again.`;a(o.quote,t),s(o.quote.totalCents),c({type:`quote_changed`});return}if(o.kind===`payment_failed`){We(r,null),c({error:o.message,type:`retryable_failure`});return}if(o.kind===`payment_unresolved`){c(qe(o)),Ge(i,{paymentReference:o.paymentReference,reason:o.reason});return}a(o.quote),We(r,null),c({message:o.payment.paymentRequired?`Payment completed successfully.`:`Order confirmed. No payment was required.`,type:`succeeded`}),t(n,Ke(o.payment,{email:o.email,lineItems:o.quote.lineItems}))}function $e(e){let{catalog:n,checkoutItems:r,client:i,elements:o,email:s,fieldValues:c,metadata:l,onPaymentComplete:u,onResumePaymentFailed:d,onPaymentRecoveryChange:f,onPaymentUncertain:p,onQuoteChange:m,onStateChange:h,quote:g,resumePayment:v,stripe:y,stripeConnectedAccountId:b,stripeLoadFailed:C,paymentState:w,updateState:T}=e,[E,k]=O(g.totalCents),[A,j]=O(),N=D(!1),P=D(0),F=D(0),I=x(e=>T(e,!0),[T]),L=x(()=>{let e=F.current+1;return F.current=e,()=>F.current===e},[]);S(()=>()=>{F.current+=1,P.current+=1},[]);let{parsedTip:R,totalCents:z}=Ne(n,c,g);S(()=>{z!==null&&(k(z),z>0&&o?.update({amount:z}))},[n.pricingPolicy.serviceFeeRateBasisPoints,n.widget.fields.serviceFee,o,c.includeServiceFee,z,g.serviceFeeCents,g.tipCents,g.totalCents,g.subtotalCents]),S(()=>{if(!v||N.current||w.status!==`recovering`)return;N.current=!0;let e=L();return h(he(w)),Ce(i,v.paymentReference,y).then(n=>{if(e()&&!Je(n,y,C)){if(n.kind===`failed`){We(f,null),d(),I({error:`The previous payment failed. Check your details and try again.`,type:`recovery_failed`});return}if(n.kind===`unresolved`){I(qe(n)),Ge(p,{paymentReference:n.paymentReference,reason:n.reason});return}We(f,null),I({message:n.payment.paymentRequired?`Payment completed successfully.`:`Order confirmed. No payment was required.`,type:`succeeded`}),t(u,Ke(n.payment,{email:null,lineItems:null}))}}),()=>{e()&&(F.current+=1),N.current=!1}},[i,u,d,f,p,h,v,y,C,L,I,w]);let B=x((e=!1,t=!1)=>{t||(P.current+=1),e&&j(void 0),T({type:`field_changed`})},[T]);async function V(e=!1,t=!1){let a=s.trim().toLowerCase(),o=_({email:a,phone:``},!1);if(!(R.success&&(o.value||e)))return;P.current+=1;let l=P.current;T({type:`quote_refresh_started`});try{let e=await i.calculateTotal({...Me(n,c,o.value?.email??``,R.cents),catalog:n,items:r});if(l!==P.current)return;Xe({nextQuote:e,onQuoteChange:m,setDisplayedTotalCents:k,setPromoError:j,updateState:T,validatePromo:t})}catch(e){if(l!==P.current)return;if(Ye(e)){T({type:`sold_out`});return}Ze({error:e,setPromoError:j,updateState:T,validatePromo:t})}}async function H(){j(void 0),await V(!0,!0)}async function ee({addresses:e,phone:t}){I({type:`submission_started`});let d=L();try{let a=await Ue({addresses:e,catalog:n,checkoutItems:r,client:i,elements:o,email:s,fieldValues:c,isAttemptActive:d,locallyPreviewedTotalCents:E,metadata:l,onPaymentRecoveryChange:f,phone:t,quote:g,stripe:y,stripeConnectedAccountId:b});if(!d())return;Qe({dispatchState:I,onPaymentComplete:u,onPaymentRecoveryChange:f,onPaymentUncertain:p,onQuoteChange:m,result:a,setDisplayedTotalCents:k})}catch(e){if(!d())return;if(We(f,null),Ye(e)){I({type:`sold_out`});return}let t=e instanceof M?a(e.serverCode):void 0;if(t)return I({type:`submission_validation_failed`}),{phoneError:t};I({error:e instanceof Error?e.message:`Payment could not be completed.`,type:`retryable_failure`})}}let te=w.status===`succeeded`||w.status===`unresolved`?w.message:void 0;return{commands:{applyPromo:H,fieldChanged:B,refreshAuthoritativeTotal:V,reportStripeLoadError:e=>I({error:e,type:`retryable_failure`}),reportValidationFailure:()=>I({type:`validation_failed`}),submit:ee},state:{displayedTotalCents:E,isRecovering:w.status===`recovering`,isRefreshingQuote:w.status===`refreshing_quote`,isSubmitting:ge(w),parsedTip:R,paymentError:me(w),promoError:A,retryUrl:w.retryUrl,terminalMessage:te}}}const et=b;function tt(e){let{connectedAccountId:t,publishableKey:n}=e.payment;return et(n,t?{stripeAccount:t}:void 0)}function nt(e){return e===`monthly`?{interval:`month`,label:`Monthly`}:e===`annually`?{interval:`year`,label:`Annual`}:e===`every-six-months`?{interval:`6 months`,label:`Every 6 months`}:null}function rt(e,t,n){if(n){let{connectedAccountId:e}=n;return e}if(`payment`in t){let{connectedAccountId:e}=t.payment;return e}let{connectedAccountId:r}=e.payment;return r}function it({accentColor:e,catalog:t,checkoutItems:n,client:r,appearanceRoot:i,initialCustomFieldValues:a,metadata:o,onPaymentComplete:s,onResumePaymentFailed:c,onPaymentRecoveryChange:l,onPaymentUncertain:u,onQuoteChange:d,quote:f,resumePayment:p,onStateChange:m,stripeLoader:g,theme:_,visualStyle:y}){let[b,C]=O(()=>Z(!!p)),w=D(b);w.current=b;let E=x((e,t=!1)=>{let n=pe(w.current,e);n!==w.current&&(w.current=n,C(n),t&&m(he(n)))},[m]),k=rt(t,f,p),j=D({connectedAccountId:k,paymentOption:f.paymentOption});b.status!==`submitting`&&b.status!==`recovering`&&(j.current={connectedAccountId:k,paymentOption:f.paymentOption});let{connectedAccountId:M,paymentOption:N}=j.current,P=T(()=>g(t.payment.publishableKey,M?{stripeAccount:M}:void 0).catch(()=>null),[t.payment.publishableKey,M,g]),[I,L]=O(!1);S(()=>{let e=!0;return L(!1),P.then(t=>{e&&t===null&&L(!0)}),()=>{e=!1}},[P]);let R=v(i,_,y,b.status===`submitting`||b.status===`recovering`,e);return R?A(F,{options:{amount:Math.max(f.totalCents,100),appearance:R,currency:t.payment.currency,excludedPaymentMethodTypes:t.community?.widgetAchEnabled?[]:[`us_bank_account`],mode:N===`one-time`?`payment`:`subscription`,syncAddressCheckbox:`none`},stripe:P,children:A(mt,{catalog:t,checkoutItems:n,client:r,initialCustomFieldValues:a,metadata:o,onPaymentComplete:s,onPaymentRecoveryChange:l,onPaymentUncertain:u,onQuoteChange:d,onResumePaymentFailed:c,onStateChange:m,paymentState:b,quote:f,resumePayment:p,stripeConnectedAccountId:M,stripeLoadFailed:I,updateState:E})},`${t.payment.publishableKey}:${M??`platform`}:${N}`):A(h,{fieldCount:3,label:`Loading payment form`})}function at({label:e}){return j(`div`,{className:`lockerverse-payment__stripe-loader`,role:`status`,children:[A(`p`,{children:e}),j(`div`,{"aria-hidden":`true`,children:[A(`span`,{}),A(`span`,{}),A(`span`,{})]})]})}function ot({onError:e,onReady:t,ready:n}){return j(`div`,{className:`lockerverse-payment__stripe-element`,"data-ready":n,children:[n?null:A(at,{label:`Loading payment form...`}),A(`div`,{className:`lockerverse-payment__stripe-mount`,children:A(I,{onLoadError:({error:t})=>e(t.message??`Payment form failed to load.`),onReady:t,options:{business:{name:`Lockerverse`},fields:{billingDetails:{address:`never`,email:`never`,name:`never`,phone:`never`}},layout:`tabs`,terms:{applePay:`auto`,auBecsDebit:`never`,bancontact:`never`,card:`always`,cashapp:`never`,googlePay:`never`,ideal:`never`,paypal:`auto`,sepaDebit:`never`,sofort:`never`,usBankAccount:`auto`},wallets:{applePay:`auto`,googlePay:`never`}}})})]})}function st({label:e,mode:t,onChange:n,onError:r,onReady:i,ready:a}){return j(`div`,{className:`lockerverse-payment__address`,children:[A(`h2`,{children:e}),j(`div`,{className:`lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address`,"data-ready":a,children:[a?null:A(at,{label:`Loading ${e.toLowerCase()}...`}),A(`div`,{className:`lockerverse-payment__stripe-mount`,children:A(P,{onChange:n,onLoadError:({error:t})=>r(t.message??`${e} failed to load.`),onReady:i,options:{autocomplete:{mode:`automatic`},mode:t}})})]})]})}function ct({message:e}){return e?A(`p`,{className:`lockerverse-payment__field-message`,role:`alert`,children:e}):null}function lt({catalog:e,displayedTotalCents:t,fieldValues:n,isBillingAddressReady:r,isPaymentReady:i,isShippingAddressReady:a,onAddressChange:o,onFieldValuesChange:s,onStripeLoadError:c,setIsBillingAddressReady:l,setIsPaymentReady:u,setIsShippingAddressReady:d}){let f=t>0;return j(k,{children:[f?A(ot,{onError:c,onReady:()=>u(!0),ready:i}):null,f||e.widget.fields.shipping?A(st,{label:f?`Billing address`:`Shipping address`,mode:`billing`,onChange:e=>o(`billing`,e),onError:c,onReady:()=>l(!0),ready:r}):null,e.widget.fields.shipping?j(`div`,{className:`lockerverse-payment__shipping`,children:[A(ue,{checked:n.shippingMatchesBilling,name:`shippingMatchesBilling`,onChange:e=>{s({...n,shippingMatchesBilling:e}),e?o(`shipping`,null):d(!1)},children:`Shipping is same as billing information`}),n.shippingMatchesBilling?null:A(st,{label:`Shipping address`,mode:`shipping`,onChange:e=>o(`shipping`,e),onError:c,onReady:()=>d(!0),ready:a})]}):null]})}function ut({catalog:t,displayedTotalCents:n,fieldValues:r,isBillingAddressReady:i,isPaymentReady:a,isRequiredShippingReady:o,isSubmitting:s,onFieldValuesChange:c,quote:l}){let u=n===0,d=u?!t.widget.fields.shipping||i&&o:a&&i&&o,f=nt(l.paymentOption),p=u?`Complete order`:`Pay ${e(n)}`;!u&&f&&(p=`Subscribe for ${e(n)}/${f.interval}`),s&&(p=u?`Completing…`:`Processing…`);let m=`Process payment for ${e(n)} total`;return u?m=`Complete order`:f&&(m=`Start ${f.label.toLowerCase()} subscription for ${e(n)}`),j(`div`,{className:`lockerverse-payment__actions`,children:[A(fe,{amountCents:l.serviceFeeCents||Math.round(l.subtotalCents*t.pricingPolicy.serviceFeeRateBasisPoints/1e4),enabled:t.widget.fields.serviceFee,onChange:c,values:r}),A(`button`,{"aria-busy":s,"aria-label":m,disabled:s||!d,type:`submit`,children:p})]})}function dt(e,t){let n=e.elements.namedItem(t);if(n instanceof HTMLElement){n.focus();return}n instanceof RadioNodeList&&Array.from(n).find(e=>e instanceof HTMLElement)?.focus()}function ft({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&&dt(n,`custom:${o}`)}function pt({email:e,emailDiscountPercentOff:t,emailErrorId:n,emailId:r,emailRef:a,errors:o,onEmailBlur:l,onEmailChange:u,onPhoneChange:d,phone:f,phoneCountry:p,phoneEnabled:m,phoneErrorId:h,phoneId:g,phoneRef:_}){return j(`div`,{className:`lockerverse-payment__contact`,children:[A(i,{error:o.email,errorId:n,id:r,label:`Email`,name:`email`,onBlur:l,onChange:e=>u(e.currentTarget.value),ref:a,required:!0,value:e}),t===void 0?null:j(`p`,{className:`lockerverse-payment__discount-message`,role:`status`,children:[`Your email qualifies for `,t,`% off.`]}),m?A(s,{error:o.phone,errorId:h,id:g,label:`Phone`,children:A(c,{country:p,error:o.phone,errorId:h,id:g,inputRef:_,name:`phone`,onChange:d,required:!0,value:f})}):null]})}function mt({catalog:e,checkoutItems:t,client:n,initialCustomFieldValues:r,metadata:i,onPaymentComplete:a,onResumePaymentFailed:s,onPaymentRecoveryChange:c,onPaymentUncertain:l,onQuoteChange:f,onStateChange:p,quote:h,resumePayment:v,stripeConnectedAccountId:y,stripeLoadFailed:b,paymentState:x,updateState:w}){let T=u(e,t),[E,M]=O(``),[N,P]=O(``),[F,I]=O(`US`),[z,B]=O({}),[V,H]=O({}),[ee,te]=O(),[ne,U]=O(!1),[W,G]=O(!1),[K,re]=O(!1),[q,ie]=O(()=>({customFields:d(T,r),customTip:``,includeServiceFee:e.widget.fields.serviceFee,memberId:``,merchSize:`M`,promoCode:``,shippingMatchesBilling:!0,tipPercent:`10`})),J=D({billing:null,shipping:null}),ae=D(null),oe=D(null),se=D(null),ce=D(h.totalCents>0),Y=$e({catalog:e,checkoutItems:t,client:n,elements:L(),email:E,fieldValues:q,metadata:i,onPaymentComplete:a,onPaymentRecoveryChange:c,onPaymentUncertain:l,onQuoteChange:f,onResumePaymentFailed:s,onStateChange:p,paymentState:x,quote:h,resumePayment:v,stripe:R(),stripeConnectedAccountId:y,stripeLoadFailed:b,updateState:w}),{displayedTotalCents:X,isRecovering:ue,isRefreshingQuote:fe,isSubmitting:Z,parsedTip:Q,paymentError:pe,promoError:me,terminalMessage:he,retryUrl:ge}=Y.state,_e=`lockerverse-${C()}`,ve=`${_e}-email`,ye=`${ve}-error`,be=`${_e}-phone`,xe=`${be}-error`,Se=`${_e}-tip-error`,Ce=(Q.success?Q.cents:null)??0,we=X-Ce,Te=!e.widget.fields.shipping||q.shippingMatchesBilling||K;S(()=>{Z&&se.current?.focus({preventScroll:!0})},[Z]),S(()=>{Z||z.email||!z.phone||oe.current?.focus()},[z.email,z.phone,Z]),S(()=>{let e=X>0;e&&!ce.current&&(U(!1),G(!1)),ce.current=e},[X]);function Ee(e){Y.commands.fieldChanged(!1,e!==`email`),B(t=>{let n={...t};return delete n[e],n})}function De(e){let t=e.promoCode!==q.promoCode,n=e.includeServiceFee!==q.includeServiceFee;Y.commands.fieldChanged(t,!(t||n)),ie(e),H({}),te(void 0)}async function Oe(t){t.preventDefault();let n=e.widget.fields.phone?o(N,F):``,r=_({email:E,phone:n},e.widget.fields.phone),i=m(T,q.customFields);if(!(r.value&&Q.success)||Object.keys(i).length>0){B(r.errors),H(i),te(Q.success?void 0:Q.message),Y.commands.reportValidationFailure();let e=t.currentTarget;queueMicrotask(()=>{ft({customFieldErrors:i,emailRef:ae,form:e,parsedTipSuccess:Q.success,phoneRef:oe,validationErrors:r.errors})});return}B({}),H({});let a=await Y.commands.submit({addresses:J.current,phone:n});a?.phoneError&&B({phone:a.phoneError})}return he?j(`p`,{className:`lockerverse-payment__payment-status`,ref:se,role:`status`,tabIndex:-1,children:[he,ge?j(k,{children:[` `,A(`a`,{href:ge,rel:`noopener noreferrer`,target:`_blank`,children:`Complete payment`})]}):null]}):ue?A(`p`,{className:`lockerverse-payment__payment-status`,role:`status`,children:`Recovering payment…`}):j(`form`,{"aria-busy":Z,className:`lockerverse-payment__form`,noValidate:!0,onSubmit:Oe,children:[A(`div`,{"data-lockerverse-input-region":``,inert:Z?!0:void 0,children:j(`fieldset`,{className:`lockerverse-payment__input-fieldset`,disabled:Z,children:[A(g,{displayedBaseCents:we,displayedTipCents:Ce,displayedTotalCents:X,quote:h}),A(le,{enabled:e.widget.fields.tipping,error:ee,errorId:Se,onChange:De,values:q}),A(pt,{email:E,emailDiscountPercentOff:h.appliedDiscount?.source===`email_list`?h.appliedDiscount.percentageOff:void 0,emailErrorId:ye,emailId:ve,emailRef:ae,errors:z,onEmailBlur:()=>Y.commands.refreshAuthoritativeTotal(),onEmailChange:e=>{M(e),Ee(`email`)},onPhoneChange:({value:e,country:t})=>{P(e),I(t),Ee(`phone`)},phone:N,phoneCountry:F,phoneEnabled:e.widget.fields.phone,phoneErrorId:xe,phoneId:be,phoneRef:oe}),A(lt,{catalog:e,displayedTotalCents:X,fieldValues:q,isBillingAddressReady:W,isPaymentReady:ne,isShippingAddressReady:K,onAddressChange:(e,t)=>{J.current[e]=t},onFieldValuesChange:De,onStripeLoadError:Y.commands.reportStripeLoadError,setIsBillingAddressReady:G,setIsPaymentReady:U,setIsShippingAddressReady:re}),A(de,{customFields:T,errors:V,fields:e.widget.fields,idPrefix:_e,isPromoApplying:fe,memberIdLabel:e.community?.memberIdLabel,onApplyPromo:Y.commands.applyPromo,onChange:De,promoError:me,values:q}),A(ut,{catalog:e,displayedTotalCents:X,fieldValues:q,isBillingAddressReady:W,isPaymentReady:ne,isRequiredShippingReady:Te,isSubmitting:Z,onFieldValuesChange:De,quote:h})]})}),Z?A(`p`,{className:`lockerverse-payment__sr-only`,ref:se,role:`status`,tabIndex:-1,children:X===0?`Completing order…`:`Processing payment…`}):null,A(ct,{message:pe})]})}function ht(){return A(h,{fieldCount:2,label:`Loading payment…`,sectionCount:2,showCheckbox:!0})}function gt(e,t){switch(t.type){case`loading`:return{phase:`loading`,revision:e.revision};case`ready`:return yt(t.displayedQuote,e.revision+1);case`error`:return{failure:t.failure,phase:`error`,revision:e.revision};case`checkout`:return e.phase===`ready`?{...e,displayedQuote:t.checkout,quoteFailure:void 0}:e;case`quote-error`:return e.phase===`ready`?{...e,quoteFailure:t.failure}:e;default:return e}}function $(e,t,n){return e?.catalog===t&&e.selectionKey===n}function _t({checkout:e}){return{displayedQuote:e,type:`ready`}}function vt(e){return e instanceof Error?e.message:`Lockerverse payment could not load.`}function yt(e,t){return{checkoutItems:[...e.items],displayedQuote:e,phase:`ready`,quoteFailure:void 0,revision:t}}function bt(e,t){let n=e.widget.fields.serviceFee;return N(e,{includeServiceFee:n,selection:t})}function xt(e,t){try{return yt(bt(e,t),1)}catch(e){return{failure:vt(e),phase:`error`,revision:0}}}function St({catalog:e,client:t,paymentState:n,selection:r}){let i=ke(r),a=i.success?JSON.stringify(i.value):`invalid-selection`,o=T(()=>i.success?i.value:[],[i.success,a]),[s,c]=E(gt,void 0,()=>i.success?xt(e,o):{phase:`loading`,revision:0}),l=D(void 0),u=D(0),d=D(s.phase===`ready`?{catalog:e,selectionKey:a}:void 0),f=D(s.phase===`error`?{catalog:e,selectionKey:a}:void 0),p=n===`submitting`||n===`success`||n===`unresolved`;S(()=>{if(!i.success||p||$(f.current,e,a)||$(l.current,e,a))return;let n=!0;l.current={catalog:e,selectionKey:a};let r=$(d.current,e,a);r||c({type:`loading`});function s(e){n&&c(e)}function m(){n&&(l.current=void 0,f.current={catalog:e,selectionKey:a})}let h;function g(t){if(!n||(l.current=void 0,f.current={catalog:e,selectionKey:a},r&&h!==void 0&&u.current!==h))return;let i=vt(t);if(i===`This option is sold out.`){c({failure:i,type:`error`});return}c(r?{failure:i,type:`quote-error`}:{failure:i,type:`error`})}async function _(){try{h=u.current;let n=e.widget.fields.serviceFee;if(!r){let t=bt(e,o);r=!0,d.current={catalog:e,selectionKey:a},s(_t({checkout:t}))}let i=await t.calculateTotal({catalog:e,includeServiceFee:n,selection:o});m(),u.current===h&&s({checkout:i,type:`checkout`})}catch(e){g(e)}}return _(),()=>{n=!1,$(l.current,e,a)&&(l.current=void 0)}},[e,t,i.success,p,a,o]);let m=$(d.current,e,a)||$(f.current,e,a)||$(l.current,e,a),h=p||m?s:{phase:`loading`,revision:s.revision};return{selectionError:i.success?void 0:i.message,session:h,updateCheckout:e=>{u.current+=1,c({checkout:e,type:`checkout`})}}}const Ct=U({recovery:U({connectedAccountId:te(J()),paymentReference:G(J(),ae(),ee())}),selectionFingerprint:J(),version:oe([B(1),B(2)]),widgetId:W(J())});function wt(e){let t=ke(e);return t.success?JSON.stringify(t.value.map(e=>{let t=e.productSlug.trim();return`quantity`in e?[`quantity`,t,e.quantity]:`amountCents`in e?[`amount`,t,e.amountCents]:[`product`,t]})):null}const Tt=`A previous payment uses different checkout details. Return to its original checkout to check the payment before you pay again.`;function Et(e,t,n){let r;try{r=window.sessionStorage.getItem(e)}catch{return{recovery:null}}if(!r)return{recovery:null};try{let e=q(Ct,JSON.parse(r));if(!e.success)throw Error(`Invalid recovery record`);let i=e.output;return i.selectionFingerprint!==t||i.version===2&&i.widgetId!==n?{error:Tt,recovery:null}:{recovery:{connectedAccountId:i.recovery.connectedAccountId,paymentReference:i.recovery.paymentReference}}}catch{return{error:`The saved payment could not be read. Contact support to check it before you pay again.`,recovery:null}}}function Dt({selection:e,storageKey:t,widgetId:n}){let r=wt(e),i=JSON.stringify([t,r,n]),[a,o]=O(null),s=D(null);S(()=>{if(!t)return;let e=s.current,a={recovery:null};e?.recovery?a=e.identity===i?{recovery:e.recovery}:{error:Tt,recovery:null}:r!==null&&(a=Et(t,r,n)),a.recovery&&(s.current={identity:i,recovery:a.recovery}),o({identity:i,...a})},[r,i,t,n]);let c=x(e=>{if(!(!t||r===null)){s.current=e?{identity:i,recovery:e}:null;try{e?window.sessionStorage.setItem(t,JSON.stringify({recovery:e,selectionFingerprint:r,version:2,widgetId:n})):window.sessionStorage.removeItem(t)}catch{}}},[r,i,t,n]);return{error:t&&a?.identity===i?a.error:void 0,ready:!t||a?.identity===i,recovery:t&&a?.identity===i?a.recovery:null,remember:c}}const Ot={annually:`/year`,"every-six-months":` every 6 months`,monthly:`/month`,"one-time":``};function kt({branding:e,catalog:t}){return j(`header`,{children:[t.widget.showCommunityBranding&&e?j(`div`,{className:`lockerverse-payment__branding`,children:[e.imageUrl?A(`img`,{alt:e.name,height:`48`,src:e.imageUrl,width:`48`}):null,A(`strong`,{children:e.name})]}):null,A(`h1`,{children:t.widget.title??t.widget.name}),t.widget.description?A(`p`,{children:t.widget.description}):null]})}function At({catalog:t,selection:n}){let r=n?.length?t.products.filter(e=>n.some(t=>t.productSlug===e.slug)):t.products;return r.length===0?null:j(`div`,{className:`lockerverse-payment__payment-summary`,children:[A(`h2`,{children:`Products`}),A(`div`,{className:`lockerverse-payment__payment-summary-items`,children:r.map(t=>{let n=t.pricingMode===`fixed`?t.amountCents:t.minimumAmountCents,r=Ot[t.paymentOption];return j(`div`,{className:`lockerverse-payment__payment-summary-row`,children:[A(`span`,{children:t.name}),A(`strong`,{children:n===null?`Choose amount`:`${t.pricingMode===`custom`?`From `:``}${e(n)}${r}`})]},t.id)})}),A(`p`,{children:`Base prices. Final total is checked at checkout.`})]})}function jt(e,t){let i=n(e?.[`--lockerverse-accent`]??t?.accentColor??`#38d77a`),a=r(i),o={...e};return(e?.[`--lockerverse-accent`]!==void 0||t?.accentColor)&&(o[`--lockerverse-accent`]=i),a&&e?.[`--lockerverse-accent-contrast`]===void 0&&(o[`--lockerverse-accent-contrast`]=a),{accent:i,rootStyle:o}}function Mt({catalog:e,client:n,loadError:r,onRetry:i,...a}){let{branding:o,className:s,completionView:c,recoveryStorageKey:l,initialCustomFieldValues:u,metadata:d,onPaymentComplete:f,onPaymentRecoveryChange:p,onPaymentUncertain:m,resumePayment:h,selection:g,style:_,stripeLoader:v=et,theme:y=`dark`,...b}=a,[C,T]=O(h),E=D(null),[k,M]=O(null),N=x(e=>{M(e),t(f,e)},[f]),[P,F]=O(),[I,L]=O(`idle`),R=D(void 0),{selectionError:z,session:B,updateCheckout:V}=St({catalog:e,client:n,paymentState:I,selection:g}),H=B.phase===`ready`?B.revision:void 0,ee=x(e=>{H!==void 0&&(R.current=H),L(e)},[H]),te=x(e=>p?.(e),[p]),ne=x(()=>{T(void 0)},[]);S(()=>{B.phase===`loading`&&F(void 0)},[B.phase]),w(()=>{B.phase===`ready`&&R.current!==B.revision&&L(e=>e===`success`||e===`unresolved`?e:`idle`)},[B.phase,B.revision]);let U=[`lockerverse-payment`,s].filter(Boolean).join(` `),W=o??e.community,{accent:G,rootStyle:K}=jt(_,W);return k&&c===`summary`?A(`section`,{...b,className:U,"data-lockerverse-theme":y,"data-payment-state":`success`,style:K,children:j(`div`,{className:`lockerverse-payment__completion`,role:`status`,children:[A(`span`,{"aria-hidden":`true`,className:`lockerverse-payment__completion-icon`,children:A(`svg`,{"aria-hidden":`true`,fill:`none`,height:`28`,stroke:`currentColor`,strokeWidth:`2`,viewBox:`0 0 24 24`,width:`28`,children:A(`path`,{d:`m5 12 4 4L19 6`})})}),A(`h1`,{children:k.paymentRequired?`Thank you`:`Order confirmed`}),A(`p`,{children:k.paymentRequired?`Your payment has been received.`:`Your order is confirmed. No payment was required.`})]})}):z?A(`section`,{...b,className:U,"data-lockerverse-theme":y,role:`alert`,style:K,children:z}):B.phase===`error`&&B.failure===`This option is sold out.`||I===`sold_out`?j(`section`,{...b,className:U,"data-lockerverse-theme":y,role:`alert`,style:K,children:[A(`h1`,{children:`Sold out`}),A(`p`,{children:`This option is sold out.`})]}):B.phase===`error`?A(`section`,{...b,className:U,"data-lockerverse-theme":y,style:K,children:A(`p`,{role:`alert`,children:B.failure})}):B.phase===`ready`?j(`section`,{...b,"aria-label":`Payment`,className:U,"data-lockerverse-theme":y,"data-payment-state":I,ref:E,style:K,children:[A(kt,{branding:W,catalog:e}),r?j(`div`,{role:`alert`,children:[A(`p`,{children:r.message}),A(`button`,{onClick:i,type:`button`,children:`Retry`})]}):null,P?A(`p`,{className:`lockerverse-payment__payment-status`,role:`status`,children:P}):null,B.quoteFailure?j(`div`,{className:`lockerverse-payment__payment-status`,role:`alert`,children:[A(`span`,{children:B.quoteFailure}),A(`span`,{children:` The final total will be checked when you submit.`})]}):null,A(it,{accentColor:G,appearanceRoot:E,catalog:e,checkoutItems:B.checkoutItems,client:n,initialCustomFieldValues:u,metadata:d,onPaymentComplete:N,onPaymentRecoveryChange:te,onPaymentUncertain:m,onQuoteChange:(e,t)=>{F(t),V(e)},onResumePaymentFailed:ne,onStateChange:ee,quote:B.displayedQuote,resumePayment:C,stripeLoader:v,theme:y,visualStyle:K},B.revision)]}):j(`section`,{...b,"aria-busy":`true`,"aria-label":`Payment`,className:U,"data-lockerverse-theme":y,style:K,children:[A(kt,{branding:W,catalog:e}),r?j(`div`,{role:`alert`,children:[A(`p`,{children:r.message}),A(`button`,{onClick:i,type:`button`,children:`Retry`})]}):null,A(ht,{})]})}function Nt({children:e,loading:t=!1,viewProps:i}){let{branding:a,className:o,completionView:s,recoveryStorageKey:c,initialCustomFieldValues:l,metadata:u,onPaymentComplete:d,onPaymentRecoveryChange:f,onPaymentUncertain:p,resumePayment:m,selection:h,stripeLoader:g,style:_,theme:v=`dark`,...y}=i,b=n(_?.[`--lockerverse-accent`]??a?.accentColor??`#38d77a`),x=r(b),S={..._};return(_?.[`--lockerverse-accent`]!==void 0||a?.accentColor)&&(S[`--lockerverse-accent`]=b),x&&_?.[`--lockerverse-accent-contrast`]===void 0&&(S[`--lockerverse-accent-contrast`]=x),A(`section`,{...y,...t?{"aria-busy":!0,"aria-label":`Payment`}:{},className:[`lockerverse-payment`,o].filter(Boolean).join(` `),"data-lockerverse-theme":v,style:S,children:e})}function Pt(e){let{catalog:n,client:r,loadError:i,onRetry:a,...o}=e,{onPaymentRecoveryChange:s,recoveryStorageKey:c,resumePayment:l,selection:u}=o,d=Dt({selection:u,storageKey:c,widgetId:n.widget.id}),f=x(e=>{d.remember(e),t(s,e)},[s,d.remember]);return!d.ready||d.error?A(Nt,{loading:!d.ready,viewProps:o,children:d.error?A(`p`,{role:`alert`,children:d.error}):A(ht,{})}):A(Mt,{...e,onPaymentRecoveryChange:f,resumePayment:l??d.recovery})}function Ft({widget:e,...t}){return e.error&&!e.catalog?j(Nt,{viewProps:t,children:[A(`p`,{role:`alert`,children:e.error.message}),A(`button`,{onClick:e.refresh,type:`button`,children:`Retry`})]}):e.loading?j(Nt,{loading:!0,viewProps:t,children:[e.catalog?j(k,{children:[A(kt,{branding:t.branding??e.catalog.community,catalog:e.catalog}),A(At,{catalog:e.catalog,selection:t.selection})]}):null,A(ht,{})]}):e.catalog?A(Pt,{catalog:e.catalog,client:e.client,loadError:e.error,onRetry:e.refresh,...t}):A(Nt,{loading:!0,viewProps:t,children:A(ht,{})})}export{tt as n,Ft as t};
1
+ import{t as e}from"./format-money.js";import{t}from"./host-callback.js";import{n,t as r}from"./accent-contrast.js";import{d as i,i as a,n as o,p as s,t as c,u as l}from"./phone-field.js";import{a as u,i as d,n as f,r as p,s as m}from"./custom-fields.js";import{t as h}from"./form-skeleton.js";import{t as g}from"./payment-summary.js";import{i as _,n as v,r as y,t as b}from"./stripe-loader.js";import{useCallback as x,useEffect as S,useId as C,useLayoutEffect as w,useMemo as T,useReducer as E,useRef as D,useState as O}from"react";import{Fragment as k,jsx as A,jsxs as j}from"react/jsx-runtime";import{LockerverseSdkError as M,estimateLockerverseCheckout as N}from"@lockerverse/sdk/checkout";import{AddressElement as P,Elements as F,PaymentElement as I,useElements as L,useStripe as R}from"@stripe/react-stripe-js";import{array as z,literal as B,minLength as ee,minValue as V,nonEmpty as te,nullable as ne,number as re,object as H,optional as U,pipe as W,regex as G,safeInteger as ie,safeParse as K,strictObject as ae,string as q,trim as oe,union as se}from"valibot";function ce({ariaDescribedBy:e,ariaLabel:t,ariaLabelledBy:n,className:r,id:i,invalid:a=!1,name:o,onValueChange:s,options:c,value:l}){return A(`select`,{"aria-describedby":e,"aria-invalid":a||void 0,"aria-label":t,"aria-labelledby":n,className:[`lockerverse-form__control`,`lockerverse-form__select`,r].filter(Boolean).join(` `),id:i,name:o,onChange:e=>s(e.currentTarget.value),value:l,children:c.map(e=>A(`option`,{value:e.value,children:e.label},e.value))})}const le=[`XS`,`S`,`M`,`L`,`XL`,`XXL`,`XXXL`],J=[`15`,`12`,`10`,`5`],Y=[...J,`custom`];function ue({enabled:e,error:t,errorId:n,onChange:r,values:i}){if(!e)return null;let a=e=>r({...i,...e}),o=(e,t)=>{let n=Y.indexOf(t),r;switch(e.key){case`ArrowDown`:case`ArrowRight`:r=(n+1)%Y.length;break;case`ArrowLeft`:case`ArrowUp`:r=(n-1+Y.length)%Y.length;break;case`Home`:r=0;break;case`End`:r=Y.length-1;break;default:return}e.preventDefault();let i=Y[r];i&&((e.currentTarget.closest(`[role="radiogroup"]`)?.querySelectorAll(`input[type="radio"]`))?.[r]?.focus(),a({tipPercent:i}))};return j(`div`,{className:`lockerverse-payment__tip-box`,children:[A(`p`,{children:`Add a tip to support the Lockerverse platform`}),j(`div`,{"aria-label":`Tip amount`,role:`radiogroup`,children:[J.map(e=>j(`label`,{className:`lockerverse-payment__tip-choice`,children:[A(`input`,{checked:i.tipPercent===e,name:`tipPercent`,onChange:()=>a({tipPercent:e}),onKeyDown:t=>o(t,e),tabIndex:i.tipPercent===e?0:-1,type:`radio`,value:e}),j(`span`,{children:[e,`%`]})]},e)),j(`label`,{className:`lockerverse-payment__tip-choice`,children:[A(`input`,{checked:i.tipPercent===`custom`,name:`tipPercent`,onChange:()=>a({tipPercent:`custom`}),onKeyDown:e=>o(e,`custom`),tabIndex:i.tipPercent===`custom`?0:-1,type:`radio`,value:`custom`}),A(`span`,{children:`Other`})]})]}),i.tipPercent===`custom`?j(`label`,{children:[A(`span`,{children:`Custom tip`}),j(`span`,{className:`lockerverse-payment__money-input`,children:[A(`span`,{"aria-hidden":`true`,children:`$`}),A(`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?A(`span`,{className:`lockerverse-payment__field-message`,id:n,children:t}):null]}):A(`input`,{name:`tip`,type:`hidden`,value:i.tipPercent})]})}function X({checked:e,children:t,name:n,onChange:r}){let i=C();return j(`label`,{className:`lockerverse-payment__check-row`,htmlFor:i,children:[A(l,{checked:e,id:i,name:n,onChange:e=>r(e.currentTarget.checked)}),A(`span`,{children:t})]})}function de({customFields:e,errors:t,fields:n,idPrefix:r,isPromoApplying:i,memberIdLabel:a,onChange:o,onApplyPromo:s,promoError:c,values:l}){let u=e=>o({...l,...e});return j(`div`,{className:`lockerverse-payment__additional-fields`,children:[n.memberId?j(`label`,{children:[A(`span`,{children:a?.trim()||`Member ID`}),A(`input`,{name:`memberId`,onChange:e=>u({memberId:e.currentTarget.value}),placeholder:`Optional`,value:l.memberId})]}):null,n.merchSize?j(`div`,{className:`lockerverse-payment__field`,children:[A(`span`,{id:`${r}-merch-size-label`,children:`Size`}),A(ce,{ariaLabelledBy:`${r}-merch-size-label`,name:`merchSize`,onValueChange:e=>{let t=le.find(t=>t===e);t&&u({merchSize:t})},options:le.map(e=>({label:e,value:e})),value:l.merchSize})]}):null,n.promoCode?j(`div`,{className:`lockerverse-payment__field`,children:[A(`span`,{id:`${r}-promo-code-label`,children:`Promo code`}),j(`div`,{className:`lockerverse-payment__promo-control`,children:[A(`input`,{"aria-describedby":c?`${r}-promo-code-error`:void 0,"aria-invalid":c?`true`:void 0,"aria-labelledby":`${r}-promo-code-label`,name:`promoCode`,onChange:e=>u({promoCode:e.currentTarget.value}),placeholder:`Optional`,value:l.promoCode}),A(`button`,{disabled:!l.promoCode.trim()||i,onClick:s,type:`button`,children:i?`Applying…`:`Apply`})]}),c?A(`p`,{className:`lockerverse-payment__field-message`,id:`${r}-promo-code-error`,role:`alert`,children:c}):null]}):null,A(f,{choiceClassName:`lockerverse-payment__check-row`,errorClassName:`lockerverse-payment__field-message`,errors:t,fields:e,idPrefix:r,onChange:e=>u({customFields:e}),values:l.customFields})]})}function fe({amountCents:t,enabled:n,onChange:r,values:i}){return n?j(X,{checked:i.includeServiceFee,name:`includeServiceFee`,onChange:e=>r({...i,includeServiceFee:e}),children:[`Add `,e(t),` to help cover processing fees`]}):null}function pe(e){return{error:void 0,message:void 0,status:e?`recovering`:`editing`}}function Z(e,t,n){return t.includes(e.status)?{...e,...n}:e}function Q(e,t){if(t.type===`recovery_started`&&e.status===`unresolved`)return{...e,message:void 0,status:`recovering`};if(e.status===`sold_out`||e.status===`succeeded`||e.status===`unresolved`)return e;switch(t.type){case`field_changed`:return Z(e,[`editing`,`invalid`,`refreshing_quote`],{error:void 0,status:`editing`});case`validation_failed`:return Z(e,[`editing`],{status:`invalid`});case`quote_refresh_started`:return Z(e,[`editing`,`invalid`],{status:`refreshing_quote`});case`quote_refresh_succeeded`:return Z(e,[`refreshing_quote`],{error:void 0,status:`editing`});case`quote_refresh_failed`:return Z(e,[`refreshing_quote`],{error:t.error??e.error,status:`editing`});case`submission_started`:return Z(e,[`editing`,`invalid`,`refreshing_quote`],{error:void 0,status:`submitting`});case`submission_validation_failed`:return Z(e,[`submitting`],{error:void 0,status:`invalid`});case`quote_changed`:return Z(e,[`submitting`],{status:`editing`});case`retryable_failure`:return Z(e,[`editing`,`invalid`,`submitting`],{error:t.error,status:`editing`});case`recovery_failed`:return Z(e,[`recovering`],{error:t.error,retryUrl:void 0,status:`editing`});case`sold_out`:return{error:void 0,message:void 0,status:`sold_out`};case`succeeded`:return Z(e,[`recovering`,`submitting`],{message:t.message,retryUrl:void 0,status:`succeeded`});case`unresolved`:return Z(e,[`recovering`,`submitting`],{message:t.message,retryUrl:t.retryUrl,status:`unresolved`});default:return e}}function me(e){return e.status===`editing`||e.status===`invalid`||e.status===`refreshing_quote`?e.error:void 0}function he(e){return e.status===`sold_out`?`sold_out`:e.status===`succeeded`?`success`:e.status===`unresolved`?`unresolved`:e.status===`submitting`||e.status===`recovering`?`submitting`:e.status===`invalid`?`invalid`:me(e)?`error`:`idle`}function ge(e){return e.status===`submitting`}const _e=[`amountCents`,`discountableSubtotalCents`,`discountCents`,`serviceFeeCents`,`subtotalCents`,`tipCents`,`totalCents`],ve=[`discountableSubtotalCents`,`discountCents`,`subtotalCents`];function ye(e,t,n,r){return(n===t.totalCents?ve:_e).some(n=>e[n]!==t[n])||r!==t.payment.connectedAccountId||e.authoritative&&(e.payment.connectedAccountId!==r||e.payment.currency!==t.payment.currency)||JSON.stringify(e.appliedDiscount)!==JSON.stringify(t.appliedDiscount)||JSON.stringify(e.lineItems)!==JSON.stringify(t.lineItems)}function be(e){if(e.checkoutStatus===`success`)return{kind:`success`,payment:e};if(e.checkoutStatus===`failed`)return{kind:`failed`,payment:e};let t={kind:`unresolved`,paymentReference:e.paymentReference,reason:e.checkoutStatus===`action_required`?`action_required`:`pending`};return e.retryUrl&&(t.retryUrl=e.retryUrl),t}async function xe(e,t,n){if(t.checkoutStatus!==`action_required`||!t.requiresAction)return be(t);if(!n)return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`};if(t.clientSecret)try{await n.handleNextAction({clientSecret:t.clientSecret})}catch{}try{return be(await e.getPaymentStatus(t.paymentReference))}catch{return{kind:`unresolved`,paymentReference:t.paymentReference,reason:`action_required`}}}async function Se(e,t,n){let r;try{r=await e.submitPayment(t)}catch(n){if(!(n instanceof M&&n.recoveryRecommended))throw n;try{r=await e.getPaymentStatus(t.checkout.paymentReference)}catch{return{kind:`unresolved`,paymentReference:t.checkout.paymentReference,reason:`recovery_failed`}}}return xe(e,r,n)}async function Ce(e,t,n){try{return xe(e,await e.getPaymentStatus(t),n)}catch{return{kind:`unresolved`,paymentReference:t,reason:`recovery_failed`}}}const we=W(q(),oe(),te()),Te=W(re(),ie(),V(1)),Ee=W(z(se([ae({amountCents:Te,productSlug:we}),ae({productSlug:we,quantity:Te}),ae({productSlug:we})])),ee(1)),De=W(q(),oe(),G(/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/,`Enter a valid tip amount.`));function Oe(e){let t=K(De,e);if(!t.success)return{message:t.issues[0]?.message??`Enter a valid tip amount.`,success:!1};let[n=`0`,r=``]=t.output.split(`.`),i=BigInt(n)*100n+BigInt(r.padEnd(2,`0`));return i>BigInt(2**53-1)?{message:`Enter a valid tip amount.`,success:!1}:{cents:Number(i),success:!0}}function ke(e){let t=K(Ee,e);return t.success?{success:!0,value:t.output}:{message:`Lockerverse payment configuration is invalid.`,success:!1}}const Ae=`This promo code is invalid or cannot be applied.`;function je(e,t){return t.tipPercent===`custom`?t.customTip.trim()?Oe(t.customTip):{cents:0,success:!0}:{cents:Math.round(e*Number(t.tipPercent)/100),success:!0}}function Me(e,t,n,r){let i={};return n&&(i.email=n),e.widget.fields.serviceFee&&(i.includeServiceFee=t.includeServiceFee),e.widget.fields.promoCode&&t.promoCode.trim()&&(i.promoCode=t.promoCode.trim()),e.widget.fields.tipping&&(i.tipCents=r),i}function Ne(e,t,n){let r=e.widget.fields.tipping?je(n.subtotalCents,t):{cents:0,success:!0};if(!r.success)return{parsedTip:r,totalCents:null};let i=e.widget.fields.serviceFee&&t.includeServiceFee?n.serviceFeeCents||Math.round(n.subtotalCents*e.pricingPolicy.serviceFeeRateBasisPoints/1e4):0;return{parsedTip:r,totalCents:n.totalCents-n.serviceFeeCents-n.tipCents+i+r.cents}}function Pe(e,t){return{displayedTotalCents:e.totalCents,promoError:t&&e.appliedDiscount?.source!==`promo_code`?Ae:void 0}}function Fe(e,t){let n;return t||(n=e instanceof Error?e.message:`The order total could not be updated.`),{paymentError:n,promoError:t?Ae:void 0}}function Ie(e,t){if(!e?.complete)throw Error(`${t} address is required.`);return e.value}function Le(e,t,n,r){if(e.widget.fields.shipping)return t.shippingMatchesBilling?n:Ie(r.shipping,`Shipping`)}function Re({billingAddress:e,catalog:t,email:n,phone:r,shippingAddress:i}){let a={payment_method_data:{billing_details:t.widget.fields.phone?{address:e.address,email:n,name:e.name,phone:r}:{address:e.address,email:n,name:e.name}}};return i?{...a,shipping:{address:i.address,name:i.name,phone:t.widget.fields.phone?r:i.phone??null}}:a}function ze({catalog:e,checkoutItems:t,confirmationToken:n,email:r,fieldValues:i,metadata:a,phone:o,shippingAddress:s}){let c={customFieldAnswers:p(u(e,t),i.customFields),email:r};if(n&&(c.confirmationToken=n),a&&(c.metadata=a),e.widget.fields.memberId&&i.memberId.trim()&&(c.memberId=i.memberId.trim()),e.widget.fields.merchSize&&(c.merchSize=i.merchSize),e.widget.fields.phone&&(c.phone=o),s){let e={city:s.address.city??``,country:s.address.country,line1:s.address.line1??``,postal_code:s.address.postal_code??``,state:s.address.state??``};s.address.line2&&(e.line2=s.address.line2),c.shipping={address:e,name:s.name}}return c}function Be(e){if(!e())throw Error(`Payment component is no longer active.`)}function Ve(e,n){t(e,n)}function He(e,t,n,r){return e.kind===`failed`?{kind:`payment_failed`,message:r}:e.kind===`unresolved`?{kind:`payment_unresolved`,paymentReference:e.paymentReference,reason:e.reason,retryUrl:e.retryUrl}:{email:n,kind:`payment`,payment:e.payment,quote:t}}async function Ue({addresses:e,catalog:t,checkoutItems:n,client:r,elements:i,email:a,fieldValues:o,isAttemptActive:s,locallyPreviewedTotalCents:c,metadata:l,onPaymentRecoveryChange:u,phone:d,quote:f,stripe:p,stripeConnectedAccountId:m}){let h=a.trim().toLowerCase(),g=y(d),_=je(f.subtotalCents,o);if(!_.success)throw Error(_.message);let v=await r.calculateTotal({...Me(t,o,h,_.cents),catalog:t,items:n});if(Be(s),v.totalCents>0&&ye(f,v,c,m))return{kind:`quote_changed`,quote:v};let b,x;if(v.totalCents===0)t.widget.fields.shipping&&(b=Le(t,o,Ie(e.billing,`Billing`),e));else{if(!(i&&p))throw Error(`Payment form is still loading.`);await i.update({amount:v.totalCents}),Be(s);let n=await i.submit();if(Be(s),n.error)throw Error(n.error.message);let r=Ie(e.billing,`Billing`);b=Le(t,o,r,e);let a=await p.createConfirmationToken({elements:i,params:Re({billingAddress:r,catalog:t,email:h,phone:g,shippingAddress:b})});if(Be(s),a.error)throw Error(a.error.message);x=a.confirmationToken.id}Ve(u,{connectedAccountId:v.payment.connectedAccountId,paymentReference:v.paymentReference});let S=await Se(r,{checkout:v,submission:ze({catalog:t,checkoutItems:n,confirmationToken:x,email:h,fieldValues:o,metadata:l,phone:g,shippingAddress:b})},p);return Be(s),He(S,v,h,v.totalCents===0?`Order could not be completed. Review the details and try again.`:`Payment was declined. Check your payment details and try again.`)}function We(e,n){t(e,n)}function Ge(e,n){t(e,n)}function Ke(e,t){return{...e,...t}}function qe(e){let t={message:e.reason===`action_required`?`Payment needs your attention. Keep this checkout open.`:`Payment is not complete. Check its status before you try again.`,type:`unresolved`};return e.retryUrl&&(t.retryUrl=e.retryUrl),t}function Je(e,t,n){return e.kind===`unresolved`&&e.reason===`action_required`&&!e.retryUrl&&!t&&!n}function Ye(e){return e instanceof M&&e.serverCode===`PAYMENT_WIDGET_SALES_LIMIT_REACHED`}function Xe({nextQuote:e,onQuoteChange:t,setDisplayedTotalCents:n,setPromoError:r,updateState:i,validatePromo:a}){let o=Pe(e,a);i({type:`quote_refresh_succeeded`}),n(o.displayedTotalCents),t(e),a&&r(o.promoError)}function Ze({error:e,setPromoError:t,updateState:n,validatePromo:r}){let i=Fe(e,r);r&&t(i.promoError),n(i.paymentError===void 0?{type:`quote_refresh_failed`}:{error:i.paymentError,type:`quote_refresh_failed`})}function Qe({onPaymentComplete:n,onPaymentRecoveryChange:r,onPaymentUncertain:i,onQuoteChange:a,result:o,setDisplayedTotalCents:s,dispatchState:c,unresolvedReferenceRef:l}){if(o.kind===`quote_changed`){let t=`The total changed to ${e(o.quote.totalCents)}. Review it and pay again.`;a(o.quote,t),s(o.quote.totalCents),c({type:`quote_changed`});return}if(o.kind===`payment_failed`){We(r,null),c({error:o.message,type:`retryable_failure`});return}if(o.kind===`payment_unresolved`){l.current=o.paymentReference,c(qe(o)),Ge(i,{paymentReference:o.paymentReference,reason:o.reason});return}a(o.quote),We(r,null),c({message:o.payment.paymentRequired?`Payment completed successfully.`:`Order confirmed. No payment was required.`,type:`succeeded`}),t(n,Ke(o.payment,{email:o.email,lineItems:o.quote.lineItems}))}function $e(e){let{catalog:n,checkoutItems:r,client:i,elements:o,email:s,fieldValues:c,metadata:l,onPaymentComplete:u,onResumePaymentFailed:d,onPaymentRecoveryChange:f,onPaymentUncertain:p,onQuoteChange:m,onStateChange:h,quote:g,resumePayment:v,stripe:y,stripeConnectedAccountId:b,stripeLoadFailed:C,paymentState:w,updateState:T}=e,[E,k]=O(g.totalCents),[A,j]=O(),N=D(!1),P=D(void 0),F=D(0),I=D(0),L=x(e=>T(e,!0),[T]),R=x(()=>{let e=I.current+1;return I.current=e,()=>I.current===e},[]);S(()=>()=>{I.current+=1,F.current+=1},[]);let{parsedTip:z,totalCents:B}=Ne(n,c,g);S(()=>{B!==null&&(k(B),B>0&&o?.update({amount:B}))},[n.pricingPolicy.serviceFeeRateBasisPoints,n.widget.fields.serviceFee,o,c.includeServiceFee,B,g.serviceFeeCents,g.tipCents,g.totalCents,g.subtotalCents]),S(()=>{let e=v?.paymentReference??P.current;if(!e||N.current||w.status!==`recovering`)return;N.current=!0;let n=R();return h(he(w)),Ce(i,e,y).then(e=>{if(n()&&!Je(e,y,C)){if(e.kind===`failed`){We(f,null),d(),L({error:`The previous payment failed. Check your details and try again.`,type:`recovery_failed`});return}if(e.kind===`unresolved`){L(qe(e)),Ge(p,{paymentReference:e.paymentReference,reason:e.reason});return}We(f,null),L({message:e.payment.paymentRequired?`Payment completed successfully.`:`Order confirmed. No payment was required.`,type:`succeeded`}),t(u,Ke(e.payment,{email:null,lineItems:null}))}}),()=>{n()&&(I.current+=1),N.current=!1}},[i,u,d,f,p,h,v,y,C,R,L,w]);let ee=x((e=!1,t=!1)=>{t||(F.current+=1),e&&j(void 0),T({type:`field_changed`})},[T]);async function V(e=!1,t=!1){let a=s.trim().toLowerCase(),o=_({email:a,phone:``},!1);if(!(z.success&&(o.value||e)))return;F.current+=1;let l=F.current;T({type:`quote_refresh_started`});try{let e=await i.calculateTotal({...Me(n,c,o.value?.email??``,z.cents),catalog:n,items:r});if(l!==F.current)return;Xe({nextQuote:e,onQuoteChange:m,setDisplayedTotalCents:k,setPromoError:j,updateState:T,validatePromo:t})}catch(e){if(l!==F.current)return;if(Ye(e)){T({type:`sold_out`});return}Ze({error:e,setPromoError:j,updateState:T,validatePromo:t})}}async function te(){j(void 0),await V(!0,!0)}async function ne({addresses:e,phone:t}){L({type:`submission_started`});let d=R();try{let a=await Ue({addresses:e,catalog:n,checkoutItems:r,client:i,elements:o,email:s,fieldValues:c,isAttemptActive:d,locallyPreviewedTotalCents:E,metadata:l,onPaymentRecoveryChange:f,phone:t,quote:g,stripe:y,stripeConnectedAccountId:b});if(!d())return;Qe({dispatchState:L,onPaymentComplete:u,onPaymentRecoveryChange:f,onPaymentUncertain:p,onQuoteChange:m,result:a,setDisplayedTotalCents:k,unresolvedReferenceRef:P})}catch(e){if(!d())return;if(We(f,null),Ye(e)){L({type:`sold_out`});return}let t=e instanceof M?a(e.serverCode):void 0;if(t)return L({type:`submission_validation_failed`}),{phoneError:t};L({error:e instanceof Error?e.message:`Payment could not be completed.`,type:`retryable_failure`})}}let re=w.status===`succeeded`||w.status===`unresolved`?w.message:void 0;return{commands:{applyPromo:te,checkPaymentStatus:()=>L({type:`recovery_started`}),fieldChanged:ee,refreshAuthoritativeTotal:V,reportStripeLoadError:e=>L({error:e,type:`retryable_failure`}),reportValidationFailure:()=>L({type:`validation_failed`}),submit:ne},state:{displayedTotalCents:E,isRecovering:w.status===`recovering`,isRefreshingQuote:w.status===`refreshing_quote`,isSubmitting:ge(w),isUnresolved:w.status===`unresolved`,parsedTip:z,paymentError:me(w),promoError:A,retryUrl:w.retryUrl,terminalMessage:re}}}const et=b;function tt(e){let{connectedAccountId:t,publishableKey:n}=e.payment;return et(n,t?{stripeAccount:t}:void 0)}function nt(e){return e===`monthly`?{interval:`month`,label:`Monthly`}:e===`annually`?{interval:`year`,label:`Annual`}:e===`every-six-months`?{interval:`6 months`,label:`Every 6 months`}:null}function rt(e,t,n){if(n){let{connectedAccountId:e}=n;return e}if(`payment`in t){let{connectedAccountId:e}=t.payment;return e}let{connectedAccountId:r}=e.payment;return r}function it({accentColor:e,catalog:t,checkoutItems:n,client:r,appearanceRoot:i,initialCustomFieldValues:a,metadata:o,onPaymentComplete:s,onResumePaymentFailed:c,onPaymentRecoveryChange:l,onPaymentUncertain:u,onQuoteChange:d,quote:f,resumePayment:p,onStateChange:m,stripeLoader:g,theme:_,visualStyle:y}){let[b,C]=O(()=>pe(!!p)),w=D(b);w.current=b;let E=x((e,t=!1)=>{let n=Q(w.current,e);n!==w.current&&(w.current=n,C(n),t&&m(he(n)))},[m]),k=rt(t,f,p),j=D({connectedAccountId:k,paymentOption:f.paymentOption});b.status!==`submitting`&&b.status!==`recovering`&&(j.current={connectedAccountId:k,paymentOption:f.paymentOption});let{connectedAccountId:M,paymentOption:N}=j.current,P=T(()=>g(t.payment.publishableKey,M?{stripeAccount:M}:void 0).catch(()=>null),[t.payment.publishableKey,M,g]),[I,L]=O(!1);S(()=>{let e=!0;return L(!1),P.then(t=>{e&&t===null&&L(!0)}),()=>{e=!1}},[P]);let R=v(i,_,y,b.status===`submitting`||b.status===`recovering`,e);return R?A(F,{options:{amount:Math.max(f.totalCents,100),appearance:R,currency:t.payment.currency,excludedPaymentMethodTypes:t.community?.widgetAchEnabled?[]:[`us_bank_account`],mode:N===`one-time`?`payment`:`subscription`,syncAddressCheckbox:`none`},stripe:P,children:A(mt,{catalog:t,checkoutItems:n,client:r,initialCustomFieldValues:a,metadata:o,onPaymentComplete:s,onPaymentRecoveryChange:l,onPaymentUncertain:u,onQuoteChange:d,onResumePaymentFailed:c,onStateChange:m,paymentState:b,quote:f,resumePayment:p,stripeConnectedAccountId:M,stripeLoadFailed:I,updateState:E})},`${t.payment.publishableKey}:${M??`platform`}:${N}`):A(h,{fieldCount:3,label:`Loading payment form`})}function at({label:e}){return j(`div`,{className:`lockerverse-payment__stripe-loader`,role:`status`,children:[A(`p`,{children:e}),j(`div`,{"aria-hidden":`true`,children:[A(`span`,{}),A(`span`,{}),A(`span`,{})]})]})}function ot({onError:e,onReady:t,ready:n}){return j(`div`,{className:`lockerverse-payment__stripe-element`,"data-ready":n,children:[n?null:A(at,{label:`Loading payment form...`}),A(`div`,{className:`lockerverse-payment__stripe-mount`,children:A(I,{onLoadError:({error:t})=>e(t.message??`Payment form failed to load.`),onReady:t,options:{business:{name:`Lockerverse`},fields:{billingDetails:{address:`never`,email:`never`,name:`never`,phone:`never`}},layout:`tabs`,terms:{applePay:`auto`,auBecsDebit:`never`,bancontact:`never`,card:`always`,cashapp:`never`,googlePay:`never`,ideal:`never`,paypal:`auto`,sepaDebit:`never`,sofort:`never`,usBankAccount:`auto`},wallets:{applePay:`auto`,googlePay:`never`}}})})]})}function st({label:e,mode:t,onChange:n,onError:r,onReady:i,ready:a}){return j(`div`,{className:`lockerverse-payment__address`,children:[A(`h2`,{children:e}),j(`div`,{className:`lockerverse-payment__stripe-element lockerverse-payment__stripe-element--address`,"data-ready":a,children:[a?null:A(at,{label:`Loading ${e.toLowerCase()}...`}),A(`div`,{className:`lockerverse-payment__stripe-mount`,children:A(P,{onChange:n,onLoadError:({error:t})=>r(t.message??`${e} failed to load.`),onReady:i,options:{autocomplete:{mode:`automatic`},mode:t}})})]})]})}function ct({message:e}){return e?A(`p`,{className:`lockerverse-payment__field-message`,role:`alert`,children:e}):null}function lt({catalog:e,displayedTotalCents:t,fieldValues:n,isBillingAddressReady:r,isPaymentReady:i,isShippingAddressReady:a,onAddressChange:o,onFieldValuesChange:s,onStripeLoadError:c,setIsBillingAddressReady:l,setIsPaymentReady:u,setIsShippingAddressReady:d}){let f=t>0;return j(k,{children:[f?A(ot,{onError:c,onReady:()=>u(!0),ready:i}):null,f||e.widget.fields.shipping?A(st,{label:f?`Billing address`:`Shipping address`,mode:`billing`,onChange:e=>o(`billing`,e),onError:c,onReady:()=>l(!0),ready:r}):null,e.widget.fields.shipping?j(`div`,{className:`lockerverse-payment__shipping`,children:[A(X,{checked:n.shippingMatchesBilling,name:`shippingMatchesBilling`,onChange:e=>{s({...n,shippingMatchesBilling:e}),e?o(`shipping`,null):d(!1)},children:`Shipping is same as billing information`}),n.shippingMatchesBilling?null:A(st,{label:`Shipping address`,mode:`shipping`,onChange:e=>o(`shipping`,e),onError:c,onReady:()=>d(!0),ready:a})]}):null]})}function ut({catalog:t,displayedTotalCents:n,fieldValues:r,isBillingAddressReady:i,isPaymentReady:a,isRequiredShippingReady:o,isSubmitting:s,onFieldValuesChange:c,quote:l}){let u=n===0,d=u?!t.widget.fields.shipping||i&&o:a&&i&&o,f=nt(l.paymentOption),p=u?`Complete order`:`Pay ${e(n)}`;!u&&f&&(p=`Subscribe for ${e(n)}/${f.interval}`),s&&(p=u?`Completing…`:`Processing…`);let m=`Process payment for ${e(n)} total`;return u?m=`Complete order`:f&&(m=`Start ${f.label.toLowerCase()} subscription for ${e(n)}`),j(`div`,{className:`lockerverse-payment__actions`,children:[A(fe,{amountCents:l.serviceFeeCents||Math.round(l.subtotalCents*t.pricingPolicy.serviceFeeRateBasisPoints/1e4),enabled:t.widget.fields.serviceFee,onChange:c,values:r}),A(`button`,{"aria-busy":s,"aria-label":m,disabled:s||!d,type:`submit`,children:p})]})}function dt(e,t){let n=e.elements.namedItem(t);if(n instanceof HTMLElement){n.focus();return}n instanceof RadioNodeList&&Array.from(n).find(e=>e instanceof HTMLElement)?.focus()}function ft({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&&dt(n,`custom:${o}`)}function pt({email:e,emailDiscountPercentOff:t,emailErrorId:n,emailId:r,emailRef:a,errors:o,onEmailBlur:l,onEmailChange:u,onPhoneChange:d,phone:f,phoneCountry:p,phoneEnabled:m,phoneErrorId:h,phoneId:g,phoneRef:_}){return j(`div`,{className:`lockerverse-payment__contact`,children:[A(i,{error:o.email,errorId:n,id:r,label:`Email`,name:`email`,onBlur:l,onChange:e=>u(e.currentTarget.value),ref:a,required:!0,value:e}),t===void 0?null:j(`p`,{className:`lockerverse-payment__discount-message`,role:`status`,children:[`Your email qualifies for `,t,`% off.`]}),m?A(s,{error:o.phone,errorId:h,id:g,label:`Phone`,children:A(c,{country:p,error:o.phone,errorId:h,id:g,inputRef:_,name:`phone`,onChange:d,required:!0,value:f})}):null]})}function mt({catalog:e,checkoutItems:t,client:n,initialCustomFieldValues:r,metadata:i,onPaymentComplete:a,onResumePaymentFailed:s,onPaymentRecoveryChange:c,onPaymentUncertain:l,onQuoteChange:f,onStateChange:p,quote:h,resumePayment:v,stripeConnectedAccountId:y,stripeLoadFailed:b,paymentState:x,updateState:w}){let T=u(e,t),[E,M]=O(``),[N,P]=O(``),[F,I]=O(`US`),[z,B]=O({}),[ee,V]=O({}),[te,ne]=O(),[re,H]=O(!1),[U,W]=O(!1),[G,ie]=O(!1),[K,ae]=O(()=>({customFields:d(T,r),customTip:``,includeServiceFee:e.widget.fields.serviceFee,memberId:``,merchSize:`M`,promoCode:``,shippingMatchesBilling:!0,tipPercent:`10`})),q=D({billing:null,shipping:null}),oe=D(null),se=D(null),ce=D(null),le=D(h.totalCents>0),J=$e({catalog:e,checkoutItems:t,client:n,elements:L(),email:E,fieldValues:K,metadata:i,onPaymentComplete:a,onPaymentRecoveryChange:c,onPaymentUncertain:l,onQuoteChange:f,onResumePaymentFailed:s,onStateChange:p,paymentState:x,quote:h,resumePayment:v,stripe:R(),stripeConnectedAccountId:y,stripeLoadFailed:b,updateState:w}),{displayedTotalCents:Y,isRecovering:X,isUnresolved:fe,isRefreshingQuote:pe,isSubmitting:Z,parsedTip:Q,paymentError:me,promoError:he,terminalMessage:ge,retryUrl:_e}=J.state,ve=`lockerverse-${C()}`,ye=`${ve}-email`,be=`${ye}-error`,xe=`${ve}-phone`,Se=`${xe}-error`,Ce=`${ve}-tip-error`,we=(Q.success?Q.cents:null)??0,Te=Y-we,Ee=!e.widget.fields.shipping||K.shippingMatchesBilling||G;S(()=>{Z&&ce.current?.focus({preventScroll:!0})},[Z]),S(()=>{Z||z.email||!z.phone||se.current?.focus()},[z.email,z.phone,Z]),S(()=>{let e=Y>0;e&&!le.current&&(H(!1),W(!1)),le.current=e},[Y]);function De(e){J.commands.fieldChanged(!1,e!==`email`),B(t=>{let n={...t};return delete n[e],n})}function Oe(e){let t=e.promoCode!==K.promoCode,n=e.includeServiceFee!==K.includeServiceFee;J.commands.fieldChanged(t,!(t||n)),ae(e),V({}),ne(void 0)}async function ke(t){t.preventDefault();let n=e.widget.fields.phone?o(N,F):``,r=_({email:E,phone:n},e.widget.fields.phone),i=m(T,K.customFields);if(!(r.value&&Q.success)||Object.keys(i).length>0){B(r.errors),V(i),ne(Q.success?void 0:Q.message),J.commands.reportValidationFailure();let e=t.currentTarget;queueMicrotask(()=>{ft({customFieldErrors:i,emailRef:oe,form:e,parsedTipSuccess:Q.success,phoneRef:se,validationErrors:r.errors})});return}B({}),V({});let a=await J.commands.submit({addresses:q.current,phone:n});a?.phoneError&&B({phone:a.phoneError})}return ge||X?j(`div`,{className:`lockerverse-payment__actions`,children:[j(`p`,{className:`lockerverse-payment__payment-status`,ref:ce,role:`status`,tabIndex:-1,children:[X?`Recovering payment…`:ge,_e?j(k,{children:[` `,A(`a`,{href:_e,rel:`noopener noreferrer`,target:`_blank`,children:`Complete payment`})]}):null]}),fe||X?A(`button`,{"aria-busy":X,className:`lockerverse-payment__status-check`,disabled:X,onClick:J.commands.checkPaymentStatus,type:`button`,children:X?`Checking payment status…`:`Check payment status`}):null]}):j(`form`,{"aria-busy":Z,className:`lockerverse-payment__form`,noValidate:!0,onSubmit:ke,children:[A(`div`,{"data-lockerverse-input-region":``,inert:Z?!0:void 0,children:j(`fieldset`,{className:`lockerverse-payment__input-fieldset`,disabled:Z,children:[A(g,{displayedBaseCents:Te,displayedTipCents:we,displayedTotalCents:Y,quote:h}),A(ue,{enabled:e.widget.fields.tipping,error:te,errorId:Ce,onChange:Oe,values:K}),A(pt,{email:E,emailDiscountPercentOff:h.appliedDiscount?.source===`email_list`?h.appliedDiscount.percentageOff:void 0,emailErrorId:be,emailId:ye,emailRef:oe,errors:z,onEmailBlur:()=>J.commands.refreshAuthoritativeTotal(),onEmailChange:e=>{M(e),De(`email`)},onPhoneChange:({value:e,country:t})=>{P(e),I(t),De(`phone`)},phone:N,phoneCountry:F,phoneEnabled:e.widget.fields.phone,phoneErrorId:Se,phoneId:xe,phoneRef:se}),A(lt,{catalog:e,displayedTotalCents:Y,fieldValues:K,isBillingAddressReady:U,isPaymentReady:re,isShippingAddressReady:G,onAddressChange:(e,t)=>{q.current[e]=t},onFieldValuesChange:Oe,onStripeLoadError:J.commands.reportStripeLoadError,setIsBillingAddressReady:W,setIsPaymentReady:H,setIsShippingAddressReady:ie}),A(de,{customFields:T,errors:ee,fields:e.widget.fields,idPrefix:ve,isPromoApplying:pe,memberIdLabel:e.community?.memberIdLabel,onApplyPromo:J.commands.applyPromo,onChange:Oe,promoError:he,values:K}),A(ut,{catalog:e,displayedTotalCents:Y,fieldValues:K,isBillingAddressReady:U,isPaymentReady:re,isRequiredShippingReady:Ee,isSubmitting:Z,onFieldValuesChange:Oe,quote:h})]})}),Z?A(`p`,{className:`lockerverse-payment__sr-only`,ref:ce,role:`status`,tabIndex:-1,children:Y===0?`Completing order…`:`Processing payment…`}):null,A(ct,{message:me})]})}function ht(){return A(h,{fieldCount:2,label:`Loading payment…`,sectionCount:2,showCheckbox:!0})}function gt(e,t){switch(t.type){case`loading`:return{phase:`loading`,revision:e.revision};case`ready`:return yt(t.displayedQuote,e.revision+1);case`error`:return{failure:t.failure,phase:`error`,revision:e.revision};case`checkout`:return e.phase===`ready`?{...e,displayedQuote:t.checkout,quoteFailure:void 0}:e;case`quote-error`:return e.phase===`ready`?{...e,quoteFailure:t.failure}:e;default:return e}}function $(e,t,n){return e?.catalog===t&&e.selectionKey===n}function _t({checkout:e}){return{displayedQuote:e,type:`ready`}}function vt(e){return e instanceof Error?e.message:`Lockerverse payment could not load.`}function yt(e,t){return{checkoutItems:[...e.items],displayedQuote:e,phase:`ready`,quoteFailure:void 0,revision:t}}function bt(e,t){let n=e.widget.fields.serviceFee;return N(e,{includeServiceFee:n,selection:t})}function xt(e,t){try{return yt(bt(e,t),1)}catch(e){return{failure:vt(e),phase:`error`,revision:0}}}function St({catalog:e,client:t,paymentState:n,selection:r}){let i=ke(r),a=i.success?JSON.stringify(i.value):`invalid-selection`,o=T(()=>i.success?i.value:[],[i.success,a]),[s,c]=E(gt,void 0,()=>i.success?xt(e,o):{phase:`loading`,revision:0}),l=D(void 0),u=D(0),d=D(s.phase===`ready`?{catalog:e,selectionKey:a}:void 0),f=D(s.phase===`error`?{catalog:e,selectionKey:a}:void 0),p=n===`submitting`||n===`success`||n===`unresolved`;S(()=>{if(!i.success||p||$(f.current,e,a)||$(l.current,e,a))return;let n=!0;l.current={catalog:e,selectionKey:a};let r=$(d.current,e,a);r||c({type:`loading`});function s(e){n&&c(e)}function m(){n&&(l.current=void 0,f.current={catalog:e,selectionKey:a})}let h;function g(t){if(!n||(l.current=void 0,f.current={catalog:e,selectionKey:a},r&&h!==void 0&&u.current!==h))return;let i=vt(t);if(i===`This option is sold out.`){c({failure:i,type:`error`});return}c(r?{failure:i,type:`quote-error`}:{failure:i,type:`error`})}async function _(){try{h=u.current;let n=e.widget.fields.serviceFee;if(!r){let t=bt(e,o);r=!0,d.current={catalog:e,selectionKey:a},s(_t({checkout:t}))}let i=await t.calculateTotal({catalog:e,includeServiceFee:n,selection:o});m(),u.current===h&&s({checkout:i,type:`checkout`})}catch(e){g(e)}}return _(),()=>{n=!1,$(l.current,e,a)&&(l.current=void 0)}},[e,t,i.success,p,a,o]);let m=$(d.current,e,a)||$(f.current,e,a)||$(l.current,e,a),h=p||m?s:{phase:`loading`,revision:s.revision};return{selectionError:i.success?void 0:i.message,session:h,updateCheckout:e=>{u.current+=1,c({checkout:e,type:`checkout`})}}}const Ct=H({recovery:H({connectedAccountId:ne(q()),paymentReference:W(q(),oe(),te())}),selectionFingerprint:q(),version:se([B(1),B(2)]),widgetId:U(q())});function wt(e){let t=ke(e);return t.success?JSON.stringify(t.value.map(e=>{let t=e.productSlug.trim();return`quantity`in e?[`quantity`,t,e.quantity]:`amountCents`in e?[`amount`,t,e.amountCents]:[`product`,t]})):null}const Tt=`A previous payment uses different checkout details. Return to its original checkout to check the payment before you pay again.`;function Et(e,t,n){let r;try{r=window.sessionStorage.getItem(e)}catch{return{recovery:null}}if(!r)return{recovery:null};try{let e=K(Ct,JSON.parse(r));if(!e.success)throw Error(`Invalid recovery record`);let i=e.output;return i.selectionFingerprint!==t||i.version===2&&i.widgetId!==n?{error:Tt,recovery:null}:{recovery:{connectedAccountId:i.recovery.connectedAccountId,paymentReference:i.recovery.paymentReference}}}catch{return{error:`The saved payment could not be read. Contact support to check it before you pay again.`,recovery:null}}}function Dt({selection:e,storageKey:t,widgetId:n}){let r=wt(e),i=JSON.stringify([t,r,n]),[a,o]=O(null),s=D(null);S(()=>{if(!t)return;let e=s.current,a={recovery:null};e?.recovery?a=e.identity===i?{recovery:e.recovery}:{error:Tt,recovery:null}:r!==null&&(a=Et(t,r,n)),a.recovery&&(s.current={identity:i,recovery:a.recovery}),o({identity:i,...a})},[r,i,t,n]);let c=x(e=>{if(!(!t||r===null)){s.current=e?{identity:i,recovery:e}:null;try{e?window.sessionStorage.setItem(t,JSON.stringify({recovery:e,selectionFingerprint:r,version:2,widgetId:n})):window.sessionStorage.removeItem(t)}catch{}}},[r,i,t,n]);return{error:t&&a?.identity===i?a.error:void 0,ready:!t||a?.identity===i,recovery:t&&a?.identity===i?a.recovery:null,remember:c}}const Ot={annually:`/year`,"every-six-months":` every 6 months`,monthly:`/month`,"one-time":``};function kt({branding:e,catalog:t}){return j(`header`,{children:[t.widget.showCommunityBranding&&e?j(`div`,{className:`lockerverse-payment__branding`,children:[e.imageUrl?A(`img`,{alt:e.name,height:`48`,src:e.imageUrl,width:`48`}):null,A(`strong`,{children:e.name})]}):null,A(`h1`,{children:t.widget.title??t.widget.name}),t.widget.description?A(`p`,{children:t.widget.description}):null]})}function At({catalog:t,selection:n}){let r=n?.length?t.products.filter(e=>n.some(t=>t.productSlug===e.slug)):t.products;return r.length===0?null:j(`div`,{className:`lockerverse-payment__payment-summary`,children:[A(`h2`,{children:`Products`}),A(`div`,{className:`lockerverse-payment__payment-summary-items`,children:r.map(t=>{let n=t.pricingMode===`fixed`?t.amountCents:t.minimumAmountCents,r=Ot[t.paymentOption];return j(`div`,{className:`lockerverse-payment__payment-summary-row`,children:[A(`span`,{children:t.name}),A(`strong`,{children:n===null?`Choose amount`:`${t.pricingMode===`custom`?`From `:``}${e(n)}${r}`})]},t.id)})}),A(`p`,{children:`Base prices. Final total is checked at checkout.`})]})}function jt(e,t){let i=n(e?.[`--lockerverse-accent`]??t?.accentColor??`#38d77a`),a=r(i),o={...e};return(e?.[`--lockerverse-accent`]!==void 0||t?.accentColor)&&(o[`--lockerverse-accent`]=i),a&&e?.[`--lockerverse-accent-contrast`]===void 0&&(o[`--lockerverse-accent-contrast`]=a),{accent:i,rootStyle:o}}function Mt({catalog:e,client:n,loadError:r,onRetry:i,...a}){let{branding:o,className:s,completionView:c,recoveryStorageKey:l,initialCustomFieldValues:u,metadata:d,onPaymentComplete:f,onPaymentRecoveryChange:p,onPaymentUncertain:m,resumePayment:h,selection:g,style:_,stripeLoader:v=et,theme:y=`dark`,...b}=a,[C,T]=O(h),E=D(null),[k,M]=O(null),N=x(e=>{M(e),t(f,e)},[f]),[P,F]=O(),[I,L]=O(`idle`),R=D(void 0),{selectionError:z,session:B,updateCheckout:ee}=St({catalog:e,client:n,paymentState:I,selection:g}),V=B.phase===`ready`?B.revision:void 0,te=x(e=>{V!==void 0&&(R.current=V),L(e)},[V]),ne=x(e=>p?.(e),[p]),re=x(()=>{T(void 0)},[]);S(()=>{B.phase===`loading`&&F(void 0)},[B.phase]),w(()=>{B.phase===`ready`&&R.current!==B.revision&&L(e=>e===`success`||e===`unresolved`?e:`idle`)},[B.phase,B.revision]);let H=[`lockerverse-payment`,s].filter(Boolean).join(` `),U=o??e.community,{accent:W,rootStyle:G}=jt(_,U);return k&&c===`summary`?A(`section`,{...b,className:H,"data-lockerverse-theme":y,"data-payment-state":`success`,style:G,children:j(`div`,{className:`lockerverse-payment__completion`,role:`status`,children:[A(`span`,{"aria-hidden":`true`,className:`lockerverse-payment__completion-icon`,children:A(`svg`,{"aria-hidden":`true`,fill:`none`,height:`28`,stroke:`currentColor`,strokeWidth:`2`,viewBox:`0 0 24 24`,width:`28`,children:A(`path`,{d:`m5 12 4 4L19 6`})})}),A(`h1`,{children:k.paymentRequired?`Thank you`:`Order confirmed`}),A(`p`,{children:k.paymentRequired?`Your payment has been received.`:`Your order is confirmed. No payment was required.`})]})}):z?A(`section`,{...b,className:H,"data-lockerverse-theme":y,role:`alert`,style:G,children:z}):B.phase===`error`&&B.failure===`This option is sold out.`||I===`sold_out`?j(`section`,{...b,className:H,"data-lockerverse-theme":y,role:`alert`,style:G,children:[A(`h1`,{children:`Sold out`}),A(`p`,{children:`This option is sold out.`})]}):B.phase===`error`?A(`section`,{...b,className:H,"data-lockerverse-theme":y,style:G,children:A(`p`,{role:`alert`,children:B.failure})}):B.phase===`ready`?j(`section`,{...b,"aria-label":`Payment`,className:H,"data-lockerverse-theme":y,"data-payment-state":I,ref:E,style:G,children:[A(kt,{branding:U,catalog:e}),r?j(`div`,{role:`alert`,children:[A(`p`,{children:r.message}),A(`button`,{onClick:i,type:`button`,children:`Retry`})]}):null,P?A(`p`,{className:`lockerverse-payment__payment-status`,role:`status`,children:P}):null,B.quoteFailure?j(`div`,{className:`lockerverse-payment__payment-status`,role:`alert`,children:[A(`span`,{children:B.quoteFailure}),A(`span`,{children:` The final total will be checked when you submit.`})]}):null,A(it,{accentColor:W,appearanceRoot:E,catalog:e,checkoutItems:B.checkoutItems,client:n,initialCustomFieldValues:u,metadata:d,onPaymentComplete:N,onPaymentRecoveryChange:ne,onPaymentUncertain:m,onQuoteChange:(e,t)=>{F(t),ee(e)},onResumePaymentFailed:re,onStateChange:te,quote:B.displayedQuote,resumePayment:C,stripeLoader:v,theme:y,visualStyle:G},B.revision)]}):j(`section`,{...b,"aria-busy":`true`,"aria-label":`Payment`,className:H,"data-lockerverse-theme":y,style:G,children:[A(kt,{branding:U,catalog:e}),r?j(`div`,{role:`alert`,children:[A(`p`,{children:r.message}),A(`button`,{onClick:i,type:`button`,children:`Retry`})]}):null,A(ht,{})]})}function Nt({children:e,loading:t=!1,viewProps:i}){let{branding:a,className:o,completionView:s,recoveryStorageKey:c,initialCustomFieldValues:l,metadata:u,onPaymentComplete:d,onPaymentRecoveryChange:f,onPaymentUncertain:p,resumePayment:m,selection:h,stripeLoader:g,style:_,theme:v=`dark`,...y}=i,b=n(_?.[`--lockerverse-accent`]??a?.accentColor??`#38d77a`),x=r(b),S={..._};return(_?.[`--lockerverse-accent`]!==void 0||a?.accentColor)&&(S[`--lockerverse-accent`]=b),x&&_?.[`--lockerverse-accent-contrast`]===void 0&&(S[`--lockerverse-accent-contrast`]=x),A(`section`,{...y,...t?{"aria-busy":!0,"aria-label":`Payment`}:{},className:[`lockerverse-payment`,o].filter(Boolean).join(` `),"data-lockerverse-theme":v,style:S,children:e})}function Pt(e){let{catalog:n,client:r,loadError:i,onRetry:a,...o}=e,{onPaymentRecoveryChange:s,recoveryStorageKey:c,resumePayment:l,selection:u}=o,d=Dt({selection:u,storageKey:c,widgetId:n.widget.id}),f=x(e=>{d.remember(e),t(s,e)},[s,d.remember]);return!d.ready||d.error?A(Nt,{loading:!d.ready,viewProps:o,children:d.error?A(`p`,{role:`alert`,children:d.error}):A(ht,{})}):A(Mt,{...e,onPaymentRecoveryChange:f,resumePayment:l??d.recovery})}function Ft({widget:e,...t}){return e.error&&!e.catalog?j(Nt,{viewProps:t,children:[A(`p`,{role:`alert`,children:e.error.message}),A(`button`,{onClick:e.refresh,type:`button`,children:`Retry`})]}):e.loading?j(Nt,{loading:!0,viewProps:t,children:[e.catalog?j(k,{children:[A(kt,{branding:t.branding??e.catalog.community,catalog:e.catalog}),A(At,{catalog:e.catalog,selection:t.selection})]}):null,A(ht,{})]}):e.catalog?A(Pt,{catalog:e.catalog,client:e.client,loadError:e.error,onRetry:e.refresh,...t}):A(Nt,{loading:!0,viewProps:t,children:A(ht,{})})}export{tt as n,Ft as t};
2
2
  //# sourceMappingURL=lockerverse-payment.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lockerverse-payment.js","names":["notifyPaymentRecovery","cachedStripeLoader"],"sources":["../src/select-control.tsx","../src/checkout-fields.tsx","../src/payment-form-state.ts","../src/payment-attempt.ts","../src/payment-input.ts","../src/payment-quote.ts","../src/payment-submission.ts","../src/use-payment-form-controller.ts","../src/payment-form.tsx","../src/use-payment-checkout.ts","../src/use-payment-recovery-storage.ts","../src/lockerverse-payment.tsx"],"sourcesContent":["export type LockerverseSelectOption = {\n label: string;\n value: string;\n};\n\nexport function LockerverseSelect({\n ariaDescribedBy,\n ariaLabel,\n ariaLabelledBy,\n className,\n id,\n invalid = false,\n name,\n onValueChange,\n options,\n value,\n}: {\n ariaDescribedBy?: string;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n className?: string;\n id?: string;\n invalid?: boolean;\n name: string;\n onValueChange: (value: string) => void;\n options: readonly LockerverseSelectOption[];\n value: string;\n}) {\n return (\n <select\n aria-describedby={ariaDescribedBy}\n aria-invalid={invalid || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={[\n \"lockerverse-form__control\",\n \"lockerverse-form__select\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n id={id}\n name={name}\n onChange={(event) => onValueChange(event.currentTarget.value)}\n value={value}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n","import type {\n LockerverseCustomField,\n LockerverseWidgetFields,\n} from \"@lockerverse/sdk/checkout\";\nimport { useId } from \"react\";\nimport { CustomFields, type CustomFieldValues } from \"./custom-fields.tsx\";\nimport { Checkbox } from \"./form-field.tsx\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { LockerverseSelect } from \"./select-control.tsx\";\n\nexport const MERCH_SIZES = [\"XS\", \"S\", \"M\", \"L\", \"XL\", \"XXL\", \"XXXL\"] as const;\n\nexport type CheckoutFieldValues = {\n customTip: string;\n customFields: CustomFieldValues;\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;\nconst TIP_VALUES = [...TIP_OPTIONS, \"custom\"] 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 const handleKeyDown = (\n event: React.KeyboardEvent<HTMLInputElement>,\n currentValue: CheckoutFieldValues[\"tipPercent\"]\n ) => {\n const currentIndex = TIP_VALUES.indexOf(currentValue);\n let nextIndex: number | undefined;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowRight\":\n nextIndex = (currentIndex + 1) % TIP_VALUES.length;\n break;\n case \"ArrowLeft\":\n case \"ArrowUp\":\n nextIndex = (currentIndex - 1 + TIP_VALUES.length) % TIP_VALUES.length;\n break;\n case \"Home\":\n nextIndex = 0;\n break;\n case \"End\":\n nextIndex = TIP_VALUES.length - 1;\n break;\n default:\n return;\n }\n event.preventDefault();\n const nextValue = TIP_VALUES[nextIndex];\n if (!nextValue) {\n return;\n }\n const radios = event.currentTarget\n .closest('[role=\"radiogroup\"]')\n ?.querySelectorAll<HTMLElement>('input[type=\"radio\"]');\n radios?.[nextIndex]?.focus();\n update({ tipPercent: nextValue });\n };\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 <label className=\"lockerverse-payment__tip-choice\" key={tip}>\n <input\n checked={values.tipPercent === tip}\n name=\"tipPercent\"\n onChange={() => update({ tipPercent: tip })}\n onKeyDown={(event) => handleKeyDown(event, tip)}\n tabIndex={values.tipPercent === tip ? 0 : -1}\n type=\"radio\"\n value={tip}\n />\n <span>{tip}%</span>\n </label>\n ))}\n <label className=\"lockerverse-payment__tip-choice\">\n <input\n checked={values.tipPercent === \"custom\"}\n name=\"tipPercent\"\n onChange={() => update({ tipPercent: \"custom\" })}\n onKeyDown={(event) => handleKeyDown(event, \"custom\")}\n tabIndex={values.tipPercent === \"custom\" ? 0 : -1}\n type=\"radio\"\n value=\"custom\"\n />\n <span>Other</span>\n </label>\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 const id = useId();\n return (\n <label className=\"lockerverse-payment__check-row\" htmlFor={id}>\n <Checkbox\n checked={checked}\n id={id}\n name={name}\n onChange={(event) => onChange(event.currentTarget.checked)}\n />\n <span>{children}</span>\n </label>\n );\n}\n\nexport function AdditionalCheckoutFields({\n customFields,\n errors,\n fields,\n idPrefix,\n isPromoApplying,\n memberIdLabel,\n onChange,\n onApplyPromo,\n promoError,\n values,\n}: {\n customFields: LockerverseCustomField[];\n errors: Record<string, string>;\n fields: LockerverseWidgetFields;\n idPrefix: string;\n isPromoApplying: boolean;\n memberIdLabel: string | null | undefined;\n onChange: (values: CheckoutFieldValues) => void;\n onApplyPromo: () => void;\n promoError: string | undefined;\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>{memberIdLabel?.trim() || \"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 <div className=\"lockerverse-payment__field\">\n <span id={`${idPrefix}-merch-size-label`}>Size</span>\n <LockerverseSelect\n ariaLabelledBy={`${idPrefix}-merch-size-label`}\n name=\"merchSize\"\n onValueChange={(value) => {\n const merchSize = MERCH_SIZES.find((size) => size === value);\n if (merchSize) {\n update({ merchSize });\n }\n }}\n options={MERCH_SIZES.map((size) => ({\n label: size,\n value: size,\n }))}\n value={values.merchSize}\n />\n </div>\n ) : null}\n {fields.promoCode ? (\n <div className=\"lockerverse-payment__field\">\n <span id={`${idPrefix}-promo-code-label`}>Promo code</span>\n <div className=\"lockerverse-payment__promo-control\">\n <input\n aria-describedby={\n promoError ? `${idPrefix}-promo-code-error` : undefined\n }\n aria-invalid={promoError ? \"true\" : undefined}\n aria-labelledby={`${idPrefix}-promo-code-label`}\n name=\"promoCode\"\n onChange={(event) =>\n update({ promoCode: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.promoCode}\n />\n <button\n disabled={!values.promoCode.trim() || isPromoApplying}\n onClick={onApplyPromo}\n type=\"button\"\n >\n {isPromoApplying ? \"Applying…\" : \"Apply\"}\n </button>\n </div>\n {promoError ? (\n <p\n className=\"lockerverse-payment__field-message\"\n id={`${idPrefix}-promo-code-error`}\n role=\"alert\"\n >\n {promoError}\n </p>\n ) : null}\n </div>\n ) : null}\n <CustomFields\n choiceClassName=\"lockerverse-payment__check-row\"\n errorClassName=\"lockerverse-payment__field-message\"\n errors={errors}\n fields={customFields}\n idPrefix={idPrefix}\n onChange={(nextCustomFields) =>\n update({ customFields: nextCustomFields })\n }\n values={values.customFields}\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","type PaymentFormStatus =\n | \"editing\"\n | \"invalid\"\n | \"recovering\"\n | \"refreshing_quote\"\n | \"submitting\"\n | \"succeeded\"\n | \"sold_out\"\n | \"unresolved\";\n\nexport type PaymentFormState = {\n error: string | undefined;\n message: string | undefined;\n retryUrl?: string;\n status: PaymentFormStatus;\n};\n\nexport type PaymentFormAction =\n | { type: \"field_changed\" }\n | { type: \"validation_failed\" }\n | { type: \"quote_refresh_started\" }\n | { type: \"quote_refresh_succeeded\" }\n | { error?: string; type: \"quote_refresh_failed\" }\n | { type: \"submission_started\" }\n | { type: \"submission_validation_failed\" }\n | { type: \"quote_changed\" }\n | { error: string; type: \"retryable_failure\" }\n | { error: string; type: \"recovery_failed\" }\n | { type: \"sold_out\" }\n | { message: string; type: \"succeeded\" }\n | { message: string; retryUrl?: string; type: \"unresolved\" };\n\nexport type PaymentUiState =\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"sold_out\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\";\n\nexport function createPaymentFormState(\n recoverPayment: boolean\n): PaymentFormState {\n return {\n error: undefined,\n message: undefined,\n status: recoverPayment ? \"recovering\" : \"editing\",\n };\n}\n\nfunction updateState(\n state: PaymentFormState,\n allowedStatuses: PaymentFormStatus[],\n changes: Partial<PaymentFormState>\n) {\n return allowedStatuses.includes(state.status)\n ? { ...state, ...changes }\n : state;\n}\n\nexport function paymentFormReducer(\n state: PaymentFormState,\n action: PaymentFormAction\n): PaymentFormState {\n if (\n state.status === \"sold_out\" ||\n state.status === \"succeeded\" ||\n state.status === \"unresolved\"\n ) {\n return state;\n }\n\n switch (action.type) {\n case \"field_changed\":\n return updateState(state, [\"editing\", \"invalid\", \"refreshing_quote\"], {\n error: undefined,\n status: \"editing\",\n });\n case \"validation_failed\":\n return updateState(state, [\"editing\"], { status: \"invalid\" });\n case \"quote_refresh_started\":\n return updateState(state, [\"editing\", \"invalid\"], {\n status: \"refreshing_quote\",\n });\n case \"quote_refresh_succeeded\":\n return updateState(state, [\"refreshing_quote\"], {\n error: undefined,\n status: \"editing\",\n });\n case \"quote_refresh_failed\":\n return updateState(state, [\"refreshing_quote\"], {\n error: action.error ?? state.error,\n status: \"editing\",\n });\n case \"submission_started\":\n return updateState(state, [\"editing\", \"invalid\", \"refreshing_quote\"], {\n error: undefined,\n status: \"submitting\",\n });\n case \"submission_validation_failed\":\n return updateState(state, [\"submitting\"], {\n error: undefined,\n status: \"invalid\",\n });\n case \"quote_changed\":\n return updateState(state, [\"submitting\"], { status: \"editing\" });\n case \"retryable_failure\":\n return updateState(state, [\"editing\", \"invalid\", \"submitting\"], {\n error: action.error,\n status: \"editing\",\n });\n case \"recovery_failed\":\n return updateState(state, [\"recovering\"], {\n error: action.error,\n status: \"editing\",\n });\n case \"sold_out\":\n return {\n error: undefined,\n message: undefined,\n status: \"sold_out\",\n };\n case \"succeeded\":\n return updateState(state, [\"recovering\", \"submitting\"], {\n message: action.message,\n status: \"succeeded\",\n });\n case \"unresolved\": {\n const changes: Partial<PaymentFormState> = {\n message: action.message,\n status: \"unresolved\",\n };\n if (action.retryUrl) {\n changes.retryUrl = action.retryUrl;\n }\n return updateState(state, [\"recovering\", \"submitting\"], changes);\n }\n default:\n return state;\n }\n}\n\nexport function getPaymentError(state: PaymentFormState) {\n return state.status === \"editing\" ||\n state.status === \"invalid\" ||\n state.status === \"refreshing_quote\"\n ? state.error\n : undefined;\n}\n\nexport function getPaymentUiState(state: PaymentFormState): PaymentUiState {\n if (state.status === \"sold_out\") {\n return \"sold_out\";\n }\n if (state.status === \"succeeded\") {\n return \"success\";\n }\n if (state.status === \"unresolved\") {\n return \"unresolved\";\n }\n if (state.status === \"submitting\" || state.status === \"recovering\") {\n return \"submitting\";\n }\n if (state.status === \"invalid\") {\n return \"invalid\";\n }\n return getPaymentError(state) ? \"error\" : \"idle\";\n}\n\nexport function isPaymentBusy(state: PaymentFormState) {\n return state.status === \"submitting\";\n}\n","import type {\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\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\nconst SERVER_CONTROLLED_AMOUNT_KEYS = [\n \"discountableSubtotalCents\",\n \"discountCents\",\n \"subtotalCents\",\n] as const satisfies readonly (keyof LockerverseCheckoutQuote)[];\n\nexport function hasMaterialQuoteChange(\n displayed: LockerverseCheckoutEstimate | LockerverseCheckoutQuote,\n current: LockerverseCheckoutQuote,\n locallyPreviewedTotalCents: number | undefined,\n stripeConnectedAccountId: string | null\n) {\n const amountKeys =\n locallyPreviewedTotalCents === current.totalCents\n ? SERVER_CONTROLLED_AMOUNT_KEYS\n : AMOUNT_KEYS;\n return (\n amountKeys.some((key) => displayed[key] !== current[key]) ||\n stripeConnectedAccountId !== current.payment.connectedAccountId ||\n (displayed.authoritative &&\n (displayed.payment.connectedAccountId !== stripeConnectedAccountId ||\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 retryUrl?: string;\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 const outcome: PaymentAttemptOutcome = {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason:\n payment.checkoutStatus === \"action_required\"\n ? \"action_required\"\n : \"pending\",\n };\n if (payment.retryUrl) {\n outcome.retryUrl = payment.retryUrl;\n }\n return outcome;\n}\n\nasync function settleRequiredAction(\n client: LockerverseCheckoutClient,\n payment: LockerversePaymentResult,\n stripe: Stripe | null | undefined\n): Promise<PaymentAttemptOutcome> {\n if (payment.checkoutStatus !== \"action_required\" || !payment.requiresAction) {\n return classifyPayment(payment);\n }\n if (!stripe) {\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason: \"action_required\",\n };\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 | null\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\nexport async function recoverPaymentAttempt(\n client: LockerverseCheckoutClient,\n paymentReference: string,\n stripe: Stripe | null\n): Promise<PaymentAttemptOutcome> {\n try {\n const payment = await client.getPaymentStatus(paymentReference);\n return settleRequiredAction(client, payment, stripe);\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference,\n reason: \"recovery_failed\",\n };\n }\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 trim,\n union,\n} from \"valibot\";\nimport type { LockerversePaymentSelectionItem } from \"./types.ts\";\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 strictObject({\n productSlug: productSlugSchema,\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);\n\nexport function parseCustomTipCents(input: string) {\n const result = safeParse(customTipSchema, input);\n if (!result.success) {\n return {\n message: result.issues[0]?.message ?? \"Enter a valid tip amount.\",\n success: false,\n } as const;\n }\n const [dollars = \"0\", fraction = \"\"] = result.output.split(\".\");\n const cents = BigInt(dollars) * 100n + BigInt(fraction.padEnd(2, \"0\"));\n if (cents > BigInt(Number.MAX_SAFE_INTEGER)) {\n return { message: \"Enter a valid tip amount.\", success: false } as const;\n }\n return { cents: Number(cents), success: true } as const;\n}\n\nexport function parsePaymentSelection(\n input: LockerversePaymentSelectionItem[]\n) {\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 {\n LockerverseCatalog,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutPricingInput,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport { parseCustomTipCents } from \"./payment-input.ts\";\n\nconst INVALID_PROMO_MESSAGE =\n \"This promo code is invalid or cannot be applied.\";\n\nexport function getTipCents(\n subtotalCents: number,\n values: Pick<CheckoutFieldValues, \"customTip\" | \"tipPercent\">\n) {\n if (values.tipPercent === \"custom\") {\n if (!values.customTip.trim()) {\n return { cents: 0, success: true } as const;\n }\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\nexport function buildQuoteRequest(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n email: string,\n tipCents: number\n) {\n const request: LockerverseCheckoutPricingInput = {};\n if (email) {\n request.email = email;\n }\n if (catalog.widget.fields.serviceFee) {\n request.includeServiceFee = fieldValues.includeServiceFee;\n }\n if (catalog.widget.fields.promoCode && fieldValues.promoCode.trim()) {\n request.promoCode = fieldValues.promoCode.trim();\n }\n if (catalog.widget.fields.tipping) {\n request.tipCents = tipCents;\n }\n return request;\n}\n\nexport function getLocalQuotePreview(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout\n) {\n const parsedTip = catalog.widget.fields.tipping\n ? getTipCents(quote.subtotalCents, fieldValues)\n : ({ cents: 0, success: true } as const);\n if (!parsedTip.success) {\n return { parsedTip, totalCents: null };\n }\n\n const serviceFeeCents =\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 return {\n parsedTip,\n totalCents:\n quote.totalCents -\n quote.serviceFeeCents -\n quote.tipCents +\n serviceFeeCents +\n parsedTip.cents,\n };\n}\n\nexport function getQuoteRefreshSuccess(\n quote: LockerversePreparedCheckout,\n validatePromo: boolean\n) {\n return {\n displayedTotalCents: quote.totalCents,\n promoError:\n validatePromo && quote.appliedDiscount?.source !== \"promo_code\"\n ? INVALID_PROMO_MESSAGE\n : undefined,\n };\n}\n\nexport function getQuoteRefreshFailure<ErrorValue>(\n error: ErrorValue,\n validatePromo: boolean\n) {\n let paymentError: string | undefined;\n if (!validatePromo) {\n paymentError =\n error instanceof Error\n ? error.message\n : \"The order total could not be updated.\";\n }\n return {\n paymentError,\n promoError: validatePromo ? INVALID_PROMO_MESSAGE : undefined,\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePaymentSubmission,\n LockerversePreparedCheckout,\n LockerverseShipping,\n} from \"@lockerverse/sdk/checkout\";\nimport type {\n Stripe,\n StripeAddressElementChangeEvent,\n StripeElements,\n} from \"@stripe/stripe-js\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport {\n buildCustomFieldAnswers,\n getCheckoutCustomFields,\n} from \"./custom-fields.tsx\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n hasMaterialQuoteChange,\n type PaymentAttemptOutcome,\n submitPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport { buildQuoteRequest, getTipCents } from \"./payment-quote.ts\";\nimport { normalizePhone } from \"./payment-validation.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\n\nexport type CheckoutAddresses = Record<\n \"billing\" | \"shipping\",\n StripeAddressElementChangeEvent | null\n>;\n\nfunction getCompleteAddress(\n address: StripeAddressElementChangeEvent | null,\n label: \"Billing\" | \"Shipping\"\n) {\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 fieldValues: CheckoutFieldValues,\n billingAddress: ReturnType<typeof getCompleteAddress>,\n addresses: CheckoutAddresses\n) {\n if (!catalog.widget.fields.shipping) {\n return;\n }\n return fieldValues.shippingMatchesBilling\n ? billingAddress\n : getCompleteAddress(addresses.shipping, \"Shipping\");\n}\n\nfunction buildConfirmationParams({\n billingAddress,\n catalog,\n email,\n phone,\n shippingAddress,\n}: {\n billingAddress: ReturnType<typeof getCompleteAddress>;\n catalog: LockerverseCatalog;\n email: string;\n phone: string;\n shippingAddress: ReturnType<typeof getCompleteAddress> | undefined;\n}) {\n const billingDetails = catalog.widget.fields.phone\n ? {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n phone,\n }\n : {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n };\n const params = {\n payment_method_data: {\n billing_details: billingDetails,\n },\n };\n if (!shippingAddress) {\n return params;\n }\n return {\n ...params,\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\nfunction buildPaymentRequest({\n catalog,\n checkoutItems,\n confirmationToken,\n email,\n fieldValues,\n metadata,\n phone,\n shippingAddress,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n confirmationToken: string | undefined;\n email: string;\n fieldValues: CheckoutFieldValues;\n metadata: Record<string, string> | undefined;\n phone: string;\n shippingAddress: ReturnType<typeof getCompleteAddress> | undefined;\n}) {\n const request: LockerversePaymentSubmission = {\n customFieldAnswers: buildCustomFieldAnswers(\n getCheckoutCustomFields(catalog, checkoutItems),\n fieldValues.customFields\n ),\n email,\n };\n if (confirmationToken) {\n request.confirmationToken = confirmationToken;\n }\n if (metadata) {\n request.metadata = metadata;\n }\n if (catalog.widget.fields.memberId && fieldValues.memberId.trim()) {\n request.memberId = fieldValues.memberId.trim();\n }\n if (catalog.widget.fields.merchSize) {\n request.merchSize = fieldValues.merchSize;\n }\n if (catalog.widget.fields.phone) {\n request.phone = phone;\n }\n if (shippingAddress) {\n const address: LockerverseShipping[\"address\"] = {\n city: shippingAddress.address.city ?? \"\",\n country: shippingAddress.address.country,\n line1: shippingAddress.address.line1 ?? \"\",\n postal_code: shippingAddress.address.postal_code ?? \"\",\n state: shippingAddress.address.state ?? \"\",\n };\n if (shippingAddress.address.line2) {\n address.line2 = shippingAddress.address.line2;\n }\n request.shipping = { address, name: shippingAddress.name };\n }\n return request;\n}\n\nfunction assertPaymentAttemptActive(isAttemptActive: () => boolean) {\n if (!isAttemptActive()) {\n throw new Error(\"Payment component is no longer active.\");\n }\n}\n\nfunction notifyPaymentRecovery(\n callback: LockerversePaymentProps[\"onPaymentRecoveryChange\"],\n recovery: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentRecoveryChange\"]>\n >[0]\n) {\n notifyHostCallback(callback, recovery);\n}\n\nfunction mapPaymentAttemptOutcome(\n outcome: PaymentAttemptOutcome,\n quote: LockerversePreparedCheckout,\n email: string,\n failureMessage: string\n) {\n if (outcome.kind === \"failed\") {\n return {\n kind: \"payment_failed\" as const,\n message: failureMessage,\n };\n }\n if (outcome.kind === \"unresolved\") {\n return {\n kind: \"payment_unresolved\" as const,\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n retryUrl: outcome.retryUrl,\n };\n }\n return {\n email,\n kind: \"payment\" as const,\n payment: outcome.payment,\n quote,\n };\n}\n\nexport type CompletePaymentOptions = {\n addresses: CheckoutAddresses;\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n elements?: StripeElements | null;\n email: string;\n fieldValues: CheckoutFieldValues;\n isAttemptActive: () => boolean;\n locallyPreviewedTotalCents: number;\n metadata: Record<string, string> | undefined;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n phone: string;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n stripe?: Stripe | null;\n stripeConnectedAccountId: string | null;\n};\n\nexport async function completePayment({\n addresses,\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n isAttemptActive,\n locallyPreviewedTotalCents,\n metadata,\n onPaymentRecoveryChange,\n phone,\n quote,\n stripe,\n stripeConnectedAccountId,\n}: CompletePaymentOptions) {\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 client.calculateTotal({\n ...buildQuoteRequest(\n catalog,\n fieldValues,\n normalizedEmail,\n parsedTip.cents\n ),\n catalog,\n items: checkoutItems,\n });\n assertPaymentAttemptActive(isAttemptActive);\n if (\n currentQuote.totalCents > 0 &&\n hasMaterialQuoteChange(\n quote,\n currentQuote,\n locallyPreviewedTotalCents,\n stripeConnectedAccountId\n )\n ) {\n return { kind: \"quote_changed\" as const, quote: currentQuote };\n }\n\n let completeShippingAddress:\n | ReturnType<typeof getCompleteAddress>\n | undefined;\n let confirmationToken: string | undefined;\n if (currentQuote.totalCents === 0) {\n if (catalog.widget.fields.shipping) {\n const completeBillingAddress = getCompleteAddress(\n addresses.billing,\n \"Billing\"\n );\n completeShippingAddress = getShippingAddress(\n catalog,\n fieldValues,\n completeBillingAddress,\n addresses\n );\n }\n } else {\n if (!(elements && stripe)) {\n throw new Error(\"Payment form is still loading.\");\n }\n await elements.update({ amount: currentQuote.totalCents });\n assertPaymentAttemptActive(isAttemptActive);\n const elementSubmission = await elements.submit();\n assertPaymentAttemptActive(isAttemptActive);\n if (elementSubmission.error) {\n throw new Error(elementSubmission.error.message);\n }\n\n const completeBillingAddress = getCompleteAddress(\n addresses.billing,\n \"Billing\"\n );\n completeShippingAddress = getShippingAddress(\n catalog,\n fieldValues,\n completeBillingAddress,\n addresses\n );\n const tokenResult = await stripe.createConfirmationToken({\n elements,\n params: buildConfirmationParams({\n billingAddress: completeBillingAddress,\n catalog,\n email: normalizedEmail,\n phone: normalizedPhone,\n shippingAddress: completeShippingAddress,\n }),\n });\n assertPaymentAttemptActive(isAttemptActive);\n if (tokenResult.error) {\n throw new Error(tokenResult.error.message);\n }\n confirmationToken = tokenResult.confirmationToken.id;\n }\n\n notifyPaymentRecovery(onPaymentRecoveryChange, {\n connectedAccountId: currentQuote.payment.connectedAccountId,\n paymentReference: currentQuote.paymentReference,\n });\n const outcome = await submitPaymentAttempt(\n client,\n {\n checkout: currentQuote,\n submission: buildPaymentRequest({\n catalog,\n checkoutItems,\n confirmationToken,\n email: normalizedEmail,\n fieldValues,\n metadata,\n phone: normalizedPhone,\n shippingAddress: completeShippingAddress,\n }),\n },\n stripe\n );\n assertPaymentAttemptActive(isAttemptActive);\n return mapPaymentAttemptOutcome(\n outcome,\n currentQuote,\n normalizedEmail,\n currentQuote.totalCents === 0\n ? \"Order could not be completed. Review the details and try again.\"\n : \"Payment was declined. Check your payment details and try again.\"\n );\n}\n\nexport type CompletePaymentResult = Awaited<ReturnType<typeof completePayment>>;\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePaymentCompletion,\n LockerversePaymentResult,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport { LockerverseSdkError } from \"@lockerverse/sdk/checkout\";\nimport type { Stripe, StripeElements } from \"@stripe/stripe-js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport { getPhoneServerError } from \"./contact-validation.ts\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n type PaymentAttemptOutcome,\n recoverPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport {\n getPaymentError,\n getPaymentUiState,\n isPaymentBusy,\n type PaymentFormAction,\n type PaymentFormState,\n type PaymentUiState,\n} from \"./payment-form-state.ts\";\nimport {\n buildQuoteRequest,\n getLocalQuotePreview,\n getQuoteRefreshFailure,\n getQuoteRefreshSuccess,\n} from \"./payment-quote.ts\";\nimport {\n type CheckoutAddresses,\n type CompletePaymentResult,\n completePayment,\n} from \"./payment-submission.ts\";\nimport { validateContact } from \"./payment-validation.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\n\nfunction notifyPaymentRecovery(\n callback: LockerversePaymentProps[\"onPaymentRecoveryChange\"],\n recovery: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentRecoveryChange\"]>\n >[0]\n) {\n notifyHostCallback(callback, recovery);\n}\n\nfunction notifyPaymentUncertain(\n callback: LockerversePaymentProps[\"onPaymentUncertain\"],\n payment: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentUncertain\"]>\n >[0]\n) {\n notifyHostCallback(callback, payment);\n}\n\nfunction createPaymentCompletion(\n payment: LockerversePaymentResult,\n context: Pick<LockerversePaymentCompletion, \"email\" | \"lineItems\">\n): LockerversePaymentCompletion {\n return { ...payment, ...context };\n}\n\nfunction unresolvedPaymentState(outcome: {\n reason: string;\n retryUrl?: string | undefined;\n}) {\n const action: PaymentFormAction = {\n message:\n outcome.reason === \"action_required\"\n ? \"Payment needs your attention. Keep this checkout open.\"\n : \"Payment is not complete. Check its status before you try again.\",\n type: \"unresolved\",\n };\n if (outcome.retryUrl) {\n action.retryUrl = outcome.retryUrl;\n }\n return action;\n}\n\nfunction mustWaitForStripe(\n outcome: PaymentAttemptOutcome,\n stripe: Stripe | null,\n stripeLoadFailed: boolean\n) {\n return (\n outcome.kind === \"unresolved\" &&\n outcome.reason === \"action_required\" &&\n !outcome.retryUrl &&\n !stripe &&\n !stripeLoadFailed\n );\n}\n\nfunction isSoldOutError<ErrorValue>(error: ErrorValue) {\n return (\n error instanceof LockerverseSdkError &&\n error.serverCode === \"PAYMENT_WIDGET_SALES_LIMIT_REACHED\"\n );\n}\n\nexport type PaymentFormControllerOptions = {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n elements: StripeElements | null;\n email: string;\n fieldValues: CheckoutFieldValues;\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n stripe: Stripe | null;\n stripeConnectedAccountId: string | null;\n stripeLoadFailed: boolean;\n paymentState: PaymentFormState;\n updateState: (action: PaymentFormAction, notifyHost?: boolean) => void;\n};\n\ntype SubmitPayment = {\n addresses: CheckoutAddresses;\n phone: string;\n};\n\nfunction applyQuoteRefreshSuccess({\n nextQuote,\n onQuoteChange,\n setDisplayedTotalCents,\n setPromoError,\n updateState,\n validatePromo,\n}: {\n nextQuote: LockerversePreparedCheckout;\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n setDisplayedTotalCents: (total: number) => void;\n setPromoError: (error: string | undefined) => void;\n updateState: (action: PaymentFormAction) => void;\n validatePromo: boolean;\n}) {\n const result = getQuoteRefreshSuccess(nextQuote, validatePromo);\n updateState({ type: \"quote_refresh_succeeded\" });\n setDisplayedTotalCents(result.displayedTotalCents);\n onQuoteChange(nextQuote);\n if (validatePromo) {\n setPromoError(result.promoError);\n }\n}\n\nfunction applyQuoteRefreshFailure({\n error,\n setPromoError,\n updateState,\n validatePromo,\n}: {\n error: unknown;\n setPromoError: (error: string | undefined) => void;\n updateState: (action: PaymentFormAction) => void;\n validatePromo: boolean;\n}) {\n const result = getQuoteRefreshFailure(error, validatePromo);\n if (validatePromo) {\n setPromoError(result.promoError);\n }\n updateState(\n result.paymentError === undefined\n ? { type: \"quote_refresh_failed\" }\n : { error: result.paymentError, type: \"quote_refresh_failed\" }\n );\n}\n\nfunction applyPaymentOutcome({\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n result,\n setDisplayedTotalCents,\n dispatchState,\n}: {\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n result: CompletePaymentResult;\n setDisplayedTotalCents: (total: number) => void;\n dispatchState: (action: PaymentFormAction) => 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 dispatchState({ type: \"quote_changed\" });\n return;\n }\n if (result.kind === \"payment_failed\") {\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({ error: result.message, type: \"retryable_failure\" });\n return;\n }\n if (result.kind === \"payment_unresolved\") {\n dispatchState(unresolvedPaymentState(result));\n notifyPaymentUncertain(onPaymentUncertain, {\n paymentReference: result.paymentReference,\n reason: result.reason,\n });\n return;\n }\n onQuoteChange(result.quote);\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({\n message: result.payment.paymentRequired\n ? \"Payment completed successfully.\"\n : \"Order confirmed. No payment was required.\",\n type: \"succeeded\",\n });\n notifyHostCallback(\n onPaymentComplete,\n createPaymentCompletion(result.payment, {\n email: result.email,\n lineItems: result.quote.lineItems,\n })\n );\n}\n\nexport function usePaymentFormController(\n options: PaymentFormControllerOptions\n) {\n const {\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n resumePayment,\n stripe,\n stripeConnectedAccountId,\n stripeLoadFailed,\n paymentState,\n updateState,\n } = options;\n const [displayedTotalCents, setDisplayedTotalCents] = useState(\n quote.totalCents\n );\n const [promoError, setPromoError] = useState<string>();\n const recoveryStartedRef = useRef(false);\n const quoteRequestRef = useRef(0);\n const attemptGenerationRef = useRef(0);\n const dispatchState = useCallback(\n (action: PaymentFormAction) => updateState(action, true),\n [updateState]\n );\n const startPaymentAttempt = useCallback(() => {\n const generation = attemptGenerationRef.current + 1;\n attemptGenerationRef.current = generation;\n return () => attemptGenerationRef.current === generation;\n }, []);\n\n useEffect(\n () => () => {\n attemptGenerationRef.current += 1;\n quoteRequestRef.current += 1;\n },\n []\n );\n\n const { parsedTip, totalCents: previewTotalCents } = getLocalQuotePreview(\n catalog,\n fieldValues,\n quote\n );\n\n useEffect(() => {\n if (previewTotalCents === null) {\n return;\n }\n setDisplayedTotalCents(previewTotalCents);\n if (previewTotalCents > 0) {\n elements?.update({ amount: previewTotalCents });\n }\n }, [\n catalog.pricingPolicy.serviceFeeRateBasisPoints,\n catalog.widget.fields.serviceFee,\n elements,\n fieldValues.includeServiceFee,\n previewTotalCents,\n quote.serviceFeeCents,\n quote.tipCents,\n quote.totalCents,\n quote.subtotalCents,\n ]);\n\n useEffect(() => {\n if (\n !resumePayment ||\n recoveryStartedRef.current ||\n paymentState.status !== \"recovering\"\n ) {\n return;\n }\n recoveryStartedRef.current = true;\n const isAttemptActive = startPaymentAttempt();\n onStateChange(getPaymentUiState(paymentState));\n\n recoverPaymentAttempt(client, resumePayment.paymentReference, stripe).then(\n (outcome) => {\n if (!isAttemptActive()) {\n return;\n }\n if (mustWaitForStripe(outcome, stripe, stripeLoadFailed)) {\n return;\n }\n if (outcome.kind === \"failed\") {\n const message =\n \"The previous payment failed. Check your details and try again.\";\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n onResumePaymentFailed();\n dispatchState({\n error: message,\n type: \"recovery_failed\",\n });\n return;\n }\n if (outcome.kind === \"unresolved\") {\n dispatchState(unresolvedPaymentState(outcome));\n notifyPaymentUncertain(onPaymentUncertain, {\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n });\n return;\n }\n\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({\n message: outcome.payment.paymentRequired\n ? \"Payment completed successfully.\"\n : \"Order confirmed. No payment was required.\",\n type: \"succeeded\",\n });\n notifyHostCallback(\n onPaymentComplete,\n createPaymentCompletion(outcome.payment, {\n email: null,\n lineItems: null,\n })\n );\n }\n );\n return () => {\n if (isAttemptActive()) {\n attemptGenerationRef.current += 1;\n }\n recoveryStartedRef.current = false;\n };\n }, [\n client,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onStateChange,\n resumePayment,\n stripe,\n stripeLoadFailed,\n startPaymentAttempt,\n dispatchState,\n paymentState,\n ]);\n\n const fieldChanged = useCallback(\n (clearPromo = false, preserveQuoteRequest = false) => {\n if (!preserveQuoteRequest) {\n quoteRequestRef.current += 1;\n }\n if (clearPromo) {\n setPromoError(undefined);\n }\n updateState({ type: \"field_changed\" });\n },\n [updateState]\n );\n\n async function refreshAuthoritativeTotal(\n allowMissingEmail = false,\n validatePromo = false\n ) {\n const normalizedEmail = email.trim().toLowerCase();\n const emailValidation = validateContact(\n { email: normalizedEmail, phone: \"\" },\n false\n );\n if (!(parsedTip.success && (emailValidation.value || allowMissingEmail))) {\n return;\n }\n\n quoteRequestRef.current += 1;\n const requestId = quoteRequestRef.current;\n updateState({ type: \"quote_refresh_started\" });\n try {\n const nextQuote = await client.calculateTotal({\n ...buildQuoteRequest(\n catalog,\n fieldValues,\n emailValidation.value?.email ?? \"\",\n parsedTip.cents\n ),\n catalog,\n items: checkoutItems,\n });\n if (requestId !== quoteRequestRef.current) {\n return;\n }\n applyQuoteRefreshSuccess({\n nextQuote,\n onQuoteChange,\n setDisplayedTotalCents,\n setPromoError,\n updateState,\n validatePromo,\n });\n } catch (error) {\n if (requestId !== quoteRequestRef.current) {\n return;\n }\n if (isSoldOutError(error)) {\n updateState({ type: \"sold_out\" });\n return;\n }\n applyQuoteRefreshFailure({\n error,\n setPromoError,\n updateState,\n validatePromo,\n });\n }\n }\n\n async function applyPromo() {\n setPromoError(undefined);\n await refreshAuthoritativeTotal(true, true);\n }\n\n async function submit({ addresses, phone }: SubmitPayment) {\n dispatchState({ type: \"submission_started\" });\n const isAttemptActive = startPaymentAttempt();\n try {\n const result = await completePayment({\n addresses,\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n isAttemptActive,\n locallyPreviewedTotalCents: displayedTotalCents,\n metadata,\n onPaymentRecoveryChange,\n phone,\n quote,\n stripe,\n stripeConnectedAccountId,\n });\n if (!isAttemptActive()) {\n return;\n }\n applyPaymentOutcome({\n dispatchState,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n result,\n setDisplayedTotalCents,\n });\n } catch (error) {\n if (!isAttemptActive()) {\n return;\n }\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n if (isSoldOutError(error)) {\n dispatchState({ type: \"sold_out\" });\n return;\n }\n const phoneError =\n error instanceof LockerverseSdkError\n ? getPhoneServerError(error.serverCode)\n : undefined;\n if (phoneError) {\n dispatchState({ type: \"submission_validation_failed\" });\n return { phoneError };\n }\n dispatchState({\n error:\n error instanceof Error\n ? error.message\n : \"Payment could not be completed.\",\n type: \"retryable_failure\",\n });\n }\n }\n\n const terminalMessage =\n paymentState.status === \"succeeded\" || paymentState.status === \"unresolved\"\n ? paymentState.message\n : undefined;\n return {\n commands: {\n applyPromo,\n fieldChanged,\n refreshAuthoritativeTotal,\n reportStripeLoadError: (message: string) =>\n dispatchState({ error: message, type: \"retryable_failure\" }),\n reportValidationFailure: () =>\n dispatchState({ type: \"validation_failed\" }),\n submit,\n },\n state: {\n displayedTotalCents,\n isRecovering: paymentState.status === \"recovering\",\n isRefreshingQuote: paymentState.status === \"refreshing_quote\",\n isSubmitting: isPaymentBusy(paymentState),\n parsedTip,\n paymentError: getPaymentError(paymentState),\n promoError,\n retryUrl: paymentState.retryUrl,\n terminalMessage,\n },\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\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 { StripeAddressElementChangeEvent } from \"@stripe/stripe-js\";\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport {\n AdditionalCheckoutFields,\n type CheckoutFieldValues,\n CheckoutToggle,\n ServiceFeeField,\n TipField,\n} from \"./checkout-fields.tsx\";\nimport {\n createCustomFieldValues,\n getCheckoutCustomFields,\n validateCustomFields,\n} from \"./custom-fields.tsx\";\nimport { EmailField, FormField } from \"./form-field.tsx\";\nimport { FormSkeleton } from \"./form-skeleton.tsx\";\nimport { formatMoney } from \"./format-money.ts\";\nimport {\n createPaymentFormState,\n getPaymentUiState,\n type PaymentFormAction,\n type PaymentFormState,\n type PaymentUiState,\n paymentFormReducer,\n} from \"./payment-form-state.ts\";\nimport type { CheckoutAddresses } from \"./payment-submission.ts\";\nimport { PaymentSummary } from \"./payment-summary.tsx\";\nimport { validateContact } from \"./payment-validation.ts\";\nimport { getInternationalPhone } from \"./phone.ts\";\nimport type { PhoneInputValue } from \"./phone-field.tsx\";\nimport { PhoneInput } from \"./phone-field.tsx\";\nimport { useStripeAppearance } from \"./stripe-appearance.ts\";\nimport { defaultLockerverseStripeLoader as cachedStripeLoader } from \"./stripe-loader.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\nimport { usePaymentFormController } from \"./use-payment-form-controller.ts\";\n\nexport const defaultLockerverseStripeLoader = cachedStripeLoader;\n\nexport function preloadLockerversePayment(\n catalog: Pick<LockerverseCatalog, \"payment\">\n) {\n const { connectedAccountId, publishableKey } = catalog.payment;\n return defaultLockerverseStripeLoader(\n publishableKey,\n connectedAccountId ? { stripeAccount: connectedAccountId } : undefined\n );\n}\n\nfunction getRecurringCadence(\n paymentOption: LockerversePreparedCheckout[\"paymentOption\"]\n) {\n if (paymentOption === \"monthly\") {\n return { interval: \"month\", label: \"Monthly\" } as const;\n }\n if (paymentOption === \"annually\") {\n return { interval: \"year\", label: \"Annual\" } as const;\n }\n if (paymentOption === \"every-six-months\") {\n return { interval: \"6 months\", label: \"Every 6 months\" } as const;\n }\n return null;\n}\n\nfunction getConnectedAccountId(\n catalog: LockerverseCatalog,\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout,\n resumePayment: LockerversePaymentProps[\"resumePayment\"]\n) {\n if (resumePayment) {\n const { connectedAccountId } = resumePayment;\n return connectedAccountId;\n }\n if (\"payment\" in quote) {\n const { connectedAccountId } = quote.payment;\n return connectedAccountId;\n }\n const { connectedAccountId } = catalog.payment;\n return connectedAccountId;\n}\n\nexport function ReadyPayment({\n accentColor,\n catalog,\n checkoutItems,\n client,\n appearanceRoot,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n quote,\n resumePayment,\n onStateChange,\n stripeLoader,\n theme,\n visualStyle,\n}: {\n accentColor: string;\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n appearanceRoot: RefObject<HTMLElement | null>;\n initialCustomFieldValues: LockerversePaymentProps[\"initialCustomFieldValues\"];\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n onStateChange: (state: PaymentUiState) => void;\n stripeLoader: NonNullable<LockerversePaymentProps[\"stripeLoader\"]>;\n theme: LockerversePaymentProps[\"theme\"];\n visualStyle: LockerversePaymentProps[\"style\"];\n}) {\n const [paymentState, setPaymentState] = useState(() =>\n createPaymentFormState(Boolean(resumePayment))\n );\n const paymentStateRef = useRef(paymentState);\n paymentStateRef.current = paymentState;\n const updateState = useCallback(\n (action: PaymentFormAction, notifyHost = false) => {\n const next = paymentFormReducer(paymentStateRef.current, action);\n if (next === paymentStateRef.current) {\n return;\n }\n paymentStateRef.current = next;\n setPaymentState(next);\n if (notifyHost) {\n onStateChange(getPaymentUiState(next));\n }\n },\n [onStateChange]\n );\n const requestedConnectedAccountId = getConnectedAccountId(\n catalog,\n quote,\n resumePayment\n );\n const stripeConfigurationRef = useRef({\n connectedAccountId: requestedConnectedAccountId,\n paymentOption: quote.paymentOption,\n });\n if (\n paymentState.status !== \"submitting\" &&\n paymentState.status !== \"recovering\"\n ) {\n stripeConfigurationRef.current = {\n connectedAccountId: requestedConnectedAccountId,\n paymentOption: quote.paymentOption,\n };\n }\n const { connectedAccountId, paymentOption } = stripeConfigurationRef.current;\n const stripe = useMemo(\n () =>\n stripeLoader(\n catalog.payment.publishableKey,\n connectedAccountId ? { stripeAccount: connectedAccountId } : undefined\n ).catch(() => null),\n [catalog.payment.publishableKey, connectedAccountId, stripeLoader]\n );\n const [stripeLoadFailed, setStripeLoadFailed] = useState(false);\n useEffect(() => {\n let active = true;\n setStripeLoadFailed(false);\n stripe.then((loadedStripe) => {\n if (active && loadedStripe === null) {\n setStripeLoadFailed(true);\n }\n });\n return () => {\n active = false;\n };\n }, [stripe]);\n\n const appearance = useStripeAppearance(\n appearanceRoot,\n theme,\n visualStyle,\n paymentState.status === \"submitting\" ||\n paymentState.status === \"recovering\",\n accentColor\n );\n if (!appearance) {\n return <FormSkeleton fieldCount={3} label=\"Loading payment form\" />;\n }\n\n return (\n <Elements\n key={`${catalog.payment.publishableKey}:${connectedAccountId ?? \"platform\"}:${paymentOption}`}\n options={{\n amount: Math.max(quote.totalCents, 100),\n appearance,\n currency: catalog.payment.currency,\n excludedPaymentMethodTypes: catalog.community?.widgetAchEnabled\n ? []\n : [\"us_bank_account\"],\n mode: paymentOption === \"one-time\" ? \"payment\" : \"subscription\",\n syncAddressCheckbox: \"none\",\n }}\n stripe={stripe}\n >\n <PaymentForm\n catalog={catalog}\n checkoutItems={checkoutItems}\n client={client}\n initialCustomFieldValues={initialCustomFieldValues}\n metadata={metadata}\n onPaymentComplete={onPaymentComplete}\n onPaymentRecoveryChange={onPaymentRecoveryChange}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={onQuoteChange}\n onResumePaymentFailed={onResumePaymentFailed}\n onStateChange={onStateChange}\n paymentState={paymentState}\n quote={quote}\n resumePayment={resumePayment}\n stripeConnectedAccountId={connectedAccountId}\n stripeLoadFailed={stripeLoadFailed}\n updateState={updateState}\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 <div className=\"lockerverse-payment__stripe-mount\">\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: {\n billingDetails: {\n address: \"never\",\n email: \"never\",\n name: \"never\",\n phone: \"never\",\n },\n },\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: \"auto\",\n },\n wallets: { applePay: \"auto\", googlePay: \"never\" },\n }}\n />\n </div>\n </div>\n );\n}\n\nfunction StripeAddressField({\n label,\n mode,\n onChange,\n onError,\n onReady,\n ready,\n}: {\n label: string;\n mode: \"billing\" | \"shipping\";\n onChange: (address: StripeAddressElementChangeEvent) => void;\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 <div className=\"lockerverse-payment__stripe-mount\">\n <AddressElement\n onChange={onChange}\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 </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\nfunction StripeCheckoutFields({\n catalog,\n displayedTotalCents,\n fieldValues,\n isBillingAddressReady,\n isPaymentReady,\n isShippingAddressReady,\n onAddressChange,\n onFieldValuesChange,\n onStripeLoadError,\n setIsBillingAddressReady,\n setIsPaymentReady,\n setIsShippingAddressReady,\n}: {\n catalog: LockerverseCatalog;\n displayedTotalCents: number;\n fieldValues: CheckoutFieldValues;\n isBillingAddressReady: boolean;\n isPaymentReady: boolean;\n isShippingAddressReady: boolean;\n onAddressChange: (\n mode: \"billing\" | \"shipping\",\n address: StripeAddressElementChangeEvent | null\n ) => void;\n onFieldValuesChange: (values: CheckoutFieldValues) => void;\n onStripeLoadError: (message: string) => void;\n setIsBillingAddressReady: (ready: boolean) => void;\n setIsPaymentReady: (ready: boolean) => void;\n setIsShippingAddressReady: (ready: boolean) => void;\n}) {\n const requiresPayment = displayedTotalCents > 0;\n\n return (\n <>\n {requiresPayment ? (\n <StripePaymentField\n onError={onStripeLoadError}\n onReady={() => setIsPaymentReady(true)}\n ready={isPaymentReady}\n />\n ) : null}\n {requiresPayment || catalog.widget.fields.shipping ? (\n <StripeAddressField\n label={requiresPayment ? \"Billing address\" : \"Shipping address\"}\n mode=\"billing\"\n onChange={(address) => onAddressChange(\"billing\", address)}\n onError={onStripeLoadError}\n onReady={() => setIsBillingAddressReady(true)}\n ready={isBillingAddressReady}\n />\n ) : null}\n {catalog.widget.fields.shipping ? (\n <div className=\"lockerverse-payment__shipping\">\n <CheckoutToggle\n checked={fieldValues.shippingMatchesBilling}\n name=\"shippingMatchesBilling\"\n onChange={(shippingMatchesBilling) => {\n onFieldValuesChange({\n ...fieldValues,\n shippingMatchesBilling,\n });\n if (shippingMatchesBilling) {\n onAddressChange(\"shipping\", null);\n } else {\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 onChange={(address) => onAddressChange(\"shipping\", address)}\n onError={onStripeLoadError}\n onReady={() => setIsShippingAddressReady(true)}\n ready={isShippingAddressReady}\n />\n )}\n </div>\n ) : null}\n </>\n );\n}\n\nfunction PaymentAction({\n catalog,\n displayedTotalCents,\n fieldValues,\n isBillingAddressReady,\n isPaymentReady,\n isRequiredShippingReady,\n isSubmitting,\n onFieldValuesChange,\n quote,\n}: {\n catalog: LockerverseCatalog;\n displayedTotalCents: number;\n fieldValues: CheckoutFieldValues;\n isBillingAddressReady: boolean;\n isPaymentReady: boolean;\n isRequiredShippingReady: boolean;\n isSubmitting: boolean;\n onFieldValuesChange: (values: CheckoutFieldValues) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n}) {\n const isFree = displayedTotalCents === 0;\n const isReady = isFree\n ? !catalog.widget.fields.shipping ||\n (isBillingAddressReady && isRequiredShippingReady)\n : isPaymentReady && isBillingAddressReady && isRequiredShippingReady;\n const cadence = getRecurringCadence(quote.paymentOption);\n let label = isFree\n ? \"Complete order\"\n : `Pay ${formatMoney(displayedTotalCents)}`;\n if (!isFree && cadence) {\n label = `Subscribe for ${formatMoney(displayedTotalCents)}/${cadence.interval}`;\n }\n if (isSubmitting) {\n label = isFree ? \"Completing…\" : \"Processing…\";\n }\n let actionLabel = `Process payment for ${formatMoney(displayedTotalCents)} total`;\n if (isFree) {\n actionLabel = \"Complete order\";\n } else if (cadence) {\n actionLabel = `Start ${cadence.label.toLowerCase()} subscription for ${formatMoney(displayedTotalCents)}`;\n }\n return (\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={onFieldValuesChange}\n values={fieldValues}\n />\n <button\n aria-busy={isSubmitting}\n aria-label={actionLabel}\n disabled={isSubmitting || !isReady}\n type=\"submit\"\n >\n {label}\n </button>\n </div>\n );\n}\n\nfunction focusNamedFormControl(form: HTMLFormElement, name: string) {\n const control = form.elements.namedItem(name);\n if (control instanceof HTMLElement) {\n control.focus();\n return;\n }\n if (control instanceof RadioNodeList) {\n Array.from(control)\n .find((item) => item instanceof HTMLElement)\n ?.focus();\n }\n}\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 focusNamedFormControl(form, `custom:${firstFieldId}`);\n }\n}\n\nfunction ContactFields({\n email,\n emailDiscountPercentOff,\n emailErrorId,\n emailId,\n emailRef,\n errors,\n onEmailBlur,\n onEmailChange,\n onPhoneChange,\n phone,\n phoneCountry,\n phoneEnabled,\n phoneErrorId,\n phoneId,\n phoneRef,\n}: {\n email: string;\n emailDiscountPercentOff: number | undefined;\n emailErrorId: string;\n emailId: string;\n emailRef: React.RefObject<HTMLInputElement | null>;\n errors: { email?: string; phone?: string };\n onEmailBlur: () => void;\n onEmailChange: (value: string) => void;\n onPhoneChange: (value: PhoneInputValue) => 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 <EmailField\n error={errors.email}\n errorId={emailErrorId}\n id={emailId}\n label=\"Email\"\n name=\"email\"\n onBlur={onEmailBlur}\n onChange={(event) => onEmailChange(event.currentTarget.value)}\n ref={emailRef}\n required\n value={email}\n />\n {emailDiscountPercentOff === undefined ? null : (\n <p className=\"lockerverse-payment__discount-message\" role=\"status\">\n Your email qualifies for {emailDiscountPercentOff}% off.\n </p>\n )}\n {phoneEnabled ? (\n <FormField\n error={errors.phone}\n errorId={phoneErrorId}\n id={phoneId}\n label=\"Phone\"\n >\n <PhoneInput\n country={phoneCountry}\n error={errors.phone}\n errorId={phoneErrorId}\n id={phoneId}\n inputRef={phoneRef}\n name=\"phone\"\n onChange={onPhoneChange}\n required\n value={phone}\n />\n </FormField>\n ) : null}\n </div>\n );\n}\n\nfunction PaymentForm({\n catalog,\n checkoutItems,\n client,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n resumePayment,\n stripeConnectedAccountId,\n stripeLoadFailed,\n paymentState,\n updateState,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n initialCustomFieldValues: LockerversePaymentProps[\"initialCustomFieldValues\"];\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n stripeConnectedAccountId: string | null;\n stripeLoadFailed: boolean;\n paymentState: PaymentFormState;\n updateState: (action: PaymentFormAction, notifyHost?: boolean) => void;\n}) {\n const customFields = getCheckoutCustomFields(catalog, checkoutItems);\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 [customFieldErrors, setCustomFieldErrors] = useState<\n Record<string, string>\n >({});\n const [tipError, setTipError] = useState<string>();\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: createCustomFieldValues(\n customFields,\n initialCustomFieldValues\n ),\n customTip: \"\",\n includeServiceFee: catalog.widget.fields.serviceFee,\n memberId: \"\",\n merchSize: \"M\",\n promoCode: \"\",\n shippingMatchesBilling: true,\n tipPercent: \"10\",\n }));\n const addressesRef = useRef<CheckoutAddresses>({\n billing: null,\n shipping: null,\n });\n const emailRef = useRef<HTMLInputElement>(null);\n const phoneRef = useRef<HTMLInputElement>(null);\n const statusRef = useRef<HTMLParagraphElement>(null);\n const paymentWasRequiredRef = useRef(quote.totalCents > 0);\n const elements = useElements();\n const stripe = useStripe();\n const controller = usePaymentFormController({\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n metadata,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onResumePaymentFailed,\n onStateChange,\n paymentState,\n quote,\n resumePayment,\n stripe,\n stripeConnectedAccountId,\n stripeLoadFailed,\n updateState,\n });\n const {\n displayedTotalCents,\n isRecovering,\n isRefreshingQuote,\n isSubmitting,\n parsedTip,\n paymentError,\n promoError,\n terminalMessage,\n retryUrl,\n } = controller.state;\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 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) {\n statusRef.current?.focus({ preventScroll: true });\n }\n }, [isSubmitting]);\n\n useEffect(() => {\n if (!(isSubmitting || errors.email || !errors.phone)) {\n phoneRef.current?.focus();\n }\n }, [errors.email, errors.phone, isSubmitting]);\n\n useEffect(() => {\n const paymentIsRequired = displayedTotalCents > 0;\n if (paymentIsRequired && !paymentWasRequiredRef.current) {\n setIsPaymentReady(false);\n setIsBillingAddressReady(false);\n }\n paymentWasRequiredRef.current = paymentIsRequired;\n }, [displayedTotalCents]);\n\n function clearError(field: \"email\" | \"phone\") {\n controller.commands.fieldChanged(false, field !== \"email\");\n setErrors((current) => {\n const next = { ...current };\n delete next[field];\n return next;\n });\n }\n\n function handleFieldValuesChange(nextValues: CheckoutFieldValues) {\n const promoChanged = nextValues.promoCode !== fieldValues.promoCode;\n const serviceFeeChanged =\n nextValues.includeServiceFee !== fieldValues.includeServiceFee;\n controller.commands.fieldChanged(\n promoChanged,\n !(promoChanged || serviceFeeChanged)\n );\n setFieldValues(nextValues);\n setCustomFieldErrors({});\n setTipError(undefined);\n }\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const internationalPhone = catalog.widget.fields.phone\n ? getInternationalPhone(phone, phoneCountry)\n : \"\";\n const validation = validateContact(\n { email, phone: internationalPhone },\n catalog.widget.fields.phone\n );\n const nextCustomFieldErrors = validateCustomFields(\n 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 controller.commands.reportValidationFailure();\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 const result = await controller.commands.submit({\n addresses: addressesRef.current,\n phone: internationalPhone,\n });\n if (result?.phoneError) {\n setErrors({ phone: result.phoneError });\n }\n }\n\n if (terminalMessage) {\n return (\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {terminalMessage}\n {retryUrl ? (\n <>\n {\" \"}\n <a href={retryUrl} rel=\"noopener noreferrer\" target=\"_blank\">\n Complete payment\n </a>\n </>\n ) : null}\n </p>\n );\n }\n\n if (isRecovering) {\n return (\n <p className=\"lockerverse-payment__payment-status\" role=\"status\">\n Recovering payment…\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 <PaymentSummary\n displayedBaseCents={displayedBaseCents}\n displayedTipCents={displayedTipCents}\n displayedTotalCents={displayedTotalCents}\n quote={quote}\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 emailDiscountPercentOff={\n quote.appliedDiscount?.source === \"email_list\"\n ? quote.appliedDiscount.percentageOff\n : undefined\n }\n emailErrorId={emailErrorId}\n emailId={emailId}\n emailRef={emailRef}\n errors={errors}\n onEmailBlur={() => controller.commands.refreshAuthoritativeTotal()}\n onEmailChange={(value) => {\n setEmail(value);\n clearError(\"email\");\n }}\n onPhoneChange={({ value, country }) => {\n setPhone(value);\n setPhoneCountry(country);\n clearError(\"phone\");\n }}\n phone={phone}\n phoneCountry={phoneCountry}\n phoneEnabled={catalog.widget.fields.phone}\n phoneErrorId={phoneErrorId}\n phoneId={phoneId}\n phoneRef={phoneRef}\n />\n <StripeCheckoutFields\n catalog={catalog}\n displayedTotalCents={displayedTotalCents}\n fieldValues={fieldValues}\n isBillingAddressReady={isBillingAddressReady}\n isPaymentReady={isPaymentReady}\n isShippingAddressReady={isShippingAddressReady}\n onAddressChange={(mode, address) => {\n addressesRef.current[mode] = address;\n }}\n onFieldValuesChange={handleFieldValuesChange}\n onStripeLoadError={controller.commands.reportStripeLoadError}\n setIsBillingAddressReady={setIsBillingAddressReady}\n setIsPaymentReady={setIsPaymentReady}\n setIsShippingAddressReady={setIsShippingAddressReady}\n />\n <AdditionalCheckoutFields\n customFields={customFields}\n errors={customFieldErrors}\n fields={catalog.widget.fields}\n idPrefix={idPrefix}\n isPromoApplying={isRefreshingQuote}\n memberIdLabel={catalog.community?.memberIdLabel}\n onApplyPromo={controller.commands.applyPromo}\n onChange={handleFieldValuesChange}\n promoError={promoError}\n values={fieldValues}\n />\n <PaymentAction\n catalog={catalog}\n displayedTotalCents={displayedTotalCents}\n fieldValues={fieldValues}\n isBillingAddressReady={isBillingAddressReady}\n isPaymentReady={isPaymentReady}\n isRequiredShippingReady={isRequiredShippingReady}\n isSubmitting={isSubmitting}\n onFieldValuesChange={handleFieldValuesChange}\n quote={quote}\n />\n </fieldset>\n </div>\n {isSubmitting ? (\n <p\n className=\"lockerverse-payment__sr-only\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {displayedTotalCents === 0\n ? \"Completing order…\"\n : \"Processing payment…\"}\n </p>\n ) : null}\n <PaymentErrorMessage message={paymentError} />\n </form>\n );\n}\n\nexport function PaymentSkeleton() {\n return (\n <FormSkeleton\n fieldCount={2}\n label=\"Loading payment…\"\n sectionCount={2}\n showCheckbox\n />\n );\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport { estimateLockerverseCheckout } from \"@lockerverse/sdk/checkout\";\nimport { useEffect, useMemo, useReducer, useRef } from \"react\";\nimport type { PaymentUiState } from \"./payment-form-state.ts\";\nimport { parsePaymentSelection } from \"./payment-input.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\ntype SessionState =\n | {\n phase: \"loading\";\n revision: number;\n }\n | {\n failure: string;\n phase: \"error\";\n revision: number;\n }\n | {\n checkoutItems: LockerverseCheckoutItem[];\n displayedQuote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n phase: \"ready\";\n quoteFailure: string | undefined;\n revision: number;\n };\n\ntype SessionAction =\n | {\n type: \"loading\";\n }\n | {\n displayedQuote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n type: \"ready\";\n }\n | {\n failure: string;\n type: \"error\";\n }\n | { checkout: LockerversePreparedCheckout; type: \"checkout\" }\n | { failure: string; type: \"quote-error\" };\n\nfunction sessionReducer(\n state: SessionState,\n action: SessionAction\n): SessionState {\n switch (action.type) {\n case \"loading\":\n return {\n phase: \"loading\",\n revision: state.revision,\n };\n case \"ready\":\n return createReadySession(action.displayedQuote, state.revision + 1);\n case \"error\":\n return {\n failure: action.failure,\n phase: \"error\",\n revision: state.revision,\n };\n case \"checkout\":\n return state.phase === \"ready\"\n ? {\n ...state,\n displayedQuote: action.checkout,\n quoteFailure: undefined,\n }\n : state;\n case \"quote-error\":\n return state.phase === \"ready\"\n ? {\n ...state,\n quoteFailure: action.failure,\n }\n : state;\n default:\n return state;\n }\n}\n\ntype LoadIdentity = {\n catalog: LockerverseCatalog;\n selectionKey: string;\n};\n\nfunction isSameLoad(\n identity: LoadIdentity | undefined,\n catalog: LockerverseCatalog,\n selectionKey: string\n) {\n return (\n identity?.catalog === catalog && identity.selectionKey === selectionKey\n );\n}\n\nfunction createReadyAction({\n checkout,\n}: {\n checkout: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n}): Extract<SessionAction, { type: \"ready\" }> {\n return {\n displayedQuote: checkout,\n type: \"ready\",\n };\n}\n\nfunction getLoadFailure<ErrorValue>(error: ErrorValue) {\n return error instanceof Error\n ? error.message\n : \"Lockerverse payment could not load.\";\n}\n\nfunction createReadySession(\n checkout: LockerverseCheckoutEstimate | LockerversePreparedCheckout,\n revision: number\n): SessionState {\n return {\n checkoutItems: [...checkout.items],\n displayedQuote: checkout,\n phase: \"ready\",\n quoteFailure: undefined,\n revision,\n };\n}\n\nfunction estimateCheckout(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n) {\n const includeServiceFee = catalog.widget.fields.serviceFee;\n return estimateLockerverseCheckout(catalog, {\n includeServiceFee,\n selection,\n });\n}\n\nfunction createInitialSession(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n): SessionState {\n try {\n return createReadySession(estimateCheckout(catalog, selection), 1);\n } catch (error) {\n return {\n failure: getLoadFailure(error),\n phase: \"error\",\n revision: 0,\n };\n }\n}\n\nexport function usePaymentCheckout({\n catalog,\n client,\n paymentState,\n selection,\n}: {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n paymentState: PaymentUiState;\n selection: LockerversePaymentProps[\"selection\"];\n}) {\n const parsedSelection = parsePaymentSelection(selection);\n const selectionKey = parsedSelection.success\n ? JSON.stringify(parsedSelection.value)\n : \"invalid-selection\";\n const stableSelection = useMemo(\n () => (parsedSelection.success ? parsedSelection.value : []),\n [parsedSelection.success, selectionKey]\n );\n const [session, dispatch] = useReducer(\n sessionReducer,\n undefined,\n (): SessionState =>\n parsedSelection.success\n ? createInitialSession(catalog, stableSelection)\n : { phase: \"loading\", revision: 0 }\n );\n const loadingRef = useRef<LoadIdentity | undefined>(undefined);\n const quoteRevisionRef = useRef(0);\n const estimatedRef = useRef<LoadIdentity | undefined>(\n session.phase === \"ready\" ? { catalog, selectionKey } : undefined\n );\n const settledRef = useRef<LoadIdentity | undefined>(\n session.phase === \"error\" ? { catalog, selectionKey } : undefined\n );\n const sessionIsLocked =\n paymentState === \"submitting\" ||\n paymentState === \"success\" ||\n paymentState === \"unresolved\";\n useEffect(() => {\n if (!parsedSelection.success) {\n return;\n }\n if (\n sessionIsLocked ||\n isSameLoad(settledRef.current, catalog, selectionKey) ||\n isSameLoad(loadingRef.current, catalog, selectionKey)\n ) {\n return;\n }\n\n let active = true;\n loadingRef.current = { catalog, selectionKey };\n let estimateIsReady = isSameLoad(\n estimatedRef.current,\n catalog,\n selectionKey\n );\n if (!estimateIsReady) {\n dispatch({ type: \"loading\" });\n }\n\n function dispatchWhenActive(action: SessionAction) {\n if (active) {\n dispatch(action);\n }\n }\n\n function settleWhenActive() {\n if (active) {\n loadingRef.current = undefined;\n settledRef.current = { catalog, selectionKey };\n }\n }\n\n let initialQuoteRevision: number | undefined;\n\n function failWhenActive<ErrorValue>(error: ErrorValue) {\n if (!active) {\n return;\n }\n loadingRef.current = undefined;\n settledRef.current = { catalog, selectionKey };\n if (\n estimateIsReady &&\n initialQuoteRevision !== undefined &&\n quoteRevisionRef.current !== initialQuoteRevision\n ) {\n return;\n }\n const failure = getLoadFailure(error);\n if (failure === \"This option is sold out.\") {\n dispatch({ failure, type: \"error\" });\n return;\n }\n if (estimateIsReady) {\n dispatch({ failure, type: \"quote-error\" });\n } else {\n dispatch({\n failure,\n type: \"error\",\n });\n }\n }\n\n async function loadPayment() {\n try {\n initialQuoteRevision = quoteRevisionRef.current;\n const includeServiceFee = catalog.widget.fields.serviceFee;\n if (!estimateIsReady) {\n const estimate = estimateCheckout(catalog, stableSelection);\n estimateIsReady = true;\n estimatedRef.current = { catalog, selectionKey };\n dispatchWhenActive(createReadyAction({ checkout: estimate }));\n }\n const preparedCheckout = await client.calculateTotal({\n catalog,\n includeServiceFee,\n selection: stableSelection,\n });\n settleWhenActive();\n if (quoteRevisionRef.current === initialQuoteRevision) {\n dispatchWhenActive({\n checkout: preparedCheckout,\n type: \"checkout\",\n });\n }\n } catch (error) {\n failWhenActive(error);\n }\n }\n\n loadPayment();\n return () => {\n active = false;\n if (isSameLoad(loadingRef.current, catalog, selectionKey)) {\n loadingRef.current = undefined;\n }\n };\n }, [\n catalog,\n client,\n parsedSelection.success,\n sessionIsLocked,\n selectionKey,\n stableSelection,\n ]);\n\n const loadIsCurrent =\n isSameLoad(estimatedRef.current, catalog, selectionKey) ||\n isSameLoad(settledRef.current, catalog, selectionKey) ||\n isSameLoad(loadingRef.current, catalog, selectionKey);\n const currentSession =\n sessionIsLocked || loadIsCurrent\n ? session\n : ({ phase: \"loading\", revision: session.revision } as const);\n\n return {\n selectionError: parsedSelection.success\n ? undefined\n : parsedSelection.message,\n session: currentSession,\n updateCheckout: (checkout: LockerversePreparedCheckout) => {\n quoteRevisionRef.current += 1;\n dispatch({ checkout, type: \"checkout\" });\n },\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n literal,\n nonEmpty,\n nullable,\n object,\n optional,\n pipe,\n safeParse,\n string,\n trim,\n union,\n} from \"valibot\";\nimport { parsePaymentSelection } from \"./payment-input.ts\";\nimport type {\n LockerversePaymentRecovery,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\nconst storedRecoverySchema = object({\n recovery: object({\n connectedAccountId: nullable(string()),\n paymentReference: pipe(string(), trim(), nonEmpty()),\n }),\n selectionFingerprint: string(),\n version: union([literal(1), literal(2)]),\n widgetId: optional(string()),\n});\n\nfunction selectionFingerprint(selection: LockerversePaymentSelectionItem[]) {\n const parsed = parsePaymentSelection(selection);\n if (!parsed.success) {\n return null;\n }\n return JSON.stringify(\n parsed.value.map((item) => {\n const slug = item.productSlug.trim();\n if (\"quantity\" in item) {\n return [\"quantity\", slug, item.quantity];\n }\n if (\"amountCents\" in item) {\n return [\"amount\", slug, item.amountCents];\n }\n return [\"product\", slug];\n })\n );\n}\n\nconst mismatchedPaymentMessage =\n \"A previous payment uses different checkout details. Return to its original checkout to check the payment before you pay again.\";\n\ntype RecoveryState = {\n error?: string;\n identity: string;\n recovery: LockerversePaymentRecovery | null;\n};\n\nfunction readRecovery(\n key: string,\n fingerprint: string,\n widgetId: string\n): Omit<RecoveryState, \"identity\"> {\n let saved: string | null;\n try {\n saved = window.sessionStorage.getItem(key);\n } catch {\n // Storage can be blocked. In-page recovery still stays with the form.\n return { recovery: null };\n }\n if (!saved) {\n return { recovery: null };\n }\n try {\n const parsed = safeParse(storedRecoverySchema, JSON.parse(saved));\n if (!parsed.success) {\n throw new Error(\"Invalid recovery record\");\n }\n const value = parsed.output;\n if (\n value.selectionFingerprint !== fingerprint ||\n (value.version === 2 && value.widgetId !== widgetId)\n ) {\n return {\n error: mismatchedPaymentMessage,\n recovery: null,\n };\n }\n return {\n recovery: {\n connectedAccountId: value.recovery.connectedAccountId,\n paymentReference: value.recovery.paymentReference,\n },\n };\n } catch {\n // An unreadable record is not proof that the previous payment failed.\n return {\n error:\n \"The saved payment could not be read. Contact support to check it before you pay again.\",\n recovery: null,\n };\n }\n}\n\n/** Read browser state after hydration, before mounting a payable form. */\nexport function usePaymentRecoveryStorage({\n selection,\n storageKey,\n widgetId,\n}: {\n selection: LockerversePaymentSelectionItem[];\n storageKey: string | undefined;\n widgetId: string;\n}) {\n const fingerprint = selectionFingerprint(selection);\n const identity = JSON.stringify([storageKey, fingerprint, widgetId]);\n const [state, setState] = useState<RecoveryState | null>(null);\n const pendingRef = useRef<RecoveryState | null>(null);\n useEffect(() => {\n if (!storageKey) {\n return;\n }\n const pending = pendingRef.current;\n let restored: Omit<RecoveryState, \"identity\"> = { recovery: null };\n if (pending?.recovery) {\n restored =\n pending.identity === identity\n ? { recovery: pending.recovery }\n : { error: mismatchedPaymentMessage, recovery: null };\n } else if (fingerprint !== null) {\n restored = readRecovery(storageKey, fingerprint, widgetId);\n }\n if (restored.recovery) {\n pendingRef.current = { identity, recovery: restored.recovery };\n }\n setState({ identity, ...restored });\n }, [fingerprint, identity, storageKey, widgetId]);\n\n const remember = useCallback(\n (recovery: LockerversePaymentRecovery | null) => {\n if (!storageKey || fingerprint === null) {\n return;\n }\n pendingRef.current = recovery ? { identity, recovery } : null;\n try {\n if (recovery) {\n window.sessionStorage.setItem(\n storageKey,\n JSON.stringify({\n recovery,\n selectionFingerprint: fingerprint,\n version: 2,\n widgetId,\n })\n );\n } else {\n window.sessionStorage.removeItem(storageKey);\n }\n } catch {\n // Keep recovery in the mounted form if browser storage is unavailable.\n }\n },\n [fingerprint, identity, storageKey, widgetId]\n );\n return {\n error: storageKey && state?.identity === identity ? state.error : undefined,\n ready: !storageKey || state?.identity === identity,\n recovery:\n storageKey && state?.identity === identity ? state.recovery : null,\n remember,\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerversePaymentCompletion,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { getAccentContrast, normalizeAccentColor } from \"./accent-contrast.ts\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n defaultLockerverseStripeLoader,\n PaymentSkeleton,\n ReadyPayment,\n} from \"./payment-form.tsx\";\nimport type { PaymentUiState } from \"./payment-form-state.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentRecovery,\n} from \"./types.ts\";\nimport { usePaymentCheckout } from \"./use-payment-checkout.ts\";\nimport { usePaymentRecoveryStorage } from \"./use-payment-recovery-storage.ts\";\n\ntype PaymentViewProps = Omit<LockerversePaymentProps, \"widget\">;\nconst paymentCadence = {\n annually: \"/year\",\n \"every-six-months\": \" every 6 months\",\n monthly: \"/month\",\n \"one-time\": \"\",\n};\n\nfunction PaymentCatalogHeader({\n branding,\n catalog,\n}: {\n branding: LockerversePaymentProps[\"branding\"] | null;\n catalog: LockerverseCatalog;\n}) {\n return (\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 ? <p>{catalog.widget.description}</p> : null}\n </header>\n );\n}\n\nfunction PaymentCatalogSummary({\n catalog,\n selection,\n}: {\n catalog: LockerverseCatalog;\n selection: LockerversePaymentProps[\"selection\"];\n}) {\n const products = selection?.length\n ? catalog.products.filter((product) =>\n selection.some((item) => item.productSlug === product.slug)\n )\n : catalog.products;\n if (products.length === 0) {\n return null;\n }\n return (\n <div className=\"lockerverse-payment__payment-summary\">\n <h2>Products</h2>\n <div className=\"lockerverse-payment__payment-summary-items\">\n {products.map((product) => {\n const amount =\n product.pricingMode === \"fixed\"\n ? product.amountCents\n : product.minimumAmountCents;\n const cadence = paymentCadence[product.paymentOption];\n return (\n <div\n className=\"lockerverse-payment__payment-summary-row\"\n key={product.id}\n >\n <span>{product.name}</span>\n <strong>\n {amount === null\n ? \"Choose amount\"\n : `${product.pricingMode === \"custom\" ? \"From \" : \"\"}${formatMoney(amount)}${cadence}`}\n </strong>\n </div>\n );\n })}\n </div>\n <p>Base prices. Final total is checked at checkout.</p>\n </div>\n );\n}\n\nfunction getPaymentAppearance(\n style: LockerversePaymentProps[\"style\"],\n branding: LockerversePaymentProps[\"branding\"] | null\n) {\n const accent = normalizeAccentColor(\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const rootStyle: LockerversePaymentProps[\"style\"] = { ...style };\n if (style?.[\"--lockerverse-accent\"] !== undefined || branding?.accentColor) {\n rootStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n rootStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n return { accent, rootStyle };\n}\n\nfunction LoadedPayment({\n catalog,\n client,\n loadError,\n onRetry,\n ...viewProps\n}: PaymentViewProps & {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n loadError?: Error | null;\n onRetry?: () => void;\n}) {\n const {\n branding,\n className,\n completionView,\n recoveryStorageKey: _recoveryStorageKey,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n resumePayment,\n selection,\n style,\n stripeLoader = defaultLockerverseStripeLoader,\n theme = \"dark\",\n ...sectionProps\n } = viewProps;\n const [activeResumePayment, setActiveResumePayment] = useState(resumePayment);\n const appearanceRootRef = useRef<HTMLElement | null>(null);\n const [completion, setCompletion] =\n useState<LockerversePaymentCompletion | null>(null);\n const handlePaymentComplete = useCallback(\n (payment: LockerversePaymentCompletion) => {\n setCompletion(payment);\n notifyHostCallback(onPaymentComplete, payment);\n },\n [onPaymentComplete]\n );\n const [notice, setNotice] = useState<string>();\n const [paymentState, setPaymentState] = useState<PaymentUiState>(\"idle\");\n const paymentStateRevisionRef = useRef<number | undefined>(undefined);\n const { selectionError, session, updateCheckout } = usePaymentCheckout({\n catalog,\n client,\n paymentState,\n selection,\n });\n const readySessionRevision =\n session.phase === \"ready\" ? session.revision : undefined;\n const handlePaymentStateChange = useCallback(\n (state: PaymentUiState) => {\n if (readySessionRevision !== undefined) {\n paymentStateRevisionRef.current = readySessionRevision;\n }\n setPaymentState(state);\n },\n [readySessionRevision]\n );\n const handlePaymentRecoveryChange = useCallback(\n (recovery: LockerversePaymentRecovery | null) =>\n onPaymentRecoveryChange?.(recovery),\n [onPaymentRecoveryChange]\n );\n const handleResumePaymentFailed = useCallback(() => {\n setActiveResumePayment(undefined);\n }, []);\n\n useEffect(() => {\n if (session.phase === \"loading\") {\n setNotice(undefined);\n }\n }, [session.phase]);\n\n useLayoutEffect(() => {\n if (\n session.phase === \"ready\" &&\n paymentStateRevisionRef.current !== session.revision\n ) {\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 effectiveBranding = branding ?? catalog.community;\n const { accent: effectiveAccent, rootStyle } = getPaymentAppearance(\n style,\n effectiveBranding\n );\n\n if (completion && completionView === \"summary\") {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n data-payment-state=\"success\"\n style={rootStyle}\n >\n <div className=\"lockerverse-payment__completion\" role=\"status\">\n <span\n aria-hidden=\"true\"\n className=\"lockerverse-payment__completion-icon\"\n >\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height=\"28\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n width=\"28\"\n >\n <path d=\"m5 12 4 4L19 6\" />\n </svg>\n </span>\n <h1>\n {completion.paymentRequired ? \"Thank you\" : \"Order confirmed\"}\n </h1>\n <p>\n {completion.paymentRequired\n ? \"Your payment has been received.\"\n : \"Your order is confirmed. No payment was required.\"}\n </p>\n </div>\n </section>\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 const sessionIsSoldOut =\n session.phase === \"error\" && session.failure === \"This option is sold out.\";\n\n if (sessionIsSoldOut || paymentState === \"sold_out\") {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n style={rootStyle}\n >\n <h1>Sold out</h1>\n <p>This option is sold out.</p>\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 style={rootStyle}\n >\n <p role=\"alert\">{session.failure}</p>\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 style={rootStyle}\n >\n <PaymentCatalogHeader branding={effectiveBranding} catalog={catalog} />\n {loadError ? (\n <div role=\"alert\">\n <p>{loadError.message}</p>\n <button onClick={onRetry} type=\"button\">\n Retry\n </button>\n </div>\n ) : null}\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 ref={appearanceRootRef}\n style={rootStyle}\n >\n <PaymentCatalogHeader branding={effectiveBranding} catalog={catalog} />\n {loadError ? (\n <div role=\"alert\">\n <p>{loadError.message}</p>\n <button onClick={onRetry} type=\"button\">\n Retry\n </button>\n </div>\n ) : null}\n {notice ? (\n <p className=\"lockerverse-payment__payment-status\" role=\"status\">\n {notice}\n </p>\n ) : null}\n {session.quoteFailure ? (\n <div className=\"lockerverse-payment__payment-status\" role=\"alert\">\n <span>{session.quoteFailure}</span>\n <span> The final total will be checked when you submit.</span>\n </div>\n ) : null}\n <ReadyPayment\n accentColor={effectiveAccent}\n appearanceRoot={appearanceRootRef}\n catalog={catalog}\n checkoutItems={session.checkoutItems}\n client={client}\n initialCustomFieldValues={initialCustomFieldValues}\n key={session.revision}\n metadata={metadata}\n onPaymentComplete={handlePaymentComplete}\n onPaymentRecoveryChange={handlePaymentRecoveryChange}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={(nextQuote, nextNotice) => {\n setNotice(nextNotice);\n updateCheckout(nextQuote);\n }}\n onResumePaymentFailed={handleResumePaymentFailed}\n onStateChange={handlePaymentStateChange}\n quote={session.displayedQuote}\n resumePayment={activeResumePayment}\n stripeLoader={stripeLoader}\n theme={theme}\n visualStyle={rootStyle}\n />\n </section>\n );\n}\n\nfunction PaymentWidgetState({\n children,\n loading = false,\n viewProps,\n}: {\n children: ReactNode;\n loading?: boolean;\n viewProps: PaymentViewProps;\n}) {\n const {\n branding,\n className,\n completionView: _completionView,\n recoveryStorageKey: _recoveryStorageKey,\n initialCustomFieldValues: _initialCustomFieldValues,\n metadata: _metadata,\n onPaymentComplete: _onPaymentComplete,\n onPaymentRecoveryChange: _onPaymentRecoveryChange,\n onPaymentUncertain: _onPaymentUncertain,\n resumePayment: _resumePayment,\n selection: _selection,\n stripeLoader: _stripeLoader,\n style,\n theme = \"dark\",\n ...sectionProps\n } = viewProps;\n const accent = normalizeAccentColor(\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const rootStyle: LockerversePaymentProps[\"style\"] = { ...style };\n if (style?.[\"--lockerverse-accent\"] !== undefined || branding?.accentColor) {\n rootStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n rootStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n\n return (\n <section\n {...sectionProps}\n {...(loading ? { \"aria-busy\": true, \"aria-label\": \"Payment\" } : {})}\n className={[\"lockerverse-payment\", className].filter(Boolean).join(\" \")}\n data-lockerverse-theme={theme}\n style={rootStyle}\n >\n {children}\n </section>\n );\n}\n\nfunction RecoverablePayment(\n props: PaymentViewProps & {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n loadError?: Error | null;\n onRetry?: () => void;\n }\n) {\n const {\n catalog,\n client: _client,\n loadError: _loadError,\n onRetry: _onRetry,\n ...viewProps\n } = props;\n const {\n onPaymentRecoveryChange,\n recoveryStorageKey,\n resumePayment,\n selection,\n } = viewProps;\n const stored = usePaymentRecoveryStorage({\n selection,\n storageKey: recoveryStorageKey,\n widgetId: catalog.widget.id,\n });\n const handleRecoveryChange = useCallback(\n (recovery: LockerversePaymentRecovery | null) => {\n stored.remember(recovery);\n notifyHostCallback(onPaymentRecoveryChange, recovery);\n },\n [onPaymentRecoveryChange, stored.remember]\n );\n if (!stored.ready || stored.error) {\n return (\n <PaymentWidgetState loading={!stored.ready} viewProps={viewProps}>\n {stored.error ? (\n <p role=\"alert\">{stored.error}</p>\n ) : (\n <PaymentSkeleton />\n )}\n </PaymentWidgetState>\n );\n }\n return (\n <LoadedPayment\n {...props}\n onPaymentRecoveryChange={handleRecoveryChange}\n resumePayment={resumePayment ?? stored.recovery}\n />\n );\n}\n\nexport function LockerversePayment({\n widget,\n ...viewProps\n}: LockerversePaymentProps) {\n if (widget.error && !widget.catalog) {\n return (\n <PaymentWidgetState viewProps={viewProps}>\n <p role=\"alert\">{widget.error.message}</p>\n <button onClick={widget.refresh} type=\"button\">\n Retry\n </button>\n </PaymentWidgetState>\n );\n }\n if (widget.loading) {\n return (\n <PaymentWidgetState loading viewProps={viewProps}>\n {widget.catalog ? (\n <>\n <PaymentCatalogHeader\n branding={viewProps.branding ?? widget.catalog.community}\n catalog={widget.catalog}\n />\n <PaymentCatalogSummary\n catalog={widget.catalog}\n selection={viewProps.selection}\n />\n </>\n ) : null}\n <PaymentSkeleton />\n </PaymentWidgetState>\n );\n }\n if (!widget.catalog) {\n return (\n <PaymentWidgetState loading viewProps={viewProps}>\n <PaymentSkeleton />\n </PaymentWidgetState>\n );\n }\n return (\n <RecoverablePayment\n catalog={widget.catalog}\n client={widget.client}\n loadError={widget.error}\n onRetry={widget.refresh}\n {...viewProps}\n />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lockerverse-payment.js","names":["notifyPaymentRecovery","cachedStripeLoader"],"sources":["../src/select-control.tsx","../src/checkout-fields.tsx","../src/payment-form-state.ts","../src/payment-attempt.ts","../src/payment-input.ts","../src/payment-quote.ts","../src/payment-submission.ts","../src/use-payment-form-controller.ts","../src/payment-form.tsx","../src/use-payment-checkout.ts","../src/use-payment-recovery-storage.ts","../src/lockerverse-payment.tsx"],"sourcesContent":["export type LockerverseSelectOption = {\n label: string;\n value: string;\n};\n\nexport function LockerverseSelect({\n ariaDescribedBy,\n ariaLabel,\n ariaLabelledBy,\n className,\n id,\n invalid = false,\n name,\n onValueChange,\n options,\n value,\n}: {\n ariaDescribedBy?: string;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n className?: string;\n id?: string;\n invalid?: boolean;\n name: string;\n onValueChange: (value: string) => void;\n options: readonly LockerverseSelectOption[];\n value: string;\n}) {\n return (\n <select\n aria-describedby={ariaDescribedBy}\n aria-invalid={invalid || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={[\n \"lockerverse-form__control\",\n \"lockerverse-form__select\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n id={id}\n name={name}\n onChange={(event) => onValueChange(event.currentTarget.value)}\n value={value}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n","import type {\n LockerverseCustomField,\n LockerverseWidgetFields,\n} from \"@lockerverse/sdk/checkout\";\nimport { useId } from \"react\";\nimport { CustomFields, type CustomFieldValues } from \"./custom-fields.tsx\";\nimport { Checkbox } from \"./form-field.tsx\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { LockerverseSelect } from \"./select-control.tsx\";\n\nexport const MERCH_SIZES = [\"XS\", \"S\", \"M\", \"L\", \"XL\", \"XXL\", \"XXXL\"] as const;\n\nexport type CheckoutFieldValues = {\n customTip: string;\n customFields: CustomFieldValues;\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;\nconst TIP_VALUES = [...TIP_OPTIONS, \"custom\"] 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 const handleKeyDown = (\n event: React.KeyboardEvent<HTMLInputElement>,\n currentValue: CheckoutFieldValues[\"tipPercent\"]\n ) => {\n const currentIndex = TIP_VALUES.indexOf(currentValue);\n let nextIndex: number | undefined;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowRight\":\n nextIndex = (currentIndex + 1) % TIP_VALUES.length;\n break;\n case \"ArrowLeft\":\n case \"ArrowUp\":\n nextIndex = (currentIndex - 1 + TIP_VALUES.length) % TIP_VALUES.length;\n break;\n case \"Home\":\n nextIndex = 0;\n break;\n case \"End\":\n nextIndex = TIP_VALUES.length - 1;\n break;\n default:\n return;\n }\n event.preventDefault();\n const nextValue = TIP_VALUES[nextIndex];\n if (!nextValue) {\n return;\n }\n const radios = event.currentTarget\n .closest('[role=\"radiogroup\"]')\n ?.querySelectorAll<HTMLElement>('input[type=\"radio\"]');\n radios?.[nextIndex]?.focus();\n update({ tipPercent: nextValue });\n };\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 <label className=\"lockerverse-payment__tip-choice\" key={tip}>\n <input\n checked={values.tipPercent === tip}\n name=\"tipPercent\"\n onChange={() => update({ tipPercent: tip })}\n onKeyDown={(event) => handleKeyDown(event, tip)}\n tabIndex={values.tipPercent === tip ? 0 : -1}\n type=\"radio\"\n value={tip}\n />\n <span>{tip}%</span>\n </label>\n ))}\n <label className=\"lockerverse-payment__tip-choice\">\n <input\n checked={values.tipPercent === \"custom\"}\n name=\"tipPercent\"\n onChange={() => update({ tipPercent: \"custom\" })}\n onKeyDown={(event) => handleKeyDown(event, \"custom\")}\n tabIndex={values.tipPercent === \"custom\" ? 0 : -1}\n type=\"radio\"\n value=\"custom\"\n />\n <span>Other</span>\n </label>\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 const id = useId();\n return (\n <label className=\"lockerverse-payment__check-row\" htmlFor={id}>\n <Checkbox\n checked={checked}\n id={id}\n name={name}\n onChange={(event) => onChange(event.currentTarget.checked)}\n />\n <span>{children}</span>\n </label>\n );\n}\n\nexport function AdditionalCheckoutFields({\n customFields,\n errors,\n fields,\n idPrefix,\n isPromoApplying,\n memberIdLabel,\n onChange,\n onApplyPromo,\n promoError,\n values,\n}: {\n customFields: LockerverseCustomField[];\n errors: Record<string, string>;\n fields: LockerverseWidgetFields;\n idPrefix: string;\n isPromoApplying: boolean;\n memberIdLabel: string | null | undefined;\n onChange: (values: CheckoutFieldValues) => void;\n onApplyPromo: () => void;\n promoError: string | undefined;\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>{memberIdLabel?.trim() || \"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 <div className=\"lockerverse-payment__field\">\n <span id={`${idPrefix}-merch-size-label`}>Size</span>\n <LockerverseSelect\n ariaLabelledBy={`${idPrefix}-merch-size-label`}\n name=\"merchSize\"\n onValueChange={(value) => {\n const merchSize = MERCH_SIZES.find((size) => size === value);\n if (merchSize) {\n update({ merchSize });\n }\n }}\n options={MERCH_SIZES.map((size) => ({\n label: size,\n value: size,\n }))}\n value={values.merchSize}\n />\n </div>\n ) : null}\n {fields.promoCode ? (\n <div className=\"lockerverse-payment__field\">\n <span id={`${idPrefix}-promo-code-label`}>Promo code</span>\n <div className=\"lockerverse-payment__promo-control\">\n <input\n aria-describedby={\n promoError ? `${idPrefix}-promo-code-error` : undefined\n }\n aria-invalid={promoError ? \"true\" : undefined}\n aria-labelledby={`${idPrefix}-promo-code-label`}\n name=\"promoCode\"\n onChange={(event) =>\n update({ promoCode: event.currentTarget.value })\n }\n placeholder=\"Optional\"\n value={values.promoCode}\n />\n <button\n disabled={!values.promoCode.trim() || isPromoApplying}\n onClick={onApplyPromo}\n type=\"button\"\n >\n {isPromoApplying ? \"Applying…\" : \"Apply\"}\n </button>\n </div>\n {promoError ? (\n <p\n className=\"lockerverse-payment__field-message\"\n id={`${idPrefix}-promo-code-error`}\n role=\"alert\"\n >\n {promoError}\n </p>\n ) : null}\n </div>\n ) : null}\n <CustomFields\n choiceClassName=\"lockerverse-payment__check-row\"\n errorClassName=\"lockerverse-payment__field-message\"\n errors={errors}\n fields={customFields}\n idPrefix={idPrefix}\n onChange={(nextCustomFields) =>\n update({ customFields: nextCustomFields })\n }\n values={values.customFields}\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","type PaymentFormStatus =\n | \"editing\"\n | \"invalid\"\n | \"recovering\"\n | \"refreshing_quote\"\n | \"submitting\"\n | \"succeeded\"\n | \"sold_out\"\n | \"unresolved\";\n\nexport type PaymentFormState = {\n error: string | undefined;\n message: string | undefined;\n retryUrl?: string | undefined;\n status: PaymentFormStatus;\n};\n\nexport type PaymentFormAction =\n | { type: \"field_changed\" }\n | { type: \"recovery_started\" }\n | { type: \"validation_failed\" }\n | { type: \"quote_refresh_started\" }\n | { type: \"quote_refresh_succeeded\" }\n | { error?: string; type: \"quote_refresh_failed\" }\n | { type: \"submission_started\" }\n | { type: \"submission_validation_failed\" }\n | { type: \"quote_changed\" }\n | { error: string; type: \"retryable_failure\" }\n | { error: string; type: \"recovery_failed\" }\n | { type: \"sold_out\" }\n | { message: string; type: \"succeeded\" }\n | { message: string; retryUrl?: string; type: \"unresolved\" };\n\nexport type PaymentUiState =\n | \"error\"\n | \"idle\"\n | \"invalid\"\n | \"sold_out\"\n | \"submitting\"\n | \"success\"\n | \"unresolved\";\n\nexport function createPaymentFormState(\n recoverPayment: boolean\n): PaymentFormState {\n return {\n error: undefined,\n message: undefined,\n status: recoverPayment ? \"recovering\" : \"editing\",\n };\n}\n\nfunction updateState(\n state: PaymentFormState,\n allowedStatuses: PaymentFormStatus[],\n changes: Partial<PaymentFormState>\n) {\n return allowedStatuses.includes(state.status)\n ? { ...state, ...changes }\n : state;\n}\n\nexport function paymentFormReducer(\n state: PaymentFormState,\n action: PaymentFormAction\n): PaymentFormState {\n if (action.type === \"recovery_started\" && state.status === \"unresolved\") {\n return { ...state, message: undefined, status: \"recovering\" };\n }\n\n if (\n state.status === \"sold_out\" ||\n state.status === \"succeeded\" ||\n state.status === \"unresolved\"\n ) {\n return state;\n }\n\n switch (action.type) {\n case \"field_changed\":\n return updateState(state, [\"editing\", \"invalid\", \"refreshing_quote\"], {\n error: undefined,\n status: \"editing\",\n });\n case \"validation_failed\":\n return updateState(state, [\"editing\"], { status: \"invalid\" });\n case \"quote_refresh_started\":\n return updateState(state, [\"editing\", \"invalid\"], {\n status: \"refreshing_quote\",\n });\n case \"quote_refresh_succeeded\":\n return updateState(state, [\"refreshing_quote\"], {\n error: undefined,\n status: \"editing\",\n });\n case \"quote_refresh_failed\":\n return updateState(state, [\"refreshing_quote\"], {\n error: action.error ?? state.error,\n status: \"editing\",\n });\n case \"submission_started\":\n return updateState(state, [\"editing\", \"invalid\", \"refreshing_quote\"], {\n error: undefined,\n status: \"submitting\",\n });\n case \"submission_validation_failed\":\n return updateState(state, [\"submitting\"], {\n error: undefined,\n status: \"invalid\",\n });\n case \"quote_changed\":\n return updateState(state, [\"submitting\"], { status: \"editing\" });\n case \"retryable_failure\":\n return updateState(state, [\"editing\", \"invalid\", \"submitting\"], {\n error: action.error,\n status: \"editing\",\n });\n case \"recovery_failed\":\n return updateState(state, [\"recovering\"], {\n error: action.error,\n retryUrl: undefined,\n status: \"editing\",\n });\n case \"sold_out\":\n return {\n error: undefined,\n message: undefined,\n status: \"sold_out\",\n };\n case \"succeeded\":\n return updateState(state, [\"recovering\", \"submitting\"], {\n message: action.message,\n retryUrl: undefined,\n status: \"succeeded\",\n });\n case \"unresolved\": {\n const changes: Partial<PaymentFormState> = {\n message: action.message,\n retryUrl: action.retryUrl,\n status: \"unresolved\",\n };\n return updateState(state, [\"recovering\", \"submitting\"], changes);\n }\n default:\n return state;\n }\n}\n\nexport function getPaymentError(state: PaymentFormState) {\n return state.status === \"editing\" ||\n state.status === \"invalid\" ||\n state.status === \"refreshing_quote\"\n ? state.error\n : undefined;\n}\n\nexport function getPaymentUiState(state: PaymentFormState): PaymentUiState {\n if (state.status === \"sold_out\") {\n return \"sold_out\";\n }\n if (state.status === \"succeeded\") {\n return \"success\";\n }\n if (state.status === \"unresolved\") {\n return \"unresolved\";\n }\n if (state.status === \"submitting\" || state.status === \"recovering\") {\n return \"submitting\";\n }\n if (state.status === \"invalid\") {\n return \"invalid\";\n }\n return getPaymentError(state) ? \"error\" : \"idle\";\n}\n\nexport function isPaymentBusy(state: PaymentFormState) {\n return state.status === \"submitting\";\n}\n","import type {\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\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\nconst SERVER_CONTROLLED_AMOUNT_KEYS = [\n \"discountableSubtotalCents\",\n \"discountCents\",\n \"subtotalCents\",\n] as const satisfies readonly (keyof LockerverseCheckoutQuote)[];\n\nexport function hasMaterialQuoteChange(\n displayed: LockerverseCheckoutEstimate | LockerverseCheckoutQuote,\n current: LockerverseCheckoutQuote,\n locallyPreviewedTotalCents: number | undefined,\n stripeConnectedAccountId: string | null\n) {\n const amountKeys =\n locallyPreviewedTotalCents === current.totalCents\n ? SERVER_CONTROLLED_AMOUNT_KEYS\n : AMOUNT_KEYS;\n return (\n amountKeys.some((key) => displayed[key] !== current[key]) ||\n stripeConnectedAccountId !== current.payment.connectedAccountId ||\n (displayed.authoritative &&\n (displayed.payment.connectedAccountId !== stripeConnectedAccountId ||\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 retryUrl?: string;\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 const outcome: PaymentAttemptOutcome = {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason:\n payment.checkoutStatus === \"action_required\"\n ? \"action_required\"\n : \"pending\",\n };\n if (payment.retryUrl) {\n outcome.retryUrl = payment.retryUrl;\n }\n return outcome;\n}\n\nasync function settleRequiredAction(\n client: LockerverseCheckoutClient,\n payment: LockerversePaymentResult,\n stripe: Stripe | null | undefined\n): Promise<PaymentAttemptOutcome> {\n if (payment.checkoutStatus !== \"action_required\" || !payment.requiresAction) {\n return classifyPayment(payment);\n }\n if (!stripe) {\n return {\n kind: \"unresolved\",\n paymentReference: payment.paymentReference,\n reason: \"action_required\",\n };\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 | null\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\nexport async function recoverPaymentAttempt(\n client: LockerverseCheckoutClient,\n paymentReference: string,\n stripe: Stripe | null\n): Promise<PaymentAttemptOutcome> {\n try {\n const payment = await client.getPaymentStatus(paymentReference);\n return settleRequiredAction(client, payment, stripe);\n } catch {\n return {\n kind: \"unresolved\",\n paymentReference,\n reason: \"recovery_failed\",\n };\n }\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 trim,\n union,\n} from \"valibot\";\nimport type { LockerversePaymentSelectionItem } from \"./types.ts\";\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 strictObject({\n productSlug: productSlugSchema,\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);\n\nexport function parseCustomTipCents(input: string) {\n const result = safeParse(customTipSchema, input);\n if (!result.success) {\n return {\n message: result.issues[0]?.message ?? \"Enter a valid tip amount.\",\n success: false,\n } as const;\n }\n const [dollars = \"0\", fraction = \"\"] = result.output.split(\".\");\n const cents = BigInt(dollars) * 100n + BigInt(fraction.padEnd(2, \"0\"));\n if (cents > BigInt(Number.MAX_SAFE_INTEGER)) {\n return { message: \"Enter a valid tip amount.\", success: false } as const;\n }\n return { cents: Number(cents), success: true } as const;\n}\n\nexport function parsePaymentSelection(\n input: LockerversePaymentSelectionItem[]\n) {\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 {\n LockerverseCatalog,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutPricingInput,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport { parseCustomTipCents } from \"./payment-input.ts\";\n\nconst INVALID_PROMO_MESSAGE =\n \"This promo code is invalid or cannot be applied.\";\n\nexport function getTipCents(\n subtotalCents: number,\n values: Pick<CheckoutFieldValues, \"customTip\" | \"tipPercent\">\n) {\n if (values.tipPercent === \"custom\") {\n if (!values.customTip.trim()) {\n return { cents: 0, success: true } as const;\n }\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\nexport function buildQuoteRequest(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n email: string,\n tipCents: number\n) {\n const request: LockerverseCheckoutPricingInput = {};\n if (email) {\n request.email = email;\n }\n if (catalog.widget.fields.serviceFee) {\n request.includeServiceFee = fieldValues.includeServiceFee;\n }\n if (catalog.widget.fields.promoCode && fieldValues.promoCode.trim()) {\n request.promoCode = fieldValues.promoCode.trim();\n }\n if (catalog.widget.fields.tipping) {\n request.tipCents = tipCents;\n }\n return request;\n}\n\nexport function getLocalQuotePreview(\n catalog: LockerverseCatalog,\n fieldValues: CheckoutFieldValues,\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout\n) {\n const parsedTip = catalog.widget.fields.tipping\n ? getTipCents(quote.subtotalCents, fieldValues)\n : ({ cents: 0, success: true } as const);\n if (!parsedTip.success) {\n return { parsedTip, totalCents: null };\n }\n\n const serviceFeeCents =\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 return {\n parsedTip,\n totalCents:\n quote.totalCents -\n quote.serviceFeeCents -\n quote.tipCents +\n serviceFeeCents +\n parsedTip.cents,\n };\n}\n\nexport function getQuoteRefreshSuccess(\n quote: LockerversePreparedCheckout,\n validatePromo: boolean\n) {\n return {\n displayedTotalCents: quote.totalCents,\n promoError:\n validatePromo && quote.appliedDiscount?.source !== \"promo_code\"\n ? INVALID_PROMO_MESSAGE\n : undefined,\n };\n}\n\nexport function getQuoteRefreshFailure<ErrorValue>(\n error: ErrorValue,\n validatePromo: boolean\n) {\n let paymentError: string | undefined;\n if (!validatePromo) {\n paymentError =\n error instanceof Error\n ? error.message\n : \"The order total could not be updated.\";\n }\n return {\n paymentError,\n promoError: validatePromo ? INVALID_PROMO_MESSAGE : undefined,\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePaymentSubmission,\n LockerversePreparedCheckout,\n LockerverseShipping,\n} from \"@lockerverse/sdk/checkout\";\nimport type {\n Stripe,\n StripeAddressElementChangeEvent,\n StripeElements,\n} from \"@stripe/stripe-js\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport {\n buildCustomFieldAnswers,\n getCheckoutCustomFields,\n} from \"./custom-fields.tsx\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n hasMaterialQuoteChange,\n type PaymentAttemptOutcome,\n submitPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport { buildQuoteRequest, getTipCents } from \"./payment-quote.ts\";\nimport { normalizePhone } from \"./payment-validation.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\n\nexport type CheckoutAddresses = Record<\n \"billing\" | \"shipping\",\n StripeAddressElementChangeEvent | null\n>;\n\nfunction getCompleteAddress(\n address: StripeAddressElementChangeEvent | null,\n label: \"Billing\" | \"Shipping\"\n) {\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 fieldValues: CheckoutFieldValues,\n billingAddress: ReturnType<typeof getCompleteAddress>,\n addresses: CheckoutAddresses\n) {\n if (!catalog.widget.fields.shipping) {\n return;\n }\n return fieldValues.shippingMatchesBilling\n ? billingAddress\n : getCompleteAddress(addresses.shipping, \"Shipping\");\n}\n\nfunction buildConfirmationParams({\n billingAddress,\n catalog,\n email,\n phone,\n shippingAddress,\n}: {\n billingAddress: ReturnType<typeof getCompleteAddress>;\n catalog: LockerverseCatalog;\n email: string;\n phone: string;\n shippingAddress: ReturnType<typeof getCompleteAddress> | undefined;\n}) {\n const billingDetails = catalog.widget.fields.phone\n ? {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n phone,\n }\n : {\n address: billingAddress.address,\n email,\n name: billingAddress.name,\n };\n const params = {\n payment_method_data: {\n billing_details: billingDetails,\n },\n };\n if (!shippingAddress) {\n return params;\n }\n return {\n ...params,\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\nfunction buildPaymentRequest({\n catalog,\n checkoutItems,\n confirmationToken,\n email,\n fieldValues,\n metadata,\n phone,\n shippingAddress,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n confirmationToken: string | undefined;\n email: string;\n fieldValues: CheckoutFieldValues;\n metadata: Record<string, string> | undefined;\n phone: string;\n shippingAddress: ReturnType<typeof getCompleteAddress> | undefined;\n}) {\n const request: LockerversePaymentSubmission = {\n customFieldAnswers: buildCustomFieldAnswers(\n getCheckoutCustomFields(catalog, checkoutItems),\n fieldValues.customFields\n ),\n email,\n };\n if (confirmationToken) {\n request.confirmationToken = confirmationToken;\n }\n if (metadata) {\n request.metadata = metadata;\n }\n if (catalog.widget.fields.memberId && fieldValues.memberId.trim()) {\n request.memberId = fieldValues.memberId.trim();\n }\n if (catalog.widget.fields.merchSize) {\n request.merchSize = fieldValues.merchSize;\n }\n if (catalog.widget.fields.phone) {\n request.phone = phone;\n }\n if (shippingAddress) {\n const address: LockerverseShipping[\"address\"] = {\n city: shippingAddress.address.city ?? \"\",\n country: shippingAddress.address.country,\n line1: shippingAddress.address.line1 ?? \"\",\n postal_code: shippingAddress.address.postal_code ?? \"\",\n state: shippingAddress.address.state ?? \"\",\n };\n if (shippingAddress.address.line2) {\n address.line2 = shippingAddress.address.line2;\n }\n request.shipping = { address, name: shippingAddress.name };\n }\n return request;\n}\n\nfunction assertPaymentAttemptActive(isAttemptActive: () => boolean) {\n if (!isAttemptActive()) {\n throw new Error(\"Payment component is no longer active.\");\n }\n}\n\nfunction notifyPaymentRecovery(\n callback: LockerversePaymentProps[\"onPaymentRecoveryChange\"],\n recovery: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentRecoveryChange\"]>\n >[0]\n) {\n notifyHostCallback(callback, recovery);\n}\n\nfunction mapPaymentAttemptOutcome(\n outcome: PaymentAttemptOutcome,\n quote: LockerversePreparedCheckout,\n email: string,\n failureMessage: string\n) {\n if (outcome.kind === \"failed\") {\n return {\n kind: \"payment_failed\" as const,\n message: failureMessage,\n };\n }\n if (outcome.kind === \"unresolved\") {\n return {\n kind: \"payment_unresolved\" as const,\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n retryUrl: outcome.retryUrl,\n };\n }\n return {\n email,\n kind: \"payment\" as const,\n payment: outcome.payment,\n quote,\n };\n}\n\nexport type CompletePaymentOptions = {\n addresses: CheckoutAddresses;\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n elements?: StripeElements | null;\n email: string;\n fieldValues: CheckoutFieldValues;\n isAttemptActive: () => boolean;\n locallyPreviewedTotalCents: number;\n metadata: Record<string, string> | undefined;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n phone: string;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n stripe?: Stripe | null;\n stripeConnectedAccountId: string | null;\n};\n\nexport async function completePayment({\n addresses,\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n isAttemptActive,\n locallyPreviewedTotalCents,\n metadata,\n onPaymentRecoveryChange,\n phone,\n quote,\n stripe,\n stripeConnectedAccountId,\n}: CompletePaymentOptions) {\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 client.calculateTotal({\n ...buildQuoteRequest(\n catalog,\n fieldValues,\n normalizedEmail,\n parsedTip.cents\n ),\n catalog,\n items: checkoutItems,\n });\n assertPaymentAttemptActive(isAttemptActive);\n if (\n currentQuote.totalCents > 0 &&\n hasMaterialQuoteChange(\n quote,\n currentQuote,\n locallyPreviewedTotalCents,\n stripeConnectedAccountId\n )\n ) {\n return { kind: \"quote_changed\" as const, quote: currentQuote };\n }\n\n let completeShippingAddress:\n | ReturnType<typeof getCompleteAddress>\n | undefined;\n let confirmationToken: string | undefined;\n if (currentQuote.totalCents === 0) {\n if (catalog.widget.fields.shipping) {\n const completeBillingAddress = getCompleteAddress(\n addresses.billing,\n \"Billing\"\n );\n completeShippingAddress = getShippingAddress(\n catalog,\n fieldValues,\n completeBillingAddress,\n addresses\n );\n }\n } else {\n if (!(elements && stripe)) {\n throw new Error(\"Payment form is still loading.\");\n }\n await elements.update({ amount: currentQuote.totalCents });\n assertPaymentAttemptActive(isAttemptActive);\n const elementSubmission = await elements.submit();\n assertPaymentAttemptActive(isAttemptActive);\n if (elementSubmission.error) {\n throw new Error(elementSubmission.error.message);\n }\n\n const completeBillingAddress = getCompleteAddress(\n addresses.billing,\n \"Billing\"\n );\n completeShippingAddress = getShippingAddress(\n catalog,\n fieldValues,\n completeBillingAddress,\n addresses\n );\n const tokenResult = await stripe.createConfirmationToken({\n elements,\n params: buildConfirmationParams({\n billingAddress: completeBillingAddress,\n catalog,\n email: normalizedEmail,\n phone: normalizedPhone,\n shippingAddress: completeShippingAddress,\n }),\n });\n assertPaymentAttemptActive(isAttemptActive);\n if (tokenResult.error) {\n throw new Error(tokenResult.error.message);\n }\n confirmationToken = tokenResult.confirmationToken.id;\n }\n\n notifyPaymentRecovery(onPaymentRecoveryChange, {\n connectedAccountId: currentQuote.payment.connectedAccountId,\n paymentReference: currentQuote.paymentReference,\n });\n const outcome = await submitPaymentAttempt(\n client,\n {\n checkout: currentQuote,\n submission: buildPaymentRequest({\n catalog,\n checkoutItems,\n confirmationToken,\n email: normalizedEmail,\n fieldValues,\n metadata,\n phone: normalizedPhone,\n shippingAddress: completeShippingAddress,\n }),\n },\n stripe\n );\n assertPaymentAttemptActive(isAttemptActive);\n return mapPaymentAttemptOutcome(\n outcome,\n currentQuote,\n normalizedEmail,\n currentQuote.totalCents === 0\n ? \"Order could not be completed. Review the details and try again.\"\n : \"Payment was declined. Check your payment details and try again.\"\n );\n}\n\nexport type CompletePaymentResult = Awaited<ReturnType<typeof completePayment>>;\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePaymentCompletion,\n LockerversePaymentResult,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport { LockerverseSdkError } from \"@lockerverse/sdk/checkout\";\nimport type { Stripe, StripeElements } from \"@stripe/stripe-js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { CheckoutFieldValues } from \"./checkout-fields.tsx\";\nimport { getPhoneServerError } from \"./contact-validation.ts\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n type PaymentAttemptOutcome,\n recoverPaymentAttempt,\n} from \"./payment-attempt.ts\";\nimport {\n getPaymentError,\n getPaymentUiState,\n isPaymentBusy,\n type PaymentFormAction,\n type PaymentFormState,\n type PaymentUiState,\n} from \"./payment-form-state.ts\";\nimport {\n buildQuoteRequest,\n getLocalQuotePreview,\n getQuoteRefreshFailure,\n getQuoteRefreshSuccess,\n} from \"./payment-quote.ts\";\nimport {\n type CheckoutAddresses,\n type CompletePaymentResult,\n completePayment,\n} from \"./payment-submission.ts\";\nimport { validateContact } from \"./payment-validation.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\n\nfunction notifyPaymentRecovery(\n callback: LockerversePaymentProps[\"onPaymentRecoveryChange\"],\n recovery: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentRecoveryChange\"]>\n >[0]\n) {\n notifyHostCallback(callback, recovery);\n}\n\nfunction notifyPaymentUncertain(\n callback: LockerversePaymentProps[\"onPaymentUncertain\"],\n payment: Parameters<\n NonNullable<LockerversePaymentProps[\"onPaymentUncertain\"]>\n >[0]\n) {\n notifyHostCallback(callback, payment);\n}\n\nfunction createPaymentCompletion(\n payment: LockerversePaymentResult,\n context: Pick<LockerversePaymentCompletion, \"email\" | \"lineItems\">\n): LockerversePaymentCompletion {\n return { ...payment, ...context };\n}\n\nfunction unresolvedPaymentState(outcome: {\n reason: string;\n retryUrl?: string | undefined;\n}) {\n const action: PaymentFormAction = {\n message:\n outcome.reason === \"action_required\"\n ? \"Payment needs your attention. Keep this checkout open.\"\n : \"Payment is not complete. Check its status before you try again.\",\n type: \"unresolved\",\n };\n if (outcome.retryUrl) {\n action.retryUrl = outcome.retryUrl;\n }\n return action;\n}\n\nfunction mustWaitForStripe(\n outcome: PaymentAttemptOutcome,\n stripe: Stripe | null,\n stripeLoadFailed: boolean\n) {\n return (\n outcome.kind === \"unresolved\" &&\n outcome.reason === \"action_required\" &&\n !outcome.retryUrl &&\n !stripe &&\n !stripeLoadFailed\n );\n}\n\nfunction isSoldOutError<ErrorValue>(error: ErrorValue) {\n return (\n error instanceof LockerverseSdkError &&\n error.serverCode === \"PAYMENT_WIDGET_SALES_LIMIT_REACHED\"\n );\n}\n\nexport type PaymentFormControllerOptions = {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n elements: StripeElements | null;\n email: string;\n fieldValues: CheckoutFieldValues;\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n stripe: Stripe | null;\n stripeConnectedAccountId: string | null;\n stripeLoadFailed: boolean;\n paymentState: PaymentFormState;\n updateState: (action: PaymentFormAction, notifyHost?: boolean) => void;\n};\n\ntype SubmitPayment = {\n addresses: CheckoutAddresses;\n phone: string;\n};\n\nfunction applyQuoteRefreshSuccess({\n nextQuote,\n onQuoteChange,\n setDisplayedTotalCents,\n setPromoError,\n updateState,\n validatePromo,\n}: {\n nextQuote: LockerversePreparedCheckout;\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n setDisplayedTotalCents: (total: number) => void;\n setPromoError: (error: string | undefined) => void;\n updateState: (action: PaymentFormAction) => void;\n validatePromo: boolean;\n}) {\n const result = getQuoteRefreshSuccess(nextQuote, validatePromo);\n updateState({ type: \"quote_refresh_succeeded\" });\n setDisplayedTotalCents(result.displayedTotalCents);\n onQuoteChange(nextQuote);\n if (validatePromo) {\n setPromoError(result.promoError);\n }\n}\n\nfunction applyQuoteRefreshFailure({\n error,\n setPromoError,\n updateState,\n validatePromo,\n}: {\n error: unknown;\n setPromoError: (error: string | undefined) => void;\n updateState: (action: PaymentFormAction) => void;\n validatePromo: boolean;\n}) {\n const result = getQuoteRefreshFailure(error, validatePromo);\n if (validatePromo) {\n setPromoError(result.promoError);\n }\n updateState(\n result.paymentError === undefined\n ? { type: \"quote_refresh_failed\" }\n : { error: result.paymentError, type: \"quote_refresh_failed\" }\n );\n}\n\nfunction applyPaymentOutcome({\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n result,\n setDisplayedTotalCents,\n dispatchState,\n unresolvedReferenceRef,\n}: {\n unresolvedReferenceRef: { current: string | undefined };\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n result: CompletePaymentResult;\n setDisplayedTotalCents: (total: number) => void;\n dispatchState: (action: PaymentFormAction) => 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 dispatchState({ type: \"quote_changed\" });\n return;\n }\n if (result.kind === \"payment_failed\") {\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({ error: result.message, type: \"retryable_failure\" });\n return;\n }\n if (result.kind === \"payment_unresolved\") {\n unresolvedReferenceRef.current = result.paymentReference;\n dispatchState(unresolvedPaymentState(result));\n notifyPaymentUncertain(onPaymentUncertain, {\n paymentReference: result.paymentReference,\n reason: result.reason,\n });\n return;\n }\n onQuoteChange(result.quote);\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({\n message: result.payment.paymentRequired\n ? \"Payment completed successfully.\"\n : \"Order confirmed. No payment was required.\",\n type: \"succeeded\",\n });\n notifyHostCallback(\n onPaymentComplete,\n createPaymentCompletion(result.payment, {\n email: result.email,\n lineItems: result.quote.lineItems,\n })\n );\n}\n\nexport function usePaymentFormController(\n options: PaymentFormControllerOptions\n) {\n const {\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n resumePayment,\n stripe,\n stripeConnectedAccountId,\n stripeLoadFailed,\n paymentState,\n updateState,\n } = options;\n const [displayedTotalCents, setDisplayedTotalCents] = useState(\n quote.totalCents\n );\n const [promoError, setPromoError] = useState<string>();\n const recoveryStartedRef = useRef(false);\n const unresolvedReferenceRef = useRef<string | undefined>(undefined);\n const quoteRequestRef = useRef(0);\n const attemptGenerationRef = useRef(0);\n const dispatchState = useCallback(\n (action: PaymentFormAction) => updateState(action, true),\n [updateState]\n );\n const startPaymentAttempt = useCallback(() => {\n const generation = attemptGenerationRef.current + 1;\n attemptGenerationRef.current = generation;\n return () => attemptGenerationRef.current === generation;\n }, []);\n\n useEffect(\n () => () => {\n attemptGenerationRef.current += 1;\n quoteRequestRef.current += 1;\n },\n []\n );\n\n const { parsedTip, totalCents: previewTotalCents } = getLocalQuotePreview(\n catalog,\n fieldValues,\n quote\n );\n\n useEffect(() => {\n if (previewTotalCents === null) {\n return;\n }\n setDisplayedTotalCents(previewTotalCents);\n if (previewTotalCents > 0) {\n elements?.update({ amount: previewTotalCents });\n }\n }, [\n catalog.pricingPolicy.serviceFeeRateBasisPoints,\n catalog.widget.fields.serviceFee,\n elements,\n fieldValues.includeServiceFee,\n previewTotalCents,\n quote.serviceFeeCents,\n quote.tipCents,\n quote.totalCents,\n quote.subtotalCents,\n ]);\n\n useEffect(() => {\n const paymentReference =\n resumePayment?.paymentReference ?? unresolvedReferenceRef.current;\n if (\n !paymentReference ||\n recoveryStartedRef.current ||\n paymentState.status !== \"recovering\"\n ) {\n return;\n }\n recoveryStartedRef.current = true;\n const isAttemptActive = startPaymentAttempt();\n onStateChange(getPaymentUiState(paymentState));\n\n recoverPaymentAttempt(client, paymentReference, stripe).then((outcome) => {\n if (!isAttemptActive()) {\n return;\n }\n if (mustWaitForStripe(outcome, stripe, stripeLoadFailed)) {\n return;\n }\n if (outcome.kind === \"failed\") {\n const message =\n \"The previous payment failed. Check your details and try again.\";\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n onResumePaymentFailed();\n dispatchState({\n error: message,\n type: \"recovery_failed\",\n });\n return;\n }\n if (outcome.kind === \"unresolved\") {\n dispatchState(unresolvedPaymentState(outcome));\n notifyPaymentUncertain(onPaymentUncertain, {\n paymentReference: outcome.paymentReference,\n reason: outcome.reason,\n });\n return;\n }\n\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n dispatchState({\n message: outcome.payment.paymentRequired\n ? \"Payment completed successfully.\"\n : \"Order confirmed. No payment was required.\",\n type: \"succeeded\",\n });\n notifyHostCallback(\n onPaymentComplete,\n createPaymentCompletion(outcome.payment, {\n email: null,\n lineItems: null,\n })\n );\n });\n return () => {\n if (isAttemptActive()) {\n attemptGenerationRef.current += 1;\n }\n recoveryStartedRef.current = false;\n };\n }, [\n client,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onStateChange,\n resumePayment,\n stripe,\n stripeLoadFailed,\n startPaymentAttempt,\n dispatchState,\n paymentState,\n ]);\n\n const fieldChanged = useCallback(\n (clearPromo = false, preserveQuoteRequest = false) => {\n if (!preserveQuoteRequest) {\n quoteRequestRef.current += 1;\n }\n if (clearPromo) {\n setPromoError(undefined);\n }\n updateState({ type: \"field_changed\" });\n },\n [updateState]\n );\n\n async function refreshAuthoritativeTotal(\n allowMissingEmail = false,\n validatePromo = false\n ) {\n const normalizedEmail = email.trim().toLowerCase();\n const emailValidation = validateContact(\n { email: normalizedEmail, phone: \"\" },\n false\n );\n if (!(parsedTip.success && (emailValidation.value || allowMissingEmail))) {\n return;\n }\n\n quoteRequestRef.current += 1;\n const requestId = quoteRequestRef.current;\n updateState({ type: \"quote_refresh_started\" });\n try {\n const nextQuote = await client.calculateTotal({\n ...buildQuoteRequest(\n catalog,\n fieldValues,\n emailValidation.value?.email ?? \"\",\n parsedTip.cents\n ),\n catalog,\n items: checkoutItems,\n });\n if (requestId !== quoteRequestRef.current) {\n return;\n }\n applyQuoteRefreshSuccess({\n nextQuote,\n onQuoteChange,\n setDisplayedTotalCents,\n setPromoError,\n updateState,\n validatePromo,\n });\n } catch (error) {\n if (requestId !== quoteRequestRef.current) {\n return;\n }\n if (isSoldOutError(error)) {\n updateState({ type: \"sold_out\" });\n return;\n }\n applyQuoteRefreshFailure({\n error,\n setPromoError,\n updateState,\n validatePromo,\n });\n }\n }\n\n async function applyPromo() {\n setPromoError(undefined);\n await refreshAuthoritativeTotal(true, true);\n }\n\n async function submit({ addresses, phone }: SubmitPayment) {\n dispatchState({ type: \"submission_started\" });\n const isAttemptActive = startPaymentAttempt();\n try {\n const result = await completePayment({\n addresses,\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n isAttemptActive,\n locallyPreviewedTotalCents: displayedTotalCents,\n metadata,\n onPaymentRecoveryChange,\n phone,\n quote,\n stripe,\n stripeConnectedAccountId,\n });\n if (!isAttemptActive()) {\n return;\n }\n applyPaymentOutcome({\n dispatchState,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n result,\n setDisplayedTotalCents,\n unresolvedReferenceRef,\n });\n } catch (error) {\n if (!isAttemptActive()) {\n return;\n }\n notifyPaymentRecovery(onPaymentRecoveryChange, null);\n if (isSoldOutError(error)) {\n dispatchState({ type: \"sold_out\" });\n return;\n }\n const phoneError =\n error instanceof LockerverseSdkError\n ? getPhoneServerError(error.serverCode)\n : undefined;\n if (phoneError) {\n dispatchState({ type: \"submission_validation_failed\" });\n return { phoneError };\n }\n dispatchState({\n error:\n error instanceof Error\n ? error.message\n : \"Payment could not be completed.\",\n type: \"retryable_failure\",\n });\n }\n }\n\n const terminalMessage =\n paymentState.status === \"succeeded\" || paymentState.status === \"unresolved\"\n ? paymentState.message\n : undefined;\n return {\n commands: {\n applyPromo,\n checkPaymentStatus: () => dispatchState({ type: \"recovery_started\" }),\n fieldChanged,\n refreshAuthoritativeTotal,\n reportStripeLoadError: (message: string) =>\n dispatchState({ error: message, type: \"retryable_failure\" }),\n reportValidationFailure: () =>\n dispatchState({ type: \"validation_failed\" }),\n submit,\n },\n state: {\n displayedTotalCents,\n isRecovering: paymentState.status === \"recovering\",\n isRefreshingQuote: paymentState.status === \"refreshing_quote\",\n isSubmitting: isPaymentBusy(paymentState),\n isUnresolved: paymentState.status === \"unresolved\",\n parsedTip,\n paymentError: getPaymentError(paymentState),\n promoError,\n retryUrl: paymentState.retryUrl,\n terminalMessage,\n },\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\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 { StripeAddressElementChangeEvent } from \"@stripe/stripe-js\";\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport {\n AdditionalCheckoutFields,\n type CheckoutFieldValues,\n CheckoutToggle,\n ServiceFeeField,\n TipField,\n} from \"./checkout-fields.tsx\";\nimport {\n createCustomFieldValues,\n getCheckoutCustomFields,\n validateCustomFields,\n} from \"./custom-fields.tsx\";\nimport { EmailField, FormField } from \"./form-field.tsx\";\nimport { FormSkeleton } from \"./form-skeleton.tsx\";\nimport { formatMoney } from \"./format-money.ts\";\nimport {\n createPaymentFormState,\n getPaymentUiState,\n type PaymentFormAction,\n type PaymentFormState,\n type PaymentUiState,\n paymentFormReducer,\n} from \"./payment-form-state.ts\";\nimport type { CheckoutAddresses } from \"./payment-submission.ts\";\nimport { PaymentSummary } from \"./payment-summary.tsx\";\nimport { validateContact } from \"./payment-validation.ts\";\nimport { getInternationalPhone } from \"./phone.ts\";\nimport type { PhoneInputValue } from \"./phone-field.tsx\";\nimport { PhoneInput } from \"./phone-field.tsx\";\nimport { useStripeAppearance } from \"./stripe-appearance.ts\";\nimport { defaultLockerverseStripeLoader as cachedStripeLoader } from \"./stripe-loader.ts\";\nimport type { LockerversePaymentProps } from \"./types.ts\";\nimport { usePaymentFormController } from \"./use-payment-form-controller.ts\";\n\nexport const defaultLockerverseStripeLoader = cachedStripeLoader;\n\nexport function preloadLockerversePayment(\n catalog: Pick<LockerverseCatalog, \"payment\">\n) {\n const { connectedAccountId, publishableKey } = catalog.payment;\n return defaultLockerverseStripeLoader(\n publishableKey,\n connectedAccountId ? { stripeAccount: connectedAccountId } : undefined\n );\n}\n\nfunction getRecurringCadence(\n paymentOption: LockerversePreparedCheckout[\"paymentOption\"]\n) {\n if (paymentOption === \"monthly\") {\n return { interval: \"month\", label: \"Monthly\" } as const;\n }\n if (paymentOption === \"annually\") {\n return { interval: \"year\", label: \"Annual\" } as const;\n }\n if (paymentOption === \"every-six-months\") {\n return { interval: \"6 months\", label: \"Every 6 months\" } as const;\n }\n return null;\n}\n\nfunction getConnectedAccountId(\n catalog: LockerverseCatalog,\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout,\n resumePayment: LockerversePaymentProps[\"resumePayment\"]\n) {\n if (resumePayment) {\n const { connectedAccountId } = resumePayment;\n return connectedAccountId;\n }\n if (\"payment\" in quote) {\n const { connectedAccountId } = quote.payment;\n return connectedAccountId;\n }\n const { connectedAccountId } = catalog.payment;\n return connectedAccountId;\n}\n\nexport function ReadyPayment({\n accentColor,\n catalog,\n checkoutItems,\n client,\n appearanceRoot,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n quote,\n resumePayment,\n onStateChange,\n stripeLoader,\n theme,\n visualStyle,\n}: {\n accentColor: string;\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n appearanceRoot: RefObject<HTMLElement | null>;\n initialCustomFieldValues: LockerversePaymentProps[\"initialCustomFieldValues\"];\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n onStateChange: (state: PaymentUiState) => void;\n stripeLoader: NonNullable<LockerversePaymentProps[\"stripeLoader\"]>;\n theme: LockerversePaymentProps[\"theme\"];\n visualStyle: LockerversePaymentProps[\"style\"];\n}) {\n const [paymentState, setPaymentState] = useState(() =>\n createPaymentFormState(Boolean(resumePayment))\n );\n const paymentStateRef = useRef(paymentState);\n paymentStateRef.current = paymentState;\n const updateState = useCallback(\n (action: PaymentFormAction, notifyHost = false) => {\n const next = paymentFormReducer(paymentStateRef.current, action);\n if (next === paymentStateRef.current) {\n return;\n }\n paymentStateRef.current = next;\n setPaymentState(next);\n if (notifyHost) {\n onStateChange(getPaymentUiState(next));\n }\n },\n [onStateChange]\n );\n const requestedConnectedAccountId = getConnectedAccountId(\n catalog,\n quote,\n resumePayment\n );\n const stripeConfigurationRef = useRef({\n connectedAccountId: requestedConnectedAccountId,\n paymentOption: quote.paymentOption,\n });\n if (\n paymentState.status !== \"submitting\" &&\n paymentState.status !== \"recovering\"\n ) {\n stripeConfigurationRef.current = {\n connectedAccountId: requestedConnectedAccountId,\n paymentOption: quote.paymentOption,\n };\n }\n const { connectedAccountId, paymentOption } = stripeConfigurationRef.current;\n const stripe = useMemo(\n () =>\n stripeLoader(\n catalog.payment.publishableKey,\n connectedAccountId ? { stripeAccount: connectedAccountId } : undefined\n ).catch(() => null),\n [catalog.payment.publishableKey, connectedAccountId, stripeLoader]\n );\n const [stripeLoadFailed, setStripeLoadFailed] = useState(false);\n useEffect(() => {\n let active = true;\n setStripeLoadFailed(false);\n stripe.then((loadedStripe) => {\n if (active && loadedStripe === null) {\n setStripeLoadFailed(true);\n }\n });\n return () => {\n active = false;\n };\n }, [stripe]);\n\n const appearance = useStripeAppearance(\n appearanceRoot,\n theme,\n visualStyle,\n paymentState.status === \"submitting\" ||\n paymentState.status === \"recovering\",\n accentColor\n );\n if (!appearance) {\n return <FormSkeleton fieldCount={3} label=\"Loading payment form\" />;\n }\n\n return (\n <Elements\n key={`${catalog.payment.publishableKey}:${connectedAccountId ?? \"platform\"}:${paymentOption}`}\n options={{\n amount: Math.max(quote.totalCents, 100),\n appearance,\n currency: catalog.payment.currency,\n excludedPaymentMethodTypes: catalog.community?.widgetAchEnabled\n ? []\n : [\"us_bank_account\"],\n mode: paymentOption === \"one-time\" ? \"payment\" : \"subscription\",\n syncAddressCheckbox: \"none\",\n }}\n stripe={stripe}\n >\n <PaymentForm\n catalog={catalog}\n checkoutItems={checkoutItems}\n client={client}\n initialCustomFieldValues={initialCustomFieldValues}\n metadata={metadata}\n onPaymentComplete={onPaymentComplete}\n onPaymentRecoveryChange={onPaymentRecoveryChange}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={onQuoteChange}\n onResumePaymentFailed={onResumePaymentFailed}\n onStateChange={onStateChange}\n paymentState={paymentState}\n quote={quote}\n resumePayment={resumePayment}\n stripeConnectedAccountId={connectedAccountId}\n stripeLoadFailed={stripeLoadFailed}\n updateState={updateState}\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 <div className=\"lockerverse-payment__stripe-mount\">\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: {\n billingDetails: {\n address: \"never\",\n email: \"never\",\n name: \"never\",\n phone: \"never\",\n },\n },\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: \"auto\",\n },\n wallets: { applePay: \"auto\", googlePay: \"never\" },\n }}\n />\n </div>\n </div>\n );\n}\n\nfunction StripeAddressField({\n label,\n mode,\n onChange,\n onError,\n onReady,\n ready,\n}: {\n label: string;\n mode: \"billing\" | \"shipping\";\n onChange: (address: StripeAddressElementChangeEvent) => void;\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 <div className=\"lockerverse-payment__stripe-mount\">\n <AddressElement\n onChange={onChange}\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 </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\nfunction StripeCheckoutFields({\n catalog,\n displayedTotalCents,\n fieldValues,\n isBillingAddressReady,\n isPaymentReady,\n isShippingAddressReady,\n onAddressChange,\n onFieldValuesChange,\n onStripeLoadError,\n setIsBillingAddressReady,\n setIsPaymentReady,\n setIsShippingAddressReady,\n}: {\n catalog: LockerverseCatalog;\n displayedTotalCents: number;\n fieldValues: CheckoutFieldValues;\n isBillingAddressReady: boolean;\n isPaymentReady: boolean;\n isShippingAddressReady: boolean;\n onAddressChange: (\n mode: \"billing\" | \"shipping\",\n address: StripeAddressElementChangeEvent | null\n ) => void;\n onFieldValuesChange: (values: CheckoutFieldValues) => void;\n onStripeLoadError: (message: string) => void;\n setIsBillingAddressReady: (ready: boolean) => void;\n setIsPaymentReady: (ready: boolean) => void;\n setIsShippingAddressReady: (ready: boolean) => void;\n}) {\n const requiresPayment = displayedTotalCents > 0;\n\n return (\n <>\n {requiresPayment ? (\n <StripePaymentField\n onError={onStripeLoadError}\n onReady={() => setIsPaymentReady(true)}\n ready={isPaymentReady}\n />\n ) : null}\n {requiresPayment || catalog.widget.fields.shipping ? (\n <StripeAddressField\n label={requiresPayment ? \"Billing address\" : \"Shipping address\"}\n mode=\"billing\"\n onChange={(address) => onAddressChange(\"billing\", address)}\n onError={onStripeLoadError}\n onReady={() => setIsBillingAddressReady(true)}\n ready={isBillingAddressReady}\n />\n ) : null}\n {catalog.widget.fields.shipping ? (\n <div className=\"lockerverse-payment__shipping\">\n <CheckoutToggle\n checked={fieldValues.shippingMatchesBilling}\n name=\"shippingMatchesBilling\"\n onChange={(shippingMatchesBilling) => {\n onFieldValuesChange({\n ...fieldValues,\n shippingMatchesBilling,\n });\n if (shippingMatchesBilling) {\n onAddressChange(\"shipping\", null);\n } else {\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 onChange={(address) => onAddressChange(\"shipping\", address)}\n onError={onStripeLoadError}\n onReady={() => setIsShippingAddressReady(true)}\n ready={isShippingAddressReady}\n />\n )}\n </div>\n ) : null}\n </>\n );\n}\n\nfunction PaymentAction({\n catalog,\n displayedTotalCents,\n fieldValues,\n isBillingAddressReady,\n isPaymentReady,\n isRequiredShippingReady,\n isSubmitting,\n onFieldValuesChange,\n quote,\n}: {\n catalog: LockerverseCatalog;\n displayedTotalCents: number;\n fieldValues: CheckoutFieldValues;\n isBillingAddressReady: boolean;\n isPaymentReady: boolean;\n isRequiredShippingReady: boolean;\n isSubmitting: boolean;\n onFieldValuesChange: (values: CheckoutFieldValues) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n}) {\n const isFree = displayedTotalCents === 0;\n const isReady = isFree\n ? !catalog.widget.fields.shipping ||\n (isBillingAddressReady && isRequiredShippingReady)\n : isPaymentReady && isBillingAddressReady && isRequiredShippingReady;\n const cadence = getRecurringCadence(quote.paymentOption);\n let label = isFree\n ? \"Complete order\"\n : `Pay ${formatMoney(displayedTotalCents)}`;\n if (!isFree && cadence) {\n label = `Subscribe for ${formatMoney(displayedTotalCents)}/${cadence.interval}`;\n }\n if (isSubmitting) {\n label = isFree ? \"Completing…\" : \"Processing…\";\n }\n let actionLabel = `Process payment for ${formatMoney(displayedTotalCents)} total`;\n if (isFree) {\n actionLabel = \"Complete order\";\n } else if (cadence) {\n actionLabel = `Start ${cadence.label.toLowerCase()} subscription for ${formatMoney(displayedTotalCents)}`;\n }\n return (\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={onFieldValuesChange}\n values={fieldValues}\n />\n <button\n aria-busy={isSubmitting}\n aria-label={actionLabel}\n disabled={isSubmitting || !isReady}\n type=\"submit\"\n >\n {label}\n </button>\n </div>\n );\n}\n\nfunction focusNamedFormControl(form: HTMLFormElement, name: string) {\n const control = form.elements.namedItem(name);\n if (control instanceof HTMLElement) {\n control.focus();\n return;\n }\n if (control instanceof RadioNodeList) {\n Array.from(control)\n .find((item) => item instanceof HTMLElement)\n ?.focus();\n }\n}\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 focusNamedFormControl(form, `custom:${firstFieldId}`);\n }\n}\n\nfunction ContactFields({\n email,\n emailDiscountPercentOff,\n emailErrorId,\n emailId,\n emailRef,\n errors,\n onEmailBlur,\n onEmailChange,\n onPhoneChange,\n phone,\n phoneCountry,\n phoneEnabled,\n phoneErrorId,\n phoneId,\n phoneRef,\n}: {\n email: string;\n emailDiscountPercentOff: number | undefined;\n emailErrorId: string;\n emailId: string;\n emailRef: React.RefObject<HTMLInputElement | null>;\n errors: { email?: string; phone?: string };\n onEmailBlur: () => void;\n onEmailChange: (value: string) => void;\n onPhoneChange: (value: PhoneInputValue) => 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 <EmailField\n error={errors.email}\n errorId={emailErrorId}\n id={emailId}\n label=\"Email\"\n name=\"email\"\n onBlur={onEmailBlur}\n onChange={(event) => onEmailChange(event.currentTarget.value)}\n ref={emailRef}\n required\n value={email}\n />\n {emailDiscountPercentOff === undefined ? null : (\n <p className=\"lockerverse-payment__discount-message\" role=\"status\">\n Your email qualifies for {emailDiscountPercentOff}% off.\n </p>\n )}\n {phoneEnabled ? (\n <FormField\n error={errors.phone}\n errorId={phoneErrorId}\n id={phoneId}\n label=\"Phone\"\n >\n <PhoneInput\n country={phoneCountry}\n error={errors.phone}\n errorId={phoneErrorId}\n id={phoneId}\n inputRef={phoneRef}\n name=\"phone\"\n onChange={onPhoneChange}\n required\n value={phone}\n />\n </FormField>\n ) : null}\n </div>\n );\n}\n\nfunction PaymentForm({\n catalog,\n checkoutItems,\n client,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onResumePaymentFailed,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onStateChange,\n quote,\n resumePayment,\n stripeConnectedAccountId,\n stripeLoadFailed,\n paymentState,\n updateState,\n}: {\n catalog: LockerverseCatalog;\n checkoutItems: LockerverseCheckoutItem[];\n client: LockerverseCheckoutClient;\n initialCustomFieldValues: LockerversePaymentProps[\"initialCustomFieldValues\"];\n metadata: Record<string, string> | undefined;\n onPaymentComplete: LockerversePaymentProps[\"onPaymentComplete\"];\n onResumePaymentFailed: () => void;\n onPaymentRecoveryChange: LockerversePaymentProps[\"onPaymentRecoveryChange\"];\n onPaymentUncertain: LockerversePaymentProps[\"onPaymentUncertain\"];\n onQuoteChange: (quote: LockerversePreparedCheckout, notice?: string) => void;\n onStateChange: (state: PaymentUiState) => void;\n quote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n resumePayment: LockerversePaymentProps[\"resumePayment\"];\n stripeConnectedAccountId: string | null;\n stripeLoadFailed: boolean;\n paymentState: PaymentFormState;\n updateState: (action: PaymentFormAction, notifyHost?: boolean) => void;\n}) {\n const customFields = getCheckoutCustomFields(catalog, checkoutItems);\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 [customFieldErrors, setCustomFieldErrors] = useState<\n Record<string, string>\n >({});\n const [tipError, setTipError] = useState<string>();\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: createCustomFieldValues(\n customFields,\n initialCustomFieldValues\n ),\n customTip: \"\",\n includeServiceFee: catalog.widget.fields.serviceFee,\n memberId: \"\",\n merchSize: \"M\",\n promoCode: \"\",\n shippingMatchesBilling: true,\n tipPercent: \"10\",\n }));\n const addressesRef = useRef<CheckoutAddresses>({\n billing: null,\n shipping: null,\n });\n const emailRef = useRef<HTMLInputElement>(null);\n const phoneRef = useRef<HTMLInputElement>(null);\n const statusRef = useRef<HTMLParagraphElement>(null);\n const paymentWasRequiredRef = useRef(quote.totalCents > 0);\n const elements = useElements();\n const stripe = useStripe();\n const controller = usePaymentFormController({\n catalog,\n checkoutItems,\n client,\n elements,\n email,\n fieldValues,\n metadata,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n onQuoteChange,\n onResumePaymentFailed,\n onStateChange,\n paymentState,\n quote,\n resumePayment,\n stripe,\n stripeConnectedAccountId,\n stripeLoadFailed,\n updateState,\n });\n const {\n displayedTotalCents,\n isRecovering,\n isUnresolved,\n isRefreshingQuote,\n isSubmitting,\n parsedTip,\n paymentError,\n promoError,\n terminalMessage,\n retryUrl,\n } = controller.state;\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 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) {\n statusRef.current?.focus({ preventScroll: true });\n }\n }, [isSubmitting]);\n\n useEffect(() => {\n if (!(isSubmitting || errors.email || !errors.phone)) {\n phoneRef.current?.focus();\n }\n }, [errors.email, errors.phone, isSubmitting]);\n\n useEffect(() => {\n const paymentIsRequired = displayedTotalCents > 0;\n if (paymentIsRequired && !paymentWasRequiredRef.current) {\n setIsPaymentReady(false);\n setIsBillingAddressReady(false);\n }\n paymentWasRequiredRef.current = paymentIsRequired;\n }, [displayedTotalCents]);\n\n function clearError(field: \"email\" | \"phone\") {\n controller.commands.fieldChanged(false, field !== \"email\");\n setErrors((current) => {\n const next = { ...current };\n delete next[field];\n return next;\n });\n }\n\n function handleFieldValuesChange(nextValues: CheckoutFieldValues) {\n const promoChanged = nextValues.promoCode !== fieldValues.promoCode;\n const serviceFeeChanged =\n nextValues.includeServiceFee !== fieldValues.includeServiceFee;\n controller.commands.fieldChanged(\n promoChanged,\n !(promoChanged || serviceFeeChanged)\n );\n setFieldValues(nextValues);\n setCustomFieldErrors({});\n setTipError(undefined);\n }\n\n async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const internationalPhone = catalog.widget.fields.phone\n ? getInternationalPhone(phone, phoneCountry)\n : \"\";\n const validation = validateContact(\n { email, phone: internationalPhone },\n catalog.widget.fields.phone\n );\n const nextCustomFieldErrors = validateCustomFields(\n 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 controller.commands.reportValidationFailure();\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 const result = await controller.commands.submit({\n addresses: addressesRef.current,\n phone: internationalPhone,\n });\n if (result?.phoneError) {\n setErrors({ phone: result.phoneError });\n }\n }\n\n if (terminalMessage || isRecovering) {\n return (\n <div className=\"lockerverse-payment__actions\">\n <p\n className=\"lockerverse-payment__payment-status\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {isRecovering ? \"Recovering payment…\" : terminalMessage}\n {retryUrl ? (\n <>\n {\" \"}\n <a href={retryUrl} rel=\"noopener noreferrer\" target=\"_blank\">\n Complete payment\n </a>\n </>\n ) : null}\n </p>\n {isUnresolved || isRecovering ? (\n <button\n aria-busy={isRecovering}\n className=\"lockerverse-payment__status-check\"\n disabled={isRecovering}\n onClick={controller.commands.checkPaymentStatus}\n type=\"button\"\n >\n {isRecovering ? \"Checking payment status…\" : \"Check payment status\"}\n </button>\n ) : null}\n </div>\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 <PaymentSummary\n displayedBaseCents={displayedBaseCents}\n displayedTipCents={displayedTipCents}\n displayedTotalCents={displayedTotalCents}\n quote={quote}\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 emailDiscountPercentOff={\n quote.appliedDiscount?.source === \"email_list\"\n ? quote.appliedDiscount.percentageOff\n : undefined\n }\n emailErrorId={emailErrorId}\n emailId={emailId}\n emailRef={emailRef}\n errors={errors}\n onEmailBlur={() => controller.commands.refreshAuthoritativeTotal()}\n onEmailChange={(value) => {\n setEmail(value);\n clearError(\"email\");\n }}\n onPhoneChange={({ value, country }) => {\n setPhone(value);\n setPhoneCountry(country);\n clearError(\"phone\");\n }}\n phone={phone}\n phoneCountry={phoneCountry}\n phoneEnabled={catalog.widget.fields.phone}\n phoneErrorId={phoneErrorId}\n phoneId={phoneId}\n phoneRef={phoneRef}\n />\n <StripeCheckoutFields\n catalog={catalog}\n displayedTotalCents={displayedTotalCents}\n fieldValues={fieldValues}\n isBillingAddressReady={isBillingAddressReady}\n isPaymentReady={isPaymentReady}\n isShippingAddressReady={isShippingAddressReady}\n onAddressChange={(mode, address) => {\n addressesRef.current[mode] = address;\n }}\n onFieldValuesChange={handleFieldValuesChange}\n onStripeLoadError={controller.commands.reportStripeLoadError}\n setIsBillingAddressReady={setIsBillingAddressReady}\n setIsPaymentReady={setIsPaymentReady}\n setIsShippingAddressReady={setIsShippingAddressReady}\n />\n <AdditionalCheckoutFields\n customFields={customFields}\n errors={customFieldErrors}\n fields={catalog.widget.fields}\n idPrefix={idPrefix}\n isPromoApplying={isRefreshingQuote}\n memberIdLabel={catalog.community?.memberIdLabel}\n onApplyPromo={controller.commands.applyPromo}\n onChange={handleFieldValuesChange}\n promoError={promoError}\n values={fieldValues}\n />\n <PaymentAction\n catalog={catalog}\n displayedTotalCents={displayedTotalCents}\n fieldValues={fieldValues}\n isBillingAddressReady={isBillingAddressReady}\n isPaymentReady={isPaymentReady}\n isRequiredShippingReady={isRequiredShippingReady}\n isSubmitting={isSubmitting}\n onFieldValuesChange={handleFieldValuesChange}\n quote={quote}\n />\n </fieldset>\n </div>\n {isSubmitting ? (\n <p\n className=\"lockerverse-payment__sr-only\"\n ref={statusRef}\n role=\"status\"\n tabIndex={-1}\n >\n {displayedTotalCents === 0\n ? \"Completing order…\"\n : \"Processing payment…\"}\n </p>\n ) : null}\n <PaymentErrorMessage message={paymentError} />\n </form>\n );\n}\n\nexport function PaymentSkeleton() {\n return (\n <FormSkeleton\n fieldCount={2}\n label=\"Loading payment…\"\n sectionCount={2}\n showCheckbox\n />\n );\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerverseCheckoutEstimate,\n LockerverseCheckoutItem,\n LockerversePreparedCheckout,\n} from \"@lockerverse/sdk/checkout\";\nimport { estimateLockerverseCheckout } from \"@lockerverse/sdk/checkout\";\nimport { useEffect, useMemo, useReducer, useRef } from \"react\";\nimport type { PaymentUiState } from \"./payment-form-state.ts\";\nimport { parsePaymentSelection } from \"./payment-input.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\ntype SessionState =\n | {\n phase: \"loading\";\n revision: number;\n }\n | {\n failure: string;\n phase: \"error\";\n revision: number;\n }\n | {\n checkoutItems: LockerverseCheckoutItem[];\n displayedQuote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n phase: \"ready\";\n quoteFailure: string | undefined;\n revision: number;\n };\n\ntype SessionAction =\n | {\n type: \"loading\";\n }\n | {\n displayedQuote: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n type: \"ready\";\n }\n | {\n failure: string;\n type: \"error\";\n }\n | { checkout: LockerversePreparedCheckout; type: \"checkout\" }\n | { failure: string; type: \"quote-error\" };\n\nfunction sessionReducer(\n state: SessionState,\n action: SessionAction\n): SessionState {\n switch (action.type) {\n case \"loading\":\n return {\n phase: \"loading\",\n revision: state.revision,\n };\n case \"ready\":\n return createReadySession(action.displayedQuote, state.revision + 1);\n case \"error\":\n return {\n failure: action.failure,\n phase: \"error\",\n revision: state.revision,\n };\n case \"checkout\":\n return state.phase === \"ready\"\n ? {\n ...state,\n displayedQuote: action.checkout,\n quoteFailure: undefined,\n }\n : state;\n case \"quote-error\":\n return state.phase === \"ready\"\n ? {\n ...state,\n quoteFailure: action.failure,\n }\n : state;\n default:\n return state;\n }\n}\n\ntype LoadIdentity = {\n catalog: LockerverseCatalog;\n selectionKey: string;\n};\n\nfunction isSameLoad(\n identity: LoadIdentity | undefined,\n catalog: LockerverseCatalog,\n selectionKey: string\n) {\n return (\n identity?.catalog === catalog && identity.selectionKey === selectionKey\n );\n}\n\nfunction createReadyAction({\n checkout,\n}: {\n checkout: LockerverseCheckoutEstimate | LockerversePreparedCheckout;\n}): Extract<SessionAction, { type: \"ready\" }> {\n return {\n displayedQuote: checkout,\n type: \"ready\",\n };\n}\n\nfunction getLoadFailure<ErrorValue>(error: ErrorValue) {\n return error instanceof Error\n ? error.message\n : \"Lockerverse payment could not load.\";\n}\n\nfunction createReadySession(\n checkout: LockerverseCheckoutEstimate | LockerversePreparedCheckout,\n revision: number\n): SessionState {\n return {\n checkoutItems: [...checkout.items],\n displayedQuote: checkout,\n phase: \"ready\",\n quoteFailure: undefined,\n revision,\n };\n}\n\nfunction estimateCheckout(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n) {\n const includeServiceFee = catalog.widget.fields.serviceFee;\n return estimateLockerverseCheckout(catalog, {\n includeServiceFee,\n selection,\n });\n}\n\nfunction createInitialSession(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n): SessionState {\n try {\n return createReadySession(estimateCheckout(catalog, selection), 1);\n } catch (error) {\n return {\n failure: getLoadFailure(error),\n phase: \"error\",\n revision: 0,\n };\n }\n}\n\nexport function usePaymentCheckout({\n catalog,\n client,\n paymentState,\n selection,\n}: {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n paymentState: PaymentUiState;\n selection: LockerversePaymentProps[\"selection\"];\n}) {\n const parsedSelection = parsePaymentSelection(selection);\n const selectionKey = parsedSelection.success\n ? JSON.stringify(parsedSelection.value)\n : \"invalid-selection\";\n const stableSelection = useMemo(\n () => (parsedSelection.success ? parsedSelection.value : []),\n [parsedSelection.success, selectionKey]\n );\n const [session, dispatch] = useReducer(\n sessionReducer,\n undefined,\n (): SessionState =>\n parsedSelection.success\n ? createInitialSession(catalog, stableSelection)\n : { phase: \"loading\", revision: 0 }\n );\n const loadingRef = useRef<LoadIdentity | undefined>(undefined);\n const quoteRevisionRef = useRef(0);\n const estimatedRef = useRef<LoadIdentity | undefined>(\n session.phase === \"ready\" ? { catalog, selectionKey } : undefined\n );\n const settledRef = useRef<LoadIdentity | undefined>(\n session.phase === \"error\" ? { catalog, selectionKey } : undefined\n );\n const sessionIsLocked =\n paymentState === \"submitting\" ||\n paymentState === \"success\" ||\n paymentState === \"unresolved\";\n useEffect(() => {\n if (!parsedSelection.success) {\n return;\n }\n if (\n sessionIsLocked ||\n isSameLoad(settledRef.current, catalog, selectionKey) ||\n isSameLoad(loadingRef.current, catalog, selectionKey)\n ) {\n return;\n }\n\n let active = true;\n loadingRef.current = { catalog, selectionKey };\n let estimateIsReady = isSameLoad(\n estimatedRef.current,\n catalog,\n selectionKey\n );\n if (!estimateIsReady) {\n dispatch({ type: \"loading\" });\n }\n\n function dispatchWhenActive(action: SessionAction) {\n if (active) {\n dispatch(action);\n }\n }\n\n function settleWhenActive() {\n if (active) {\n loadingRef.current = undefined;\n settledRef.current = { catalog, selectionKey };\n }\n }\n\n let initialQuoteRevision: number | undefined;\n\n function failWhenActive<ErrorValue>(error: ErrorValue) {\n if (!active) {\n return;\n }\n loadingRef.current = undefined;\n settledRef.current = { catalog, selectionKey };\n if (\n estimateIsReady &&\n initialQuoteRevision !== undefined &&\n quoteRevisionRef.current !== initialQuoteRevision\n ) {\n return;\n }\n const failure = getLoadFailure(error);\n if (failure === \"This option is sold out.\") {\n dispatch({ failure, type: \"error\" });\n return;\n }\n if (estimateIsReady) {\n dispatch({ failure, type: \"quote-error\" });\n } else {\n dispatch({\n failure,\n type: \"error\",\n });\n }\n }\n\n async function loadPayment() {\n try {\n initialQuoteRevision = quoteRevisionRef.current;\n const includeServiceFee = catalog.widget.fields.serviceFee;\n if (!estimateIsReady) {\n const estimate = estimateCheckout(catalog, stableSelection);\n estimateIsReady = true;\n estimatedRef.current = { catalog, selectionKey };\n dispatchWhenActive(createReadyAction({ checkout: estimate }));\n }\n const preparedCheckout = await client.calculateTotal({\n catalog,\n includeServiceFee,\n selection: stableSelection,\n });\n settleWhenActive();\n if (quoteRevisionRef.current === initialQuoteRevision) {\n dispatchWhenActive({\n checkout: preparedCheckout,\n type: \"checkout\",\n });\n }\n } catch (error) {\n failWhenActive(error);\n }\n }\n\n loadPayment();\n return () => {\n active = false;\n if (isSameLoad(loadingRef.current, catalog, selectionKey)) {\n loadingRef.current = undefined;\n }\n };\n }, [\n catalog,\n client,\n parsedSelection.success,\n sessionIsLocked,\n selectionKey,\n stableSelection,\n ]);\n\n const loadIsCurrent =\n isSameLoad(estimatedRef.current, catalog, selectionKey) ||\n isSameLoad(settledRef.current, catalog, selectionKey) ||\n isSameLoad(loadingRef.current, catalog, selectionKey);\n const currentSession =\n sessionIsLocked || loadIsCurrent\n ? session\n : ({ phase: \"loading\", revision: session.revision } as const);\n\n return {\n selectionError: parsedSelection.success\n ? undefined\n : parsedSelection.message,\n session: currentSession,\n updateCheckout: (checkout: LockerversePreparedCheckout) => {\n quoteRevisionRef.current += 1;\n dispatch({ checkout, type: \"checkout\" });\n },\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n literal,\n nonEmpty,\n nullable,\n object,\n optional,\n pipe,\n safeParse,\n string,\n trim,\n union,\n} from \"valibot\";\nimport { parsePaymentSelection } from \"./payment-input.ts\";\nimport type {\n LockerversePaymentRecovery,\n LockerversePaymentSelectionItem,\n} from \"./types.ts\";\n\nconst storedRecoverySchema = object({\n recovery: object({\n connectedAccountId: nullable(string()),\n paymentReference: pipe(string(), trim(), nonEmpty()),\n }),\n selectionFingerprint: string(),\n version: union([literal(1), literal(2)]),\n widgetId: optional(string()),\n});\n\nfunction selectionFingerprint(selection: LockerversePaymentSelectionItem[]) {\n const parsed = parsePaymentSelection(selection);\n if (!parsed.success) {\n return null;\n }\n return JSON.stringify(\n parsed.value.map((item) => {\n const slug = item.productSlug.trim();\n if (\"quantity\" in item) {\n return [\"quantity\", slug, item.quantity];\n }\n if (\"amountCents\" in item) {\n return [\"amount\", slug, item.amountCents];\n }\n return [\"product\", slug];\n })\n );\n}\n\nconst mismatchedPaymentMessage =\n \"A previous payment uses different checkout details. Return to its original checkout to check the payment before you pay again.\";\n\ntype RecoveryState = {\n error?: string;\n identity: string;\n recovery: LockerversePaymentRecovery | null;\n};\n\nfunction readRecovery(\n key: string,\n fingerprint: string,\n widgetId: string\n): Omit<RecoveryState, \"identity\"> {\n let saved: string | null;\n try {\n saved = window.sessionStorage.getItem(key);\n } catch {\n // Storage can be blocked. In-page recovery still stays with the form.\n return { recovery: null };\n }\n if (!saved) {\n return { recovery: null };\n }\n try {\n const parsed = safeParse(storedRecoverySchema, JSON.parse(saved));\n if (!parsed.success) {\n throw new Error(\"Invalid recovery record\");\n }\n const value = parsed.output;\n if (\n value.selectionFingerprint !== fingerprint ||\n (value.version === 2 && value.widgetId !== widgetId)\n ) {\n return {\n error: mismatchedPaymentMessage,\n recovery: null,\n };\n }\n return {\n recovery: {\n connectedAccountId: value.recovery.connectedAccountId,\n paymentReference: value.recovery.paymentReference,\n },\n };\n } catch {\n // An unreadable record is not proof that the previous payment failed.\n return {\n error:\n \"The saved payment could not be read. Contact support to check it before you pay again.\",\n recovery: null,\n };\n }\n}\n\n/** Read browser state after hydration, before mounting a payable form. */\nexport function usePaymentRecoveryStorage({\n selection,\n storageKey,\n widgetId,\n}: {\n selection: LockerversePaymentSelectionItem[];\n storageKey: string | undefined;\n widgetId: string;\n}) {\n const fingerprint = selectionFingerprint(selection);\n const identity = JSON.stringify([storageKey, fingerprint, widgetId]);\n const [state, setState] = useState<RecoveryState | null>(null);\n const pendingRef = useRef<RecoveryState | null>(null);\n useEffect(() => {\n if (!storageKey) {\n return;\n }\n const pending = pendingRef.current;\n let restored: Omit<RecoveryState, \"identity\"> = { recovery: null };\n if (pending?.recovery) {\n restored =\n pending.identity === identity\n ? { recovery: pending.recovery }\n : { error: mismatchedPaymentMessage, recovery: null };\n } else if (fingerprint !== null) {\n restored = readRecovery(storageKey, fingerprint, widgetId);\n }\n if (restored.recovery) {\n pendingRef.current = { identity, recovery: restored.recovery };\n }\n setState({ identity, ...restored });\n }, [fingerprint, identity, storageKey, widgetId]);\n\n const remember = useCallback(\n (recovery: LockerversePaymentRecovery | null) => {\n if (!storageKey || fingerprint === null) {\n return;\n }\n pendingRef.current = recovery ? { identity, recovery } : null;\n try {\n if (recovery) {\n window.sessionStorage.setItem(\n storageKey,\n JSON.stringify({\n recovery,\n selectionFingerprint: fingerprint,\n version: 2,\n widgetId,\n })\n );\n } else {\n window.sessionStorage.removeItem(storageKey);\n }\n } catch {\n // Keep recovery in the mounted form if browser storage is unavailable.\n }\n },\n [fingerprint, identity, storageKey, widgetId]\n );\n return {\n error: storageKey && state?.identity === identity ? state.error : undefined,\n ready: !storageKey || state?.identity === identity,\n recovery:\n storageKey && state?.identity === identity ? state.recovery : null,\n remember,\n };\n}\n","import type {\n LockerverseCatalog,\n LockerverseCheckoutClient,\n LockerversePaymentCompletion,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { getAccentContrast, normalizeAccentColor } from \"./accent-contrast.ts\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\nimport {\n defaultLockerverseStripeLoader,\n PaymentSkeleton,\n ReadyPayment,\n} from \"./payment-form.tsx\";\nimport type { PaymentUiState } from \"./payment-form-state.ts\";\nimport type {\n LockerversePaymentProps,\n LockerversePaymentRecovery,\n} from \"./types.ts\";\nimport { usePaymentCheckout } from \"./use-payment-checkout.ts\";\nimport { usePaymentRecoveryStorage } from \"./use-payment-recovery-storage.ts\";\n\ntype PaymentViewProps = Omit<LockerversePaymentProps, \"widget\">;\nconst paymentCadence = {\n annually: \"/year\",\n \"every-six-months\": \" every 6 months\",\n monthly: \"/month\",\n \"one-time\": \"\",\n};\n\nfunction PaymentCatalogHeader({\n branding,\n catalog,\n}: {\n branding: LockerversePaymentProps[\"branding\"] | null;\n catalog: LockerverseCatalog;\n}) {\n return (\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 ? <p>{catalog.widget.description}</p> : null}\n </header>\n );\n}\n\nfunction PaymentCatalogSummary({\n catalog,\n selection,\n}: {\n catalog: LockerverseCatalog;\n selection: LockerversePaymentProps[\"selection\"];\n}) {\n const products = selection?.length\n ? catalog.products.filter((product) =>\n selection.some((item) => item.productSlug === product.slug)\n )\n : catalog.products;\n if (products.length === 0) {\n return null;\n }\n return (\n <div className=\"lockerverse-payment__payment-summary\">\n <h2>Products</h2>\n <div className=\"lockerverse-payment__payment-summary-items\">\n {products.map((product) => {\n const amount =\n product.pricingMode === \"fixed\"\n ? product.amountCents\n : product.minimumAmountCents;\n const cadence = paymentCadence[product.paymentOption];\n return (\n <div\n className=\"lockerverse-payment__payment-summary-row\"\n key={product.id}\n >\n <span>{product.name}</span>\n <strong>\n {amount === null\n ? \"Choose amount\"\n : `${product.pricingMode === \"custom\" ? \"From \" : \"\"}${formatMoney(amount)}${cadence}`}\n </strong>\n </div>\n );\n })}\n </div>\n <p>Base prices. Final total is checked at checkout.</p>\n </div>\n );\n}\n\nfunction getPaymentAppearance(\n style: LockerversePaymentProps[\"style\"],\n branding: LockerversePaymentProps[\"branding\"] | null\n) {\n const accent = normalizeAccentColor(\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const rootStyle: LockerversePaymentProps[\"style\"] = { ...style };\n if (style?.[\"--lockerverse-accent\"] !== undefined || branding?.accentColor) {\n rootStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n rootStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n return { accent, rootStyle };\n}\n\nfunction LoadedPayment({\n catalog,\n client,\n loadError,\n onRetry,\n ...viewProps\n}: PaymentViewProps & {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n loadError?: Error | null;\n onRetry?: () => void;\n}) {\n const {\n branding,\n className,\n completionView,\n recoveryStorageKey: _recoveryStorageKey,\n initialCustomFieldValues,\n metadata,\n onPaymentComplete,\n onPaymentRecoveryChange,\n onPaymentUncertain,\n resumePayment,\n selection,\n style,\n stripeLoader = defaultLockerverseStripeLoader,\n theme = \"dark\",\n ...sectionProps\n } = viewProps;\n const [activeResumePayment, setActiveResumePayment] = useState(resumePayment);\n const appearanceRootRef = useRef<HTMLElement | null>(null);\n const [completion, setCompletion] =\n useState<LockerversePaymentCompletion | null>(null);\n const handlePaymentComplete = useCallback(\n (payment: LockerversePaymentCompletion) => {\n setCompletion(payment);\n notifyHostCallback(onPaymentComplete, payment);\n },\n [onPaymentComplete]\n );\n const [notice, setNotice] = useState<string>();\n const [paymentState, setPaymentState] = useState<PaymentUiState>(\"idle\");\n const paymentStateRevisionRef = useRef<number | undefined>(undefined);\n const { selectionError, session, updateCheckout } = usePaymentCheckout({\n catalog,\n client,\n paymentState,\n selection,\n });\n const readySessionRevision =\n session.phase === \"ready\" ? session.revision : undefined;\n const handlePaymentStateChange = useCallback(\n (state: PaymentUiState) => {\n if (readySessionRevision !== undefined) {\n paymentStateRevisionRef.current = readySessionRevision;\n }\n setPaymentState(state);\n },\n [readySessionRevision]\n );\n const handlePaymentRecoveryChange = useCallback(\n (recovery: LockerversePaymentRecovery | null) =>\n onPaymentRecoveryChange?.(recovery),\n [onPaymentRecoveryChange]\n );\n const handleResumePaymentFailed = useCallback(() => {\n setActiveResumePayment(undefined);\n }, []);\n\n useEffect(() => {\n if (session.phase === \"loading\") {\n setNotice(undefined);\n }\n }, [session.phase]);\n\n useLayoutEffect(() => {\n if (\n session.phase === \"ready\" &&\n paymentStateRevisionRef.current !== session.revision\n ) {\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 effectiveBranding = branding ?? catalog.community;\n const { accent: effectiveAccent, rootStyle } = getPaymentAppearance(\n style,\n effectiveBranding\n );\n\n if (completion && completionView === \"summary\") {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n data-payment-state=\"success\"\n style={rootStyle}\n >\n <div className=\"lockerverse-payment__completion\" role=\"status\">\n <span\n aria-hidden=\"true\"\n className=\"lockerverse-payment__completion-icon\"\n >\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height=\"28\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n width=\"28\"\n >\n <path d=\"m5 12 4 4L19 6\" />\n </svg>\n </span>\n <h1>\n {completion.paymentRequired ? \"Thank you\" : \"Order confirmed\"}\n </h1>\n <p>\n {completion.paymentRequired\n ? \"Your payment has been received.\"\n : \"Your order is confirmed. No payment was required.\"}\n </p>\n </div>\n </section>\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 const sessionIsSoldOut =\n session.phase === \"error\" && session.failure === \"This option is sold out.\";\n\n if (sessionIsSoldOut || paymentState === \"sold_out\") {\n return (\n <section\n {...sectionProps}\n className={rootClassName}\n data-lockerverse-theme={theme}\n role=\"alert\"\n style={rootStyle}\n >\n <h1>Sold out</h1>\n <p>This option is sold out.</p>\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 style={rootStyle}\n >\n <p role=\"alert\">{session.failure}</p>\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 style={rootStyle}\n >\n <PaymentCatalogHeader branding={effectiveBranding} catalog={catalog} />\n {loadError ? (\n <div role=\"alert\">\n <p>{loadError.message}</p>\n <button onClick={onRetry} type=\"button\">\n Retry\n </button>\n </div>\n ) : null}\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 ref={appearanceRootRef}\n style={rootStyle}\n >\n <PaymentCatalogHeader branding={effectiveBranding} catalog={catalog} />\n {loadError ? (\n <div role=\"alert\">\n <p>{loadError.message}</p>\n <button onClick={onRetry} type=\"button\">\n Retry\n </button>\n </div>\n ) : null}\n {notice ? (\n <p className=\"lockerverse-payment__payment-status\" role=\"status\">\n {notice}\n </p>\n ) : null}\n {session.quoteFailure ? (\n <div className=\"lockerverse-payment__payment-status\" role=\"alert\">\n <span>{session.quoteFailure}</span>\n <span> The final total will be checked when you submit.</span>\n </div>\n ) : null}\n <ReadyPayment\n accentColor={effectiveAccent}\n appearanceRoot={appearanceRootRef}\n catalog={catalog}\n checkoutItems={session.checkoutItems}\n client={client}\n initialCustomFieldValues={initialCustomFieldValues}\n key={session.revision}\n metadata={metadata}\n onPaymentComplete={handlePaymentComplete}\n onPaymentRecoveryChange={handlePaymentRecoveryChange}\n onPaymentUncertain={onPaymentUncertain}\n onQuoteChange={(nextQuote, nextNotice) => {\n setNotice(nextNotice);\n updateCheckout(nextQuote);\n }}\n onResumePaymentFailed={handleResumePaymentFailed}\n onStateChange={handlePaymentStateChange}\n quote={session.displayedQuote}\n resumePayment={activeResumePayment}\n stripeLoader={stripeLoader}\n theme={theme}\n visualStyle={rootStyle}\n />\n </section>\n );\n}\n\nfunction PaymentWidgetState({\n children,\n loading = false,\n viewProps,\n}: {\n children: ReactNode;\n loading?: boolean;\n viewProps: PaymentViewProps;\n}) {\n const {\n branding,\n className,\n completionView: _completionView,\n recoveryStorageKey: _recoveryStorageKey,\n initialCustomFieldValues: _initialCustomFieldValues,\n metadata: _metadata,\n onPaymentComplete: _onPaymentComplete,\n onPaymentRecoveryChange: _onPaymentRecoveryChange,\n onPaymentUncertain: _onPaymentUncertain,\n resumePayment: _resumePayment,\n selection: _selection,\n stripeLoader: _stripeLoader,\n style,\n theme = \"dark\",\n ...sectionProps\n } = viewProps;\n const accent = normalizeAccentColor(\n style?.[\"--lockerverse-accent\"] ?? branding?.accentColor ?? \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const rootStyle: LockerversePaymentProps[\"style\"] = { ...style };\n if (style?.[\"--lockerverse-accent\"] !== undefined || branding?.accentColor) {\n rootStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n rootStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n\n return (\n <section\n {...sectionProps}\n {...(loading ? { \"aria-busy\": true, \"aria-label\": \"Payment\" } : {})}\n className={[\"lockerverse-payment\", className].filter(Boolean).join(\" \")}\n data-lockerverse-theme={theme}\n style={rootStyle}\n >\n {children}\n </section>\n );\n}\n\nfunction RecoverablePayment(\n props: PaymentViewProps & {\n catalog: LockerverseCatalog;\n client: LockerverseCheckoutClient;\n loadError?: Error | null;\n onRetry?: () => void;\n }\n) {\n const {\n catalog,\n client: _client,\n loadError: _loadError,\n onRetry: _onRetry,\n ...viewProps\n } = props;\n const {\n onPaymentRecoveryChange,\n recoveryStorageKey,\n resumePayment,\n selection,\n } = viewProps;\n const stored = usePaymentRecoveryStorage({\n selection,\n storageKey: recoveryStorageKey,\n widgetId: catalog.widget.id,\n });\n const handleRecoveryChange = useCallback(\n (recovery: LockerversePaymentRecovery | null) => {\n stored.remember(recovery);\n notifyHostCallback(onPaymentRecoveryChange, recovery);\n },\n [onPaymentRecoveryChange, stored.remember]\n );\n if (!stored.ready || stored.error) {\n return (\n <PaymentWidgetState loading={!stored.ready} viewProps={viewProps}>\n {stored.error ? (\n <p role=\"alert\">{stored.error}</p>\n ) : (\n <PaymentSkeleton />\n )}\n </PaymentWidgetState>\n );\n }\n return (\n <LoadedPayment\n {...props}\n onPaymentRecoveryChange={handleRecoveryChange}\n resumePayment={resumePayment ?? stored.recovery}\n />\n );\n}\n\nexport function LockerversePayment({\n widget,\n ...viewProps\n}: LockerversePaymentProps) {\n if (widget.error && !widget.catalog) {\n return (\n <PaymentWidgetState viewProps={viewProps}>\n <p role=\"alert\">{widget.error.message}</p>\n <button onClick={widget.refresh} type=\"button\">\n Retry\n </button>\n </PaymentWidgetState>\n );\n }\n if (widget.loading) {\n return (\n <PaymentWidgetState loading viewProps={viewProps}>\n {widget.catalog ? (\n <>\n <PaymentCatalogHeader\n branding={viewProps.branding ?? widget.catalog.community}\n catalog={widget.catalog}\n />\n <PaymentCatalogSummary\n catalog={widget.catalog}\n selection={viewProps.selection}\n />\n </>\n ) : null}\n <PaymentSkeleton />\n </PaymentWidgetState>\n );\n }\n if (!widget.catalog) {\n return (\n <PaymentWidgetState loading viewProps={viewProps}>\n <PaymentSkeleton />\n </PaymentWidgetState>\n );\n }\n return (\n <RecoverablePayment\n catalog={widget.catalog}\n client={widget.client}\n loadError={widget.error}\n onRetry={widget.refresh}\n {...viewProps}\n />\n );\n}\n"],"mappings":"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"}
package/dist/styles.css CHANGED
@@ -539,7 +539,8 @@
539
539
  clip: rect(0, 0, 0, 0);
540
540
  }
541
541
 
542
- .lockerverse-payment button[type="submit"] {
542
+ .lockerverse-payment button[type="submit"],
543
+ .lockerverse-payment__status-check {
543
544
  width: 100%;
544
545
  min-height: 48px;
545
546
  padding: 12px;
@@ -558,11 +559,13 @@
558
559
  transform 140ms ease;
559
560
  }
560
561
 
561
- .lockerverse-payment button[type="submit"]:hover {
562
+ .lockerverse-payment button[type="submit"]:hover,
563
+ .lockerverse-payment__status-check:hover {
562
564
  filter: brightness(1.06);
563
565
  }
564
566
 
565
- .lockerverse-payment button[type="submit"]:active {
567
+ .lockerverse-payment button[type="submit"]:active,
568
+ .lockerverse-payment__status-check:active {
566
569
  transform: translateY(1px);
567
570
  }
568
571
 
@@ -1,6 +1,6 @@
1
1
  # Lockerverse auctions guide
2
2
 
3
- Package: @lockerverse/react@0.2.171-dev.1
3
+ Package: @lockerverse/react@0.2.173
4
4
 
5
5
  Generated from this release's maintained documentation. Do not edit this copy.
6
6
 
package/guides/events.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Lockerverse events guide
2
2
 
3
- Package: @lockerverse/react@0.2.171-dev.1
3
+ Package: @lockerverse/react@0.2.173
4
4
 
5
5
  Generated from this release's maintained documentation. Do not edit this copy.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Lockerverse integration guide
2
2
 
3
- Package: @lockerverse/react@0.2.171-dev.1
3
+ Package: @lockerverse/react@0.2.173
4
4
 
5
5
  Generated from this release's maintained documentation. Do not edit this copy.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Lockerverse payment-widgets guide
2
2
 
3
- Package: @lockerverse/react@0.2.171-dev.1
3
+ Package: @lockerverse/react@0.2.173
4
4
 
5
5
  Generated from this release's maintained documentation. Do not edit this copy.
6
6
 
package/guides/signup.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Lockerverse signup guide
2
2
 
3
- Package: @lockerverse/react@0.2.171-dev.1
3
+ Package: @lockerverse/react@0.2.173
4
4
 
5
5
  Generated from this release's maintained documentation. Do not edit this copy.
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lockerverse/react",
3
- "version": "0.2.171-dev.1",
3
+ "version": "0.2.173",
4
4
  "description": "Tree-shakable React payment and signup UI for Lockerverse",
5
5
  "repository": {
6
6
  "type": "git",
@@ -136,7 +136,7 @@
136
136
  "embla-carousel-react": "8.6.0",
137
137
  "lucide-react": "0.536.0",
138
138
  "valibot": "1.4.2",
139
- "@lockerverse/sdk": "0.2.171-dev.1"
139
+ "@lockerverse/sdk": "0.2.173"
140
140
  },
141
141
  "devDependencies": {
142
142
  "@size-limit/file": "13.0.3",