@flopay/ui 0.6.2 → 0.7.1

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 CHANGED
@@ -104,6 +104,8 @@ and copyright live in `flopay-footer.tsx`, so adding a footer link is one change
104
104
  here plus a version bump, and every portal picks it up. Portals hosted off
105
105
  `flopay.com` pass `baseUrl` to make the marketing routes absolute; `demoUrl` and
106
106
  `contactUrl` cover the two entries a portal usually wants to re-point at itself.
107
+ The Product column links to Card Vault, Chargeback Prevention and Subscription
108
+ Recovery in that order, followed by the remaining product placeholders.
107
109
 
108
110
  Need a different sitemap (a partner or internal portal)? Use the lower-level
109
111
  `Footer` with your own `columns`/`legal`, or start from `flopayFooterContent()`
@@ -162,6 +164,74 @@ Colour and face come from `--annotation-ink` (brand blue) and
162
164
  floating/list switch is a `@media (min-width: 1120px)` rule sized for a ~720px
163
165
  content box — apps in a constrained layout should re-declare that one block.
164
166
 
167
+ ### 6. Transactional email
168
+
169
+ `@flopay/ui/email` renders a provider-neutral HTML string and matching plain
170
+ text. It does not send messages or configure a delivery provider.
171
+
172
+ ```tsx
173
+ import { renderTransactionalEmail } from "@flopay/ui/email";
174
+
175
+ const { html, text } = renderTransactionalEmail({
176
+ preheader: "Your FloPay payment receipt is ready",
177
+ heading: "Payment received",
178
+ body: [
179
+ "Thanks, Alex. Your payment was processed successfully.",
180
+ "Keep this receipt for your records.",
181
+ ],
182
+ action: {
183
+ label: "View receipt",
184
+ href: "https://flopay.com/receipts/FP-2048",
185
+ },
186
+ detail: {
187
+ kind: "keyValue",
188
+ rows: [
189
+ { label: "Reference", value: "FP-2048" },
190
+ { label: "Amount", value: "$48.00 USD" },
191
+ ],
192
+ },
193
+ footer: {
194
+ address: "FloPay LLC, 100 Payments Way, New York, NY",
195
+ },
196
+ });
197
+ ```
198
+
199
+ The fixed slots are the content contract: one concise preheader, one heading,
200
+ plain-text body paragraphs, an optional action, and either a code or key-value
201
+ detail. Consumers supply content rather than React children or arbitrary HTML,
202
+ so new account and payment messages reuse the same reading order and layout.
203
+ All links are real anchors, and the action URL and labelled details remain
204
+ usable in the generated plain text.
205
+
206
+ Email clients cannot use the live CSS token preset. The template therefore
207
+ mirrors the approved values as inline literals: brand `#1785e0`, text
208
+ `#0a0a0b`, border `#e5e5e8`, an `8px` radius, and an Inter-first system font
209
+ stack with Roboto/Arial fallbacks. The layout is a 600px table-based card with
210
+ 40px desktop padding and 24px narrow-screen padding. Update
211
+ `src/email/theme.ts` whenever the corresponding values in `styles/tokens.css`
212
+ change.
213
+
214
+ The default `FLOPAY_EMAIL_LOGO_URL` is the hosted approved asset at
215
+ `https://flopay.com/logo.png`. The logo is decorative (`alt=""`) because the
216
+ adjacent text brand name provides the accessible name and remains visible for
217
+ images-off clients. A service may pass an absolute HTTPS `logoUrl` when it
218
+ needs to host the same asset itself; packaged files, `data:` URLs, and
219
+ provider-specific CID references are not portable email sources.
220
+
221
+ The shared transactional footer defaults to `FloPay LLC`,
222
+ `hello@flopay.com`, Privacy, Terms, and a service-message notice. It does not
223
+ include a marketing unsubscribe. `footer` can override the company, support
224
+ label/URL, legal URLs, notice, and optional mailing address when legal or
225
+ support requirements differ.
226
+
227
+ The initial compatibility baseline is Apple Mail on macOS/iOS; Gmail web,
228
+ iOS, and Android; Outlook Windows desktop/MSO, Outlook.com, and Microsoft 365
229
+ web; and Yahoo. The markup uses layout tables and inline styles, with responsive
230
+ and dark-mode CSS as progressive enhancements. Before a release changes the
231
+ layout, verify Outlook Windows, dark mode, and images-off behavior in real
232
+ clients or an email rendering service in addition to the automated render
233
+ snapshot.
234
+
165
235
  ## Design tokens
166
236
 
