@pagenflow/email 1.4.1 → 1.4.3

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.js CHANGED
@@ -10,41 +10,49 @@ function Body({ children, config = {} }) {
10
10
  const globalFontSize = config.fontSize || "16px";
11
11
  const globalBackgroundColor = config.backgroundColor || "#ffffff";
12
12
  const globalLineHeight = config.lineHeight || "1.4";
13
+ const globalFontFamily = config.fontFamily || "Arial, Helvetica, sans-serif";
13
14
  // Background image properties
14
15
  const bgImage = ((_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.src) || "";
15
16
  const bgRepeat = ((_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat) || "no-repeat";
16
17
  const bgSize = ((_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size) || "cover";
17
18
  const bgPosition = ((_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position) || "center";
18
19
  // 1. Style for the <body> tag inline
19
- const bodyStyle = Object.assign({ backgroundColor: globalBackgroundColor, color: globalColor, fontSize: globalFontSize, lineHeight: globalLineHeight, padding: "0", margin: "0", WebkitTextSizeAdjust: "100%", overflowX: "hidden",
20
- // ✅ FIX 1: Use string indexing for MSO property
21
- // ['ms-text-size-adjust' as string]: '100%',
22
- ["msTextSizeAdjust"]: "100%",
23
- // ["mso-line-height-rule" as string]: "exactly",
24
- ["msoLineHeightRule"]: "exactly",
25
- // Base font for body
26
- fontFamily: "Arial, Helvetica, sans-serif" }, (bgImage && {
27
- backgroundImage: `url(${bgImage})`,
28
- backgroundRepeat: bgRepeat,
29
- backgroundSize: bgSize,
30
- backgroundPosition: bgPosition,
31
- }));
20
+ const bodyStyle = {
21
+ backgroundColor: globalBackgroundColor,
22
+ color: globalColor,
23
+ fontSize: globalFontSize,
24
+ lineHeight: globalLineHeight,
25
+ padding: "0",
26
+ margin: "0",
27
+ WebkitTextSizeAdjust: "100%",
28
+ overflowX: "hidden",
29
+ ["msTextSizeAdjust"]: "100%",
30
+ ["msoLineHeightRule"]: "exactly",
31
+ fontFamily: globalFontFamily,
32
+ // Background image support (if provided)
33
+ ...(bgImage && {
34
+ backgroundImage: `url(${bgImage})`,
35
+ backgroundRepeat: bgRepeat,
36
+ backgroundSize: bgSize,
37
+ backgroundPosition: bgPosition,
38
+ }),
39
+ };
32
40
  // 2. Style for the top-level <table> wrapper
33
41
  const outerTableStyle = {
34
42
  width: "100%",
35
- // ✅ FIX 1 (on table): Use string indexing for MSO property
36
43
  ["msoLineHeightRule"]: "exactly",
37
- // ['mso-line-height-rule' as string]: 'exactly',
38
44
  borderCollapse: "collapse",
39
45
  };
40
- return (
41
- // The <body> tag with inline styles
42
- jsxRuntime.jsxs("body", { style: bodyStyle, children: [jsxRuntime.jsx("center", { style: Object.assign({ width: "100%", background: globalBackgroundColor }, (bgImage && {
43
- backgroundImage: `url(${bgImage})`,
44
- backgroundRepeat: bgRepeat,
45
- backgroundSize: bgSize,
46
- backgroundPosition: bgPosition,
47
- })), children: jsxRuntime.jsx("table", { role: "presentation", border: 0, cellPadding: 0, cellSpacing: 0, align: "center", width: "100%", style: outerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: "center", style: { padding: "0", margin: "0" }, children: children }) }) }) }) }), jsxRuntime.jsx("div", { style: {
46
+ return (jsxRuntime.jsxs("body", { style: bodyStyle, children: [jsxRuntime.jsx("center", { style: {
47
+ width: "100%",
48
+ background: globalBackgroundColor,
49
+ ...(bgImage && {
50
+ backgroundImage: `url(${bgImage})`,
51
+ backgroundRepeat: bgRepeat,
52
+ backgroundSize: bgSize,
53
+ backgroundPosition: bgPosition,
54
+ }),
55
+ }, children: jsxRuntime.jsx("table", { role: "presentation", border: 0, cellPadding: 0, cellSpacing: 0, align: "center", width: "100%", style: outerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: "center", style: { padding: "0", margin: "0" }, children: children }) }) }) }) }), jsxRuntime.jsx("div", { style: {
48
56
  display: "none",
49
57
  whiteSpace: "nowrap",
50
58
  font: "15px courier",
@@ -1531,41 +1539,6 @@ const justifyMap$3 = {
1531
1539
  center: "center",
1532
1540
  end: "right",
1533
1541
  };
1534
- function getBorderStyle$6(border) {
1535
- if (!border)
1536
- return {};
1537
- const style = {};
1538
- // If a full border is specified, apply it
1539
- if (border.width && border.style && border.color) {
1540
- style.border = `${border.width} ${border.style} ${border.color}`;
1541
- }
1542
- else {
1543
- // If only individual borders are specified, explicitly set others to 'none'
1544
- // to prevent Outlook Classic from showing black borders
1545
- const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
1546
- if (hasIndividualBorders) {
1547
- // Default all borders to none
1548
- style.borderTop = "none";
1549
- style.borderRight = "none";
1550
- style.borderBottom = "none";
1551
- style.borderLeft = "none";
1552
- }
1553
- }
1554
- // Override with specific borders if provided
1555
- if (border.top) {
1556
- style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
1557
- }
1558
- if (border.right) {
1559
- style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
1560
- }
1561
- if (border.bottom) {
1562
- style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
1563
- }
1564
- if (border.left) {
1565
- style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
1566
- }
1567
- return style;
1568
- }
1569
1542
  function getBorderStyleString$2(border) {
1570
1543
  if (!border)
1571
1544
  return "";
@@ -1607,10 +1580,16 @@ function Button({ config, devMode }) {
1607
1580
  const safeFontFamily = fontFamily
1608
1581
  ? fontFamily.replace(/['"]/g, "")
1609
1582
  : fontFamily;
1610
- // 2. Outer TD Style for Background and Border Radius (no border)
1611
- const backgroundTdStyle = Object.assign(Object.assign({ backgroundColor: backgroundColor, borderRadius: borderRadius, width: width || "auto" }, (maxWidth && { maxWidth: maxWidth })), (borderRadius && { overflow: "hidden" }));
1612
- // 3. Border styles
1613
- getBorderStyle$6(border);
1583
+ // Outer TD Style for Background and Border Radius (no border)
1584
+ const backgroundTdStyle = {
1585
+ backgroundColor: backgroundColor,
1586
+ borderRadius: borderRadius,
1587
+ width: width || "auto",
1588
+ ...(maxWidth && { maxWidth: maxWidth }),
1589
+ // Overflow hidden to clip background to border-radius
1590
+ ...(borderRadius && { overflow: "hidden" }),
1591
+ };
1592
+ // Border styles
1614
1593
  const borderStyleString = getBorderStyleString$2(border);
1615
1594
  // --- Determine Button Approach Based on Width ---
1616
1595
  // Check if width is percentage-based or not defined
@@ -1681,9 +1660,12 @@ function Button({ config, devMode }) {
1681
1660
  else {
1682
1661
  vmlAlignStyle = `text-align:${textAlign};`;
1683
1662
  }
1663
+ // Border radius is intentionally omitted (arcsize="0%") for Outlook Classic.
1664
+ // Outlook Classic does not reliably support rounded corners and the result
1665
+ // is inconsistent, so we render sharp corners there instead.
1684
1666
  vmlButton = `
1685
1667
  <!--[if mso]>
1686
- <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${href}" style="height:${vmlHeight}px;width:${vmlWidth}px;" arcsize="${Math.min((parseInt(borderRadius) / vmlHeight) * 100, 50)}%" strokecolor="${vmlStrokeColor}" ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} fillcolor="${vmlFillColor}">
1668
+ <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${href}" style="height:${vmlHeight}px;width:${vmlWidth}px;" arcsize="0%" strokecolor="${vmlStrokeColor}" ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} fillcolor="${vmlFillColor}">
1687
1669
  <w:anchorlock/>
1688
1670
  <v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
1689
1671
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
@@ -1716,6 +1698,9 @@ function Button({ config, devMode }) {
1716
1698
  const directionProp = direction ? `direction: ${direction};` : "";
1717
1699
  const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
1718
1700
  const wordBreakProp = wordBreak !== "break-word" ? `word-break: ${wordBreak};` : "";
1701
+ // Border radius is intentionally omitted from the Outlook Classic table cell.
1702
+ // Outlook Classic ignores border-radius on table cells anyway, and including it
1703
+ // can cause unexpected rendering artifacts, so we explicitly leave it out.
1719
1704
  simpleOutlookButton = `
1720
1705
  <!--[if mso]>
1721
1706
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
@@ -1723,7 +1708,7 @@ function Button({ config, devMode }) {
1723
1708
  <td align="${align}" style="padding: 0;">
1724
1709
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
1725
1710
  <tr>
1726
- <td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}; text-align: ${textAlign}; border-radius: ${borderRadius}; ${borderStyleString}">
1711
+ <td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}; text-align: ${textAlign}; ${borderStyleString}">
1727
1712
  <a href="${href}" target="_blank" rel="noopener noreferrer" style="color: ${color}; ${textDecorationStyle} display: block; font-family: ${safeFontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; ${fontStyleProp} line-height: ${lineHeight}; ${letterSpacingProp} ${textTransformProp} text-align: ${textAlign}; ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
1728
1713
  ${typeof children === "string" ? children : ""}
1729
1714
  </a>
@@ -1768,15 +1753,21 @@ function Button({ config, devMode }) {
1768
1753
  padding: 0,
1769
1754
  }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: align, style: {
1770
1755
  padding: 0,
1771
- }, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({
1756
+ }, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
1772
1757
  // --- Start dev
1773
- position: "relative",
1758
+ position: "relative",
1774
1759
  // --- End dev
1775
- width: width || "auto" }, (maxWidth && { maxWidth: maxWidth })), { borderCollapse: "collapse",
1760
+ width: width || "auto",
1761
+ ...(maxWidth && { maxWidth: maxWidth }),
1762
+ borderCollapse: "collapse",
1776
1763
  // base
1777
- boxSizing: "border-box", border: 0, margin: 0, padding: 0 }), onClick: devMode ? (e) => e.preventDefault() : undefined, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
1764
+ boxSizing: "border-box",
1765
+ border: 0,
1766
+ margin: 0,
1767
+ padding: 0,
1768
+ }, onClick: devMode ? (e) => e.preventDefault() : undefined, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
1778
1769
  __html: `
1779
- ${devMode ? "" : useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
1770
+ ${useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
1780
1771
  <!--[if !mso]><!-->
1781
1772
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
1782
1773
  <tbody>
@@ -1787,11 +1778,11 @@ function Button({ config, devMode }) {
1787
1778
  <tr>
1788
1779
  <td style="padding: 0;">
1789
1780
  ${devMode
1790
- ? `<span style="${sharedTextStyles} display: block; text-align: ${textAlign}; word-break: ${wordBreak}; padding: ${padding};">
1781
+ ? `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; word-break: ${wordBreak}; text-align: ${textAlign}; padding: ${padding};">
1791
1782
  ${typeof children === "string" ? children : ""}
1792
1783
  </span>`
1793
1784
  : `<a href="${href}" target="_blank" rel="noopener noreferrer" style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; word-break: ${wordBreak}; text-align: ${textAlign}; padding: ${padding};">
1794
- <span style="${sharedTextStyles}">
1785
+ <span>
1795
1786
  ${typeof children === "string" ? children : ""}
1796
1787
  </span>
1797
1788
  </a>`}
@@ -1871,14 +1862,31 @@ function Column({ children, config, devNode }) {
1871
1862
  };
1872
1863
  // 2. Outer TD style: Background and Border Radius (no border here).
1873
1864
  // height is set so the TD occupies the full declared height.
1874
- const outerTdStyle = Object.assign({ width: config.width, height: config.height, backgroundColor: config.backgroundColor, borderRadius: config.borderRadius,
1865
+ const outerTdStyle = {
1866
+ width: config.width,
1867
+ height: config.height,
1868
+ backgroundColor: config.backgroundColor,
1869
+ borderRadius: config.borderRadius,
1875
1870
  // Background Image styles
1876
1871
  backgroundImage: config.backgroundImage
1877
1872
  ? `url(${config.backgroundImage.src})`
1878
- : undefined, backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat, backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size, backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position }, (config.borderRadius && { overflow: "hidden" }));
1873
+ : undefined,
1874
+ backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
1875
+ backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
1876
+ backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
1877
+ // Overflow hidden to clip background to border-radius
1878
+ ...(config.borderRadius && { overflow: "hidden" }),
1879
+ };
1879
1880
  // 2b. Inner table style: Border and Border Radius.
1880
1881
  // height: 100% so it stretches to fill the outer TD's declared height.
1881
- const innerTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$5(config.border));
1882
+ const innerTableStyle = {
1883
+ width: "100%",
1884
+ height: "100%", // fill the outer TD rather than re-declaring the pixel value
1885
+ borderCollapse: "separate",
1886
+ borderSpacing: 0,
1887
+ borderRadius: config.borderRadius,
1888
+ ...getBorderStyle$5(config.border),
1889
+ };
1882
1890
  // 3. Inner TD style: Padding and Vertical Alignment only.
1883
1891
  // *** No height here. ***
1884
1892
  // The outer TD/table owns the height; padding is purely inner spacing,
@@ -1910,7 +1918,10 @@ function Column({ children, config, devNode }) {
1910
1918
  : "top", align: config.alignItems
1911
1919
  ? alignMap$2[config.alignItems]
1912
1920
  : "left", children: child }) }), index < numChildren - 1 && (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
1913
- return (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign({ position: "relative" }, outerTableStyle) }, (config.height && { height: config.height }), { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: outerTdStyle }, (config.width && { width: config.width }), (config.height && { height: config.height }), { children: renderContent() })) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
1921
+ return (jsxRuntime.jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
1922
+ position: "relative",
1923
+ ...outerTableStyle,
1924
+ }, ...(config.height && { height: config.height }), children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: outerTdStyle, ...(config.width && { width: config.width }), ...(config.height && { height: config.height }), children: renderContent() }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
1914
1925
  }
