@asteby/storefront-react 0.11.0 → 0.12.0
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 +25 -0
- package/dist/checkout.cjs +673 -51
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.css +230 -0
- package/dist/checkout.d.cts +323 -4
- package/dist/checkout.d.ts +323 -4
- package/dist/checkout.js +652 -45
- package/dist/checkout.js.map +1 -1
- package/dist/{chunk-3ZJTDFHE.js → chunk-ODIQR6TG.js} +5 -4
- package/dist/chunk-ODIQR6TG.js.map +1 -0
- package/dist/payments.cjs +171 -40
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.css +14 -1
- package/dist/payments.d.cts +37 -1
- package/dist/payments.d.ts +37 -1
- package/dist/payments.js +169 -40
- package/dist/payments.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-3ZJTDFHE.js.map +0 -1
package/dist/payments.css
CHANGED
|
@@ -45,13 +45,26 @@
|
|
|
45
45
|
display: inline-block;
|
|
46
46
|
vertical-align: middle;
|
|
47
47
|
}
|
|
48
|
+
/* The mark of a provider row (Mercado Pago…) is as wide as its logo: in line between the radio and the text, never over them. */
|
|
49
|
+
[data-sf-pay-method] [data-sf-pay-icon='mark'] {
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
flex: none;
|
|
52
|
+
align-items: center;
|
|
53
|
+
width: auto;
|
|
54
|
+
height: auto;
|
|
55
|
+
}
|
|
48
56
|
/* The open cash row already lists every point with its mark: the preview would repeat them. */
|
|
49
57
|
[data-sf-pay-method] [data-sf-pay-choice]:has(input[name='payment_choice']:checked) [data-sf-pay-brands='cash'] {
|
|
50
58
|
display: none;
|
|
51
59
|
}
|
|
60
|
+
/* The card form opens inside its row: a little air between the row and the provider form. */
|
|
61
|
+
[data-sf-pay-method] [data-sf-pay-card] [data-sf-pay-container] {
|
|
62
|
+
margin-block: 0.25rem;
|
|
63
|
+
}
|
|
52
64
|
@media (max-width: 24rem) {
|
|
53
65
|
/* Narrow phones: the row text wins over the preview marks. */
|
|
66
|
+
/* !important: the logo plate sets its own inline `display`. */
|
|
54
67
|
[data-sf-pay-method] [data-sf-pay-choice] [data-sf-pay-brands] [data-sf-brand-mark]:nth-child(n + 3) {
|
|
55
|
-
display: none;
|
|
68
|
+
display: none !important;
|
|
56
69
|
}
|
|
57
70
|
}
|
package/dist/payments.d.cts
CHANGED
|
@@ -33,6 +33,8 @@ type PaymentFormMountOptions = {
|
|
|
33
33
|
locale?: string;
|
|
34
34
|
/** Visual tokens read from CSS variables (see `readPaymentTheme`). */
|
|
35
35
|
theme?: Record<string, string>;
|
|
36
|
+
/** Light or dark page (see `readPaymentScheme`): the adapter picks the provider's matching base theme. */
|
|
37
|
+
colorScheme?: 'light' | 'dark';
|
|
36
38
|
onReady: () => void;
|
|
37
39
|
onError: (error: PaymentFormError) => void;
|
|
38
40
|
};
|
|
@@ -168,6 +170,8 @@ type UseEmbeddedPaymentOptions = {
|
|
|
168
170
|
onEvent?: (event: PaymentEvent) => void;
|
|
169
171
|
/** Overrides the theme read from `--sf-pay-*` tokens. */
|
|
170
172
|
theme?: Record<string, string>;
|
|
173
|
+
/** Overrides the light / dark scheme read from the page (`--sf-pay-scheme` or `color-scheme`). */
|
|
174
|
+
colorScheme?: 'light' | 'dark';
|
|
171
175
|
/** Test hooks. */
|
|
172
176
|
newAttemptId?: () => string;
|
|
173
177
|
};
|
|
@@ -326,6 +330,10 @@ type PaymentMethodMessages = {
|
|
|
326
330
|
pay: string;
|
|
327
331
|
/** Button label for card and cash, before the total. */
|
|
328
332
|
placeOrder: string;
|
|
333
|
+
/** Button label for cash (the buyer gets a payment slip and pays later), before the total. */
|
|
334
|
+
placeOrderCash: string;
|
|
335
|
+
/** Button label while no delivery is chosen yet. */
|
|
336
|
+
chooseDelivery: string;
|
|
329
337
|
/** Button label when the buyer leaves for the provider's page. */
|
|
330
338
|
payRedirect: string;
|
|
331
339
|
/** Button label for the first step (address) of a two-step checkout. */
|
|
@@ -443,6 +451,22 @@ type PaymentMethodSectionProps = {
|
|
|
443
451
|
transport?: PaymentTransport;
|
|
444
452
|
/** Extra props for the card form (`adapter`, `adapters`, `messages`, `minHeight`, `storage`, timeouts...). */
|
|
445
453
|
brickProps?: Partial<Omit<PaymentBrickProps, 'client' | 'amount' | 'transport' | 'onResult' | 'onEvent' | 'onFallback'>>;
|
|
454
|
+
/**
|
|
455
|
+
* Remember the chosen row (and cash point) for this `scope` in `sessionStorage`, so a reload, the "back" button from
|
|
456
|
+
* the provider or the address step does not ask to choose again. Used only while that row is still published.
|
|
457
|
+
* Default true (needs `scope`); `false` turns it off. Nothing personal is stored: only the row value.
|
|
458
|
+
*/
|
|
459
|
+
rememberChoice?: boolean;
|
|
460
|
+
/**
|
|
461
|
+
* Cash points shown before "more payment points". Default: every point the provider marks `main`. With a number, the
|
|
462
|
+
* first N `main` points show and the rest join the "more" list (a remembered point inside it opens the list).
|
|
463
|
+
*/
|
|
464
|
+
cashPointsVisible?: number;
|
|
465
|
+
/**
|
|
466
|
+
* Name of the page form field with the buyer's e-mail. Its value is handed to the card form, so the provider does not
|
|
467
|
+
* ask for the e-mail again. Default `email`; `null` to never pass it. `brickProps.email` wins.
|
|
468
|
+
*/
|
|
469
|
+
payerEmailField?: string | null;
|
|
446
470
|
};
|
|
447
471
|
/**
|
|
448
472
|
* "Payment method", hybrid. Card: the provider's secure form INSIDE the page (`PaymentBrick`) with the shop's own
|
|
@@ -470,11 +494,23 @@ declare const PAYMENT_THEME_TOKENS: {
|
|
|
470
494
|
readonly '--sf-pay-success': "successColor";
|
|
471
495
|
readonly '--sf-pay-outline': "outlinePrimaryColor";
|
|
472
496
|
readonly '--sf-pay-radius': "borderRadiusMedium";
|
|
497
|
+
readonly '--sf-pay-radius-small': "borderRadiusSmall";
|
|
498
|
+
readonly '--sf-pay-radius-large': "borderRadiusLarge";
|
|
499
|
+
readonly '--sf-pay-outline-secondary': "outlineSecondaryColor";
|
|
500
|
+
readonly '--sf-pay-primary-variant': "baseColorFirstVariant";
|
|
501
|
+
readonly '--sf-pay-input-border-width': "inputBorderWidth";
|
|
502
|
+
readonly '--sf-pay-form-padding': "formPadding";
|
|
473
503
|
};
|
|
474
504
|
/**
|
|
475
505
|
* Reads the `--sf-pay-*` tokens from an element's computed style, so the provider form follows the shop's
|
|
476
506
|
* theme without the shop copying colors into JavaScript. Unsafe or empty values are skipped.
|
|
477
507
|
*/
|
|
478
508
|
declare function readPaymentTheme(el: Element | null | undefined, tokens?: Record<string, string>): Record<string, string>;
|
|
509
|
+
/**
|
|
510
|
+
* Light or dark for the provider form, so it does not paint a white card inside a dark page. Order: the
|
|
511
|
+
* `--sf-pay-scheme` token (`light` / `dark`), then the element's `color-scheme` (`light dark` follows the system
|
|
512
|
+
* preference). `null` when nothing says it (the provider default).
|
|
513
|
+
*/
|
|
514
|
+
declare function readPaymentScheme(el: Element | null | undefined): 'light' | 'dark' | null;
|
|
479
515
|
|
|
480
|
-
export { CASH_POINT_FIELD, type EmbeddedPaymentState, type EmbeddedPaymentStatus, type FetchTransportOptions, type LoadScriptOptions, MERCADOPAGO_BRICKS_KIND, type MercadoPagoAdapterOptions, type MercadoPagoCtor, type MountedPaymentForm, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PayChoices, PaymentBrick, type PaymentBrickHandle, type PaymentBrickProps, PaymentChallenge, type PaymentChallengeProps, type PaymentEvent, type PaymentFallbackReason, type PaymentFormAdapter, type PaymentFormData, type PaymentFormError, type PaymentFormMountOptions, PaymentHttpError, type PaymentMethodClassNames, type PaymentMethodMessages, PaymentMethodSection, type PaymentMethodSectionProps, type PaymentMethodTestIds, type PaymentSubmitRequest, type PaymentTransport, type UseEmbeddedPaymentOptions, VoucherCard, type VoucherCardProps, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
|
516
|
+
export { CASH_POINT_FIELD, type EmbeddedPaymentState, type EmbeddedPaymentStatus, type FetchTransportOptions, type LoadScriptOptions, MERCADOPAGO_BRICKS_KIND, type MercadoPagoAdapterOptions, type MercadoPagoCtor, type MountedPaymentForm, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PayChoices, PaymentBrick, type PaymentBrickHandle, type PaymentBrickProps, PaymentChallenge, type PaymentChallengeProps, type PaymentEvent, type PaymentFallbackReason, type PaymentFormAdapter, type PaymentFormData, type PaymentFormError, type PaymentFormMountOptions, PaymentHttpError, type PaymentMethodClassNames, type PaymentMethodMessages, PaymentMethodSection, type PaymentMethodSectionProps, type PaymentMethodTestIds, type PaymentSubmitRequest, type PaymentTransport, type UseEmbeddedPaymentOptions, VoucherCard, type VoucherCardProps, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentScheme, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
package/dist/payments.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ type PaymentFormMountOptions = {
|
|
|
33
33
|
locale?: string;
|
|
34
34
|
/** Visual tokens read from CSS variables (see `readPaymentTheme`). */
|
|
35
35
|
theme?: Record<string, string>;
|
|
36
|
+
/** Light or dark page (see `readPaymentScheme`): the adapter picks the provider's matching base theme. */
|
|
37
|
+
colorScheme?: 'light' | 'dark';
|
|
36
38
|
onReady: () => void;
|
|
37
39
|
onError: (error: PaymentFormError) => void;
|
|
38
40
|
};
|
|
@@ -168,6 +170,8 @@ type UseEmbeddedPaymentOptions = {
|
|
|
168
170
|
onEvent?: (event: PaymentEvent) => void;
|
|
169
171
|
/** Overrides the theme read from `--sf-pay-*` tokens. */
|
|
170
172
|
theme?: Record<string, string>;
|
|
173
|
+
/** Overrides the light / dark scheme read from the page (`--sf-pay-scheme` or `color-scheme`). */
|
|
174
|
+
colorScheme?: 'light' | 'dark';
|
|
171
175
|
/** Test hooks. */
|
|
172
176
|
newAttemptId?: () => string;
|
|
173
177
|
};
|
|
@@ -326,6 +330,10 @@ type PaymentMethodMessages = {
|
|
|
326
330
|
pay: string;
|
|
327
331
|
/** Button label for card and cash, before the total. */
|
|
328
332
|
placeOrder: string;
|
|
333
|
+
/** Button label for cash (the buyer gets a payment slip and pays later), before the total. */
|
|
334
|
+
placeOrderCash: string;
|
|
335
|
+
/** Button label while no delivery is chosen yet. */
|
|
336
|
+
chooseDelivery: string;
|
|
329
337
|
/** Button label when the buyer leaves for the provider's page. */
|
|
330
338
|
payRedirect: string;
|
|
331
339
|
/** Button label for the first step (address) of a two-step checkout. */
|
|
@@ -443,6 +451,22 @@ type PaymentMethodSectionProps = {
|
|
|
443
451
|
transport?: PaymentTransport;
|
|
444
452
|
/** Extra props for the card form (`adapter`, `adapters`, `messages`, `minHeight`, `storage`, timeouts...). */
|
|
445
453
|
brickProps?: Partial<Omit<PaymentBrickProps, 'client' | 'amount' | 'transport' | 'onResult' | 'onEvent' | 'onFallback'>>;
|
|
454
|
+
/**
|
|
455
|
+
* Remember the chosen row (and cash point) for this `scope` in `sessionStorage`, so a reload, the "back" button from
|
|
456
|
+
* the provider or the address step does not ask to choose again. Used only while that row is still published.
|
|
457
|
+
* Default true (needs `scope`); `false` turns it off. Nothing personal is stored: only the row value.
|
|
458
|
+
*/
|
|
459
|
+
rememberChoice?: boolean;
|
|
460
|
+
/**
|
|
461
|
+
* Cash points shown before "more payment points". Default: every point the provider marks `main`. With a number, the
|
|
462
|
+
* first N `main` points show and the rest join the "more" list (a remembered point inside it opens the list).
|
|
463
|
+
*/
|
|
464
|
+
cashPointsVisible?: number;
|
|
465
|
+
/**
|
|
466
|
+
* Name of the page form field with the buyer's e-mail. Its value is handed to the card form, so the provider does not
|
|
467
|
+
* ask for the e-mail again. Default `email`; `null` to never pass it. `brickProps.email` wins.
|
|
468
|
+
*/
|
|
469
|
+
payerEmailField?: string | null;
|
|
446
470
|
};
|
|
447
471
|
/**
|
|
448
472
|
* "Payment method", hybrid. Card: the provider's secure form INSIDE the page (`PaymentBrick`) with the shop's own
|
|
@@ -470,11 +494,23 @@ declare const PAYMENT_THEME_TOKENS: {
|
|
|
470
494
|
readonly '--sf-pay-success': "successColor";
|
|
471
495
|
readonly '--sf-pay-outline': "outlinePrimaryColor";
|
|
472
496
|
readonly '--sf-pay-radius': "borderRadiusMedium";
|
|
497
|
+
readonly '--sf-pay-radius-small': "borderRadiusSmall";
|
|
498
|
+
readonly '--sf-pay-radius-large': "borderRadiusLarge";
|
|
499
|
+
readonly '--sf-pay-outline-secondary': "outlineSecondaryColor";
|
|
500
|
+
readonly '--sf-pay-primary-variant': "baseColorFirstVariant";
|
|
501
|
+
readonly '--sf-pay-input-border-width': "inputBorderWidth";
|
|
502
|
+
readonly '--sf-pay-form-padding': "formPadding";
|
|
473
503
|
};
|
|
474
504
|
/**
|
|
475
505
|
* Reads the `--sf-pay-*` tokens from an element's computed style, so the provider form follows the shop's
|
|
476
506
|
* theme without the shop copying colors into JavaScript. Unsafe or empty values are skipped.
|
|
477
507
|
*/
|
|
478
508
|
declare function readPaymentTheme(el: Element | null | undefined, tokens?: Record<string, string>): Record<string, string>;
|
|
509
|
+
/**
|
|
510
|
+
* Light or dark for the provider form, so it does not paint a white card inside a dark page. Order: the
|
|
511
|
+
* `--sf-pay-scheme` token (`light` / `dark`), then the element's `color-scheme` (`light dark` follows the system
|
|
512
|
+
* preference). `null` when nothing says it (the provider default).
|
|
513
|
+
*/
|
|
514
|
+
declare function readPaymentScheme(el: Element | null | undefined): 'light' | 'dark' | null;
|
|
479
515
|
|
|
480
|
-
export { CASH_POINT_FIELD, type EmbeddedPaymentState, type EmbeddedPaymentStatus, type FetchTransportOptions, type LoadScriptOptions, MERCADOPAGO_BRICKS_KIND, type MercadoPagoAdapterOptions, type MercadoPagoCtor, type MountedPaymentForm, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PayChoices, PaymentBrick, type PaymentBrickHandle, type PaymentBrickProps, PaymentChallenge, type PaymentChallengeProps, type PaymentEvent, type PaymentFallbackReason, type PaymentFormAdapter, type PaymentFormData, type PaymentFormError, type PaymentFormMountOptions, PaymentHttpError, type PaymentMethodClassNames, type PaymentMethodMessages, PaymentMethodSection, type PaymentMethodSectionProps, type PaymentMethodTestIds, type PaymentSubmitRequest, type PaymentTransport, type UseEmbeddedPaymentOptions, VoucherCard, type VoucherCardProps, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
|
516
|
+
export { CASH_POINT_FIELD, type EmbeddedPaymentState, type EmbeddedPaymentStatus, type FetchTransportOptions, type LoadScriptOptions, MERCADOPAGO_BRICKS_KIND, type MercadoPagoAdapterOptions, type MercadoPagoCtor, type MountedPaymentForm, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PayChoices, PaymentBrick, type PaymentBrickHandle, type PaymentBrickProps, PaymentChallenge, type PaymentChallengeProps, type PaymentEvent, type PaymentFallbackReason, type PaymentFormAdapter, type PaymentFormData, type PaymentFormError, type PaymentFormMountOptions, PaymentHttpError, type PaymentMethodClassNames, type PaymentMethodMessages, PaymentMethodSection, type PaymentMethodSectionProps, type PaymentMethodTestIds, type PaymentSubmitRequest, type PaymentTransport, type UseEmbeddedPaymentOptions, VoucherCard, type VoucherCardProps, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentScheme, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
package/dist/payments.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isSafeCssValue } from './chunk-672OTUM2.js';
|
|
2
|
-
import {
|
|
2
|
+
import { findBrand, BrandMark } from './chunk-ODIQR6TG.js';
|
|
3
3
|
export { buildPayChoices, cashProviderData, checkoutToAttempt, choiceValue, parseChoice, payErrorResponse, paymentCsp, paymentCspHeaderName, paymentCspHeaders, paymentCspMode, paymentNonce, paymentNonceFromHeaders, voucherRows } from './chunk-ISEOCKIR.js';
|
|
4
4
|
import { useModalDialog } from './chunk-ZBH7JYU4.js';
|
|
5
5
|
import { useResolvedLocale } from './chunk-T52H5HL3.js';
|
|
@@ -108,7 +108,8 @@ function mercadoPagoBricksAdapter(options = {}) {
|
|
|
108
108
|
// fila de método de pago y se veía cortado (p. ej. AMEX partido). hideFormTitle oculta
|
|
109
109
|
// la línea del título y las banderas.
|
|
110
110
|
hideFormTitle: true,
|
|
111
|
-
|
|
111
|
+
// Dark page: the Brick's `dark` base theme, so it does not draw a white card; the shop tokens refine it.
|
|
112
|
+
style: { theme: opts.colorScheme === "dark" ? "dark" : "default", ...opts.theme && Object.keys(opts.theme).length ? { customVariables: opts.theme } : {} }
|
|
112
113
|
}
|
|
113
114
|
},
|
|
114
115
|
callbacks: {
|
|
@@ -152,7 +153,13 @@ var PAYMENT_THEME_TOKENS = {
|
|
|
152
153
|
"--sf-pay-error": "errorColor",
|
|
153
154
|
"--sf-pay-success": "successColor",
|
|
154
155
|
"--sf-pay-outline": "outlinePrimaryColor",
|
|
155
|
-
"--sf-pay-radius": "borderRadiusMedium"
|
|
156
|
+
"--sf-pay-radius": "borderRadiusMedium",
|
|
157
|
+
"--sf-pay-radius-small": "borderRadiusSmall",
|
|
158
|
+
"--sf-pay-radius-large": "borderRadiusLarge",
|
|
159
|
+
"--sf-pay-outline-secondary": "outlineSecondaryColor",
|
|
160
|
+
"--sf-pay-primary-variant": "baseColorFirstVariant",
|
|
161
|
+
"--sf-pay-input-border-width": "inputBorderWidth",
|
|
162
|
+
"--sf-pay-form-padding": "formPadding"
|
|
156
163
|
};
|
|
157
164
|
function readPaymentTheme(el, tokens = PAYMENT_THEME_TOKENS) {
|
|
158
165
|
const out = {};
|
|
@@ -164,6 +171,19 @@ function readPaymentTheme(el, tokens = PAYMENT_THEME_TOKENS) {
|
|
|
164
171
|
}
|
|
165
172
|
return out;
|
|
166
173
|
}
|
|
174
|
+
function readPaymentScheme(el) {
|
|
175
|
+
if (!el || typeof getComputedStyle !== "function") return null;
|
|
176
|
+
const style = getComputedStyle(el);
|
|
177
|
+
const token = style.getPropertyValue("--sf-pay-scheme").trim();
|
|
178
|
+
if (token === "dark" || token === "light") return token;
|
|
179
|
+
const cs = (style.getPropertyValue("color-scheme") || style.colorScheme || "").toLowerCase();
|
|
180
|
+
const dark = /\bdark\b/.test(cs);
|
|
181
|
+
const light = /\blight\b/.test(cs);
|
|
182
|
+
if (dark && !light) return "dark";
|
|
183
|
+
if (light && !dark) return "light";
|
|
184
|
+
if (dark && light && typeof matchMedia === "function") return matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
167
187
|
|
|
168
188
|
// src/payments/use-embedded-payment.ts
|
|
169
189
|
var DEFAULT_ADAPTERS = {};
|
|
@@ -289,6 +309,7 @@ function useEmbeddedPayment(options) {
|
|
|
289
309
|
await adapter.load(client, { ...live.current.nonce ? { nonce: live.current.nonce } : {}, timeoutMs: sdkTimeoutMs });
|
|
290
310
|
if (stale()) return;
|
|
291
311
|
const theme = live.current.theme ?? readPaymentTheme(container);
|
|
312
|
+
const colorScheme = live.current.colorScheme ?? readPaymentScheme(container);
|
|
292
313
|
const m = await adapter.mount({
|
|
293
314
|
container,
|
|
294
315
|
client,
|
|
@@ -296,6 +317,7 @@ function useEmbeddedPayment(options) {
|
|
|
296
317
|
...live.current.email ? { email: live.current.email } : {},
|
|
297
318
|
...live.current.locale ? { locale: live.current.locale } : {},
|
|
298
319
|
theme,
|
|
320
|
+
...colorScheme ? { colorScheme } : {},
|
|
299
321
|
onReady: () => {
|
|
300
322
|
if (stale()) return;
|
|
301
323
|
clearTimeout(timer);
|
|
@@ -649,6 +671,8 @@ var ES = {
|
|
|
649
671
|
legend: "M\xE9todo de pago",
|
|
650
672
|
pay: "Pagar",
|
|
651
673
|
placeOrder: "Realizar el pedido",
|
|
674
|
+
placeOrderCash: "Generar ficha de pago",
|
|
675
|
+
chooseDelivery: "Elige la entrega para continuar",
|
|
652
676
|
payRedirect: "Continuar al pago",
|
|
653
677
|
continue: "Continuar",
|
|
654
678
|
retryAddress: "Guardar direcci\xF3n y continuar",
|
|
@@ -677,6 +701,8 @@ var EN = {
|
|
|
677
701
|
legend: "Payment method",
|
|
678
702
|
pay: "Pay",
|
|
679
703
|
placeOrder: "Place order",
|
|
704
|
+
placeOrderCash: "Get payment slip",
|
|
705
|
+
chooseDelivery: "Choose delivery to continue",
|
|
680
706
|
payRedirect: "Continue to payment",
|
|
681
707
|
continue: "Continue",
|
|
682
708
|
retryAddress: "Save address and continue",
|
|
@@ -715,6 +741,26 @@ function formFields(form) {
|
|
|
715
741
|
for (const [k, v] of new FormData(form).entries()) if (typeof v === "string") out[k] = v;
|
|
716
742
|
return out;
|
|
717
743
|
}
|
|
744
|
+
var CHOICE_STORAGE_PREFIX = "sf:pay-choice:";
|
|
745
|
+
function readStoredChoice(scope) {
|
|
746
|
+
if (!scope || typeof window === "undefined") return null;
|
|
747
|
+
try {
|
|
748
|
+
const raw = window.sessionStorage.getItem(CHOICE_STORAGE_PREFIX + scope);
|
|
749
|
+
if (!raw) return null;
|
|
750
|
+
const v = JSON.parse(raw);
|
|
751
|
+
return typeof v?.choice === "string" ? v : null;
|
|
752
|
+
} catch {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function writeStoredChoice(scope, value) {
|
|
757
|
+
if (!scope || typeof window === "undefined") return;
|
|
758
|
+
try {
|
|
759
|
+
window.sessionStorage.setItem(CHOICE_STORAGE_PREFIX + scope, JSON.stringify(value));
|
|
760
|
+
} catch {
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
718
764
|
var useHydrated = () => useSyncExternalStore(
|
|
719
765
|
() => () => {
|
|
720
766
|
},
|
|
@@ -751,12 +797,37 @@ function PaymentMethodSection(props) {
|
|
|
751
797
|
classNames: cx = {},
|
|
752
798
|
testIds = {},
|
|
753
799
|
hideSubmit,
|
|
754
|
-
brickProps
|
|
800
|
+
brickProps,
|
|
801
|
+
rememberChoice = true,
|
|
802
|
+
cashPointsVisible,
|
|
803
|
+
payerEmailField = "email"
|
|
755
804
|
} = props;
|
|
756
805
|
const locale = useResolvedLocale(props.locale);
|
|
757
806
|
const m = useMemo(() => paymentMethodMessages(locale, props.messages), [locale, props.messages]);
|
|
758
807
|
const hydrated = useHydrated();
|
|
759
|
-
const [choiceValue2,
|
|
808
|
+
const [choiceValue2, setChoiceValueState] = useState(props.defaultChoice ?? choices.defaultValue);
|
|
809
|
+
const remember = rememberChoice && Boolean(scope);
|
|
810
|
+
const rootRef = useRef(null);
|
|
811
|
+
const [storedPoint, setStoredPoint] = useState(null);
|
|
812
|
+
const setChoiceValue = (v) => {
|
|
813
|
+
setChoiceValueState(v);
|
|
814
|
+
if (remember) writeStoredChoice(scope, { choice: v, point: readCheckedPoint(rootRef.current) });
|
|
815
|
+
};
|
|
816
|
+
useEffect(() => {
|
|
817
|
+
if (!remember) return;
|
|
818
|
+
const stored = readStoredChoice(scope);
|
|
819
|
+
if (!stored) return;
|
|
820
|
+
if (choices.choices.some((c) => c.value === stored.choice)) setChoiceValueState(stored.choice);
|
|
821
|
+
if (stored.point) setStoredPoint(stored.point);
|
|
822
|
+
}, [remember, scope]);
|
|
823
|
+
useEffect(() => {
|
|
824
|
+
if (!storedPoint || !rootRef.current) return;
|
|
825
|
+
const input = Array.from(rootRef.current.querySelectorAll(`input[name="${CASH_POINT_FIELD}"]`)).find((i) => i.value === storedPoint);
|
|
826
|
+
if (input) input.checked = true;
|
|
827
|
+
}, [storedPoint, choiceValue2]);
|
|
828
|
+
const onPointChange = (point) => {
|
|
829
|
+
if (remember && choiceValue2) writeStoredChoice(scope, { choice: choiceValue2, point });
|
|
830
|
+
};
|
|
760
831
|
const selected = choices.choices.find((c) => c.value === choiceValue2) ?? null;
|
|
761
832
|
const noPayment = choices.choices.length === 0;
|
|
762
833
|
const tid = (k) => testIds[k] ? { "data-testid": testIds[k] } : {};
|
|
@@ -807,8 +878,33 @@ function PaymentMethodSection(props) {
|
|
|
807
878
|
}
|
|
808
879
|
onEvent?.(e);
|
|
809
880
|
};
|
|
881
|
+
const [payerEmail, setPayerEmail] = useState(void 0);
|
|
882
|
+
useEffect(() => {
|
|
883
|
+
const form = formRef.current;
|
|
884
|
+
if (!payerEmailField || !form) return;
|
|
885
|
+
const selector = `[name="${typeof CSS !== "undefined" && CSS.escape ? CSS.escape(payerEmailField) : payerEmailField}"]`;
|
|
886
|
+
const read = () => {
|
|
887
|
+
const v = String(form.querySelector(selector)?.value ?? "").trim();
|
|
888
|
+
setPayerEmail(EMAIL_RE.test(v) ? v : void 0);
|
|
889
|
+
};
|
|
890
|
+
read();
|
|
891
|
+
const onChange = (e) => {
|
|
892
|
+
if (e.target?.name === payerEmailField) read();
|
|
893
|
+
};
|
|
894
|
+
form.addEventListener("change", onChange);
|
|
895
|
+
return () => form.removeEventListener("change", onChange);
|
|
896
|
+
}, [formRef, payerEmailField]);
|
|
810
897
|
const total = wantSync && (!settled || requote) ? null : renderAmount ? renderAmount(amount) : formatMoney(amount, locale);
|
|
811
|
-
const label = retryAddress ? m.retryAddress : addressFirst ? m.continue :
|
|
898
|
+
const label = retryAddress ? m.retryAddress : addressFirst ? m.continue : !deliveryReady && selected ? (
|
|
899
|
+
// Says what is missing instead of a button that silently does nothing.
|
|
900
|
+
m.chooseDelivery
|
|
901
|
+
) : selected?.mode === "cash" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
902
|
+
m.placeOrderCash,
|
|
903
|
+
total ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
904
|
+
" ",
|
|
905
|
+
total
|
|
906
|
+
] }) : null
|
|
907
|
+
] }) : selected?.mode === "plain" || !selected ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
812
908
|
m.pay,
|
|
813
909
|
total ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
814
910
|
" ",
|
|
@@ -822,6 +918,11 @@ function PaymentMethodSection(props) {
|
|
|
822
918
|
] }) : null
|
|
823
919
|
] });
|
|
824
920
|
function onPayClick(event) {
|
|
921
|
+
if (!addressFirst && !retryAddress && !deliveryReady && selected) {
|
|
922
|
+
event.preventDefault();
|
|
923
|
+
formRef.current?.reportValidity();
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
825
926
|
if (!cardActive || syncFailed) return;
|
|
826
927
|
event.preventDefault();
|
|
827
928
|
const form = formRef.current;
|
|
@@ -830,7 +931,7 @@ function PaymentMethodSection(props) {
|
|
|
830
931
|
}
|
|
831
932
|
const cardNotice = (k, node) => k === "syncFailed" ? /* @__PURE__ */ jsx("p", { role: "alert", className: cx.alert, "data-sf-pay-notice": "sync-failed", ...tid("syncFailed"), children: node }) : /* @__PURE__ */ jsx("p", { role: "status", className: cx.status, "data-sf-pay-notice": k, ...k === "syncing" ? tid("syncing") : {}, children: node });
|
|
832
933
|
const Link = renderLink ?? (({ href, className, children, testId }) => /* @__PURE__ */ jsx("a", { href, className, ...testId ? { "data-testid": testId } : {}, children }));
|
|
833
|
-
return /* @__PURE__ */ jsxs("fieldset", { id: "pago", className: cx.root, "data-sf-pay-method": true, children: [
|
|
934
|
+
return /* @__PURE__ */ jsxs("fieldset", { id: "pago", ref: rootRef, className: cx.root, "data-sf-pay-method": true, children: [
|
|
834
935
|
/* @__PURE__ */ jsx("legend", { className: cx.legend, children: m.legend }),
|
|
835
936
|
choices.choices.map((choice) => {
|
|
836
937
|
const { label: rowLabel, hint } = rowText(choice, m, methodLabel);
|
|
@@ -838,6 +939,7 @@ function PaymentMethodSection(props) {
|
|
|
838
939
|
const slot = choice.option ?? "plain";
|
|
839
940
|
const icon = icons?.[slot] ?? (brandMarks ? defaultIcon(choice) : null);
|
|
840
941
|
const marks = brandMarks ? rowMarks(choice, cardBrands) : [];
|
|
942
|
+
const brandMarkIcon = !icons?.[slot] && brandMarks && choice.option !== "card" && choice.option !== "cash" && !!findBrand(choice.methodKey);
|
|
841
943
|
return /* @__PURE__ */ jsxs("div", { className: cx.choice, "data-sf-pay-choice": true, children: [
|
|
842
944
|
/* @__PURE__ */ jsxs("label", { className: cx.radioLabel, children: [
|
|
843
945
|
/* @__PURE__ */ jsx(
|
|
@@ -855,7 +957,11 @@ function PaymentMethodSection(props) {
|
|
|
855
957
|
...tid("method")
|
|
856
958
|
}
|
|
857
959
|
),
|
|
858
|
-
icon ?
|
|
960
|
+
icon ? (
|
|
961
|
+
// The default mark of a provider row is as wide as its logo: it does not take the shop's `icon` box (a fixed
|
|
962
|
+
// square would let the logo spill over the radio and the text).
|
|
963
|
+
/* @__PURE__ */ jsx("span", { className: brandMarkIcon ? void 0 : cx.icon, "data-sf-pay-icon": brandMarkIcon ? "mark" : void 0, "aria-hidden": "true", children: icon })
|
|
964
|
+
) : null,
|
|
859
965
|
/* @__PURE__ */ jsxs("span", { className: cx.labelText, children: [
|
|
860
966
|
rowLabel,
|
|
861
967
|
hint ? /* @__PURE__ */ jsxs("span", { className: cx.hint, children: [
|
|
@@ -865,38 +971,40 @@ function PaymentMethodSection(props) {
|
|
|
865
971
|
] }),
|
|
866
972
|
marks.length ? /* @__PURE__ */ jsx("span", { className: cx.brands, "data-sf-pay-brands": choice.option ?? "plain", "aria-hidden": "true", children: marks.map((mk) => /* @__PURE__ */ jsx(BrandMark, { brand: mk.key, logoUrl: mk.logoUrl ?? null, size: 20 }, mk.key)) }) : null
|
|
867
973
|
] }),
|
|
868
|
-
/* @__PURE__ */ jsx(ChoicePanel, { choice, m, invalid, cx, tid, hidden: hydrated && !checked, marks: brandMarks })
|
|
974
|
+
/* @__PURE__ */ jsx(ChoicePanel, { choice, m, invalid, cx, tid, hidden: hydrated && !checked, marks: brandMarks, visible: cashPointsVisible, openMore: storedPoint, onPointChange }),
|
|
975
|
+
choice.mode === "card" && checked && cardChosen && hydrated && choices.cardClient ? /* @__PURE__ */ jsxs("div", { className: cx.brickWrap, "data-sf-pay-card": true, ...tid("card"), children: [
|
|
976
|
+
fallback ? null : !deliveryReady ? cardNotice("pickDelivery", m.pickDeliveryFirst) : syncFailed ? cardNotice("syncFailed", m.syncFailed) : requote ? cardNotice("requote", m.quoteChanged) : !synced ? cardNotice("syncing", m.updatingTotal) : null,
|
|
977
|
+
brickReady || fallback ? /* @__PURE__ */ jsx(
|
|
978
|
+
PaymentBrick,
|
|
979
|
+
{
|
|
980
|
+
...brickProps,
|
|
981
|
+
ref: brick,
|
|
982
|
+
client: choices.cardClient,
|
|
983
|
+
amount,
|
|
984
|
+
transport,
|
|
985
|
+
...nonce ? { nonce } : {},
|
|
986
|
+
locale,
|
|
987
|
+
...scope ? { scope } : {},
|
|
988
|
+
...payerEmail && !brickProps?.email ? { email: payerEmail } : {},
|
|
989
|
+
enabled: brickReady,
|
|
990
|
+
...cx.brick ? { className: cx.brick } : {},
|
|
991
|
+
onEvent: handleEvent,
|
|
992
|
+
onFallback: () => setFallback(true),
|
|
993
|
+
onResult: (o) => {
|
|
994
|
+
if (o.kind === "approved" || o.kind === "in_review" || o.kind === "voucher") onDone(o);
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
payerEmail || brickProps?.email ? "with-email" : "without-email"
|
|
998
|
+
) : null,
|
|
999
|
+
/* @__PURE__ */ jsx("p", { className: cx.note, children: m.secureCard }),
|
|
1000
|
+
expired && rebuildHref ? Link({ href: rebuildHref, ...cx.rebuild ? { className: cx.rebuild } : {}, children: m.rebuildCart, ...testIds.rebuild ? { testId: testIds.rebuild } : {} }) : null
|
|
1001
|
+
] }) : null
|
|
869
1002
|
] }, choice.value);
|
|
870
1003
|
}),
|
|
871
1004
|
noPayment ? /* @__PURE__ */ jsxs("div", { role: "alert", className: cx.alert, "data-sf-pay-notice": "no-payment", ...tid("noPayment"), children: [
|
|
872
1005
|
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: m.noPaymentTitle }) }),
|
|
873
1006
|
/* @__PURE__ */ jsx("p", { children: m.noPayment })
|
|
874
1007
|
] }) : null,
|
|
875
|
-
cardChosen && hydrated && choices.cardClient ? /* @__PURE__ */ jsxs("div", { className: cx.brickWrap, "data-sf-pay-card": true, ...tid("card"), children: [
|
|
876
|
-
fallback ? null : !deliveryReady ? cardNotice("pickDelivery", m.pickDeliveryFirst) : syncFailed ? cardNotice("syncFailed", m.syncFailed) : requote ? cardNotice("requote", m.quoteChanged) : !synced ? cardNotice("syncing", m.updatingTotal) : null,
|
|
877
|
-
brickReady || fallback ? /* @__PURE__ */ jsx(
|
|
878
|
-
PaymentBrick,
|
|
879
|
-
{
|
|
880
|
-
...brickProps,
|
|
881
|
-
ref: brick,
|
|
882
|
-
client: choices.cardClient,
|
|
883
|
-
amount,
|
|
884
|
-
transport,
|
|
885
|
-
...nonce ? { nonce } : {},
|
|
886
|
-
locale,
|
|
887
|
-
...scope ? { scope } : {},
|
|
888
|
-
enabled: brickReady,
|
|
889
|
-
...cx.brick ? { className: cx.brick } : {},
|
|
890
|
-
onEvent: handleEvent,
|
|
891
|
-
onFallback: () => setFallback(true),
|
|
892
|
-
onResult: (o) => {
|
|
893
|
-
if (o.kind === "approved" || o.kind === "in_review" || o.kind === "voucher") onDone(o);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
) : null,
|
|
897
|
-
/* @__PURE__ */ jsx("p", { className: cx.note, children: m.secureCard }),
|
|
898
|
-
expired && rebuildHref ? Link({ href: rebuildHref, ...cx.rebuild ? { className: cx.rebuild } : {}, children: m.rebuildCart, ...testIds.rebuild ? { testId: testIds.rebuild } : {} }) : null
|
|
899
|
-
] }) : null,
|
|
900
1008
|
noPayment || choices.choices.some((c) => c.option) ? null : /* @__PURE__ */ jsx("p", { className: cx.note, children: m.paymentNote }),
|
|
901
1009
|
hideSubmit ? null : /* @__PURE__ */ jsx(
|
|
902
1010
|
"button",
|
|
@@ -925,16 +1033,33 @@ function ChoicePanel({
|
|
|
925
1033
|
cx,
|
|
926
1034
|
tid,
|
|
927
1035
|
hidden,
|
|
928
|
-
marks = true
|
|
1036
|
+
marks = true,
|
|
1037
|
+
visible,
|
|
1038
|
+
openMore,
|
|
1039
|
+
onPointChange
|
|
929
1040
|
}) {
|
|
930
1041
|
if (choice.mode === "redirect") {
|
|
931
1042
|
return /* @__PURE__ */ jsx("p", { className: cx.panel, hidden, "data-sf-pay-panel": "redirect", ...tid("redirectNote"), children: m.redirectNote });
|
|
932
1043
|
}
|
|
933
1044
|
if (choice.mode !== "cash") return null;
|
|
934
|
-
const
|
|
935
|
-
const
|
|
1045
|
+
const allMain = choice.points.filter((p) => p.group === "main");
|
|
1046
|
+
const cut = typeof visible === "number" && visible > 0 ? visible : allMain.length;
|
|
1047
|
+
const main = allMain.slice(0, cut);
|
|
1048
|
+
const more = [...allMain.slice(cut), ...choice.points.filter((p) => p.group !== "main")];
|
|
1049
|
+
const moreOpen = Boolean(openMore && more.some((p) => p.id === openMore));
|
|
936
1050
|
const row = (p, i, first) => /* @__PURE__ */ jsxs("label", { className: cx.cashPoint, "data-sf-pay-point": true, children: [
|
|
937
|
-
/* @__PURE__ */ jsx(
|
|
1051
|
+
/* @__PURE__ */ jsx(
|
|
1052
|
+
"input",
|
|
1053
|
+
{
|
|
1054
|
+
type: "radio",
|
|
1055
|
+
name: CASH_POINT_FIELD,
|
|
1056
|
+
value: p.id,
|
|
1057
|
+
defaultChecked: first && i === 0,
|
|
1058
|
+
className: cx.cashPointInput,
|
|
1059
|
+
"aria-invalid": invalid?.has("cash_point") || void 0,
|
|
1060
|
+
...onPointChange ? { onChange: () => onPointChange(p.id) } : {}
|
|
1061
|
+
}
|
|
1062
|
+
),
|
|
938
1063
|
marks ? /* @__PURE__ */ jsx(BrandMark, { brand: p.payment_point || p.id, logoUrl: p.logo_url ?? null, size: 22 }) : null,
|
|
939
1064
|
/* @__PURE__ */ jsx("span", { children: p.label })
|
|
940
1065
|
] }, p.id);
|
|
@@ -942,7 +1067,7 @@ function ChoicePanel({
|
|
|
942
1067
|
/* @__PURE__ */ jsxs("fieldset", { children: [
|
|
943
1068
|
/* @__PURE__ */ jsx("legend", { children: m.cashPoints }),
|
|
944
1069
|
/* @__PURE__ */ jsx("div", { "data-sf-pay-points": true, children: main.map((p, i) => row(p, i, true)) }),
|
|
945
|
-
more.length ? /* @__PURE__ */ jsxs("details", { children: [
|
|
1070
|
+
more.length ? /* @__PURE__ */ jsxs("details", { ...moreOpen ? { open: true } : {}, children: [
|
|
946
1071
|
/* @__PURE__ */ jsx("summary", { className: cx.cashMore, style: { minHeight: 44 }, children: m.cashMore }),
|
|
947
1072
|
/* @__PURE__ */ jsx("div", { "data-sf-pay-points": true, children: more.map((p, i) => row(p, i, false)) })
|
|
948
1073
|
] }) : null
|
|
@@ -958,6 +1083,10 @@ function defaultIcon(choice) {
|
|
|
958
1083
|
if (choice.option === "cash") return glyph(CASH_GLYPH);
|
|
959
1084
|
return findBrand(choice.methodKey) ? /* @__PURE__ */ jsx(BrandMark, { brand: choice.methodKey, size: 24 }) : null;
|
|
960
1085
|
}
|
|
1086
|
+
function readCheckedPoint(root) {
|
|
1087
|
+
const el = root?.querySelector(`input[name="${CASH_POINT_FIELD}"]:checked`);
|
|
1088
|
+
return el?.value ?? null;
|
|
1089
|
+
}
|
|
961
1090
|
function rowMarks(choice, cardBrands) {
|
|
962
1091
|
if (choice.option === "card") return cardBrands.map((key) => ({ key }));
|
|
963
1092
|
if (choice.option === "cash") {
|
|
@@ -975,6 +1104,6 @@ function rowMarks(choice, cardBrands) {
|
|
|
975
1104
|
return [];
|
|
976
1105
|
}
|
|
977
1106
|
|
|
978
|
-
export { CASH_POINT_FIELD, MERCADOPAGO_BRICKS_KIND, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PaymentBrick, PaymentChallenge, PaymentHttpError, PaymentMethodSection, VoucherCard, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
|
1107
|
+
export { CASH_POINT_FIELD, MERCADOPAGO_BRICKS_KIND, PAYMENT_CHOICE_FIELD, PAYMENT_THEME_TOKENS, PaymentBrick, PaymentChallenge, PaymentHttpError, PaymentMethodSection, VoucherCard, createFetchTransport, formFields, loadPaymentSdk, mercadoPagoBricksAdapter, paymentMethodMessages, readPaymentScheme, readPaymentTheme, resetPaymentSdkCache, sanitizeMercadoPagoFormData, useEmbeddedPayment };
|
|
979
1108
|
//# sourceMappingURL=payments.js.map
|
|
980
1109
|
//# sourceMappingURL=payments.js.map
|