@sazito/checkout 0.4.0 → 0.4.2

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.
Files changed (38) hide show
  1. package/README.md +46 -1
  2. package/dist/chunks/{labels-CnPllzhT.cjs → labels-DlZCs2z3.cjs} +24 -10
  3. package/dist/chunks/labels-DlZCs2z3.cjs.map +1 -0
  4. package/dist/chunks/{labels-e8w4zRbg.js → labels-DxIkDijU.js} +24 -10
  5. package/dist/chunks/labels-DxIkDijU.js.map +1 -0
  6. package/dist/chunks/{use-checkout-DPtLgxlA.cjs → use-checkout-BPcxdj0A.cjs} +31 -10
  7. package/dist/chunks/use-checkout-BPcxdj0A.cjs.map +1 -0
  8. package/dist/chunks/{use-checkout-BM810__v.js → use-checkout-tQfM_-7X.js} +31 -10
  9. package/dist/chunks/use-checkout-tQfM_-7X.js.map +1 -0
  10. package/dist/core/index.cjs +2 -1
  11. package/dist/core/index.cjs.map +1 -1
  12. package/dist/core/index.d.cts +14 -2
  13. package/dist/core/index.d.ts +14 -2
  14. package/dist/core/index.js +2 -2
  15. package/dist/next/index.cjs +48 -11
  16. package/dist/next/index.cjs.map +1 -1
  17. package/dist/next/index.d.cts +26 -4
  18. package/dist/next/index.d.ts +26 -4
  19. package/dist/next/index.js +49 -12
  20. package/dist/next/index.js.map +1 -1
  21. package/dist/next/payment-return.cjs +40 -0
  22. package/dist/next/payment-return.cjs.map +1 -1
  23. package/dist/next/payment-return.d.cts +7 -1
  24. package/dist/next/payment-return.d.ts +7 -1
  25. package/dist/next/payment-return.js +40 -1
  26. package/dist/next/payment-return.js.map +1 -1
  27. package/dist/react/index.cjs +3 -2
  28. package/dist/react/index.cjs.map +1 -1
  29. package/dist/react/index.d.cts +6 -0
  30. package/dist/react/index.d.ts +6 -0
  31. package/dist/react/index.js +3 -2
  32. package/dist/react/index.js.map +1 -1
  33. package/dist/styles.css +263 -5
  34. package/package.json +1 -1
  35. package/dist/chunks/labels-CnPllzhT.cjs.map +0 -1
  36. package/dist/chunks/labels-e8w4zRbg.js.map +0 -1
  37. package/dist/chunks/use-checkout-BM810__v.js.map +0 -1
  38. package/dist/chunks/use-checkout-DPtLgxlA.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes } from 'react';
3
- import { Cart, Invoice, ApplicableShippingMethods, InvoiceItem, ShippingRate, PaymentMethod, Order } from '@sazito/client-sdk';
3
+ import { Order, Cart, Invoice, ApplicableShippingMethods, InvoiceItem, ShippingRate, PaymentMethod } from '@sazito/client-sdk';
4
4
 
5
5
  /**
6
6
  * Checkout domain types.
@@ -317,6 +317,12 @@ interface Strings {
317
317
  paymentPending: string;
318
318
  paymentPendingHint: string;
319
319
  orderNumber: string;
320
+ orderId: string;
321
+ orderConfirmedHint: string;
322
+ orderDetails: string;
323
+ orderItems: string;
324
+ product: string;
325
+ lineTotal: string;
320
326
  tryAgain: string;
321
327
  loading: string;
322
328
  processing: string;
@@ -360,6 +366,19 @@ interface RenderEmptyCartProps {
360
366
  actionLabel: ReactNode;
361
367
  icon: ReactNode;
362
368
  }
369
+ /** Props passed to a custom checkout result renderer. */
370
+ interface RenderResultProps {
371
+ /** Complete post-payment result, including any backend message and order. */
372
+ result: CheckoutResult | null;
373
+ /** Normalized result status. Falls back to `pending` while resolving. */
374
+ status: CheckoutResultStatus;
375
+ /** Finalized order returned by Sazito on a successful payment. */
376
+ order?: Order;
377
+ /** Configured destination for the continue-shopping action. */
378
+ continueShoppingUrl?: string;
379
+ /** Return to the payment step after a failed or stock-violated result. */
380
+ onRetry: () => void;
381
+ }
363
382
  /** Content-level customisation for the built-in empty-cart screen. */
