@cymbal/atoms-email-renderer 0.0.0 → 0.0.2

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 CHANGED
@@ -2,183 +2,26 @@
2
2
 
3
3
  var components = require('@react-email/components');
4
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
5
 
159
6
  const MIN_LAYOUT_BASIS = 1;
160
7
  const DEFAULT_LAYOUT_BASIS = 100;
161
8
 
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
9
  function resolveLayoutVisualStyleValue({
175
10
  override,
176
11
  global
177
12
  }) {
178
- if (override === void 0 || override === null) {
179
- return global;
13
+ return override === null || override === void 0 ? global : override;
14
+ }
15
+ function normalizePadding(padding) {
16
+ if (!padding) {
17
+ return { top: 0, right: 0, bottom: 0, left: 0 };
180
18
  }
181
- return override;
19
+ return {
20
+ top: padding.top ?? 0,
21
+ right: padding.right ?? 0,
22
+ bottom: padding.bottom ?? 0,
23
+ left: padding.left ?? 0
24
+ };
182
25
  }
183
26
  function mergeResolvedLayoutWidth(overrides, global) {
184
27
  if (overrides === null) {
@@ -383,10 +226,10 @@ function horizontalBorderInsetPx(border) {
383
226
  return 0;
384
227
  }
385
228
  function computeAtomContentWidth(boxWidth, layoutStyles) {
386
- const borderW = layoutStyles.border !== "none" ? horizontalBorderInsetPx(layoutStyles.border) : 0;
229
+ const borderWidth = layoutStyles.border !== "none" ? horizontalBorderInsetPx(layoutStyles.border) : 0;
387
230
  const padLeft = layoutStyles.padding?.left ?? 0;
388
231
  const padRight = layoutStyles.padding?.right ?? 0;
389
- return Math.max(0, boxWidth - padLeft - padRight - borderW);
232
+ return Math.max(0, boxWidth - padLeft - padRight - borderWidth);
390
233
  }
391
234
  function calculateRowChildWidth({
392
235
  contentWidth,
@@ -462,27 +305,6 @@ function calculateColumnChildWidths({
462
305
  }
463
306
  return widths;
464
307
  }
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
308
  function ensureUrlHasProtocolForPreview(url) {
487
309
  const trimmed = url.trim();
488
310
  if (trimmed === "") {
@@ -941,7 +763,76 @@ const EmailColumnsAtom = ({ atom, ctx }) => {
941
763
  });
942
764
  return /* @__PURE__ */ React.createElement(components.Section, { style: outerTableStyle }, /* @__PURE__ */ React.createElement(components.Row, { style: innerRowStyle }, cells));
943
765
  };
944
- const AtomDocumentContentsEmail = ({ document: doc }) => {
766
+ const hiddenPreheaderStyle = {
767
+ display: "none",
768
+ fontSize: "1px",
769
+ lineHeight: "1px",
770
+ maxHeight: 0,
771
+ maxWidth: 0,
772
+ opacity: 0,
773
+ overflow: "hidden"
774
+ };
775
+ const TopUnsubscribeBar = ({ unsubscribeLink }) => /* @__PURE__ */ React.createElement(
776
+ "table",
777
+ {
778
+ align: "center",
779
+ border: 0,
780
+ cellPadding: "0",
781
+ cellSpacing: "0",
782
+ role: "presentation",
783
+ style: { background: "#FFFFFF", backgroundColor: "#FFFFFF", width: "100%" }
784
+ },
785
+ /* @__PURE__ */ React.createElement("tbody", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", null, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
786
+ "table",
787
+ {
788
+ align: "center",
789
+ border: 0,
790
+ cellPadding: "0",
791
+ cellSpacing: "0",
792
+ role: "presentation",
793
+ style: { width: "100%" }
794
+ },
795
+ /* @__PURE__ */ React.createElement("tbody", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement(
796
+ "td",
797
+ {
798
+ className: "top-unsubscribe",
799
+ style: {
800
+ fontSize: 0,
801
+ paddingTop: "16px",
802
+ paddingBottom: "16px",
803
+ textAlign: "left"
804
+ }
805
+ },
806
+ /* @__PURE__ */ React.createElement(
807
+ "div",
808
+ {
809
+ style: {
810
+ fontFamily: "'Google Sans', Roboto, RobotoDraft, Helvetica, Arial, sans-serif",
811
+ fontSize: "14px",
812
+ fontWeight: "500",
813
+ lineHeight: "1",
814
+ textAlign: "left",
815
+ color: "#3771e0"
816
+ }
817
+ },
818
+ /* @__PURE__ */ React.createElement(
819
+ "a",
820
+ {
821
+ style: { color: "#3771e0", textDecoration: "none" },
822
+ href: unsubscribeLink,
823
+ target: "_blank",
824
+ rel: "noopener noreferrer"
825
+ },
826
+ "Unsubscribe"
827
+ )
828
+ )
829
+ )))
830
+ )))))
831
+ );
832
+ const AtomDocumentContentsEmail = ({
833
+ document: doc,
834
+ options
835
+ }) => {
945
836
  const webFonts = collectFontFamilies(doc);
946
837
  const ctx = {
947
838
  globalAtomStyles: doc.globalAtomStyles,
@@ -957,10 +848,19 @@ const AtomDocumentContentsEmail = ({ document: doc }) => {
957
848
  rel: "stylesheet",
958
849
  href: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fontFamily)}:wght@100;200;300;400;500;600;700;800;900&display=swap`
959
850
  }
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 }))));
851
+ ))), /* @__PURE__ */ React.createElement(components.Body, { style: { backgroundColor: bodyBackgroundColor, margin: 0, padding: 0 } }, options?.emailPreviewText ? /* @__PURE__ */ React.createElement("div", { style: hiddenPreheaderStyle }, options.emailPreviewText) : null, options?.topUnsubscribeLink ? /* @__PURE__ */ React.createElement(TopUnsubscribeBar, { unsubscribeLink: options.topUnsubscribeLink }) : null, options?.automationPreviewHeaderHtml ? /* @__PURE__ */ React.createElement("div", { dangerouslySetInnerHTML: { __html: options.automationPreviewHeaderHtml } }) : null, /* @__PURE__ */ React.createElement(components.Container, { style: { maxWidth: doc.maxWidth, margin: "0 auto" } }, /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: doc.rootRow, ctx }), options?.cymbalBrandingUrl ? /* @__PURE__ */ React.createElement(components.Section, null, /* @__PURE__ */ React.createElement(components.Text, { style: { color: "#999999", fontSize: 12, textAlign: "center" } }, "Powered by", " ", /* @__PURE__ */ React.createElement(components.Link, { href: options.cymbalBrandingUrl, style: { color: "#999999" } }, "Cymbal"))) : null), options?.trackingPixelUrl ? /* @__PURE__ */ React.createElement(
852
+ components.Img,
853
+ {
854
+ src: options.trackingPixelUrl,
855
+ width: "1",
856
+ height: "1",
857
+ style: { display: "none", height: 1, width: 1 },
858
+ alt: ""
859
+ }
860
+ ) : null));
961
861
  };
962
- async function renderAtomDocumentToHtml(doc) {
963
- return components.render(/* @__PURE__ */ React.createElement(AtomDocumentContentsEmail, { document: doc }));
862
+ async function renderAtomDocumentToHtml(doc, options) {
863
+ return components.render(/* @__PURE__ */ React.createElement(AtomDocumentContentsEmail, { document: doc, options }));
964
864
  }
965
865
 
966
866
  exports.renderAtomDocumentToHtml = renderAtomDocumentToHtml;
package/dist/index.d.ts CHANGED
@@ -521,7 +521,15 @@ interface AtomTextEventStyle {
521
521
  dynamicDataSetting: AtomDynamicDataSetting;
522
522
  }
523
523
 
524
- declare function renderAtomDocumentToHtml(doc: AtomDocumentContents): Promise<string>;
524
+ interface RenderAtomDocumentToHtmlOptions {
525
+ automationPreviewHeaderHtml?: string | null;
526
+ cymbalBrandingUrl?: string | null;
527
+ emailPreviewText?: string | null;
528
+ trackingPixelUrl?: string | null;
529
+ /** When set, renders the top "Unsubscribe" bar linking to this URL. */
530
+ topUnsubscribeLink?: string | null;
531
+ }
532
+ declare function renderAtomDocumentToHtml(doc: AtomDocumentContents, options?: RenderAtomDocumentToHtmlOptions): Promise<string>;
525
533
 
526
534
  export { renderAtomDocumentToHtml };
527
- export type { Atom, AtomDocument, AutomationTriggeredEventAtom, AutomationUpcomingEventsAtom, ContestAtom, FormAtom, InputAtom, OptionAtom, QuestionAtom };
535
+ export type { Atom, AtomDocument, AtomDocumentContents, AutomationTriggeredEventAtom, AutomationUpcomingEventsAtom, ContestAtom, FormAtom, InputAtom, OptionAtom, QuestionAtom, RenderAtomDocumentToHtmlOptions };
package/dist/index.mjs CHANGED
@@ -1,182 +1,25 @@
1
- import { render, Html, Head, Body, Container, Section, Button, Text, Column, Row, Hr, Img, Link, Heading } from '@react-email/components';
1
+ import { render, Html, Head, Body, Container, Section, Text, Link, Img, Column, Row, Heading, Button, Hr } from '@react-email/components';
2
2
  import React from 'react';
3
- import { defaultStyles } from '@cymbal/legos';
4
- import '@primer/octicons-react';
5
- import 'date-fns';
6
- import 'date-fns-tz';
7
- import 'slate';
8
- import 'date-fns/addMinutes';
9
- import 'date-fns/differenceInMinutes';
10
- import 'date-fns/format';
11
- import 'date-fns/addHours';
12
- import 'date-fns/differenceInHours';
13
- import 'date-fns/getHours';
14
- import 'date-fns/getMinutes';
15
- import 'date-fns/isValid';
16
- import 'date-fns/parse';
17
- import 'slate-react';
18
- import 'uuid';
19
- import '@dnd-kit/core';
20
-
21
- const envVariables = {
22
- etixOAuth2Params: {
23
- clientId: process.env.ETIX_OAUTH2_CLIENT_ID ?? "",
24
- clientSecret: process.env.ETIX_OAUTH2_CLIENT_SECRET ?? "",
25
- redirectUri: "https://manager.cymbal.co/oauth2/etix/callback"
26
- },
27
- eventbriteOAuth2Params: {
28
- apiKey: process.env.EVENTBRITE_OAUTH2_API_KEY ?? "",
29
- clientSecret: process.env.EVENTBRITE_OAUTH2_CLIENT_SECRET ?? ""
30
- },
31
- shopifyOAuth2Params: {
32
- clientId: process.env.SHOPIFY_OAUTH2_CLIENT_ID ?? "",
33
- clientSecret: process.env.SHOPIFY_OAUTH2_CLIENT_SECRET ?? ""
34
- },
35
- universeOAuth2Params: {
36
- clientId: "26360beb48fefbbb4c45e0e4053123272a03fd4cf3eae54f5dd4620520c819d3",
37
- clientSecret: "4e46048f9a7c74271b9907f25663dd5d9131159b70dea225a6808f8d2200beab",
38
- redirectUri: "https://manager.cymbal.co/oauth2/universe/callback"
39
- },
40
- turnstileSecretKey: process.env.TURNSTILE_SECRET_KEY ?? ""
41
- };
42
- const envConfigRecord = {
43
- development: {
44
- ...envVariables,
45
- eventbriteOAuth2Params: {
46
- ...envVariables.eventbriteOAuth2Params,
47
- redirectUri: "http://localhost:3031/oauth2/eventbrite/callback"
48
- },
49
- shopifyOAuth2Params: {
50
- ...envVariables.shopifyOAuth2Params,
51
- redirectUri: "http://localhost:3031/oauth2/shopify/callback"
52
- },
53
- universeOAuth2Params: {
54
- ...envVariables.universeOAuth2Params,
55
- redirectUri: "https://localhost:3031/oauth2/universe/callback"
56
- },
57
- showclixLoginUrl: "https://admin-demo.showclix.com/api/registration",
58
- showclixEventBaseUrl: "https://www-demo.showclix.com/event"
59
- },
60
- staging: {
61
- ...envVariables,
62
- eventbriteOAuth2Params: {
63
- ...envVariables.eventbriteOAuth2Params,
64
- redirectUri: "https://staging-manager.cymbal.co/oauth2/eventbrite/callback"
65
- },
66
- shopifyOAuth2Params: {
67
- ...envVariables.shopifyOAuth2Params,
68
- redirectUri: "https://staging-manager.cymbal.co/oauth2/shopify/callback"
69
- },
70
- universeOAuth2Params: {
71
- ...envVariables.universeOAuth2Params,
72
- redirectUri: "https://staging-manager.cymbal.co/oauth2/universe/callback"
73
- },
74
- showclixLoginUrl: "https://admin-demo.showclix.com/api/registration",
75
- showclixEventBaseUrl: "https://www-demo.showclix.com/event"
76
- },
77
- production: {
78
- ...envVariables,
79
- eventbriteOAuth2Params: {
80
- ...envVariables.eventbriteOAuth2Params,
81
- redirectUri: "https://manager.cymbal.co/oauth2/eventbrite/callback"
82
- },
83
- shopifyOAuth2Params: {
84
- ...envVariables.shopifyOAuth2Params,
85
- redirectUri: "https://manager.cymbal.co/oauth2/shopify/callback"
86
- },
87
- universeOAuth2Params: {
88
- ...envVariables.universeOAuth2Params,
89
- redirectUri: "https://manager.cymbal.co/oauth2/universe/callback"
90
- },
91
- showclixLoginUrl: "https://admin.showclix.com/api/registration",
92
- showclixEventBaseUrl: "https://www.showclix.com/event"
93
- }
94
- };
95
- const configRecord = {
96
- development: {
97
- env: "development",
98
- host: "http://localhost:3031",
99
- apiHost: "http://localhost:8080",
100
- cachedApiHost: "http://localhost:8080",
101
- homepageHost: "http://localhost:3029",
102
- webHost: "http://localhost:3030",
103
- trackingHost: "http://localhost:8081",
104
- stripeApiKey: "pk_test_51LKSx9DUFJHrciOV6vQAOVOCPJWBZOPIQZ7MqDykKdRFk5oRGOc1OCZOzo3kIPJKr6tVr3jOJefmKZmiSMRPJtwq007p0vVP57",
105
- turnstileSiteKey: "1x00000000000000000000AA"
106
- // AA to always succeed, AB to always fail
107
- },
108
- staging: {
109
- env: "staging",
110
- host: "https://staging-manager.cymbal.co",
111
- apiHost: "https://staging-api.cymbal.co",
112
- cachedApiHost: "https://staging-cache-api.cymbal.co",
113
- homepageHost: "https://staging.cymbal.co",
114
- webHost: "https://staging-app.cymbal.co",
115
- trackingHost: "https://staging.cy.link",
116
- stripeApiKey: "pk_test_51LKSx9DUFJHrciOV6vQAOVOCPJWBZOPIQZ7MqDykKdRFk5oRGOc1OCZOzo3kIPJKr6tVr3jOJefmKZmiSMRPJtwq007p0vVP57",
117
- turnstileSiteKey: "0x4AAAAAADcxWmLeTC3FZ8Pt"
118
- },
119
- production: {
120
- env: "production",
121
- host: "https://manager.cymbal.co",
122
- apiHost: "https://api.cymbal.co",
123
- cachedApiHost: "https://cache-api.cymbal.co",
124
- homepageHost: "https://cymbal.co",
125
- webHost: "https://app.cymbal.co",
126
- trackingHost: "https://cy.link",
127
- stripeApiKey: "pk_live_51LKSx9DUFJHrciOVruTpEgzJ8HU2rnpfUoBvSFrwULMpRCzLoVaEeLI4crV4GhykMN2cgNAmmVhLbXK2rMiBIASp00HdegT6uO",
128
- turnstileSiteKey: "0x4AAAAAADcxWmLeTC3FZ8Pt"
129
- }
130
- };
131
- const getEnv = () => {
132
- switch (process.env.NEXT_PUBLIC_ENV) {
133
- case "production":
134
- case "staging":
135
- case "development":
136
- return process.env.NEXT_PUBLIC_ENV;
137
- default:
138
- return "development";
139
- }
140
- };
141
- configRecord[getEnv()] ?? configRecord["development"];
142
- envConfigRecord[getEnv()] ?? envConfigRecord["development"];
143
-
144
- const allMarksKeys = [
145
- "color",
146
- "fontWeight",
147
- "fontStyle",
148
- "textDecoration",
149
- "textTransform",
150
- "fontSize",
151
- "fontFamily",
152
- "lineHeight",
153
- "letterSpacing"
154
- ];
155
- new Set(allMarksKeys);
156
3
 
157
4
  const MIN_LAYOUT_BASIS = 1;
158
5
  const DEFAULT_LAYOUT_BASIS = 100;
159
6
 
160
- ({
161
- linkColor: defaultStyles.page_style.link_color,
162
- pagesMaxWidth: defaultStyles.page_style.pages_max_width,
163
- underlineLinks: defaultStyles.page_style.underline_links
164
- });
165
- const zeroPadding = { top: 0, right: 0, bottom: 0, left: 0 };
166
- function normalizePadding(padding) {
167
- if (padding === null || padding === void 0) {
168
- return { ...zeroPadding };
169
- }
170
- return { ...zeroPadding, ...padding };
171
- }
172
7
  function resolveLayoutVisualStyleValue({
173
8
  override,
174
9
  global
175
10
  }) {
176
- if (override === void 0 || override === null) {
177
- return global;
11
+ return override === null || override === void 0 ? global : override;
12
+ }
13
+ function normalizePadding(padding) {
14
+ if (!padding) {
15
+ return { top: 0, right: 0, bottom: 0, left: 0 };
178
16
  }
179
- return override;
17
+ return {
18
+ top: padding.top ?? 0,
19
+ right: padding.right ?? 0,
20
+ bottom: padding.bottom ?? 0,
21
+ left: padding.left ?? 0
22
+ };
180
23
  }
181
24
  function mergeResolvedLayoutWidth(overrides, global) {
182
25
  if (overrides === null) {
@@ -381,10 +224,10 @@ function horizontalBorderInsetPx(border) {
381
224
  return 0;
382
225
  }
383
226
  function computeAtomContentWidth(boxWidth, layoutStyles) {
384
- const borderW = layoutStyles.border !== "none" ? horizontalBorderInsetPx(layoutStyles.border) : 0;
227
+ const borderWidth = layoutStyles.border !== "none" ? horizontalBorderInsetPx(layoutStyles.border) : 0;
385
228
  const padLeft = layoutStyles.padding?.left ?? 0;
386
229
  const padRight = layoutStyles.padding?.right ?? 0;
387
- return Math.max(0, boxWidth - padLeft - padRight - borderW);
230
+ return Math.max(0, boxWidth - padLeft - padRight - borderWidth);
388
231
  }
389
232
  function calculateRowChildWidth({
390
233
  contentWidth,
@@ -460,27 +303,6 @@ function calculateColumnChildWidths({
460
303
  }
461
304
  return widths;
462
305
  }
463
-
464
- const ATOM_SOCIAL_ORDINAL_TO_PLATFORM = {
465
- facebookOrdinal: "facebook",
466
- xOrdinal: "x",
467
- instagramOrdinal: "instagram",
468
- tiktokOrdinal: "tiktok",
469
- youtubeOrdinal: "youtube",
470
- websiteOrdinal: "website",
471
- spotifyOrdinal: "spotify",
472
- discordOrdinal: "discord",
473
- soundcloudOrdinal: "soundcloud",
474
- appleMusicOrdinal: "apple_music",
475
- threadsOrdinal: "threads"
476
- };
477
- Object.entries(ATOM_SOCIAL_ORDINAL_TO_PLATFORM).reduce(
478
- (accumulator, [ordinalKey, platform]) => {
479
- accumulator[platform] = ordinalKey;
480
- return accumulator;
481
- },
482
- {}
483
- );
484
306
  function ensureUrlHasProtocolForPreview(url) {
485
307
  const trimmed = url.trim();
486
308
  if (trimmed === "") {
@@ -939,7 +761,76 @@ const EmailColumnsAtom = ({ atom, ctx }) => {
939
761
  });
940
762
  return /* @__PURE__ */ React.createElement(Section, { style: outerTableStyle }, /* @__PURE__ */ React.createElement(Row, { style: innerRowStyle }, cells));
941
763
  };
942
- const AtomDocumentContentsEmail = ({ document: doc }) => {
764
+ const hiddenPreheaderStyle = {
765
+ display: "none",
766
+ fontSize: "1px",
767
+ lineHeight: "1px",
768
+ maxHeight: 0,
769
+ maxWidth: 0,
770
+ opacity: 0,
771
+ overflow: "hidden"
772
+ };
773
+ const TopUnsubscribeBar = ({ unsubscribeLink }) => /* @__PURE__ */ React.createElement(
774
+ "table",
775
+ {
776
+ align: "center",
777
+ border: 0,
778
+ cellPadding: "0",
779
+ cellSpacing: "0",
780
+ role: "presentation",
781
+ style: { background: "#FFFFFF", backgroundColor: "#FFFFFF", width: "100%" }
782
+ },
783
+ /* @__PURE__ */ React.createElement("tbody", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("td", null, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
784
+ "table",
785
+ {
786
+ align: "center",
787
+ border: 0,
788
+ cellPadding: "0",
789
+ cellSpacing: "0",
790
+ role: "presentation",
791
+ style: { width: "100%" }
792
+ },
793
+ /* @__PURE__ */ React.createElement("tbody", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement(
794
+ "td",
795
+ {
796
+ className: "top-unsubscribe",
797
+ style: {
798
+ fontSize: 0,
799
+ paddingTop: "16px",
800
+ paddingBottom: "16px",
801
+ textAlign: "left"
802
+ }
803
+ },
804
+ /* @__PURE__ */ React.createElement(
805
+ "div",
806
+ {
807
+ style: {
808
+ fontFamily: "'Google Sans', Roboto, RobotoDraft, Helvetica, Arial, sans-serif",
809
+ fontSize: "14px",
810
+ fontWeight: "500",
811
+ lineHeight: "1",
812
+ textAlign: "left",
813
+ color: "#3771e0"
814
+ }
815
+ },
816
+ /* @__PURE__ */ React.createElement(
817
+ "a",
818
+ {
819
+ style: { color: "#3771e0", textDecoration: "none" },
820
+ href: unsubscribeLink,
821
+ target: "_blank",
822
+ rel: "noopener noreferrer"
823
+ },
824
+ "Unsubscribe"
825
+ )
826
+ )
827
+ )))
828
+ )))))
829
+ );
830
+ const AtomDocumentContentsEmail = ({
831
+ document: doc,
832
+ options
833
+ }) => {
943
834
  const webFonts = collectFontFamilies(doc);
944
835
  const ctx = {
945
836
  globalAtomStyles: doc.globalAtomStyles,
@@ -955,10 +846,19 @@ const AtomDocumentContentsEmail = ({ document: doc }) => {
955
846
  rel: "stylesheet",
956
847
  href: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fontFamily)}:wght@100;200;300;400;500;600;700;800;900&display=swap`
957
848
  }
958
- ))), /* @__PURE__ */ React.createElement(Body, { style: { backgroundColor: bodyBackgroundColor, margin: 0, padding: 0 } }, /* @__PURE__ */ React.createElement(Container, { style: { maxWidth: doc.maxWidth, margin: "0 auto" } }, /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: doc.rootRow, ctx }))));
849
+ ))), /* @__PURE__ */ React.createElement(Body, { style: { backgroundColor: bodyBackgroundColor, margin: 0, padding: 0 } }, options?.emailPreviewText ? /* @__PURE__ */ React.createElement("div", { style: hiddenPreheaderStyle }, options.emailPreviewText) : null, options?.topUnsubscribeLink ? /* @__PURE__ */ React.createElement(TopUnsubscribeBar, { unsubscribeLink: options.topUnsubscribeLink }) : null, options?.automationPreviewHeaderHtml ? /* @__PURE__ */ React.createElement("div", { dangerouslySetInnerHTML: { __html: options.automationPreviewHeaderHtml } }) : null, /* @__PURE__ */ React.createElement(Container, { style: { maxWidth: doc.maxWidth, margin: "0 auto" } }, /* @__PURE__ */ React.createElement(EmailRowsAtom, { atom: doc.rootRow, ctx }), options?.cymbalBrandingUrl ? /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Text, { style: { color: "#999999", fontSize: 12, textAlign: "center" } }, "Powered by", " ", /* @__PURE__ */ React.createElement(Link, { href: options.cymbalBrandingUrl, style: { color: "#999999" } }, "Cymbal"))) : null), options?.trackingPixelUrl ? /* @__PURE__ */ React.createElement(
850
+ Img,
851
+ {
852
+ src: options.trackingPixelUrl,
853
+ width: "1",
854
+ height: "1",
855
+ style: { display: "none", height: 1, width: 1 },
856
+ alt: ""
857
+ }
858
+ ) : null));
959
859
  };
960
- async function renderAtomDocumentToHtml(doc) {
961
- return render(/* @__PURE__ */ React.createElement(AtomDocumentContentsEmail, { document: doc }));
860
+ async function renderAtomDocumentToHtml(doc, options) {
861
+ return render(/* @__PURE__ */ React.createElement(AtomDocumentContentsEmail, { document: doc, options }));
962
862
  }
963
863
 
964
864
  export { renderAtomDocumentToHtml };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cymbal/atoms-email-renderer",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",