@asteby/storefront-react 0.26.0 → 0.28.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.
Files changed (38) hide show
  1. package/README.md +7 -2
  2. package/dist/account-server.cjs +533 -83
  3. package/dist/account-server.cjs.map +1 -1
  4. package/dist/account-server.d.cts +13 -2
  5. package/dist/account-server.d.ts +13 -2
  6. package/dist/account-server.js +23 -6
  7. package/dist/account-server.js.map +1 -1
  8. package/dist/account.cjs +572 -96
  9. package/dist/account.cjs.map +1 -1
  10. package/dist/account.d.cts +82 -45
  11. package/dist/account.d.ts +82 -45
  12. package/dist/account.js +53 -14
  13. package/dist/account.js.map +1 -1
  14. package/dist/checkout.cjs +114 -38
  15. package/dist/checkout.cjs.map +1 -1
  16. package/dist/checkout.d.cts +24 -1
  17. package/dist/checkout.d.ts +24 -1
  18. package/dist/checkout.js +114 -38
  19. package/dist/checkout.js.map +1 -1
  20. package/dist/chunk-BXKV2KWZ.js +291 -0
  21. package/dist/chunk-BXKV2KWZ.js.map +1 -0
  22. package/dist/chunk-LIUEQENV.js +156 -0
  23. package/dist/chunk-LIUEQENV.js.map +1 -0
  24. package/dist/fiscal-server.cjs +27 -2
  25. package/dist/fiscal-server.cjs.map +1 -1
  26. package/dist/fiscal-server.d.cts +10 -1
  27. package/dist/fiscal-server.d.ts +10 -1
  28. package/dist/fiscal-server.js +26 -3
  29. package/dist/fiscal-server.js.map +1 -1
  30. package/dist/voucher-document-FWH4DQ5N.js +72 -0
  31. package/dist/voucher-document-FWH4DQ5N.js.map +1 -0
  32. package/dist/voucher-pdf-LQC333AB.js +213 -0
  33. package/dist/voucher-pdf-LQC333AB.js.map +1 -0
  34. package/package.json +1 -1
  35. package/dist/chunk-TXEYBDFG.js +0 -182
  36. package/dist/chunk-TXEYBDFG.js.map +0 -1
  37. package/dist/voucher-document-SFWJCLTN.js +0 -124
  38. package/dist/voucher-document-SFWJCLTN.js.map +0 -1
