@solvapay/react 2.0.1 → 2.0.2-preview-55843c4d7bb67bbe89bfcdabbbe0e3a679eb2805

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2441,7 +2441,7 @@ function usePaymentForm() {
2441
2441
  var PaymentFormProvider = ({ value, children }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaymentFormContext.Provider, { value, children });
2442
2442
 
2443
2443
  // src/primitives/CheckoutSummary.tsx
2444
- var import_react13 = require("react");
2444
+ var import_react14 = require("react");
2445
2445
 
2446
2446
  // src/utils/format.ts
2447
2447
  var ZERO_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
@@ -2507,11 +2507,302 @@ function interpolate(template, vars) {
2507
2507
  });
2508
2508
  }
2509
2509
 
2510
- // src/primitives/CheckoutSummary.tsx
2510
+ // src/components/businessCheckoutParts.tsx
2511
+ var import_react13 = require("react");
2512
+ var import_core2 = require("@solvapay/core");
2511
2513
  var import_jsx_runtime7 = require("react/jsx-runtime");
2512
- var CheckoutSummaryContext = (0, import_react13.createContext)(null);
2514
+ function mapBusinessFieldErrors(input) {
2515
+ const result = (0, import_core2.validateBusinessDetails)(input);
2516
+ if (result.success) return {};
2517
+ const errors = {};
2518
+ for (const issue of result.error.issues) {
2519
+ const key = issue.path[0];
2520
+ if (typeof key === "string" && isBusinessDetailsKey(key) && !errors[key]) {
2521
+ errors[key] = issue.message;
2522
+ }
2523
+ }
2524
+ return errors;
2525
+ }
2526
+ function isBusinessDetailsKey(key) {
2527
+ return key === "isBusiness" || key === "businessName" || key === "country" || key === "customerCountry" || key === "customerName" || key === "taxId" || key === "taxIdType";
2528
+ }
2529
+ function attr(prefix, suffix) {
2530
+ return `data-solvapay-${prefix}-${suffix}`;
2531
+ }
2532
+ var SUPPORTED_BUSINESS_COUNTRIES_SET = new Set(import_core2.SUPPORTED_BUSINESS_COUNTRIES);
2533
+ function isSupportedBusinessCountry(value) {
2534
+ return SUPPORTED_BUSINESS_COUNTRIES_SET.has(value);
2535
+ }
2536
+ function resolveTaxIdLabel(country) {
2537
+ if (country && isSupportedBusinessCountry(country)) {
2538
+ return (0, import_core2.getTaxIdFieldLabel)(country);
2539
+ }
2540
+ return "Tax ID";
2541
+ }
2542
+ function resolveTaxIdPlaceholder(country) {
2543
+ if (country && isSupportedBusinessCountry(country)) {
2544
+ return (0, import_core2.getTaxIdExample)(country);
2545
+ }
2546
+ return "Enter tax ID";
2547
+ }
2548
+ function resolveTaxIdHelperText(country) {
2549
+ if (country && isSupportedBusinessCountry(country)) {
2550
+ return (0, import_core2.getTaxIdHelperText)(country);
2551
+ }
2552
+ return "";
2553
+ }
2554
+ var REVERSE_CHARGE_NOTE = "VAT reverse charge applies \u2014 you are responsible for reporting VAT in your jurisdiction.";
2555
+ var TAX_NOT_COLLECTED_NOTE = "Tax is not collected on this purchase.";
2556
+ function formatVatSummaryLabel(breakdown) {
2557
+ if (breakdown.treatment === "reverse_charge") {
2558
+ return "VAT (reverse charge)";
2559
+ }
2560
+ if (breakdown.taxRate > 0) {
2561
+ const ratePercent = breakdown.taxRate <= 1 ? Math.round(breakdown.taxRate * 100) : breakdown.taxRate;
2562
+ return `VAT (${ratePercent}%)`;
2563
+ }
2564
+ return "VAT";
2565
+ }
2566
+ function shouldShowTaxRow(treatment) {
2567
+ return treatment !== "not_collecting" && treatment !== "not_supported";
2568
+ }
2569
+ function formatSubtotalLabel(treatment) {
2570
+ return shouldShowTaxRow(treatment) ? "Subtotal (excl. VAT)" : "Subtotal";
2571
+ }
2572
+ function createBusinessDetailsParts(useCtx, prefix) {
2573
+ const Root14 = (0, import_react13.forwardRef)(function BusinessDetailsRoot({ asChild, children, ...rest }, forwardedRef) {
2574
+ useCtx("BusinessDetails");
2575
+ const Comp = asChild ? Slot : "section";
2576
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "business-details")]: "" }, ...rest, children });
2577
+ });
2578
+ const Toggle = (0, import_react13.forwardRef)(function BusinessDetailsToggle({ asChild, onChange, ...rest }, forwardedRef) {
2579
+ const ctx = useCtx("BusinessDetails.Toggle");
2580
+ const commonProps = {
2581
+ [attr(prefix, "business-details-toggle")]: "",
2582
+ type: "checkbox",
2583
+ checked: ctx.businessDetails.isBusiness,
2584
+ onChange: composeEventHandlers(onChange, (e) => {
2585
+ ctx.setBusinessDetails({ isBusiness: e.target.checked });
2586
+ }),
2587
+ ...rest
2588
+ };
2589
+ if (asChild) {
2590
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...commonProps });
2591
+ }
2592
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref: forwardedRef, ...commonProps });
2593
+ });
2594
+ const BusinessName = (0, import_react13.forwardRef)(
2595
+ function BusinessDetailsBusinessName({ asChild, onChange, ...rest }, forwardedRef) {
2596
+ const ctx = useCtx("BusinessDetails.BusinessName");
2597
+ if (!ctx.businessDetails.isBusiness) return null;
2598
+ const commonProps = {
2599
+ [attr(prefix, "business-details-name")]: "",
2600
+ type: "text",
2601
+ value: ctx.businessDetails.businessName ?? "",
2602
+ "aria-invalid": ctx.fieldErrors.businessName ? true : void 0,
2603
+ onChange: composeEventHandlers(onChange, (e) => {
2604
+ ctx.setBusinessDetails({ businessName: e.target.value });
2605
+ }),
2606
+ ...rest
2607
+ };
2608
+ if (asChild) {
2609
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...commonProps });
2610
+ }
2611
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref: forwardedRef, ...commonProps });
2612
+ }
2613
+ );
2614
+ const Country = (0, import_react13.forwardRef)(function BusinessDetailsCountry({ asChild, onChange, children, ...rest }, forwardedRef) {
2615
+ const ctx = useCtx("BusinessDetails.Country");
2616
+ if (!ctx.businessDetails.isBusiness) return null;
2617
+ const commonProps = {
2618
+ [attr(prefix, "business-details-country")]: "",
2619
+ value: ctx.businessDetails.country ?? "",
2620
+ "aria-invalid": ctx.fieldErrors.country ? true : void 0,
2621
+ onChange: composeEventHandlers(onChange, (e) => {
2622
+ ctx.setBusinessDetails({ country: e.target.value });
2623
+ }),
2624
+ ...rest
2625
+ };
2626
+ const defaultOptions = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2627
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: "Select country" }),
2628
+ import_core2.BUSINESS_COUNTRY_OPTIONS.map(({ value, label }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value, children: label }, value))
2629
+ ] });
2630
+ if (asChild) {
2631
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...commonProps, children: children ?? defaultOptions });
2632
+ }
2633
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { ref: forwardedRef, ...commonProps, children: children ?? defaultOptions });
2634
+ });
2635
+ const TaxId = (0, import_react13.forwardRef)(function BusinessDetailsTaxId({ asChild, onChange, ...rest }, forwardedRef) {
2636
+ const ctx = useCtx("BusinessDetails.TaxId");
2637
+ if (!ctx.businessDetails.isBusiness) return null;
2638
+ const commonProps = {
2639
+ [attr(prefix, "business-details-tax-id")]: "",
2640
+ type: "text",
2641
+ value: ctx.businessDetails.taxId ?? "",
2642
+ "aria-invalid": ctx.fieldErrors.taxId ? true : void 0,
2643
+ onChange: composeEventHandlers(onChange, (e) => {
2644
+ ctx.setBusinessDetails({ taxId: e.target.value });
2645
+ }),
2646
+ ...rest
2647
+ };
2648
+ if (asChild) {
2649
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...commonProps });
2650
+ }
2651
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { ref: forwardedRef, ...commonProps });
2652
+ });
2653
+ const Fields2 = (0, import_react13.forwardRef)(function BusinessDetailsFields({ asChild, children, ...rest }, forwardedRef) {
2654
+ const ctx = useCtx("BusinessDetails.Fields");
2655
+ const country = ctx.businessDetails.country ?? "";
2656
+ const taxIdLabel = resolveTaxIdLabel(country);
2657
+ const taxIdPlaceholder = resolveTaxIdPlaceholder(country);
2658
+ const taxIdHelperText = resolveTaxIdHelperText(country);
2659
+ const content = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "solvapay-checkout-business-toggle", children: [
2661
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Toggle, {}),
2662
+ "I'm purchasing as a business"
2663
+ ] }),
2664
+ ctx.businessDetails.isBusiness ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: "solvapay-business-fields", children: [
2665
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "solvapay-business-field", children: [
2666
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "solvapay-business-field-label", children: "Business name" }),
2667
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BusinessName, { placeholder: "Acme GmbH" })
2668
+ ] }),
2669
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "solvapay-business-field", children: [
2670
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "solvapay-business-field-label", children: "Country" }),
2671
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Country, {})
2672
+ ] }),
2673
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "solvapay-business-field", children: [
2674
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "solvapay-business-field-label", children: taxIdLabel }),
2675
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TaxId, { placeholder: taxIdPlaceholder }),
2676
+ taxIdHelperText ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "solvapay-business-field-hint", children: taxIdHelperText }) : null
2677
+ ] })
2678
+ ] }) : null,
2679
+ children
2680
+ ] });
2681
+ if (asChild) {
2682
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...rest, children: content });
2683
+ }
2684
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { ref: forwardedRef, ...{ [attr(prefix, "business-details-fields")]: "" }, ...rest, children: content });
2685
+ });
2686
+ return {
2687
+ Root: Root14,
2688
+ Toggle,
2689
+ BusinessName,
2690
+ Country,
2691
+ TaxId,
2692
+ Fields: Fields2
2693
+ };
2694
+ }
2695
+ function useSummaryAmounts(useCtx, part) {
2696
+ const ctx = useCtx(part);
2697
+ const locale = useLocale();
2698
+ const currency = (ctx.taxBreakdown?.currency ?? ctx.currency ?? "usd").toLowerCase();
2699
+ const subtotalMinor = ctx.taxBreakdown?.subtotal ?? ctx.baseAmountMinor;
2700
+ const taxMinor = ctx.taxBreakdown?.taxAmount ?? 0;
2701
+ const totalMinor = ctx.taxBreakdown?.total ?? ctx.baseAmountMinor;
2702
+ return {
2703
+ // `free: ''` — a summary line is an amount, not a price. Without it
2704
+ // formatPrice turns any zero (VAT, and a zero subtotal or total) into
2705
+ // the word "Free". DEV-723.
2706
+ subtotalFormatted: formatPrice(subtotalMinor, currency, { locale, free: "" }),
2707
+ taxFormatted: formatPrice(taxMinor, currency, { locale, free: "" }),
2708
+ totalFormatted: formatPrice(totalMinor, currency, { locale, free: "" }),
2709
+ taxRate: ctx.taxBreakdown?.taxRate ?? 0,
2710
+ treatment: ctx.taxBreakdown?.treatment ?? null,
2711
+ attaching: ctx.businessDetailsAttaching
2712
+ };
2713
+ }
2714
+ function createTaxSummaryParts(useCtx, prefix) {
2715
+ const Root14 = (0, import_react13.forwardRef)(function TaxSummaryRoot({ asChild, children, ...rest }, forwardedRef) {
2716
+ const ctx = useCtx("Summary");
2717
+ if (!ctx.isBusiness) return null;
2718
+ const Comp = asChild ? Slot : "section";
2719
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary")]: "" }, ...rest, children });
2720
+ });
2721
+ const Subtotal = (0, import_react13.forwardRef)(function TaxSummarySubtotal({ asChild, children, ...rest }, forwardedRef) {
2722
+ const ctx = useCtx("Summary.Subtotal");
2723
+ const { subtotalFormatted } = useSummaryAmounts(useCtx, "Summary.Subtotal");
2724
+ if (!ctx.isBusiness) return null;
2725
+ const Comp = asChild ? Slot : "span";
2726
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-subtotal")]: "" }, ...rest, children: children ?? subtotalFormatted });
2727
+ });
2728
+ const Tax = (0, import_react13.forwardRef)(function TaxSummaryTax({ asChild, children, ...rest }, forwardedRef) {
2729
+ const ctx = useCtx("Summary.Tax");
2730
+ const { taxFormatted, taxRate, treatment } = useSummaryAmounts(useCtx, "Summary.Tax");
2731
+ if (!ctx.isBusiness) return null;
2732
+ if (!shouldShowTaxRow(treatment)) return null;
2733
+ const Comp = asChild ? Slot : "span";
2734
+ const defaultLabel = formatVatSummaryLabel({
2735
+ treatment: treatment ?? "standard",
2736
+ taxRate
2737
+ });
2738
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-tax")]: "" }, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2739
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: defaultLabel }),
2740
+ " ",
2741
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { ...{ [attr(prefix, "summary-tax-amount")]: "" }, children: taxFormatted })
2742
+ ] }) });
2743
+ });
2744
+ const Total = (0, import_react13.forwardRef)(function TaxSummaryTotal({ asChild, children, ...rest }, forwardedRef) {
2745
+ const ctx = useCtx("Summary.Total");
2746
+ const { totalFormatted } = useSummaryAmounts(useCtx, "Summary.Total");
2747
+ if (!ctx.isBusiness) return null;
2748
+ const Comp = asChild ? Slot : "span";
2749
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-total")]: "" }, ...rest, children: children ?? totalFormatted });
2750
+ });
2751
+ const TaxNote = (0, import_react13.forwardRef)(function TaxSummaryTaxNote({ asChild, children, ...rest }, forwardedRef) {
2752
+ const ctx = useCtx("Summary.TaxNote");
2753
+ const { treatment } = useSummaryAmounts(useCtx, "Summary.TaxNote");
2754
+ if (!ctx.isBusiness) return null;
2755
+ if (!treatment || treatment === "standard") return null;
2756
+ const Comp = asChild ? Slot : "p";
2757
+ const defaultNote = treatment === "reverse_charge" ? REVERSE_CHARGE_NOTE : treatment === "not_collecting" || treatment === "not_supported" ? TAX_NOT_COLLECTED_NOTE : null;
2758
+ if (!defaultNote && !children) return null;
2759
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-tax-note")]: "" }, ...rest, children: children ?? defaultNote });
2760
+ });
2761
+ const Rows = (0, import_react13.forwardRef)(function TaxSummaryRows({ asChild, children, ...rest }, forwardedRef) {
2762
+ const ctx = useCtx("Summary.Rows");
2763
+ const { taxRate, treatment, taxFormatted } = useSummaryAmounts(useCtx, "Summary.Rows");
2764
+ if (!ctx.isBusiness) return null;
2765
+ const showTaxRow = shouldShowTaxRow(treatment);
2766
+ const vatLabel = formatVatSummaryLabel({
2767
+ treatment: treatment ?? "standard",
2768
+ taxRate
2769
+ });
2770
+ const content = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("dl", { className: "solvapay-tax-summary-rows", children: [
2771
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "solvapay-tax-summary-row", children: [
2772
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: formatSubtotalLabel(treatment) }),
2773
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Subtotal, {}) })
2774
+ ] }),
2775
+ showTaxRow ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "solvapay-tax-summary-row", children: [
2776
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: vatLabel }),
2777
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { ...{ [attr(prefix, "summary-tax-amount")]: "" }, children: taxFormatted }) })
2778
+ ] }) : null,
2779
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "solvapay-tax-summary-row solvapay-tax-summary-row--total", children: [
2780
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dt", { children: "Total" }),
2781
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Total, {}) })
2782
+ ] }),
2783
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TaxNote, {}),
2784
+ children
2785
+ ] });
2786
+ if (asChild) {
2787
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Slot, { ref: forwardedRef, ...rest, children: content });
2788
+ }
2789
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("section", { ref: forwardedRef, ...{ [attr(prefix, "summary-rows")]: "" }, ...rest, children: content });
2790
+ });
2791
+ return {
2792
+ Root: Root14,
2793
+ Subtotal,
2794
+ Tax,
2795
+ Total,
2796
+ TaxNote,
2797
+ Rows
2798
+ };
2799
+ }
2800
+
2801
+ // src/primitives/CheckoutSummary.tsx
2802
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2803
+ var CheckoutSummaryContext = (0, import_react14.createContext)(null);
2513
2804
  function useCheckoutSummaryContext(part) {
2514
- const ctx = (0, import_react13.useContext)(CheckoutSummaryContext);
2805
+ const ctx = (0, import_react14.useContext)(CheckoutSummaryContext);
2515
2806
  if (!ctx) {
2516
2807
  throw new Error(
2517
2808
  `CheckoutSummary.${part} must be rendered inside <CheckoutSummary.Root>.`
@@ -2519,8 +2810,8 @@ function useCheckoutSummaryContext(part) {
2519
2810
  }
2520
2811
  return ctx;
2521
2812
  }
2522
- var Root = (0, import_react13.forwardRef)(function CheckoutSummaryRoot({ planRef, productRef, taxBreakdown = null, baseAmountMinor = 0, asChild, children, ...rest }, forwardedRef) {
2523
- const solva = (0, import_react13.useContext)(SolvaPayContext);
2813
+ var Root = (0, import_react14.forwardRef)(function CheckoutSummaryRoot({ planRef, productRef, taxBreakdown = null, baseAmountMinor = 0, asChild, children, ...rest }, forwardedRef) {
2814
+ const solva = (0, import_react14.useContext)(SolvaPayContext);
2524
2815
  if (!solva) throw new MissingProviderError("CheckoutSummary");
2525
2816
  const locale = useLocale();
2526
2817
  const copy = useCopy();
@@ -2533,7 +2824,7 @@ var Root = (0, import_react13.forwardRef)(function CheckoutSummaryRoot({ planRef
2533
2824
  });
2534
2825
  const { product, loading: productLoading } = useProduct(resolvedProductRef);
2535
2826
  const loading = planLoading || productLoading;
2536
- const priceFormatted = (0, import_react13.useMemo)(() => {
2827
+ const priceFormatted = (0, import_react14.useMemo)(() => {
2537
2828
  const price = plan?.price ?? 0;
2538
2829
  const currency = plan?.currency ?? "usd";
2539
2830
  return formatPrice(price, currency, {
@@ -2543,7 +2834,7 @@ var Root = (0, import_react13.forwardRef)(function CheckoutSummaryRoot({ planRef
2543
2834
  free: copy.interval.free
2544
2835
  });
2545
2836
  }, [plan, locale, copy.interval.free]);
2546
- const trialBanner = (0, import_react13.useMemo)(() => {
2837
+ const trialBanner = (0, import_react14.useMemo)(() => {
2547
2838
  const trialDays = plan?.trialDays;
2548
2839
  if (!trialDays || trialDays <= 0) return null;
2549
2840
  return interpolate(copy.interval.trial, { trialDays });
@@ -2552,10 +2843,10 @@ var Root = (0, import_react13.forwardRef)(function CheckoutSummaryRoot({ planRef
2552
2843
  const subtotalMinor = taxBreakdown?.subtotal ?? baseAmountMinor;
2553
2844
  const taxMinor = taxBreakdown?.taxAmount ?? 0;
2554
2845
  const totalMinor = taxBreakdown?.total ?? baseAmountMinor;
2555
- const subtotalFormatted = formatPrice(subtotalMinor, taxCurrency, { locale });
2556
- const taxFormatted = formatPrice(taxMinor, taxCurrency, { locale });
2557
- const totalFormatted = formatPrice(totalMinor, taxCurrency, { locale });
2558
- const ctx = (0, import_react13.useMemo)(
2846
+ const subtotalFormatted = formatPrice(subtotalMinor, taxCurrency, { locale, free: "" });
2847
+ const taxFormatted = formatPrice(taxMinor, taxCurrency, { locale, free: "" });
2848
+ const totalFormatted = formatPrice(totalMinor, taxCurrency, { locale, free: "" });
2849
+ const ctx = (0, import_react14.useMemo)(
2559
2850
  () => ({
2560
2851
  plan,
2561
2852
  product,
@@ -2582,77 +2873,78 @@ var Root = (0, import_react13.forwardRef)(function CheckoutSummaryRoot({ planRef
2582
2873
  ]
2583
2874
  );
2584
2875
  const Comp = asChild ? Slot : "section";
2585
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary": "", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CheckoutSummaryContext.Provider, { value: ctx, children }) });
2876
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary": "", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummaryContext.Provider, { value: ctx, children }) });
2586
2877
  });
2587
- var ProductSlot = (0, import_react13.forwardRef)(function CheckoutSummaryProduct({ asChild, children, ...rest }, forwardedRef) {
2878
+ var ProductSlot = (0, import_react14.forwardRef)(function CheckoutSummaryProduct({ asChild, children, ...rest }, forwardedRef) {
2588
2879
  const ctx = useCheckoutSummaryContext("Product");
2589
2880
  const name = ctx.product?.name;
2590
2881
  if (!name) return null;
2591
2882
  const Comp = asChild ? Slot : "span";
2592
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-product": "", ...rest, children: children ?? name });
2883
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-product": "", ...rest, children: children ?? name });
2593
2884
  });
2594
- var PlanSlot = (0, import_react13.forwardRef)(function CheckoutSummaryPlan({ asChild, children, ...rest }, forwardedRef) {
2885
+ var PlanSlot = (0, import_react14.forwardRef)(function CheckoutSummaryPlan({ asChild, children, ...rest }, forwardedRef) {
2595
2886
  const ctx = useCheckoutSummaryContext("Plan");
2596
2887
  const name = ctx.plan?.name;
2597
2888
  if (!name) return null;
2598
2889
  const Comp = asChild ? Slot : "span";
2599
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-plan": "", ...rest, children: children ?? name });
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-plan": "", ...rest, children: children ?? name });
2600
2891
  });
2601
- var TaxNoteSlot = (0, import_react13.forwardRef)(
2892
+ var TaxNoteSlot = (0, import_react14.forwardRef)(
2602
2893
  function CheckoutSummaryTaxNote({ asChild, children, ...rest }, forwardedRef) {
2603
2894
  const ctx = useCheckoutSummaryContext("TaxNote");
2604
2895
  if (ctx.taxBreakdown) return null;
2605
2896
  const Comp = asChild ? Slot : "p";
2606
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax-note": "", ...rest, children: children ?? "Taxes calculated at checkout" });
2897
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax-note": "", ...rest, children: children ?? "Taxes calculated at checkout" });
2607
2898
  }
2608
2899
  );
2609
- var SubtotalSlot = (0, import_react13.forwardRef)(function CheckoutSummarySubtotal({ asChild, children, ...rest }, forwardedRef) {
2900
+ var SubtotalSlot = (0, import_react14.forwardRef)(function CheckoutSummarySubtotal({ asChild, children, ...rest }, forwardedRef) {
2610
2901
  const ctx = useCheckoutSummaryContext("Subtotal");
2611
2902
  if (!ctx.taxBreakdown) return null;
2612
2903
  const Comp = asChild ? Slot : "span";
2613
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-subtotal": "", ...rest, children: children ?? ctx.subtotalFormatted });
2904
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-subtotal": "", ...rest, children: children ?? ctx.subtotalFormatted });
2614
2905
  });
2615
- var TaxSlot = (0, import_react13.forwardRef)(function CheckoutSummaryTax({ asChild, children, ...rest }, forwardedRef) {
2906
+ var TaxSlot = (0, import_react14.forwardRef)(function CheckoutSummaryTax({ asChild, children, ...rest }, forwardedRef) {
2616
2907
  const ctx = useCheckoutSummaryContext("Tax");
2617
2908
  if (!ctx.taxBreakdown) return null;
2618
- const Comp = asChild ? Slot : "span";
2619
2909
  const { taxRate, treatment } = ctx.taxBreakdown;
2620
- const defaultLabel = treatment === "reverse_charge" ? `VAT reverse charge (${ctx.taxFormatted})` : taxRate != null ? `Tax (${Math.round(taxRate * 100)}%)` : "Tax";
2621
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax": "", ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2622
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: defaultLabel }),
2910
+ if (!shouldShowTaxRow(treatment)) return null;
2911
+ const Comp = asChild ? Slot : "span";
2912
+ const defaultLabel = formatVatSummaryLabel({ treatment, taxRate: taxRate ?? 0 });
2913
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax": "", ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2914
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: defaultLabel }),
2623
2915
  " ",
2624
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "data-solvapay-checkout-summary-tax-amount": "", children: ctx.taxFormatted })
2916
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-solvapay-checkout-summary-tax-amount": "", children: ctx.taxFormatted })
2625
2917
  ] }) });
2626
2918
  });
2627
- var TotalSlot = (0, import_react13.forwardRef)(function CheckoutSummaryTotal({ asChild, children, ...rest }, forwardedRef) {
2919
+ var TotalSlot = (0, import_react14.forwardRef)(function CheckoutSummaryTotal({ asChild, children, ...rest }, forwardedRef) {
2628
2920
  const ctx = useCheckoutSummaryContext("Total");
2629
2921
  if (!ctx.taxBreakdown) return null;
2630
2922
  const Comp = asChild ? Slot : "span";
2631
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-total": "", ...rest, children: children ?? ctx.totalFormatted });
2923
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-total": "", ...rest, children: children ?? ctx.totalFormatted });
2632
2924
  });
2633
- var TaxTreatmentNoteSlot = (0, import_react13.forwardRef)(
2925
+ var TaxTreatmentNoteSlot = (0, import_react14.forwardRef)(
2634
2926
  function CheckoutSummaryTaxTreatmentNote({ asChild, children, ...rest }, forwardedRef) {
2635
2927
  const ctx = useCheckoutSummaryContext("TaxTreatmentNote");
2636
2928
  const treatment = ctx.taxBreakdown?.treatment;
2637
2929
  if (!treatment || treatment === "standard") return null;
2638
2930
  const Comp = asChild ? Slot : "p";
2639
- const defaultNote = treatment === "reverse_charge" ? "VAT reverse charge applies \u2014 you are responsible for reporting VAT in your jurisdiction." : treatment === "not_collecting" ? "Tax is not collected on this purchase." : null;
2931
+ const defaultNote = treatment === "reverse_charge" ? REVERSE_CHARGE_NOTE : treatment === "not_collecting" || treatment === "not_supported" ? TAX_NOT_COLLECTED_NOTE : null;
2640
2932
  if (!defaultNote && !children) return null;
2641
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax-treatment-note": "", ...rest, children: children ?? defaultNote });
2933
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-tax-treatment-note": "", ...rest, children: children ?? defaultNote });
2642
2934
  }
2643
2935
  );
2644
- var PriceSlot = (0, import_react13.forwardRef)(function CheckoutSummaryPrice({ asChild, children, ...rest }, forwardedRef) {
2936
+ var PriceSlot = (0, import_react14.forwardRef)(function CheckoutSummaryPrice({ asChild, children, ...rest }, forwardedRef) {
2645
2937
  const ctx = useCheckoutSummaryContext("Price");
2646
2938
  if (ctx.taxBreakdown) return null;
2647
2939
  const Comp = asChild ? Slot : "span";
2648
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-price": "", ...rest, children: children ?? ctx.priceFormatted });
2940
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-price": "", ...rest, children: children ?? ctx.priceFormatted });
2649
2941
  });
2650
- var TrialSlot = (0, import_react13.forwardRef)(
2942
+ var TrialSlot = (0, import_react14.forwardRef)(
2651
2943
  function CheckoutSummaryTrial({ asChild, children, ...rest }, forwardedRef) {
2652
2944
  const ctx = useCheckoutSummaryContext("Trial");
2653
2945
  if (!ctx.trialBanner || ctx.taxBreakdown) return null;
2654
2946
  const Comp = asChild ? Slot : "p";
2655
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-trial": "", ...rest, children: children ?? ctx.trialBanner });
2947
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Comp, { ref: forwardedRef, "data-solvapay-checkout-summary-trial": "", ...rest, children: children ?? ctx.trialBanner });
2656
2948
  }
2657
2949
  );
2658
2950
  var CheckoutSummary = {
@@ -2669,7 +2961,7 @@ var CheckoutSummary = {
2669
2961
  };
2670
2962
 
2671
2963
  // src/components/CheckoutSummary.tsx
2672
- var import_jsx_runtime8 = require("react/jsx-runtime");
2964
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2673
2965
  var CheckoutSummary2 = ({
2674
2966
  planRef,
2675
2967
  productRef,
@@ -2681,7 +2973,7 @@ var CheckoutSummary2 = ({
2681
2973
  }) => {
2682
2974
  const rootClass = ["solvapay-checkout-summary", className].filter(Boolean).join(" ");
2683
2975
  const hasTax = taxBreakdown != null;
2684
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2976
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2685
2977
  CheckoutSummary.Root,
2686
2978
  {
2687
2979
  planRef,
@@ -2690,25 +2982,25 @@ var CheckoutSummary2 = ({
2690
2982
  baseAmountMinor,
2691
2983
  className: rootClass,
2692
2984
  children: [
2693
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Product, { className: "solvapay-checkout-summary-product" }),
2694
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2695
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Plan, { className: "solvapay-checkout-summary-plan" }),
2696
- !hasTax && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Price, { className: "solvapay-checkout-summary-price" })
2985
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Product, { className: "solvapay-checkout-summary-product" }),
2986
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2987
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Plan, { className: "solvapay-checkout-summary-plan" }),
2988
+ !hasTax && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Price, { className: "solvapay-checkout-summary-price" })
2697
2989
  ] }),
2698
- hasTax ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2699
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2700
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Subtotal" }),
2701
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Subtotal, { className: "solvapay-checkout-summary-subtotal" })
2990
+ hasTax ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2991
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2992
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Subtotal" }),
2993
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Subtotal, { className: "solvapay-checkout-summary-subtotal" })
2702
2994
  ] }),
2703
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "solvapay-checkout-summary-row", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Tax, { className: "solvapay-checkout-summary-tax" }) }),
2704
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2705
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Total" }),
2706
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Total, { className: "solvapay-checkout-summary-total" })
2995
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "solvapay-checkout-summary-row", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Tax, { className: "solvapay-checkout-summary-tax" }) }),
2996
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "solvapay-checkout-summary-row", children: [
2997
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Total" }),
2998
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Total, { className: "solvapay-checkout-summary-total" })
2707
2999
  ] }),
2708
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.TaxTreatmentNote, { className: "solvapay-checkout-summary-tax-treatment-note" })
2709
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2710
- showTrial && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.Trial, { className: "solvapay-checkout-summary-trial" }),
2711
- showTaxNote && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckoutSummary.TaxNote, { className: "solvapay-checkout-summary-tax-note" })
3000
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.TaxTreatmentNote, { className: "solvapay-checkout-summary-tax-treatment-note" })
3001
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
3002
+ showTrial && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.Trial, { className: "solvapay-checkout-summary-trial" }),
3003
+ showTaxNote && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckoutSummary.TaxNote, { className: "solvapay-checkout-summary-tax-note" })
2712
3004
  ] })