1915
1926
  var Column_default = React.memo(Column, arePropsEqual);
1916
1927
 
@@ -2015,11 +2026,27 @@ function Container({ children, config, devMode, devNode }) {
2015
2026
  borderCollapse: "collapse",
2016
2027
  };
2017
2028
  // 1. Background TD Style - Background color, border radius, background image
2018
- const backgroundTdStyle = Object.assign({ backgroundColor: config.backgroundColor, borderRadius: config.borderRadius, maxWidth: widthType === "fixed" ? config.width || "600px" : undefined, backgroundImage: config.backgroundImage
2029
+ const backgroundTdStyle = {
2030
+ backgroundColor: config.backgroundColor,
2031
+ borderRadius: config.borderRadius,
2032
+ maxWidth: widthType === "fixed" ? config.width || "600px" : undefined,
2033
+ backgroundImage: config.backgroundImage
2019
2034
  ? `url(${config.backgroundImage.src})`
2020
- : undefined, backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat, backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size, backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position }, (config.borderRadius && { overflow: "hidden" }));
2035
+ : undefined,
2036
+ backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
2037
+ backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
2038
+ backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
2039
+ // Overflow hidden to clip background to border-radius
2040
+ ...(config.borderRadius && { overflow: "hidden" }),
2041
+ };
2021
2042
  // 2. Border Table Style - Border and border radius