@@ -0,0 +1,213 @@
1
+ import { docText, formatMoney, methodName, voucherFields, formatDate, voucherSteps } from './chunk-LIUEQENV.js';
2
+ import { barcodeGeometry } from './chunk-BXKV2KWZ.js';
3
+
4
+ // src/account/voucher-pdf.ts
5
+ var MAX_VOUCHER_PDF_BYTES = 256 * 1024;
6
+ var MAX_PAGES = 3;
7
+ var HELV = [278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584];
8
+ var HELV_B = [278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584];
9
+ var FONT_NAMES = { F1: "Helvetica", F2: "Helvetica-Bold", F3: "Courier-Bold", F4: "Courier" };
10
+ var CP1252 = { 8364: 128, 8216: 145, 8217: 146, 8220: 147, 8221: 148, 8226: 149, 8211: 150, 8212: 151 };
11
+ function toBytes(s) {
12
+ const out = [];
13
+ for (const ch of s) {
14
+ const c = ch.codePointAt(0);
15
+ if (c < 32 || c === 127) out.push(32);
16
+ else if (c < 127 || c >= 160 && c <= 255) out.push(c);
17
+ else out.push(CP1252[c] ?? 63);
18
+ }
19
+ return out;
20
+ }
21
+ function pdfString(s) {
22
+ let o = "(";
23
+ for (const b of toBytes(s)) o += b >= 32 && b < 127 && b !== 40 && b !== 41 && b !== 92 ? String.fromCharCode(b) : `\\${b.toString(8).padStart(3, "0")}`;
24
+ return o + ")";
25
+ }
26
+ function charWidth(font, ch) {
27
+ if (font === "F3" || font === "F4") return 600;
28
+ const c = ch.codePointAt(0);
29
+ const table = font === "F2" ? HELV_B : HELV;
30
+ if (c >= 32 && c < 127) return table[c - 32];
31
+ const base = ch.normalize("NFD")[0].codePointAt(0);
32
+ return base >= 32 && base < 127 ? table[base - 32] : 556;
33
+ }
34
+ var textWidth = (font, size, s) => [...s].reduce((w, ch) => w + charWidth(font, ch), 0) * size / 1e3;
35
+ function wrap(font, size, text, max) {
36
+ const lines = [];
37
+ for (const para of text.split(/\r?\n/)) {
38
+ let line = "";
39
+ for (const word of para.split(/\s+/).filter(Boolean)) {
40
+ let w = word;
41
+ while (textWidth(font, size, w) > max) {
42
+ let n2 = 1;
43
+ while (n2 < w.length && textWidth(font, size, w.slice(0, n2 + 1)) <= max) n2++;
44
+ if (line) lines.push(line), line = "";
45
+ lines.push(w.slice(0, n2));
46
+ w = w.slice(n2);
47
+ }
48
+ const next = line ? `${line} ${w}` : w;
49
+ if (line && textWidth(font, size, next) > max) lines.push(line), line = w;
50
+ else line = next;
51
+ }
52
+ lines.push(line);
53
+ }
54
+ return lines;
55
+ }
56
+ var n = (x) => String(Math.round(x * 100) / 100);
57
+ function renderVoucherPdf(v, opts = {}) {
58
+ const locale = opts.locale ?? "es-MX";
59
+ const t = docText(locale);
60
+ const [W, H] = opts.paper === "letter" ? [612, 792] : [595.28, 841.89];
61
+ const M = 54;
62
+ const right = W - M;
63
+ const inner = right - M;
64
+ const pages = [];
65
+ let ops = "";
66
+ let y = H - M;
67
+ const newPage = () => {
68
+ if (pages.length >= MAX_PAGES) return false;
69
+ if (ops) pages.push(ops);
70
+ ops = "";
71
+ y = H - M;
72
+ return true;
73
+ };
74
+ const text = (font, size, x, s, gray = 0) => {
75
+ ops += `BT ${n(gray)} g /${font} ${size} Tf ${n(x)} ${n(y)} Td ${pdfString(s)} Tj ET
76
+ `;
77
+ };
78
+ const ensure = (h) => {
79
+ if (y - h < M) newPage();
80
+ };
81
+ const paragraph = (font, size, s, opt = {}) => {
82
+ const lead = opt.lead ?? size * 1.4;
83
+ for (const line of wrap(font, size, s, opt.width ?? inner)) {
84
+ ensure(lead);
85
+ y -= lead;
86
+ if (line) text(font, size, opt.x ?? M, line, opt.gray ?? 0);
87
+ }
88
+ };
89
+ const amount = formatMoney(v.amount, locale);
90
+ const top = y;
91
+ y -= 20;
92
+ text("F2", 20, M, t.title);
93
+ const subtitle = [opts.shopName, methodName(v, t), opts.number ? `${t.order} ${opts.number}` : ""].filter(Boolean).join(" \xB7 ");
94
+ if (subtitle) {
95
+ y -= 15;
96
+ paragraph("F1", 10, subtitle, { width: amount ? inner * 0.6 : inner, gray: 0.33, lead: 12 });
97
+ }
98
+ const afterTitle = y;
99
+ if (amount) {
100
+ y = top - 10;
101
+ const label = t.total.toUpperCase();
102
+ text("F1", 8, right - textWidth("F1", 8, label), label, 0.33);
103
+ y -= 22;
104
+ text("F2", 22, right - textWidth("F2", 22, amount), amount);
105
+ }
106
+ y = Math.min(afterTitle, y) - 10;
107
+ ops += `0 g 2 w ${n(M)} ${n(y)} m ${n(right)} ${n(y)} l S
108
+ `;
109
+ y -= 8;
110
+ for (const f of voucherFields(v, t)) {
111
+ const size = f.value.length > 36 ? 12 : 16;
112
+ const lines = wrap("F3", size, f.value, inner - 24);
113
+ const h = 14 + 12 + lines.length * size * 1.3 + 8;
114
+ ensure(h + 12);
115
+ y -= 12;
116
+ ops += `0 G 0.8 w ${n(M)} ${n(y - h)} ${n(inner)} ${n(h)} re S
117
+ `;
118
+ const boxTop = y;
119
+ y -= 16;
120
+ text("F1", 8, M + 12, f.label.toUpperCase(), 0.33);
121
+ y -= 4;
122
+ for (const line of lines) {
123
+ y -= size * 1.3;
124
+ text("F3", size, M + 12, line);
125
+ }
126
+ y = boxTop - h;
127
+ }
128
+ const g = v.barcode ? barcodeGeometry(v.barcode, { ...v.barcode_format ? { format: v.barcode_format } : {}, height: 60 }) : null;
129
+ if (g && v.barcode) {
130
+ const scale = Math.min(1, inner / g.width) * 0.75;
131
+ const bw = g.width * scale;
132
+ const bh = 60;
133
+ ensure(bh + 40);
134
+ y -= 18;
135
+ ops += `0 g
136
+ `;
137
+ const x0 = M + (inner - bw) / 2;
138
+ for (const r of g.rects) ops += `${n(x0 + r.x * scale)} ${n(y - bh)} ${n(r.w * scale)} ${n(bh)} re f
139
+ `;
140
+ y -= bh + 12;
141
+ const cw = textWidth("F4", 10, v.barcode);
142
+ text("F4", 10, M + (inner - Math.min(cw, inner)) / 2, v.barcode.slice(0, Math.floor(inner / 6)));
143
+ y -= 4;
144
+ }
145
+ const expires = formatDate(v.expires_at, locale, opts.timeZone);
146
+ if (expires) {
147
+ y -= 8;
148
+ paragraph("F2", 10, `${t.expires}: ${expires.replace(/\.$/, "")}.`);
149
+ paragraph("F1", 10, t.expiresNote);
150
+ }
151
+ y -= 10;
152
+ ensure(40);
153
+ paragraph("F2", 12, t.stepsTitle, { lead: 16 });
154
+ voucherSteps(v, t).forEach((s, i) => {
155
+ const lines = wrap("F1", 10, s, inner - 18);
156
+ ensure(lines.length * 14 + 2);
157
+ y -= 2;
158
+ lines.forEach((line, j) => {
159
+ y -= 14;
160
+ if (j === 0) text("F1", 10, M, `${i + 1}.`);
161
+ text("F1", 10, M + 18, line);
162
+ });
163
+ });
164
+ if (v.instructions) {
165
+ y -= 6;
166
+ paragraph("F1", 9, v.instructions, { gray: 0.33, lead: 12 });
167
+ }
168
+ y -= 8;
169
+ paragraph("F1", 8, t.footer, { gray: 0.33, lead: 11 });
170
+ pages.push(ops);
171
+ const objs = [];
172
+ const kids = pages.map((_, i) => `${8 + i * 2} 0 R`).join(" ");
173
+ objs[1] = "<< /Type /Catalog /Pages 2 0 R >>";
174
+ objs[2] = `<< /Type /Pages /Kids [${kids}] /Count ${pages.length} >>`;
175
+ ["F1", "F2", "F3", "F4"].forEach((f, i) => objs[3 + i] = `<< /Type /Font /Subtype /Type1 /BaseFont /${FONT_NAMES[f]} /Encoding /WinAnsiEncoding >>`);
176
+ objs[7] = `<< /Title ${pdfString(`${t.title}${opts.shopName ? ` - ${opts.shopName}` : ""}`)} /Producer ${pdfString("@asteby/storefront-react")} >>`;
177
+ pages.forEach((content, i) => {
178
+ objs[8 + i * 2] = `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${n(W)} ${n(H)}] /Resources << /Font << /F1 3 0 R /F2 4 0 R /F3 5 0 R /F4 6 0 R >> >> /Contents ${9 + i * 2} 0 R >>`;
179
+ objs[9 + i * 2] = `<< /Length ${content.length} >>
180
+ stream
181
+ ${content}endstream`;
182
+ });
183
+ let out = "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n";
184
+ const offsets = [];
185
+ for (let i = 1; i < objs.length; i++) {
186
+ offsets[i] = out.length;
187
+ out += `${i} 0 obj
188
+ ${objs[i]}
189
+ endobj
190
+ `;
191
+ }
192
+ const xref = out.length;
193
+ out += `xref
194
+ 0 ${objs.length}
195
+ 0000000000 65535 f
196
+ `;
197
+ for (let i = 1; i < objs.length; i++) out += `${String(offsets[i]).padStart(10, "0")} 00000 n
198
+ `;
199
+ out += `trailer
200
+ << /Size ${objs.length} /Root 1 0 R /Info 7 0 R >>
201
+ startxref
202
+ ${xref}
203
+ %%EOF
204
+ `;
205
+ if (out.length > MAX_VOUCHER_PDF_BYTES) throw new RangeError("voucher PDF too large");
206
+ const bytes = new Uint8Array(out.length);
207
+ for (let i = 0; i < out.length; i++) bytes[i] = out.charCodeAt(i) & 255;
208
+ return bytes;
209
+ }
210
+
211
+ export { MAX_VOUCHER_PDF_BYTES, pdfString, renderVoucherPdf };
212
+ //# sourceMappingURL=voucher-pdf-LQC333AB.js.map
213
+ //# sourceMappingURL=voucher-pdf-LQC333AB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/account/voucher-pdf.ts"],"names":["n"],"mappings":"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","file":"voucher-pdf-LQC333AB.js","sourcesContent":["/**\n * The voucher as a real PDF 1.4, written by hand: no browser, no native module, no dependency, so the same code runs in\n * the store's Node/SSR route and in the buyer's browser. Standard Helvetica / Courier fonts (not embedded: every reader\n * has them), text in WinAnsi, the barcode as filled rectangles. Every external string reaches the file only through\n * `pdfString`, which writes it as ASCII octal escapes, so nothing a gateway sends can close a string or add an object.\n * Loaded on demand (the server route or the buyer's tap), never in the first load of the order screens.\n */\nimport { barcodeGeometry, type VoucherView } from './voucher.js'\nimport { docText, formatDate, formatMoney, methodName, voucherFields, voucherSteps } from './voucher-text.js'\n\nexport type VoucherPdfOptions = {\n shopName?: string\n number?: string | null\n locale?: string\n timeZone?: string\n /** `a4` (default) or `letter` (Mexico prints on both). */\n paper?: 'a4' | 'letter'\n}\n\n/** Hard ceiling of the file: a voucher is a few KB; anything near this is a bug, not a voucher. */\nexport const MAX_VOUCHER_PDF_BYTES = 256 * 1024\nconst MAX_PAGES = 3\n\n// Advance widths (1/1000 em) of ASCII 32..126 for the standard Helvetica and Helvetica-Bold (Adobe AFM).\nconst HELV = [278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584]\nconst HELV_B = [278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584]\n\ntype Font = 'F1' | 'F2' | 'F3' | 'F4'\nconst FONT_NAMES: Record<Font, string> = { F1: 'Helvetica', F2: 'Helvetica-Bold', F3: 'Courier-Bold', F4: 'Courier' }\n\n// The few characters outside Latin-1 that WinAnsi (cp1252) has at 0x80..0x9F.\nconst CP1252: Record<number, number> = { 0x20ac: 0x80, 0x2018: 0x91, 0x2019: 0x92, 0x201c: 0x93, 0x201d: 0x94, 0x2022: 0x95, 0x2013: 0x96, 0x2014: 0x97 }\n\n/** One WinAnsi byte per character; anything it cannot show becomes `?` (and control characters a space). */\nfunction toBytes(s: string): number[] {\n const out: number[] = []\n for (const ch of s) {\n const c = ch.codePointAt(0)!\n if (c < 32 || c === 127) out.push(32)\n else if (c < 127 || (c >= 160 && c <= 255)) out.push(c)\n else out.push(CP1252[c] ?? 63)\n }\n return out\n}\n\n/** PDF literal string: printable ASCII as is (minus the three that delimit), the rest as `\\ddd`. */\nexport function pdfString(s: string): string {\n let o = '('\n for (const b of toBytes(s)) o += b >= 32 && b < 127 && b !== 40 && b !== 41 && b !== 92 ? String.fromCharCode(b) : `\\\\${b.toString(8).padStart(3, '0')}`\n return o + ')'\n}\n\nfunction charWidth(font: Font, ch: string): number {\n if (font === 'F3' || font === 'F4') return 600\n const c = ch.codePointAt(0)!\n const table = font === 'F2' ? HELV_B : HELV\n if (c >= 32 && c < 127) return table[c - 32]!\n const base = ch.normalize('NFD')[0]!.codePointAt(0)!\n return base >= 32 && base < 127 ? table[base - 32]! : 556\n}\nconst textWidth = (font: Font, size: number, s: string) => ([...s].reduce((w, ch) => w + charWidth(font, ch), 0) * size) / 1000\n\n/** Greedy word wrap to `max` points; a word wider than the line is cut. Explicit newlines are honored. */\nfunction wrap(font: Font, size: number, text: string, max: number): string[] {\n const lines: string[] = []\n for (const para of text.split(/\\r?\\n/)) {\n let line = ''\n for (const word of para.split(/\\s+/).filter(Boolean)) {\n let w = word\n while (textWidth(font, size, w) > max) {\n let n = 1\n while (n < w.length && textWidth(font, size, w.slice(0, n + 1)) <= max) n++\n if (line) (lines.push(line), (line = ''))\n lines.push(w.slice(0, n))\n w = w.slice(n)\n }\n const next = line ? `${line} ${w}` : w\n if (line && textWidth(font, size, next) > max) (lines.push(line), (line = w))\n else line = next\n }\n lines.push(line)\n }\n return lines\n}\n\nconst n = (x: number) => String(Math.round(x * 100) / 100)\n\n/** The voucher as the bytes of a PDF. Throws only if the result would exceed `MAX_VOUCHER_PDF_BYTES`. */\nexport function renderVoucherPdf(v: VoucherView, opts: VoucherPdfOptions = {}): Uint8Array {\n const locale = opts.locale ?? 'es-MX'\n const t = docText(locale)\n const [W, H] = opts.paper === 'letter' ? [612, 792] : [595.28, 841.89]\n const M = 54\n const right = W - M\n const inner = right - M\n\n const pages: string[] = []\n let ops = ''\n let y = H - M\n const newPage = () => {\n if (pages.length >= MAX_PAGES) return false\n if (ops) pages.push(ops)\n ops = ''\n y = H - M\n return true\n }\n const text = (font: Font, size: number, x: number, s: string, gray = 0) => {\n ops += `BT ${n(gray)} g /${font} ${size} Tf ${n(x)} ${n(y)} Td ${pdfString(s)} Tj ET\\n`\n }\n const ensure = (h: number) => {\n if (y - h < M) newPage()\n }\n const paragraph = (font: Font, size: number, s: string, opt: { x?: number; width?: number; gray?: number; lead?: number } = {}) => {\n const lead = opt.lead ?? size * 1.4\n for (const line of wrap(font, size, s, opt.width ?? inner)) {\n ensure(lead)\n y -= lead\n if (line) text(font, size, opt.x ?? M, line, opt.gray ?? 0)\n }\n }\n\n // Header: title and subtitle on the left, amount on the right.\n const amount = formatMoney(v.amount, locale)\n const top = y\n y -= 20\n text('F2', 20, M, t.title)\n const subtitle = [opts.shopName, methodName(v, t), opts.number ? `${t.order} ${opts.number}` : ''].filter(Boolean).join(' · ')\n if (subtitle) {\n y -= 15\n paragraph('F1', 10, subtitle, { width: amount ? inner * 0.6 : inner, gray: 0.33, lead: 12 })\n }\n const afterTitle = y\n if (amount) {\n y = top - 10\n const label = t.total.toUpperCase()\n text('F1', 8, right - textWidth('F1', 8, label), label, 0.33)\n y -= 22\n text('F2', 22, right - textWidth('F2', 22, amount), amount)\n }\n y = Math.min(afterTitle, y) - 10\n ops += `0 g 2 w ${n(M)} ${n(y)} m ${n(right)} ${n(y)} l S\\n`\n y -= 8\n\n // Fields of the method, each in a box.\n for (const f of voucherFields(v, t)) {\n const size = f.value.length > 36 ? 12 : 16\n const lines = wrap('F3', size, f.value, inner - 24)\n const h = 14 + 12 + lines.length * size * 1.3 + 8\n ensure(h + 12)\n y -= 12\n ops += `0 G 0.8 w ${n(M)} ${n(y - h)} ${n(inner)} ${n(h)} re S\\n`\n const boxTop = y\n y -= 16\n text('F1', 8, M + 12, f.label.toUpperCase(), 0.33)\n y -= 4\n for (const line of lines) {\n y -= size * 1.3\n text('F3', size, M + 12, line)\n }\n y = boxTop - h\n }\n\n // Barcode: filled rectangles, the quiet zone included in the width.\n const g = v.barcode ? barcodeGeometry(v.barcode, { ...(v.barcode_format ? { format: v.barcode_format } : {}), height: 60 }) : null\n if (g && v.barcode) {\n const scale = Math.min(1, inner / g.width) * 0.75 // module = 1.5pt at most\n const bw = g.width * scale\n const bh = 60\n ensure(bh + 40)\n y -= 18\n ops += `0 g\\n`\n const x0 = M + (inner - bw) / 2\n for (const r of g.rects) ops += `${n(x0 + r.x * scale)} ${n(y - bh)} ${n(r.w * scale)} ${n(bh)} re f\\n`\n y -= bh + 12\n const cw = textWidth('F4', 10, v.barcode)\n text('F4', 10, M + (inner - Math.min(cw, inner)) / 2, v.barcode.slice(0, Math.floor(inner / 6)))\n y -= 4\n }\n\n const expires = formatDate(v.expires_at, locale, opts.timeZone)\n if (expires) {\n y -= 8\n paragraph('F2', 10, `${t.expires}: ${expires.replace(/\\.$/, '')}.`)\n paragraph('F1', 10, t.expiresNote)\n }\n\n y -= 10\n ensure(40)\n paragraph('F2', 12, t.stepsTitle, { lead: 16 })\n voucherSteps(v, t).forEach((s, i) => {\n const lines = wrap('F1', 10, s, inner - 18)\n ensure(lines.length * 14 + 2)\n y -= 2\n lines.forEach((line, j) => {\n y -= 14\n if (j === 0) text('F1', 10, M, `${i + 1}.`)\n text('F1', 10, M + 18, line)\n })\n })\n if (v.instructions) {\n y -= 6\n paragraph('F1', 9, v.instructions, { gray: 0.33, lead: 12 })\n }\n y -= 8\n paragraph('F1', 8, t.footer, { gray: 0.33, lead: 11 })\n pages.push(ops)\n\n // Objects: 1 catalog, 2 pages, 3..6 fonts, 7 info, then (page, content) pairs.\n const objs: string[] = []\n const kids = pages.map((_, i) => `${8 + i * 2} 0 R`).join(' ')\n objs[1] = '<< /Type /Catalog /Pages 2 0 R >>'\n objs[2] = `<< /Type /Pages /Kids [${kids}] /Count ${pages.length} >>`\n ;(['F1', 'F2', 'F3', 'F4'] as Font[]).forEach((f, i) => (objs[3 + i] = `<< /Type /Font /Subtype /Type1 /BaseFont /${FONT_NAMES[f]} /Encoding /WinAnsiEncoding >>`))\n objs[7] = `<< /Title ${pdfString(`${t.title}${opts.shopName ? ` - ${opts.shopName}` : ''}`)} /Producer ${pdfString('@asteby/storefront-react')} >>`\n pages.forEach((content, i) => {\n objs[8 + i * 2] = `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${n(W)} ${n(H)}] /Resources << /Font << /F1 3 0 R /F2 4 0 R /F3 5 0 R /F4 6 0 R >> >> /Contents ${9 + i * 2} 0 R >>`\n objs[9 + i * 2] = `<< /Length ${content.length} >>\\nstream\\n${content}endstream`\n })\n\n let out = '%PDF-1.4\\n%\\xE2\\xE3\\xCF\\xD3\\n'\n const offsets: number[] = []\n for (let i = 1; i < objs.length; i++) {\n offsets[i] = out.length\n out += `${i} 0 obj\\n${objs[i]}\\nendobj\\n`\n }\n const xref = out.length\n out += `xref\\n0 ${objs.length}\\n0000000000 65535 f \\n`\n for (let i = 1; i < objs.length; i++) out += `${String(offsets[i]).padStart(10, '0')} 00000 n \\n`\n out += `trailer\\n<< /Size ${objs.length} /Root 1 0 R /Info 7 0 R >>\\nstartxref\\n${xref}\\n%%EOF\\n`\n\n if (out.length > MAX_VOUCHER_PDF_BYTES) throw new RangeError('voucher PDF too large')\n const bytes = new Uint8Array(out.length)\n for (let i = 0; i < out.length; i++) bytes[i] = out.charCodeAt(i) & 0xff\n return bytes\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/storefront-react",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "React bindings for @asteby/storefront — SSR-safe provider, optimistic cart, Money, responsive Image, prices, variant selection, SEO meta and JSON-LD, section registry and server-rendered theme CSS.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -1,182 +0,0 @@
1
- // src/account/voucher.ts
2
- var MAX = 256;
3
- function text(v) {
4
- if (typeof v === "number" && Number.isFinite(v)) return String(v);
5
- if (typeof v !== "string") return null;
6
- const s = v.trim().slice(0, MAX);
7
- return s || null;
8
- }
9
- function moneyOf(v) {
10
- if (!v || typeof v !== "object") return null;
11
- const m = v;
12
- const amount = text(m.amount);
13
- const cur = text(m.currency_code);
14
- return amount && cur && Number.isFinite(Number(amount)) ? { amount, currency_code: cur.toUpperCase() } : null;
15
- }
16
- function voucherOf(p) {
17
- const pay = p?.payment;
18
- if (!pay || typeof pay !== "object") return null;
19
- const v = {
20
- method: text(pay.method ?? pay.provider),
21
- reference: text(pay.reference),
22
- barcode: text(pay.barcode),
23
- clabe: text(pay.clabe),
24
- expires_at: text(pay.expires_at) ?? text(p?.expires_at),
25
- amount: moneyOf(pay.amount) ?? moneyOf(p?.total),
26
- instructions: text(pay.instructions)
27
- };
28
- return v.reference || v.barcode || v.clabe ? v : null;
29
- }
30
- function barcodeValue(v) {
31
- return v.barcode ?? (v.method?.toLowerCase() === "oxxo" ? v.reference : null);
32
- }
33
- var BARS = [
34
- "11011001100",
35
- "11001101100",
36
- "11001100110",
37
- "10010011000",
38
- "10010001100",
39
- "10001001100",
40
- "10011001000",
41
- "10011000100",
42
- "10001100100",
43
- "11001001000",
44
- "11001000100",
45
- "11000100100",
46
- "10110011100",
47
- "10011011100",
48
- "10011001110",
49
- "10111001100",
50
- "10011101100",
51
- "10011100110",
52
- "11001110010",
53
- "11001011100",
54
- "11001001110",
55
- "11011100100",
56
- "11001110100",
57
- "11101101110",
58
- "11101001100",
59
- "11100101100",
60
- "11100100110",
61
- "11101100100",
62
- "11100110100",
63
- "11100110010",
64
- "11011011000",
65
- "11011000110",
66
- "11000110110",
67
- "10100011000",
68
- "10001011000",
69
- "10001000110",
70
- "10110001000",
71
- "10001101000",
72
- "10001100010",
73
- "11010001000",
74
- "11000101000",
75
- "11000100010",
76
- "10110111000",
77
- "10110001110",
78
- "10001101110",
79
- "10111011000",
80
- "10111000110",
81
- "10001110110",
82
- "11101110110",
83
- "11010001110",
84
- "11000101110",
85
- "11011101000",
86
- "11011100010",
87
- "11011101110",
88
- "11101011000",
89
- "11101000110",
90
- "11100010110",
91
- "11101101000",
92
- "11101100010",
93
- "11100011010",
94
- "11101111010",
95
- "11001000010",
96
- "11110001010",
97
- "10100110000",
98
- "10100001100",
99
- "10010110000",
100
- "10010000110",
101
- "10000101100",
102
- "10000100110",
103
- "10110010000",
104
- "10110000100",
105
- "10011010000",
106
- "10011000010",
107
- "10000110100",
108
- "10000110010",
109
- "11000010010",
110
- "11001010000",
111
- "11110111010",
112
- "11000010100",
113
- "10001111010",
114
- "10100111100",
115
- "10010111100",
116
- "10010011110",
117
- "10111100100",
118
- "10011110100",
119
- "10011110010",
120
- "11110100100",
121
- "11110010100",
122
- "11110010010",
123
- "11011011110",
124
- "11011110110",
125
- "11110110110",
126
- "10101111000",
127
- "10100011110",
128
- "10001011110",
129
- "10111101000",
130
- "10111100010",
131
- "11110101000",
132
- "11110100010",
133
- "10111011110",
134
- "10111101110",
135
- "11101011110",
136
- "11110101110",
137
- "11010000100",
138
- "11010010000",
139
- "11010011100"
140
- ];
141
- var STOP = "1100011101011";
142
- function code128Modules(value) {
143
- if (!value || value.length > 80) return null;
144
- let codes;
145
- if (/^\d+$/.test(value) && value.length % 2 === 0) {
146
- codes = [105];
147
- for (let i = 0; i < value.length; i += 2) codes.push(Number(value.slice(i, i + 2)));
148
- } else {
149
- codes = [104];
150
- for (const ch of value) {
151
- const c = ch.charCodeAt(0);
152
- if (c < 32 || c > 126) return null;
153
- codes.push(c - 32);
154
- }
155
- }
156
- let sum = codes[0];
157
- for (let i = 1; i < codes.length; i++) sum += codes[i] * i;
158
- codes.push(sum % 103);
159
- return codes.map((c) => BARS[c]).join("") + STOP;
160
- }
161
- function barcodeGeometry(value, opts = {}) {
162
- const bits = code128Modules(value);
163
- if (!bits) return null;
164
- const mod = opts.module ?? 2;
165
- const quiet = 10;
166
- const rects = [];
167
- for (let i = 0; i < bits.length; ) {
168
- if (bits[i] === "0") {
169
- i++;
170
- continue;
171
- }
172
- let j = i;
173
- while (j < bits.length && bits[j] === "1") j++;
174
- rects.push({ x: (quiet + i) * mod, w: (j - i) * mod });
175
- i = j;
176
- }
177
- return { width: (bits.length + quiet * 2) * mod, height: opts.height ?? 70, rects };
178
- }
179
-
180
- export { barcodeGeometry, barcodeValue, code128Modules, voucherOf };
181
- //# sourceMappingURL=chunk-TXEYBDFG.js.map
182
- //# sourceMappingURL=chunk-TXEYBDFG.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/account/voucher.ts"],"names":[],"mappings":"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","file":"chunk-TXEYBDFG.js","sourcesContent":["/**\n * Pure pieces of the cash voucher (OXXO, SPEI, deposit): the normalized `VoucherView` of a `PendingPayment` and the\n * Code 128 barcode (the one cashiers' readers scan). No React, no DOM: the same code draws the barcode in the page\n * (`<Barcode>`) and in the printable document (`voucher-document.ts`, loaded only when the buyer prints).\n */\nimport type { Money, PendingPayment } from '@asteby/storefront'\n\nexport type VoucherView = {\n /** `oxxo`, `spei`, ... as the gateway publishes it. */\n method: string | null\n reference: string | null\n barcode: string | null\n clabe: string | null\n expires_at: string | null\n amount: Money | null\n instructions: string | null\n}\n\nconst MAX = 256\n\nfunction text(v: unknown): string | null {\n if (typeof v === 'number' && Number.isFinite(v)) return String(v)\n if (typeof v !== 'string') return null\n const s = v.trim().slice(0, MAX)\n return s || null\n}\n\nfunction moneyOf(v: unknown): Money | null {\n if (!v || typeof v !== 'object') return null\n const m = v as Record<string, unknown>\n const amount = text(m.amount)\n const cur = text(m.currency_code)\n return amount && cur && Number.isFinite(Number(amount)) ? { amount, currency_code: cur.toUpperCase() } : null\n}\n\n/** The voucher of a pending payment; `null` when it has neither reference, barcode nor CLABE (nothing to pay with). */\nexport function voucherOf(p: Pick<PendingPayment, 'payment' | 'total' | 'expires_at'> | null | undefined): VoucherView | null {\n const pay = p?.payment\n if (!pay || typeof pay !== 'object') return null\n const v: VoucherView = {\n method: text(pay.method ?? pay.provider),\n reference: text(pay.reference),\n barcode: text(pay.barcode),\n clabe: text(pay.clabe),\n expires_at: text(pay.expires_at) ?? text(p?.expires_at),\n amount: moneyOf(pay.amount) ?? moneyOf(p?.total),\n instructions: text(pay.instructions),\n }\n return v.reference || v.barcode || v.clabe ? v : null\n}\n\n/** The value the barcode encodes: the gateway's `barcode`, else the reference of an OXXO voucher. */\nexport function barcodeValue(v: Pick<VoucherView, 'barcode' | 'method' | 'reference'>): string | null {\n return v.barcode ?? (v.method?.toLowerCase() === 'oxxo' ? v.reference : null)\n}\n\n// 11-module patterns of symbols 0..105 and the 13-module stop (ISO/IEC 15417).\nconst BARS = [\n '11011001100', '11001101100', '11001100110', '10010011000', '10010001100', '10001001100', '10011001000', '10011000100', '10001100100', '11001001000',\n '11001000100', '11000100100', '10110011100', '10011011100', '10011001110', '10111001100', '10011101100', '10011100110', '11001110010', '11001011100',\n '11001001110', '11011100100', '11001110100', '11101101110', '11101001100', '11100101100', '11100100110', '11101100100', '11100110100', '11100110010',\n '11011011000', '11011000110', '11000110110', '10100011000', '10001011000', '10001000110', '10110001000', '10001101000', '10001100010', '11010001000',\n '11000101000', '11000100010', '10110111000', '10110001110', '10001101110', '10111011000', '10111000110', '10001110110', '11101110110', '11010001110',\n '11000101110', '11011101000', '11011100010', '11011101110', '11101011000', '11101000110', '11100010110', '11101101000', '11101100010', '11100011010',\n '11101111010', '11001000010', '11110001010', '10100110000', '10100001100', '10010110000', '10010000110', '10000101100', '10000100110', '10110010000',\n '10110000100', '10011010000', '10011000010', '10000110100', '10000110010', '11000010010', '11001010000', '11110111010', '11000010100', '10001111010',\n '10100111100', '10010111100', '10010011110', '10111100100', '10011110100', '10011110010', '11110100100', '11110010100', '11110010010', '11011011110',\n '11011110110', '11110110110', '10101111000', '10100011110', '10001011110', '10111101000', '10111100010', '11110101000', '11110100010', '10111011110',\n '10111101110', '11101011110', '11110101110', '11010000100', '11010010000', '11010011100',\n]\nconst STOP = '1100011101011'\n\n/**\n * Modules (`1` bar, `0` space) of the Code 128 of `value`: set C (digit pairs) when it is all digits of even length,\n * set B (printable ASCII) otherwise. `null` when it cannot be encoded.\n */\nexport function code128Modules(value: string): string | null {\n if (!value || value.length > 80) return null\n let codes: number[]\n if (/^\\d+$/.test(value) && value.length % 2 === 0) {\n codes = [105]\n for (let i = 0; i < value.length; i += 2) codes.push(Number(value.slice(i, i + 2)))\n } else {\n codes = [104]\n for (const ch of value) {\n const c = ch.charCodeAt(0)\n if (c < 32 || c > 126) return null\n codes.push(c - 32)\n }\n }\n let sum = codes[0]!\n for (let i = 1; i < codes.length; i++) sum += codes[i]! * i\n codes.push(sum % 103)\n return codes.map((c) => BARS[c]).join('') + STOP\n}\n\nexport type BarcodeGeometry = { width: number; height: number; rects: { x: number; w: number }[] }\n\n/** Bars of the barcode as rectangles (quiet zone of 10 modules each side included in `width`). `null` if not encodable. */\nexport function barcodeGeometry(value: string, opts: { module?: number; height?: number } = {}): BarcodeGeometry | null {\n const bits = code128Modules(value)\n if (!bits) return null\n const mod = opts.module ?? 2\n const quiet = 10\n const rects: { x: number; w: number }[] = []\n for (let i = 0; i < bits.length; ) {\n if (bits[i] === '0') {\n i++\n continue\n }\n let j = i\n while (j < bits.length && bits[j] === '1') j++\n rects.push({ x: (quiet + i) * mod, w: (j - i) * mod })\n i = j\n }\n return { width: (bits.length + quiet * 2) * mod, height: opts.height ?? 70, rects }\n}\n"]}
@@ -1,124 +0,0 @@
1
- import { barcodeValue, barcodeGeometry } from './chunk-TXEYBDFG.js';
2
-
3
- // src/account/voucher-document.ts
4
- function esc(s) {
5
- return s.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
6
- }
7
- var ES = {
8
- title: "Ficha de pago",
9
- total: "Total a pagar",
10
- reference: "Referencia",
11
- clabe: "CLABE",
12
- expires: "Vence",
13
- expiresNote: "Pasada esa fecha la ficha deja de ser v\xE1lida.",
14
- order: "Pedido",
15
- barcode: "C\xF3digo de barras",
16
- print: "Imprimir ficha",
17
- footer: "Tu pedido se genera cuando se confirma el pago. Esta ficha es de un solo uso; no la compartas.",
18
- stepsCash: [
19
- "Acude a la tienda OXXO (o el comercio indicado) y di que vas a hacer un pago de servicio en efectivo.",
20
- "Muestra el c\xF3digo de barras o dicta la referencia y paga el monto exacto.",
21
- "Conserva tu comprobante: confirmaremos tu pago autom\xE1ticamente."
22
- ],
23
- stepsSpei: ["Entra a la banca en l\xEDnea o app de tu banco.", "Haz una transferencia SPEI a la CLABE indicada por el monto exacto.", "Conserva tu comprobante: confirmaremos tu pago autom\xE1ticamente."],
24
- methods: { oxxo: "OXXO", spei: "Transferencia SPEI", bank_transfer: "Transferencia bancaria", bank_deposit: "Dep\xF3sito bancario", cash: "Pago en efectivo" },
25
- cash: "Pago en efectivo"
26
- };
27
- var EN = {
28
- title: "Payment voucher",
29
- total: "Amount to pay",
30
- reference: "Reference",
31
- clabe: "CLABE",
32
- expires: "Expires",
33
- expiresNote: "After that date the voucher is no longer valid.",
34
- order: "Order",
35
- barcode: "Barcode",
36
- print: "Print voucher",
37
- footer: "Your order is created when the payment is confirmed. This voucher is single-use; do not share it.",
38
- stepsCash: [
39
- "Go to an OXXO store (or the store indicated) and say you want to make a cash service payment.",
40
- "Show the barcode or read out the reference and pay the exact amount.",
41
- "Keep your receipt: we will confirm your payment automatically."
42
- ],
43
- stepsSpei: ["Open your bank online or app.", "Make a SPEI transfer to the CLABE below for the exact amount.", "Keep your receipt: we will confirm your payment automatically."],
44
- methods: { oxxo: "OXXO", spei: "SPEI transfer", bank_transfer: "Bank transfer", bank_deposit: "Bank deposit", cash: "Cash payment" },
45
- cash: "Cash payment"
46
- };
47
- var CSS = `
48
- @page { size: A4; margin: 18mm; }
49
- * { box-sizing: border-box; }
50
- body { margin: 0; font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: #111; background: #fff; }
51
- main { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }
52
- h1 { font-size: 22px; margin: 0; }
53
- .muted { color: #555; }
54
- .head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }
55
- .amount { font-size: 28px; font-weight: 700; text-align: right; }
56
- .box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }
57
- .label { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }
58
- .value { font: 700 22px/1.3 ui-monospace, "SF Mono", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }
59
- .bar { margin-top: 18px; text-align: center; }
60
- .bar svg { max-width: 100%; height: auto; }
61
- .steps { margin: 18px 0 0; padding-left: 20px; }
62
- .note { margin-top: 18px; font-size: 12px; }
63
- .pre { white-space: pre-line; }
64
- .actions { margin-top: 24px; display: flex; gap: 12px; }
65
- .actions button { font: inherit; padding: 10px 18px; border: 1px solid #111; background: #111; color: #fff; cursor: pointer; }
66
- @media print { .actions { display: none; } main { padding: 0; } }
67
- `;
68
- function formatMoney(m, locale) {
69
- if (!m) return "";
70
- try {
71
- return new Intl.NumberFormat(locale, { style: "currency", currency: m.currency_code }).format(Number(m.amount));
72
- } catch {
73
- return `${m.amount} ${m.currency_code}`;
74
- }
75
- }
76
- function formatDate(iso, locale, timeZone) {
77
- if (!iso) return "";
78
- const d = new Date(iso);
79
- if (Number.isNaN(d.getTime())) return "";
80
- try {
81
- return d.toLocaleString(locale, { dateStyle: "long", timeStyle: "short", ...timeZone ? { timeZone } : {} });
82
- } catch {
83
- return d.toISOString();
84
- }
85
- }
86
- function barcodeSvg(value, label) {
87
- const g = barcodeGeometry(value);
88
- if (!g) return null;
89
- const rects = g.rects.map((r) => `<rect x="${r.x}" y="0" width="${r.w}" height="${g.height}"/>`).join("");
90
- return `<svg viewBox="0 0 ${g.width} ${g.height}" width="${g.width}" height="${g.height}" role="img" aria-label="${esc(label)} ${esc(value)}" shape-rendering="crispEdges" fill="#000">${rects}</svg>`;
91
- }
92
- function renderVoucherDocument(v, opts = {}) {
93
- const locale = opts.locale ?? "es-MX";
94
- const t = locale.toLowerCase().startsWith("en") ? EN : ES;
95
- const shop = opts.shopName || "";
96
- const method = v.method ? Object.prototype.hasOwnProperty.call(t.methods, v.method.toLowerCase()) ? t.methods[v.method.toLowerCase()] : v.method : t.cash;
97
- const isSpei = !!v.clabe && !v.reference;
98
- const code = barcodeValue(v);
99
- const svg = code ? barcodeSvg(code, t.barcode) : null;
100
- const expires = formatDate(v.expires_at, locale, opts.timeZone);
101
- const field = (label, value) => value ? `<div class="box"><div class="label">${esc(label)}</div><div class="value">${esc(value)}</div></div>` : "";
102
- const steps = isSpei ? t.stepsSpei : t.stepsCash;
103
- const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ""].filter(Boolean).map(esc).join(" \xB7 ");
104
- return `<!doctype html>
105
- <html lang="${esc(locale)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
106
- <meta name="robots" content="noindex"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ""}</title><style>${CSS}</style></head>
107
- <body><main>
108
- <div class="head"><div><h1>${esc(t.title)}</h1><div class="muted">${subtitle}</div></div>
109
- ${v.amount ? `<div><div class="label" style="text-align:right">${esc(t.total)}</div><div class="amount">${esc(formatMoney(v.amount, locale))}</div></div>` : ""}</div>
110
- ${field(t.reference, v.reference)}${field(t.clabe, v.clabe)}
111
- ${svg ? `<div class="bar">${svg}<div class="muted" style="font-family:ui-monospace,monospace">${esc(code)}</div></div>` : ""}
112
- ${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires)}. ${esc(t.expiresNote)}</p>` : ""}
113
- <ol class="steps">${steps.map((s) => `<li>${esc(s)}</li>`).join("")}</ol>
114
- ${v.instructions ? `<p class="note pre muted">${esc(v.instructions)}</p>` : ""}
115
- <p class="note muted">${esc(t.footer)}</p>
116
- ${opts.printButton ? `<div class="actions"><button type="button" id="print">${esc(t.print)}</button></div>` : ""}
117
- </main>
118
- ${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce="${esc(opts.nonce)}"` : ""}>(function(){var b=document.getElementById("print");if(b)b.addEventListener("click",function(){window.print()});${opts.autoPrint ? 'window.addEventListener("load",function(){setTimeout(function(){window.print()},300)});' : ""}})();</script>` : ""}
119
- </body></html>`;
120
- }
121
-
122
- export { esc, renderVoucherDocument };
123
- //# sourceMappingURL=voucher-document-SFWJCLTN.js.map
124
- //# sourceMappingURL=voucher-document-SFWJCLTN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/account/voucher-document.ts"],"names":[],"mappings":"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","file":"voucher-document-SFWJCLTN.js","sourcesContent":["/**\n * Printable voucher (A4 HTML) that does not depend on any payment gateway: built only from the voucher data OPS keeps.\n * Loaded on demand (the buyer taps print/download) or by `pendingVoucherResponse` on the server; plain text, no React.\n * Everything external passes through `esc` before it enters the HTML.\n */\nimport type { Money } from '@asteby/storefront'\nimport { barcodeGeometry, barcodeValue, type VoucherView } from './voucher.js'\n\nexport function esc(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[c] as string)\n}\n\ntype DocText = {\n title: string\n total: string\n reference: string\n clabe: string\n expires: string\n expiresNote: string\n order: string\n barcode: string\n print: string\n footer: string\n stepsCash: string[]\n stepsSpei: string[]\n methods: Record<string, string>\n cash: string\n}\n\nconst ES: DocText = {\n title: 'Ficha de pago',\n total: 'Total a pagar',\n reference: 'Referencia',\n clabe: 'CLABE',\n expires: 'Vence',\n expiresNote: 'Pasada esa fecha la ficha deja de ser válida.',\n order: 'Pedido',\n barcode: 'Código de barras',\n print: 'Imprimir ficha',\n footer: 'Tu pedido se genera cuando se confirma el pago. Esta ficha es de un solo uso; no la compartas.',\n stepsCash: [\n 'Acude a la tienda OXXO (o el comercio indicado) y di que vas a hacer un pago de servicio en efectivo.',\n 'Muestra el código de barras o dicta la referencia y paga el monto exacto.',\n 'Conserva tu comprobante: confirmaremos tu pago automáticamente.',\n ],\n stepsSpei: ['Entra a la banca en línea o app de tu banco.', 'Haz una transferencia SPEI a la CLABE indicada por el monto exacto.', 'Conserva tu comprobante: confirmaremos tu pago automáticamente.'],\n methods: { oxxo: 'OXXO', spei: 'Transferencia SPEI', bank_transfer: 'Transferencia bancaria', bank_deposit: 'Depósito bancario', cash: 'Pago en efectivo' },\n cash: 'Pago en efectivo',\n}\n\nconst EN: DocText = {\n title: 'Payment voucher',\n total: 'Amount to pay',\n reference: 'Reference',\n clabe: 'CLABE',\n expires: 'Expires',\n expiresNote: 'After that date the voucher is no longer valid.',\n order: 'Order',\n barcode: 'Barcode',\n print: 'Print voucher',\n footer: 'Your order is created when the payment is confirmed. This voucher is single-use; do not share it.',\n stepsCash: [\n 'Go to an OXXO store (or the store indicated) and say you want to make a cash service payment.',\n 'Show the barcode or read out the reference and pay the exact amount.',\n 'Keep your receipt: we will confirm your payment automatically.',\n ],\n stepsSpei: ['Open your bank online or app.', 'Make a SPEI transfer to the CLABE below for the exact amount.', 'Keep your receipt: we will confirm your payment automatically.'],\n methods: { oxxo: 'OXXO', spei: 'SPEI transfer', bank_transfer: 'Bank transfer', bank_deposit: 'Bank deposit', cash: 'Cash payment' },\n cash: 'Cash payment',\n}\n\nexport type VoucherDocumentOptions = {\n shopName?: string\n /** Order number, if there is one yet. */\n number?: string | null\n locale?: string\n /** IANA zone the expiry is printed in (default: the runtime's). */\n timeZone?: string\n /** Print button on screen (hidden when printing). */\n printButton?: boolean\n /** Opens the print dialog on load. */\n autoPrint?: boolean\n /** `<script>` nonce when the one serving the voucher sends a CSP with `script-src 'nonce-…'`. */\n nonce?: string\n}\n\nconst CSS = `\n@page { size: A4; margin: 18mm; }\n* { box-sizing: border-box; }\nbody { margin: 0; font: 14px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: #111; background: #fff; }\nmain { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }\nh1 { font-size: 22px; margin: 0; }\n.muted { color: #555; }\n.head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }\n.amount { font-size: 28px; font-weight: 700; text-align: right; }\n.box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }\n.label { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }\n.value { font: 700 22px/1.3 ui-monospace, \"SF Mono\", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }\n.bar { margin-top: 18px; text-align: center; }\n.bar svg { max-width: 100%; height: auto; }\n.steps { margin: 18px 0 0; padding-left: 20px; }\n.note { margin-top: 18px; font-size: 12px; }\n.pre { white-space: pre-line; }\n.actions { margin-top: 24px; display: flex; gap: 12px; }\n.actions button { font: inherit; padding: 10px 18px; border: 1px solid #111; background: #111; color: #fff; cursor: pointer; }\n@media print { .actions { display: none; } main { padding: 0; } }\n`\n\nfunction formatMoney(m: Money | null, locale: string): string {\n if (!m) return ''\n try {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: m.currency_code }).format(Number(m.amount))\n } catch {\n return `${m.amount} ${m.currency_code}`\n }\n}\n\nfunction formatDate(iso: string | null, locale: string, timeZone?: string): string {\n if (!iso) return ''\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return ''\n try {\n return d.toLocaleString(locale, { dateStyle: 'long', timeStyle: 'short', ...(timeZone ? { timeZone } : {}) })\n } catch {\n return d.toISOString()\n }\n}\n\nfunction barcodeSvg(value: string, label: string): string | null {\n const g = barcodeGeometry(value)\n if (!g) return null\n const rects = g.rects.map((r) => `<rect x=\"${r.x}\" y=\"0\" width=\"${r.w}\" height=\"${g.height}\"/>`).join('')\n return `<svg viewBox=\"0 0 ${g.width} ${g.height}\" width=\"${g.width}\" height=\"${g.height}\" role=\"img\" aria-label=\"${esc(label)} ${esc(value)}\" shape-rendering=\"crispEdges\" fill=\"#000\">${rects}</svg>`\n}\n\n/** Complete HTML document of the voucher. Missing data is simply not drawn. */\nexport function renderVoucherDocument(v: VoucherView, opts: VoucherDocumentOptions = {}): string {\n const locale = opts.locale ?? 'es-MX'\n const t = locale.toLowerCase().startsWith('en') ? EN : ES\n const shop = opts.shopName || ''\n // Own keys only: a gateway method named `constructor` or `__proto__` must print as itself, not as Object internals.\n const method = v.method ? (Object.prototype.hasOwnProperty.call(t.methods, v.method.toLowerCase()) ? t.methods[v.method.toLowerCase()]! : v.method) : t.cash\n const isSpei = !!v.clabe && !v.reference\n const code = barcodeValue(v)\n const svg = code ? barcodeSvg(code, t.barcode) : null\n const expires = formatDate(v.expires_at, locale, opts.timeZone)\n const field = (label: string, value: string | null) => (value ? `<div class=\"box\"><div class=\"label\">${esc(label)}</div><div class=\"value\">${esc(value)}</div></div>` : '')\n const steps = isSpei ? t.stepsSpei : t.stepsCash\n const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ''].filter(Boolean).map(esc).join(' · ')\n return `<!doctype html>\n<html lang=\"${esc(locale)}\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"robots\" content=\"noindex\"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ''}</title><style>${CSS}</style></head>\n<body><main>\n<div class=\"head\"><div><h1>${esc(t.title)}</h1><div class=\"muted\">${subtitle}</div></div>\n${v.amount ? `<div><div class=\"label\" style=\"text-align:right\">${esc(t.total)}</div><div class=\"amount\">${esc(formatMoney(v.amount, locale))}</div></div>` : ''}</div>\n${field(t.reference, v.reference)}${field(t.clabe, v.clabe)}\n${svg ? `<div class=\"bar\">${svg}<div class=\"muted\" style=\"font-family:ui-monospace,monospace\">${esc(code as string)}</div></div>` : ''}\n${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires)}. ${esc(t.expiresNote)}</p>` : ''}\n<ol class=\"steps\">${steps.map((s) => `<li>${esc(s)}</li>`).join('')}</ol>\n${v.instructions ? `<p class=\"note pre muted\">${esc(v.instructions)}</p>` : ''}\n<p class=\"note muted\">${esc(t.footer)}</p>\n${opts.printButton ? `<div class=\"actions\"><button type=\"button\" id=\"print\">${esc(t.print)}</button></div>` : ''}\n</main>\n${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce=\"${esc(opts.nonce)}\"` : ''}>(function(){var b=document.getElementById(\"print\");if(b)b.addEventListener(\"click\",function(){window.print()});${opts.autoPrint ? 'window.addEventListener(\"load\",function(){setTimeout(function(){window.print()},300)});' : ''}})();</script>` : ''}\n</body></html>`\n}\n"]}