email-builder-utils 1.1.29 → 1.1.31

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.
@@ -31,6 +31,8 @@ interface IProps {
31
31
  youtubeVideoUrl?: string;
32
32
  thumbnailUrl?: string;
33
33
  shape?: string;
34
+ hideOnDesktop?: boolean;
35
+ hideOnMobile?: boolean;
34
36
  }
35
37
  interface IStyle {
36
38
  [key: string]: any;
@@ -1 +1 @@
1
- {"version":3,"file":"Template.d.ts","sourceRoot":"","sources":["../../src/types/Template.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,IAAI,YAAY;IAChB,KAAK,UAAU;IACf,QAAQ,WAAW;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;IACf,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED,UAAU,MAAM;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAGhB;AAED,UAAU,MAAM;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH"}
1
+ {"version":3,"file":"Template.d.ts","sourceRoot":"","sources":["../../src/types/Template.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,IAAI,YAAY;IAChB,KAAK,UAAU;IACf,QAAQ,WAAW;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;IACf,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED,oBAAY,UAAU;IACpB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED,UAAU,MAAM;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,MAAM;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH"}
@@ -1,3 +1,7 @@
1
1
  export declare const extractYouTubeId: (url: string) => string | null;
2
2
  export declare const extractVimeoId: (url: string) => string | null;
3
+ export declare function getVisibilityClass(props?: {
4
+ hideOnDesktop?: boolean;
5
+ hideOnMobile?: boolean;
6
+ }): string;
3
7
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAqBvD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAIrD,CAAC"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/utils/common.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAqBvD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAIrD,CAAC;AAGF,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,UASA"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractVimeoId = exports.extractYouTubeId = void 0;
4
+ exports.getVisibilityClass = getVisibilityClass;
4
5
  const extractYouTubeId = (url) => {
5
6
  try {
6
7
  const u = new URL(url);
@@ -31,3 +32,14 @@ const extractVimeoId = (url) => {
31
32
  return match ? match[1] : null;
32
33
  };
33
34
  exports.extractVimeoId = extractVimeoId;
35
+ function getVisibilityClass(props) {
36
+ if (!props)
37
+ return "";
38
+ const { hideOnDesktop, hideOnMobile } = props;
39
+ return [
40
+ hideOnMobile ? "hide-mobile" : "",
41
+ hideOnDesktop ? "hide-desktop" : "",
42
+ ]
43
+ .filter(Boolean)
44
+ .join(" ");
45
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,oBAgFpD,CAAC"}
1
+ {"version":3,"file":"convertJsonToHtml.d.ts","sourceRoot":"","sources":["../../src/utils/convertJsonToHtml.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,GAAU,UAAU,GAAG,oBA4GpD,CAAC"}
@@ -18,7 +18,7 @@ const convertJsonToHtml = async (jsonData) => {
18
18
  <meta charset="UTF-8" />
19
19
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
20
20
  <meta name="x-apple-disable-message-reformatting" />
21
- <style>
21
+ <style>
22
22
  .responsive-table {
23
23
  width: 100%;
24
24
  max-width: 600px;
@@ -34,6 +34,34 @@ const convertJsonToHtml = async (jsonData) => {
34
34
  max-width: 100% !important;
35
35
  }
36
36
  }
37
+ .hide-mobile {
38
+ display: block !important;
39
+ mso-hide: all !important; /* Hide in Outlook */
40
+ }
41
+
42
+ .hide-desktop {
43
+ display: block !important;
44
+ mso-hide: all !important; /* Hide in Outlook */
45
+ }
46
+
47
+ @media only screen and (max-width: 600px) {
48
+ .hide-mobile {
49
+ display: none !important;
50
+ max-height: 0 !important;
51
+ overflow: hidden !important;
52
+ mso-hide: all !important;
53
+ }
54
+ }
55
+
56
+ @media only screen and (min-width: 601px) {
57
+ .hide-desktop {
58
+ display: none !important;
59
+ max-height: 0 !important;
60
+ overflow: hidden !important;
61
+ mso-hide: all !important;
62
+ }
63
+ }
64
+
37
65
  </style>
38
66
  </head>
39
67
  <body>
@@ -12,6 +12,8 @@ interface BlockJsonProps {
12
12
  youtubeVideoUrl?: string;
13
13
  thumbnailUrl?: string;
14
14
  shape?: string;
15
+ hideOnDesktop?: boolean;
16
+ hideOnMobile?: boolean;
15
17
  }
16
18
  interface IBlockData {
17
19
  type: BlockType;
@@ -1 +1 @@
1
- {"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAUrC,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAGhB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,cAAc,CAAC;QACtB,KAAK,EAAE,GAAG,CAAC;QACX,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KAC7B,CAAC;CACH;AAYD,eAAO,MAAM,gBAAgB,kDAAkD,CAAC;AA2DhF,wBAAsB,aAAa,CACjC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,mBAwBtB;AAsbD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBA8K5E"}
1
+ {"version":3,"file":"jsonToHTML.d.ts","sourceRoot":"","sources":["../../src/utils/jsonToHTML.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAUrC,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,cAAc,CAAC;QACtB,KAAK,EAAE,GAAG,CAAC;QACX,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KAC7B,CAAC;CACH;AAYD,eAAO,MAAM,gBAAgB,kDAAkD,CAAC;AA2DhF,wBAAsB,aAAa,CACjC,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,MAAM,mBAwBtB;AAuiBD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,mBAyL5E"}
@@ -84,35 +84,67 @@ async function convertToHtml(blockData, rootData, cellWidthInPx) {
84
84
  return "";
85
85
  }
86
86
  }
87
- function appendOutlookSupport(content, contentStyle) {
87
+ // function appendOutlookSupport(content: string, contentStyle: string) {
88
+ // return `
89
+ // <table width="100%" style="${tableCommonStyle}"><tr><td style="${contentStyle}">${content}</td></tr></table>
90
+ // `;
91
+ // }
92
+ function appendOutlookSupport(content, contentStyle, className) {
93
+ const visibilityClass = className || "";
94
+ const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
95
+ if (shouldHideInOutlook) {
96
+ return `
97
+ <!--[if !mso]><!-->
98
+ <table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
99
+ <!--<![endif]-->
100
+ `;
101
+ }
88
102
  return `
89
- <table width="100%" style="${exports.tableCommonStyle}"><tr><td style="${contentStyle}">${content}</td></tr></table>
103
+ <table width="100%" style="${exports.tableCommonStyle}" class="${visibilityClass}"><tr><td style="${contentStyle}">${content}</td></tr></table>
90
104
  `;
91
105
  }
92
106
  function convertDividerBlockToHtml(blockData) {
93
107
  const { style, props } = blockData.data;
108
+ const { hideOnMobile, hideOnDesktop } = props;
94
109
  const { thickness, dividerColor, width, ...rest } = style;
95
110
  const convertedStyle = buildStyles(rest, {
96
111
  perChanges: [],
97
112
  pxChanges: allPxAttributes,
98
113
  });
99
114
  const dividerWidth = width || "100%";
115
+ // Build class name based on visibility
116
+ const visibilityClass = [
117
+ hideOnMobile ? "hide-mobile" : "",
118
+ hideOnDesktop ? "hide-desktop" : "",
119
+ ]
120
+ .filter(Boolean)
121
+ .join(" ");
100
122
  const dividerContent = `
101
- <table width="${dividerWidth}%" cellpadding="0" cellspacing="0">
123
+ <table
124
+ width="${dividerWidth}%"
125
+ cellpadding="0"
126
+ cellspacing="0"
127
+ >
102
128
  <tr>
103
- <td height="${thickness}" style="font-size:1px; line-height:1px; background:${dividerColor}; width:${dividerWidth};">&nbsp;</td>
129
+ <td
130
+ height="${thickness}"
131
+ style="font-size:1px; line-height:1px; background:${dividerColor}; width:${dividerWidth};"
132
+ >
133
+ &nbsp;
134
+ </td>
104
135
  </tr>
105
136
  </table>
106
137
  `;
107
- return appendOutlookSupport(dividerContent, convertedStyle);
138
+ return appendOutlookSupport(dividerContent, convertedStyle, visibilityClass);
108
139
  }
109
140
  function convertSpacerBlockToHtml(blockData) {
110
- const { style } = blockData.data;
141
+ const { style, props } = blockData.data;
142
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
111
143
  const styles = buildStyles(style, {
112
144
  perChanges: [],
113
145
  pxChanges: allPxAttributes,
114
146
  });
115
- return appendOutlookSupport(``, styles);
147
+ return appendOutlookSupport(``, styles, visibilityClass);
116
148
  }
117
149
  // function convertTextBlock(blockData: IBlockData) {
118
150
  // const { style, props } = blockData.data;
@@ -132,6 +164,7 @@ function convertSpacerBlockToHtml(blockData) {
132
164
  // }
133
165
  function convertTextBlock(blockData) {
134
166
  const { style, props } = blockData.data;
167
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
135
168
  const { width, backgroundColor, padding, borderRadius, borderStyle, borderColor, borderWidth, textContainerBackgroundColor, textContainerPadding, ...rest } = style;
136
169
  const textBoxStyle = {
137
170
  width,
@@ -159,9 +192,9 @@ function convertTextBlock(blockData) {
159
192
  .replaceAll(/<\/p>/g, "</div>");
160
193
  const navigateToUrl = props.navigateToUrl || "";
161
194
  const convertedTextBox = `<div style="display: inline-block; max-width: 100%; box-sizing: border-box; ${convertedTextStyle}">${sanitizedText.replaceAll(/\n/g, "<br>")}</div>`;
162
- const textContent = appendOutlookSupport(convertedTextBox, styles);
195
+ const textContent = appendOutlookSupport(convertedTextBox, styles, visibilityClass);
163
196
  return navigateToUrl
164
- ? `<a href="${navigateToUrl}" rel="noreferrer noopener" style="color:inherit; text-decoration:none; cursor:pointer;">${textContent}</a>`
197
+ ? `<a href="${navigateToUrl}" rel="noreferrer noopener" style="color:inherit;text-decoration:none;cursor:pointer;">${textContent}</a>`
165
198
  : textContent;
166
199
  }
167
200
  async function appendOutlookForImage(content, outerContainerWidth, innerContainerWidth, imageUrl, style = {}) {
@@ -198,13 +231,20 @@ async function appendOutlookForImage(content, outerContainerWidth, innerContaine
198
231
  <!--<![endif]-->
199
232
  `;
200
233
  }
234
+ async function computeScaledDimensions(imageUrl, maxContainerWidthPx) {
235
+ const image = await jimp_1.Jimp.read(imageUrl);
236
+ const originalWidth = image.bitmap.width;
237
+ const originalHeight = image.bitmap.height;
238
+ const widthScalingFactor = Math.min(maxContainerWidthPx / originalWidth, 1);
239
+ const scaledWidth = Math.round(originalWidth * widthScalingFactor);
240
+ const scaledHeight = Math.round(originalHeight * widthScalingFactor);
241
+ return { originalWidth, originalHeight, scaledWidth, scaledHeight };
242
+ }
201
243
  async function convertImageBlock(blockData, cellWidthInPx) {
202
244
  const { style, props } = blockData.data;
203
245
  const { altText, imageUrl, navigateToUrl } = props;
246
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
204
247
  const { width, height, objectFit, borderRadius, borderWidth, borderColor, borderStyle, ...containerStyle } = style;
205
- const image = await jimp_1.Jimp.read(imageUrl);
206
- const originalWidth = image.bitmap.width;
207
- const originalHeight = image.bitmap.height;
208
248
  // Ensure border styles are applied only to the container, not the image
209
249
  const imageStyle = {
210
250
  width,
@@ -213,27 +253,37 @@ async function convertImageBlock(blockData, cellWidthInPx) {
213
253
  borderStyle,
214
254
  borderRadius: borderRadius,
215
255
  borderColor,
216
- maxWidth: `${originalWidth}px`, // Limit to original size
217
- maxHeight: `${originalHeight}px`,
218
256
  };
219
257
  // Add border styles to container for fallback clients
220
258
  const containerStyles = buildStyles({
221
259
  ...containerStyle,
222
260
  }, { perChanges: [], pxChanges: addPxToAttributes });
223
- const imageTagStyles = buildStyles(imageStyle, {
224
- perChanges: addPxOrPerToAttributes,
225
- pxChanges: addPxToAttributes,
226
- });
227
- const imageElement = `<img src="${imageUrl}" alt="${altText}" style="${imageTagStyles}; max-width: ${originalWidth}px; max-height: ${originalHeight}px;" />`;
228
- const innerContainerWidth = ((typeof width === "string" ? parseInt(width.replace("%", "")) : width) /
261
+ const innerContainerWidth = (((typeof width === "string" ? parseInt(width.replace("%", "")) : width) ||
262
+ 100) /
229
263
  100) *
230
264
  (cellWidthInPx -
231
265
  (style?.padding?.left || 0) -
232
266
  (style?.padding?.right || 0));
233
- const outlookImage = await appendOutlookForImage(imageElement, cellWidthInPx, innerContainerWidth, imageUrl, style);
234
- const imageContent = appendOutlookSupport(outlookImage, containerStyles);
267
+ const { originalWidth, originalHeight, scaledWidth, scaledHeight } = await computeScaledDimensions(imageUrl, innerContainerWidth);
268
+ const imageTagStyles = buildStyles({
269
+ maxWidth: `${originalWidth}px`, // Limit to original size
270
+ maxHeight: `${originalHeight}px`,
271
+ ...imageStyle,
272
+ }, {
273
+ perChanges: addPxOrPerToAttributes,
274
+ pxChanges: addPxToAttributes,
275
+ });
276
+ const imageElement = `<img src="${imageUrl}" alt="${altText}" width="${scaledWidth}" height="${scaledHeight}" style="${imageTagStyles}; width:100%; height:auto; max-width:${originalWidth}px; max-height:${originalHeight}px;" />`;
277
+ const percentWidth = typeof width === "string" && width.endsWith("%")
278
+ ? width
279
+ : typeof width === "number"
280
+ ? `${width}%`
281
+ : "100%";
282
+ const nonMsoWrapper = `<div style="display:inline-block; width:${percentWidth}; max-width:${originalWidth}px;">${imageElement}</div>`;
283
+ const outlookImage = await appendOutlookForImage(nonMsoWrapper, cellWidthInPx, innerContainerWidth, imageUrl, style);
284
+ const imageContent = appendOutlookSupport(outlookImage, containerStyles, visibilityClass);
235
285
  return navigateToUrl
236
- ? `<a href="${navigateToUrl}" target="_blank" rel="noreferrer noopener" style="display:block; text-decoration:none; cursor:pointer;">${imageContent}</a>`
286
+ ? `<a href="${navigateToUrl}" target="_blank" rel="noreferrer noopener" style="display:block;">${imageContent}</a>`
237
287
  : imageContent;
238
288
  }
239
289
  function appendOutlookForButton(content, buttonStyle, navigateToUrl, text) {
@@ -263,6 +313,7 @@ function appendOutlookForButton(content, buttonStyle, navigateToUrl, text) {
263
313
  function convertButtonBlock(blockData) {
264
314
  const { style, props } = blockData.data;
265
315
  const { text, navigateToUrl } = props;
316
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
266
317
  const { fontFamily, fontSize, fontWeight, borderColor, borderRadius, borderWidth, borderStyle, buttonPadding, color, buttonColor, width, height, ...rest } = style;
267
318
  const buttonStyle = {
268
319
  width,
@@ -287,44 +338,71 @@ function convertButtonBlock(blockData) {
287
338
  pxChanges: allPxAttributes,
288
339
  });
289
340
  const buttonElement = `<a href="${navigateToUrl}" rel="noreferrer noopener" style="display:inline-block; text-decoration:none; cursor:pointer;"><button style="${convertedButtonStyle}">${text}</button></a>`;
290
- const buttonContent = appendOutlookSupport(appendOutlookForButton(buttonElement, style, navigateToUrl, text), convertedStyles);
341
+ const buttonContent = appendOutlookSupport(appendOutlookForButton(buttonElement, style, navigateToUrl, text), convertedStyles, visibilityClass);
291
342
  return buttonContent;
292
343
  }
293
344
  async function convertGridBlock(blockData, rootData, cellWidthInPx) {
294
345
  const { style = {}, childrenIds = [], props } = blockData.data;
295
346
  const { columns = 1, cellWidths = [], responsive = true } = props;
296
347
  const { columnGap = 0, ...restStyle } = style;
348
+ const gridVisibilityClass = (0, common_1.getVisibilityClass)(props);
297
349
  const tableStyles = buildStyles(restStyle, {
298
350
  perChanges: [],
299
351
  pxChanges: allPxAttributes,
300
352
  });
301
353
  const total = childrenIds.length;
302
354
  const visualRows = Math.ceil(total / columns);
355
+ // Fix: Calculate visible cells per row to adjust widths
303
356
  let html = `
304
357
  <!--[if mso]>
305
- <table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" style="${exports.tableCommonStyle}border-collapse: separate;border-spacing:${columnGap}px;">
358
+ <table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%"
359
+ style="${exports.tableCommonStyle}border-collapse: separate;border-spacing:${columnGap}px;" class="${gridVisibilityClass}">
306
360
  <![endif]-->
307
- <table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" role="presentation" style="${exports.tableCommonStyle} ${tableStyles}border-collapse: separate;border-spacing:${columnGap}px;">
361
+ <table border="0" cellpadding="0" cellspacing="${columnGap}" width="100%" role="presentation"
362
+ style="${exports.tableCommonStyle} ${tableStyles}border-collapse: separate;border-spacing:${columnGap}px;" class="${gridVisibilityClass}">
308
363
  `;
309
364
  for (let r = 0; r < visualRows; r++) {
310
365
  html += "<tr>";
366
+ let visibleCellsInRow = 0;
367
+ const rowCellVisibility = [];
311
368
  for (let c = 0; c < columns; c++) {
312
369
  const idx = r * columns + c;
313
370
  const childId = childrenIds[idx];
314
- const widthPercent = cellWidths[c] ?? 100 / columns;
315
371
  if (childId) {
316
372
  const child = rootData[childId];
317
- const { style: cellStyle = {} } = child.data || {};
373
+ const { props: childProps = {} } = child.data || {};
374
+ const isVisible = !childProps.hideOnDesktop;
375
+ rowCellVisibility.push(isVisible);
376
+ if (isVisible)
377
+ visibleCellsInRow++;
378
+ }
379
+ else {
380
+ rowCellVisibility.push(false);
381
+ }
382
+ }
383
+ const widthPerVisibleCell = visibleCellsInRow > 0 ? 100 / visibleCellsInRow : 100 / columns;
384
+ for (let c = 0; c < columns; c++) {
385
+ const idx = r * columns + c;
386
+ const childId = childrenIds[idx];
387
+ const widthPercent = cellWidths[c] ?? widthPerVisibleCell;
388
+ if (childId) {
389
+ const child = rootData[childId];
390
+ const { style: cellStyle = {}, props: childProps = {} } = child.data || {};
318
391
  const verticalAlign = cellStyle.verticalAlign || "top";
319
392
  const { html: childHtml, styles } = await convertGridCellBlock(child, rootData, widthPercent, cellWidthInPx);
320
- html += `
321
- <td
322
- width="${widthPercent}%"
323
- ${responsive ? 'class="stack-column"' : ""}
324
- style="vertical-align:${verticalAlign}; word-break:break-word; ${styles} "
325
- >
326
- ${childHtml}
327
- </td>`;
393
+ const cellVisibilityClass = (0, common_1.getVisibilityClass)(childProps);
394
+ if (!childProps.hideOnDesktop) {
395
+ html += `
396
+ <td
397
+ width="${widthPercent}%"
398
+ class="${[responsive ? "stack-column" : "", cellVisibilityClass]
399
+ .filter(Boolean)
400
+ .join(" ")}"
401
+ style="vertical-align:${verticalAlign}; word-break:break-word; ${styles}"
402
+ >
403
+ ${childHtml}
404
+ </td>`;
405
+ }
328
406
  }
329
407
  else {
330
408
  html += `<td width="${widthPercent}%" ${responsive ? 'class="stack-column"' : ""} style=""></td>`;
@@ -336,7 +414,7 @@ async function convertGridBlock(blockData, rootData, cellWidthInPx) {
336
414
  return html;
337
415
  }
338
416
  async function convertGridCellBlock(blockData, rootData, cellWidthPercent, parentCellWidthPx) {
339
- const { style = {}, childrenIds = [] } = blockData.data;
417
+ const { style = {}, childrenIds = [], props = {} } = blockData.data;
340
418
  const styles = buildStyles(style, {
341
419
  perChanges: [],
342
420
  pxChanges: allPxAttributes,
@@ -349,13 +427,17 @@ async function convertGridCellBlock(blockData, rootData, cellWidthPercent, paren
349
427
  innerHtmlParts.push(await convertToHtml(child, rootData, cellWidthPx));
350
428
  }
351
429
  }
430
+ const cellContent = innerHtmlParts.join("");
352
431
  return {
353
- html: innerHtmlParts.join(""),
432
+ html: cellContent,
354
433
  styles,
355
434
  };
356
435
  }
436
+ // Enhanced Video Block HTML Conversion with centered play button
357
437
  async function convertVideoBlock(blockData, cellWidthInPx) {
358
438
  const { style, props } = blockData.data;
439
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
440
+ const { hideOnDesktop } = props; // Get the hideOnDesktop prop
359
441
  const { videoUrl, youtubeVideoUrl, thumbnailUrl, altText } = props;
360
442
  const videoLink = youtubeVideoUrl || videoUrl || "#";
361
443
  let resolvedThumbnail = thumbnailUrl || "https://via.placeholder.com/480x360?text=No+Thumbnail";
@@ -387,10 +469,7 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
387
469
  else {
388
470
  percentWidth = "100%";
389
471
  }
390
- const innerContainerWidth = (parseFloat(percentWidth) / 100) *
391
- (cellWidthInPx -
392
- (style?.padding?.left || 0) -
393
- (style?.padding?.right || 0));
472
+ const innerContainerWidth = (parseFloat(percentWidth) / 100) * (cellWidthInPx - (style?.padding?.left || 0) - (style?.padding?.right || 0));
394
473
  const aspectRatio = 16 / 9;
395
474
  const calculatedHeight = innerContainerWidth / aspectRatio;
396
475
  const outerContainerStyles = buildStyles({
@@ -413,77 +492,99 @@ async function convertVideoBlock(blockData, cellWidthInPx) {
413
492
  // VML centering math (for Outlook)
414
493
  const vmlLeft = innerContainerWidth / 2 - playIconWidth / 2;
415
494
  const vmlTop = calculatedHeight / 2 - playIconHeight / 2;
416
- const videoContent = `
417
- <!--[if mso]>
418
- <v:group xmlns:v="urn:schemas-microsoft-com:vml"
419
- coordsize="${innerContainerWidth},${calculatedHeight}"
420
- href="${videoLink}"
421
- style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
422
- <v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
423
- strokeweight="${borderWidth}px"
424
- strokecolor="${borderColor}"
425
- ${borderRadius > 0
426
- ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"`
427
- : ""}
495
+ const shouldHideInOutlook = hideOnDesktop;
496
+ const outlookVideoContent = shouldHideInOutlook
497
+ ? `<!--[if !mso]><!-->
498
+ <v:group xmlns:v="urn:schemas-microsoft-com:vml"
499
+ coordsize="${innerContainerWidth},${calculatedHeight}"
500
+ href="${videoLink}"
501
+ style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
502
+ <v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
503
+ strokeweight="${borderWidth}px"
504
+ strokecolor="${borderColor}"
505
+ ${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
506
+ >
507
+ <v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
508
+ </v:rect>
509
+ <v:shape type="#_x0000_t75"
510
+ style="position:absolute;
511
+ left:${vmlLeft.toFixed(1)}px;
512
+ top:${vmlTop.toFixed(1)}px;
513
+ width:${playIconWidth}px;
514
+ height:${playIconHeight}px;"
515
+ alt="Play" href="${videoLink}" title="${altText || "Video"}"
516
+ stroked="f" filled="t">
517
+ <v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
518
+ </v:shape>
519
+ </v:group>
520
+ <!--<![endif]-->`
521
+ : `<!--[if mso]>
522
+ <v:group xmlns:v="urn:schemas-microsoft-com:vml"
523
+ coordsize="${innerContainerWidth},${calculatedHeight}"
524
+ href="${videoLink}"
525
+ style="width:${innerContainerWidth}px;height:${calculatedHeight}px;">
526
+ <v:rect fill="t" style="position:absolute;width:${innerContainerWidth}px;height:${calculatedHeight}px; stroked="t"
527
+ strokeweight="${borderWidth}px"
528
+ strokecolor="${borderColor}"
529
+ ${borderRadius > 0 ? `arcsize="${Math.min(borderRadius / calculatedHeight, 1).toFixed(2)}"` : ""}
530
+ >
531
+ <v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
532
+ </v:rect>
533
+ <v:shape type="#_x0000_t75"
534
+ style="position:absolute;
535
+ left:${vmlLeft.toFixed(1)}px;
536
+ top:${vmlTop.toFixed(1)}px;
537
+ width:${playIconWidth}px;
538
+ height:${playIconHeight}px;"
539
+ alt="Play" href="${videoLink}" title="${altText || "Video"}"
540
+ stroked="f" filled="t">
541
+ <v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
542
+ </v:shape>
543
+ </v:group>
544
+ <![endif]-->`;
545
+ const nonOutlookVideoContent = `<!--[if !mso]><!-->
546
+ <table
547
+ width="${innerContainerWidth}"
548
+ cellpadding="0"
549
+ cellspacing="0"
550
+ border="0"
551
+ role="presentation"
552
+ align="${style?.textAlign || "left"}"
553
+ style="
554
+ max-width: ${innerContainerWidth}px;
555
+ width: 100%;
556
+ height: ${calculatedHeight}px;
557
+ background-color: ${style?.backgroundColor || "#FFFFFF"};
558
+ background-image: url('${resolvedThumbnail}');
559
+ background-size: cover;
560
+ background-position: center;
561
+ background-repeat: no-repeat;
562
+ box-sizing: border-box;
563
+ border: ${borderWidth}px ${style?.borderStyle || "solid"} ${borderColor};
564
+ border-radius: ${borderRadius}px;
565
+ "
428
566
  >
429
- <v:fill src="${resolvedThumbnail}" type="frame" color="${style?.backgroundColor || "#FFFFFF"}"/>
430
- </v:rect>
431
- <v:shape type="#_x0000_t75"
432
- style="position:absolute;
433
- left:${vmlLeft.toFixed(1)}px;
434
- top:${vmlTop.toFixed(1)}px;
435
- width:${playIconWidth}px;
436
- height:${playIconHeight}px;"
437
- alt="Play" href="${videoLink}" title="${altText || "Video"}"
438
- stroked="f" filled="t">
439
- <v:imagedata src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png" />
440
- </v:shape>
441
- </v:group>
442
- <![endif]-->
443
-
444
- <!--[if !mso]><!-->
445
- <table
446
- width="${innerContainerWidth}"
447
- cellpadding="0"
448
- cellspacing="0"
449
- border="0"
450
- role="presentation"
451
- align="${style?.textAlign || "left"}"
452
- style="
453
- max-width: ${innerContainerWidth}px;
454
- width: 100%;
455
- height: ${calculatedHeight}px;
456
- background-color: ${style?.backgroundColor || "#FFFFFF"};
457
- background-image: url('${resolvedThumbnail}');
458
- background-size: cover;
459
- background-position: center;
460
- background-repeat: no-repeat;
461
- box-sizing: border-box;
462
- border: ${borderWidth}px ${style?.borderStyle || "solid"} ${borderColor};
463
- border-radius: ${borderRadius}px;
464
- "
465
- >
466
- <tr>
467
- <td style="padding: 0; height: ${calculatedHeight}px; text-align: center; vertical-align: middle;" valign="middle">
468
- <a href="${videoLink}" target="_blank" style="display:inline-block; border: 0; outline: none; text-decoration: none;">
469
- <img
470
- src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png"
471
- width="${playIconWidth}"
472
- alt="Play"
473
- style="display: block;
474
- border: 0;
475
- outline: none;
476
- text-decoration: none;
477
- height: auto;"
478
- />
479
- </a>
480
- </td>
481
- </tr>
482
- </table>
483
- <!--<![endif]-->
484
- `;
567
+ <tr>
568
+ <td style="padding: 0; height: ${calculatedHeight}px; text-align: center; vertical-align: middle;" valign="middle">
569
+ <a href="${videoLink}" target="_blank" style="display:inline-block; border: 0; outline: none; text-decoration: none;">
570
+ <img
571
+ src="https://app-rsrc.getbee.io/public/resources/components/widgetBar/video-content-icon-sets/light/type-01.png"
572
+ width="${playIconWidth}"
573
+ alt="Play"
574
+ style="display: block;
575
+ border: 0;
576
+ outline: none;
577
+ text-decoration: none;
578
+ height: auto;"
579
+ />
580
+ </a>
581
+ </td>
582
+ </tr>
583
+ </table>
584
+ <!--<![endif]-->`;
585
+ const videoContent = `${outlookVideoContent}${nonOutlookVideoContent}`;
485
586
  const wrapperHtml = `
486
- <table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse;">
587
+ <table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0; padding:0; border-collapse: collapse;" class="${visibilityClass}">
487
588
  <tr>
488
589
  <td align="${style?.textAlign || "left"}" style="padding:0; ${outerContainerStyles}">
489
590
  <table border="0" cellpadding="0" cellspacing="0" role="presentation"
@@ -670,130 +771,10 @@ function computeArcSize(borderRadius, widthPx) {
670
771
  // </tr>
671
772
  // </table>`;
672
773
  // }
673
- // // ---------- Updated VML builder with better text containment ----------
674
- // function buildVMLShape({
675
- // shape,
676
- // widthPx,
677
- // heightPx,
678
- // imageUrl,
679
- // backgroundColor,
680
- // borderWidth,
681
- // borderColor,
682
- // borderRadius,
683
- // text,
684
- // textColor = "#000000",
685
- // textSize = 14,
686
- // verticalAlign = "center",
687
- // msoHasBakedText = false,
688
- // }: any) {
689
- // // --- Basic setup ---
690
- // const bw = borderWidth || 0;
691
- // const bc = borderColor || "transparent";
692
- // const borderAttrs =
693
- // bw > 0 ? `strokeweight="${bw}px" strokecolor="${bc}"` : `stroked="false"`;
694
- // const fillColor = backgroundColor || "#2F80ED";
695
- // const fillMarkup = `<v:fill ${
696
- // imageUrl ? `src="${imageUrl}" type="frame" aspect="atleast"` : ""
697
- // } color="${fillColor}" />`;
698
- // // --- Shape tag ---
699
- // let tag = "rect";
700
- // let extraAttr = "";
701
- // if (shape === "circle" || shape === "oval") {
702
- // tag = "oval";
703
- // } else if (shape === "rounded") {
704
- // tag = "roundrect";
705
- // extraAttr = `arcsize="${computeArcSize(borderRadius, widthPx)}"`;
706
- // }
707
- // // --- Text alignment ---
708
- // const vAlignMap = { top: "top", center: "middle", bottom: "bottom" };
709
- // const vAlign = vAlignMap[verticalAlign as keyof typeof vAlignMap] || "middle";
710
- // const safeFontSize = Math.max(textSize, 10);
711
- // // --- Text inside shape ---
712
- // const textboxMarkup =
713
- // text && !msoHasBakedText
714
- // ? `<v:textbox inset="6pt,6pt,6pt,6pt" style="mso-fit-shape-to-text:false;">
715
- // <div style="display:table;width:100%;height:100%;">
716
- // <div style="display:table-cell;vertical-align:${vAlign};text-align:center;">
717
- // <div style="color:${textColor};font-family:Arial, sans-serif;font-size:${safeFontSize}px;line-height:1.3;word-wrap:break-word;">
718
- // ${text}
719
- // </div>
720
- // </div>
721
- // </div>
722
- // </v:textbox>`
723
- // : `<v:textbox inset="0,0,0,0"><div style="display:none;">.</div></v:textbox>`;
724
- // // --- Final shape markup ---
725
- // return `
726
- // <v:${tag} xmlns:v="urn:schemas-microsoft-com:vml"
727
- // style="width:${widthPx}px;height:${heightPx}px;
728
- // mso-position-horizontal:center;
729
- // mso-position-vertical:center;"
730
- // ${borderAttrs}
731
- // fill="true" fillcolor="${fillColor}"${extraAttr}>
732
- // ${fillMarkup}
733
- // ${textboxMarkup}
734
- // </v:${tag}>`;
735
- // }
736
- // // ---------- Updated appendOutlookForShape ----------
737
- // async function appendOutlookForShape(
738
- // content: string,
739
- // outerContainerWidth: number,
740
- // innerContainerWidth: number,
741
- // opts: {
742
- // shape: string;
743
- // imageUrl?: string;
744
- // backgroundColor?: string;
745
- // shapeColor?: string;
746
- // borderWidth?: number;
747
- // borderColor?: string;
748
- // borderRadius?: string | number;
749
- // heightPx: number;
750
- // text?: string;
751
- // textColor?: string;
752
- // textSize?: number;
753
- // verticalAlign?: "top" | "middle" | "bottom";
754
- // alignment?: "left" | "center" | "right";
755
- // padding?: { top?: number; right?: number; bottom?: number; left?: number };
756
- // msoBakeImageWithText?: string;
757
- // }
758
- // ) {
759
- // const widthPx = Math.round(
760
- // Math.min(outerContainerWidth, innerContainerWidth)
761
- // );
762
- // const heightPx = Math.max(1, Math.round(opts.heightPx));
763
- // const vml = buildVMLShape({
764
- // shape: opts.shape,
765
- // widthPx,
766
- // heightPx,
767
- // imageUrl: opts.msoBakeImageWithText || opts.imageUrl,
768
- // backgroundColor: opts.shapeColor || opts.backgroundColor,
769
- // borderWidth: opts.borderWidth,
770
- // borderColor: opts.borderColor,
771
- // borderRadius: opts.borderRadius,
772
- // text: opts.text,
773
- // textColor: opts.textColor,
774
- // textSize: opts.textSize,
775
- // msoHasBakedText: Boolean(opts.msoBakeImageWithText),
776
- // });
777
- // const pad = opts.padding || {};
778
- // const align = opts.alignment || "left";
779
- // const valign = opts.verticalAlign || "middle";
780
- // return `<!--[if mso]>
781
- // <table align="${align}" border="0" cellpadding="0" cellspacing="0"
782
- // style="width:${widthPx}px;height:${heightPx}px;">
783
- // <tr>
784
- // <td valign="${valign}"
785
- // style="padding:${pad.top || 0}px ${pad.right || 0}px ${
786
- // pad.bottom || 0
787
- // }px ${pad.left || 0}px;">
788
- // ${vml}
789
- // </td>
790
- // </tr>
791
- // </table>
792
- // <![endif]-->`;
793
- // }
794
774
  async function convertShapeBlock(blockData) {
795
775
  const { style, props } = blockData.data;
796
776
  const { shape, text, imageUrl } = props;
777
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
797
778
  const { width = "100", height = "150", padding = {}, backgroundColor = "#2F80ED", borderRadius, borderWidth = 0, borderStyle = "solid", borderColor = "transparent", customCss, shapeColor, alignment = "left", msoBakeImageWithText, color = "#000000", fontSize = 14, textAlign = "center", verticalAlign = "middle", } = style || {};
798
779
  const borderRadiusMap = {
799
780
  rectangle: "0",
@@ -910,10 +891,10 @@ async function convertShapeBlock(blockData) {
910
891
  alignment,
911
892
  padding,
912
893
  msoBakeImageWithText,
913
- });
894
+ }, visibilityClass);
914
895
  // Combine into table wrapper
915
896
  return `
916
- <table width="100%" style="border-collapse:collapse;table-layout:fixed;">
897
+ <table width="100%" style="border-collapse:collapse;table-layout:fixed;" class="${visibilityClass}">
917
898
  <tr>
918
899
  <td style="padding:${padding.top || 0}px ${padding.right || 0}px ${padding.bottom || 0}px ${padding.left || 0}px;text-align:${alignment};">
919
900
  ${outlookContent}
@@ -974,7 +955,7 @@ function buildVMLShape({ shape, widthPx, heightPx, imageUrl, backgroundColor, bo
974
955
  ${textboxMarkup}
975
956
  </v:${tag}>`;
976
957
  }
977
- function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth, opts) {
958
+ function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth, opts, visibilityClass) {
978
959
  const widthPx = Math.round(Math.min(outerContainerWidth, innerContainerWidth));
979
960
  const heightPx = Math.max(1, Math.round(opts.heightPx));
980
961
  const vml = buildVMLShape({
@@ -996,10 +977,24 @@ function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth
996
977
  const pad = opts.padding || {};
997
978
  const align = opts.alignment || "left";
998
979
  const valign = opts.verticalAlign || "middle";
999
- // Outlook wrapper table ensures the cell's valign works if vml alone doesn't
980
+ const shouldHideInOutlook = visibilityClass.includes("hide-desktop");
981
+ // Fix: Properly handle Outlook visibility with conditional comments
982
+ if (shouldHideInOutlook) {
983
+ return `<!--[if !mso]><!-->
984
+ <table align="${align}" border="0" cellpadding="0" cellspacing="0"
985
+ style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
986
+ <tr>
987
+ <td valign="${valign}"
988
+ style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
989
+ ${vml}
990
+ </td>
991
+ </tr>
992
+ </table>
993
+ <!--<![endif]-->`;
994
+ }
1000
995
  return `<!--[if mso]>
1001
996
  <table align="${align}" border="0" cellpadding="0" cellspacing="0"
1002
- style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;">
997
+ style="width:${widthPx}px;height:${heightPx}px;border-collapse:collapse;" class="${visibilityClass}">
1003
998
  <tr>
1004
999
  <td valign="${valign}"
1005
1000
  style="padding:${pad.top || 0}px ${pad.right || 0}px ${pad.bottom || 0}px ${pad.left || 0}px;">
@@ -1010,8 +1005,9 @@ function appendOutlookForShape(content, outerContainerWidth, innerContainerWidth
1010
1005
  <![endif]-->`;
1011
1006
  }
1012
1007
  function convertVerticalDividerBlockToHtml(blockData) {
1013
- const { style } = blockData.data;
1008
+ const { style, props } = blockData.data;
1014
1009
  const { width, height, dividerColor, ...rest } = style;
1010
+ const visibilityClass = (0, common_1.getVisibilityClass)(props);
1015
1011
  // Convert other styles to inline-safe HTML attributes
1016
1012
  const convertedStyle = buildStyles(rest, {
1017
1013
  perChanges: [],
@@ -1032,5 +1028,5 @@ function convertVerticalDividerBlockToHtml(blockData) {
1032
1028
  </tr>
1033
1029
  </table>
1034
1030
  `;
1035
- return appendOutlookSupport(dividerContent, convertedStyle);
1031
+ return appendOutlookSupport(dividerContent, convertedStyle, visibilityClass);
1036
1032
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "email-builder-utils",
3
- "version": "1.1.29",
3
+ "version": "1.1.31",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [