@asteby/storefront-react 0.8.0 → 0.10.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 +60 -1
- package/dist/cart.js +2 -1
- package/dist/cart.js.map +1 -1
- package/dist/checkout.cjs +440 -0
- package/dist/checkout.cjs.map +1 -0
- package/dist/checkout.css +100 -0
- package/dist/checkout.d.cts +197 -0
- package/dist/checkout.d.ts +197 -0
- package/dist/checkout.js +243 -0
- package/dist/checkout.js.map +1 -0
- package/dist/choices-DEPE9KRq.d.cts +130 -0
- package/dist/choices-DEPE9KRq.d.ts +130 -0
- package/dist/chunk-DSZVJ2PW.js +180 -0
- package/dist/chunk-DSZVJ2PW.js.map +1 -0
- package/dist/chunk-ISEOCKIR.js +160 -0
- package/dist/chunk-ISEOCKIR.js.map +1 -0
- package/dist/chunk-T52H5HL3.js +11 -0
- package/dist/chunk-T52H5HL3.js.map +1 -0
- package/dist/{chunk-2WZIWIBW.js → chunk-ZBH7JYU4.js} +4 -10
- package/dist/chunk-ZBH7JYU4.js.map +1 -0
- package/dist/payments-server.cjs +369 -0
- package/dist/payments-server.cjs.map +1 -0
- package/dist/payments-server.d.cts +145 -0
- package/dist/payments-server.d.ts +145 -0
- package/dist/payments-server.js +191 -0
- package/dist/payments-server.js.map +1 -0
- package/dist/payments.cjs +639 -2
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.css +57 -0
- package/dist/payments.d.cts +137 -21
- package/dist/payments.d.ts +137 -21
- package/dist/payments.js +332 -37
- package/dist/payments.js.map +1 -1
- package/dist/promotions.js +2 -1
- package/dist/promotions.js.map +1 -1
- package/package.json +24 -2
- package/dist/chunk-2WZIWIBW.js.map +0 -1
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/checkout/brands.ts
|
|
4
|
+
var B = (key, name, kind, bg, fg, mark, shape) => ({
|
|
5
|
+
key,
|
|
6
|
+
name,
|
|
7
|
+
kind,
|
|
8
|
+
bg,
|
|
9
|
+
fg,
|
|
10
|
+
...mark ? { mark } : {},
|
|
11
|
+
...shape ? { shape } : {}
|
|
12
|
+
});
|
|
13
|
+
var LIST = [
|
|
14
|
+
// Parcel carriers (Mexico and global).
|
|
15
|
+
B("fedex", "FedEx", "carrier", "#4D148C", "#FFFFFF"),
|
|
16
|
+
B("dhl", "DHL", "carrier", "#FFCC00", "#B00410"),
|
|
17
|
+
B("estafeta", "Estafeta", "carrier", "#C8102E", "#FFFFFF"),
|
|
18
|
+
B("paquetexpress", "Paquetexpress", "carrier", "#0B4EA2", "#FFFFFF", "Paquet\nexpress"),
|
|
19
|
+
B("ups", "UPS", "carrier", "#351C15", "#FFB500"),
|
|
20
|
+
B("redpack", "Redpack", "carrier", "#C8102E", "#FFFFFF"),
|
|
21
|
+
B("99minutos", "99 Minutos", "carrier", "#00704A", "#FFFFFF", "99"),
|
|
22
|
+
B("jtexpress", "J&T Express", "carrier", "#C8102E", "#FFFFFF", "J&T"),
|
|
23
|
+
B("sendex", "Sendex", "carrier", "#003A70", "#FFFFFF"),
|
|
24
|
+
B("ampm", "AMPM", "carrier", "#1D1D1B", "#FFFFFF"),
|
|
25
|
+
B("tresguerras", "Tresguerras", "carrier", "#005BAC", "#FFFFFF", "3G"),
|
|
26
|
+
B("quiken", "Quiken", "carrier", "#1D1D1B", "#FFFFFF"),
|
|
27
|
+
B("imile", "iMile", "carrier", "#0057B8", "#FFFFFF"),
|
|
28
|
+
B("carssa", "Carssa", "carrier", "#00529B", "#FFFFFF"),
|
|
29
|
+
B("correosdemexico", "Correos de M\xE9xico", "carrier", "#7A1E3A", "#FFFFFF", "Correos\nM\xE9xico"),
|
|
30
|
+
B("usps", "USPS", "carrier", "#333366", "#FFFFFF"),
|
|
31
|
+
B("canadapost", "Canada Post", "carrier", "#DA291C", "#FFFFFF", "CPC"),
|
|
32
|
+
// Card networks.
|
|
33
|
+
B("visa", "Visa", "card", "#1A1F71", "#FFFFFF", "VISA"),
|
|
34
|
+
B("mastercard", "Mastercard", "card", "#FFFFFF", "#1D1D1B", "MC", "mastercard"),
|
|
35
|
+
B("amex", "American Express", "card", "#1F72CD", "#FFFFFF", "AMEX"),
|
|
36
|
+
B("carnet", "Carnet", "card", "#003B71", "#FFFFFF"),
|
|
37
|
+
// Wallets and payment providers.
|
|
38
|
+
B("mercadopago", "Mercado Pago", "wallet", "#00B1EA", "#0B1F4E", "mercado\npago"),
|
|
39
|
+
B("paypal", "PayPal", "wallet", "#003087", "#FFFFFF"),
|
|
40
|
+
B("clip", "Clip", "wallet", "#FC4C02", "#1D1D1B"),
|
|
41
|
+
B("applepay", "Apple Pay", "wallet", "#000000", "#FFFFFF", "Pay"),
|
|
42
|
+
B("googlepay", "Google Pay", "wallet", "#FFFFFF", "#3C4043", "G Pay"),
|
|
43
|
+
// Cash points and transfers (Mexico).
|
|
44
|
+
B("oxxo", "OXXO", "cash", "#E21E26", "#FFE600"),
|
|
45
|
+
B("spei", "SPEI", "bank", "#14365F", "#FFFFFF"),
|
|
46
|
+
B("stp", "STP", "bank", "#14365F", "#FFFFFF", "SPEI"),
|
|
47
|
+
B("7eleven", "7-Eleven", "cash", "#00704A", "#FFFFFF", "7-11"),
|
|
48
|
+
B("circlek", "Circle K", "cash", "#DA291C", "#FFFFFF", "K"),
|
|
49
|
+
B("soriana", "Soriana", "cash", "#C8102E", "#FFFFFF"),
|
|
50
|
+
B("extra", "Extra", "cash", "#E35205", "#FFFFFF"),
|
|
51
|
+
B("kiosko", "Kiosko", "cash", "#C8102E", "#FFFFFF"),
|
|
52
|
+
B("calimax", "Calimax", "cash", "#D52B1E", "#FFFFFF"),
|
|
53
|
+
B("farmaciasyza", "Farmacias Yza", "cash", "#0A5A9C", "#FFFFFF", "Yza"),
|
|
54
|
+
B("chedraui", "Chedraui", "cash", "#0047BB", "#FFFFFF"),
|
|
55
|
+
B("casaley", "Casa Ley", "cash", "#C8102E", "#FFFFFF", "Ley"),
|
|
56
|
+
B("telecomm", "Telecomm", "cash", "#6F1D46", "#FFFFFF"),
|
|
57
|
+
B("walmart", "Walmart", "cash", "#0071CE", "#FFFFFF"),
|
|
58
|
+
B("santander", "Santander", "bank", "#C00000", "#FFFFFF"),
|
|
59
|
+
B("bbva", "BBVA", "bank", "#004481", "#FFFFFF"),
|
|
60
|
+
B("citibanamex", "Citibanamex", "bank", "#004B8D", "#FFFFFF", "Citi"),
|
|
61
|
+
B("banorte", "Banorte", "bank", "#C8102E", "#FFFFFF")
|
|
62
|
+
];
|
|
63
|
+
var ALIASES = {
|
|
64
|
+
fedexmx: "fedex",
|
|
65
|
+
fedexexpress: "fedex",
|
|
66
|
+
dhlexpress: "dhl",
|
|
67
|
+
dhlmx: "dhl",
|
|
68
|
+
paquetexpres: "paquetexpress",
|
|
69
|
+
paqueteexpress: "paquetexpress",
|
|
70
|
+
jt: "jtexpress",
|
|
71
|
+
jandtexpress: "jtexpress",
|
|
72
|
+
noventaynueveminutos: "99minutos",
|
|
73
|
+
correos: "correosdemexico",
|
|
74
|
+
sepomex: "correosdemexico",
|
|
75
|
+
master: "mastercard",
|
|
76
|
+
americanexpress: "amex",
|
|
77
|
+
mercadopagomx: "mercadopago",
|
|
78
|
+
mp: "mercadopago",
|
|
79
|
+
clabe: "spei",
|
|
80
|
+
banktransfer: "spei",
|
|
81
|
+
seveneleven: "7eleven",
|
|
82
|
+
"711": "7eleven",
|
|
83
|
+
circulok: "circlek",
|
|
84
|
+
yza: "farmaciasyza",
|
|
85
|
+
bancomer: "bbva",
|
|
86
|
+
banamex: "citibanamex",
|
|
87
|
+
ley: "casaley"
|
|
88
|
+
};
|
|
89
|
+
var BY_KEY = new Map(LIST.map((b) => [b.key, b]));
|
|
90
|
+
function brandKey(raw) {
|
|
91
|
+
const flat = (raw ?? "").normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]/g, "");
|
|
92
|
+
const noCountry = flat.endsWith("mexico") && flat !== "correosdemexico" ? flat.slice(0, -6) : flat;
|
|
93
|
+
return ALIASES[noCountry] ?? (BY_KEY.has(noCountry) ? noCountry : ALIASES[flat] ?? flat);
|
|
94
|
+
}
|
|
95
|
+
function findBrand(raw) {
|
|
96
|
+
return BY_KEY.get(brandKey(raw)) ?? null;
|
|
97
|
+
}
|
|
98
|
+
function brandName(raw) {
|
|
99
|
+
const brand = findBrand(raw);
|
|
100
|
+
if (brand) return brand.name;
|
|
101
|
+
const text = (raw ?? "").trim();
|
|
102
|
+
if (!text) return null;
|
|
103
|
+
if (text !== text.toLowerCase() && text !== text.toUpperCase()) return text;
|
|
104
|
+
return text.toLowerCase().split(/[\s_-]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
105
|
+
}
|
|
106
|
+
function listBrands(kind) {
|
|
107
|
+
return kind ? LIST.filter((b) => b.kind === kind) : [...LIST];
|
|
108
|
+
}
|
|
109
|
+
function safeLogo(url) {
|
|
110
|
+
if (!url) return null;
|
|
111
|
+
try {
|
|
112
|
+
return new URL(url).protocol === "https:" ? url : null;
|
|
113
|
+
} catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function monogram(raw) {
|
|
118
|
+
const words = (brandName(raw) ?? raw).split(/\s+/).filter(Boolean);
|
|
119
|
+
const letters = words.length > 1 ? words.slice(0, 2).map((w) => w[0]) : [(words[0] ?? "?").slice(0, 2)];
|
|
120
|
+
return letters.join("").toUpperCase();
|
|
121
|
+
}
|
|
122
|
+
function BrandMark({ brand, logoUrl, size = 24, title, className }) {
|
|
123
|
+
const height = size;
|
|
124
|
+
const width = Math.round(size * 1.5);
|
|
125
|
+
const a11y = title ? { role: "img", "aria-label": title } : { "aria-hidden": true };
|
|
126
|
+
const logo = safeLogo(logoUrl);
|
|
127
|
+
const found = findBrand(brand);
|
|
128
|
+
const key = found?.key ?? "generic";
|
|
129
|
+
const style = { width, height, flex: "none" };
|
|
130
|
+
if (logo) {
|
|
131
|
+
return /* @__PURE__ */ jsx(
|
|
132
|
+
"img",
|
|
133
|
+
{
|
|
134
|
+
src: logo,
|
|
135
|
+
alt: title ?? "",
|
|
136
|
+
width,
|
|
137
|
+
height,
|
|
138
|
+
loading: "lazy",
|
|
139
|
+
decoding: "async",
|
|
140
|
+
className,
|
|
141
|
+
style: { ...style, objectFit: "contain" },
|
|
142
|
+
"data-sf-brand-mark": key,
|
|
143
|
+
...title ? {} : { "aria-hidden": true }
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const ring = "var(--sf-brand-mark-ring, rgb(127 127 127 / 0.35))";
|
|
148
|
+
if (found?.shape === "mastercard") {
|
|
149
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 32", width, height, className, style, "data-sf-brand-mark": key, focusable: "false", ...a11y, children: [
|
|
150
|
+
/* @__PURE__ */ jsx("rect", { x: "0.5", y: "0.5", width: "47", height: "31", rx: "5", fill: found.bg, stroke: ring }),
|
|
151
|
+
/* @__PURE__ */ jsx("circle", { cx: "19", cy: "16", r: "9", fill: "#EB001B" }),
|
|
152
|
+
/* @__PURE__ */ jsx("circle", { cx: "29", cy: "16", r: "9", fill: "#F79E1B" }),
|
|
153
|
+
/* @__PURE__ */ jsx("path", { d: "M24 8.52a9 9 0 0 1 0 14.96a9 9 0 0 1 0-14.96z", fill: "#FF5F00" })
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
const text = found ? found.mark ?? found.name : monogram(brand ?? "");
|
|
157
|
+
const bg = found?.bg ?? "var(--sf-brand-mark-bg, #E7E9EE)";
|
|
158
|
+
const fg = found?.fg ?? "var(--sf-brand-mark-fg, #2B2F38)";
|
|
159
|
+
const lines = text.split("\n");
|
|
160
|
+
const longest = Math.max(...lines.map((l) => l.length));
|
|
161
|
+
const fontSize = lines.length > 1 ? longest <= 5 ? 11 : 9.5 : longest <= 2 ? 15 : longest <= 4 ? 12 : 10;
|
|
162
|
+
const fit = (l) => l.length > 5 ? { textLength: 40, lengthAdjust: "spacingAndGlyphs" } : {};
|
|
163
|
+
const italic = found?.key === "visa" || found?.key === "fedex" ? "italic" : void 0;
|
|
164
|
+
const common = {
|
|
165
|
+
textAnchor: "middle",
|
|
166
|
+
fill: fg,
|
|
167
|
+
fontFamily: "system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif",
|
|
168
|
+
fontWeight: 800,
|
|
169
|
+
fontSize,
|
|
170
|
+
fontStyle: italic
|
|
171
|
+
};
|
|
172
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 32", width, height, className, style, "data-sf-brand-mark": key, focusable: "false", ...a11y, children: [
|
|
173
|
+
/* @__PURE__ */ jsx("rect", { x: "0.5", y: "0.5", width: "47", height: "31", rx: "5", fill: bg, stroke: ring }),
|
|
174
|
+
lines.length > 1 ? lines.slice(0, 2).map((l, i) => /* @__PURE__ */ jsx("text", { x: "24", y: i === 0 ? 15 : 25.5, ...common, ...fit(l), children: l }, i)) : /* @__PURE__ */ jsx("text", { x: "24", y: "16", dominantBaseline: "central", letterSpacing: longest <= 4 ? 0.3 : 0, ...common, ...fit(text), children: text })
|
|
175
|
+
] });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export { BrandMark, brandKey, brandName, findBrand, listBrands };
|
|
179
|
+
//# sourceMappingURL=chunk-DSZVJ2PW.js.map
|
|
180
|
+
//# sourceMappingURL=chunk-DSZVJ2PW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkout/brands.ts","../src/checkout/brand-mark.tsx"],"names":[],"mappings":"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","file":"chunk-DSZVJ2PW.js","sourcesContent":["/**\n * Shared catalog of the brands a checkout names: parcel carriers, card networks, wallets and cash payment points.\n *\n * Keys are the stable identifiers the providers already send (`ShippingRate.carrier` of Skydropx / Envía, the\n * `PaymentPoint.payment_point` or `id` of the payment addon, a `PaymentMethod.key`). Nothing here decides what a shop\n * offers: the server lists the rates and methods; this only gives each one its commercial name and a mark.\n *\n * Marks are typographic badges drawn by `<BrandMark>` (brand color + short wordmark): no third-party logo files are\n * bundled, so there is no licensing question and no extra request. A provider that holds a licensed logo sends it as\n * `logo_url` and it wins over the badge. Colors are close approximations of each brand's public color.\n */\n\nexport type BrandKind = 'carrier' | 'card' | 'wallet' | 'cash' | 'bank'\n\nexport type Brand = {\n key: string\n /** Commercial name, as the brand writes it. */\n name: string\n kind: BrandKind\n /** Badge background. */\n bg: string\n /** Badge text color (AA on `bg`). */\n fg: string\n /** Short wordmark drawn in the badge (`\\n` = two lines). Default: `name`. */\n mark?: string\n /** Special drawings instead of a wordmark. */\n shape?: 'mastercard'\n}\n\nconst B = (key: string, name: string, kind: BrandKind, bg: string, fg: string, mark?: string, shape?: Brand['shape']): Brand => ({\n key,\n name,\n kind,\n bg,\n fg,\n ...(mark ? { mark } : {}),\n ...(shape ? { shape } : {}),\n})\n\nconst LIST: Brand[] = [\n // Parcel carriers (Mexico and global).\n B('fedex', 'FedEx', 'carrier', '#4D148C', '#FFFFFF'),\n B('dhl', 'DHL', 'carrier', '#FFCC00', '#B00410'),\n B('estafeta', 'Estafeta', 'carrier', '#C8102E', '#FFFFFF'),\n B('paquetexpress', 'Paquetexpress', 'carrier', '#0B4EA2', '#FFFFFF', 'Paquet\\nexpress'),\n B('ups', 'UPS', 'carrier', '#351C15', '#FFB500'),\n B('redpack', 'Redpack', 'carrier', '#C8102E', '#FFFFFF'),\n B('99minutos', '99 Minutos', 'carrier', '#00704A', '#FFFFFF', '99'),\n B('jtexpress', 'J&T Express', 'carrier', '#C8102E', '#FFFFFF', 'J&T'),\n B('sendex', 'Sendex', 'carrier', '#003A70', '#FFFFFF'),\n B('ampm', 'AMPM', 'carrier', '#1D1D1B', '#FFFFFF'),\n B('tresguerras', 'Tresguerras', 'carrier', '#005BAC', '#FFFFFF', '3G'),\n B('quiken', 'Quiken', 'carrier', '#1D1D1B', '#FFFFFF'),\n B('imile', 'iMile', 'carrier', '#0057B8', '#FFFFFF'),\n B('carssa', 'Carssa', 'carrier', '#00529B', '#FFFFFF'),\n B('correosdemexico', 'Correos de México', 'carrier', '#7A1E3A', '#FFFFFF', 'Correos\\nMéxico'),\n B('usps', 'USPS', 'carrier', '#333366', '#FFFFFF'),\n B('canadapost', 'Canada Post', 'carrier', '#DA291C', '#FFFFFF', 'CPC'),\n // Card networks.\n B('visa', 'Visa', 'card', '#1A1F71', '#FFFFFF', 'VISA'),\n B('mastercard', 'Mastercard', 'card', '#FFFFFF', '#1D1D1B', 'MC', 'mastercard'),\n B('amex', 'American Express', 'card', '#1F72CD', '#FFFFFF', 'AMEX'),\n B('carnet', 'Carnet', 'card', '#003B71', '#FFFFFF'),\n // Wallets and payment providers.\n B('mercadopago', 'Mercado Pago', 'wallet', '#00B1EA', '#0B1F4E', 'mercado\\npago'),\n B('paypal', 'PayPal', 'wallet', '#003087', '#FFFFFF'),\n B('clip', 'Clip', 'wallet', '#FC4C02', '#1D1D1B'),\n B('applepay', 'Apple Pay', 'wallet', '#000000', '#FFFFFF', 'Pay'),\n B('googlepay', 'Google Pay', 'wallet', '#FFFFFF', '#3C4043', 'G Pay'),\n // Cash points and transfers (Mexico).\n B('oxxo', 'OXXO', 'cash', '#E21E26', '#FFE600'),\n B('spei', 'SPEI', 'bank', '#14365F', '#FFFFFF'),\n B('stp', 'STP', 'bank', '#14365F', '#FFFFFF', 'SPEI'),\n B('7eleven', '7-Eleven', 'cash', '#00704A', '#FFFFFF', '7-11'),\n B('circlek', 'Circle K', 'cash', '#DA291C', '#FFFFFF', 'K'),\n B('soriana', 'Soriana', 'cash', '#C8102E', '#FFFFFF'),\n B('extra', 'Extra', 'cash', '#E35205', '#FFFFFF'),\n B('kiosko', 'Kiosko', 'cash', '#C8102E', '#FFFFFF'),\n B('calimax', 'Calimax', 'cash', '#D52B1E', '#FFFFFF'),\n B('farmaciasyza', 'Farmacias Yza', 'cash', '#0A5A9C', '#FFFFFF', 'Yza'),\n B('chedraui', 'Chedraui', 'cash', '#0047BB', '#FFFFFF'),\n B('casaley', 'Casa Ley', 'cash', '#C8102E', '#FFFFFF', 'Ley'),\n B('telecomm', 'Telecomm', 'cash', '#6F1D46', '#FFFFFF'),\n B('walmart', 'Walmart', 'cash', '#0071CE', '#FFFFFF'),\n B('santander', 'Santander', 'bank', '#C00000', '#FFFFFF'),\n B('bbva', 'BBVA', 'bank', '#004481', '#FFFFFF'),\n B('citibanamex', 'Citibanamex', 'bank', '#004B8D', '#FFFFFF', 'Citi'),\n B('banorte', 'Banorte', 'bank', '#C8102E', '#FFFFFF'),\n]\n\n/** Alternative spellings that providers send for the same brand (already normalized by `brandKey`). */\nconst ALIASES: Record<string, string> = {\n fedexmx: 'fedex',\n fedexexpress: 'fedex',\n dhlexpress: 'dhl',\n dhlmx: 'dhl',\n paquetexpres: 'paquetexpress',\n paqueteexpress: 'paquetexpress',\n jt: 'jtexpress',\n jandtexpress: 'jtexpress',\n noventaynueveminutos: '99minutos',\n correos: 'correosdemexico',\n sepomex: 'correosdemexico',\n master: 'mastercard',\n americanexpress: 'amex',\n mercadopagomx: 'mercadopago',\n mp: 'mercadopago',\n clabe: 'spei',\n banktransfer: 'spei',\n seveneleven: '7eleven',\n '711': '7eleven',\n circulok: 'circlek',\n yza: 'farmaciasyza',\n bancomer: 'bbva',\n banamex: 'citibanamex',\n ley: 'casaley',\n}\n\nconst BY_KEY = new Map(LIST.map((b) => [b.key, b]))\n\n/** `\"FedEx México\"`, `\"fedex_mx\"` and `\"FEDEX\"` all become `fedex`. Lowercase ASCII letters and digits only. */\nexport function brandKey(raw: string | null | undefined): string {\n const flat = (raw ?? '')\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/&/g, 'and')\n .replace(/[^a-z0-9]/g, '')\n const noCountry = flat.endsWith('mexico') && flat !== 'correosdemexico' ? flat.slice(0, -6) : flat\n return ALIASES[noCountry] ?? (BY_KEY.has(noCountry) ? noCountry : ALIASES[flat] ?? flat)\n}\n\n/** Catalog entry for a provider identifier, or `null` when the brand is not in the catalog. */\nexport function findBrand(raw: string | null | undefined): Brand | null {\n return BY_KEY.get(brandKey(raw)) ?? null\n}\n\n/**\n * Commercial name for a provider identifier: the catalog's (`fedex` → \"FedEx\") or, for an unknown one, the identifier\n * in title case (`\"envios_rapidos\"` → \"Envios Rapidos\"). `null` for an empty input.\n */\nexport function brandName(raw: string | null | undefined): string | null {\n const brand = findBrand(raw)\n if (brand) return brand.name\n const text = (raw ?? '').trim()\n if (!text) return null\n // Already cased by the provider (\"Envía Plus\"): keep it.\n if (text !== text.toLowerCase() && text !== text.toUpperCase()) return text\n return text\n .toLowerCase()\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ')\n}\n\n/** Every brand of the catalog (for docs, previews and tests). */\nexport function listBrands(kind?: BrandKind): Brand[] {\n return kind ? LIST.filter((b) => b.kind === kind) : [...LIST]\n}\n","import type { CSSProperties } from 'react'\nimport { brandName, findBrand } from './brands.js'\n\nexport type BrandMarkProps = {\n /** Provider identifier (`fedex`, `oxxo`, `mercadopago`, `7eleven`…). Unknown keys get a neutral monogram. */\n brand: string | null | undefined\n /** Licensed logo sent by the provider (`PaymentPoint.logo_url`…). Only `https:`; it wins over the badge. */\n logoUrl?: string | null\n /** Height in px. The badge is 3:2 (width = 1.5 × height). Default 24. */\n size?: number\n /**\n * Accessible name. Omit it when the brand name is already written next to the mark (the usual case): the mark is then\n * decorative (`aria-hidden`).\n */\n title?: string\n className?: string\n}\n\nfunction safeLogo(url: string | null | undefined): string | null {\n if (!url) return null\n try {\n return new URL(url).protocol === 'https:' ? url : null\n } catch {\n return null\n }\n}\n\n/** Letters of a monogram for a brand outside the catalog: \"envios rapidos\" → \"ER\". */\nfunction monogram(raw: string): string {\n const words = (brandName(raw) ?? raw).split(/\\s+/).filter(Boolean)\n const letters = words.length > 1 ? words.slice(0, 2).map((w) => w[0]) : [(words[0] ?? '?').slice(0, 2)]\n return letters.join('').toUpperCase()\n}\n\n/**\n * The mark of a carrier, card network, wallet or cash point: an inline SVG badge in the brand color with its short\n * wordmark (no network request, same size on the server and in the browser, so no layout shift). With `logoUrl` it\n * draws the provider's licensed logo instead, lazily, with fixed dimensions.\n *\n * The badge carries its own background, so it keeps its contrast on light and dark themes; a hairline\n * (`--sf-brand-mark-ring`) separates it from the page.\n */\nexport function BrandMark({ brand, logoUrl, size = 24, title, className }: BrandMarkProps) {\n const height = size\n const width = Math.round(size * 1.5)\n const a11y = title ? { role: 'img' as const, 'aria-label': title } : { 'aria-hidden': true as const }\n const logo = safeLogo(logoUrl)\n const found = findBrand(brand)\n const key = found?.key ?? 'generic'\n const style: CSSProperties = { width, height, flex: 'none' }\n if (logo) {\n return (\n <img\n src={logo}\n alt={title ?? ''}\n width={width}\n height={height}\n loading=\"lazy\"\n decoding=\"async\"\n className={className}\n style={{ ...style, objectFit: 'contain' }}\n data-sf-brand-mark={key}\n {...(title ? {} : { 'aria-hidden': true })}\n />\n )\n }\n const ring = 'var(--sf-brand-mark-ring, rgb(127 127 127 / 0.35))'\n if (found?.shape === 'mastercard') {\n return (\n <svg viewBox=\"0 0 48 32\" width={width} height={height} className={className} style={style} data-sf-brand-mark={key} focusable=\"false\" {...a11y}>\n <rect x=\"0.5\" y=\"0.5\" width=\"47\" height=\"31\" rx=\"5\" fill={found.bg} stroke={ring} />\n <circle cx=\"19\" cy=\"16\" r=\"9\" fill=\"#EB001B\" />\n <circle cx=\"29\" cy=\"16\" r=\"9\" fill=\"#F79E1B\" />\n <path d=\"M24 8.52a9 9 0 0 1 0 14.96a9 9 0 0 1 0-14.96z\" fill=\"#FF5F00\" />\n </svg>\n )\n }\n const text = found ? (found.mark ?? found.name) : monogram(brand ?? '')\n const bg = found?.bg ?? 'var(--sf-brand-mark-bg, #E7E9EE)'\n const fg = found?.fg ?? 'var(--sf-brand-mark-fg, #2B2F38)'\n const lines = text.split('\\n')\n const longest = Math.max(...lines.map((l) => l.length))\n // Short marks grow; long ones are squeezed into the badge (textLength) so every badge has the same box.\n const fontSize = lines.length > 1 ? (longest <= 5 ? 11 : 9.5) : longest <= 2 ? 15 : longest <= 4 ? 12 : 10\n const fit = (l: string) => (l.length > 5 ? { textLength: 40, lengthAdjust: 'spacingAndGlyphs' as const } : {})\n const italic = found?.key === 'visa' || found?.key === 'fedex' ? 'italic' : undefined\n const common = {\n textAnchor: 'middle' as const,\n fill: fg,\n fontFamily: \"system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif\",\n fontWeight: 800,\n fontSize,\n fontStyle: italic,\n }\n return (\n <svg viewBox=\"0 0 48 32\" width={width} height={height} className={className} style={style} data-sf-brand-mark={key} focusable=\"false\" {...a11y}>\n <rect x=\"0.5\" y=\"0.5\" width=\"47\" height=\"31\" rx=\"5\" fill={bg} stroke={ring} />\n {lines.length > 1 ? (\n lines.slice(0, 2).map((l, i) => (\n <text key={i} x=\"24\" y={i === 0 ? 15 : 25.5} {...common} {...fit(l)}>\n {l}\n </text>\n ))\n ) : (\n <text x=\"24\" y=\"16\" dominantBaseline=\"central\" letterSpacing={longest <= 4 ? 0.3 : 0} {...common} {...fit(text)}>\n {text}\n </text>\n )}\n </svg>\n )\n}\n"]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/payments/csp.ts
|
|
2
|
+
var ORIGIN = /^https:\/\/(\*\.)?[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*(:\d{1,5})?$/i;
|
|
3
|
+
function origins(...lists) {
|
|
4
|
+
const out = /* @__PURE__ */ new Set();
|
|
5
|
+
for (const list of lists) for (const o of list ?? []) if (ORIGIN.test(o)) out.add(o);
|
|
6
|
+
return [...out];
|
|
7
|
+
}
|
|
8
|
+
function paymentCsp(clients, options = {}) {
|
|
9
|
+
const list = clients.filter((c) => !!c);
|
|
10
|
+
const pick = (k) => list.map((c) => c.csp?.[k]);
|
|
11
|
+
const nonce = options.nonce && /^[A-Za-z0-9+/=_-]+$/.test(options.nonce) ? options.nonce : void 0;
|
|
12
|
+
const sdkOrigins = list.flatMap((c) => {
|
|
13
|
+
try {
|
|
14
|
+
const u = new URL(c.sdk_url);
|
|
15
|
+
return u.protocol === "https:" ? [u.origin] : [];
|
|
16
|
+
} catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const dir = (name, values) => `${name} ${values.join(" ")}`;
|
|
21
|
+
const parts = [
|
|
22
|
+
"default-src 'self'",
|
|
23
|
+
dir("script-src", ["'self'", ...(options.scriptHashes ?? []).filter((h) => /^'sha(256|384|512)-[A-Za-z0-9+/=]+'$/.test(h)), ...nonce ? [`'nonce-${nonce}'`] : [], ...origins(sdkOrigins, ...pick("script"), options.extra?.script)]),
|
|
24
|
+
dir("frame-src", origins(...pick("frame"), options.extra?.frame).length ? origins(...pick("frame"), options.extra?.frame) : ["'none'"]),
|
|
25
|
+
dir("connect-src", ["'self'", ...origins(...pick("connect"), options.extra?.connect)]),
|
|
26
|
+
dir("img-src", ["'self'", "data:", ...options.imgHttps ? ["https:"] : [], ...origins(...pick("img"), options.extra?.img)]),
|
|
27
|
+
"style-src 'self' 'unsafe-inline'",
|
|
28
|
+
dir("form-action", ["'self'", ...origins(...pick("form"), options.extra?.form)]),
|
|
29
|
+
"frame-ancestors 'none'",
|
|
30
|
+
"base-uri 'self'",
|
|
31
|
+
"object-src 'none'"
|
|
32
|
+
];
|
|
33
|
+
if (options.reportUri && /^(https:\/\/|\/)[^\s;,]+$/.test(options.reportUri)) parts.push(`report-uri ${options.reportUri}`);
|
|
34
|
+
return parts.join("; ");
|
|
35
|
+
}
|
|
36
|
+
function paymentCspHeaderName(reportOnly) {
|
|
37
|
+
return reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy";
|
|
38
|
+
}
|
|
39
|
+
function paymentCspMode(value, production) {
|
|
40
|
+
const raw = (value ?? "").trim().toLowerCase();
|
|
41
|
+
if (raw === "off" || raw === "report-only" || raw === "enforce") return raw;
|
|
42
|
+
return production ? "report-only" : "off";
|
|
43
|
+
}
|
|
44
|
+
function paymentNonce() {
|
|
45
|
+
const bytes = new Uint8Array(16);
|
|
46
|
+
crypto.getRandomValues(bytes);
|
|
47
|
+
let bin = "";
|
|
48
|
+
for (const b of bytes) bin += String.fromCharCode(b);
|
|
49
|
+
return btoa(bin);
|
|
50
|
+
}
|
|
51
|
+
function paymentCspHeaders(clients, options) {
|
|
52
|
+
if (options.mode === "off") return {};
|
|
53
|
+
return { [paymentCspHeaderName(options.mode === "report-only")]: paymentCsp(clients, options) };
|
|
54
|
+
}
|
|
55
|
+
function paymentNonceFromHeaders(headers) {
|
|
56
|
+
const csp = headers.get("Content-Security-Policy") ?? headers.get("Content-Security-Policy-Report-Only") ?? "";
|
|
57
|
+
return /'nonce-([A-Za-z0-9+/=_-]+)'/.exec(csp)?.[1];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/payments/choices.ts
|
|
61
|
+
var SEP = "|";
|
|
62
|
+
function choiceValue(methodKey, option) {
|
|
63
|
+
return option ? `${methodKey}${SEP}${option}` : methodKey;
|
|
64
|
+
}
|
|
65
|
+
function parseChoice(value) {
|
|
66
|
+
const raw = (value ?? "").trim();
|
|
67
|
+
if (!raw) return null;
|
|
68
|
+
const i = raw.lastIndexOf(SEP);
|
|
69
|
+
if (i === -1) return { methodKey: raw, option: null };
|
|
70
|
+
const option = raw.slice(i + 1);
|
|
71
|
+
if (option !== "card" && option !== "cash" && option !== "wallet" && option !== "credits") return null;
|
|
72
|
+
return { methodKey: raw.slice(0, i), option };
|
|
73
|
+
}
|
|
74
|
+
function modeOf(option) {
|
|
75
|
+
if (option.redirect || option.key === "wallet" || option.key === "credits") return "redirect";
|
|
76
|
+
return option.key === "cash" ? "cash" : "card";
|
|
77
|
+
}
|
|
78
|
+
function buildPayChoices(methods, options = {}) {
|
|
79
|
+
const hidden = new Set(options.hide ?? []);
|
|
80
|
+
const choices = [];
|
|
81
|
+
let cardClient = null;
|
|
82
|
+
let defaultValue = null;
|
|
83
|
+
for (const method of methods) {
|
|
84
|
+
if (hidden.has(method.key)) continue;
|
|
85
|
+
const opts = method.options ?? [];
|
|
86
|
+
if (opts.length === 0) {
|
|
87
|
+
const value = choiceValue(method.key, null);
|
|
88
|
+
choices.push({ value, methodKey: method.key, option: null, mode: "plain", label: null, points: [], maxInstallments: null });
|
|
89
|
+
if (method.default && !defaultValue) defaultValue = value;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
opts.forEach((option, i) => {
|
|
93
|
+
const mode = modeOf(option);
|
|
94
|
+
const value = choiceValue(method.key, option.key);
|
|
95
|
+
choices.push({
|
|
96
|
+
value,
|
|
97
|
+
methodKey: method.key,
|
|
98
|
+
option: option.key,
|
|
99
|
+
mode,
|
|
100
|
+
label: option.label?.trim() || null,
|
|
101
|
+
points: option.key === "cash" ? option.points ?? [] : [],
|
|
102
|
+
maxInstallments: option.max_installments ?? null
|
|
103
|
+
});
|
|
104
|
+
if (mode === "card" && method.client && !cardClient) cardClient = method.client;
|
|
105
|
+
if (method.default && i === 0 && !defaultValue) defaultValue = value;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const usable = choices.map((c) => c.mode === "card" && !cardClient ? { ...c, mode: "redirect" } : c);
|
|
109
|
+
return { choices: usable, cardClient, defaultValue: defaultValue ?? usable[0]?.value ?? null };
|
|
110
|
+
}
|
|
111
|
+
function cashProviderData(points, pointId) {
|
|
112
|
+
const point = points.find((p) => p.id === pointId) ?? (pointId ? null : points[0]);
|
|
113
|
+
if (!point) return null;
|
|
114
|
+
return {
|
|
115
|
+
payment_method_id: point.payment_method_id,
|
|
116
|
+
...point.payment_point ? { payment_point: point.payment_point } : {}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function checkoutToAttempt(result) {
|
|
120
|
+
const { checkout, payment, order } = result;
|
|
121
|
+
const action = payment.action ?? null;
|
|
122
|
+
const base = { checkout, ...order ? { order } : {} };
|
|
123
|
+
const status = (checkout.status ?? "").toLowerCase();
|
|
124
|
+
if (status === "paid" || status === "converted") return { ...base, payment: { provider: payment.provider, status: "paid", outcome: "approved" } };
|
|
125
|
+
if (status === "cancelled" || status === "canceled") return { ...base, payment: { provider: payment.provider, status: "cancelled" } };
|
|
126
|
+
if (status === "expired") return { ...base, payment: { provider: payment.provider, status: "expired" } };
|
|
127
|
+
if (status === "failed") {
|
|
128
|
+
const decline = payment.decline_code ?? "declined";
|
|
129
|
+
return { ...base, payment: { provider: payment.provider, status: "failed", outcome: "rejected", decline_code: decline, retryable: true } };
|
|
130
|
+
}
|
|
131
|
+
if (action?.type === "challenge") return { ...base, payment: { provider: payment.provider, status: "requires_action", outcome: "challenge", action } };
|
|
132
|
+
return { ...base, payment: { provider: payment.provider, status: "pending", outcome: "pending", action: action ?? { type: "none" } } };
|
|
133
|
+
}
|
|
134
|
+
function payErrorResponse(err) {
|
|
135
|
+
const status = typeof err.status === "number" && err.status >= 400 ? err.status : 503;
|
|
136
|
+
let code = err.code ?? "server_error";
|
|
137
|
+
if (status === 409 && err.field === "payment_in_progress") code = "payment_in_progress";
|
|
138
|
+
if (status === 429) code = "too_many_attempts";
|
|
139
|
+
if (status === 422 && err.field === "expected_total") code = "price_mismatch";
|
|
140
|
+
return { status, body: { error: { code, message: err.message ?? "", ...err.details !== void 0 ? { details: err.details } : {} } } };
|
|
141
|
+
}
|
|
142
|
+
function voucherRows(voucher, labels, locale) {
|
|
143
|
+
if (!voucher) return [];
|
|
144
|
+
const rows = [];
|
|
145
|
+
if (voucher.payment_point) rows.push([labels.point, String(voucher.payment_point).slice(0, 60)]);
|
|
146
|
+
if (voucher.reference) rows.push([labels.reference, String(voucher.reference).slice(0, 80)]);
|
|
147
|
+
if (voucher.clabe) rows.push([labels.clabe, String(voucher.clabe).slice(0, 40)]);
|
|
148
|
+
if (voucher.barcode) rows.push([labels.barcode, String(voucher.barcode).slice(0, 80)]);
|
|
149
|
+
if (voucher.expires_at) {
|
|
150
|
+
const d = new Date(voucher.expires_at);
|
|
151
|
+
if (!Number.isNaN(d.getTime())) {
|
|
152
|
+
rows.push([labels.expires, new Intl.DateTimeFormat(locale, { dateStyle: "long", timeStyle: "short", timeZone: "UTC" }).format(d) + " UTC"]);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return rows;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { buildPayChoices, cashProviderData, checkoutToAttempt, choiceValue, parseChoice, payErrorResponse, paymentCsp, paymentCspHeaderName, paymentCspHeaders, paymentCspMode, paymentNonce, paymentNonceFromHeaders, voucherRows };
|
|
159
|
+
//# sourceMappingURL=chunk-ISEOCKIR.js.map
|
|
160
|
+
//# sourceMappingURL=chunk-ISEOCKIR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/payments/csp.ts","../src/payments/choices.ts"],"names":[],"mappings":"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","file":"chunk-ISEOCKIR.js","sourcesContent":["import type { PaymentClient } from '@asteby/storefront'\n\nexport type PaymentCspOptions = {\n /** Per-request nonce; also set it on the inserted `<script>` and on `<Scripts nonce>`. */\n nonce?: string\n /** Extra origins by directive (e.g. your image CDN). */\n extra?: { script?: string[]; frame?: string[]; connect?: string[]; img?: string[]; form?: string[] }\n /** `report-uri` / `report-to` target for the report-only rollout. */\n reportUri?: string\n /** Inline scripts allowed by hash (`'sha256-…'`), e.g. a theme bootstrap that runs before paint. */\n scriptHashes?: string[]\n /** Allow any https image source (product photos from a CDN). */\n imgHttps?: boolean\n}\n\n/** One origin source: `https://host`, `https://*.host`, optional port. Anything else (`;`, spaces, `'unsafe-eval'`) is dropped. */\nconst ORIGIN = /^https:\\/\\/(\\*\\.)?[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*(:\\d{1,5})?$/i\n\nfunction origins(...lists: (readonly string[] | undefined)[]): string[] {\n const out = new Set<string>()\n for (const list of lists) for (const o of list ?? []) if (ORIGIN.test(o)) out.add(o)\n return [...out]\n}\n\n/**\n * Builds the Content-Security-Policy for the payment routes from what each provider declares\n * (`PaymentClient.csp`), so the shop never hard-codes provider hosts. Meant for `/pagar` only,\n * never for the whole site. Roll out as `Content-Security-Policy-Report-Only` first.\n *\n * No SRI on purpose: provider SDK URLs are unversioned and a hash would break payments on any update.\n */\nexport function paymentCsp(clients: readonly (PaymentClient | null | undefined)[], options: PaymentCspOptions = {}): string {\n const list = clients.filter((c): c is PaymentClient => !!c)\n const pick = (k: keyof NonNullable<PaymentClient['csp']>) => list.map((c) => c.csp?.[k])\n const nonce = options.nonce && /^[A-Za-z0-9+/=_-]+$/.test(options.nonce) ? options.nonce : undefined\n const sdkOrigins = list.flatMap((c) => {\n try {\n const u = new URL(c.sdk_url)\n return u.protocol === 'https:' ? [u.origin] : []\n } catch {\n return []\n }\n })\n const dir = (name: string, values: string[]) => `${name} ${values.join(' ')}`\n const parts = [\n \"default-src 'self'\",\n dir('script-src', [\"'self'\", ...(options.scriptHashes ?? []).filter((h) => /^'sha(256|384|512)-[A-Za-z0-9+/=]+'$/.test(h)), ...(nonce ? [`'nonce-${nonce}'`] : []), ...origins(sdkOrigins, ...pick('script'), options.extra?.script)]),\n dir('frame-src', origins(...pick('frame'), options.extra?.frame).length ? origins(...pick('frame'), options.extra?.frame) : [\"'none'\"]),\n dir('connect-src', [\"'self'\", ...origins(...pick('connect'), options.extra?.connect)]),\n dir('img-src', [\"'self'\", 'data:', ...(options.imgHttps ? ['https:'] : []), ...origins(...pick('img'), options.extra?.img)]),\n \"style-src 'self' 'unsafe-inline'\",\n dir('form-action', [\"'self'\", ...origins(...pick('form'), options.extra?.form)]),\n \"frame-ancestors 'none'\",\n \"base-uri 'self'\",\n \"object-src 'none'\",\n ]\n if (options.reportUri && /^(https:\\/\\/|\\/)[^\\s;,]+$/.test(options.reportUri)) parts.push(`report-uri ${options.reportUri}`)\n return parts.join('; ')\n}\n\n/** `Content-Security-Policy` or, during the rollout week, `Content-Security-Policy-Report-Only`. */\nexport function paymentCspHeaderName(reportOnly: boolean): string {\n return reportOnly ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'\n}\n\nexport type PaymentCspMode = 'off' | 'report-only' | 'enforce'\n\n/** `PAYMENT_CSP`-style value: `off`, `report-only` or `enforce`. Unset: report-only in production, off elsewhere (dev servers inject scripts). */\nexport function paymentCspMode(value: string | null | undefined, production: boolean): PaymentCspMode {\n const raw = (value ?? '').trim().toLowerCase()\n if (raw === 'off' || raw === 'report-only' || raw === 'enforce') return raw\n return production ? 'report-only' : 'off'\n}\n\n/** Fresh per-request nonce (128 bits, base64). Works in Node, edge and browsers. */\nexport function paymentNonce(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n let bin = ''\n for (const b of bytes) bin += String.fromCharCode(b)\n return btoa(bin)\n}\n\n/** Header ready for the response (`{}` when `off`): policy from the providers' `client.csp`, never the whole site. */\nexport function paymentCspHeaders(\n clients: readonly (PaymentClient | null | undefined)[],\n options: PaymentCspOptions & { mode: PaymentCspMode },\n): Record<string, string> {\n if (options.mode === 'off') return {}\n return { [paymentCspHeaderName(options.mode === 'report-only')]: paymentCsp(clients, options) }\n}\n\n/** The nonce the route left in the CSP header, to hand to `ServerRouter` / `<Scripts>`. */\nexport function paymentNonceFromHeaders(headers: Headers): string | undefined {\n const csp = headers.get('Content-Security-Policy') ?? headers.get('Content-Security-Policy-Report-Only') ?? ''\n return /'nonce-([A-Za-z0-9+/=_-]+)'/.exec(csp)?.[1]\n}\n","/**\n * \"Payment method\" rows for a hybrid checkout: pure functions, no DOM and no server, so the loader, the action and the\n * browser share them.\n *\n * Rules (embedded-payment contract 1.2):\n * - Rows come ONLY from what the server publishes (`payment-methods[].options` and `.client`). No provider names and no\n * amounts live here.\n * - Card and cash are paid in the page; `wallet` and `credits` redirect to the provider.\n * - Without `client`, or with the card flagged `redirect: true`, the server does not offer `embedded`: the shop falls\n * back to the usual redirect flow.\n */\nimport type {\n CheckoutResult,\n PaymentAttemptResult,\n PaymentClient,\n PaymentMethod,\n PaymentOption,\n PaymentOptionKey,\n PaymentPoint,\n} from '@asteby/storefront'\n\n/** One row of \"Payment method\". `value` is what travels in the form (`payment_choice`). */\nexport type PayChoice = {\n value: string\n /** Server method key (`payment_method` of the checkout). */\n methodKey: string\n /** Provider option; `null` for a method without options (the plain flow). */\n option: PaymentOptionKey | null\n /** `card` (form in the page), `cash` (voucher), `redirect` (leaves to the gateway) or `plain`. */\n mode: 'card' | 'cash' | 'redirect' | 'plain'\n /** The provider's own text (`option.label`); the shop supplies its own when missing. */\n label: string | null\n points: PaymentPoint[]\n maxInstallments: number | null\n}\n\nexport type PayChoices = {\n choices: PayChoice[]\n /** Public data to mount the card form; `null` when the server does not offer `embedded`. */\n cardClient: PaymentClient | null\n defaultValue: string | null\n}\n\nexport type BuildPayChoicesOptions = {\n /** Method keys this shop never offers even when the server publishes them (e.g. a manual transfer). */\n hide?: Iterable<string>\n}\n\nconst SEP = '|'\n\nexport function choiceValue(methodKey: string, option: PaymentOptionKey | null): string {\n return option ? `${methodKey}${SEP}${option}` : methodKey\n}\n\n/** `\"mercadopago|card\"` becomes method and option. A value without `|` is a method without options. */\nexport function parseChoice(value: string | null | undefined): { methodKey: string; option: PaymentOptionKey | null } | null {\n const raw = (value ?? '').trim()\n if (!raw) return null\n const i = raw.lastIndexOf(SEP)\n if (i === -1) return { methodKey: raw, option: null }\n const option = raw.slice(i + 1)\n if (option !== 'card' && option !== 'cash' && option !== 'wallet' && option !== 'credits') return null\n return { methodKey: raw.slice(0, i), option }\n}\n\nfunction modeOf(option: PaymentOption): PayChoice['mode'] {\n if (option.redirect || option.key === 'wallet' || option.key === 'credits') return 'redirect'\n return option.key === 'cash' ? 'cash' : 'card'\n}\n\n/**\n * Rows from `GET payment-methods`. A method with `options` unfolds into one row per option (server order); one without\n * is a single plain row. `cardClient` only exists when the card is paid in the page.\n */\nexport function buildPayChoices(methods: readonly PaymentMethod[], options: BuildPayChoicesOptions = {}): PayChoices {\n const hidden = new Set(options.hide ?? [])\n const choices: PayChoice[] = []\n let cardClient: PaymentClient | null = null\n let defaultValue: string | null = null\n for (const method of methods) {\n if (hidden.has(method.key)) continue\n const opts = method.options ?? []\n if (opts.length === 0) {\n const value = choiceValue(method.key, null)\n choices.push({ value, methodKey: method.key, option: null, mode: 'plain', label: null, points: [], maxInstallments: null })\n if (method.default && !defaultValue) defaultValue = value\n continue\n }\n opts.forEach((option, i) => {\n const mode = modeOf(option)\n const value = choiceValue(method.key, option.key)\n choices.push({\n value,\n methodKey: method.key,\n option: option.key,\n mode,\n label: option.label?.trim() || null,\n points: option.key === 'cash' ? (option.points ?? []) : [],\n maxInstallments: option.max_installments ?? null,\n })\n if (mode === 'card' && method.client && !cardClient) cardClient = method.client\n if (method.default && i === 0 && !defaultValue) defaultValue = value\n })\n }\n // A card meant for the page but without `client` cannot be mounted: it is paid by redirect.\n const usable = choices.map((c) => (c.mode === 'card' && !cardClient ? { ...c, mode: 'redirect' as const } : c))\n return { choices: usable, cardClient, defaultValue: defaultValue ?? usable[0]?.value ?? null }\n}\n\n/** Chosen cash point becomes the cash `provider_data`, built on the server from the provider's list. */\nexport function cashProviderData(points: readonly PaymentPoint[], pointId: string | null | undefined): Record<string, string> | null {\n const point = points.find((p) => p.id === pointId) ?? (pointId ? null : points[0])\n if (!point) return null\n return {\n payment_method_id: point.payment_method_id,\n ...(point.payment_point ? { payment_point: point.payment_point } : {}),\n }\n}\n\n/**\n * A checkout (`GET checkouts/:id`) as an attempt result, for polling a 3DS challenge or a payment under review.\n * It only translates server states: it never decides a payment.\n */\nexport function checkoutToAttempt(result: CheckoutResult): PaymentAttemptResult {\n const { checkout, payment, order } = result\n const action = payment.action ?? null\n const base = { checkout, ...(order ? { order } : {}) }\n const status = (checkout.status ?? '').toLowerCase()\n if (status === 'paid' || status === 'converted') return { ...base, payment: { provider: payment.provider, status: 'paid', outcome: 'approved' } }\n if (status === 'cancelled' || status === 'canceled') return { ...base, payment: { provider: payment.provider, status: 'cancelled' } }\n if (status === 'expired') return { ...base, payment: { provider: payment.provider, status: 'expired' } }\n if (status === 'failed') {\n const decline = (payment as { decline_code?: PaymentAttemptResult['payment']['decline_code'] }).decline_code ?? 'declined'\n return { ...base, payment: { provider: payment.provider, status: 'failed', outcome: 'rejected', decline_code: decline, retryable: true } }\n }\n // Still pending: same as the last attempt left it (challenge or review), so the screen does not change.\n if (action?.type === 'challenge') return { ...base, payment: { provider: payment.provider, status: 'requires_action', outcome: 'challenge', action } }\n return { ...base, payment: { provider: payment.provider, status: 'pending', outcome: 'pending', action: action ?? { type: 'none' } } }\n}\n\n/** Body `{ error: { code, message, details } }` that `createFetchTransport` understands. */\nexport type PayErrorBody = { error: { code: string; message: string; details?: unknown } }\n\ntype ErrorLike = { status?: number; code?: string; field?: string; message?: string; details?: unknown }\n\n/**\n * Server error becomes a JSON response for the browser. Keeps the codes the SDK knows how to read (`price_mismatch`,\n * `payment_in_progress`, `expired`, `too_many_attempts`); the mock sends \"in progress\" in `field`, so that is checked too.\n */\nexport function payErrorResponse(err: ErrorLike): { status: number; body: PayErrorBody } {\n const status = typeof err.status === 'number' && err.status >= 400 ? err.status : 503\n let code = err.code ?? 'server_error'\n if (status === 409 && err.field === 'payment_in_progress') code = 'payment_in_progress'\n if (status === 429) code = 'too_many_attempts'\n if (status === 422 && err.field === 'expected_total') code = 'price_mismatch'\n return { status, body: { error: { code, message: err.message ?? '', ...(err.details !== undefined ? { details: err.details } : {}) } } }\n}\n\nexport type VoucherRowLabels = { point: string; reference: string; clabe: string; barcode: string; expires: string }\n\n/** Cookie receipt rows for a payment under review or with a voucher (shown on the thank-you page). */\nexport function voucherRows(\n voucher: NonNullable<NonNullable<PaymentAttemptResult['payment']['action']>['voucher']> | null | undefined,\n labels: VoucherRowLabels,\n locale: string,\n): [label: string, value: string][] {\n if (!voucher) return []\n const rows: [string, string][] = []\n if (voucher.payment_point) rows.push([labels.point, String(voucher.payment_point).slice(0, 60)])\n if (voucher.reference) rows.push([labels.reference, String(voucher.reference).slice(0, 80)])\n if (voucher.clabe) rows.push([labels.clabe, String(voucher.clabe).slice(0, 40)])\n if (voucher.barcode) rows.push([labels.barcode, String(voucher.barcode).slice(0, 80)])\n if (voucher.expires_at) {\n const d = new Date(voucher.expires_at)\n if (!Number.isNaN(d.getTime())) {\n rows.push([labels.expires, new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeStyle: 'short', timeZone: 'UTC' }).format(d) + ' UTC'])\n }\n }\n return rows\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useOptionalStorefront } from './chunk-DQBL2DFJ.js';
|
|
2
|
+
|
|
3
|
+
// src/locale.ts
|
|
4
|
+
function useResolvedLocale(locale) {
|
|
5
|
+
const sf = useOptionalStorefront();
|
|
6
|
+
return locale ?? sf?.locale ?? "es-MX";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { useResolvedLocale };
|
|
10
|
+
//# sourceMappingURL=chunk-T52H5HL3.js.map
|
|
11
|
+
//# sourceMappingURL=chunk-T52H5HL3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/locale.ts"],"names":[],"mappings":";;;AAGO,SAAS,kBAAkB,MAAA,EAAgC;AAChE,EAAA,MAAM,KAAK,qBAAA,EAAsB;AACjC,EAAA,OAAO,MAAA,IAAU,IAAI,MAAA,IAAU,OAAA;AACjC","file":"chunk-T52H5HL3.js","sourcesContent":["import { useOptionalStorefront } from './context.js'\n\n/** Locale of a component: its own prop, else the `StorefrontProvider`'s, else `es-MX`. */\nexport function useResolvedLocale(locale?: string | null): string {\n const sf = useOptionalStorefront()\n return locale ?? sf?.locale ?? 'es-MX'\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useOptionalStorefront } from './chunk-DQBL2DFJ.js';
|
|
2
1
|
import { useRef, useEffect, useCallback } from 'react';
|
|
3
2
|
|
|
3
|
+
// src/dialog.tsx
|
|
4
4
|
function useModalDialog({ open, onClose, initialFocus }) {
|
|
5
5
|
const ref = useRef(null);
|
|
6
6
|
const opener = useRef(null);
|
|
@@ -64,12 +64,6 @@ function prefersReducedMotion() {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return locale ?? sf?.locale ?? "es-MX";
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export { prefersReducedMotion, useModalDialog, useResolvedLocale };
|
|
74
|
-
//# sourceMappingURL=chunk-2WZIWIBW.js.map
|
|
75
|
-
//# sourceMappingURL=chunk-2WZIWIBW.js.map
|
|
67
|
+
export { prefersReducedMotion, useModalDialog };
|
|
68
|
+
//# sourceMappingURL=chunk-ZBH7JYU4.js.map
|
|
69
|
+
//# sourceMappingURL=chunk-ZBH7JYU4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dialog.tsx"],"names":[],"mappings":"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","file":"chunk-ZBH7JYU4.js","sourcesContent":["import { useCallback, useEffect, useRef, type RefObject } from 'react'\n\nexport type DialogCloseReason = 'esc' | 'x' | 'backdrop' | 'action'\n\ntype UseModalDialogOptions = {\n open: boolean\n /** Called for Esc and backdrop clicks. The owner decides whether to close. */\n onClose: (reason: DialogCloseReason) => void\n /** Element focused when the dialog opens. Default: the element marked `data-sf-autofocus`, else the dialog itself. */\n initialFocus?: RefObject<HTMLElement | null>\n}\n\n/**\n * Native `<dialog>` wiring: `showModal()` (focus trap and inert background come from the browser),\n * Esc and backdrop clicks routed to `onClose`, and focus restored to the opener on close.\n * Falls back to the `open` attribute where `showModal` does not exist (old browsers, some test DOMs)\n * with an Esc key handler.\n */\nexport function useModalDialog({ open, onClose, initialFocus }: UseModalDialogOptions) {\n const ref = useRef<HTMLDialogElement | null>(null)\n const opener = useRef<Element | null>(null)\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n\n useEffect(() => {\n const el = ref.current\n if (!el || !open) return\n opener.current = typeof document !== 'undefined' ? document.activeElement : null\n const hasModal = typeof el.showModal === 'function'\n if (!el.open) {\n if (hasModal) {\n try {\n el.showModal()\n } catch {\n el.setAttribute('open', '')\n }\n } else el.setAttribute('open', '')\n }\n const target = initialFocus?.current ?? el.querySelector<HTMLElement>('[data-sf-autofocus]') ?? el\n if (!target.hasAttribute('tabindex') && target === el) el.setAttribute('tabindex', '-1')\n target.focus({ preventScroll: true })\n\n const onCancel = (e: Event) => {\n e.preventDefault() // we close through state so the owner can navigate/track first\n onCloseRef.current('esc')\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onCloseRef.current('esc')\n }\n }\n el.addEventListener('cancel', onCancel)\n if (!hasModal) el.addEventListener('keydown', onKey)\n return () => {\n el.removeEventListener('cancel', onCancel)\n el.removeEventListener('keydown', onKey)\n if (el.open) {\n if (typeof el.close === 'function') {\n try {\n el.close()\n } catch {\n el.removeAttribute('open')\n }\n } else el.removeAttribute('open')\n }\n const back = opener.current\n if (back instanceof HTMLElement && back.isConnected) back.focus({ preventScroll: true })\n }\n }, [open])\n\n /** Click on the backdrop (the dialog element itself, outside its content box). */\n const onBackdropClick = useCallback((e: { target: EventTarget; currentTarget: EventTarget }) => {\n if (e.target === e.currentTarget) onCloseRef.current('backdrop')\n }, [])\n\n return { ref, onBackdropClick }\n}\n\n/** `prefers-reduced-motion: reduce`, read after hydration (false on the server). */\nexport function prefersReducedMotion(): boolean {\n try {\n return typeof window !== 'undefined' && !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n } catch {\n return false\n }\n}\n"]}
|