2713
3005
  ]
2714
3006
  }
@@ -2716,10 +3008,10 @@ var CheckoutSummary2 = ({
2716
3008
  };
2717
3009
 
2718
3010
  // src/primitives/MandateText.tsx
2719
- var import_react15 = require("react");
3011
+ var import_react16 = require("react");
2720
3012
 
2721
3013
  // src/hooks/useMerchant.ts
2722
- var import_react14 = require("react");
3014
+ var import_react15 = require("react");
2723
3015
  var merchantCache = /* @__PURE__ */ new Map();
2724
3016
  var CACHE_DURATION5 = 5 * 60 * 1e3;
2725
3017
  function cacheKeyFor2(config) {
@@ -2733,15 +3025,15 @@ async function fetchMerchant(config) {
2733
3025
  function useMerchant() {
2734
3026
  const { _config } = useSolvaPay();
2735
3027
  const key = cacheKeyFor2(_config);
2736
- const [merchant, setMerchant] = (0, import_react14.useState)(
3028
+ const [merchant, setMerchant] = (0, import_react15.useState)(
2737
3029
  () => merchantCache.get(key)?.merchant ?? null
2738
3030
  );
2739
- const [loading, setLoading] = (0, import_react14.useState)(() => {
3031
+ const [loading, setLoading] = (0, import_react15.useState)(() => {
2740
3032
  const cached = merchantCache.get(key);
2741
3033
  return !cached || !cached.merchant && !cached.promise;
2742
3034
  });
2743
- const [error, setError] = (0, import_react14.useState)(null);
2744
- const load = (0, import_react14.useCallback)(
3035
+ const [error, setError] = (0, import_react15.useState)(null);
3036
+ const load = (0, import_react15.useCallback)(
2745
3037
  async (force = false) => {
2746
3038
  const cached = merchantCache.get(key);
2747
3039
  const now = Date.now();
@@ -2795,7 +3087,7 @@ function useMerchant() {
2795
3087
  },
2796
3088
  [_config, key]
2797
3089
  );
2798
- (0, import_react14.useEffect)(() => {
3090
+ (0, import_react15.useEffect)(() => {
2799
3091
  load();
2800
3092
  }, [load]);
2801
3093
  return {
@@ -2824,8 +3116,8 @@ function deriveVariant(plan, mode) {
2824
3116
  }
2825
3117
 
2826
3118
  // src/primitives/MandateText.tsx
2827
- var import_jsx_runtime9 = require("react/jsx-runtime");
2828
- var MandateText = (0, import_react15.forwardRef)(
3119
+ var import_jsx_runtime10 = require("react/jsx-runtime");
3120
+ var MandateText = (0, import_react16.forwardRef)(
2829
3121
  function MandateText2({
2830
3122
  planRef,
2831
3123
  productRef,
@@ -2837,7 +3129,7 @@ var MandateText = (0, import_react15.forwardRef)(
2837
3129
  children,
2838
3130
  ...rest
2839
3131
  }, forwardedRef) {
2840
- const solva = (0, import_react15.useContext)(SolvaPayContext);
3132
+ const solva = (0, import_react16.useContext)(SolvaPayContext);
2841
3133
  if (!solva) throw new MissingProviderError("MandateText");
2842
3134
  const locale = useLocale();
2843
3135
  const copy = useCopy();
@@ -2854,7 +3146,7 @@ var MandateText = (0, import_react15.forwardRef)(
2854
3146
  locale,
2855
3147
  free: copy.interval.free
2856
3148
  });
2857
- const ctx = (0, import_react15.useMemo)(
3149
+ const ctx = (0, import_react16.useMemo)(
2858
3150
  () => ({
2859
3151
  merchant: {
2860
3152
  legalName: merchant?.legalName ?? merchant?.displayName ?? "",
@@ -2881,7 +3173,7 @@ var MandateText = (0, import_react15.forwardRef)(
2881
3173
  const text = typeof template === "function" ? template(ctx) : template;
2882
3174
  if (!text) return null;
2883
3175
  const Comp = asChild ? Slot : "p";
2884
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3176
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2885
3177
  Comp,
2886
3178
  {
2887
3179
  ref: forwardedRef,
@@ -2903,7 +3195,7 @@ function linkifyMandateText(text, merchant, copy) {
2903
3195
  return text.split(pattern).map((part, i) => {
2904
3196
  const match = entries.find((e) => e.url === part);
2905
3197
  if (!match) return part;
2906
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3198
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2907
3199
  "a",
2908
3200
  {
2909
3201
  href: match.url,
@@ -2921,11 +3213,11 @@ function escapeRegExp(value) {
2921
3213
  }
2922
3214
 
2923
3215
  // src/components/Spinner.tsx
2924
- var import_jsx_runtime10 = require("react/jsx-runtime");
3216
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2925
3217
  var SIZE_PX = { sm: 16, md: 20, lg: 24 };
2926
3218
  var Spinner = ({ className, size = "md" }) => {
2927
3219
  const px = SIZE_PX[size];
2928
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3220
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2929
3221
  "svg",
2930
3222
  {
2931
3223
  "data-solvapay-spinner": "",
@@ -2936,7 +3228,7 @@ var Spinner = ({ className, size = "md" }) => {
2936
3228
  fill: "none",
2937
3229
  "aria-hidden": "true",
2938
3230
  children: [
2939
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3231
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2940
3232
  "circle",
2941
3233
  {
2942
3234
  cx: "12",
@@ -2947,7 +3239,7 @@ var Spinner = ({ className, size = "md" }) => {
2947
3239
  strokeOpacity: "0.25"
2948
3240
  }
2949
3241
  ),
2950
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3242
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2951
3243
  "path",
2952
3244
  {
2953
3245
  fill: "currentColor",
@@ -3160,295 +3452,6 @@ function resolveCta(input) {
3160
3452
  // src/hooks/useBusinessDetailsAttach.ts
3161
3453
  var import_react17 = require("react");
3162
3454
  var import_core3 = require("@solvapay/core");
3163
-
3164
- // src/components/businessCheckoutParts.tsx
3165
- var import_react16 = require("react");
3166
- var import_core2 = require("@solvapay/core");
3167
- var import_jsx_runtime11 = require("react/jsx-runtime");
3168
- function mapBusinessFieldErrors(input) {
3169
- const result = (0, import_core2.validateBusinessDetails)(input);
3170
- if (result.success) return {};
3171
- const errors = {};
3172
- for (const issue of result.error.issues) {
3173
- const key = issue.path[0];
3174
- if (typeof key === "string" && isBusinessDetailsKey(key) && !errors[key]) {
3175
- errors[key] = issue.message;
3176
- }
3177
- }
3178
- return errors;
3179
- }
3180
- function isBusinessDetailsKey(key) {
3181
- return key === "isBusiness" || key === "businessName" || key === "country" || key === "customerCountry" || key === "customerName" || key === "taxId" || key === "taxIdType";
3182
- }
3183
- function attr(prefix, suffix) {
3184
- return `data-solvapay-${prefix}-${suffix}`;
3185
- }
3186
- var SUPPORTED_BUSINESS_COUNTRIES_SET = new Set(import_core2.SUPPORTED_BUSINESS_COUNTRIES);
3187
- function isSupportedBusinessCountry(value) {
3188
- return SUPPORTED_BUSINESS_COUNTRIES_SET.has(value);
3189
- }
3190
- function resolveTaxIdLabel(country) {
3191
- if (country && isSupportedBusinessCountry(country)) {
3192
- return (0, import_core2.getTaxIdFieldLabel)(country);
3193
- }
3194
- return "Tax ID";
3195
- }
3196
- function resolveTaxIdPlaceholder(country) {
3197
- if (country && isSupportedBusinessCountry(country)) {
3198
- return (0, import_core2.getTaxIdExample)(country);
3199
- }
3200
- return "Enter tax ID";
3201
- }
3202
- function resolveTaxIdHelperText(country) {
3203
- if (country && isSupportedBusinessCountry(country)) {
3204
- return (0, import_core2.getTaxIdHelperText)(country);
3205
- }
3206
- return "";
3207
- }
3208
- function formatVatSummaryLabel(breakdown) {
3209
- if (breakdown.treatment === "reverse_charge") {
3210
- return "VAT (reverse charge)";
3211
- }
3212
- if (breakdown.taxRate > 0) {
3213
- const ratePercent = breakdown.taxRate <= 1 ? Math.round(breakdown.taxRate * 100) : breakdown.taxRate;
3214
- return breakdown.inclusive ? `VAT (${ratePercent}%, incl.)` : `VAT (${ratePercent}%)`;
3215
- }
3216
- return "VAT";
3217
- }
3218
- function shouldShowTaxRow(treatment, taxRate) {
3219
- if (treatment === "not_collecting") return false;
3220
- if (treatment === "reverse_charge") return true;
3221
- return taxRate > 0;
3222
- }
3223
- function createBusinessDetailsParts(useCtx, prefix) {
3224
- const Root14 = (0, import_react16.forwardRef)(function BusinessDetailsRoot({ asChild, children, ...rest }, forwardedRef) {
3225
- useCtx("BusinessDetails");
3226
- const Comp = asChild ? Slot : "section";
3227
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "business-details")]: "" }, ...rest, children });
3228
- });
3229
- const Toggle = (0, import_react16.forwardRef)(function BusinessDetailsToggle({ asChild, onChange, ...rest }, forwardedRef) {
3230
- const ctx = useCtx("BusinessDetails.Toggle");
3231
- const commonProps = {
3232
- [attr(prefix, "business-details-toggle")]: "",
3233
- type: "checkbox",
3234
- checked: ctx.businessDetails.isBusiness,
3235
- onChange: composeEventHandlers(onChange, (e) => {
3236
- ctx.setBusinessDetails({ isBusiness: e.target.checked });
3237
- }),
3238
- ...rest
3239
- };
3240
- if (asChild) {
3241
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...commonProps });
3242
- }
3243
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { ref: forwardedRef, ...commonProps });
3244
- });
3245
- const BusinessName = (0, import_react16.forwardRef)(
3246
- function BusinessDetailsBusinessName({ asChild, onChange, ...rest }, forwardedRef) {
3247
- const ctx = useCtx("BusinessDetails.BusinessName");
3248
- if (!ctx.businessDetails.isBusiness) return null;
3249
- const commonProps = {
3250
- [attr(prefix, "business-details-name")]: "",
3251
- type: "text",
3252
- value: ctx.businessDetails.businessName ?? "",
3253
- "aria-invalid": ctx.fieldErrors.businessName ? true : void 0,
3254
- onChange: composeEventHandlers(onChange, (e) => {
3255
- ctx.setBusinessDetails({ businessName: e.target.value });
3256
- }),
3257
- ...rest
3258
- };
3259
- if (asChild) {
3260
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...commonProps });
3261
- }
3262
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { ref: forwardedRef, ...commonProps });
3263
- }
3264
- );
3265
- const Country = (0, import_react16.forwardRef)(function BusinessDetailsCountry({ asChild, onChange, children, ...rest }, forwardedRef) {
3266
- const ctx = useCtx("BusinessDetails.Country");
3267
- if (!ctx.businessDetails.isBusiness) return null;
3268
- const commonProps = {
3269
- [attr(prefix, "business-details-country")]: "",
3270
- value: ctx.businessDetails.country ?? "",
3271
- "aria-invalid": ctx.fieldErrors.country ? true : void 0,
3272
- onChange: composeEventHandlers(onChange, (e) => {
3273
- ctx.setBusinessDetails({ country: e.target.value });
3274
- }),
3275
- ...rest
3276
- };
3277
- const defaultOptions = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3278
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "", children: "Select country" }),
3279
- import_core2.BUSINESS_COUNTRY_OPTIONS.map(({ value, label }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value, children: label }, value))
3280
- ] });
3281
- if (asChild) {
3282
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...commonProps, children: children ?? defaultOptions });
3283
- }
3284
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("select", { ref: forwardedRef, ...commonProps, children: children ?? defaultOptions });
3285
- });
3286
- const TaxId = (0, import_react16.forwardRef)(function BusinessDetailsTaxId({ asChild, onChange, ...rest }, forwardedRef) {
3287
- const ctx = useCtx("BusinessDetails.TaxId");
3288
- if (!ctx.businessDetails.isBusiness) return null;
3289
- const commonProps = {
3290
- [attr(prefix, "business-details-tax-id")]: "",
3291
- type: "text",
3292
- value: ctx.businessDetails.taxId ?? "",
3293
- "aria-invalid": ctx.fieldErrors.taxId ? true : void 0,
3294
- onChange: composeEventHandlers(onChange, (e) => {
3295
- ctx.setBusinessDetails({ taxId: e.target.value });
3296
- }),
3297
- ...rest
3298
- };
3299
- if (asChild) {
3300
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...commonProps });
3301
- }
3302
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { ref: forwardedRef, ...commonProps });
3303
- });
3304
- const Fields2 = (0, import_react16.forwardRef)(function BusinessDetailsFields({ asChild, children, ...rest }, forwardedRef) {
3305
- const ctx = useCtx("BusinessDetails.Fields");
3306
- const country = ctx.businessDetails.country ?? "";
3307
- const taxIdLabel = resolveTaxIdLabel(country);
3308
- const taxIdPlaceholder = resolveTaxIdPlaceholder(country);
3309
- const taxIdHelperText = resolveTaxIdHelperText(country);
3310
- const content = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3311
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "solvapay-checkout-business-toggle", children: [
3312
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Toggle, {}),
3313
- "I'm purchasing as a business"
3314
- ] }),
3315
- ctx.businessDetails.isBusiness ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("fieldset", { className: "solvapay-business-fields", children: [
3316
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "solvapay-business-field", children: [
3317
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "solvapay-business-field-label", children: "Business name" }),
3318
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(BusinessName, { placeholder: "Acme GmbH" })
3319
- ] }),
3320
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "solvapay-business-field", children: [
3321
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "solvapay-business-field-label", children: "Country" }),
3322
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Country, {})
3323
- ] }),
3324
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "solvapay-business-field", children: [
3325
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "solvapay-business-field-label", children: taxIdLabel }),
3326
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TaxId, { placeholder: taxIdPlaceholder }),
3327
- taxIdHelperText ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "solvapay-business-field-hint", children: taxIdHelperText }) : null
3328
- ] })
3329
- ] }) : null,
3330
- children
3331
- ] });
3332
- if (asChild) {
3333
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...rest, children: content });
3334
- }
3335
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("section", { ref: forwardedRef, ...{ [attr(prefix, "business-details-fields")]: "" }, ...rest, children: content });
3336
- });
3337
- return {
3338
- Root: Root14,
3339
- Toggle,
3340
- BusinessName,
3341
- Country,
3342
- TaxId,
3343
- Fields: Fields2
3344
- };
3345
- }
3346
- function useSummaryAmounts(useCtx, part) {
3347
- const ctx = useCtx(part);
3348
- const locale = useLocale();
3349
- const currency = (ctx.taxBreakdown?.currency ?? ctx.currency ?? "usd").toLowerCase();
3350
- const subtotalMinor = ctx.taxBreakdown?.subtotal ?? ctx.baseAmountMinor;
3351
- const taxMinor = ctx.taxBreakdown?.taxAmount ?? 0;
3352
- const totalMinor = ctx.taxBreakdown?.total ?? ctx.baseAmountMinor;
3353
- return {
3354
- subtotalFormatted: formatPrice(subtotalMinor, currency, { locale }),
3355
- taxFormatted: formatPrice(taxMinor, currency, { locale }),
3356
- totalFormatted: formatPrice(totalMinor, currency, { locale }),
3357
- taxRate: ctx.taxBreakdown?.taxRate ?? 0,
3358
- treatment: ctx.taxBreakdown?.treatment ?? null,
3359
- inclusive: ctx.taxBreakdown?.inclusive ?? false,
3360
- attaching: ctx.businessDetailsAttaching
3361
- };
3362
- }
3363
- function createTaxSummaryParts(useCtx, prefix) {
3364
- const Root14 = (0, import_react16.forwardRef)(function TaxSummaryRoot({ asChild, children, ...rest }, forwardedRef) {
3365
- const ctx = useCtx("Summary");
3366
- if (!ctx.isBusiness) return null;
3367
- const Comp = asChild ? Slot : "section";
3368
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary")]: "" }, ...rest, children });
3369
- });
3370
- const Subtotal = (0, import_react16.forwardRef)(function TaxSummarySubtotal({ asChild, children, ...rest }, forwardedRef) {
3371
- const ctx = useCtx("Summary.Subtotal");
3372
- const { subtotalFormatted } = useSummaryAmounts(useCtx, "Summary.Subtotal");
3373
- if (!ctx.isBusiness) return null;
3374
- const Comp = asChild ? Slot : "span";
3375
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-subtotal")]: "" }, ...rest, children: children ?? subtotalFormatted });
3376
- });
3377
- const Tax = (0, import_react16.forwardRef)(function TaxSummaryTax({ asChild, children, ...rest }, forwardedRef) {
3378
- const ctx = useCtx("Summary.Tax");
3379
- const { taxFormatted, taxRate, treatment, inclusive } = useSummaryAmounts(useCtx, "Summary.Tax");
3380
- if (!ctx.isBusiness) return null;
3381
- const Comp = asChild ? Slot : "span";
3382
- const defaultLabel = formatVatSummaryLabel({
3383
- treatment: treatment ?? "standard",
3384
- taxRate,
3385
- inclusive
3386
- });
3387
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-tax")]: "" }, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3388
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: defaultLabel }),
3389
- " ",
3390
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { ...{ [attr(prefix, "summary-tax-amount")]: "" }, children: taxFormatted })
3391
- ] }) });
3392
- });
3393
- const Total = (0, import_react16.forwardRef)(function TaxSummaryTotal({ asChild, children, ...rest }, forwardedRef) {
3394
- const ctx = useCtx("Summary.Total");
3395
- const { totalFormatted } = useSummaryAmounts(useCtx, "Summary.Total");
3396
- if (!ctx.isBusiness) return null;
3397
- const Comp = asChild ? Slot : "span";
3398
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-total")]: "" }, ...rest, children: children ?? totalFormatted });
3399
- });
3400
- const TaxNote = (0, import_react16.forwardRef)(function TaxSummaryTaxNote({ asChild, children, ...rest }, forwardedRef) {
3401
- const ctx = useCtx("Summary.TaxNote");
3402
- const { treatment } = useSummaryAmounts(useCtx, "Summary.TaxNote");
3403
- if (!ctx.isBusiness) return null;
3404
- if (!treatment || treatment === "standard") return null;
3405
- const Comp = asChild ? Slot : "p";
3406
- const defaultNote = treatment === "reverse_charge" ? "VAT reverse charge applies \u2014 you are responsible for reporting VAT in your jurisdiction." : treatment === "not_collecting" ? "Tax is not collected on this purchase." : null;
3407
- if (!defaultNote && !children) return null;
3408
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Comp, { ref: forwardedRef, ...{ [attr(prefix, "summary-tax-note")]: "" }, ...rest, children: children ?? defaultNote });
3409
- });
3410
- const Rows = (0, import_react16.forwardRef)(function TaxSummaryRows({ asChild, children, ...rest }, forwardedRef) {
3411
- const ctx = useCtx("Summary.Rows");
3412
- const { taxRate, treatment, inclusive, taxFormatted } = useSummaryAmounts(useCtx, "Summary.Rows");
3413
- if (!ctx.isBusiness) return null;
3414
- const showTaxRow = shouldShowTaxRow(treatment, taxRate);
3415
- const vatLabel = formatVatSummaryLabel({
3416
- treatment: treatment ?? "standard",
3417
- taxRate,
3418
- inclusive
3419
- });
3420
- const content = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("dl", { className: "solvapay-tax-summary-rows", children: [
3421
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "solvapay-tax-summary-row", children: [
3422
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { children: "Subtotal" }),
3423
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Subtotal, {}) })
3424
- ] }),
3425
- showTaxRow ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "solvapay-tax-summary-row", children: [
3426
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { children: vatLabel }),
3427
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { ...{ [attr(prefix, "summary-tax-amount")]: "" }, children: taxFormatted }) })
3428
- ] }) : null,
3429
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "solvapay-tax-summary-row solvapay-tax-summary-row--total", children: [
3430
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dt", { children: "Total" }),
3431
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Total, {}) })
3432
- ] }),
3433
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TaxNote, {}),
3434
- children
3435
- ] });
3436
- if (asChild) {
3437
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Slot, { ref: forwardedRef, ...rest, children: content });
3438
- }
3439
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("section", { ref: forwardedRef, ...{ [attr(prefix, "summary-rows")]: "" }, ...rest, children: content });
3440
- });
3441
- return {
3442
- Root: Root14,
3443
- Subtotal,
3444
- Tax,
3445
- Total,
3446
- TaxNote,
3447
- Rows
3448
- };
3449
- }
3450
-
3451
- // src/hooks/useBusinessDetailsAttach.ts
3452
3455
  var defaultBusinessDetails = { isBusiness: false };