2022
- const borderTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$4(config.border));
2043
+ const borderTableStyle = {
2044
+ width: "100%",
2045
+ borderCollapse: "separate",
2046
+ borderSpacing: 0,
2047
+ borderRadius: config.borderRadius,
2048
+ ...getBorderStyle$4(config.border),
2049
+ };
2023
2050
  // 3. Padding TD Style
2024
2051
  const innerTdStyle = {
2025
2052
  padding: config.padding,
@@ -2059,7 +2086,10 @@ function Container({ children, config, devMode, devNode }) {
2059
2086
  }
2060
2087
  return (jsxRuntime.jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
2061
2088
  });
2062
- return (jsxRuntime.jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: Object.assign({ position: "relative" }, outerTableStyle), children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsxs("td", { align: justifyAlign, children: [jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxRuntime.jsxs("table", { className: [
2089
+ return (jsxRuntime.jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: {
2090
+ position: "relative",
2091
+ ...outerTableStyle,
2092
+ }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsxs("td", { align: justifyAlign, children: [jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxRuntime.jsxs("table", { className: [
2063
2093
  widthType === "fixed" ? "container-fixed-width" : undefined,
2064
2094
  devMode ? "main-wrapper relative" : undefined,
2065
2095
  ]
@@ -2102,12 +2132,12 @@ function Divider({ config, devNode }) {
2102
2132
  // --- End dev
2103
2133
  width: "100%",
2104
2134
  borderCollapse: "collapse",
2105
- }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: outerTdStyle, align: align, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Divider Line", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: dividerTableStyle }, { height: dividerHeightAttribute }, { children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
2135
+ }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: outerTdStyle, align: align, children: jsxRuntime.jsx("table", { "aria-label": "Divider Line", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: dividerTableStyle, ...{ height: dividerHeightAttribute }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
2106
2136
  height: height,
2107
2137
  fontSize: "0",
2108
2138
  lineHeight: "0",
2109
2139
  padding: "0",
2110
- }, children: "\u00A0" }) }) }) })) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2140
+ }, children: "\u00A0" }) }) }) }) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2111
2141
  }
