@cymbal/atoms-email-renderer 0.0.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/dist/index.cjs ADDED
@@ -0,0 +1,966 @@
1
+ 'use strict';
2
+
3
+ var components = require('@react-email/components');
4
+ var React = require('react');
5
+ var legos = require('@cymbal/legos');
6
+ require('@primer/octicons-react');
7
+ require('date-fns');
8
+ require('date-fns-tz');
9
+ require('slate');
10
+ require('date-fns/addMinutes');
11
+ require('date-fns/differenceInMinutes');
12
+ require('date-fns/format');
13
+ require('date-fns/addHours');
14
+ require('date-fns/differenceInHours');
15
+ require('date-fns/getHours');
16
+ require('date-fns/getMinutes');
17
+ require('date-fns/isValid');
18
+ require('date-fns/parse');
19
+ require('slate-react');
20
+ require('uuid');
21
+ require('@dnd-kit/core');
22
+
23
+ const envVariables = {
24
+ etixOAuth2Params: {
25
+ clientId: process.env.ETIX_OAUTH2_CLIENT_ID ?? "",
26
+ clientSecret: process.env.ETIX_OAUTH2_CLIENT_SECRET ?? "",
27
+ redirectUri: "https://manager.cymbal.co/oauth2/etix/callback"
28
+ },
29
+ eventbriteOAuth2Params: {
30
+ apiKey: process.env.EVENTBRITE_OAUTH2_API_KEY ?? "",
31
+ clientSecret: process.env.EVENTBRITE_OAUTH2_CLIENT_SECRET ?? ""
32
+ },
33
+ shopifyOAuth2Params: {
34
+ clientId: process.env.SHOPIFY_OAUTH2_CLIENT_ID ?? "",
35
+ clientSecret: process.env.SHOPIFY_OAUTH2_CLIENT_SECRET ?? ""
36
+ },
37
+ universeOAuth2Params: {
38
+ clientId: "26360beb48fefbbb4c45e0e4053123272a03fd4cf3eae54f5dd4620520c819d3",
39
+ clientSecret: "4e46048f9a7c74271b9907f25663dd5d9131159b70dea225a6808f8d2200beab",
40
+ redirectUri: "https://manager.cymbal.co/oauth2/universe/callback"
41
+ },
42
+ turnstileSecretKey: process.env.TURNSTILE_SECRET_KEY ?? ""
43
+ };
44
+ const envConfigRecord = {
45
+ development: {
46
+ ...envVariables,
47
+ eventbriteOAuth2Params: {
48
+ ...envVariables.eventbriteOAuth2Params,
49
+ redirectUri: "http://localhost:3031/oauth2/eventbrite/callback"
50
+ },
51
+ shopifyOAuth2Params: {
52
+ ...envVariables.shopifyOAuth2Params,
53
+ redirectUri: "http://localhost:3031/oauth2/shopify/callback"
54
+ },
55
+ universeOAuth2Params: {
56
+ ...envVariables.universeOAuth2Params,
57
+ redirectUri: "https://localhost:3031/oauth2/universe/callback"
58
+ },
59
+ showclixLoginUrl: "https://admin-demo.showclix.com/api/registration",
60
+ showclixEventBaseUrl: "https://www-demo.showclix.com/event"
61
+ },
62
+ staging: {
63
+ ...envVariables,
64
+ eventbriteOAuth2Params: {
65
+ ...envVariables.eventbriteOAuth2Params,
66
+ redirectUri: "https://staging-manager.cymbal.co/oauth2/eventbrite/callback"
67
+ },
68
+ shopifyOAuth2Params: {
69
+ ...envVariables.shopifyOAuth2Params,
70
+ redirectUri: "https://staging-manager.cymbal.co/oauth2/shopify/callback"
71
+ },
72
+ universeOAuth2Params: {
73
+ ...envVariables.universeOAuth2Params,
74
+ redirectUri: "https://staging-manager.cymbal.co/oauth2/universe/callback"
75
+ },
76
+ showclixLoginUrl: "https://admin-demo.showclix.com/api/registration",
77
+ showclixEventBaseUrl: "https://www-demo.showclix.com/event"
78
+ },
79
+ production: {
80
+ ...envVariables,
81
+ eventbriteOAuth2Params: {
82
+ ...envVariables.eventbriteOAuth2Params,
83
+ redirectUri: "https://manager.cymbal.co/oauth2/eventbrite/callback"
84
+ },
85
+ shopifyOAuth2Params: {
86
+ ...envVariables.shopifyOAuth2Params,
87
+ redirectUri: "https://manager.cymbal.co/oauth2/shopify/callback"
88
+ },
89
+ universeOAuth2Params: {
90
+ ...envVariables.universeOAuth2Params,
91
+ redirectUri: "https://manager.cymbal.co/oauth2/universe/callback"
92
+ },
93
+ showclixLoginUrl: "https://admin.showclix.com/api/registration",
94
+ showclixEventBaseUrl: "https://www.showclix.com/event"
95
+ }
96
+ };
97
+ const configRecord = {
98
+ development: {
99
+ env: "development",
100
+ host: "http://localhost:3031",
101
+ apiHost: "http://localhost:8080",
102
+ cachedApiHost: "http://localhost:8080",
103
+ homepageHost: "http://localhost:3029",
104
+ webHost: "http://localhost:3030",
105
+ trackingHost: "http://localhost:8081",
106
+ stripeApiKey: "pk_test_51LKSx9DUFJHrciOV6vQAOVOCPJWBZOPIQZ7MqDykKdRFk5oRGOc1OCZOzo3kIPJKr6tVr3jOJefmKZmiSMRPJtwq007p0vVP57",
107
+ turnstileSiteKey: "1x00000000000000000000AA"
108
+ // AA to always succeed, AB to always fail
109
+ },
110
+ staging: {
111
+ env: "staging",
112
+ host: "https://staging-manager.cymbal.co",
113
+ apiHost: "https://staging-api.cymbal.co",
114
+ cachedApiHost: "https://staging-cache-api.cymbal.co",
115
+ homepageHost: "https://staging.cymbal.co",
116
+ webHost: "https://staging-app.cymbal.co",
117
+ trackingHost: "https://staging.cy.link",
118
+ stripeApiKey: "pk_test_51LKSx9DUFJHrciOV6vQAOVOCPJWBZOPIQZ7MqDykKdRFk5oRGOc1OCZOzo3kIPJKr6tVr3jOJefmKZmiSMRPJtwq007p0vVP57",
119
+ turnstileSiteKey: "0x4AAAAAADcxWmLeTC3FZ8Pt"
120
+ },
121
+ production: {
122
+ env: "production",
123
+ host: "https://manager.cymbal.co",
124
+ apiHost: "https://api.cymbal.co",
125
+ cachedApiHost: "https://cache-api.cymbal.co",
126
+ homepageHost: "https://cymbal.co",
127
+ webHost: "https://app.cymbal.co",
128
+ trackingHost: "https://cy.link",
129
+ stripeApiKey: "pk_live_51LKSx9DUFJHrciOVruTpEgzJ8HU2rnpfUoBvSFrwULMpRCzLoVaEeLI4crV4GhykMN2cgNAmmVhLbXK2rMiBIASp00HdegT6uO",
130
+ turnstileSiteKey: "0x4AAAAAADcxWmLeTC3FZ8Pt"
131
+ }
132
+ };
133
+ const getEnv = () => {
134
+ switch (process.env.NEXT_PUBLIC_ENV) {
135
+ case "production":
136
+ case "staging":
137
+ case "development":
138
+ return process.env.NEXT_PUBLIC_ENV;
139
+ default:
140
+ return "development";
141
+ }
142
+ };
143
+ configRecord[getEnv()] ?? configRecord["development"];
144
+ envConfigRecord[getEnv()] ?? envConfigRecord["development"];
145
+
146
+ const allMarksKeys = [
147
+ "color",
148
+ "fontWeight",
149
+ "fontStyle",
150
+ "textDecoration",
151
+ "textTransform",
152
+ "fontSize",
153
+ "fontFamily",
154
+ "lineHeight",
155
+ "letterSpacing"
156
+ ];
157
+ new Set(allMarksKeys);
158
+
159
+ const MIN_LAYOUT_BASIS = 1;
160
+ const DEFAULT_LAYOUT_BASIS = 100;
161
+
162
+ ({
163
+ linkColor: legos.defaultStyles.page_style.link_color,
164
+ pagesMaxWidth: legos.defaultStyles.page_style.pages_max_width,
165
+ underlineLinks: legos.defaultStyles.page_style.underline_links
166
+ });
167
+ const zeroPadding = { top: 0, right: 0, bottom: 0, left: 0 };
168
+ function normalizePadding(padding) {
169
+ if (padding === null || padding === void 0) {
170
+ return { ...zeroPadding };
171
+ }
172
+ return { ...zeroPadding, ...padding };
173
+ }
174
+ function resolveLayoutVisualStyleValue({
175
+ override,
176
+ global
177
+ }) {
178
+ if (override === void 0 || override === null) {
179
+ return global;
180
+ }
181
+ return override;
182
+ }
183
+ function mergeResolvedLayoutWidth(overrides, global) {
184
+ if (overrides === null) {
185
+ return { ...global.width };
186
+ }
187
+ const widthOverride = overrides.width;
188
+ if (widthOverride === void 0 || widthOverride === null) {
189
+ return { ...global.width };
190
+ }
191
+ if (widthOverride && typeof widthOverride === "object" && "type" in widthOverride && widthOverride.type === "max") {
192
+ const legacyMaxWidth = widthOverride;
193
+ return {
194
+ basis: global.width.basis,
195
+ max: legacyMaxWidth.max ?? 200
196
+ };
197
+ }
198
+ if (widthOverride && typeof widthOverride === "object" && "type" in widthOverride && widthOverride.type === "maxWidth") {
199
+ const legacyMaxWidth = widthOverride;
200
+ return {
201
+ basis: global.width.basis,
202
+ max: legacyMaxWidth.maxWidth ?? 200
203
+ };
204
+ }
205
+ if (widthOverride && typeof widthOverride === "object" && "type" in widthOverride && widthOverride.type === "basis") {
206
+ const legacyBasis = widthOverride;
207
+ return {
208
+ basis: legacyBasis.basis ?? DEFAULT_LAYOUT_BASIS,
209
+ max: "none"
210
+ };
211
+ }
212
+ const normalizedWidth = widthOverride;
213
+ return {
214
+ basis: normalizedWidth.basis ?? global.width.basis,
215
+ max: normalizedWidth.max !== void 0 ? normalizedWidth.max : global.width.max
216
+ };
217
+ }
218
+ function resolveTextStyles(overrides, global) {
219
+ if (overrides === null) {
220
+ return { ...global };
221
+ }
222
+ return {
223
+ color: overrides.color ?? global.color,
224
+ fontWeight: overrides.fontWeight ?? global.fontWeight,
225
+ fontStyle: overrides.fontStyle ?? global.fontStyle,
226
+ textTransform: overrides.textTransform ?? global.textTransform,
227
+ textDecoration: overrides.textDecoration ?? global.textDecoration,
228
+ fontSizePx: overrides.fontSizePx ?? global.fontSizePx,
229
+ fontFamily: overrides.fontFamily ?? global.fontFamily,
230
+ align: overrides.align ?? global.align,
231
+ lineHeight: overrides.lineHeight ?? global.lineHeight,
232
+ letterSpacingEm: overrides.letterSpacingEm ?? global.letterSpacingEm
233
+ };
234
+ }
235
+ function resolveDividerStyles(overrides, global) {
236
+ if (overrides === null) {
237
+ return { ...global };
238
+ }
239
+ return {
240
+ color: overrides.color ?? global.color,
241
+ width: overrides.width ?? global.width,
242
+ style: overrides.style ?? global.style,
243
+ side: overrides.side ?? global.side
244
+ };
245
+ }
246
+ function resolveColumnsStyles(overrides, global) {
247
+ if (overrides === null) {
248
+ return { ...global };
249
+ }
250
+ return {
251
+ gap: overrides.gap ?? global.gap,
252
+ verticalAlign: overrides.verticalAlign ?? global.verticalAlign,
253
+ horizontalAlign: overrides.horizontalAlign ?? global.horizontalAlign,
254
+ format: overrides.format ?? global.format
255
+ };
256
+ }
257
+ function effectiveBlockHorizontalAlign({
258
+ layoutHorizontalAlign,
259
+ parentRowBlockHorizontalAlign
260
+ }) {
261
+ if (layoutHorizontalAlign !== "inherit") {
262
+ return layoutHorizontalAlign;
263
+ }
264
+ if (parentRowBlockHorizontalAlign !== null) {
265
+ return parentRowBlockHorizontalAlign;
266
+ }
267
+ return "left";
268
+ }
269
+ function resolveRowsStyles(overrides, global) {
270
+ if (overrides === null) {
271
+ return { ...global };
272
+ }
273
+ return {
274
+ gap: overrides.gap ?? global.gap,
275
+ horizontalAlign: overrides.horizontalAlign ?? global.horizontalAlign
276
+ };
277
+ }
278
+ function resolvePadding(overrides, global) {
279
+ if (overrides === null) {
280
+ return { ...global };
281
+ }
282
+ return {
283
+ top: overrides.top ?? global.top,
284
+ right: overrides.right ?? global.right,
285
+ bottom: overrides.bottom ?? global.bottom,
286
+ left: overrides.left ?? global.left
287
+ };
288
+ }
289
+ function getRootTextStyles(textType, globalAtomStyles) {
290
+ switch (textType) {
291
+ case "title":
292
+ return globalAtomStyles.titleStyles;
293
+ case "subtitle":
294
+ return globalAtomStyles.subtitleStyles;
295
+ case "heading":
296
+ return globalAtomStyles.headingStyles;
297
+ case "subheading":
298
+ return globalAtomStyles.subheadingStyles;
299
+ case "section":
300
+ return globalAtomStyles.sectionStyles;
301
+ case "body":
302
+ return globalAtomStyles.bodyStyles;
303
+ case "accent":
304
+ return globalAtomStyles.accentStyles;
305
+ case "caption":
306
+ return globalAtomStyles.captionStyles;
307
+ case "promo":
308
+ return {
309
+ textStyles: globalAtomStyles.promoStyles.textStyles,
310
+ layoutStyles: {
311
+ ...globalAtomStyles.promoStyles.layoutStyles,
312
+ padding: globalAtomStyles.promoStyles.innerPadding
313
+ }
314
+ };
315
+ }
316
+ }
317
+ function getRootLayoutStyles(atom, globalAtomStyles) {
318
+ switch (atom.type) {
319
+ case "text":
320
+ return getRootTextStyles(atom.textType, globalAtomStyles).layoutStyles;
321
+ case "button":
322
+ return globalAtomStyles.buttonStyles.layoutStyles;
323
+ case "image":
324
+ return globalAtomStyles.imageStyles.layoutStyles;
325
+ case "divider":
326
+ return globalAtomStyles.dividerStyles.layoutStyles;
327
+ case "option":
328
+ return globalAtomStyles.optionStyles.layoutStyles;
329
+ case "input":
330
+ return globalAtomStyles.inputStyles.layoutStyles;
331
+ case "contest":
332
+ return globalAtomStyles.buttonStyles.layoutStyles;
333
+ case "question":
334
+ return globalAtomStyles.questionStyles.layoutStyles;
335
+ case "form":
336
+ return globalAtomStyles.formStyles.layoutStyles;
337
+ case "automation-upcoming-events":
338
+ case "automation-triggered-event":
339
+ return globalAtomStyles.rowsStyles.layoutStyles;
340
+ case "rows":
341
+ return globalAtomStyles.rowsStyles.layoutStyles;
342
+ case "columns":
343
+ return globalAtomStyles.columnsStyles.layoutStyles;
344
+ }
345
+ }
346
+ function resolveAtomLayoutStyles(atom, globalAtomStyles) {
347
+ const overrides = atom.layoutStyles;
348
+ const global = getRootLayoutStyles(atom, globalAtomStyles);
349
+ if (overrides === null) {
350
+ return { ...global };
351
+ }
352
+ const width = mergeResolvedLayoutWidth(overrides, global);
353
+ const background = resolveLayoutVisualStyleValue({
354
+ override: overrides.background,
355
+ global: global.background
356
+ });
357
+ const border = resolveLayoutVisualStyleValue({
358
+ override: overrides.border,
359
+ global: global.border
360
+ });
361
+ return {
362
+ margin: overrides.margin !== null ? overrides.margin : global.margin,
363
+ padding: normalizePadding(overrides.padding !== null ? overrides.padding : global.padding),
364
+ background,
365
+ border,
366
+ borderRadius: overrides.borderRadius ?? global.borderRadius,
367
+ width,
368
+ horizontalAlign: overrides.horizontalAlign ?? global.horizontalAlign
369
+ };
370
+ }
371
+ function horizontalBorderInsetPx(border) {
372
+ const borderWidth = border.width;
373
+ const side = border.side;
374
+ if (side === "all") {
375
+ return borderWidth * 2;
376
+ }
377
+ if (side === "left") {
378
+ return borderWidth;
379
+ }
380
+ if (side === "right") {
381
+ return borderWidth;
382
+ }
383
+ return 0;
384
+ }
385
+ function computeAtomContentWidth(boxWidth, layoutStyles) {
386
+ const borderW = layoutStyles.border !== "none" ? horizontalBorderInsetPx(layoutStyles.border) : 0;
387
+ const padLeft = layoutStyles.padding?.left ?? 0;
388
+ const padRight = layoutStyles.padding?.right ?? 0;
389
+ return Math.max(0, boxWidth - padLeft - padRight - borderW);
390
+ }
391
+ function calculateRowChildWidth({
392
+ contentWidth,
393
+ child,
394
+ globalAtomStyles
395
+ }) {
396
+ const resolved = resolveAtomLayoutStyles(child, globalAtomStyles);
397
+ const cap = resolved.width.max;
398
+ if (cap === "none") {
399
+ return contentWidth;
400
+ }
401
+ return Math.min(cap, contentWidth);
402
+ }
403
+ const COLUMN_WIDTH_SPLIT_EPS = 1e-6;
404
+ function calculateColumnChildWidths({
405
+ contentWidth,
406
+ children,
407
+ gap,
408
+ globalAtomStyles
409
+ }) {
410
+ const childCount = children.length;
411
+ if (childCount === 0) {
412
+ return [];
413
+ }
414
+ const totalGap = gap * (childCount - 1);
415
+ const distributable = Math.max(0, contentWidth - totalGap);
416
+ const resolvedLayouts = children.map((child) => resolveAtomLayoutStyles(child, globalAtomStyles));
417
+ const bases = resolvedLayouts.map((layoutStyles) => layoutStyles.width.basis);
418
+ const caps = resolvedLayouts.map(
419
+ (layoutStyles) => layoutStyles.width.max === "none" ? Number.POSITIVE_INFINITY : layoutStyles.width.max
420
+ );
421
+ const widths = Array(childCount).fill(0);
422
+ const active = new Set(Array.from({ length: childCount }, (_, index) => index));
423
+ let remaining = distributable;
424
+ let guard = 0;
425
+ while (active.size > 0 && guard < childCount + 24) {
426
+ guard += 1;
427
+ const activeList = [...active].sort((indexA, indexB) => indexA - indexB);
428
+ const sumBasis = activeList.reduce((sum, index) => sum + bases[index], 0);
429
+ const denominator = sumBasis > 0 ? sumBasis : MIN_LAYOUT_BASIS;
430
+ const tentative = Array(childCount).fill(0);
431
+ for (const index of activeList) {
432
+ tentative[index] = bases[index] / denominator * remaining;
433
+ }
434
+ const clampedIndices = [];
435
+ for (const index of activeList) {
436
+ if (caps[index] < Number.POSITIVE_INFINITY && tentative[index] > caps[index] + COLUMN_WIDTH_SPLIT_EPS) {
437
+ clampedIndices.push(index);
438
+ }
439
+ }
440
+ if (clampedIndices.length === 0) {
441
+ for (const index of activeList) {
442
+ widths[index] = tentative[index];
443
+ }
444
+ break;
445
+ }
446
+ clampedIndices.sort((indexA, indexB) => indexA - indexB);
447
+ for (const index of clampedIndices) {
448
+ const assigned = caps[index];
449
+ widths[index] = assigned;
450
+ remaining -= assigned;
451
+ active.delete(index);
452
+ }
453
+ if (remaining <= COLUMN_WIDTH_SPLIT_EPS) {
454
+ for (const index of activeList) {
455
+ if (active.has(index)) {
456
+ widths[index] = 0;
457
+ active.delete(index);
458
+ }
459
+ }
460
+ break;
461
+ }
462
+ }
463
+ return widths;
464
+ }
465
+
466
+ const ATOM_SOCIAL_ORDINAL_TO_PLATFORM = {
467
+ facebookOrdinal: "facebook",
468
+ xOrdinal: "x",
469
+ instagramOrdinal: "instagram",
470
+ tiktokOrdinal: "tiktok",
471
+ youtubeOrdinal: "youtube",
472
+ websiteOrdinal: "website",
473
+ spotifyOrdinal: "spotify",
474
+ discordOrdinal: "discord",
475
+ soundcloudOrdinal: "soundcloud",
476
+ appleMusicOrdinal: "apple_music",
477
+ threadsOrdinal: "threads"
478
+ };
479
+ Object.entries(ATOM_SOCIAL_ORDINAL_TO_PLATFORM).reduce(
480
+ (accumulator, [ordinalKey, platform]) => {
481
+ accumulator[platform] = ordinalKey;
482
+ return accumulator;
483
+ },
484
+ {}
485
+ );
486
+ function ensureUrlHasProtocolForPreview(url) {
487
+ const trimmed = url.trim();
488
+ if (trimmed === "") {
489
+ return "";
490
+ }
491
+ if (/^https?:\/\//i.test(trimmed)) {
492
+ return trimmed;
493
+ }
494
+ if (trimmed.startsWith("mailto:")) {
495
+ return trimmed;
496
+ }
497
+ return `https://${trimmed}`;
498
+ }
499
+
500
+ const atomBorderToReactStyle = (border) => {
501
+ const side = border.side;
502
+ const spec = `${border.width}px ${border.style} ${border.color}`;
503
+ const none = "none";
504
+ if (side === "all") {
505
+ return { border: spec };
506
+ }
507
+ if (side === "top") {
508
+ return { borderTop: spec, borderRight: none, borderBottom: none, borderLeft: none };
509
+ }
510
+ if (side === "right") {
511
+ return { borderTop: none, borderRight: spec, borderBottom: none, borderLeft: none };
512
+ }
513
+ if (side === "bottom") {
514
+ return { borderTop: none, borderRight: none, borderBottom: spec, borderLeft: none };
515
+ }
516
+ return { borderTop: none, borderRight: none, borderBottom: none, borderLeft: spec };
517
+ };
518
+
519
+ const SYSTEM_SAFE_FONTS = /* @__PURE__ */ new Set([
520
+ "Arial",
521
+ "Arial Black",
522
+ "Arial Narrow",
523
+ "Calibri",
524
+ "Consolas",
525
+ "Courier",
526
+ "Courier New",
527
+ "Franklin Gothic",
528
+ "Garamond",
529
+ "Georgia",
530
+ "Helvetica",
531
+ "Lucida Console",
532
+ "Lucida Grande",
533
+ "Tahoma",
534
+ "Times New Roman",
535
+ "Trebuchet MS",
536
+ "Verdana"
537
+ ]);
538
+ function collectFontFamilies(doc) {
539
+ const families = /* @__PURE__ */ new Set();
540
+ const rootStyles = doc.globalAtomStyles;
541
+ const addFromTextStyles = (ts) => {
542
+ if (!ts) {
543
+ return;
544
+ }
545
+ if (ts.fontFamily) {
546
+ families.add(ts.fontFamily);
547
+ }
548
+ };
549
+ addFromTextStyles(rootStyles.titleStyles.textStyles);
550
+ addFromTextStyles(rootStyles.subtitleStyles.textStyles);
551
+ addFromTextStyles(rootStyles.headingStyles.textStyles);
552
+ addFromTextStyles(rootStyles.subheadingStyles.textStyles);
553
+ addFromTextStyles(rootStyles.sectionStyles.textStyles);
554
+ addFromTextStyles(rootStyles.bodyStyles.textStyles);
555
+ addFromTextStyles(rootStyles.accentStyles.textStyles);
556
+ addFromTextStyles(rootStyles.captionStyles.textStyles);
557
+ addFromTextStyles(rootStyles.promoStyles.textStyles);
558
+ addFromTextStyles(rootStyles.inputStyles.textStyles);
559
+ addFromTextStyles(rootStyles.optionStyles.textStyles);
560
+ const walkAtom = (atom) => {
561
+ if (atom.type === "text" || atom.type === "button" || atom.type === "input" || atom.type === "contest" || atom.type === "option") {
562
+ addFromTextStyles(atom.textStyles);
563
+ }
564
+ if ("children" in atom && atom.children) {
565
+ atom.children.forEach(walkAtom);
566
+ }
567
+ };
568
+ walkAtom(doc.rootRow);
569
+ return [...families].filter((f) => !SYSTEM_SAFE_FONTS.has(f));
570
+ }
571
+ function backgroundColorFromAtomBg(bg) {
572
+ if (bg === "none") {
573
+ return void 0;
574
+ }
575
+ if (bg.color) {
576
+ return bg.color;
577
+ }
578
+ return void 0;
579
+ }
580
+ function cornerRadiusToCssValue(radius) {
581
+ return `${radius.topLeft}px ${radius.topRight}px ${radius.bottomRight}px ${radius.bottomLeft}px`;
582
+ }
583
+ function layoutHorizontalBlockStyle(horizontalAlign) {
584
+ return {
585
+ display: "flex",
586
+ flexDirection: "row",
587
+ justifyContent: horizontalAlign === "left" ? "flex-start" : horizontalAlign === "center" ? "center" : "flex-end",
588
+ width: "100%"
589
+ };
590
+ }
591
+ function layoutToWrapperStyle(ls, parentRowBlockHorizontalAlign, forceBlockHorizontalAlign) {
592
+ const paddingTop = (ls.padding?.top ?? 0) + (ls.margin?.top ?? 0);
593
+ const paddingBottom = (ls.padding?.bottom ?? 0) + (ls.margin?.bottom ?? 0);
594
+ const paddingLeft = ls.padding?.left ?? 0;
595
+ const paddingRight = ls.padding?.right ?? 0;
596
+ const hasPadding = paddingTop > 0 || paddingRight > 0 || paddingBottom > 0 || paddingLeft > 0;
597
+ const blockAlign = forceBlockHorizontalAlign !== void 0 ? forceBlockHorizontalAlign : effectiveBlockHorizontalAlign({
598
+ layoutHorizontalAlign: ls.horizontalAlign,
599
+ parentRowBlockHorizontalAlign
600
+ });
601
+ return {
602
+ ...hasPadding ? { padding: `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px` } : {},
603
+ ...backgroundColorFromAtomBg(ls.background) ? { backgroundColor: backgroundColorFromAtomBg(ls.background) } : {},
604
+ ...ls.border !== "none" ? atomBorderToReactStyle(ls.border) : {},
605
+ ...ls.borderRadius ? { borderRadius: cornerRadiusToCssValue(ls.borderRadius) } : {},
606
+ ...layoutHorizontalBlockStyle(blockAlign)
607
+ };
608
+ }
609
+ function textStyleToCss(styles) {
610
+ return {
611
+ color: styles.color,
612
+ fontWeight: Number(styles.fontWeight),
613
+ fontStyle: styles.fontStyle,
614
+ textTransform: styles.textTransform,
615
+ textDecoration: styles.textDecoration,
616
+ fontSize: styles.fontSizePx,
617
+ fontFamily: styles.fontFamily,
618
+ textAlign: styles.align,
619
+ lineHeight: styles.lineHeight,
620
+ letterSpacing: `${styles.letterSpacingEm}em`,
621
+ margin: 0
622
+ };
623
+ }
624
+ function headingLevel(textType) {
625
+ switch (textType) {
626
+ case "title":
627
+ return "h1";
628
+ case "subtitle":
629
+ return "h2";
630
+ case "heading":
631
+ return "h3";
632
+ default:
633
+ return "h1";
634
+ }
635
+ }
636
+ const EmailTextAtom = ({ atom, ctx }) => {
637
+ const rootTextStyles = getRootTextStyles(atom.textType ?? "body", ctx.globalAtomStyles);
638
+ const resolvedText = resolveTextStyles(atom.textStyles, rootTextStyles.textStyles);
639
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
640
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
641
+ const cssStyles = textStyleToCss(resolvedText);
642
+ const inner = /* @__PURE__ */ React.createElement("span", { dangerouslySetInnerHTML: { __html: atom.text } });
643
+ if (atom.textType === "title" || atom.textType === "subtitle" || atom.textType === "heading") {
644
+ return /* @__PURE__ */ React.createElement(components.Heading, { as: headingLevel(atom.textType), style: { ...wrapperStyle, ...cssStyles, width: "100%" } }, inner);
645
+ }
646
+ return /* @__PURE__ */ React.createElement(components.Text, { style: { ...wrapperStyle, ...cssStyles, width: "100%" } }, inner);
647
+ };
648
+ const EmailButtonAtom = ({ atom, ctx }) => {
649
+ const resolvedText = resolveTextStyles(atom.textStyles, ctx.globalAtomStyles.buttonStyles.textStyles);
650
+ const resolvedInnerPadding = resolvePadding(atom.innerPadding, ctx.globalAtomStyles.buttonStyles.innerPadding);
651
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
652
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
653
+ const cssStyles = textStyleToCss(resolvedText);
654
+ const buttonStyle = {
655
+ ...cssStyles,
656
+ display: "block",
657
+ width: "100%",
658
+ boxSizing: "border-box",
659
+ textDecoration: "none",
660
+ padding: `${resolvedInnerPadding.top}px ${resolvedInnerPadding.right}px ${resolvedInnerPadding.bottom}px ${resolvedInnerPadding.left}px`,
661
+ maxWidth: "100%"
662
+ };
663
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React.createElement(components.Button, { href: atom.href || "#", style: buttonStyle }, /* @__PURE__ */ React.createElement("span", { dangerouslySetInnerHTML: { __html: atom.text } })));
664
+ };
665
+ const EmailImageAtom = ({ atom, ctx }) => {
666
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
667
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
668
+ const imgStyle = {
669
+ width: "100%",
670
+ display: "block",
671
+ ...resolvedLayout.borderRadius ? { borderRadius: cornerRadiusToCssValue(resolvedLayout.borderRadius) } : {}
672
+ };
673
+ const img = /* @__PURE__ */ React.createElement(components.Img, { src: atom.src, alt: "", style: imgStyle });
674
+ if (atom.href) {
675
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React.createElement(components.Link, { href: ensureUrlHasProtocolForPreview(atom.href), style: { display: "inline-block", width: "100%" } }, img));
676
+ }
677
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, img);
678
+ };
679
+ const EmailDividerAtom = ({ atom, ctx }) => {
680
+ const resolvedDivider = resolveDividerStyles(atom.dividerStyles, ctx.globalAtomStyles.dividerStyles.dividerStyles);
681
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
682
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
683
+ return /* @__PURE__ */ React.createElement(
684
+ components.Hr,
685
+ {
686
+ style: {
687
+ ...wrapperStyle,
688
+ ...atomBorderToReactStyle(resolvedDivider)
689
+ }
690
+ }
691
+ );
692
+ };
693
+ const fieldBoxStyle = {
694
+ border: "1px solid #555",
695
+ borderRadius: 8,
696
+ boxSizing: "border-box",
697
+ color: "#999",
698
+ fontSize: 14,
699
+ minHeight: 40,
700
+ padding: "10px 12px",
701
+ width: "100%"
702
+ };
703
+ const EmailInputAtom = ({ atom, ctx }) => {
704
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
705
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
706
+ const resolvedText = resolveTextStyles(atom.textStyles, ctx.globalAtomStyles.inputStyles.textStyles);
707
+ const resolvedInnerPadding = resolvePadding(atom.innerPadding, ctx.globalAtomStyles.inputStyles.innerPadding);
708
+ const fieldStyle = {
709
+ ...fieldBoxStyle,
710
+ ...textStyleToCss(resolvedText),
711
+ backgroundColor: backgroundColorFromAtomBg(resolvedLayout.background),
712
+ border: resolvedLayout.border !== "none" ? `${resolvedLayout.border.width}px ${resolvedLayout.border.style} ${resolvedLayout.border.color}` : fieldBoxStyle.border,
713
+ borderRadius: cornerRadiusToCssValue(resolvedLayout.borderRadius),
714
+ padding: `${resolvedInnerPadding.top}px ${resolvedInnerPadding.right}px ${resolvedInnerPadding.bottom}px ${resolvedInnerPadding.left}px`
715
+ };
716
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React.createElement("div", { style: fieldStyle }, atom.placeholder || "Text input"));
717
+ };
718
+ const EmailQuestionAtom = ({ atom, ctx }) => {
719
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
720
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
721
+ const resolvedInnerPadding = resolvePadding(atom.innerPadding, ctx.globalAtomStyles.questionStyles.innerPadding);
722
+ const dropdownStyle = {
723
+ ...fieldBoxStyle,
724
+ padding: `${resolvedInnerPadding.top}px ${resolvedInnerPadding.right}px ${resolvedInnerPadding.bottom}px ${resolvedInnerPadding.left}px`
725
+ };
726
+ const optionNodes = atom.children.map((option) => /* @__PURE__ */ React.createElement(
727
+ components.Text,
728
+ {
729
+ key: option.id,
730
+ style: {
731
+ ...textStyleToCss(resolveTextStyles(option.textStyles, ctx.globalAtomStyles.optionStyles.textStyles)),
732
+ margin: "0 0 6px 0"
733
+ }
734
+ },
735
+ "[ ] ",
736
+ option.text
737
+ ));
738
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, atom.questionType === "dropdown" ? /* @__PURE__ */ React.createElement("div", { style: dropdownStyle }, "Select an option") : optionNodes);
739
+ };
740
+ const EmailOptionAtom = ({ atom, ctx }) => {
741
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
742
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
743
+ const resolvedText = resolveTextStyles(atom.textStyles, ctx.globalAtomStyles.optionStyles.textStyles);
744
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React.createElement(components.Text, { style: { ...textStyleToCss(resolvedText), margin: 0 } }, atom.text));
745
+ };
746
+ const EmailContestAtom = ({ atom, ctx }) => {
747
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
748
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign);
749
+ const resolvedText = resolveTextStyles(atom.textStyles, ctx.globalAtomStyles.buttonStyles.textStyles);
750
+ const resolvedButtonLayout = resolvedLayout;
751
+ const resolvedInnerPadding = resolvePadding(atom.innerPadding, ctx.globalAtomStyles.buttonStyles.innerPadding);
752
+ const buttonBackground = resolvedButtonLayout.background !== "none" ? backgroundColorFromAtomBg(resolvedButtonLayout.background) : void 0;
753
+ const buttonStyle = {
754
+ ...textStyleToCss(resolvedText),
755
+ backgroundColor: buttonBackground,
756
+ borderRadius: cornerRadiusToCssValue(resolvedButtonLayout.borderRadius),
757
+ boxSizing: "border-box",
758
+ display: "block",
759
+ minHeight: Math.max(42, resolvedText.fontSizePx * 2.5),
760
+ padding: `${resolvedInnerPadding.top}px ${resolvedInnerPadding.right}px ${resolvedInnerPadding.bottom}px ${resolvedInnerPadding.left}px`,
761
+ textDecoration: "none",
762
+ width: "100%"
763
+ };
764
+ const label = atom.contestType === "facebook" ? "Share link on Facebook" : atom.contestType === "instagram" ? `Follow ${atom.identifier}` : "Share this contest";
765
+ return /* @__PURE__ */ React.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React.createElement(components.Button, { href: "#", style: buttonStyle }, label, " +", atom.entriesPerSubmission));
766
+ };
767
+ const EmailAutomationUpcomingEventsAtom = ({
768
+ atom,
769
+ ctx
770
+ }) => {
771
+ return null;
772
+ };
773
+ const EmailAutomationTriggeredEventAtom = ({
774
+ atom,
775
+ ctx
776
+ }) => {
777
+ return null;
778
+ };
779
+ const EmailFormAtom = ({ atom, ctx }) => {
780
+ const rowsAtom = {
781
+ atomKey: atom.atomKey,
782
+ type: "rows",
783
+ source: null,
784
+ children: atom.children,
785
+ rowsStyles: atom.rowsStyles,
786
+ layoutStyles: atom.layoutStyles
787
+ };
788
+ const belowSubmitRowsAtom = {
789
+ atomKey: atom.atomKey,
790
+ type: "rows",
791
+ source: null,
792
+ children: atom.belowSubmitChildren,
793
+ rowsStyles: null,
794
+ layoutStyles: null
795
+ };
796
+ return /* @__PURE__ */ React.createElement(components.Section, null, /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: rowsAtom, ctx }), atom.belowSubmitChildren.length > 0 && /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: belowSubmitRowsAtom, ctx }));
797
+ };
798
+ const EmailAtom = ({ atom, ctx }) => {
799
+ switch (atom.type) {
800
+ case "text":
801
+ return /* @__PURE__ */ React.createElement(EmailTextAtom, { atom, ctx });
802
+ case "button":
803
+ return /* @__PURE__ */ React.createElement(EmailButtonAtom, { atom, ctx });
804
+ case "image":
805
+ return /* @__PURE__ */ React.createElement(EmailImageAtom, { atom, ctx });
806
+ case "divider":
807
+ return /* @__PURE__ */ React.createElement(EmailDividerAtom, { atom, ctx });
808
+ case "option":
809
+ return /* @__PURE__ */ React.createElement(EmailOptionAtom, { atom, ctx });
810
+ case "rows":
811
+ return /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom, ctx });
812
+ case "columns":
813
+ return /* @__PURE__ */ React.createElement(EmailColumnsAtom, { atom, ctx });
814
+ case "input":
815
+ return /* @__PURE__ */ React.createElement(EmailInputAtom, { atom, ctx });
816
+ case "question":
817
+ return /* @__PURE__ */ React.createElement(EmailQuestionAtom, { atom, ctx });
818
+ case "contest":
819
+ return /* @__PURE__ */ React.createElement(EmailContestAtom, { atom, ctx });
820
+ case "form":
821
+ return /* @__PURE__ */ React.createElement(EmailFormAtom, { atom, ctx });
822
+ case "automation-upcoming-events":
823
+ return /* @__PURE__ */ React.createElement(EmailAutomationUpcomingEventsAtom, { atom, ctx });
824
+ case "automation-triggered-event":
825
+ return /* @__PURE__ */ React.createElement(EmailAutomationTriggeredEventAtom, { atom, ctx });
826
+ }
827
+ };
828
+ const EmailRowsAtom = ({ atom, ctx }) => {
829
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
830
+ const resolvedRows = resolveRowsStyles(atom.rowsStyles, ctx.globalAtomStyles.rowsStyles.rowsStyles);
831
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign, "left");
832
+ const gap = resolvedRows.gap;
833
+ const innerWidth = computeAtomContentWidth(ctx.contentWidthPx, resolvedLayout);
834
+ const rowCrossAlign = resolvedRows.horizontalAlign === "left" ? "flex-start" : resolvedRows.horizontalAlign === "center" ? "center" : "flex-end";
835
+ const widthStyle = {
836
+ width: "100%",
837
+ ...resolvedLayout.width.max !== "none" ? { maxWidth: resolvedLayout.width.max } : {}
838
+ };
839
+ return /* @__PURE__ */ React.createElement(components.Section, { style: { ...wrapperStyle, ...widthStyle } }, /* @__PURE__ */ React.createElement(
840
+ "div",
841
+ {
842
+ style: {
843
+ width: "100%",
844
+ display: "flex",
845
+ flexDirection: "column",
846
+ alignItems: rowCrossAlign
847
+ }
848
+ },
849
+ atom.children.map((child, i) => {
850
+ const childResolved = resolveAtomLayoutStyles(child, ctx.globalAtomStyles);
851
+ const childMaxWidth = childResolved.width.max;
852
+ const slotOuterWidth = calculateRowChildWidth({
853
+ contentWidth: innerWidth,
854
+ child,
855
+ globalAtomStyles: ctx.globalAtomStyles
856
+ });
857
+ const childContentWidthPx = computeAtomContentWidth(slotOuterWidth, childResolved);
858
+ const childWidthStyle = {
859
+ width: "100%",
860
+ ...childMaxWidth !== "none" ? { maxWidth: childMaxWidth } : {}
861
+ };
862
+ const gapStyle = i > 0 && gap > 0 ? { paddingTop: gap } : {};
863
+ const childCtx = {
864
+ ...ctx,
865
+ contentWidthPx: childContentWidthPx,
866
+ parentRowBlockHorizontalAlign: resolvedRows.horizontalAlign
867
+ };
868
+ return /* @__PURE__ */ React.createElement("div", { key: child.atomKey, style: { ...gapStyle, ...childWidthStyle } }, /* @__PURE__ */ React.createElement(EmailAtom, { atom: child, ctx: childCtx }));
869
+ })
870
+ ));
871
+ };
872
+ const EmailColumnsAtom = ({ atom, ctx }) => {
873
+ const resolvedLayout = resolveAtomLayoutStyles(atom, ctx.globalAtomStyles);
874
+ const resolvedCols = resolveColumnsStyles(atom.columnsStyles, ctx.globalAtomStyles.columnsStyles.columnsStyles);
875
+ const wrapperStyle = layoutToWrapperStyle(resolvedLayout, ctx.parentRowBlockHorizontalAlign, "left");
876
+ const gap = resolvedCols.gap;
877
+ const gapPx = Math.max(0, Math.round(gap));
878
+ const innerWidth = computeAtomContentWidth(ctx.contentWidthPx, resolvedLayout);
879
+ const innerWidthPx = Math.max(0, Math.round(innerWidth));
880
+ const resolvedChildLayouts = atom.children.map(
881
+ (child) => resolveAtomLayoutStyles(child, ctx.globalAtomStyles)
882
+ );
883
+ const verticalAlignMap = {
884
+ top: "top",
885
+ middle: "middle",
886
+ bottom: "bottom"
887
+ };
888
+ const vAlign = verticalAlignMap[resolvedCols.verticalAlign] ?? "top";
889
+ const childCount = atom.children.length;
890
+ const totalGapPx = childCount > 1 ? gapPx * (childCount - 1) : 0;
891
+ const rawColumnWidths = childCount === 0 ? [] : calculateColumnChildWidths({
892
+ contentWidth: innerWidthPx,
893
+ children: atom.children,
894
+ gap: gapPx,
895
+ globalAtomStyles: ctx.globalAtomStyles
896
+ });
897
+ const columnWidthsPx = rawColumnWidths.map((w) => Math.round(w));
898
+ const columnsWidthSum = columnWidthsPx.reduce((a, b) => a + b, 0);
899
+ const totalTableWidth = columnsWidthSum + totalGapPx;
900
+ const horizontalAlign = resolvedCols.horizontalAlign;
901
+ const narrowColumnsMargins = horizontalAlign === "center" ? { marginLeft: "auto", marginRight: "auto" } : horizontalAlign === "right" ? { marginLeft: "auto", marginRight: "0" } : { marginLeft: "0", marginRight: "auto" };
902
+ const outerTableStyle = {
903
+ ...wrapperStyle,
904
+ width: totalTableWidth,
905
+ ...narrowColumnsMargins,
906
+ ...resolvedLayout.width.max !== "none" ? { maxWidth: resolvedLayout.width.max } : {}
907
+ };
908
+ const innerRowStyle = {
909
+ width: totalTableWidth,
910
+ tableLayout: "fixed"
911
+ };
912
+ const spacerStyle = {
913
+ width: gapPx,
914
+ padding: 0,
915
+ verticalAlign: vAlign,
916
+ lineHeight: 0,
917
+ fontSize: 0
918
+ };
919
+ const cells = [];
920
+ atom.children.forEach((child, i) => {
921
+ if (i > 0 && gapPx > 0) {
922
+ cells.push(
923
+ /* @__PURE__ */ React.createElement(components.Column, { key: `${atom.atomKey}-gap-${i}`, style: spacerStyle }, "\xA0")
924
+ );
925
+ }
926
+ const wPx = columnWidthsPx[i] ?? 0;
927
+ const childResolved = resolvedChildLayouts[i];
928
+ const childContentWidthPx = computeAtomContentWidth(wPx, childResolved);
929
+ const columnStyle = {
930
+ width: wPx,
931
+ verticalAlign: vAlign
932
+ };
933
+ const childCtx = {
934
+ ...ctx,
935
+ contentWidthPx: childContentWidthPx,
936
+ parentRowBlockHorizontalAlign: null
937
+ };
938
+ cells.push(
939
+ /* @__PURE__ */ React.createElement(components.Column, { key: child.atomKey, style: columnStyle }, /* @__PURE__ */ React.createElement(EmailAtom, { atom: child, ctx: childCtx }))
940
+ );
941
+ });
942
+ return /* @__PURE__ */ React.createElement(components.Section, { style: outerTableStyle }, /* @__PURE__ */ React.createElement(components.Row, { style: innerRowStyle }, cells));
943
+ };
944
+ const AtomDocumentContentsEmail = ({ document: doc }) => {
945
+ const webFonts = collectFontFamilies(doc);
946
+ const ctx = {
947
+ globalAtomStyles: doc.globalAtomStyles,
948
+ contentWidthPx: doc.maxWidth,
949
+ parentRowBlockHorizontalAlign: null
950
+ };
951
+ const resolvedRootLayoutStyles = resolveAtomLayoutStyles(doc.rootRow, doc.globalAtomStyles);
952
+ const bodyBackgroundColor = resolvedRootLayoutStyles.background === "none" ? void 0 : backgroundColorFromAtomBg(resolvedRootLayoutStyles.background);
953
+ return /* @__PURE__ */ React.createElement(components.Html, { lang: "en", dir: "ltr" }, /* @__PURE__ */ React.createElement(components.Head, null, webFonts.map((fontFamily) => /* @__PURE__ */ React.createElement(
954
+ "link",
955
+ {
956
+ key: fontFamily,
957
+ rel: "stylesheet",
958
+ href: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fontFamily)}:wght@100;200;300;400;500;600;700;800;900&display=swap`
959
+ }
960
+ ))), /* @__PURE__ */ React.createElement(components.Body, { style: { backgroundColor: bodyBackgroundColor, margin: 0, padding: 0 } }, /* @__PURE__ */ React.createElement(components.Container, { style: { maxWidth: doc.maxWidth, margin: "0 auto" } }, /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: doc.rootRow, ctx }))));
961
+ };
962
+ async function renderAtomDocumentToHtml(doc) {
963
+ return components.render(/* @__PURE__ */ React.createElement(AtomDocumentContentsEmail, { document: doc }));
964
+ }
965
+
966
+ exports.renderAtomDocumentToHtml = renderAtomDocumentToHtml;