3453
3456
  function useBusinessDetailsAttach(options) {
3454
3457
  const {
@@ -10218,15 +10221,14 @@ function planBillingInterval(plan) {
10218
10221
  return (0, import_core10.billingCycle)(plan)?.interval ?? null;
10219
10222
  }
10220
10223
  function formatPaygRate(plan, locale, balance) {
10224
+ const rate = (0, import_core10.usageRate)(plan);
10225
+ if (!rate || !(rate.amountMinor > 0)) return null;
10226
+ const prefix = rate.tiered ? "from " : "";
10221
10227
  const credits = (0, import_core10.creditsPerUnitFromBalance)(plan, balance);
10222
10228
  if (credits != null) {
10223
- return `${credits.toLocaleString(locale)} ${credits === 1 ? "credit" : "credits"} / call`;
10224
- }
10225
- const charge = (0, import_core10.perUnitCharge)(plan);
10226
- if (charge && charge.amountMinor > 0) {
10227
- return `${formatPrice(charge.amountMinor, charge.currency.toUpperCase(), { locale })} / call`;
10229
+ return `${prefix}${credits.toLocaleString(locale)} ${credits === 1 ? "credit" : "credits"} / call`;
10228
10230
  }
10229
- return null;
10231
+ return `${prefix}${formatPrice(rate.amountMinor, rate.currency.toUpperCase(), { locale })} / call`;
10230
10232
  }
10231
10233
  function inferIncludedUnits(plan) {
10232
10234
  const cap = (0, import_core10.includedUnits)(plan);