167
237
  `styles/tokens.css` defines surfaces, borders, text, accent, **brand
@@ -0,0 +1,425 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/email/index.tsx
21
+ var email_exports = {};
22
+ __export(email_exports, {
23
+ FLOPAY_EMAIL_LOGO_URL: () => FLOPAY_EMAIL_LOGO_URL,
24
+ TransactionalEmail: () => TransactionalEmail,
25
+ renderTransactionalEmail: () => renderTransactionalEmail
26
+ });
27
+ module.exports = __toCommonJS(email_exports);
28
+ var import_components = require("@react-email/components");
29
+ var import_render = require("@react-email/render");
30
+ var import_server = require("react-dom/server");
31
+
32
+ // src/email/theme.ts
33
+ var emailTheme = {
34
+ colors: {
35
+ background: "#f7f7f8",
36
+ surface: "#ffffff",
37
+ muted: "#f0f0f2",
38
+ border: "#e5e5e8",
39
+ text: "#0a0a0b",
40
+ textSecondary: "#52525b",
41
+ brand: "#1785e0",
42
+ brandLight: "#4ba6ec",
43
+ accessibleLink: "#0969b3",
44
+ darkBackground: "#0a0a0b",
45
+ darkSurface: "#141416",
46
+ darkMuted: "#1c1c1f",
47
+ darkBorder: "#27272a",
48
+ darkText: "#fafafa",
49
+ darkTextSecondary: "#a1a1aa"
50
+ },
51
+ radius: "8px",
52
+ font: "Inter, -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif",
53
+ fontMono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
54
+ width: "600px"
55
+ };
56
+
57
+ // src/email/index.tsx
58
+ var import_jsx_runtime = require("react/jsx-runtime");
59
+ var FLOPAY_EMAIL_LOGO_URL = "https://flopay.com/logo.png";
60
+ var DEFAULT_TRANSACTIONAL_FOOTER = {
61
+ companyName: "FloPay LLC",
62
+ supportLabel: "hello@flopay.com",
63
+ supportUrl: "mailto:hello@flopay.com",
64
+ privacyUrl: "https://flopay.com/legal/privacy",
65
+ termsUrl: "https://flopay.com/legal/terms",
66
+ notice: "This is a service message about your FloPay account.",
67
+ address: ""
68
+ };
69
+ var FOOTER_TEXT_STYLE = {
70
+ color: emailTheme.colors.textSecondary,
71
+ fontSize: "13px",
72
+ lineHeight: "20px",
73
+ margin: "0 0 12px"
74
+ };
75
+ function Detail({ detail }) {
76
+ if (detail.kind === "keyValue") {
77
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
+ "table",
79
+ {
80
+ cellPadding: "0",
81
+ cellSpacing: "0",
82
+ className: "email-detail",
83
+ "data-key-value": "true",
84
+ style: {
85
+ backgroundColor: emailTheme.colors.background,
86
+ border: `1px solid ${emailTheme.colors.border}`,
87
+ borderRadius: emailTheme.radius,
88
+ margin: "24px 0",
89
+ width: "100%"
90
+ },
91
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: detail.rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { "data-key-value-row": "true", children: [
92
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
93
+ "th",
94
+ {
95
+ className: "email-muted",
96
+ scope: "row",
97
+ style: {
98
+ borderBottom: index < detail.rows.length - 1 ? `1px solid ${emailTheme.colors.border}` : void 0,
99
+ color: emailTheme.colors.textSecondary,
100
+ fontSize: "14px",
101
+ fontWeight: 600,
102
+ padding: "12px 16px",
103
+ verticalAlign: "top",
104
+ width: "36%"
105
+ },
106
+ children: [
107
+ row.label,
108
+ ":"
109
+ ]
110
+ }
111
+ ),
112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
113
+ "td",
114
+ {
115
+ className: "email-text",
116
+ style: {
117
+ borderBottom: index < detail.rows.length - 1 ? `1px solid ${emailTheme.colors.border}` : void 0,
118
+ color: emailTheme.colors.text,
119
+ fontSize: "14px",
120
+ padding: "12px 16px",
121
+ verticalAlign: "top",
122
+ wordBreak: "break-word"
123
+ },
124
+ children: [
125
+ " ",
126
+ row.value
127
+ ]
128
+ }
129
+ )
130
+ ] }, `${index}-${row.label}`)) })
131
+ }
132
+ );
133
+ }
134
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
135
+ import_components.Section,
136
+ {
137
+ className: "email-detail",
138
+ style: {
139
+ backgroundColor: emailTheme.colors.muted,
140
+ border: `1px solid ${emailTheme.colors.border}`,
141
+ borderRadius: emailTheme.radius,
142
+ margin: "24px 0",
143
+ padding: "20px"
144
+ },
145
+ children: [
146
+ detail.caption ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ import_components.Text,
148
+ {
149
+ className: "email-muted",
150
+ style: {
151
+ color: emailTheme.colors.textSecondary,
152
+ fontSize: "13px",
153
+ fontWeight: 600,
154
+ lineHeight: "20px",
155
+ margin: "0 0 8px"
156
+ },
157
+ children: detail.caption
158
+ }
159
+ ) : null,
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
161
+ import_components.Text,
162
+ {
163
+ className: "email-text",
164
+ style: {
165
+ color: emailTheme.colors.text,
166
+ fontFamily: emailTheme.fontMono,
167
+ fontSize: "24px",
168
+ fontWeight: 700,
169
+ letterSpacing: "0.12em",
170
+ lineHeight: "32px",
171
+ margin: 0,
172
+ overflowWrap: "anywhere"
173
+ },
174
+ children: detail.value
175
+ }
176
+ )
177
+ ]
178
+ }
179
+ );
180
+ }
181
+ function EmailFooter({ overrides }) {
182
+ const footer = { ...DEFAULT_TRANSACTIONAL_FOOTER, ...overrides };
183
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Section, { style: { marginTop: "32px" }, children: [
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
185
+ import_components.Hr,
186
+ {
187
+ className: "email-divider",
188
+ style: { borderColor: emailTheme.colors.border, margin: "0 0 24px" }
189
+ }
190
+ ),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Text, { className: "email-muted", style: FOOTER_TEXT_STYLE, children: footer.notice }),
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Text, { className: "email-muted", style: FOOTER_TEXT_STYLE, children: [
193
+ "Need help?",
194
+ " ",
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
196
+ import_components.Link,
197
+ {
198
+ className: "email-link",
199
+ href: footer.supportUrl,
200
+ style: { color: emailTheme.colors.accessibleLink, textDecoration: "underline" },
201
+ children: footer.supportLabel
202
+ }
203
+ )
204
+ ] }),
205
+ footer.address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Text, { className: "email-muted", style: FOOTER_TEXT_STYLE, children: footer.address }) : null,
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Text, { className: "email-muted", style: { ...FOOTER_TEXT_STYLE, margin: 0 }, children: [
207
+ "\xA9 ",
208
+ (/* @__PURE__ */ new Date()).getFullYear(),
209
+ " ",
210
+ footer.companyName,
211
+ ".",
212
+ " ",
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
214
+ import_components.Link,
215
+ {
216
+ className: "email-link",
217
+ href: footer.privacyUrl,
218
+ style: { color: emailTheme.colors.accessibleLink, textDecoration: "underline" },
219
+ children: "Privacy"
220
+ }
221
+ ),
222
+ " ",
223
+ "\xB7",
224
+ " ",
225
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
226
+ import_components.Link,
227
+ {
228
+ className: "email-link",
229
+ href: footer.termsUrl,
230
+ style: { color: emailTheme.colors.accessibleLink, textDecoration: "underline" },
231
+ children: "Terms"
232
+ }
233
+ )
234
+ ] })
235
+ ] });
236
+ }
237
+ function Brand({ logoUrl }) {
238
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { cellPadding: "0", cellSpacing: "0", role: "presentation", style: { marginBottom: "32px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { verticalAlign: "middle", width: "40px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
240
+ import_components.Img,
241
+ {
242
+ alt: "",
243
+ height: "40",
244
+ src: logoUrl,
245
+ style: { borderRadius: emailTheme.radius },
246
+ width: "40"
247
+ }
248
+ ) }),
249
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { paddingLeft: "12px", verticalAlign: "middle" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
250
+ import_components.Text,
251
+ {
252
+ className: "email-text",
253
+ style: {
254
+ color: emailTheme.colors.text,
255
+ fontSize: "18px",
256
+ fontWeight: 700,
257
+ lineHeight: "24px",
258
+ margin: 0
259
+ },
260
+ children: "FloPay"
261
+ }
262
+ ) })
263
+ ] }) }) });
264
+ }
265
+ function TransactionalEmail({
266
+ preheader,
267
+ heading,
268
+ body,
269
+ action,
270
+ detail,
271
+ logoUrl = FLOPAY_EMAIL_LOGO_URL,
272
+ footer
273
+ }) {
274
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Html, { lang: "en", children: [
275
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Head, { children: [
276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("meta", { content: "width=device-width, initial-scale=1.0", name: "viewport" }),
277
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
278
+ :root {
279
+ color-scheme: light dark;
280
+ supported-color-schemes: light dark;
281
+ }
282
+
283
+ @media only screen and (max-width: 620px) {
284
+ .email-shell { padding: 0 !important; }
285
+ .email-card { border-left: 0 !important; border-radius: 0 !important; border-right: 0 !important; margin: 0 !important; width: 100% !important; }
286
+ .email-content { padding: 24px !important; }
287
+ }
288
+
289
+ @media (prefers-color-scheme: dark) {
290
+ .email-body { background-color: ${emailTheme.colors.darkBackground} !important; }
291
+ .email-shell { background-color: ${emailTheme.colors.darkBackground} !important; }
292
+ .email-card { background-color: ${emailTheme.colors.darkSurface} !important; border-color: ${emailTheme.colors.darkBorder} !important; }
293
+ .email-text { color: ${emailTheme.colors.darkText} !important; }
294
+ .email-muted { color: ${emailTheme.colors.darkTextSecondary} !important; }
295
+ .email-detail { background-color: ${emailTheme.colors.darkMuted} !important; border-color: ${emailTheme.colors.darkBorder} !important; }
296
+ .email-link { color: ${emailTheme.colors.brandLight} !important; }
297
+ .email-action { background-color: ${emailTheme.colors.darkText} !important; color: ${emailTheme.colors.darkBackground} !important; }
298
+ .email-divider { border-color: ${emailTheme.colors.darkBorder} !important; }
299
+ }
300
+ ` })
301
+ ] }),
302
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Preview, { children: preheader }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
304
+ import_components.Body,
305
+ {
306
+ className: "email-body",
307
+ style: {
308
+ backgroundColor: emailTheme.colors.background,
309
+ margin: 0,
310
+ padding: 0
311
+ },
312
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
313
+ import_components.Section,
314
+ {
315
+ className: "email-shell",
316
+ style: {
317
+ backgroundColor: emailTheme.colors.background,
318
+ color: emailTheme.colors.text,
319
+ fontFamily: emailTheme.font,
320
+ padding: "32px 12px",
321
+ width: "100%"
322
+ },
323
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
324
+ import_components.Container,
325
+ {
326
+ className: "email-card",
327
+ style: {
328
+ backgroundColor: emailTheme.colors.surface,
329
+ border: `1px solid ${emailTheme.colors.border}`,
330
+ borderRadius: emailTheme.radius,
331
+ borderTop: `4px solid ${emailTheme.colors.brand}`,
332
+ margin: "0 auto",
333
+ maxWidth: emailTheme.width,
334
+ overflow: "hidden",
335
+ width: "100%"
336
+ },
337
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.Section, { className: "email-content", style: { padding: "40px" }, children: [
338
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Brand, { logoUrl }),
339
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
340
+ import_components.Heading,
341
+ {
342
+ as: "h1",
343
+ className: "email-text",
344
+ style: {
345
+ color: emailTheme.colors.text,
346
+ fontSize: "28px",
347
+ fontWeight: 700,
348
+ letterSpacing: "-0.02em",
349
+ lineHeight: "36px",
350
+ margin: "0 0 16px"
351
+ },
352
+ children: heading
353
+ }
354
+ ),
355
+ body.map((paragraph, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
356
+ import_components.Text,
357
+ {
358
+ className: "email-text",
359
+ style: {
360
+ color: emailTheme.colors.text,
361
+ fontSize: "16px",
362
+ lineHeight: "25px",
363
+ margin: "0 0 16px"
364
+ },
365
+ children: paragraph
366
+ },
367
+ `${index}-${paragraph}`
368
+ )),
369
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Detail, { detail }) : null,
370
+ action ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
371
+ import_components.Button,
372
+ {
373
+ className: "email-action",
374
+ href: action.href,
375
+ style: {
376
+ backgroundColor: emailTheme.colors.text,
377
+ borderRadius: emailTheme.radius,
378
+ color: emailTheme.colors.surface,
379
+ fontSize: "16px",
380
+ fontWeight: 700,
381
+ lineHeight: "20px",
382
+ marginTop: "8px",
383
+ padding: "14px 24px",
384
+ textDecoration: "none"
385
+ },
386
+ children: action.label
387
+ }
388
+ ) : null,
389
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailFooter, { overrides: footer })
390
+ ] })
391
+ }
392
+ )
393
+ }
394
+ )
395
+ }
396
+ )
397
+ ] });
398
+ }
399
+ function renderTransactionalEmail(props) {
400
+ const markup = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransactionalEmail, { ...props }));
401
+ const html = `<!doctype html>${markup.replace(
402
+ /<link\b(?=[^>]*\brel="preload")(?=[^>]*\bas="image")[^>]*\/?>/gi,
403
+ ""
404
+ )}`;
405
+ return {
406
+ html,
407
+ text: (0, import_render.toPlainText)(html, {
408
+ selectors: [
409
+ { selector: "h1", options: { uppercase: false } },
410
+ {
411
+ selector: 'tr[data-key-value-row="true"]',
412
+ format: "block",
413
+ options: { leadingLineBreaks: 1, trailingLineBreaks: 1 }
414
+ }
415
+ ]
416
+ })
417
+ };
418
+ }
419
+ // Annotate the CommonJS export names for ESM import in node:
420
+ 0 && (module.exports = {
421
+ FLOPAY_EMAIL_LOGO_URL,
422
+ TransactionalEmail,
423
+ renderTransactionalEmail
424
+ });
425
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/email/index.tsx","../../src/email/theme.ts"],"sourcesContent":["import {\n Body,\n Button,\n Container,\n Head,\n Heading,\n Hr,\n Html,\n Img,\n Link,\n Preview,\n Section,\n Text,\n} from '@react-email/components';\nimport { toPlainText } from '@react-email/render';\nimport { renderToStaticMarkup } from 'react-dom/server';\nimport { emailTheme } from './theme';\n\nexport const FLOPAY_EMAIL_LOGO_URL = 'https://flopay.com/logo.png';\n\nexport interface TransactionalEmailAction {\n label: string;\n href: string;\n}\n\nexport interface TransactionalCodeDetail {\n kind: 'code';\n value: string;\n caption?: string;\n}\n\nexport interface TransactionalKeyValueDetail {\n kind: 'keyValue';\n rows: { label: string; value: string }[];\n}\n\nexport type TransactionalEmailDetail = TransactionalCodeDetail | TransactionalKeyValueDetail;\n\nexport interface TransactionalFooter {\n companyName: string;\n supportLabel: string;\n supportUrl: string;\n privacyUrl: string;\n termsUrl: string;\n notice: string;\n address: string;\n}\n\nexport interface TransactionalEmailProps {\n preheader: string;\n heading: string;\n body: string[];\n action?: TransactionalEmailAction;\n detail?: TransactionalEmailDetail;\n logoUrl?: string;\n footer?: Partial<TransactionalFooter>;\n}\n\nexport interface RenderedTransactionalEmail {\n html: string;\n text: string;\n}\n\nconst DEFAULT_TRANSACTIONAL_FOOTER: TransactionalFooter = {\n companyName: 'FloPay LLC',\n supportLabel: 'hello@flopay.com',\n supportUrl: 'mailto:hello@flopay.com',\n privacyUrl: 'https://flopay.com/legal/privacy',\n termsUrl: 'https://flopay.com/legal/terms',\n notice: 'This is a service message about your FloPay account.',\n address: '',\n};\n\nconst FOOTER_TEXT_STYLE = {\n color: emailTheme.colors.textSecondary,\n fontSize: '13px',\n lineHeight: '20px',\n margin: '0 0 12px',\n} as const;\n\nfunction Detail({ detail }: { detail: TransactionalEmailDetail }) {\n if (detail.kind === 'keyValue') {\n return (\n <table\n cellPadding=\"0\"\n cellSpacing=\"0\"\n className=\"email-detail\"\n data-key-value=\"true\"\n style={{\n backgroundColor: emailTheme.colors.background,\n border: `1px solid ${emailTheme.colors.border}`,\n borderRadius: emailTheme.radius,\n margin: '24px 0',\n width: '100%',\n }}\n >\n <tbody>\n {detail.rows.map((row, index) => (\n <tr data-key-value-row=\"true\" key={`${index}-${row.label}`}>\n <th\n className=\"email-muted\"\n scope=\"row\"\n style={{\n borderBottom:\n index < detail.rows.length - 1\n ? `1px solid ${emailTheme.colors.border}`\n : undefined,\n color: emailTheme.colors.textSecondary,\n fontSize: '14px',\n fontWeight: 600,\n padding: '12px 16px',\n verticalAlign: 'top',\n width: '36%',\n }}\n >\n {row.label}:\n </th>\n <td\n className=\"email-text\"\n style={{\n borderBottom:\n index < detail.rows.length - 1\n ? `1px solid ${emailTheme.colors.border}`\n : undefined,\n color: emailTheme.colors.text,\n fontSize: '14px',\n padding: '12px 16px',\n verticalAlign: 'top',\n wordBreak: 'break-word',\n }}\n >\n {' '}\n {row.value}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n }\n\n return (\n <Section\n className=\"email-detail\"\n style={{\n backgroundColor: emailTheme.colors.muted,\n border: `1px solid ${emailTheme.colors.border}`,\n borderRadius: emailTheme.radius,\n margin: '24px 0',\n padding: '20px',\n }}\n >\n {detail.caption ? (\n <Text\n className=\"email-muted\"\n style={{\n color: emailTheme.colors.textSecondary,\n fontSize: '13px',\n fontWeight: 600,\n lineHeight: '20px',\n margin: '0 0 8px',\n }}\n >\n {detail.caption}\n </Text>\n ) : null}\n <Text\n className=\"email-text\"\n style={{\n color: emailTheme.colors.text,\n fontFamily: emailTheme.fontMono,\n fontSize: '24px',\n fontWeight: 700,\n letterSpacing: '0.12em',\n lineHeight: '32px',\n margin: 0,\n overflowWrap: 'anywhere',\n }}\n >\n {detail.value}\n </Text>\n </Section>\n );\n}\n\nfunction EmailFooter({ overrides }: { overrides?: Partial<TransactionalFooter> }) {\n const footer = { ...DEFAULT_TRANSACTIONAL_FOOTER, ...overrides };\n\n return (\n <Section style={{ marginTop: '32px' }}>\n <Hr\n className=\"email-divider\"\n style={{ borderColor: emailTheme.colors.border, margin: '0 0 24px' }}\n />\n <Text className=\"email-muted\" style={FOOTER_TEXT_STYLE}>\n {footer.notice}\n </Text>\n <Text className=\"email-muted\" style={FOOTER_TEXT_STYLE}>\n Need help?{' '}\n <Link\n className=\"email-link\"\n href={footer.supportUrl}\n style={{ color: emailTheme.colors.accessibleLink, textDecoration: 'underline' }}\n >\n {footer.supportLabel}\n </Link>\n </Text>\n {footer.address ? (\n <Text className=\"email-muted\" style={FOOTER_TEXT_STYLE}>\n {footer.address}\n </Text>\n ) : null}\n <Text className=\"email-muted\" style={{ ...FOOTER_TEXT_STYLE, margin: 0 }}>\n © {new Date().getFullYear()} {footer.companyName}.{' '}\n <Link\n className=\"email-link\"\n href={footer.privacyUrl}\n style={{ color: emailTheme.colors.accessibleLink, textDecoration: 'underline' }}\n >\n Privacy\n </Link>{' '}\n ·{' '}\n <Link\n className=\"email-link\"\n href={footer.termsUrl}\n style={{ color: emailTheme.colors.accessibleLink, textDecoration: 'underline' }}\n >\n Terms\n </Link>\n </Text>\n </Section>\n );\n}\n\nfunction Brand({ logoUrl }: { logoUrl: string }) {\n return (\n <table cellPadding=\"0\" cellSpacing=\"0\" role=\"presentation\" style={{ marginBottom: '32px' }}>\n <tbody>\n <tr>\n <td style={{ verticalAlign: 'middle', width: '40px' }}>\n <Img\n alt=\"\"\n height=\"40\"\n src={logoUrl}\n style={{ borderRadius: emailTheme.radius }}\n width=\"40\"\n />\n </td>\n <td style={{ paddingLeft: '12px', verticalAlign: 'middle' }}>\n <Text\n className=\"email-text\"\n style={{\n color: emailTheme.colors.text,\n fontSize: '18px',\n fontWeight: 700,\n lineHeight: '24px',\n margin: 0,\n }}\n >\n FloPay\n </Text>\n </td>\n </tr>\n </tbody>\n </table>\n );\n}\n\nexport function TransactionalEmail({\n preheader,\n heading,\n body,\n action,\n detail,\n logoUrl = FLOPAY_EMAIL_LOGO_URL,\n footer,\n}: TransactionalEmailProps) {\n return (\n <Html lang=\"en\">\n <Head>\n <meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\" />\n <style>{`\n :root {\n color-scheme: light dark;\n supported-color-schemes: light dark;\n }\n\n @media only screen and (max-width: 620px) {\n .email-shell { padding: 0 !important; }\n .email-card { border-left: 0 !important; border-radius: 0 !important; border-right: 0 !important; margin: 0 !important; width: 100% !important; }\n .email-content { padding: 24px !important; }\n }\n\n @media (prefers-color-scheme: dark) {\n .email-body { background-color: ${emailTheme.colors.darkBackground} !important; }\n .email-shell { background-color: ${emailTheme.colors.darkBackground} !important; }\n .email-card { background-color: ${emailTheme.colors.darkSurface} !important; border-color: ${emailTheme.colors.darkBorder} !important; }\n .email-text { color: ${emailTheme.colors.darkText} !important; }\n .email-muted { color: ${emailTheme.colors.darkTextSecondary} !important; }\n .email-detail { background-color: ${emailTheme.colors.darkMuted} !important; border-color: ${emailTheme.colors.darkBorder} !important; }\n .email-link { color: ${emailTheme.colors.brandLight} !important; }\n .email-action { background-color: ${emailTheme.colors.darkText} !important; color: ${emailTheme.colors.darkBackground} !important; }\n .email-divider { border-color: ${emailTheme.colors.darkBorder} !important; }\n }\n `}</style>\n </Head>\n <Preview>{preheader}</Preview>\n <Body\n className=\"email-body\"\n style={{\n backgroundColor: emailTheme.colors.background,\n margin: 0,\n padding: 0,\n }}\n >\n <Section\n className=\"email-shell\"\n style={{\n backgroundColor: emailTheme.colors.background,\n color: emailTheme.colors.text,\n fontFamily: emailTheme.font,\n padding: '32px 12px',\n width: '100%',\n }}\n >\n <Container\n className=\"email-card\"\n style={{\n backgroundColor: emailTheme.colors.surface,\n border: `1px solid ${emailTheme.colors.border}`,\n borderRadius: emailTheme.radius,\n borderTop: `4px solid ${emailTheme.colors.brand}`,\n margin: '0 auto',\n maxWidth: emailTheme.width,\n overflow: 'hidden',\n width: '100%',\n }}\n >\n <Section className=\"email-content\" style={{ padding: '40px' }}>\n <Brand logoUrl={logoUrl} />\n <Heading\n as=\"h1\"\n className=\"email-text\"\n style={{\n color: emailTheme.colors.text,\n fontSize: '28px',\n fontWeight: 700,\n letterSpacing: '-0.02em',\n lineHeight: '36px',\n margin: '0 0 16px',\n }}\n >\n {heading}\n </Heading>\n {body.map((paragraph, index) => (\n <Text\n className=\"email-text\"\n key={`${index}-${paragraph}`}\n style={{\n color: emailTheme.colors.text,\n fontSize: '16px',\n lineHeight: '25px',\n margin: '0 0 16px',\n }}\n >\n {paragraph}\n </Text>\n ))}\n {detail ? <Detail detail={detail} /> : null}\n {action ? (\n <Button\n className=\"email-action\"\n href={action.href}\n style={{\n backgroundColor: emailTheme.colors.text,\n borderRadius: emailTheme.radius,\n color: emailTheme.colors.surface,\n fontSize: '16px',\n fontWeight: 700,\n lineHeight: '20px',\n marginTop: '8px',\n padding: '14px 24px',\n textDecoration: 'none',\n }}\n >\n {action.label}\n </Button>\n ) : null}\n <EmailFooter overrides={footer} />\n </Section>\n </Container>\n </Section>\n </Body>\n </Html>\n );\n}\n\nexport function renderTransactionalEmail(\n props: TransactionalEmailProps,\n): RenderedTransactionalEmail {\n const markup = renderToStaticMarkup(<TransactionalEmail {...props} />);\n const html = `<!doctype html>${markup.replace(\n /<link\\b(?=[^>]*\\brel=\"preload\")(?=[^>]*\\bas=\"image\")[^>]*\\/?>/gi,\n '',\n )}`;\n\n return {\n html,\n text: toPlainText(html, {\n selectors: [\n { selector: 'h1', options: { uppercase: false } },\n {\n selector: 'tr[data-key-value-row=\"true\"]',\n format: 'block',\n options: { leadingLineBreaks: 1, trailingLineBreaks: 1 },\n },\n ],\n }),\n };\n}\n","/**\n * Email clients cannot resolve the package's CSS custom properties. Keep this\n * literal palette aligned with styles/tokens.css and cover changes in the\n * rendered-output snapshot.\n */\nexport const emailTheme = {\n colors: {\n background: '#f7f7f8',\n surface: '#ffffff',\n muted: '#f0f0f2',\n border: '#e5e5e8',\n text: '#0a0a0b',\n textSecondary: '#52525b',\n brand: '#1785e0',\n brandLight: '#4ba6ec',\n accessibleLink: '#0969b3',\n darkBackground: '#0a0a0b',\n darkSurface: '#141416',\n darkMuted: '#1c1c1f',\n darkBorder: '#27272a',\n darkText: '#fafafa',\n darkTextSecondary: '#a1a1aa',\n },\n radius: '8px',\n font: 'Inter, -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif',\n fontMono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n width: '600px',\n} as const;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,46 @@
1
+ import * as react from 'react';
2
+
3
+ declare const FLOPAY_EMAIL_LOGO_URL = "https://flopay.com/logo.png";
4
+ interface TransactionalEmailAction {
5
+ label: string;
6
+ href: string;
7
+ }
8
+ interface TransactionalCodeDetail {
9
+ kind: 'code';
10
+ value: string;
11
+ caption?: string;
12
+ }
13
+ interface TransactionalKeyValueDetail {
14
+ kind: 'keyValue';
15
+ rows: {
16
+ label: string;
17
+ value: string;
18
+ }[];
19
+ }
20
+ type TransactionalEmailDetail = TransactionalCodeDetail | TransactionalKeyValueDetail;
21
+ interface TransactionalFooter {
22
+ companyName: string;
23
+ supportLabel: string;
24
+ supportUrl: string;
25
+ privacyUrl: string;
26
+ termsUrl: string;
27
+ notice: string;
28
+ address: string;
29
+ }
30
+ interface TransactionalEmailProps {
31
+ preheader: string;
32
+ heading: string;
33
+ body: string[];
34
+ action?: TransactionalEmailAction;
35
+ detail?: TransactionalEmailDetail;
36
+ logoUrl?: string;
37
+ footer?: Partial<TransactionalFooter>;
38
+ }
39
+ interface RenderedTransactionalEmail {
40
+ html: string;
41
+ text: string;
42
+ }
43
+ declare function TransactionalEmail({ preheader, heading, body, action, detail, logoUrl, footer, }: TransactionalEmailProps): react.JSX.Element;
44
+ declare function renderTransactionalEmail(props: TransactionalEmailProps): RenderedTransactionalEmail;
45
+
46
+ export { FLOPAY_EMAIL_LOGO_URL, type RenderedTransactionalEmail, type TransactionalCodeDetail, TransactionalEmail, type TransactionalEmailAction, type TransactionalEmailDetail, type TransactionalEmailProps, type TransactionalFooter, type TransactionalKeyValueDetail, renderTransactionalEmail };
@@ -0,0 +1,46 @@
1
+ import * as react from 'react';
2
+
3
+ declare const FLOPAY_EMAIL_LOGO_URL = "https://flopay.com/logo.png";
4
+ interface TransactionalEmailAction {
5
+ label: string;
6
+ href: string;
7
+ }
8
+ interface TransactionalCodeDetail {
9
+ kind: 'code';
10
+ value: string;
11
+ caption?: string;
12
+ }
13
+ interface TransactionalKeyValueDetail {
14
+ kind: 'keyValue';
15
+ rows: {
16
+ label: string;
17
+ value: string;
18
+ }[];
19
+ }
20
+ type TransactionalEmailDetail = TransactionalCodeDetail | TransactionalKeyValueDetail;
21
+ interface TransactionalFooter {
22
+ companyName: string;
23
+ supportLabel: string;
24
+ supportUrl: string;
25
+ privacyUrl: string;
26
+ termsUrl: string;
27
+ notice: string;
28
+ address: string;
29
+ }
30
+ interface TransactionalEmailProps {
31
+ preheader: string;
32
+ heading: string;
33
+ body: string[];
34
+ action?: TransactionalEmailAction;
35
+ detail?: TransactionalEmailDetail;
36
+ logoUrl?: string;
37
+ footer?: Partial<TransactionalFooter>;
38
+ }
39
+ interface RenderedTransactionalEmail {
40
+ html: string;
41
+ text: string;
42
+ }
43
+ declare function TransactionalEmail({ preheader, heading, body, action, detail, logoUrl, footer, }: TransactionalEmailProps): react.JSX.Element;
44
+ declare function renderTransactionalEmail(props: TransactionalEmailProps): RenderedTransactionalEmail;
45
+
46
+ export { FLOPAY_EMAIL_LOGO_URL, type RenderedTransactionalEmail, type TransactionalCodeDetail, TransactionalEmail, type TransactionalEmailAction, type TransactionalEmailDetail, type TransactionalEmailProps, type TransactionalFooter, type TransactionalKeyValueDetail, renderTransactionalEmail };