364
383
  interface EmptyCartOptions {
365
384
  /** Empty-state heading. Defaults to the active locale. */
@@ -382,9 +401,11 @@ interface SazitoCheckoutProps {
382
401
  renderNextButton?: (props: RenderButtonProps) => ReactNode;
383
402
  renderBackButton?: (props: RenderButtonProps) => ReactNode;
384
403
  renderEmptyCart?: (props: RenderEmptyCartProps) => ReactNode;
404
+ /** Completely replace the built-in post-payment result screen. */
405
+ renderResult?: (props: RenderResultProps) => ReactNode;
385
406
  emptyCart?: EmptyCartOptions;
386
407
  }
387
- declare function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }: SazitoCheckoutProps): react_jsx_runtime.JSX.Element;
408
+ declare function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }: SazitoCheckoutProps): react_jsx_runtime.JSX.Element;
388
409
 
389
410
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
390
411
  variant?: 'primary' | 'outline' | 'ghost';
@@ -437,9 +458,10 @@ interface SazitoCheckoutPageProps {
437
458
  renderNextButton?: (props: RenderButtonProps) => React.ReactNode;
438
459
  renderBackButton?: (props: RenderButtonProps) => React.ReactNode;
439
460
  renderEmptyCart?: (props: RenderEmptyCartProps) => React.ReactNode;
461
+ renderResult?: (props: RenderResultProps) => React.ReactNode;
440
462
  emptyCart?: EmptyCartOptions;
441
463
  }
442
- declare function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }: SazitoCheckoutPageProps): react_jsx_runtime.JSX.Element;
464
+ declare function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }: SazitoCheckoutPageProps): react_jsx_runtime.JSX.Element;
443
465
 
