@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 +966 -0
- package/dist/index.d.ts +527 -0
- package/dist/index.mjs +964 -0
- package/package.json +28 -0
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;
|