@flopay/ui 0.6.1 → 0.7.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 +68 -0
- package/dist/email/index.cjs +425 -0
- package/dist/email/index.cjs.map +1 -0
- package/dist/email/index.d.cts +46 -0
- package/dist/email/index.d.ts +46 -0
- package/dist/email/index.mjs +411 -0
- package/dist/email/index.mjs.map +1 -0
- package/dist/marketing/index.cjs +3 -2
- package/dist/marketing/index.cjs.map +1 -1
- package/dist/marketing/index.mjs +3 -2
- package/dist/marketing/index.mjs.map +1 -1
- package/package.json +17 -8
- package/styles/tokens.css +6 -2
package/README.md
CHANGED
|
@@ -162,6 +162,74 @@ Colour and face come from `--annotation-ink` (brand blue) and
|
|
|
162
162
|
floating/list switch is a `@media (min-width: 1120px)` rule sized for a ~720px
|
|
163
163
|
content box — apps in a constrained layout should re-declare that one block.
|
|
164
164
|
|
|
165
|
+
### 6. Transactional email
|
|
166
|
+
|
|
167
|
+
`@flopay/ui/email` renders a provider-neutral HTML string and matching plain
|
|
168
|
+
text. It does not send messages or configure a delivery provider.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { renderTransactionalEmail } from "@flopay/ui/email";
|
|
172
|
+
|
|
173
|
+
const { html, text } = renderTransactionalEmail({
|
|
174
|
+
preheader: "Your FloPay payment receipt is ready",
|
|
175
|
+
heading: "Payment received",
|
|
176
|
+
body: [
|
|
177
|
+
"Thanks, Alex. Your payment was processed successfully.",
|
|
178
|
+
"Keep this receipt for your records.",
|
|
179
|
+
],
|
|
180
|
+
action: {
|
|
181
|
+
label: "View receipt",
|
|
182
|
+
href: "https://flopay.com/receipts/FP-2048",
|
|
183
|
+
},
|
|
184
|
+
detail: {
|
|
185
|
+
kind: "keyValue",
|
|
186
|
+
rows: [
|
|
187
|
+
{ label: "Reference", value: "FP-2048" },
|
|
188
|
+
{ label: "Amount", value: "$48.00 USD" },
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
footer: {
|
|
192
|
+
address: "FloPay LLC, 100 Payments Way, New York, NY",
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The fixed slots are the content contract: one concise preheader, one heading,
|
|
198
|
+
plain-text body paragraphs, an optional action, and either a code or key-value
|
|
199
|
+
detail. Consumers supply content rather than React children or arbitrary HTML,
|
|
200
|
+
so new account and payment messages reuse the same reading order and layout.
|
|
201
|
+
All links are real anchors, and the action URL and labelled details remain
|
|
202
|
+
usable in the generated plain text.
|
|
203
|
+
|
|
204
|
+
Email clients cannot use the live CSS token preset. The template therefore
|
|
205
|
+
mirrors the approved values as inline literals: brand `#1785e0`, text
|
|
206
|
+
`#0a0a0b`, border `#e5e5e8`, an `8px` radius, and an Inter-first system font
|
|
207
|
+
stack with Roboto/Arial fallbacks. The layout is a 600px table-based card with
|
|
208
|
+
40px desktop padding and 24px narrow-screen padding. Update
|
|
209
|
+
`src/email/theme.ts` whenever the corresponding values in `styles/tokens.css`
|
|
210
|
+
change.
|
|
211
|
+
|
|
212
|
+
The default `FLOPAY_EMAIL_LOGO_URL` is the hosted approved asset at
|
|
213
|
+
`https://flopay.com/logo.png`. The logo is decorative (`alt=""`) because the
|
|
214
|
+
adjacent text brand name provides the accessible name and remains visible for
|
|
215
|
+
images-off clients. A service may pass an absolute HTTPS `logoUrl` when it
|
|
216
|
+
needs to host the same asset itself; packaged files, `data:` URLs, and
|
|
217
|
+
provider-specific CID references are not portable email sources.
|
|
218
|
+
|
|
219
|
+
The shared transactional footer defaults to `FloPay LLC`,
|
|
220
|
+
`hello@flopay.com`, Privacy, Terms, and a service-message notice. It does not
|
|
221
|
+
include a marketing unsubscribe. `footer` can override the company, support
|
|
222
|
+
label/URL, legal URLs, notice, and optional mailing address when legal or
|
|
223
|
+
support requirements differ.
|
|
224
|
+
|
|
225
|
+
The initial compatibility baseline is Apple Mail on macOS/iOS; Gmail web,
|
|
226
|
+
iOS, and Android; Outlook Windows desktop/MSO, Outlook.com, and Microsoft 365
|
|
227
|
+
web; and Yahoo. The markup uses layout tables and inline styles, with responsive
|
|
228
|
+
and dark-mode CSS as progressive enhancements. Before a release changes the
|
|
229
|
+
layout, verify Outlook Windows, dark mode, and images-off behavior in real
|
|
230
|
+
clients or an email rendering service in addition to the automated render
|
|
231
|
+
snapshot.
|
|
232
|
+
|
|
165
233
|
## Design tokens
|
|
166
234
|
|
|
167
235
|
`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 };
|