2112
2142
  var Divider_default = React.memo(Divider, arePropsEqual);
2113
2143
 
@@ -2285,7 +2315,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
2285
2315
  }
2286
2316
  h1, h2, h3, h4, h5, h6 { margin: 0; padding: 0; font-weight: inherit; }
2287
2317
  `;
2288
- return (jsxRuntime.jsxs("head", { children: [jsxRuntime.jsx("meta", { httpEquiv: "Content-Type", content: "text/html; charset=utf-8" }), jsxRuntime.jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), jsxRuntime.jsx("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge" }), jsxRuntime.jsx("title", { children: title }), fonts.flatMap((resolved) => resolved.fontProps.map((props, i) => (jsxRuntime.jsx(Font, Object.assign({}, props), `${resolved.family}-${props.fontWeight}-${props.fontStyle}-${i}`)))), children, jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: msoResetStyles } }), jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: globalStyles } })] }));
2318
+ return (jsxRuntime.jsxs("head", { children: [jsxRuntime.jsx("meta", { httpEquiv: "Content-Type", content: "text/html; charset=utf-8" }), jsxRuntime.jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), jsxRuntime.jsx("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge" }), jsxRuntime.jsx("title", { children: title }), fonts.flatMap((resolved) => resolved.fontProps.map((props, i) => (jsxRuntime.jsx(Font, { ...props }, `${resolved.family}-${props.fontWeight}-${props.fontStyle}-${i}`)))), children, jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: msoResetStyles } }), jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: globalStyles } })] }));
2289
2319
  }
2290
2320
 
2291
2321
  function Heading({ config, devMode, children }) {
@@ -2352,28 +2382,6 @@ function Html({ children, backgroundColor = "#ffffff", }) {
2352
2382
  );
2353
2383
  }
2354
2384
 
2355
- /**
2356
- * Content rendered by Outlook Classic only.
2357
- * Outputs: <!--[if mso]> ... <![endif]-->
2358
- */
2359
- function MsoOnly({ html }) {
2360
- return (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
2361
- __html: `<!--[if mso]>${html}<![endif]-->`,
2362
- } }));
2363
- }
2364
- /**
2365
- * Content hidden from Outlook Classic, visible in all other clients.
2366
- * Outputs: <!--[if !mso]><!--> ... <!--<![endif]-->
2367
- */
2368
- function NonMso({ html }) {
2369
- return (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
2370
- __html: `<!--[if !mso]><!-->${html}<!--<![endif]-->`,
2371
- } }));
2372
- }
2373
-
2374
- // ---------------------------------------------------------------------------
2375
- // Helpers
2376
- // ---------------------------------------------------------------------------
2377
2385
  function getBorderStyle$3(border) {
2378
2386
  if (!border)
2379
2387
  return {};
@@ -2381,15 +2389,6 @@ function getBorderStyle$3(border) {
2381
2389
  if (border.width && border.style && border.color) {
2382
2390
  style.border = `${border.width} ${border.style} ${border.color}`;
2383
2391
  }
2384
- else {
2385
- const hasIndividual = border.top || border.right || border.bottom || border.left;
2386
- if (hasIndividual) {
2387
- style.borderTop = "none";
2388
- style.borderRight = "none";
2389
- style.borderBottom = "none";
2390
- style.borderLeft = "none";
2391
- }
2392
- }
2393
2392
  if (border.top)
2394
2393
  style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
2395
2394
  if (border.right)
@@ -2404,143 +2403,114 @@ function getBorderStyleString$1(border) {
2404
2403
  if (!border)
2405
2404
  return "";
2406
2405
  const styles = [];
2406
+ // Standard shorthand
2407
2407
  if (border.width && border.style && border.color) {
2408
- styles.push(`border:${border.width} ${border.style} ${border.color};`);
2408
+ styles.push(`border:${border.width} ${border.style} ${border.color} !important;`);
2409
2409
  }
2410
2410
  else {
2411
- const hasIndividual = border.top || border.right || border.bottom || border.left;
2412
- if (hasIndividual) {
2413
- styles.push("border-top:none;", "border-right:none;", "border-bottom:none;", "border-left:none;");
2414
- }
2411
+ // If desktop had a border and mobile wants "none", we must explicitly kill it
2412
+ styles.push(`border: none !important;`);
2415
2413
  }
2414
+ // Individual sides
2416
2415
  if (border.top)
2417
- styles.push(`border-top:${border.top.width} ${border.top.style} ${border.top.color};`);
2416
+ styles.push(`border-top:${border.top.width} ${border.top.style} ${border.top.color} !important;`);
2418
2417
  if (border.right)
2419
- styles.push(`border-right:${border.right.width} ${border.right.style} ${border.right.color};`);
2418
+ styles.push(`border-right:${border.right.width} ${border.right.style} ${border.right.color} !important;`);
2420
2419
  if (border.bottom)
2421
- styles.push(`border-bottom:${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
2420
+ styles.push(`border-bottom:${border.bottom.width} ${border.bottom.style} ${border.bottom.color} !important;`);
2422
2421
  if (border.left)
2423
- styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color};`);
2422
+ styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color} !important;`);
2424
2423
  return styles.join(" ");
2425
2424
  }