444
466
  interface CheckoutProviderProps {
445
467
  /** Override the SazitoProvider client for this checkout instance only. */
@@ -472,4 +494,4 @@ interface SazitoProviderProps {
472
494
  declare function SazitoProvider({ client, children }: SazitoProviderProps): react_jsx_runtime.JSX.Element;
473
495
 
474
496
  export { Button, CheckoutProvider, ErrorBanner, Field, ProductPlaceholder, SazitoCheckout, SazitoCheckoutPage, SazitoProvider, SectionTitle, Spinner, useCheckout };
475
- export type { ButtonProps, CheckoutPaymentReturn, CheckoutProviderProps, EmptyCartOptions, ErrorBannerProps, FieldProps, PaymentReturnSearchParams, ProductPlaceholderProps, RenderButtonProps, RenderEmptyCartProps as RenderEmptyCartPageProps, RenderEmptyCartProps, SazitoCheckoutPageProps, SazitoCheckoutProps, SazitoProviderProps, SectionTitleProps, SpinnerProps };
497
+ export type { ButtonProps, CheckoutPaymentReturn, CheckoutProviderProps, EmptyCartOptions, ErrorBannerProps, FieldProps, PaymentReturnSearchParams, ProductPlaceholderProps, RenderButtonProps, RenderEmptyCartProps as RenderEmptyCartPageProps, RenderEmptyCartProps, RenderResultProps, SazitoCheckoutPageProps, SazitoCheckoutProps, SazitoProviderProps, SectionTitleProps, SpinnerProps };
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React, { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes } from 'react';
3
- import { Cart, Invoice, ApplicableShippingMethods, InvoiceItem, ShippingRate, PaymentMethod, Order } from '@sazito/client-sdk';
3
+ import { Order, Cart, Invoice, ApplicableShippingMethods, InvoiceItem, ShippingRate, PaymentMethod } from '@sazito/client-sdk';
4
4
 
5
5
  /**
6
6
  * Checkout domain types.
@@ -317,6 +317,12 @@ interface Strings {
317
317
  paymentPending: string;
318
318
  paymentPendingHint: string;
319
319
  orderNumber: string;
320
+ orderId: string;
321
+ orderConfirmedHint: string;
322
+ orderDetails: string;
323
+ orderItems: string;
324
+ product: string;
325
+ lineTotal: string;
320
326
  tryAgain: string;
321
327
  loading: string;
322
328
  processing: string;
@@ -360,6 +366,19 @@ interface RenderEmptyCartProps {
360
366
  actionLabel: ReactNode;
361
367
  icon: ReactNode;
362
368
  }
369
+ /** Props passed to a custom checkout result renderer. */
370
+ interface RenderResultProps {
371
+ /** Complete post-payment result, including any backend message and order. */
372
+ result: CheckoutResult | null;
373
+ /** Normalized result status. Falls back to `pending` while resolving. */
374
+ status: CheckoutResultStatus;
375
+ /** Finalized order returned by Sazito on a successful payment. */
376
+ order?: Order;
377
+ /** Configured destination for the continue-shopping action. */
378
+ continueShoppingUrl?: string;
379
+ /** Return to the payment step after a failed or stock-violated result. */
380
+ onRetry: () => void;
381
+ }
363
382
  /** Content-level customisation for the built-in empty-cart screen. */
364
383
  interface EmptyCartOptions {
365
384
  /** Empty-state heading. Defaults to the active locale. */
@@ -382,9 +401,11 @@ interface SazitoCheckoutProps {
382
401
  renderNextButton?: (props: RenderButtonProps) => ReactNode;
383
402
  renderBackButton?: (props: RenderButtonProps) => ReactNode;
384
403
  renderEmptyCart?: (props: RenderEmptyCartProps) => ReactNode;
404
+ /** Completely replace the built-in post-payment result screen. */
405
+ renderResult?: (props: RenderResultProps) => ReactNode;
385
406
  emptyCart?: EmptyCartOptions;
386
407
  }
387
- declare function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }: SazitoCheckoutProps): react_jsx_runtime.JSX.Element;
408
+ declare function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }: SazitoCheckoutProps): react_jsx_runtime.JSX.Element;
388
409
 
389
410
  interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
390
411
  variant?: 'primary' | 'outline' | 'ghost';
@@ -437,9 +458,10 @@ interface SazitoCheckoutPageProps {
437
458
  renderNextButton?: (props: RenderButtonProps) => React.ReactNode;
438
459
  renderBackButton?: (props: RenderButtonProps) => React.ReactNode;
439
460
  renderEmptyCart?: (props: RenderEmptyCartProps) => React.ReactNode;
461
+ renderResult?: (props: RenderResultProps) => React.ReactNode;
440
462
  emptyCart?: EmptyCartOptions;
441
463
  }
442
- declare function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }: SazitoCheckoutPageProps): react_jsx_runtime.JSX.Element;
464
+ declare function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }: SazitoCheckoutPageProps): react_jsx_runtime.JSX.Element;
443
465
 
