@lockerverse/react 0.2.173 → 0.2.174-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATIONS.md +72 -1
- package/dist/lockerverse-payment.js +1 -1
- package/dist/lockerverse-payment.js.map +1 -1
- package/guides/auctions.md +1 -1
- package/guides/events.md +1 -1
- package/guides/integration.md +1 -1
- package/guides/payment-widgets.md +1 -1
- package/guides/signup.md +1 -1
- package/package.json +2 -2
package/MIGRATIONS.md
CHANGED
|
@@ -36,6 +36,20 @@ 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.174-dev.1 — Match Stripe Elements payment method configuration
|
|
40
|
+
|
|
41
|
+
- **Affected:** Core checkout submission and React payment widgets.
|
|
42
|
+
- **Automatic:** React configures explicit card, Link, and community-enabled bank
|
|
43
|
+
methods in Stripe Elements and marks the confirmation request with
|
|
44
|
+
`paymentMethodConfiguration: "explicit"`. This matches the backend's Stripe
|
|
45
|
+
PaymentIntent configuration.
|
|
46
|
+
- **Required:** deploy the backend that supports this optional marker before
|
|
47
|
+
upgrading React. Keep Core and React matched. Existing Core-only callers omit
|
|
48
|
+
the marker and retain automatic payment methods. Custom Elements integrations
|
|
49
|
+
must send the marker only when they use the explicit method list.
|
|
50
|
+
- **Check:** submit card and bank payments through Stripe Elements in test mode,
|
|
51
|
+
including recurring checkout. Confirm pending recovery and settlement.
|
|
52
|
+
|
|
39
53
|
## 0.2.173 — widget ACH and SDK checkout UI
|
|
40
54
|
|
|
41
55
|
### Bank authorization terms
|
|
@@ -97,7 +111,39 @@ version already matches: a previous upgrade may have missed host adoption steps.
|
|
|
97
111
|
verify a changed selection cannot discard it. Check both paid and free order
|
|
98
112
|
confirmation panels. Do not submit a live transaction for this check.
|
|
99
113
|
|
|
100
|
-
## 0.2.
|
|
114
|
+
## 0.2.172-dev.1 — Check pending payment status
|
|
115
|
+
|
|
116
|
+
- **Affected:** React payment widgets with unresolved payments.
|
|
117
|
+
- **Automatic behavior:** the existing pending-payment screen now offers Check
|
|
118
|
+
payment status. It checks the saved payment reference and cannot submit a new
|
|
119
|
+
payment. The control is disabled while the check runs.
|
|
120
|
+
- **Required host changes:** none. Update Core and React together.
|
|
121
|
+
- **Verification:** complete a test bank payment, return to its pending checkout,
|
|
122
|
+
and check its status. Confirm completion clears recovery storage.
|
|
123
|
+
|
|
124
|
+
## 0.2.171-dev.1 — SDK payment recovery and completion UI
|
|
125
|
+
|
|
126
|
+
- **Affected:** React payment widgets and custom hosts that persist payment recovery.
|
|
127
|
+
- **Optional adoption:** pass `recoveryStorageKey` to `LockerversePayment` to let
|
|
128
|
+
the SDK save and restore the pending payment in session storage. Use a stable
|
|
129
|
+
key scoped to the API environment, community, and widget. Remove the host's
|
|
130
|
+
storage code and recovery-driven component key. Do not combine automatic
|
|
131
|
+
persistence with a second host persistence writer.
|
|
132
|
+
- **Compatibility:** the SDK reads the hosted Next app's existing version 1
|
|
133
|
+
records when the same key is used. It writes version 2 records with widget
|
|
134
|
+
identity. It checks widget and selection identity before recovery and keeps
|
|
135
|
+
an unresolved record if those details differ. Recovery uses the saved connected
|
|
136
|
+
account even if current payment routing has changed. Storage is read after hydration,
|
|
137
|
+
before the payable form mounts. No contact details or payment tokens are saved.
|
|
138
|
+
- **Optional UI adoption:** use `completionView="summary"` for the SDK confirmation
|
|
139
|
+
panel and remove the host's duplicate success panel. Completion callbacks still
|
|
140
|
+
run. The default inline message and explicit `resumePayment` integrations remain
|
|
141
|
+
supported. Auctions and legacy custom checkout forms are unchanged.
|
|
142
|
+
- **Check:** reload a pending checkout and confirm the existing payment is checked;
|
|
143
|
+
verify a changed selection cannot discard it. Check both paid and free order
|
|
144
|
+
confirmation panels. Do not submit a live transaction for this check.
|
|
145
|
+
|
|
146
|
+
## 0.2.169-dev.1 — six-month payment widgets
|
|
101
147
|
|
|
102
148
|
Affected: @lockerverse/sdk checkout and @lockerverse/react payment widgets.
|
|
103
149
|
|
|
@@ -113,6 +159,31 @@ Affected: @lockerverse/sdk checkout and @lockerverse/react payment widgets.
|
|
|
113
159
|
submission. Do not submit a live payment for an integration check.
|
|
114
160
|
|
|
115
161
|
|
|
162
|
+
## 0.2.168-dev.1 — bank authorization terms
|
|
163
|
+
|
|
164
|
+
- **Affected:** React payment widgets with ACH enabled.
|
|
165
|
+
- **Automatic:** Stripe displays its bank authorization terms before payment confirmation.
|
|
166
|
+
- **Adoption:** update the matching SDK/React development pair. No prop changes are required.
|
|
167
|
+
- **Check:** confirm that the bank authorization text is visible when a bank account is selected.
|
|
168
|
+
|
|
169
|
+
## 0.2.167-dev.1 — widget ACH and subscription payment recovery
|
|
170
|
+
|
|
171
|
+
- **Affected:** Core checkout data and React payment widgets.
|
|
172
|
+
- **Automatic:** bank payment availability follows the organization default and
|
|
173
|
+
community override returned by the backend. Missing policy remains disabled.
|
|
174
|
+
Pending payments keep their existing payment reference. A failed subscription
|
|
175
|
+
invoice can return `action_required` with `requiresAction: false` and `retryUrl`;
|
|
176
|
+
React shows a link to pay the same invoice instead of creating a second subscription.
|
|
177
|
+
- **Required for custom payment UI:** preserve the reference for pending and
|
|
178
|
+
action-required results. Handle `retryUrl` by opening that invoice, and recover
|
|
179
|
+
status before permitting a new checkout. Do not treat submission as settlement.
|
|
180
|
+
- **Adoption:** deploy the matching backend policy and recovery contract before
|
|
181
|
+
enabling ACH. Existing React hosts need no component prop changes. Keep Core and
|
|
182
|
+
React versions matched when upgrading. Auction payment methods are unchanged.
|
|
183
|
+
- **Check:** verify disabled/inherited/enabled bank visibility and pending, bank
|
|
184
|
+
verification, invoice retry, success, and terminal failure in Stripe test mode.
|
|
185
|
+
Do not create a live transaction for this check.
|
|
186
|
+
|
|
116
187
|
## 0.2.166 — single dropdown arrow
|
|
117
188
|
|
|
118
189
|
- **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 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};
|
|
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,c.paymentMethodConfiguration=`explicit`),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,mode:N===`one-time`?`payment`:`subscription`,paymentMethodTypes:t.community?.widgetAchEnabled?[`card`,`link`,`us_bank_account`]:[`card`,`link`],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 | 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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"}
|
|
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 request.paymentMethodConfiguration = \"explicit\";\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 mode: paymentOption === \"one-time\" ? \"payment\" : \"subscription\",\n paymentMethodTypes: catalog.community?.widgetAchEnabled\n ? [\"card\", \"link\", \"us_bank_account\"]\n : [\"card\", \"link\"],\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/guides/auctions.md
CHANGED
package/guides/events.md
CHANGED
package/guides/integration.md
CHANGED
package/guides/signup.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lockerverse/react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.174-dev.1",
|
|
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.
|
|
139
|
+
"@lockerverse/sdk": "0.2.174-dev.1"
|
|
140
140
|
},
|
|
141
141
|
"devDependencies": {
|
|
142
142
|
"@size-limit/file": "13.0.3",
|