2426
- // ---------------------------------------------------------------------------
2427
- // Merged styles helper — applies mobile overrides on top of desktop values
2428
- // ---------------------------------------------------------------------------
2429
- function mergeConfig(config, overrides) {
2430
- var _a, _b, _c, _d, _e, _f, _g, _h;
2431
- return {
2432
- width: (_a = overrides === null || overrides === void 0 ? void 0 : overrides.width) !== null && _a !== void 0 ? _a : config.width,
2433
- height: (_b = overrides === null || overrides === void 0 ? void 0 : overrides.height) !== null && _b !== void 0 ? _b : config.height,
2434
- maxWidth: (_c = overrides === null || overrides === void 0 ? void 0 : overrides.maxWidth) !== null && _c !== void 0 ? _c : config.maxWidth,
2435
- maxHeight: (_d = overrides === null || overrides === void 0 ? void 0 : overrides.maxHeight) !== null && _d !== void 0 ? _d : config.maxHeight,
2436
- backgroundColor: (_e = overrides === null || overrides === void 0 ? void 0 : overrides.backgroundColor) !== null && _e !== void 0 ? _e : config.backgroundColor,
2437
- padding: (_f = overrides === null || overrides === void 0 ? void 0 : overrides.padding) !== null && _f !== void 0 ? _f : config.padding,
2438
- borderRadius: (_g = overrides === null || overrides === void 0 ? void 0 : overrides.borderRadius) !== null && _g !== void 0 ? _g : config.borderRadius,
2439
- border: (_h = overrides === null || overrides === void 0 ? void 0 : overrides.border) !== null && _h !== void 0 ? _h : config.border,
2440
- };
2441
- }
2442
- // ---------------------------------------------------------------------------
2443
- // Desktop table JSX (same as original)
2444
- // ---------------------------------------------------------------------------
2445
- function renderDesktopTable({ config, className, devNode, devMode, }) {
2446
- const { src, alt, href, target } = config;
2447
- const { width, height, maxWidth, maxHeight, backgroundColor, padding, borderRadius, border, } = mergeConfig(config);
2448
- const borderStyle = getBorderStyle$3(border);
2449
- const imgStyle = Object.assign({ display: "block", objectFit: "cover", width: width || "100%", height: height || "auto", maxWidth: maxWidth || "100%", maxHeight: maxHeight, border: "0", borderRadius: borderRadius }, borderStyle);
2450
- const linkStyle = {
2425
+ function Image({ config, devNode, devMode }) {
2426
+ var _a, _b;
2427
+ const { src, alt, href, target, mobile } = config;
2428
+ const seed = src + (alt || "");
2429
+ const instanceId = seed
2430
+ .split("")
2431
+ .reduce((acc, char) => acc + char.charCodeAt(0), 0)
2432
+ .toString(36);
2433
+ const imgClass = `img-${instanceId}`;
2434
+ // 1. Desktop Dimensional Logic
2435
+ const desktopWidth = config.width || "100%";
2436
+ const isPercent = desktopWidth.includes("%");
2437
+ const widthAttr = desktopWidth.replace("px", "");
2438
+ const heightAttr = (_a = config.height) === null || _a === void 0 ? void 0 : _a.replace("px", "");
2439
+ // Determine the table's "initial" width.
2440
+ // If it's 300px, the table should be 300px, not 100%.
2441
+ const tableWidth = isPercent ? desktopWidth : `${widthAttr}px`;
2442
+ // When width is a percentage, Outlook ignores CSS and renders the image at
2443
+ // its intrinsic pixel size. Setting a concrete `width` HTML attribute gives
2444
+ // Outlook a value to constrain against while modern clients continue to use
2445
+ // the CSS `width: 100%` for fluid rendering.
2446
+ //
2447
+ // If `maxWidth` is a pixel value (e.g. "600px"), we extract the number and
2448
+ // use it as the HTML `width` attribute so Outlook enforces that cap.
2449
+ // Other clients ignore the attribute and rely on CSS styles instead.
2450
+ // If `maxWidth` is not set or is not a pixel value (e.g. "100%"), we fall
2451
+ // back to the original behaviour (numeric string for px widths, undefined
2452
+ // for % widths).
2453
+ const maxWidthPx = ((_b = config.maxWidth) === null || _b === void 0 ? void 0 : _b.endsWith("px"))
2454
+ ? parseInt(config.maxWidth, 10)
2455
+ : undefined;
2456
+ const imgWidthAttr = isPercent ? (maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined) : widthAttr;
2457
+ // 2. Mobile Overrides (Every property used)
2458
+ let mobileCss = "";
2459
+ if (mobile) {
2460
+ mobileCss = `
2461
+ @media screen and (max-width: 768px) {
2462
+ .wrap-${imgClass} {
2463
+ /* This breaks the px lock from desktop and makes it fluid */
2464
+ width: ${mobile.width || "100%"} !important;
2465
+ max-width: ${mobile.maxWidth || "100%"} !important;
2466
+ min-width: 0 !important;
2467
+ }
2468
+ .td-${imgClass} {
2469
+ padding: ${mobile.padding || "0"} !important;
2470
+ background-color: ${mobile.backgroundColor || "transparent"} !important;
2471
+ width: 100% !important;
2472
+ }
2473
+ .${imgClass} {
2474
+ width: ${mobile.width || "100%"} !important;
2475
+ height: ${mobile.height || "auto"} !important;
2476
+ max-width: ${mobile.maxWidth || "100%"} !important;
2477
+ max-height: ${mobile.maxHeight || "none"} !important;
2478
+ border-radius: ${mobile.borderRadius || "0"} !important;
2479
+ display: ${mobile.hidden ? "none" : "block"} !important;
2480
+ object-fit: ${mobile.objectFit || "fill"} !important;
2481
+ object-position: ${mobile.objectPosition || "center"} !important;
2482
+ ${getBorderStyleString$1(mobile.border)}
2483
+ }
2484
+ }
2485
+ `;
2486
+ }
2487
+ const imgStyle = {
2451
2488
  display: "block",
2452
- textDecoration: "none",
2453
- border: "0",
2489
+ width: isPercent ? "100%" : desktopWidth,
2490
+ height: config.height || "auto",
2491
+ maxWidth: config.maxWidth || "100%",
2492
+ maxHeight: config.maxHeight || "none",
2493
+ borderRadius: config.borderRadius || "0",
2494
+ ...getBorderStyle$3(config.border),
2454
2495
  outline: "none",
2496
+ textDecoration: "none",
2497
+ objectFit: config.objectFit,
2498
+ objectPosition: config.objectPosition,
2455
2499
  };
2456
- const tdStyle = {
2457
- padding: padding,
2458
- backgroundColor: backgroundColor,
2459
- fontSize: "0",
2460
- lineHeight: "0",
2461
- };
2462
- const widthNum = (width === null || width === void 0 ? void 0 : width.endsWith("px")) ? parseInt(width, 10) : undefined;
2463
- const maxWidthNum = (maxWidth === null || maxWidth === void 0 ? void 0 : maxWidth.endsWith("px"))
2464
- ? parseInt(maxWidth, 10)
2465
- : undefined;
2466
- const heightNum = (height === null || height === void 0 ? void 0 : height.endsWith("px")) ? parseInt(height, 10) : undefined;
2467
- const imageElement = (jsxRuntime.jsx("img", { draggable: false, src: src, alt: alt, style: imgStyle, width: widthNum && maxWidthNum
2468
- ? Math.min(widthNum, maxWidthNum)
2469
- : widthNum || maxWidthNum, height: heightNum, border: 0 }));
2470
- const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: imageElement }))) : (imageElement);
2471
- return (jsxRuntime.jsxs("table", { "aria-label": `Image Wrapper for: ${alt}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, className: className, style: {
2472
- position: "relative",
2473
- width: width || "100%",
2474
- borderCollapse: "collapse",
2475
- }, onClick: devMode ? (e) => e.preventDefault() : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: "center", children: content }) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2476
- }
2477
- // ---------------------------------------------------------------------------
2478
- // Mobile table — HTML string (injected via NonMso, same pattern as Icon VML)
2479
- // ---------------------------------------------------------------------------
2480
- function buildMobileTableHTML({ config, overrides, className, }) {
2481
- const { src, alt, href, target } = config;
2482
- const { width, height, maxWidth, maxHeight, backgroundColor, padding, borderRadius, border, } = mergeConfig(config, overrides);
2483
- const borderStyleStr = getBorderStyleString$1(border);
2484
- const widthNum = (width === null || width === void 0 ? void 0 : width.endsWith("px")) ? parseInt(width, 10) : undefined;
2485
- const maxWidthNum = (maxWidth === null || maxWidth === void 0 ? void 0 : maxWidth.endsWith("px"))
2486
- ? parseInt(maxWidth, 10)
2487
- : undefined;
2488
- const heightNum = (height === null || height === void 0 ? void 0 : height.endsWith("px")) ? parseInt(height, 10) : undefined;
2489
- const resolvedWidth = widthNum && maxWidthNum
2490
- ? Math.min(widthNum, maxWidthNum)
2491
- : widthNum || maxWidthNum;
2492
- const imgTag = `<img
2493
- draggable="false"
2494
- src="${src}"
2495
- alt="${alt}"
2496
- ${resolvedWidth ? `width="${resolvedWidth}"` : ""}
2497
- ${heightNum ? `height="${heightNum}"` : ""}
2498
- border="0"
2499
- style="display:block;object-fit:cover;width:${width || "100%"};height:${height || "auto"};max-width:${maxWidth || "100%"};${maxHeight ? `max-height:${maxHeight};` : ""}border:0;${borderRadius ? `border-radius:${borderRadius};` : ""}${borderStyleStr}"
2500
- />`;
2501
- const content = href
2502
- ? `<a href="${href}" target="${target || "_self"}" style="display:block;text-decoration:none;border:0;outline:none;"${target === "_blank" ? ' rel="noopener noreferrer"' : ""}>${imgTag}</a>`
2503
- : imgTag;
2504
- return `
2505
- <table
2506
- aria-label="Image Wrapper for: ${alt}"
2507
- role="presentation"
2508
- cellpadding="0"
2509
- cellspacing="0"
2510
- border="0"
2511
- class="${className}"
2512
- style="position:relative;width:${width || "100%"};border-collapse:collapse;"
2513
- >
2514
- <tbody>
2515
- <tr>
2516
- <td
2517
- align="center"
2518
- style="padding:${padding || ""};background-color:${backgroundColor || ""};font-size:0;line-height:0;"
2519
- >
2520
- ${content}
2521
- </td>
2522
- </tr>
2523
- </tbody>
2524
- </table>
2525
- `;
2526
- }
2527
- // ---------------------------------------------------------------------------
2528
- // Component
2529
- // ---------------------------------------------------------------------------
2530
- function Image({ config, devNode, devMode }) {
2531
- const { mobile } = config;
2532
- const hasMobileOverrides = !!mobile && !mobile.hidden;
2533
- const isHiddenOnMobile = !!(mobile === null || mobile === void 0 ? void 0 : mobile.hidden);
2534
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderDesktopTable({
2535
- config,
2536
- className: hasMobileOverrides || isHiddenOnMobile ? "hide-on-mobile" : undefined,
2537
- devNode,
2538
- devMode,
2539
- }), hasMobileOverrides && !devMode && (jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: { width: "100%", borderCollapse: "collapse" }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx(NonMso, { html: buildMobileTableHTML({
2540
- config,
2541
- overrides: mobile,
2542
- className: "hide-on-desktop",
2543
- }) }) }) }) }))] }));
2500
+ const imageElement = (jsxRuntime.jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle }));
2501
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [mobile && jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: mobileCss } }), jsxRuntime.jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, className: `wrap-${imgClass}`, align: "center" // Ensures a 300px image stays centered in its parent
2502
+ , style: {
2503
+ width: tableWidth, // Fixed px here prevents the 100% "ghost space"
2504
+ maxWidth: "100%",
2505
+ borderCollapse: "collapse",
2506
+ margin: "0 auto",
2507
+ }, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { className: `td-${imgClass}`, align: "center", style: {
2508
+ padding: config.padding,
2509
+ backgroundColor: config.backgroundColor,
2510
+ fontSize: "0",
2511
+ lineHeight: "0",
2512
+ width: tableWidth, // Lock the cell as well
2513
+ }, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, style: { display: "block", width: "100%" }, children: imageElement })) : (imageElement) }) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })] }));
2544
2514
  }
2545
2515
  var Image_default = React.memo(Image, arePropsEqual);
2546
2516
 
@@ -2615,35 +2585,54 @@ function Row({ children, config, devNode, devMode }) {
2615
2585
  const numChildren = childrenArray.length;
2616
2586
  const href = getHrefFromInnerLink(config.innerLink);
2617
2587
  const target = (_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target;
2618
- // 1. Outer TD for Background and Border Radius (no border here).
2619
- // height declared here is the *total* outer height.
2620
- const backgroundTdStyle = Object.assign({ backgroundColor: config.backgroundColor, borderRadius: config.borderRadius, width: config.width || "100%", height: config.height,
2621
- // Background Image styles
2588
+ // 1. Outer TD: Background, Border Radius, Width, Height.
2589
+ const backgroundTdStyle = {
2590
+ backgroundColor: config.backgroundColor,
2591
+ borderRadius: config.borderRadius,
2592
+ width: config.width || "100%",
2593
+ height: config.height,
2622
2594
  backgroundImage: config.backgroundImage
2623
2595
  ? `url(${config.backgroundImage.src})`
2624
- : undefined, backgroundRepeat: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat, backgroundSize: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size, backgroundPosition: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position }, (config.borderRadius && { overflow: "hidden" }));
2625
- // 2. Inner Table for Border and Border Radius.
2626
- // height: 100% so it stretches to fill the outer TD.
2627
- const borderTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$2(config.border));
2628
- // 3. TD for Padding only — no height.
2629
- // The outer TD owns the total height; setting height here would cause
2630
- // browsers/email clients to treat it as content-box height and add
2631
- // padding on top, making the row taller than the declared height.
2596
+ : undefined,
2597
+ backgroundRepeat: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat,
2598
+ backgroundSize: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size,
2599
+ backgroundPosition: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position,
2600
+ ...(config.borderRadius && { overflow: "hidden" }),
2601
+ };
2602
+ // 2. Inner Table: Border and Border Radius.
2603
+ const borderTableStyle = {
2604
+ width: "100%",
2605
+ height: "100%",
2606
+ borderCollapse: "separate",
2607
+ borderSpacing: 0,
2608
+ borderRadius: config.borderRadius,
2609
+ ...getBorderStyle$2(config.border),
2610
+ };
2611
+ // 3. Padding TD.
2632
2612
  const paddingTdStyle = {
2633
2613
  padding: config.padding,
2634
2614
  width: "100%",
2635
- // height intentionally omitted — padding must be inner, not additive
2636
2615
  verticalAlign: "top",
2637
2616
  };
2638
- // 4. Content Table - horizontal layout
2617
+ // 4. Content Table.
2618
+ //
2619
+ // fillWidth: false/undefined (default) → width: "auto"
2620
+ // Original behavior. Children shrink-wrap to their natural sizes.
2621
+ // Use for icon rows, button rows, social link rows.
2622
+ // Centering works via the Justification Wrapper TD (align + width="100%").
2623
+ //
2624
+ // fillWidth: true → width: "100%"
2625
+ // Content table fills available space, giving Outlook Classic a hard
2626
+ // boundary so text children get a constrained box and line wrapping
2627
+ // triggers correctly. Use for rows containing text + image layouts.
2639
2628
  const contentTableStyle = {
2640
- width: "auto",
2629
+ width: config.fillWidth ? "100%" : "auto",
2641
2630
  height: "100%",
2642
2631
  borderCollapse: "collapse",
2643
2632
  minWidth: "1px",
2644
- maxWidth: config.width || "100%",
2633
+ ...(!config.fillWidth && { maxWidth: config.width || "100%" }),
2645
2634
  };
2646
- // 5. Gap styles for horizontal spacing between children
2635
+ // 5. Gap TD.
2647
2636
  const gapTdStyle = {
2648
2637
  width: config.gap || "0",
2649
2638
  lineHeight: "1px",
@@ -2653,30 +2642,28 @@ function Row({ children, config, devNode, devMode }) {
2653
2642
  ? justifyMap$1[config.justifyContent]
2654
2643
  : "left";
2655
2644
  const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
2656
- // Content to render - wrapped in anchor if innerLink is defined
2657
- const content = (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2645
+ const content = (jsxRuntime.jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2658
2646
  position: "relative",
2659
2647
  width: config.width || "100%",
2660
2648
  height: config.height,
2661
2649
  borderCollapse: "collapse",
2662
- } }, (config.height && { height: config.height }), { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: backgroundTdStyle }, (config.height && { height: config.height }), { children: jsxRuntime.jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: paddingTdStyle, children: jsxRuntime.jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2650
+ }, ...(config.height && { height: config.height }), children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: backgroundTdStyle, ...(config.height && { height: config.height }), children: jsxRuntime.jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: paddingTdStyle, children: jsxRuntime.jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2663
2651
  width: "100%",
2664
2652
  height: "100%",
2665
2653
  borderCollapse: "collapse",
2666
- }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle }, (config.height && { height: config.height }), { className: "content-table row-content-table", "data-mobile-justify": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.justifyContent, "data-mobile-align": (_f = config.mobile) === null || _f === void 0 ? void 0 : _f.alignItems, "data-mobile-wrap": ((_g = config.mobile) === null || _g === void 0 ? void 0 : _g.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
2654
+ }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, width: "100%", style: { width: "100%" }, children: jsxRuntime.jsx("table", { "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle, ...(config.height && { height: config.height }), className: "content-table row-content-table", "data-mobile-justify": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.justifyContent, "data-mobile-align": (_f = config.mobile) === null || _f === void 0 ? void 0 : _f.alignItems, "data-mobile-wrap": ((_g = config.mobile) === null || _g === void 0 ? void 0 : _g.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
2667
2655
  verticalAlign: tdValign,
2668
2656
  textAlign: "left",
2669
2657
  padding: "0",
2670
2658
  margin: "0",
2671
2659
  }, className: "child-cell", children: child }), index < numChildren - 1 &&
2672
- config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) })) }) }) }) }) }) }) }) }) })) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
2673
- // Wrap in anchor tag if innerLink is defined and NOT in dev mode
2660
+ config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2674
2661
  if (href && !devMode) {
2675
- return (jsxRuntime.jsx("a", Object.assign({ href: href }, (target && { target }), { style: {
2662
+ return (jsxRuntime.jsx("a", { href: href, ...(target && { target }), style: {
2676
2663
  textDecoration: "none",
2677
2664
  color: "inherit",
2678
2665
  display: "block",
2679
- }, children: content })));
2666
+ }, children: content }));
2680
2667
  }
2681
2668
  return content;
2682
2669
  }
@@ -2720,9 +2707,18 @@ function getBorderStyle$1(border) {
2720
2707
  const Section = ({ config, children, devNode, }) => {
2721
2708
  var _a, _b, _c;
2722
2709
  const { sectionType, padding } = config;
2723
- return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({ position: "relative", width: "100%", backgroundColor: config.backgroundColor }, getBorderStyle$1(config.border)), { backgroundImage: config.backgroundImage
2710
+ return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2711
+ position: "relative",
2712
+ width: "100%",
2713
+ backgroundColor: config.backgroundColor,
2714
+ ...getBorderStyle$1(config.border),
2715
+ backgroundImage: config.backgroundImage
2724
2716
  ? `url(${config.backgroundImage.src})`
2725
- : undefined, backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat, backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size, backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position }), children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
2717
+ : undefined,
2718
+ backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
2719
+ backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
2720
+ backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
2721
+ }, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
2726
2722
  padding: padding,
2727
2723
  }, children: children }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsxs("td", { children: [jsxRuntime.jsxs("span", { style: {
2728
2724
  backgroundColor: "black",
@@ -2763,16 +2759,19 @@ function Spacer({ config, devNode }) {
2763
2759
  const spacerHeightAttribute = parseInt(height, 10) || 1;
2764
2760
  return (
2765
2761
  // Outer table ensures the spacer spans the full width of its container
2766
- jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign({
2762
+ jsxRuntime.jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2767
2763
  // --- Start dev
2768
- position: "relative" }, spacerTableStyle) }, { height: spacerHeightAttribute }, { className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
2764
+ position: "relative",
2765
+ // --- End dev
2766
+ ...spacerTableStyle,
2767
+ }, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
2769
2768
  // Explicit height attribute
2770
- height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
2769
+ height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2771
2770
  }
2772
2771
  var Spacer_default = React.memo(Spacer, arePropsEqual);
2773
2772
 
2774
2773
  function Text({ config, devMode, children }) {
2775
- const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", } = config;
2774
+ const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth } = config;
2776
2775
  // 1. TD Style: Where padding and background are reliably applied.
2777
2776
  const tdStyle = {
2778
2777
  padding: padding,
@@ -2799,6 +2798,7 @@ function Text({ config, devMode, children }) {
2799
2798
  wordBreak: wordBreak,
2800
2799
  margin: "0",
2801
2800
  padding: "0",
2801
+ maxWidth
2802
2802
  };
2803
2803
  // Determine content to render
2804
2804
  const content = text !== null && text !== void 0 ? text : children;
@@ -2982,7 +2982,13 @@ function Icon({ config, devNode, devMode, children }) {
2982
2982
  lineHeight: "0",
2983
2983
  };
2984
2984
  // 4. Inner Table Style: Apply border here with border-collapse: separate
2985
- const innerTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: borderRadius }, borderStyle);
2985
+ const innerTableStyle = {
2986
+ width: "100%",
2987
+ borderCollapse: "separate",
2988
+ borderSpacing: 0,
2989
+ borderRadius: borderRadius,
2990
+ ...borderStyle,
2991
+ };
2986
2992
  // 5. Inner TD Style: Padding
2987
2993
  const innerTdStyle = {
2988
2994
  padding: padding,
@@ -3030,7 +3036,7 @@ function Icon({ config, devNode, devMode, children }) {
3030
3036
  // Icon image element
3031
3037
  const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: "", style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
3032
3038
  // Wrap in link if href exists and not in dev mode
3033
- const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: iconElement }))) : (iconElement);
3039
+ const content = href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, style: linkStyle, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), children: iconElement })) : (iconElement);
3034
3040
  // Build the HTML content with VML support (only when NOT in dev mode)
3035
3041
  const useVML = !devMode && backgroundColor && numericBorderRadius > 0;
3036
3042
  const htmlContent = useVML
@@ -3078,6 +3084,25 @@ function Icon({ config, devNode, devMode, children }) {
3078
3084
  }
3079
3085
  var Icon_default = React.memo(Icon, arePropsEqual);
3080
3086
 
3087
+ /**
3088
+ * Content rendered by Outlook Classic only.
3089
+ * Outputs: <!--[if mso]> ... <![endif]-->
3090
+ */
3091
+ function MsoOnly({ html }) {
3092
+ return (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
3093
+ __html: `<!--[if mso]>${html}<![endif]-->`,
3094
+ } }));
3095
+ }
3096
+ /**
3097
+ * Content hidden from Outlook Classic, visible in all other clients.
3098
+ * Outputs: <!--[if !mso]><!--> ... <!--<![endif]-->
3099
+ */
3100
+ function NonMso({ html }) {
3101
+ return (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
3102
+ __html: `<!--[if !mso]><!-->${html}<!--<![endif]-->`,
3103
+ } }));
3104
+ }
3105
+
3081
3106
  exports.Body = Body;
3082
3107
  exports.Button = Button_default;
3083
3108
  exports.Column = Column_default;