444
466
  interface CheckoutProviderProps {
445
467
  /** Override the SazitoProvider client for this checkout instance only. */
@@ -472,4 +494,4 @@ interface SazitoProviderProps {
472
494
  declare function SazitoProvider({ client, children }: SazitoProviderProps): react_jsx_runtime.JSX.Element;
473
495
 
474
496
  export { Button, CheckoutProvider, ErrorBanner, Field, ProductPlaceholder, SazitoCheckout, SazitoCheckoutPage, SazitoProvider, SectionTitle, Spinner, useCheckout };
475
- export type { ButtonProps, CheckoutPaymentReturn, CheckoutProviderProps, EmptyCartOptions, ErrorBannerProps, FieldProps, PaymentReturnSearchParams, ProductPlaceholderProps, RenderButtonProps, RenderEmptyCartProps as RenderEmptyCartPageProps, RenderEmptyCartProps, SazitoCheckoutPageProps, SazitoCheckoutProps, SazitoProviderProps, SectionTitleProps, SpinnerProps };
497
+ export type { ButtonProps, CheckoutPaymentReturn, CheckoutProviderProps, EmptyCartOptions, ErrorBannerProps, FieldProps, PaymentReturnSearchParams, ProductPlaceholderProps, RenderButtonProps, RenderEmptyCartProps as RenderEmptyCartPageProps, RenderEmptyCartProps, RenderResultProps, SazitoCheckoutPageProps, SazitoCheckoutProps, SazitoProviderProps, SectionTitleProps, SpinnerProps };
@@ -1,9 +1,10 @@
1
1
  'use client';
2
2
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
3
  import { isValidElement, cloneElement, useMemo, useState, useRef, useEffect, useCallback } from 'react';
4
- import { u as useCheckout, b as useSazitoClient, C as CheckoutProvider } from '../chunks/use-checkout-BM810__v.js';
5
- export { S as SazitoProvider } from '../chunks/use-checkout-BM810__v.js';
6
- import { m as formatPercent, E as sortCartItemsNewestFirst, H as toPersianDigits, r as isDigitalServiceGroup, t as isValidIranianMobile, z as normalizeIranianPhone, A as paymentMethodInfo, l as formatNumber } from '../chunks/labels-e8w4zRbg.js';
4
+ import { u as useCheckout, b as useSazitoClient, C as CheckoutProvider } from '../chunks/use-checkout-tQfM_-7X.js';
5
+ export { S as SazitoProvider } from '../chunks/use-checkout-tQfM_-7X.js';
6
+ import { m as formatPercent, E as sortCartItemsNewestFirst, H as toPersianDigits, r as isDigitalServiceGroup, t as isValidIranianMobile, z as normalizeIranianPhone, A as paymentMethodInfo, l as formatNumber } from '../chunks/labels-DxIkDijU.js';
7
+ import { parsePaymentReturnUrl } from './payment-return.js';
7
8
  import '@sazito/client-sdk';
8
9
 
9
10
  /**
@@ -709,16 +710,29 @@ function PaymentIcon({ kind }) {
709
710
  }
710
711
 
711
712
  function ResultStep({ continueShoppingUrl }) {
712
- const { state, actions, t } = useCheckout();
713
+ const { state, actions, money, price, t } = useCheckout();
713
714
  const result = state.result;
714
715
  const status = result?.status ?? 'pending';
716
+ const order = result?.order;
717
+ const invoice = order?.invoice;
718
+ const showDetails = Boolean(order && (status === 'success' || status === 'pending'));
715
719
  const titleMap = {
716
720
  success: t.paymentSuccess,
717
721
  failed: t.paymentFailed,
718
722
  pending: t.paymentPending,
719
723
  stock_violated: t.paymentFailed
720
724
  };
721
- return (jsxs("section", { className: `szc-result szc-result--${status}`, children: [jsx("div", { className: "szc-result__icon", children: status === 'success' ? (jsx(CheckCircle, {})) : status === 'pending' ? (jsx(Spinner, {})) : (jsx(CrossCircle, {})) }), jsx("h2", { className: "szc-result__title", children: titleMap[status] }), status === 'pending' ? jsx("p", { className: "szc-muted", children: t.paymentPendingHint }) : null, result?.message ? jsx("p", { className: "szc-muted", children: result.message }) : null, result?.order ? (jsxs("p", { className: "szc-result__order", children: [t.orderNumber, ": ", jsx("strong", { children: result.order.orderNumber })] })) : null, jsxs("div", { className: "szc-result__actions", children: [status === 'failed' || status === 'stock_violated' ? (jsx(Button, { onClick: () => actions.goToStep('payment'), children: t.tryAgain })) : null, continueShoppingUrl ? (jsx(Button, { variant: "outline", onClick: () => (window.location.href = continueShoppingUrl), children: t.continueShopping })) : null] })] }));
725
+ return (jsxs("section", { className: `szc-result szc-result--${status}`, children: [jsxs("div", { className: "szc-result__hero", role: "status", "aria-live": "polite", children: [jsx("div", { className: "szc-result__icon", children: status === 'success' ? (jsx(CheckCircle, {})) : status === 'pending' ? (jsx(Spinner, {})) : (jsx(CrossCircle, {})) }), jsx("h2", { className: "szc-result__title", children: titleMap[status] }), status === 'pending' ? jsx("p", { className: "szc-muted", children: t.paymentPendingHint }) : null, result?.message ? jsx("p", { className: "szc-muted", children: result.message }) : null, status === 'success' && order ? (jsx("p", { className: "szc-result__hint", children: t.orderConfirmedHint })) : null, order ? (jsxs("dl", { className: "szc-result__reference", children: [jsxs("div", { className: "szc-result__reference-primary", children: [jsx("dt", { children: t.orderNumber }), jsx("dd", { children: formatPublicId(order.orderNumber, state.locale) })] }), jsxs("div", { children: [jsx("dt", { children: t.orderId }), jsx("dd", { children: formatPublicId(order.id, state.locale) })] })] })) : null, jsxs("div", { className: "szc-result__actions", children: [status === 'failed' || status === 'stock_violated' ? (jsx(Button, { onClick: () => actions.goToStep('payment'), children: t.tryAgain })) : null, continueShoppingUrl ? (jsx(Button, { variant: status === 'success' ? 'primary' : 'outline', asChild: true, children: jsx("a", { href: continueShoppingUrl, children: t.continueShopping }) })) : null] })] }), showDetails && order && invoice ? (jsxs("div", { className: "szc-result__details", children: [jsx("h3", { className: "szc-result__details-title", children: t.orderDetails }), invoice.shippingItems.length > 0 ? (jsxs("section", { className: "szc-result__section", "aria-labelledby": "szc-result-shipping-title", children: [jsx("h4", { id: "szc-result-shipping-title", className: "szc-result__section-title", children: t.shippingMethods }), jsx("div", { className: "szc-result-shipping-list", children: invoice.shippingItems.map((shipping) => (jsx("article", { className: "szc-result-group", children: jsxs("header", { className: "szc-result-group__head", children: [jsx("span", { className: "szc-result-group__mark", "aria-hidden": "true", children: shipping.rate.icon ? jsx("img", { src: shipping.rate.icon, alt: "" }) : jsx(DeliveryIcon, {}) }), jsx("span", { className: "szc-result-group__title", children: shipping.rate.name }), jsx("span", { className: "szc-result-group__price", children: price(shipping.rate.price) })] }) }, String(shipping.id)))) })] })) : null, invoice.invoiceItems.length > 0 ? (jsxs("section", { className: "szc-result-group", "aria-labelledby": "szc-result-items-title", children: [jsxs("header", { className: "szc-result-group__head", children: [jsx("span", { className: "szc-result-group__mark", "aria-hidden": "true", children: jsx(OrderItemsIcon, {}) }), jsx("h4", { id: "szc-result-items-title", className: "szc-result-group__title", children: t.orderItems })] }), jsxs("div", { className: "szc-result-items__head", "aria-hidden": "true", children: [jsx("span", { children: t.product }), jsx("span", { children: t.quantity }), jsx("span", { children: t.lineTotal })] }), jsx("ul", { className: "szc-result-items", children: invoice.invoiceItems.map((item, index) => (jsxs("li", { className: "szc-result-item", children: [jsxs("span", { className: "szc-result-item__product", children: [item.image?.url ? (jsx("img", { className: "szc-result-item__thumb", src: item.image.url, alt: "" })) : (jsx(ProductPlaceholder, { className: "szc-result-item__thumb" })), jsxs("span", { children: [jsx("strong", { children: item.name }), item.variantAttributes.length ? (jsx("small", { children: item.variantAttributes.map(formatAttribute).join(' · ') })) : null] })] }), jsxs("span", { className: "szc-result-item__quantity", children: [jsx("span", { className: "szc-result-item__mobile-label", children: t.quantity }), formatNumber(item.noOfItems, state.locale)] }), jsxs("span", { className: "szc-result-item__total", children: [jsx("span", { className: "szc-result-item__mobile-label", children: t.lineTotal }), money(item.totalItemsPrice)] })] }, `${String(item.productVariantId)}-${index}`))) })] })) : null, jsxs("dl", { className: "szc-result-summary", children: [jsx(SummaryRow, { label: t.subtotal, value: money(invoice.netTotal) }), invoice.shippingTotal != null ? (jsx(SummaryRow, { label: t.shipping, value: money(invoice.shippingTotal) })) : null, invoice.discountTotal != null && invoice.discountTotal > 0 ? (jsx(SummaryRow, { label: t.discount, value: `−${money(invoice.discountTotal)}` })) : null, invoice.creditTotal != null && invoice.creditTotal > 0 ? (jsx(SummaryRow, { label: t.credit, value: `−${money(invoice.creditTotal)}` })) : null, invoice.vat != null && invoice.vat > 0 ? (jsx(SummaryRow, { label: t.vat, value: money(invoice.vat) })) : null, invoice.customerProfit != null && invoice.customerProfit > 0 ? (jsx(SummaryRow, { label: t.yourSavings, value: money(invoice.customerProfit), savings: true })) : null, jsx(SummaryRow, { label: t.total, value: money(invoice.finalTotal), total: true })] })] })) : null] }));
726
+ }
727
+ function formatPublicId(value, locale) {
728
+ const text = String(value);
729
+ return locale === 'fa' ? toPersianDigits(text) : text;
730
+ }
731
+ function formatAttribute(attribute) {
732
+ return `${attribute.name}: ${attribute.value}`;
733
+ }
734
+ function SummaryRow({ label, value, savings = false, total = false }) {
735
+ return (jsxs("div", { className: `${total ? 'szc-result-summary__total' : ''} ${savings ? 'szc-result-summary__savings' : ''}`.trim(), children: [jsx("dt", { children: label }), jsx("dd", { children: value })] }));
722
736
  }
723
737
  function CheckCircle() {
724
738
  return (jsxs("svg", { viewBox: "0 0 48 48", width: "48", height: "48", fill: "none", "aria-hidden": "true", children: [jsx("circle", { cx: "24", cy: "24", r: "22", stroke: "currentColor", strokeWidth: "2.5" }), jsx("path", { d: "M15 24.5l6 6 12-13", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
@@ -726,6 +740,12 @@ function CheckCircle() {
726
740
  function CrossCircle() {
727
741
  return (jsxs("svg", { viewBox: "0 0 48 48", width: "48", height: "48", fill: "none", "aria-hidden": "true", children: [jsx("circle", { cx: "24", cy: "24", r: "22", stroke: "currentColor", strokeWidth: "2.5" }), jsx("path", { d: "M17 17l14 14M31 17L17 31", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })] }));
728
742
  }
743
+ function DeliveryIcon() {
744
+ return (jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", "aria-hidden": "true", children: [jsx("path", { d: "M3 6.5h11v10H3zM14 10h3.5l3 3v3.5H14z", stroke: "currentColor", strokeWidth: "1.6", strokeLinejoin: "round" }), jsx("circle", { cx: "7", cy: "18", r: "1.75", stroke: "currentColor", strokeWidth: "1.6" }), jsx("circle", { cx: "17.5", cy: "18", r: "1.75", stroke: "currentColor", strokeWidth: "1.6" })] }));
745
+ }
746
+ function OrderItemsIcon() {
747
+ return (jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", "aria-hidden": "true", children: [jsx("path", { d: "M5 7.5h14v11H5zM8 7.5V5h8v2.5", stroke: "currentColor", strokeWidth: "1.6", strokeLinejoin: "round" }), jsx("path", { d: "M8.5 12h7M8.5 15h5", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })] }));
748
+ }
729
749
 
730
750
  function themeVars(theme) {
731
751
  const vars = {};
@@ -770,10 +790,11 @@ function themeVars(theme) {
770
790
  function CheckoutLoading({ label }) {
771
791
  return (jsxs("div", { className: "szc-checkout-loading", role: "status", "aria-live": "polite", children: [jsx(Spinner, { className: "szc-checkout-loading__spinner" }), jsx("span", { children: label })] }));
772
792
  }
773
- function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }) {
793
+ function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }) {
774
794
  const { state, actions, t, summary, money } = useCheckout();
775
795
  const { step, direction, flags, error } = state;
776
796
  const isResult = step === 'result';
797
+ const resultStatus = state.result?.status ?? 'pending';
777
798
  const bootstrapping = step === 'cart' && !error && (!state.cart || !state.invoice || flags.bootstrapping);
778
799
  const emptyCartError = error?.code === 'no_cart';
779
800
  const fatal = error && !state.cart && step === 'cart' && !emptyCartError;
@@ -844,17 +865,33 @@ function SazitoCheckout({ theme, continueShoppingUrl, className, renderNextButto
844
865
  ? CardIcon
845
866
  : ClipboardIcon;
846
867
  const mobileHead = (jsxs("div", { className: "szc-mobile-head", children: [footerVisible && backVisible ? (jsx("button", { type: "button", className: "szc-mobile-head__back", "aria-label": t.back, onClick: backOnClick, children: jsx("svg", { className: "szc-back-arrow", viewBox: "0 0 16 16", width: "18", height: "18", fill: "none", "aria-hidden": "true", children: jsx("path", { d: "M9.5 3.5 5 8l4.5 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })) : (jsx("span", {})), jsxs("span", { className: "szc-mobile-head__title", children: [jsx("span", { className: "szc-mobile-head__dot", children: jsx(HeadIcon, {}) }), headTitle] }), flowIndex >= 0 ? (jsx("span", { className: "szc-mobile-head__count", children: t.stepOf(formatNumber(flowIndex + 1, state.locale), formatNumber(flowSteps.length, state.locale)) })) : (jsx("span", {}))] }));
847
- return (jsxs("div", { className: `szc-root${className ? ` ${className}` : ''}`, dir: direction, style: themeVars(theme), children: [mobileHead, jsx(Stepper, {}), bootstrapping ? (jsx(CheckoutLoading, { label: t.loading })) : fatal ? (jsx(ErrorBanner, { message: error.message })) : isResult ? (jsx("div", { className: "szc-result-wrap", children: jsx(ResultStep, { continueShoppingUrl: continueShoppingUrl }) })) : (jsx(Fragment, { children: jsxs("div", { className: `szc-layout${cartEmpty ? ' szc-layout--full' : ''}`, children: [jsxs("main", { className: "szc-main", children: [error && !emptyCartError ? jsx(ErrorBanner, { message: error.message }) : null, step === 'cart' ? (jsx(CartStep, { continueShoppingUrl: continueShoppingUrl, emptyCart: emptyCart, renderEmpty: renderEmptyCart })) : null, step === 'shipping' ? jsx(ShippingStep, {}) : null, step === 'payment' ? jsx(PaymentStep, {}) : null, actionsVisible && backButtonNode ? (jsx("div", { className: "szc-back-row", children: backButtonNode })) : null] }), !cartEmpty ? (jsxs("div", { className: "szc-side", children: [jsx(OrderSummary, {}), actionsVisible ? jsx("div", { className: "szc-side__cta", children: nextButtonNode }) : null] })) : null] }) })), actionsVisible ? (jsx("div", { className: "szc-footer-bar", children: jsxs("div", { className: "szc-footer", children: [jsxs("div", { className: "szc-footer__total", children: [jsx("span", { className: "szc-footer__total-label", children: t.total }), jsx("span", { className: "szc-footer__total-value", children: money(summary.total) })] }), jsx("div", { className: "szc-footer__actions", children: nextButtonNode })] }) })) : null] }));
868
+ return (jsxs("div", { className: `szc-root${className ? ` ${className}` : ''}`, dir: direction, style: themeVars(theme), children: [mobileHead, jsx(Stepper, {}), bootstrapping ? (jsx(CheckoutLoading, { label: t.loading })) : fatal ? (jsx(ErrorBanner, { message: error.message })) : isResult ? (jsx("div", { className: "szc-result-wrap", children: renderResult ? (renderResult({
869
+ result: state.result,
870
+ status: resultStatus,
871
+ order: state.result?.order,
872
+ continueShoppingUrl,
873
+ onRetry: () => actions.goToStep('payment')
874
+ })) : (jsx(ResultStep, { continueShoppingUrl: continueShoppingUrl })) })) : (jsx(Fragment, { children: jsxs("div", { className: `szc-layout${cartEmpty ? ' szc-layout--full' : ''}`, children: [jsxs("main", { className: "szc-main", children: [error && !emptyCartError ? jsx(ErrorBanner, { message: error.message }) : null, step === 'cart' ? (jsx(CartStep, { continueShoppingUrl: continueShoppingUrl, emptyCart: emptyCart, renderEmpty: renderEmptyCart })) : null, step === 'shipping' ? jsx(ShippingStep, {}) : null, step === 'payment' ? jsx(PaymentStep, {}) : null, actionsVisible && backButtonNode ? (jsx("div", { className: "szc-back-row", children: backButtonNode })) : null] }), !cartEmpty ? (jsxs("div", { className: "szc-side", children: [jsx(OrderSummary, {}), actionsVisible ? jsx("div", { className: "szc-side__cta", children: nextButtonNode }) : null] })) : null] }) })), actionsVisible ? (jsx("div", { className: "szc-footer-bar", children: jsxs("div", { className: "szc-footer", children: [jsxs("div", { className: "szc-footer__total", children: [jsx("span", { className: "szc-footer__total-label", children: t.total }), jsx("span", { className: "szc-footer__total-value", children: money(summary.total) })] }), jsx("div", { className: "szc-footer__actions", children: nextButtonNode })] }) })) : null] }));
848
875
  }
849
876
 
850
- function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, emptyCart, }) {
851
- const returnParams = paymentReturn?.params ?? paymentReturnParams;
877
+ function SazitoCheckoutPage({ credentials, config, paymentReturn, paymentReturnParams, className, renderNextButton, renderBackButton, renderEmptyCart, renderResult, emptyCart, }) {
878
+ // The explicit server-parsed value remains authoritative. As a fallback,
879
+ // detect Sazito's well-known nested callback in the browser. This prevents a
880
+ // caught callback route from silently booting a fresh checkout when the host
881
+ // forgot to forward its catch-all params.
882
+ const detectedPaymentReturn = paymentReturn == null &&
883
+ paymentReturnParams == null &&
884
+ typeof window !== 'undefined'
885
+ ? parsePaymentReturnUrl(window.location.href)
886
+ : undefined;
887
+ const resolvedPaymentReturn = paymentReturn ?? detectedPaymentReturn;
888
+ const returnParams = resolvedPaymentReturn?.params ?? paymentReturnParams;
852
889
  const isReturn = returnParams != null;
853
- const checkoutCredentials = paymentReturn
854
- ? { ...credentials, payment: paymentReturn.payment }
890
+ const checkoutCredentials = resolvedPaymentReturn
891
+ ? { ...credentials, payment: resolvedPaymentReturn.payment }
855
892
  : credentials;
856
893
  const client = useSazitoClient();
857
- return (jsxs(CheckoutProvider, { client: client, credentials: checkoutCredentials, config: config, autoStart: !isReturn, children: [returnParams ? jsx(ResolveReturn, { params: returnParams }) : null, jsx(SazitoCheckout, { theme: config?.theme, continueShoppingUrl: config?.continueShoppingUrl, className: className, renderNextButton: renderNextButton, renderBackButton: renderBackButton, renderEmptyCart: renderEmptyCart, emptyCart: emptyCart })] }));
894
+ return (jsxs(CheckoutProvider, { client: client, credentials: checkoutCredentials, config: config, autoStart: !isReturn, children: [returnParams ? jsx(ResolveReturn, { params: returnParams }) : null, jsx(SazitoCheckout, { theme: config?.theme, continueShoppingUrl: config?.continueShoppingUrl, className: className, renderNextButton: renderNextButton, renderBackButton: renderBackButton, renderEmptyCart: renderEmptyCart, renderResult: renderResult, emptyCart: emptyCart })] }));
858
895
  }
859
896
  function ResolveReturn({ params }) {
860
897
  const { actions } = useCheckout();