@lockerverse/react 0.2.90 → 0.2.92
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/README.md +7 -1
- package/dist/donate-launcher.d.ts +2 -1
- package/dist/host-callback.js +1 -1
- package/dist/host-callback.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/lockerverse-donate-launcher.d.ts.map +1 -1
- package/dist/lockerverse-donate-launcher.js +1 -1
- package/dist/lockerverse-donate-launcher.js.map +1 -1
- package/dist/lockerverse-payment.js +1 -1
- package/dist/lockerverse-payment.js.map +1 -1
- package/dist/payment-form.d.ts.map +1 -1
- package/dist/signup.css +59 -0
- package/dist/signup.d.ts.map +1 -1
- package/dist/signup.js +1 -1
- package/dist/signup.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ npm install @stripe/react-stripe-js @stripe/stripe-js
|
|
|
19
19
|
```tsx
|
|
20
20
|
import {
|
|
21
21
|
LockerversePayment,
|
|
22
|
+
type LockerversePaymentCompletion,
|
|
22
23
|
type LockerversePaymentSelectionItem,
|
|
23
24
|
} from "@lockerverse/react/payment";
|
|
24
25
|
import "@lockerverse/react/payment.css";
|
|
@@ -32,8 +33,10 @@ export function Checkout() {
|
|
|
32
33
|
return (
|
|
33
34
|
<LockerversePayment
|
|
34
35
|
metadata={{ source: "community-site" }}
|
|
35
|
-
onPaymentComplete={(payment) => {
|
|
36
|
+
onPaymentComplete={(payment: LockerversePaymentCompletion) => {
|
|
36
37
|
console.info("Payment complete", payment.checkoutId);
|
|
38
|
+
console.info("Customer", payment.email);
|
|
39
|
+
console.info("Authoritative items", payment.lineItems);
|
|
37
40
|
}}
|
|
38
41
|
onPaymentUncertain={({ paymentReference, reason }) => {
|
|
39
42
|
console.info("Payment needs status recovery", paymentReference, reason);
|
|
@@ -283,6 +286,9 @@ The package keeps React, React DOM, and Stripe's React libraries as peer depende
|
|
|
283
286
|
|
|
284
287
|
`onPaymentComplete` runs only after Lockerverse reports `success`. A successful payment is terminal, even if the host callback throws.
|
|
285
288
|
|
|
289
|
+
A direct completion includes the normalized customer `email` and authoritative
|
|
290
|
+
`lineItems`. A completion recovered after reload has `null` for both fields.
|
|
291
|
+
|
|
286
292
|
If the authoritative total, discount, currency, line items, or connected Stripe account changes, the component displays the new quote before creating a Stripe token. The customer must explicitly submit again.
|
|
287
293
|
|
|
288
294
|
An authoritative `failed` result is retryable and the next submit receives a new payment reference. `pending`, unresolved `action_required`, and failed same-reference recovery stay locked so the customer cannot accidentally create a second payment. The optional `onPaymentUncertain` callback receives the retained `paymentReference` and one of these reasons:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as LockerverseTheme, t as LockerverseStyle } from "./theme.js";
|
|
2
2
|
import { n as LockerverseDonateLauncherProps, t as LockerverseDonateLauncherPosition } from "./types.js";
|
|
3
3
|
import { t as LockerverseDonateLauncher } from "./lockerverse-donate-launcher.js";
|
|
4
|
-
|
|
4
|
+
import { LockerversePaymentCompletion } from "@lockerverse/sdk/checkout";
|
|
5
|
+
export { LockerverseDonateLauncher, type LockerverseDonateLauncherPosition, type LockerverseDonateLauncherProps, type LockerversePaymentCompletion, type LockerverseStyle, type LockerverseTheme };
|
package/dist/host-callback.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{array as e,email as t,minLength as n,nonEmpty as r,pipe as i,regex as a,safeParse as o,string as s,transform as c,trim as l}from"valibot";import{jsx as u,jsxs as d}from"react/jsx-runtime";const f=/^#([\da-f]{3}|[\da-f]{6})$/i,p=/^([\da-f]{3}|[\da-f]{6})$/i;function m(e){let t=e.trim();return p.test(t)?`#${t}`:t}function h(e){let t=f.exec(m(e));if(!t)return;let[,n]=t;if(!n)return;let r=n.length===3?Array.from(n,e=>`${e}${e}`).join(``):n;return[0,2,4].map(e=>Number.parseInt(r.slice(e,e+2),16))}function g([e,t,n]){let[r=0,i=0,a=0]=[e,t,n].map((e=0)=>{let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4});return .2126*r+.7152*i+.0722*a}function _(e){let t=h(e);if(!t)return;let n=g(t);return(n+.05)/.05>=1.05/(n+.05)?`#000`:`#fff`}function v(e){return e.type===`checkbox`?!1:e.type===`checkboxes`||e.type===`multi_select`?[]:``}function y(e){let t={};for(let n of e)t[n.id]=v(n);return t}function b(e){let t=o(s(),e);return t.success?t.output:``}function x(e,t){return e.map(e=>{let n=t[e.id];return e.type===`checkbox`?{fieldId:e.id,value:n===!0}:e.type===`checkboxes`||e.type===`multi_select`?{fieldId:e.id,value:Array.isArray(n)?n:[]}:{fieldId:e.id,value:b(n)}})}function S(t,a){let c={};for(let u of t){if(!u.required)continue;let t=`${u.label} is required.`,d=a[u.id];if(u.type===`checkbox`){d!==!0&&(c[u.id]=t);continue}let f=u.type===`checkboxes`||u.type===`multi_select`?o(i(e(s()),n(1,t)),d??[]):o(i(s(),l(),r(t)),b(d));f.success||(c[u.id]=f.issues[0]?.message??t)}return c}function C({choiceClassName:e,errorClassName:t,errors:n,fields:r,idPrefix:i,onChange:a,values:o}){return r.map(r=>u(w,{choiceClassName:e,error:n[r.id],errorClassName:t,field:r,idPrefix:i,onChange:e=>a({...o,[r.id]:e}),value:o[r.id]},r.id))}function w(e){let{field:t,idPrefix:n}=e,r=`${n}-custom-${t.id}`,i=`${r}-error`,a={...e,controlId:r,errorId:i};switch(t.type){case`checkbox`:return u(T,{...a,field:t});case`text`:case`textarea`:return u(D,{...a,field:t});case`select`:case`multi_select`:return u(O,{...a,field:t});case`radio`:case`checkboxes`:return u(k,{...a,field:t});default:return null}}function T({choiceClassName:e,controlId:t,error:n,errorClassName:r,errorId:i,field:a,onChange:o,value:s}){return d(`label`,{className:e,htmlFor:t,children:[u(`input`,{"aria-describedby":n?i:void 0,"aria-invalid":n?`true`:void 0,checked:s===!0,id:t,name:`custom:${a.id}`,onChange:e=>o(e.currentTarget.checked),required:a.required,type:`checkbox`}),u(`span`,{children:a.label}),u(E,{className:r,error:n,id:i})]})}function E({className:e,error:t,id:n}){return t?u(`span`,{className:e,id:n,role:`alert`,children:t}):null}function D({controlId:e,error:t,errorClassName:n,errorId:r,field:i,onChange:a,value:o}){let s={"aria-describedby":t?r:void 0,"aria-invalid":t?`true`:void 0,id:e,name:`custom:${i.id}`,onChange:e=>a(e.currentTarget.value),required:i.required,value:b(o)};return d(`label`,{htmlFor:e,children:[u(`span`,{children:i.label}),i.type===`textarea`?u(`textarea`,{...s}):u(`input`,{...s}),u(E,{className:n,error:t,id:r})]})}function O({controlId:e,error:t,errorClassName:n,errorId:r,field:i,onChange:a,value:o}){return d(`label`,{htmlFor:e,children:[u(`span`,{children:i.label}),d(`select`,{"aria-describedby":t?r:void 0,"aria-invalid":t?`true`:void 0,id:e,multiple:i.type===`multi_select`,name:`custom:${i.id}`,onChange:e=>a(i.type===`multi_select`?[...e.currentTarget.selectedOptions].map(e=>e.value):e.currentTarget.value),required:i.required,value:o===!0||o===!1?``:o??(i.type===`multi_select`?[]:``),children:[i.type===`select`?u(`option`,{value:``,children:`Select…`}):null,i.options.map(e=>u(`option`,{value:e.id,children:e.label},e.id))]}),u(E,{className:n,error:t,id:r})]})}function k({choiceClassName:e,controlId:t,error:n,errorClassName:r,errorId:i,field:a,onChange:o,value:s}){let c=Array.isArray(s)?s:[];return d(`fieldset`,{"aria-describedby":n?i:void 0,"aria-invalid":n?`true`:void 0,children:[u(`legend`,{children:a.label}),a.options.map((n,r)=>d(`label`,{className:e,children:[u(`input`,{checked:Array.isArray(s)?s.includes(n.id):s===n.id,id:`${t}-${r}`,name:`custom:${a.id}`,onChange:e=>{if(a.type===`radio`){o(n.id);return}o(e.currentTarget.checked?[...c,n.id]:c.filter(e=>e!==n.id))},required:a.required&&a.type===`radio`,type:a.type===`radio`?`radio`:`checkbox`,value:n.id}),u(`span`,{children:n.label})]},n.id)),u(E,{className:r,error:n,id:i})]})}function A({fieldCount:e,label:t,sectionCount:n=0,showCheckbox:r=!1}){return d(`div`,{className:`lockerverse-form-skeleton__loading`,children:[u(`span`,{className:`lockerverse-form-skeleton__sr-only`,role:`status`,children:t}),d(`div`,{"aria-hidden":`true`,className:`lockerverse-form-skeleton`,children:[d(`div`,{className:`lockerverse-form-skeleton__branding`,children:[u(`span`,{className:`lockerverse-form-skeleton__avatar`}),u(`span`,{className:`lockerverse-form-skeleton__community`})]}),u(`div`,{className:`lockerverse-form-skeleton__fields`,children:Array.from({length:e},(e,t)=>d(`div`,{className:`lockerverse-form-skeleton__field`,children:[u(`span`,{className:`lockerverse-form-skeleton__label`}),u(`span`,{className:`lockerverse-form-skeleton__input`})]},t))}),Array.from({length:n},(e,t)=>d(`div`,{className:`lockerverse-form-skeleton__section`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-label`}),d(`div`,{className:`lockerverse-form-skeleton__section-content`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-full`}),d(`div`,{className:`lockerverse-form-skeleton__section-grid`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-half`}),u(`span`,{className:`lockerverse-form-skeleton__section-half`})]})]})]},t)),d(`div`,{className:`lockerverse-form-skeleton__actions`,children:[r?u(`span`,{className:`lockerverse-form-skeleton__check-line`}):null,u(`span`,{className:`lockerverse-form-skeleton__button`})]})]})]})}const j=`Enter a valid email address.`,M=`Enter a valid phone number.`,
|
|
1
|
+
import{array as e,email as t,minLength as n,nonEmpty as r,pipe as i,regex as a,safeParse as o,string as s,transform as c,trim as l}from"valibot";import{jsx as u,jsxs as d}from"react/jsx-runtime";const f=/^#([\da-f]{3}|[\da-f]{6})$/i,p=/^([\da-f]{3}|[\da-f]{6})$/i;function m(e){let t=e.trim();return p.test(t)?`#${t}`:t}function h(e){let t=f.exec(m(e));if(!t)return;let[,n]=t;if(!n)return;let r=n.length===3?Array.from(n,e=>`${e}${e}`).join(``):n;return[0,2,4].map(e=>Number.parseInt(r.slice(e,e+2),16))}function g([e,t,n]){let[r=0,i=0,a=0]=[e,t,n].map((e=0)=>{let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4});return .2126*r+.7152*i+.0722*a}function _(e){let t=h(e);if(!t)return;let n=g(t);return(n+.05)/.05>=1.05/(n+.05)?`#000`:`#fff`}function v(e){return e.type===`checkbox`?!1:e.type===`checkboxes`||e.type===`multi_select`?[]:``}function y(e){let t={};for(let n of e)t[n.id]=v(n);return t}function b(e){let t=o(s(),e);return t.success?t.output:``}function x(e,t){return e.map(e=>{let n=t[e.id];return e.type===`checkbox`?{fieldId:e.id,value:n===!0}:e.type===`checkboxes`||e.type===`multi_select`?{fieldId:e.id,value:Array.isArray(n)?n:[]}:{fieldId:e.id,value:b(n)}})}function S(t,a){let c={};for(let u of t){if(!u.required)continue;let t=`${u.label} is required.`,d=a[u.id];if(u.type===`checkbox`){d!==!0&&(c[u.id]=t);continue}let f=u.type===`checkboxes`||u.type===`multi_select`?o(i(e(s()),n(1,t)),d??[]):o(i(s(),l(),r(t)),b(d));f.success||(c[u.id]=f.issues[0]?.message??t)}return c}function C({choiceClassName:e,errorClassName:t,errors:n,fields:r,idPrefix:i,onChange:a,values:o}){return r.map(r=>u(w,{choiceClassName:e,error:n[r.id],errorClassName:t,field:r,idPrefix:i,onChange:e=>a({...o,[r.id]:e}),value:o[r.id]},r.id))}function w(e){let{field:t,idPrefix:n}=e,r=`${n}-custom-${t.id}`,i=`${r}-error`,a={...e,controlId:r,errorId:i};switch(t.type){case`checkbox`:return u(T,{...a,field:t});case`text`:case`textarea`:return u(D,{...a,field:t});case`select`:case`multi_select`:return u(O,{...a,field:t});case`radio`:case`checkboxes`:return u(k,{...a,field:t});default:return null}}function T({choiceClassName:e,controlId:t,error:n,errorClassName:r,errorId:i,field:a,onChange:o,value:s}){return d(`label`,{className:e,htmlFor:t,children:[u(`input`,{"aria-describedby":n?i:void 0,"aria-invalid":n?`true`:void 0,checked:s===!0,id:t,name:`custom:${a.id}`,onChange:e=>o(e.currentTarget.checked),required:a.required,type:`checkbox`}),u(`span`,{children:a.label}),u(E,{className:r,error:n,id:i})]})}function E({className:e,error:t,id:n}){return t?u(`span`,{className:e,id:n,role:`alert`,children:t}):null}function D({controlId:e,error:t,errorClassName:n,errorId:r,field:i,onChange:a,value:o}){let s={"aria-describedby":t?r:void 0,"aria-invalid":t?`true`:void 0,id:e,name:`custom:${i.id}`,onChange:e=>a(e.currentTarget.value),required:i.required,value:b(o)};return d(`label`,{htmlFor:e,children:[u(`span`,{children:i.label}),i.type===`textarea`?u(`textarea`,{...s}):u(`input`,{...s}),u(E,{className:n,error:t,id:r})]})}function O({controlId:e,error:t,errorClassName:n,errorId:r,field:i,onChange:a,value:o}){return d(`label`,{htmlFor:e,children:[u(`span`,{children:i.label}),d(`select`,{"aria-describedby":t?r:void 0,"aria-invalid":t?`true`:void 0,id:e,multiple:i.type===`multi_select`,name:`custom:${i.id}`,onChange:e=>a(i.type===`multi_select`?[...e.currentTarget.selectedOptions].map(e=>e.value):e.currentTarget.value),required:i.required,value:o===!0||o===!1?``:o??(i.type===`multi_select`?[]:``),children:[i.type===`select`?u(`option`,{value:``,children:`Select…`}):null,i.options.map(e=>u(`option`,{value:e.id,children:e.label},e.id))]}),u(E,{className:n,error:t,id:r})]})}function k({choiceClassName:e,controlId:t,error:n,errorClassName:r,errorId:i,field:a,onChange:o,value:s}){let c=Array.isArray(s)?s:[];return d(`fieldset`,{"aria-describedby":n?i:void 0,"aria-invalid":n?`true`:void 0,children:[u(`legend`,{children:a.label}),a.options.map((n,r)=>d(`label`,{className:e,children:[u(`input`,{checked:Array.isArray(s)?s.includes(n.id):s===n.id,id:`${t}-${r}`,name:`custom:${a.id}`,onChange:e=>{if(a.type===`radio`){o(n.id);return}o(e.currentTarget.checked?[...c,n.id]:c.filter(e=>e!==n.id))},required:a.required&&a.type===`radio`,type:a.type===`radio`?`radio`:`checkbox`,value:n.id}),u(`span`,{children:n.label})]},n.id)),u(E,{className:r,error:n,id:i})]})}function A({fieldCount:e,label:t,sectionCount:n=0,showCheckbox:r=!1}){return d(`div`,{className:`lockerverse-form-skeleton__loading`,children:[u(`span`,{className:`lockerverse-form-skeleton__sr-only`,role:`status`,children:t}),d(`div`,{"aria-hidden":`true`,className:`lockerverse-form-skeleton`,children:[d(`div`,{className:`lockerverse-form-skeleton__branding`,children:[u(`span`,{className:`lockerverse-form-skeleton__avatar`}),u(`span`,{className:`lockerverse-form-skeleton__community`})]}),u(`div`,{className:`lockerverse-form-skeleton__fields`,children:Array.from({length:e},(e,t)=>d(`div`,{className:`lockerverse-form-skeleton__field`,children:[u(`span`,{className:`lockerverse-form-skeleton__label`}),u(`span`,{className:`lockerverse-form-skeleton__input`})]},t))}),Array.from({length:n},(e,t)=>d(`div`,{className:`lockerverse-form-skeleton__section`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-label`}),d(`div`,{className:`lockerverse-form-skeleton__section-content`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-full`}),d(`div`,{className:`lockerverse-form-skeleton__section-grid`,children:[u(`span`,{className:`lockerverse-form-skeleton__section-half`}),u(`span`,{className:`lockerverse-form-skeleton__section-half`})]})]})]},t)),d(`div`,{className:`lockerverse-form-skeleton__actions`,children:[r?u(`span`,{className:`lockerverse-form-skeleton__check-line`}):null,u(`span`,{className:`lockerverse-form-skeleton__button`})]})]})]})}const j=`Enter a valid email address.`,M=`Phone is required.`,N=`Enter a valid phone number.`,P=/^(?:$|[^\s@]+@[^\s@]+\.[^\s@]+)$/,F=/^\+[1-9]\d{6,14}$/,I=/^(?:$|\+[1-9]\d{6,14})$/;function L(e){return e.trim().replace(/[().\s-]/g,``)}const R=i(s(),l(),a(P,j)),z=i(s(),l(),r(`Email is required.`),t(j)),B=i(s(),l(),c(L),a(I,N)),V=i(s(),l(),r(M),c(L),a(F,N)),H=[{callingCode:`+1`,label:`🇺🇸 +1`,value:`US`},{callingCode:`+52`,label:`🇲🇽 +52`,value:`MX`},{callingCode:`+380`,label:`🇺🇦 +380`,value:`UA`},{callingCode:`+48`,label:`🇵🇱 +48`,value:`PL`},{callingCode:`+1`,label:`🇨🇦 +1`,value:`CA`},{callingCode:`+49`,label:`🇩🇪 +49`,value:`DE`},{callingCode:`+44`,label:`🇬🇧 +44`,value:`GB`},{callingCode:`+46`,label:`🇸🇪 +46`,value:`SE`},{callingCode:`+358`,label:`🇫🇮 +358`,value:`FI`},{callingCode:`+1`,label:`🇵🇷 +1`,value:`PR`}];function U(e){if(e===`PAYMENT_WIDGET_PHONE_REQUIRED`||e===`SIGN_UP_WIDGET_PHONE_REQUIRED`)return M;if(e===`PAYMENT_WIDGET_PHONE_INVALID`||e===`SIGN_UP_WIDGET_PHONE_INVALID`)return N}function W(e){return H.find(t=>t.value===e)??H[0]}function G(e,t){let n=`${t}${t}`,r=e;for(;r.startsWith(n);)r=`${t}${r.slice(n.length)}`;return r}function K(e,t){let n=L(e);if(!n)return``;let r=W(t),i=G(n,r.callingCode);return i.startsWith(`+`)?i:`${r.callingCode}${i}`}function q(e,t){if(e)try{Promise.resolve(e(t)).catch(()=>void 0)}catch{}}export{L as a,z as c,C as d,x as f,m as g,_ as h,U as i,V as l,S as m,H as n,R as o,y as p,K as r,B as s,q as t,A as u};
|
|
2
2
|
//# sourceMappingURL=host-callback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-callback.js","names":[],"sources":["../src/accent-contrast.ts","../src/custom-fields.tsx","../src/form-skeleton.tsx","../src/contact-validation.ts","../src/host-callback.ts"],"sourcesContent":["const HEX_COLOR = /^#([\\da-f]{3}|[\\da-f]{6})$/i;\nconst UNPREFIXED_HEX_COLOR = /^([\\da-f]{3}|[\\da-f]{6})$/i;\n\nexport function normalizeAccentColor(color: string) {\n const trimmedColor = color.trim();\n return UNPREFIXED_HEX_COLOR.test(trimmedColor)\n ? `#${trimmedColor}`\n : trimmedColor;\n}\n\nfunction parseHexColor(color: string) {\n const match = HEX_COLOR.exec(normalizeAccentColor(color));\n if (!match) {\n return;\n }\n const [, value] = match;\n if (!value) {\n return;\n }\n const expanded =\n value.length === 3\n ? Array.from(value, (character) => `${character}${character}`).join(\"\")\n : value;\n return [0, 2, 4].map((offset) =>\n Number.parseInt(expanded.slice(offset, offset + 2), 16)\n );\n}\n\nfunction relativeLuminance([red, green, blue]: number[]) {\n const [linearRed = 0, linearGreen = 0, linearBlue = 0] = [\n red,\n green,\n blue,\n ].map((channel = 0) => {\n const normalized = channel / 255;\n return normalized <= 0.040_45\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * linearRed + 0.7152 * linearGreen + 0.0722 * linearBlue;\n}\n\nexport function getAccentContrast(color: string) {\n const parsed = parseHexColor(color);\n if (!parsed) {\n return;\n }\n const luminance = relativeLuminance(parsed);\n const blackContrast = (luminance + 0.05) / 0.05;\n const whiteContrast = 1.05 / (luminance + 0.05);\n return blackContrast >= whiteContrast ? \"#000\" : \"#fff\";\n}\n","import type {\n LockerverseBooleanCustomField,\n LockerverseCustomField,\n LockerverseCustomFieldAnswer,\n LockerverseMultiOptionCustomField,\n LockerverseSingleOptionCustomField,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n array,\n minLength,\n nonEmpty,\n pipe,\n safeParse,\n string,\n trim,\n} from \"valibot\";\n\nexport type CustomFieldValues = Record<string, boolean | string | string[]>;\n\nfunction createCustomFieldValue(field: LockerverseCustomField) {\n if (field.type === \"checkbox\") {\n return false;\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return [];\n }\n return \"\";\n}\n\nexport function createCustomFieldValues(fields: LockerverseCustomField[]) {\n const values: CustomFieldValues = {};\n for (const field of fields) {\n values[field.id] = createCustomFieldValue(field);\n }\n return values;\n}\n\nfunction getStringValue(value: CustomFieldValues[string] | undefined) {\n const result = safeParse(string(), value);\n return result.success ? result.output : \"\";\n}\n\nexport function buildCustomFieldAnswers(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n): LockerverseCustomFieldAnswer[] {\n return fields.map((field): LockerverseCustomFieldAnswer => {\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n return { fieldId: field.id, value: value === true };\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return { fieldId: field.id, value: Array.isArray(value) ? value : [] };\n }\n return {\n fieldId: field.id,\n value: getStringValue(value),\n };\n });\n}\n\nexport function validateCustomFields(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n) {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (!field.required) {\n continue;\n }\n const message = `${field.label} is required.`;\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n if (value !== true) {\n errors[field.id] = message;\n }\n continue;\n }\n const result =\n field.type === \"checkboxes\" || field.type === \"multi_select\"\n ? safeParse(pipe(array(string()), minLength(1, message)), value ?? [])\n : safeParse(\n pipe(string(), trim(), nonEmpty(message)),\n getStringValue(value)\n );\n if (!result.success) {\n errors[field.id] = result.issues[0]?.message ?? message;\n }\n }\n return errors;\n}\n\nexport function CustomFields({\n choiceClassName,\n errorClassName,\n errors,\n fields,\n idPrefix,\n onChange,\n values,\n}: {\n choiceClassName: string;\n errorClassName: string;\n errors: Record<string, string>;\n fields: LockerverseCustomField[];\n idPrefix: string;\n onChange: (values: CustomFieldValues) => void;\n values: CustomFieldValues;\n}) {\n return fields.map((field) => (\n <CustomField\n choiceClassName={choiceClassName}\n error={errors[field.id]}\n errorClassName={errorClassName}\n field={field}\n idPrefix={idPrefix}\n key={field.id}\n onChange={(value) => onChange({ ...values, [field.id]: value })}\n value={values[field.id]}\n />\n ));\n}\n\ntype CustomFieldProps = {\n choiceClassName: string;\n error: string | undefined;\n errorClassName: string;\n field: LockerverseCustomField;\n idPrefix: string;\n onChange: (value: boolean | string | string[]) => void;\n value: boolean | string | string[] | undefined;\n};\n\nfunction CustomField(props: CustomFieldProps) {\n const { field, idPrefix } = props;\n const controlId = `${idPrefix}-custom-${field.id}`;\n const errorId = `${controlId}-error`;\n const controlProps = { ...props, controlId, errorId };\n switch (field.type) {\n case \"checkbox\":\n return <BooleanCustomField {...controlProps} field={field} />;\n case \"text\":\n case \"textarea\":\n return <TextCustomField {...controlProps} field={field} />;\n case \"select\":\n case \"multi_select\":\n return <SelectCustomField {...controlProps} field={field} />;\n case \"radio\":\n case \"checkboxes\":\n return <ChoiceCustomField {...controlProps} field={field} />;\n default:\n return null;\n }\n}\n\nfunction BooleanCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & { field: LockerverseBooleanCustomField }) {\n return (\n <label className={choiceClassName} htmlFor={controlId}>\n <input\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n checked={value === true}\n id={controlId}\n name={`custom:${field.id}`}\n onChange={(event) => onChange(event.currentTarget.checked)}\n required={field.required}\n type=\"checkbox\"\n />\n <span>{field.label}</span>\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\ntype ControlProps = CustomFieldProps & {\n controlId: string;\n errorId: string;\n};\n\nfunction FieldError({\n className,\n error,\n id,\n}: {\n className: string;\n error: string | undefined;\n id: string;\n}) {\n return error ? (\n <span className={className} id={id} role=\"alert\">\n {error}\n </span>\n ) : null;\n}\n\nfunction TextCustomField({\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: Extract<LockerverseCustomField, { type: \"text\" | \"textarea\" }>;\n}) {\n const commonProps = {\n \"aria-describedby\": error ? errorId : undefined,\n \"aria-invalid\": error ? (\"true\" as const) : undefined,\n id: controlId,\n name: `custom:${field.id}`,\n onChange: (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => onChange(event.currentTarget.value),\n required: field.required,\n value: getStringValue(value),\n };\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n {field.type === \"textarea\" ? (\n <textarea {...commonProps} />\n ) : (\n <input {...commonProps} />\n )}\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\nfunction SelectCustomField({\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n <select\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n id={controlId}\n multiple={field.type === \"multi_select\"}\n name={`custom:${field.id}`}\n onChange={(event) =>\n onChange(\n field.type === \"multi_select\"\n ? [...event.currentTarget.selectedOptions].map(\n (option) => option.value\n )\n : event.currentTarget.value\n )\n }\n required={field.required}\n value={\n value === true || value === false\n ? \"\"\n : (value ?? (field.type === \"multi_select\" ? [] : \"\"))\n }\n >\n {field.type === \"select\" ? <option value=\"\">Select…</option> : null}\n {field.options.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\nfunction ChoiceCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n const selectedValues = Array.isArray(value) ? value : [];\n return (\n <fieldset\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n >\n <legend>{field.label}</legend>\n {field.options.map((option, index) => (\n <label className={choiceClassName} key={option.id}>\n <input\n checked={\n Array.isArray(value)\n ? value.includes(option.id)\n : value === option.id\n }\n id={`${controlId}-${index}`}\n name={`custom:${field.id}`}\n onChange={(event) => {\n if (field.type === \"radio\") {\n onChange(option.id);\n return;\n }\n onChange(\n event.currentTarget.checked\n ? [...selectedValues, option.id]\n : selectedValues.filter((id) => id !== option.id)\n );\n }}\n required={field.required && field.type === \"radio\"}\n type={field.type === \"radio\" ? \"radio\" : \"checkbox\"}\n value={option.id}\n />\n <span>{option.label}</span>\n </label>\n ))}\n <FieldError className={errorClassName} error={error} id={errorId} />\n </fieldset>\n );\n}\n","export function FormSkeleton({\n fieldCount,\n label,\n sectionCount = 0,\n showCheckbox = false,\n}: {\n fieldCount: number;\n label: string;\n sectionCount?: number;\n showCheckbox?: boolean;\n}) {\n return (\n <div className=\"lockerverse-form-skeleton__loading\">\n <span className=\"lockerverse-form-skeleton__sr-only\" role=\"status\">\n {label}\n </span>\n <div aria-hidden=\"true\" className=\"lockerverse-form-skeleton\">\n <div className=\"lockerverse-form-skeleton__branding\">\n <span className=\"lockerverse-form-skeleton__avatar\" />\n <span className=\"lockerverse-form-skeleton__community\" />\n </div>\n <div className=\"lockerverse-form-skeleton__fields\">\n {Array.from({ length: fieldCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__field\" key={index}>\n <span className=\"lockerverse-form-skeleton__label\" />\n <span className=\"lockerverse-form-skeleton__input\" />\n </div>\n ))}\n </div>\n {Array.from({ length: sectionCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__section\" key={index}>\n <span className=\"lockerverse-form-skeleton__section-label\" />\n <div className=\"lockerverse-form-skeleton__section-content\">\n <span className=\"lockerverse-form-skeleton__section-full\" />\n <div className=\"lockerverse-form-skeleton__section-grid\">\n <span className=\"lockerverse-form-skeleton__section-half\" />\n <span className=\"lockerverse-form-skeleton__section-half\" />\n </div>\n </div>\n </div>\n ))}\n <div className=\"lockerverse-form-skeleton__actions\">\n {showCheckbox ? (\n <span className=\"lockerverse-form-skeleton__check-line\" />\n ) : null}\n <span className=\"lockerverse-form-skeleton__button\" />\n </div>\n </div>\n </div>\n );\n}\n","import { email, nonEmpty, pipe, regex, string, transform, trim } from \"valibot\";\n\nexport const EMAIL_REQUIRED_MESSAGE = \"Email is required.\";\nexport const EMAIL_INVALID_MESSAGE = \"Enter a valid email address.\";\nexport const PHONE_REQUIRED_MESSAGE = \"Phone is required.\";\nexport const PHONE_INVALID_MESSAGE = \"Enter a valid phone number.\";\n\nconst OPTIONAL_EMAIL_PATTERN = /^(?:$|[^\\s@]+@[^\\s@]+\\.[^\\s@]+)$/;\nconst INTERNATIONAL_PHONE_PATTERN = /^\\+[1-9]\\d{6,14}$/;\nconst OPTIONAL_INTERNATIONAL_PHONE_PATTERN = /^(?:$|\\+[1-9]\\d{6,14})$/;\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport const optionalEmailSchema = pipe(\n string(),\n trim(),\n regex(OPTIONAL_EMAIL_PATTERN, EMAIL_INVALID_MESSAGE)\n);\n\nexport const requiredEmailSchema = pipe(\n string(),\n trim(),\n nonEmpty(EMAIL_REQUIRED_MESSAGE),\n email(EMAIL_INVALID_MESSAGE)\n);\n\nexport const optionalPhoneSchema = pipe(\n string(),\n trim(),\n transform(normalizePhone),\n regex(OPTIONAL_INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n\nexport const requiredPhoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(PHONE_REQUIRED_MESSAGE),\n transform(normalizePhone),\n regex(INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n","export function notifyHostCallback<Value>(\n callback: ((value: Value) => void) | undefined,\n value: Value\n) {\n if (!callback) {\n return;\n }\n try {\n Promise.resolve(callback(value)).catch(() => undefined);\n } catch {\n // Host callback failures must not change completed SDK state.\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"host-callback.js","names":[],"sources":["../src/accent-contrast.ts","../src/custom-fields.tsx","../src/form-skeleton.tsx","../src/contact-validation.ts","../src/phone.ts","../src/host-callback.ts"],"sourcesContent":["const HEX_COLOR = /^#([\\da-f]{3}|[\\da-f]{6})$/i;\nconst UNPREFIXED_HEX_COLOR = /^([\\da-f]{3}|[\\da-f]{6})$/i;\n\nexport function normalizeAccentColor(color: string) {\n const trimmedColor = color.trim();\n return UNPREFIXED_HEX_COLOR.test(trimmedColor)\n ? `#${trimmedColor}`\n : trimmedColor;\n}\n\nfunction parseHexColor(color: string) {\n const match = HEX_COLOR.exec(normalizeAccentColor(color));\n if (!match) {\n return;\n }\n const [, value] = match;\n if (!value) {\n return;\n }\n const expanded =\n value.length === 3\n ? Array.from(value, (character) => `${character}${character}`).join(\"\")\n : value;\n return [0, 2, 4].map((offset) =>\n Number.parseInt(expanded.slice(offset, offset + 2), 16)\n );\n}\n\nfunction relativeLuminance([red, green, blue]: number[]) {\n const [linearRed = 0, linearGreen = 0, linearBlue = 0] = [\n red,\n green,\n blue,\n ].map((channel = 0) => {\n const normalized = channel / 255;\n return normalized <= 0.040_45\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * linearRed + 0.7152 * linearGreen + 0.0722 * linearBlue;\n}\n\nexport function getAccentContrast(color: string) {\n const parsed = parseHexColor(color);\n if (!parsed) {\n return;\n }\n const luminance = relativeLuminance(parsed);\n const blackContrast = (luminance + 0.05) / 0.05;\n const whiteContrast = 1.05 / (luminance + 0.05);\n return blackContrast >= whiteContrast ? \"#000\" : \"#fff\";\n}\n","import type {\n LockerverseBooleanCustomField,\n LockerverseCustomField,\n LockerverseCustomFieldAnswer,\n LockerverseMultiOptionCustomField,\n LockerverseSingleOptionCustomField,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n array,\n minLength,\n nonEmpty,\n pipe,\n safeParse,\n string,\n trim,\n} from \"valibot\";\n\nexport type CustomFieldValues = Record<string, boolean | string | string[]>;\n\nfunction createCustomFieldValue(field: LockerverseCustomField) {\n if (field.type === \"checkbox\") {\n return false;\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return [];\n }\n return \"\";\n}\n\nexport function createCustomFieldValues(fields: LockerverseCustomField[]) {\n const values: CustomFieldValues = {};\n for (const field of fields) {\n values[field.id] = createCustomFieldValue(field);\n }\n return values;\n}\n\nfunction getStringValue(value: CustomFieldValues[string] | undefined) {\n const result = safeParse(string(), value);\n return result.success ? result.output : \"\";\n}\n\nexport function buildCustomFieldAnswers(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n): LockerverseCustomFieldAnswer[] {\n return fields.map((field): LockerverseCustomFieldAnswer => {\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n return { fieldId: field.id, value: value === true };\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return { fieldId: field.id, value: Array.isArray(value) ? value : [] };\n }\n return {\n fieldId: field.id,\n value: getStringValue(value),\n };\n });\n}\n\nexport function validateCustomFields(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n) {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (!field.required) {\n continue;\n }\n const message = `${field.label} is required.`;\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n if (value !== true) {\n errors[field.id] = message;\n }\n continue;\n }\n const result =\n field.type === \"checkboxes\" || field.type === \"multi_select\"\n ? safeParse(pipe(array(string()), minLength(1, message)), value ?? [])\n : safeParse(\n pipe(string(), trim(), nonEmpty(message)),\n getStringValue(value)\n );\n if (!result.success) {\n errors[field.id] = result.issues[0]?.message ?? message;\n }\n }\n return errors;\n}\n\nexport function CustomFields({\n choiceClassName,\n errorClassName,\n errors,\n fields,\n idPrefix,\n onChange,\n values,\n}: {\n choiceClassName: string;\n errorClassName: string;\n errors: Record<string, string>;\n fields: LockerverseCustomField[];\n idPrefix: string;\n onChange: (values: CustomFieldValues) => void;\n values: CustomFieldValues;\n}) {\n return fields.map((field) => (\n <CustomField\n choiceClassName={choiceClassName}\n error={errors[field.id]}\n errorClassName={errorClassName}\n field={field}\n idPrefix={idPrefix}\n key={field.id}\n onChange={(value) => onChange({ ...values, [field.id]: value })}\n value={values[field.id]}\n />\n ));\n}\n\ntype CustomFieldProps = {\n choiceClassName: string;\n error: string | undefined;\n errorClassName: string;\n field: LockerverseCustomField;\n idPrefix: string;\n onChange: (value: boolean | string | string[]) => void;\n value: boolean | string | string[] | undefined;\n};\n\nfunction CustomField(props: CustomFieldProps) {\n const { field, idPrefix } = props;\n const controlId = `${idPrefix}-custom-${field.id}`;\n const errorId = `${controlId}-error`;\n const controlProps = { ...props, controlId, errorId };\n switch (field.type) {\n case \"checkbox\":\n return <BooleanCustomField {...controlProps} field={field} />;\n case \"text\":\n case \"textarea\":\n return <TextCustomField {...controlProps} field={field} />;\n case \"select\":\n case \"multi_select\":\n return <SelectCustomField {...controlProps} field={field} />;\n case \"radio\":\n case \"checkboxes\":\n return <ChoiceCustomField {...controlProps} field={field} />;\n default:\n return null;\n }\n}\n\nfunction BooleanCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & { field: LockerverseBooleanCustomField }) {\n return (\n <label className={choiceClassName} htmlFor={controlId}>\n <input\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n checked={value === true}\n id={controlId}\n name={`custom:${field.id}`}\n onChange={(event) => onChange(event.currentTarget.checked)}\n required={field.required}\n type=\"checkbox\"\n />\n <span>{field.label}</span>\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\ntype ControlProps = CustomFieldProps & {\n controlId: string;\n errorId: string;\n};\n\nfunction FieldError({\n className,\n error,\n id,\n}: {\n className: string;\n error: string | undefined;\n id: string;\n}) {\n return error ? (\n <span className={className} id={id} role=\"alert\">\n {error}\n </span>\n ) : null;\n}\n\nfunction TextCustomField({\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: Extract<LockerverseCustomField, { type: \"text\" | \"textarea\" }>;\n}) {\n const commonProps = {\n \"aria-describedby\": error ? errorId : undefined,\n \"aria-invalid\": error ? (\"true\" as const) : undefined,\n id: controlId,\n name: `custom:${field.id}`,\n onChange: (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => onChange(event.currentTarget.value),\n required: field.required,\n value: getStringValue(value),\n };\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n {field.type === \"textarea\" ? (\n <textarea {...commonProps} />\n ) : (\n <input {...commonProps} />\n )}\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\nfunction SelectCustomField({\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <label htmlFor={controlId}>\n <span>{field.label}</span>\n <select\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n id={controlId}\n multiple={field.type === \"multi_select\"}\n name={`custom:${field.id}`}\n onChange={(event) =>\n onChange(\n field.type === \"multi_select\"\n ? [...event.currentTarget.selectedOptions].map(\n (option) => option.value\n )\n : event.currentTarget.value\n )\n }\n required={field.required}\n value={\n value === true || value === false\n ? \"\"\n : (value ?? (field.type === \"multi_select\" ? [] : \"\"))\n }\n >\n {field.type === \"select\" ? <option value=\"\">Select…</option> : null}\n {field.options.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\nfunction ChoiceCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n const selectedValues = Array.isArray(value) ? value : [];\n return (\n <fieldset\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n >\n <legend>{field.label}</legend>\n {field.options.map((option, index) => (\n <label className={choiceClassName} key={option.id}>\n <input\n checked={\n Array.isArray(value)\n ? value.includes(option.id)\n : value === option.id\n }\n id={`${controlId}-${index}`}\n name={`custom:${field.id}`}\n onChange={(event) => {\n if (field.type === \"radio\") {\n onChange(option.id);\n return;\n }\n onChange(\n event.currentTarget.checked\n ? [...selectedValues, option.id]\n : selectedValues.filter((id) => id !== option.id)\n );\n }}\n required={field.required && field.type === \"radio\"}\n type={field.type === \"radio\" ? \"radio\" : \"checkbox\"}\n value={option.id}\n />\n <span>{option.label}</span>\n </label>\n ))}\n <FieldError className={errorClassName} error={error} id={errorId} />\n </fieldset>\n );\n}\n","export function FormSkeleton({\n fieldCount,\n label,\n sectionCount = 0,\n showCheckbox = false,\n}: {\n fieldCount: number;\n label: string;\n sectionCount?: number;\n showCheckbox?: boolean;\n}) {\n return (\n <div className=\"lockerverse-form-skeleton__loading\">\n <span className=\"lockerverse-form-skeleton__sr-only\" role=\"status\">\n {label}\n </span>\n <div aria-hidden=\"true\" className=\"lockerverse-form-skeleton\">\n <div className=\"lockerverse-form-skeleton__branding\">\n <span className=\"lockerverse-form-skeleton__avatar\" />\n <span className=\"lockerverse-form-skeleton__community\" />\n </div>\n <div className=\"lockerverse-form-skeleton__fields\">\n {Array.from({ length: fieldCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__field\" key={index}>\n <span className=\"lockerverse-form-skeleton__label\" />\n <span className=\"lockerverse-form-skeleton__input\" />\n </div>\n ))}\n </div>\n {Array.from({ length: sectionCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__section\" key={index}>\n <span className=\"lockerverse-form-skeleton__section-label\" />\n <div className=\"lockerverse-form-skeleton__section-content\">\n <span className=\"lockerverse-form-skeleton__section-full\" />\n <div className=\"lockerverse-form-skeleton__section-grid\">\n <span className=\"lockerverse-form-skeleton__section-half\" />\n <span className=\"lockerverse-form-skeleton__section-half\" />\n </div>\n </div>\n </div>\n ))}\n <div className=\"lockerverse-form-skeleton__actions\">\n {showCheckbox ? (\n <span className=\"lockerverse-form-skeleton__check-line\" />\n ) : null}\n <span className=\"lockerverse-form-skeleton__button\" />\n </div>\n </div>\n </div>\n );\n}\n","import { email, nonEmpty, pipe, regex, string, transform, trim } from \"valibot\";\n\nexport const EMAIL_REQUIRED_MESSAGE = \"Email is required.\";\nexport const EMAIL_INVALID_MESSAGE = \"Enter a valid email address.\";\nexport const PHONE_REQUIRED_MESSAGE = \"Phone is required.\";\nexport const PHONE_INVALID_MESSAGE = \"Enter a valid phone number.\";\n\nconst OPTIONAL_EMAIL_PATTERN = /^(?:$|[^\\s@]+@[^\\s@]+\\.[^\\s@]+)$/;\nconst INTERNATIONAL_PHONE_PATTERN = /^\\+[1-9]\\d{6,14}$/;\nconst OPTIONAL_INTERNATIONAL_PHONE_PATTERN = /^(?:$|\\+[1-9]\\d{6,14})$/;\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport const optionalEmailSchema = pipe(\n string(),\n trim(),\n regex(OPTIONAL_EMAIL_PATTERN, EMAIL_INVALID_MESSAGE)\n);\n\nexport const requiredEmailSchema = pipe(\n string(),\n trim(),\n nonEmpty(EMAIL_REQUIRED_MESSAGE),\n email(EMAIL_INVALID_MESSAGE)\n);\n\nexport const optionalPhoneSchema = pipe(\n string(),\n trim(),\n transform(normalizePhone),\n regex(OPTIONAL_INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n\nexport const requiredPhoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(PHONE_REQUIRED_MESSAGE),\n transform(normalizePhone),\n regex(INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n","import {\n normalizePhone,\n PHONE_INVALID_MESSAGE,\n PHONE_REQUIRED_MESSAGE,\n} from \"./contact-validation.ts\";\n\nexport const PHONE_COUNTRIES = [\n {\n callingCode: \"+1\",\n label: \"🇺🇸 +1\",\n value: \"US\",\n },\n {\n callingCode: \"+52\",\n label: \"🇲🇽 +52\",\n value: \"MX\",\n },\n {\n callingCode: \"+380\",\n label: \"🇺🇦 +380\",\n value: \"UA\",\n },\n {\n callingCode: \"+48\",\n label: \"🇵🇱 +48\",\n value: \"PL\",\n },\n {\n callingCode: \"+1\",\n label: \"🇨🇦 +1\",\n value: \"CA\",\n },\n {\n callingCode: \"+49\",\n label: \"🇩🇪 +49\",\n value: \"DE\",\n },\n {\n callingCode: \"+44\",\n label: \"🇬🇧 +44\",\n value: \"GB\",\n },\n {\n callingCode: \"+46\",\n label: \"🇸🇪 +46\",\n value: \"SE\",\n },\n {\n callingCode: \"+358\",\n label: \"🇫🇮 +358\",\n value: \"FI\",\n },\n {\n callingCode: \"+1\",\n label: \"🇵🇷 +1\",\n value: \"PR\",\n },\n] as const;\n\nexport type PhoneCountry = (typeof PHONE_COUNTRIES)[number][\"value\"];\n\nexport function getPhoneServerError(serverCode: string | undefined) {\n if (\n serverCode === \"PAYMENT_WIDGET_PHONE_REQUIRED\" ||\n serverCode === \"SIGN_UP_WIDGET_PHONE_REQUIRED\"\n ) {\n return PHONE_REQUIRED_MESSAGE;\n }\n if (\n serverCode === \"PAYMENT_WIDGET_PHONE_INVALID\" ||\n serverCode === \"SIGN_UP_WIDGET_PHONE_INVALID\"\n ) {\n return PHONE_INVALID_MESSAGE;\n }\n}\n\nfunction getPhoneCountry(country: string) {\n return (\n PHONE_COUNTRIES.find((option) => option.value === country) ??\n PHONE_COUNTRIES[0]\n );\n}\n\nfunction removeRepeatedCallingCode(phone: string, callingCode: string) {\n const repeatedCallingCode = `${callingCode}${callingCode}`;\n let normalizedPhone = phone;\n while (normalizedPhone.startsWith(repeatedCallingCode)) {\n normalizedPhone = `${callingCode}${normalizedPhone.slice(repeatedCallingCode.length)}`;\n }\n return normalizedPhone;\n}\n\nexport function getInternationalPhone(phone: string, country: string) {\n const normalizedPhone = normalizePhone(phone);\n if (!normalizedPhone) {\n return \"\";\n }\n\n const selectedCountry = getPhoneCountry(country);\n const phoneWithOneCallingCode = removeRepeatedCallingCode(\n normalizedPhone,\n selectedCountry.callingCode\n );\n\n return phoneWithOneCallingCode.startsWith(\"+\")\n ? phoneWithOneCallingCode\n : `${selectedCountry.callingCode}${phoneWithOneCallingCode}`;\n}\n","export function notifyHostCallback<Value>(\n callback: ((value: Value) => void) | undefined,\n value: Value\n) {\n if (!callback) {\n return;\n }\n try {\n Promise.resolve(callback(value)).catch(() => undefined);\n } catch {\n // Host callback failures must not change completed SDK state.\n }\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ import { n as useLockerverseWidget, t as UseLockerverseWidgetResult } from "./us
|
|
|
3
3
|
import { a as LockerversePaymentRecovery, c as LockerversePaymentTheme, i as LockerversePaymentProps, l as LockerversePaymentUncertain, n as LockerverseDonateLauncherProps, o as LockerversePaymentSelectionItem, r as LockerversePaymentBranding, s as LockerversePaymentStyle, t as LockerverseDonateLauncherPosition, u as LockerverseStripeLoader } from "./types.js";
|
|
4
4
|
import { t as LockerverseDonateLauncher } from "./lockerverse-donate-launcher.js";
|
|
5
5
|
import { n as LockerversePayment, t as preloadLockerversePayment } from "./payment-form.js";
|
|
6
|
-
|
|
6
|
+
import { LockerversePaymentCompletion } from "@lockerverse/sdk/checkout";
|
|
7
|
+
export { LockerverseDonateLauncher, type LockerverseDonateLauncherPosition, type LockerverseDonateLauncherProps, LockerversePayment, type LockerversePaymentBranding, type LockerversePaymentCompletion, type LockerversePaymentProps, type LockerversePaymentRecovery, type LockerversePaymentSelectionItem, type LockerversePaymentStyle, type LockerversePaymentTheme, type LockerversePaymentUncertain, type LockerverseStripeLoader, type LockerverseStyle, type LockerverseTheme, type UseLockerverseWidgetResult, preloadLockerversePayment, useLockerverseWidget };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockerverse-donate-launcher.d.ts","names":[],"sources":["../src/lockerverse-donate-launcher.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"lockerverse-donate-launcher.d.ts","names":[],"sources":["../src/lockerverse-donate-launcher.tsx"],"mappings":";;iBAwjBgB,4BACd,aACA,UACA,WACG,gBACF,iDAA8B,IAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{g as e,h as t}from"./host-callback.js";import{n,t as r}from"./lockerverse-payment.js";import{Dialog as i}from"@base-ui/react/dialog";import{getLockerverseMinimumCustomAmountCents as a}from"@lockerverse/sdk/checkout";import{createElement as o,useState as s}from"react";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";const d=new Intl.NumberFormat(`en-US`,{currency:`USD`,style:`currency`}),f=/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/,p=[1e3,2500,5e3,1e4];function m(e){if(!f.test(e))return null;let t=Math.round(Number(e)*100);return Number.isSafeInteger(t)&&t>0?t:null}function h(e,t){let n=``;return t===`monthly`&&(n=`/month`),t===`annually`&&(n=`/year`),`${d.format(e/100)}${n}`}function g({customAmounts:e,product:t,quantities:n,recurringProductId:r,setCustomAmounts:i,setQuantities:o,setRecurringProductId:s}){let c=n[t.id]??0;if(t.pricingMode===`fixed`&&t.paymentOption===`one-time`){let e=t.minimumQuantity??1,n=Math.min(t.maximumQuantity??1/0,t.inventoryQuantity??1/0);return u(`span`,{className:`lockerverse-launcher__quantity`,children:[l(`button`,{"aria-label":`Decrease ${t.name} quantity`,disabled:c===0,onClick:()=>{s(null),o(n=>{let r=n[t.id]??0;return{...n,[t.id]:r<=e?0:r-1}})},type:`button`,children:`−`}),l(`output`,{"aria-label":`${t.name} quantity`,children:c}),l(`button`,{"aria-label":`Increase ${t.name} quantity`,disabled:n<e||c>=n,onClick:()=>{s(null),o(n=>{let r=n[t.id]??0;return{...n,[t.id]:r===0?e:r+1}})},type:`button`,children:`+`})]})}return t.pricingMode===`custom`&&t.paymentOption===`one-time`?u(`span`,{className:`lockerverse-launcher__custom-amount`,children:[l(`span`,{"aria-hidden":`true`,children:`$`}),l(`input`,{"aria-label":`${t.name} amount`,min:a(t)/100,name:`amount-${t.slug}`,onChange:e=>{s(null),i(n=>({...n,[t.id]:e.target.value}))},placeholder:`0.00`,step:`0.01`,type:`number`,value:e[t.id]??``}),t.minimumAmountCents===null?null:u(`small`,{children:[`Minimum `,d.format(t.minimumAmountCents/100)]})]}):l(`button`,{"aria-label":`Select ${t.name}`,"aria-pressed":r===t.id,className:`lockerverse-launcher__select`,onClick:()=>{o({}),i({}),s(e=>e===t.id?null:t.id)},type:`button`,children:`Select`})}function _({variant:e=`default`,...t}){let{customAmounts:n,product:r,quantities:i,recurringProductId:o}=t,s=m(n[r.id]??``),c=o===r.id||r.paymentOption===`one-time`&&(r.pricingMode===`fixed`&&(i[r.id]??0)>0||r.pricingMode===`custom`&&s!==null&&s>=a(r));return u(`article`,{className:`lockerverse-launcher__product lockerverse-launcher__product--${e}`,"data-selected":c||void 0,children:[u(`span`,{className:`lockerverse-launcher__product-copy`,children:[l(`strong`,{className:`lockerverse-launcher__product-name`,children:r.name}),r.description?l(`small`,{children:r.description}):null,r.amountCents===null?null:l(`span`,{className:`lockerverse-launcher__product-price`,children:h(r.amountCents,r.paymentOption)})]}),l(g,{...t})]})}function v({customAmounts:e,product:t,setCustomAmounts:n,setRecurringProductId:r}){let i=e[t.id]??``,o=m(i),s=p.filter(e=>e>=a(t)),c=s.includes(o??0),f=e=>{r(null),n(n=>({...n,[t.id]:e}))};return l(`div`,{className:`lockerverse-launcher__donation-option`,children:u(`fieldset`,{className:`lockerverse-launcher__donation-choices`,children:[u(`legend`,{className:`lockerverse-launcher__sr-only`,children:[t.name,` amount`]}),l(`button`,{"aria-pressed":i===``,onClick:()=>f(``),type:`button`,children:`No thanks`}),s.map(e=>l(`button`,{"aria-pressed":o===e,onClick:()=>f(String(e/100)),type:`button`,children:d.format(e/100).replace(`.00`,``)},e)),l(`label`,{className:`lockerverse-launcher__donation-other`,"data-selected":i!==``&&!c||void 0,children:l(`input`,{"aria-label":`${t.name} amount`,min:a(t)/100,name:`amount-${t.slug}`,onChange:e=>f(e.target.value),placeholder:`Other $`,step:`0.01`,type:`number`,value:c?``:i})})]})})}function y({products:e,variant:t=`default`,...n}){return l(`div`,{className:`lockerverse-launcher__product-list`,children:e.map(e=>t===`donation`?o(v,{...n,key:e.id,product:e}):o(_,{...n,key:e.id,product:e,variant:t}))})}function b(e,t){let n=0,r=0;for(let i of t){let t=e.products.find(e=>e.slug===i.productSlug);if(t){if(`quantity`in i){n+=i.quantity,r+=(t.amountCents??0)*i.quantity;continue}n+=1,r+=`amountCents`in i?i.amountCents:t.amountCents??0}}return{amountCents:r,itemCount:n}}function x(){return l(`div`,{"aria-label":`Loading donation options`,className:`lockerverse-launcher__loading`,role:`status`,children:[0,1,2].map(e=>l(`span`,{"aria-hidden":`true`,className:`lockerverse-launcher__loading-row`},e))})}function S(e,t,n,r){if(r){let t=e.products.find(e=>e.id===r&&e.paymentOption!==`one-time`);return t?[{productSlug:t.slug}]:[]}return e.products.flatMap(e=>{let r=t[e.id]??0;if(e.pricingMode===`fixed`&&e.paymentOption===`one-time`&&r>0)return[{productSlug:e.slug,quantity:r}];let i=m(n[e.id]??``);return e.pricingMode===`custom`&&e.paymentOption===`one-time`&&i!==null&&i>=a(e)?[{amountCents:i,productSlug:e.slug}]:[]})}function C({catalog:e,onContinue:t,...n}){let r=S(e,n.quantities,n.customAmounts,n.recurringProductId),i=b(e,r),a=e.products.filter(e=>e.paymentOption===`one-time`&&e.pricingMode===`custom`),o=e.products.filter(e=>!a.includes(e));return u(`form`,{className:`lockerverse-launcher__products`,onSubmit:e=>{e.preventDefault(),r.length>0&&t(r)},children:[o.length>0?l(`section`,{className:`lockerverse-launcher__section`,children:l(y,{...n,products:o})}):null,a.length>0?u(`section`,{className:`lockerverse-launcher__donation`,children:[u(`header`,{className:`lockerverse-launcher__section-header`,children:[l(`h3`,{children:`Add a donation`}),l(`p`,{children:`Choose an amount to add to this order.`})]}),l(y,{...n,products:a,variant:`donation`})]}):null,e.products.length>0?u(`footer`,{className:`lockerverse-launcher__footer`,children:[u(`p`,{"aria-live":`polite`,className:`lockerverse-launcher__summary`,children:[l(`span`,{children:i.itemCount===0?`No items selected`:`${i.itemCount} ${i.itemCount===1?`item`:`items`} selected`}),i.itemCount===0?null:l(`strong`,{children:d.format(i.amountCents/100)})]}),l(`button`,{className:`lockerverse-launcher__continue`,disabled:r.length===0,type:`submit`,children:`Continue`})]}):null]})}function w({onEdit:e,paymentProps:t,selection:n,style:i,widget:a}){return u(`div`,{className:`lockerverse-launcher__checkout`,children:[l(`header`,{className:`lockerverse-launcher__checkout-toolbar`,children:l(`button`,{className:`lockerverse-launcher__back`,onClick:e,type:`button`,children:`Edit order`})}),l(r,{...t,selection:n,style:i,widget:a})]})}function T({catalog:e,checkout:t}){return t?u(c,{children:[l(i.Title,{className:`lockerverse-launcher__sr-only`,children:`Checkout`}),l(i.Description,{className:`lockerverse-launcher__sr-only`,children:`Review the order and complete payment.`})]}):e?u(`header`,{className:`lockerverse-launcher__header`,children:[e.community?u(`div`,{className:`lockerverse-launcher__brand`,children:[e.community.imageUrl?l(`img`,{alt:`${e.community.name} logo`,height:`28`,src:e.community.imageUrl,width:`28`}):null,l(`span`,{children:e.community.name})]}):null,l(i.Title,{className:`lockerverse-launcher__title`,children:e.widget.title??e.widget.name}),l(i.Description,{className:`lockerverse-launcher__description`,children:e.widget.description??`Choose your options, then continue to checkout.`})]}):u(`header`,{className:`lockerverse-launcher__header`,children:[l(i.Title,{className:`lockerverse-launcher__title`,children:`Donate`}),l(i.Description,{className:`lockerverse-launcher__description`,children:`Choose your options, then continue to checkout.`})]})}function E({buttonLabel:r=`Donate`,position:a=`inline`,widget:o,...c}){let[d,f]=s(null),[p,m]=s({}),[h,g]=s({}),[_,v]=s(null),{catalog:y,error:b,loading:S}=o,E=e(c.style?.[`--lockerverse-accent`]??y?.community?.accentColor??`#38d77a`),D=t(E),O={...c.style};(c.style?.[`--lockerverse-accent`]!==void 0||y?.community?.accentColor)&&(O[`--lockerverse-accent`]=E),D&&c.style?.[`--lockerverse-accent-contrast`]===void 0&&(O[`--lockerverse-accent-contrast`]=D);let k;return k=S?l(x,{}):b?u(`div`,{role:`alert`,children:[l(`p`,{children:`Unable to load donation options.`}),l(`button`,{onClick:o.refresh,type:`button`,children:`Retry`})]}):y?l(C,{catalog:y,customAmounts:p,onContinue:f,quantities:h,recurringProductId:_,setCustomAmounts:m,setQuantities:g,setRecurringProductId:v}):l(x,{}),!(S||b)&&d&&y&&(k=l(w,{onEdit:()=>f(null),paymentProps:c,selection:d,style:O,widget:o})),u(i.Root,{onOpenChange:e=>{e&&y&&c.stripeLoader===void 0&&requestAnimationFrame(()=>{n(y)})},children:[l(i.Trigger,{className:`lockerverse-launcher lockerverse-launcher--${a}`,"data-lockerverse-theme":c.theme??`dark`,style:O,children:r}),u(i.Portal,{children:[l(i.Backdrop,{className:`lockerverse-launcher__backdrop`}),l(i.Viewport,{className:`lockerverse-launcher__viewport`,children:u(i.Popup,{className:`lockerverse-launcher__dialog`,"data-lockerverse-theme":c.theme??`dark`,style:O,children:[l(T,{catalog:y,checkout:d!==null}),l(i.Close,{"aria-label":`Close donation dialog`,className:`lockerverse-launcher__close`,children:l(`span`,{"aria-hidden":`true`,children:`×`})}),k]})})]})]})}export{E as t};
|
|
2
2
|
//# sourceMappingURL=lockerverse-donate-launcher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockerverse-donate-launcher.js","names":[],"sources":["../src/lockerverse-donate-launcher.tsx"],"sourcesContent":["import { Dialog } from \"@base-ui/react/dialog\";\nimport {\n getLockerverseMinimumCustomAmountCents,\n type LockerverseCatalog,\n type LockerverseProduct,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n useState,\n} from \"react\";\nimport { getAccentContrast, normalizeAccentColor } from \"./accent-contrast.ts\";\nimport { LockerversePayment } from \"./lockerverse-payment.tsx\";\nimport { preloadLockerversePayment } from \"./payment-form.tsx\";\nimport type {\n LockerverseDonateLauncherProps,\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n LockerversePaymentStyle,\n} from \"./types.ts\";\nimport type { UseLockerverseWidgetResult } from \"./use-lockerverse-widget.ts\";\n\nconst usd = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n});\nconst decimalAmountPattern = /^(?:0|[1-9]\\d*)(?:\\.\\d{1,2})?$/;\nconst suggestedDonationAmountsCents = [1000, 2500, 5000, 10_000];\n\nfunction parseAmountCents(value: string) {\n if (!decimalAmountPattern.test(value)) {\n return null;\n }\n const amountCents = Math.round(Number(value) * 100);\n return Number.isSafeInteger(amountCents) && amountCents > 0\n ? amountCents\n : null;\n}\n\nfunction formatProductPrice(\n amountCents: number,\n paymentOption: \"one-time\" | \"monthly\" | \"annually\"\n) {\n let cadence = \"\";\n if (paymentOption === \"monthly\") {\n cadence = \"/month\";\n }\n if (paymentOption === \"annually\") {\n cadence = \"/year\";\n }\n return `${usd.format(amountCents / 100)}${cadence}`;\n}\n\ntype LauncherProductControlProps = {\n customAmounts: Record<string, string>;\n product: LockerverseProduct;\n quantities: Record<string, number>;\n recurringProductId: string | null;\n setCustomAmounts: Dispatch<SetStateAction<Record<string, string>>>;\n setQuantities: Dispatch<SetStateAction<Record<string, number>>>;\n setRecurringProductId: Dispatch<SetStateAction<string | null>>;\n};\n\nfunction LauncherProductControl({\n customAmounts,\n product,\n quantities,\n recurringProductId,\n setCustomAmounts,\n setQuantities,\n setRecurringProductId,\n}: LauncherProductControlProps) {\n const quantity = quantities[product.id] ?? 0;\n if (product.pricingMode === \"fixed\" && product.paymentOption === \"one-time\") {\n const maximum = Math.min(\n product.maximumQuantity ?? Number.POSITIVE_INFINITY,\n product.inventoryQuantity ?? Number.POSITIVE_INFINITY\n );\n return (\n <span className=\"lockerverse-launcher__quantity\">\n <button\n aria-label={`Decrease ${product.name} quantity`}\n disabled={quantity === 0}\n onClick={() => {\n setRecurringProductId(null);\n setQuantities((current) => {\n const currentQuantity = current[product.id] ?? 0;\n const minimum = product.minimumQuantity ?? 1;\n return {\n ...current,\n [product.id]:\n currentQuantity <= minimum ? 0 : currentQuantity - 1,\n };\n });\n }}\n type=\"button\"\n >\n −\n </button>\n <output aria-label={`${product.name} quantity`}>{quantity}</output>\n <button\n aria-label={`Increase ${product.name} quantity`}\n disabled={quantity >= maximum}\n onClick={() => {\n setRecurringProductId(null);\n setQuantities((current) => {\n const currentQuantity = current[product.id] ?? 0;\n return {\n ...current,\n [product.id]:\n currentQuantity === 0\n ? (product.minimumQuantity ?? 1)\n : currentQuantity + 1,\n };\n });\n }}\n type=\"button\"\n >\n +\n </button>\n </span>\n );\n }\n\n if (\n product.pricingMode === \"custom\" &&\n product.paymentOption === \"one-time\"\n ) {\n return (\n <span className=\"lockerverse-launcher__custom-amount\">\n <span aria-hidden=\"true\">$</span>\n <input\n aria-label={`${product.name} amount`}\n min={getLockerverseMinimumCustomAmountCents(product) / 100}\n name={`amount-${product.slug}`}\n onChange={(event) => {\n setRecurringProductId(null);\n setCustomAmounts((current) => ({\n ...current,\n [product.id]: event.target.value,\n }));\n }}\n placeholder=\"0.00\"\n step=\"0.01\"\n type=\"number\"\n value={customAmounts[product.id] ?? \"\"}\n />\n {product.minimumAmountCents === null ? null : (\n <small>Minimum {usd.format(product.minimumAmountCents / 100)}</small>\n )}\n </span>\n );\n }\n\n return (\n <button\n aria-label={`Select ${product.name}`}\n aria-pressed={recurringProductId === product.id}\n className=\"lockerverse-launcher__select\"\n onClick={() => {\n setQuantities({});\n setCustomAmounts({});\n setRecurringProductId((current) =>\n current === product.id ? null : product.id\n );\n }}\n type=\"button\"\n >\n Select\n </button>\n );\n}\n\ntype LauncherProductOptionProps = LauncherProductControlProps & {\n variant?: \"default\" | \"donation\";\n};\n\nfunction LauncherProductOption({\n variant = \"default\",\n ...props\n}: LauncherProductOptionProps) {\n const { customAmounts, product, quantities, recurringProductId } = props;\n const customAmount = parseAmountCents(customAmounts[product.id] ?? \"\");\n const isSelected =\n recurringProductId === product.id ||\n (product.paymentOption === \"one-time\" &&\n ((product.pricingMode === \"fixed\" && (quantities[product.id] ?? 0) > 0) ||\n (product.pricingMode === \"custom\" &&\n customAmount !== null &&\n customAmount >= getLockerverseMinimumCustomAmountCents(product))));\n return (\n <article\n className={`lockerverse-launcher__product lockerverse-launcher__product--${variant}`}\n data-selected={isSelected || undefined}\n >\n <span className=\"lockerverse-launcher__product-copy\">\n <strong className=\"lockerverse-launcher__product-name\">\n {product.name}\n </strong>\n {product.description ? <small>{product.description}</small> : null}\n {product.amountCents === null ? null : (\n <span className=\"lockerverse-launcher__product-price\">\n {formatProductPrice(product.amountCents, product.paymentOption)}\n </span>\n )}\n </span>\n <LauncherProductControl {...props} />\n </article>\n );\n}\n\nfunction LauncherDonationOption({\n customAmounts,\n product,\n setCustomAmounts,\n setRecurringProductId,\n}: LauncherProductControlProps) {\n const amount = customAmounts[product.id] ?? \"\";\n const amountCents = parseAmountCents(amount);\n const suggestions = suggestedDonationAmountsCents.filter(\n (suggestion) =>\n suggestion >= getLockerverseMinimumCustomAmountCents(product)\n );\n const isSuggestedAmount = suggestions.includes(amountCents ?? 0);\n const setAmount = (value: string) => {\n setRecurringProductId(null);\n setCustomAmounts((current) => ({\n ...current,\n [product.id]: value,\n }));\n };\n\n return (\n <div className=\"lockerverse-launcher__donation-option\">\n <fieldset className=\"lockerverse-launcher__donation-choices\">\n <legend className=\"lockerverse-launcher__sr-only\">\n {product.name} amount\n </legend>\n <button\n aria-pressed={amount === \"\"}\n onClick={() => setAmount(\"\")}\n type=\"button\"\n >\n No thanks\n </button>\n {suggestions.map((suggestion) => (\n <button\n aria-pressed={amountCents === suggestion}\n key={suggestion}\n onClick={() => setAmount(String(suggestion / 100))}\n type=\"button\"\n >\n {usd.format(suggestion / 100).replace(\".00\", \"\")}\n </button>\n ))}\n <label\n className=\"lockerverse-launcher__donation-other\"\n data-selected={amount !== \"\" && !isSuggestedAmount ? true : undefined}\n >\n <input\n aria-label={`${product.name} amount`}\n min={getLockerverseMinimumCustomAmountCents(product) / 100}\n name={`amount-${product.slug}`}\n onChange={(event) => setAmount(event.target.value)}\n placeholder=\"Other $\"\n step=\"0.01\"\n type=\"number\"\n value={isSuggestedAmount ? \"\" : amount}\n />\n </label>\n </fieldset>\n </div>\n );\n}\n\ntype LauncherProductListProps = Omit<LauncherProductControlProps, \"product\"> & {\n products: LockerverseProduct[];\n variant?: LauncherProductOptionProps[\"variant\"];\n};\n\nfunction LauncherProductList({\n products,\n variant = \"default\",\n ...controlProps\n}: LauncherProductListProps) {\n return (\n <div className=\"lockerverse-launcher__product-list\">\n {products.map((product) =>\n variant === \"donation\" ? (\n <LauncherDonationOption\n {...controlProps}\n key={product.id}\n product={product}\n />\n ) : (\n <LauncherProductOption\n {...controlProps}\n key={product.id}\n product={product}\n variant={variant}\n />\n )\n )}\n </div>\n );\n}\n\nfunction getSelectionSummary(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n) {\n let itemCount = 0;\n let amountCents = 0;\n for (const item of selection) {\n const product = catalog.products.find(\n (candidate) => candidate.slug === item.productSlug\n );\n if (!product) {\n continue;\n }\n if (\"quantity\" in item) {\n itemCount += item.quantity;\n amountCents += (product.amountCents ?? 0) * item.quantity;\n continue;\n }\n itemCount += 1;\n amountCents +=\n \"amountCents\" in item ? item.amountCents : (product.amountCents ?? 0);\n }\n return { amountCents, itemCount };\n}\n\nfunction LauncherLoading() {\n return (\n <div\n aria-label=\"Loading donation options\"\n className=\"lockerverse-launcher__loading\"\n role=\"status\"\n >\n {[0, 1, 2].map((item) => (\n <span\n aria-hidden=\"true\"\n className=\"lockerverse-launcher__loading-row\"\n key={item}\n />\n ))}\n </div>\n );\n}\n\nfunction createLauncherSelection(\n catalog: LockerverseCatalog,\n quantities: Record<string, number>,\n customAmounts: Record<string, string>,\n recurringProductId: string | null\n): LockerversePaymentSelectionItem[] {\n if (recurringProductId) {\n const product = catalog.products.find(\n (candidate) =>\n candidate.id === recurringProductId &&\n candidate.paymentOption !== \"one-time\"\n );\n return product ? [{ productSlug: product.slug }] : [];\n }\n\n return catalog.products.flatMap(\n (product): LockerversePaymentSelectionItem[] => {\n const quantity = quantities[product.id] ?? 0;\n if (\n product.pricingMode === \"fixed\" &&\n product.paymentOption === \"one-time\" &&\n quantity > 0\n ) {\n return [{ productSlug: product.slug, quantity }];\n }\n const amountCents = parseAmountCents(customAmounts[product.id] ?? \"\");\n if (\n product.pricingMode === \"custom\" &&\n product.paymentOption === \"one-time\" &&\n amountCents !== null &&\n amountCents >= getLockerverseMinimumCustomAmountCents(product)\n ) {\n return [{ amountCents, productSlug: product.slug }];\n }\n return [];\n }\n );\n}\n\ntype LauncherSelectionStateProps = Omit<LauncherProductControlProps, \"product\">;\n\ntype LauncherCatalogProps = LauncherSelectionStateProps & {\n catalog: LockerverseCatalog;\n onContinue: (selection: LockerversePaymentSelectionItem[]) => void;\n};\n\nfunction LauncherCatalog({\n catalog,\n onContinue,\n ...selectionState\n}: LauncherCatalogProps) {\n const draftSelection = createLauncherSelection(\n catalog,\n selectionState.quantities,\n selectionState.customAmounts,\n selectionState.recurringProductId\n );\n const summary = getSelectionSummary(catalog, draftSelection);\n const donationProducts = catalog.products.filter(\n (product) =>\n product.paymentOption === \"one-time\" && product.pricingMode === \"custom\"\n );\n const orderProducts = catalog.products.filter(\n (product) => !donationProducts.includes(product)\n );\n\n return (\n <form\n className=\"lockerverse-launcher__products\"\n onSubmit={(event) => {\n event.preventDefault();\n if (draftSelection.length > 0) {\n onContinue(draftSelection);\n }\n }}\n >\n {orderProducts.length > 0 ? (\n <section className=\"lockerverse-launcher__section\">\n <LauncherProductList {...selectionState} products={orderProducts} />\n </section>\n ) : null}\n {donationProducts.length > 0 ? (\n <section className=\"lockerverse-launcher__donation\">\n <header className=\"lockerverse-launcher__section-header\">\n <h3>Add a donation</h3>\n <p>Choose an amount to add to this order.</p>\n </header>\n <LauncherProductList\n {...selectionState}\n products={donationProducts}\n variant=\"donation\"\n />\n </section>\n ) : null}\n {catalog.products.length > 0 ? (\n <footer className=\"lockerverse-launcher__footer\">\n <p aria-live=\"polite\" className=\"lockerverse-launcher__summary\">\n <span>\n {summary.itemCount === 0\n ? \"No items selected\"\n : `${summary.itemCount} ${summary.itemCount === 1 ? \"item\" : \"items\"} selected`}\n </span>\n {summary.itemCount === 0 ? null : (\n <strong>{usd.format(summary.amountCents / 100)}</strong>\n )}\n </p>\n <button\n className=\"lockerverse-launcher__continue\"\n disabled={draftSelection.length === 0}\n type=\"submit\"\n >\n Continue\n </button>\n </footer>\n ) : null}\n </form>\n );\n}\n\ntype LauncherPaymentProps = Omit<\n LockerversePaymentProps,\n \"selection\" | \"widget\"\n>;\n\ntype LauncherCheckoutProps = {\n onEdit: () => void;\n paymentProps: LauncherPaymentProps;\n selection: LockerversePaymentSelectionItem[];\n style: LockerversePaymentStyle;\n widget: UseLockerverseWidgetResult;\n};\n\nfunction LauncherCheckout({\n onEdit,\n paymentProps,\n selection,\n style,\n widget,\n}: LauncherCheckoutProps) {\n return (\n <div className=\"lockerverse-launcher__checkout\">\n <header className=\"lockerverse-launcher__checkout-toolbar\">\n <button\n className=\"lockerverse-launcher__back\"\n onClick={onEdit}\n type=\"button\"\n >\n Edit order\n </button>\n </header>\n <LockerversePayment\n {...paymentProps}\n selection={selection}\n style={style}\n widget={widget}\n />\n </div>\n );\n}\n\nfunction LauncherDialogHeading({\n catalog,\n checkout,\n}: {\n catalog: LockerverseCatalog | null;\n checkout: boolean;\n}) {\n if (checkout) {\n return (\n <>\n <Dialog.Title className=\"lockerverse-launcher__sr-only\">\n Checkout\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__sr-only\">\n Review the order and complete payment.\n </Dialog.Description>\n </>\n );\n }\n\n if (!catalog) {\n return (\n <header className=\"lockerverse-launcher__header\">\n <Dialog.Title className=\"lockerverse-launcher__title\">\n Donate\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__description\">\n Choose your options, then continue to checkout.\n </Dialog.Description>\n </header>\n );\n }\n\n return (\n <header className=\"lockerverse-launcher__header\">\n {catalog.community ? (\n <div className=\"lockerverse-launcher__brand\">\n {catalog.community.imageUrl ? (\n <img\n alt={`${catalog.community.name} logo`}\n height=\"28\"\n src={catalog.community.imageUrl}\n width=\"28\"\n />\n ) : null}\n <span>{catalog.community.name}</span>\n </div>\n ) : null}\n <Dialog.Title className=\"lockerverse-launcher__title\">\n {catalog.widget.title ?? catalog.widget.name}\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__description\">\n {catalog.widget.description ??\n \"Choose your options, then continue to checkout.\"}\n </Dialog.Description>\n </header>\n );\n}\n\nexport function LockerverseDonateLauncher({\n buttonLabel = \"Donate\",\n position = \"inline\",\n widget,\n ...paymentProps\n}: LockerverseDonateLauncherProps) {\n const [selection, setSelection] = useState<\n LockerversePaymentSelectionItem[] | null\n >(null);\n const [customAmounts, setCustomAmounts] = useState<Record<string, string>>(\n {}\n );\n const [quantities, setQuantities] = useState<Record<string, number>>({});\n const [recurringProductId, setRecurringProductId] = useState<string | null>(\n null\n );\n const { catalog, error, loading } = widget;\n const accent = normalizeAccentColor(\n paymentProps.style?.[\"--lockerverse-accent\"] ??\n catalog?.community?.accentColor ??\n \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const launcherStyle: LockerversePaymentStyle = { ...paymentProps.style };\n if (\n paymentProps.style?.[\"--lockerverse-accent\"] !== undefined ||\n catalog?.community?.accentColor\n ) {\n launcherStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n paymentProps.style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n launcherStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n\n let content: ReactNode;\n if (loading) {\n content = <LauncherLoading />;\n } else if (error) {\n content = (\n <div role=\"alert\">\n <p>Unable to load donation options.</p>\n <button onClick={widget.refresh} type=\"button\">\n Retry\n </button>\n </div>\n );\n } else if (catalog) {\n content = (\n <LauncherCatalog\n catalog={catalog}\n customAmounts={customAmounts}\n onContinue={setSelection}\n quantities={quantities}\n recurringProductId={recurringProductId}\n setCustomAmounts={setCustomAmounts}\n setQuantities={setQuantities}\n setRecurringProductId={setRecurringProductId}\n />\n );\n } else {\n content = <LauncherLoading />;\n }\n if (!(loading || error) && selection && catalog) {\n content = (\n <LauncherCheckout\n onEdit={() => setSelection(null)}\n paymentProps={paymentProps}\n selection={selection}\n style={launcherStyle}\n widget={widget}\n />\n );\n }\n\n return (\n <Dialog.Root\n onOpenChange={(open) => {\n if (open && catalog && paymentProps.stripeLoader === undefined) {\n requestAnimationFrame(() => {\n preloadLockerversePayment(catalog);\n });\n }\n }}\n >\n <Dialog.Trigger\n className={`lockerverse-launcher lockerverse-launcher--${position}`}\n data-lockerverse-theme={paymentProps.theme ?? \"dark\"}\n style={launcherStyle}\n >\n {buttonLabel}\n </Dialog.Trigger>\n <Dialog.Portal>\n <Dialog.Backdrop className=\"lockerverse-launcher__backdrop\" />\n <Dialog.Viewport className=\"lockerverse-launcher__viewport\">\n <Dialog.Popup\n className=\"lockerverse-launcher__dialog\"\n data-lockerverse-theme={paymentProps.theme ?? \"dark\"}\n style={launcherStyle}\n >\n <LauncherDialogHeading\n catalog={catalog}\n checkout={selection !== null}\n />\n <Dialog.Close\n aria-label=\"Close donation dialog\"\n className=\"lockerverse-launcher__close\"\n >\n <span aria-hidden=\"true\">×</span>\n </Dialog.Close>\n {content}\n </Dialog.Popup>\n </Dialog.Viewport>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lockerverse-donate-launcher.js","names":[],"sources":["../src/lockerverse-donate-launcher.tsx"],"sourcesContent":["import { Dialog } from \"@base-ui/react/dialog\";\nimport {\n getLockerverseMinimumCustomAmountCents,\n type LockerverseCatalog,\n type LockerverseProduct,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n useState,\n} from \"react\";\nimport { getAccentContrast, normalizeAccentColor } from \"./accent-contrast.ts\";\nimport { LockerversePayment } from \"./lockerverse-payment.tsx\";\nimport { preloadLockerversePayment } from \"./payment-form.tsx\";\nimport type {\n LockerverseDonateLauncherProps,\n LockerversePaymentProps,\n LockerversePaymentSelectionItem,\n LockerversePaymentStyle,\n} from \"./types.ts\";\nimport type { UseLockerverseWidgetResult } from \"./use-lockerverse-widget.ts\";\n\nconst usd = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n});\nconst decimalAmountPattern = /^(?:0|[1-9]\\d*)(?:\\.\\d{1,2})?$/;\nconst suggestedDonationAmountsCents = [1000, 2500, 5000, 10_000];\n\nfunction parseAmountCents(value: string) {\n if (!decimalAmountPattern.test(value)) {\n return null;\n }\n const amountCents = Math.round(Number(value) * 100);\n return Number.isSafeInteger(amountCents) && amountCents > 0\n ? amountCents\n : null;\n}\n\nfunction formatProductPrice(\n amountCents: number,\n paymentOption: \"one-time\" | \"monthly\" | \"annually\"\n) {\n let cadence = \"\";\n if (paymentOption === \"monthly\") {\n cadence = \"/month\";\n }\n if (paymentOption === \"annually\") {\n cadence = \"/year\";\n }\n return `${usd.format(amountCents / 100)}${cadence}`;\n}\n\ntype LauncherProductControlProps = {\n customAmounts: Record<string, string>;\n product: LockerverseProduct;\n quantities: Record<string, number>;\n recurringProductId: string | null;\n setCustomAmounts: Dispatch<SetStateAction<Record<string, string>>>;\n setQuantities: Dispatch<SetStateAction<Record<string, number>>>;\n setRecurringProductId: Dispatch<SetStateAction<string | null>>;\n};\n\nfunction LauncherProductControl({\n customAmounts,\n product,\n quantities,\n recurringProductId,\n setCustomAmounts,\n setQuantities,\n setRecurringProductId,\n}: LauncherProductControlProps) {\n const quantity = quantities[product.id] ?? 0;\n if (product.pricingMode === \"fixed\" && product.paymentOption === \"one-time\") {\n const minimum = product.minimumQuantity ?? 1;\n const maximum = Math.min(\n product.maximumQuantity ?? Number.POSITIVE_INFINITY,\n product.inventoryQuantity ?? Number.POSITIVE_INFINITY\n );\n return (\n <span className=\"lockerverse-launcher__quantity\">\n <button\n aria-label={`Decrease ${product.name} quantity`}\n disabled={quantity === 0}\n onClick={() => {\n setRecurringProductId(null);\n setQuantities((current) => {\n const currentQuantity = current[product.id] ?? 0;\n return {\n ...current,\n [product.id]:\n currentQuantity <= minimum ? 0 : currentQuantity - 1,\n };\n });\n }}\n type=\"button\"\n >\n −\n </button>\n <output aria-label={`${product.name} quantity`}>{quantity}</output>\n <button\n aria-label={`Increase ${product.name} quantity`}\n disabled={maximum < minimum || quantity >= maximum}\n onClick={() => {\n setRecurringProductId(null);\n setQuantities((current) => {\n const currentQuantity = current[product.id] ?? 0;\n return {\n ...current,\n [product.id]:\n currentQuantity === 0 ? minimum : currentQuantity + 1,\n };\n });\n }}\n type=\"button\"\n >\n +\n </button>\n </span>\n );\n }\n\n if (\n product.pricingMode === \"custom\" &&\n product.paymentOption === \"one-time\"\n ) {\n return (\n <span className=\"lockerverse-launcher__custom-amount\">\n <span aria-hidden=\"true\">$</span>\n <input\n aria-label={`${product.name} amount`}\n min={getLockerverseMinimumCustomAmountCents(product) / 100}\n name={`amount-${product.slug}`}\n onChange={(event) => {\n setRecurringProductId(null);\n setCustomAmounts((current) => ({\n ...current,\n [product.id]: event.target.value,\n }));\n }}\n placeholder=\"0.00\"\n step=\"0.01\"\n type=\"number\"\n value={customAmounts[product.id] ?? \"\"}\n />\n {product.minimumAmountCents === null ? null : (\n <small>Minimum {usd.format(product.minimumAmountCents / 100)}</small>\n )}\n </span>\n );\n }\n\n return (\n <button\n aria-label={`Select ${product.name}`}\n aria-pressed={recurringProductId === product.id}\n className=\"lockerverse-launcher__select\"\n onClick={() => {\n setQuantities({});\n setCustomAmounts({});\n setRecurringProductId((current) =>\n current === product.id ? null : product.id\n );\n }}\n type=\"button\"\n >\n Select\n </button>\n );\n}\n\ntype LauncherProductOptionProps = LauncherProductControlProps & {\n variant?: \"default\" | \"donation\";\n};\n\nfunction LauncherProductOption({\n variant = \"default\",\n ...props\n}: LauncherProductOptionProps) {\n const { customAmounts, product, quantities, recurringProductId } = props;\n const customAmount = parseAmountCents(customAmounts[product.id] ?? \"\");\n const isSelected =\n recurringProductId === product.id ||\n (product.paymentOption === \"one-time\" &&\n ((product.pricingMode === \"fixed\" && (quantities[product.id] ?? 0) > 0) ||\n (product.pricingMode === \"custom\" &&\n customAmount !== null &&\n customAmount >= getLockerverseMinimumCustomAmountCents(product))));\n return (\n <article\n className={`lockerverse-launcher__product lockerverse-launcher__product--${variant}`}\n data-selected={isSelected || undefined}\n >\n <span className=\"lockerverse-launcher__product-copy\">\n <strong className=\"lockerverse-launcher__product-name\">\n {product.name}\n </strong>\n {product.description ? <small>{product.description}</small> : null}\n {product.amountCents === null ? null : (\n <span className=\"lockerverse-launcher__product-price\">\n {formatProductPrice(product.amountCents, product.paymentOption)}\n </span>\n )}\n </span>\n <LauncherProductControl {...props} />\n </article>\n );\n}\n\nfunction LauncherDonationOption({\n customAmounts,\n product,\n setCustomAmounts,\n setRecurringProductId,\n}: LauncherProductControlProps) {\n const amount = customAmounts[product.id] ?? \"\";\n const amountCents = parseAmountCents(amount);\n const suggestions = suggestedDonationAmountsCents.filter(\n (suggestion) =>\n suggestion >= getLockerverseMinimumCustomAmountCents(product)\n );\n const isSuggestedAmount = suggestions.includes(amountCents ?? 0);\n const setAmount = (value: string) => {\n setRecurringProductId(null);\n setCustomAmounts((current) => ({\n ...current,\n [product.id]: value,\n }));\n };\n\n return (\n <div className=\"lockerverse-launcher__donation-option\">\n <fieldset className=\"lockerverse-launcher__donation-choices\">\n <legend className=\"lockerverse-launcher__sr-only\">\n {product.name} amount\n </legend>\n <button\n aria-pressed={amount === \"\"}\n onClick={() => setAmount(\"\")}\n type=\"button\"\n >\n No thanks\n </button>\n {suggestions.map((suggestion) => (\n <button\n aria-pressed={amountCents === suggestion}\n key={suggestion}\n onClick={() => setAmount(String(suggestion / 100))}\n type=\"button\"\n >\n {usd.format(suggestion / 100).replace(\".00\", \"\")}\n </button>\n ))}\n <label\n className=\"lockerverse-launcher__donation-other\"\n data-selected={amount !== \"\" && !isSuggestedAmount ? true : undefined}\n >\n <input\n aria-label={`${product.name} amount`}\n min={getLockerverseMinimumCustomAmountCents(product) / 100}\n name={`amount-${product.slug}`}\n onChange={(event) => setAmount(event.target.value)}\n placeholder=\"Other $\"\n step=\"0.01\"\n type=\"number\"\n value={isSuggestedAmount ? \"\" : amount}\n />\n </label>\n </fieldset>\n </div>\n );\n}\n\ntype LauncherProductListProps = Omit<LauncherProductControlProps, \"product\"> & {\n products: LockerverseProduct[];\n variant?: LauncherProductOptionProps[\"variant\"];\n};\n\nfunction LauncherProductList({\n products,\n variant = \"default\",\n ...controlProps\n}: LauncherProductListProps) {\n return (\n <div className=\"lockerverse-launcher__product-list\">\n {products.map((product) =>\n variant === \"donation\" ? (\n <LauncherDonationOption\n {...controlProps}\n key={product.id}\n product={product}\n />\n ) : (\n <LauncherProductOption\n {...controlProps}\n key={product.id}\n product={product}\n variant={variant}\n />\n )\n )}\n </div>\n );\n}\n\nfunction getSelectionSummary(\n catalog: LockerverseCatalog,\n selection: LockerversePaymentSelectionItem[]\n) {\n let itemCount = 0;\n let amountCents = 0;\n for (const item of selection) {\n const product = catalog.products.find(\n (candidate) => candidate.slug === item.productSlug\n );\n if (!product) {\n continue;\n }\n if (\"quantity\" in item) {\n itemCount += item.quantity;\n amountCents += (product.amountCents ?? 0) * item.quantity;\n continue;\n }\n itemCount += 1;\n amountCents +=\n \"amountCents\" in item ? item.amountCents : (product.amountCents ?? 0);\n }\n return { amountCents, itemCount };\n}\n\nfunction LauncherLoading() {\n return (\n <div\n aria-label=\"Loading donation options\"\n className=\"lockerverse-launcher__loading\"\n role=\"status\"\n >\n {[0, 1, 2].map((item) => (\n <span\n aria-hidden=\"true\"\n className=\"lockerverse-launcher__loading-row\"\n key={item}\n />\n ))}\n </div>\n );\n}\n\nfunction createLauncherSelection(\n catalog: LockerverseCatalog,\n quantities: Record<string, number>,\n customAmounts: Record<string, string>,\n recurringProductId: string | null\n): LockerversePaymentSelectionItem[] {\n if (recurringProductId) {\n const product = catalog.products.find(\n (candidate) =>\n candidate.id === recurringProductId &&\n candidate.paymentOption !== \"one-time\"\n );\n return product ? [{ productSlug: product.slug }] : [];\n }\n\n return catalog.products.flatMap(\n (product): LockerversePaymentSelectionItem[] => {\n const quantity = quantities[product.id] ?? 0;\n if (\n product.pricingMode === \"fixed\" &&\n product.paymentOption === \"one-time\" &&\n quantity > 0\n ) {\n return [{ productSlug: product.slug, quantity }];\n }\n const amountCents = parseAmountCents(customAmounts[product.id] ?? \"\");\n if (\n product.pricingMode === \"custom\" &&\n product.paymentOption === \"one-time\" &&\n amountCents !== null &&\n amountCents >= getLockerverseMinimumCustomAmountCents(product)\n ) {\n return [{ amountCents, productSlug: product.slug }];\n }\n return [];\n }\n );\n}\n\ntype LauncherSelectionStateProps = Omit<LauncherProductControlProps, \"product\">;\n\ntype LauncherCatalogProps = LauncherSelectionStateProps & {\n catalog: LockerverseCatalog;\n onContinue: (selection: LockerversePaymentSelectionItem[]) => void;\n};\n\nfunction LauncherCatalog({\n catalog,\n onContinue,\n ...selectionState\n}: LauncherCatalogProps) {\n const draftSelection = createLauncherSelection(\n catalog,\n selectionState.quantities,\n selectionState.customAmounts,\n selectionState.recurringProductId\n );\n const summary = getSelectionSummary(catalog, draftSelection);\n const donationProducts = catalog.products.filter(\n (product) =>\n product.paymentOption === \"one-time\" && product.pricingMode === \"custom\"\n );\n const orderProducts = catalog.products.filter(\n (product) => !donationProducts.includes(product)\n );\n\n return (\n <form\n className=\"lockerverse-launcher__products\"\n onSubmit={(event) => {\n event.preventDefault();\n if (draftSelection.length > 0) {\n onContinue(draftSelection);\n }\n }}\n >\n {orderProducts.length > 0 ? (\n <section className=\"lockerverse-launcher__section\">\n <LauncherProductList {...selectionState} products={orderProducts} />\n </section>\n ) : null}\n {donationProducts.length > 0 ? (\n <section className=\"lockerverse-launcher__donation\">\n <header className=\"lockerverse-launcher__section-header\">\n <h3>Add a donation</h3>\n <p>Choose an amount to add to this order.</p>\n </header>\n <LauncherProductList\n {...selectionState}\n products={donationProducts}\n variant=\"donation\"\n />\n </section>\n ) : null}\n {catalog.products.length > 0 ? (\n <footer className=\"lockerverse-launcher__footer\">\n <p aria-live=\"polite\" className=\"lockerverse-launcher__summary\">\n <span>\n {summary.itemCount === 0\n ? \"No items selected\"\n : `${summary.itemCount} ${summary.itemCount === 1 ? \"item\" : \"items\"} selected`}\n </span>\n {summary.itemCount === 0 ? null : (\n <strong>{usd.format(summary.amountCents / 100)}</strong>\n )}\n </p>\n <button\n className=\"lockerverse-launcher__continue\"\n disabled={draftSelection.length === 0}\n type=\"submit\"\n >\n Continue\n </button>\n </footer>\n ) : null}\n </form>\n );\n}\n\ntype LauncherPaymentProps = Omit<\n LockerversePaymentProps,\n \"selection\" | \"widget\"\n>;\n\ntype LauncherCheckoutProps = {\n onEdit: () => void;\n paymentProps: LauncherPaymentProps;\n selection: LockerversePaymentSelectionItem[];\n style: LockerversePaymentStyle;\n widget: UseLockerverseWidgetResult;\n};\n\nfunction LauncherCheckout({\n onEdit,\n paymentProps,\n selection,\n style,\n widget,\n}: LauncherCheckoutProps) {\n return (\n <div className=\"lockerverse-launcher__checkout\">\n <header className=\"lockerverse-launcher__checkout-toolbar\">\n <button\n className=\"lockerverse-launcher__back\"\n onClick={onEdit}\n type=\"button\"\n >\n Edit order\n </button>\n </header>\n <LockerversePayment\n {...paymentProps}\n selection={selection}\n style={style}\n widget={widget}\n />\n </div>\n );\n}\n\nfunction LauncherDialogHeading({\n catalog,\n checkout,\n}: {\n catalog: LockerverseCatalog | null;\n checkout: boolean;\n}) {\n if (checkout) {\n return (\n <>\n <Dialog.Title className=\"lockerverse-launcher__sr-only\">\n Checkout\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__sr-only\">\n Review the order and complete payment.\n </Dialog.Description>\n </>\n );\n }\n\n if (!catalog) {\n return (\n <header className=\"lockerverse-launcher__header\">\n <Dialog.Title className=\"lockerverse-launcher__title\">\n Donate\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__description\">\n Choose your options, then continue to checkout.\n </Dialog.Description>\n </header>\n );\n }\n\n return (\n <header className=\"lockerverse-launcher__header\">\n {catalog.community ? (\n <div className=\"lockerverse-launcher__brand\">\n {catalog.community.imageUrl ? (\n <img\n alt={`${catalog.community.name} logo`}\n height=\"28\"\n src={catalog.community.imageUrl}\n width=\"28\"\n />\n ) : null}\n <span>{catalog.community.name}</span>\n </div>\n ) : null}\n <Dialog.Title className=\"lockerverse-launcher__title\">\n {catalog.widget.title ?? catalog.widget.name}\n </Dialog.Title>\n <Dialog.Description className=\"lockerverse-launcher__description\">\n {catalog.widget.description ??\n \"Choose your options, then continue to checkout.\"}\n </Dialog.Description>\n </header>\n );\n}\n\nexport function LockerverseDonateLauncher({\n buttonLabel = \"Donate\",\n position = \"inline\",\n widget,\n ...paymentProps\n}: LockerverseDonateLauncherProps) {\n const [selection, setSelection] = useState<\n LockerversePaymentSelectionItem[] | null\n >(null);\n const [customAmounts, setCustomAmounts] = useState<Record<string, string>>(\n {}\n );\n const [quantities, setQuantities] = useState<Record<string, number>>({});\n const [recurringProductId, setRecurringProductId] = useState<string | null>(\n null\n );\n const { catalog, error, loading } = widget;\n const accent = normalizeAccentColor(\n paymentProps.style?.[\"--lockerverse-accent\"] ??\n catalog?.community?.accentColor ??\n \"#38d77a\"\n );\n const accentContrast = getAccentContrast(accent);\n const launcherStyle: LockerversePaymentStyle = { ...paymentProps.style };\n if (\n paymentProps.style?.[\"--lockerverse-accent\"] !== undefined ||\n catalog?.community?.accentColor\n ) {\n launcherStyle[\"--lockerverse-accent\"] = accent;\n }\n if (\n accentContrast &&\n paymentProps.style?.[\"--lockerverse-accent-contrast\"] === undefined\n ) {\n launcherStyle[\"--lockerverse-accent-contrast\"] = accentContrast;\n }\n\n let content: ReactNode;\n if (loading) {\n content = <LauncherLoading />;\n } else if (error) {\n content = (\n <div role=\"alert\">\n <p>Unable to load donation options.</p>\n <button onClick={widget.refresh} type=\"button\">\n Retry\n </button>\n </div>\n );\n } else if (catalog) {\n content = (\n <LauncherCatalog\n catalog={catalog}\n customAmounts={customAmounts}\n onContinue={setSelection}\n quantities={quantities}\n recurringProductId={recurringProductId}\n setCustomAmounts={setCustomAmounts}\n setQuantities={setQuantities}\n setRecurringProductId={setRecurringProductId}\n />\n );\n } else {\n content = <LauncherLoading />;\n }\n if (!(loading || error) && selection && catalog) {\n content = (\n <LauncherCheckout\n onEdit={() => setSelection(null)}\n paymentProps={paymentProps}\n selection={selection}\n style={launcherStyle}\n widget={widget}\n />\n );\n }\n\n return (\n <Dialog.Root\n onOpenChange={(open) => {\n if (open && catalog && paymentProps.stripeLoader === undefined) {\n requestAnimationFrame(() => {\n preloadLockerversePayment(catalog);\n });\n }\n }}\n >\n <Dialog.Trigger\n className={`lockerverse-launcher lockerverse-launcher--${position}`}\n data-lockerverse-theme={paymentProps.theme ?? \"dark\"}\n style={launcherStyle}\n >\n {buttonLabel}\n </Dialog.Trigger>\n <Dialog.Portal>\n <Dialog.Backdrop className=\"lockerverse-launcher__backdrop\" />\n <Dialog.Viewport className=\"lockerverse-launcher__viewport\">\n <Dialog.Popup\n className=\"lockerverse-launcher__dialog\"\n data-lockerverse-theme={paymentProps.theme ?? \"dark\"}\n style={launcherStyle}\n >\n <LauncherDialogHeading\n catalog={catalog}\n checkout={selection !== null}\n />\n <Dialog.Close\n aria-label=\"Close donation dialog\"\n className=\"lockerverse-launcher__close\"\n >\n <span aria-hidden=\"true\">×</span>\n </Dialog.Close>\n {content}\n </Dialog.Popup>\n </Dialog.Viewport>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n"],"mappings":"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"}
|